1
2 #include "state.hpp"
3
4 #include <stdexcept>
5 #include <algorithm>
6 #include <sstream>
7
8 #include "intsetting.hpp"
9 #include "doublesetting.hpp"
10 #include "boolsetting.hpp"
11 #include "coloursetting.hpp"
12 #include "shortcutsetting.hpp"
13 #include "modifiersetting.hpp"
14
15 CSMPrefs::State *CSMPrefs::State::sThis = nullptr;
16
load()17 void CSMPrefs::State::load()
18 {
19 // default settings file
20 boost::filesystem::path local = mConfigurationManager.getLocalPath() / mDefaultConfigFile;
21 boost::filesystem::path global = mConfigurationManager.getGlobalPath() / mDefaultConfigFile;
22
23 if (boost::filesystem::exists (local))
24 mSettings.loadDefault (local.string());
25 else if (boost::filesystem::exists (global))
26 mSettings.loadDefault (global.string());
27 else
28 throw std::runtime_error ("No default settings file found! Make sure the file \"" + mDefaultConfigFile + "\" was properly installed.");
29
30 // user settings file
31 boost::filesystem::path user = mConfigurationManager.getUserConfigPath() / mConfigFile;
32
33 if (boost::filesystem::exists (user))
34 mSettings.loadUser (user.string());
35 }
36
declare()37 void CSMPrefs::State::declare()
38 {
39 declareCategory ("Windows");
40 declareInt ("default-width", "Default window width", 800).
41 setTooltip ("Newly opened top-level windows will open with this width.").
42 setMin (80);
43 declareInt ("default-height", "Default window height", 600).
44 setTooltip ("Newly opened top-level windows will open with this height.").
45 setMin (80);
46 declareBool ("show-statusbar", "Show Status Bar", true).
47 setTooltip ("If a newly open top level window is showing status bars or not. "
48 " Note that this does not affect existing windows.");
49 declareSeparator();
50 declareBool ("reuse", "Reuse Subviews", true).
51 setTooltip ("When a new subview is requested and a matching subview already "
52 " exist, do not open a new subview and use the existing one instead.");
53 declareInt ("max-subviews", "Maximum number of subviews per top-level window", 256).
54 setTooltip ("If the maximum number is reached and a new subview is opened "
55 "it will be placed into a new top-level window.").
56 setRange (1, 256);
57 declareBool ("hide-subview", "Hide single subview", false).
58 setTooltip ("When a view contains only a single subview, hide the subview title "
59 "bar and if this subview is closed also close the view (unless it is the last "
60 "view for this document)");
61 declareInt ("minimum-width", "Minimum subview width", 325).
62 setTooltip ("Minimum width of subviews.").
63 setRange (50, 10000);
64 declareSeparator();
65 EnumValue scrollbarOnly ("Scrollbar Only", "Simple addition of scrollbars, the view window "
66 "does not grow automatically.");
67 declareEnum ("mainwindow-scrollbar", "Horizontal scrollbar mode for main window.", scrollbarOnly).
68 addValue (scrollbarOnly).
69 addValue ("Grow Only", "The view window grows as subviews are added. No scrollbars.").
70 addValue ("Grow then Scroll", "The view window grows. The scrollbar appears once it cannot grow any further.");
71 declareBool ("grow-limit", "Grow Limit Screen", false).
72 setTooltip ("When \"Grow then Scroll\" option is selected, the window size grows to"
73 " the width of the virtual desktop. \nIf this option is selected the the window growth"
74 "is limited to the current screen.");
75
76 declareCategory ("Records");
77 EnumValue iconAndText ("Icon and Text");
78 EnumValues recordValues;
79 recordValues.add (iconAndText).add ("Icon Only").add ("Text Only");
80 declareEnum ("status-format", "Modification status display format", iconAndText).
81 addValues (recordValues);
82 declareEnum ("type-format", "ID type display format", iconAndText).
83 addValues (recordValues);
84
85 declareCategory ("ID Tables");
86 EnumValue inPlaceEdit ("Edit in Place", "Edit the clicked cell");
87 EnumValue editRecord ("Edit Record", "Open a dialogue subview for the clicked record");
88 EnumValue view ("View", "Open a scene subview for the clicked record (not available everywhere)");
89 EnumValue editRecordAndClose ("Edit Record and Close");
90 EnumValues doubleClickValues;
91 doubleClickValues.add (inPlaceEdit).add (editRecord).add (view).add ("Revert").
92 add ("Delete").add (editRecordAndClose).
93 add ("View and Close", "Open a scene subview for the clicked record and close the table subview");
94 declareEnum ("double", "Double Click", inPlaceEdit).addValues (doubleClickValues);
95 declareEnum ("double-s", "Shift Double Click", editRecord).addValues (doubleClickValues);
96 declareEnum ("double-c", "Control Double Click", view).addValues (doubleClickValues);
97 declareEnum ("double-sc", "Shift Control Double Click", editRecordAndClose).addValues (doubleClickValues);
98 declareSeparator();
99 EnumValue jumpAndSelect ("Jump and Select", "Scroll new record into view and make it the selection");
100 declareEnum ("jump-to-added", "Action on adding or cloning a record", jumpAndSelect).
101 addValue (jumpAndSelect).
102 addValue ("Jump Only", "Scroll new record into view").
103 addValue ("No Jump", "No special action");
104 declareBool ("extended-config",
105 "Manually specify affected record types for an extended delete/revert", false).
106 setTooltip ("Delete and revert commands have an extended form that also affects "
107 "associated records.\n\n"
108 "If this option is enabled, types of affected records are selected "
109 "manually before a command execution.\nOtherwise, all associated "
110 "records are deleted/reverted immediately.");
111
112 declareCategory ("ID Dialogues");
113 declareBool ("toolbar", "Show toolbar", true);
114
115 declareCategory ("Reports");
116 EnumValue actionNone ("None");
117 EnumValue actionEdit ("Edit", "Open a table or dialogue suitable for addressing the listed report");
118 EnumValue actionRemove ("Remove", "Remove the report from the report table");
119 EnumValue actionEditAndRemove ("Edit And Remove", "Open a table or dialogue suitable for addressing the listed report, then remove the report from the report table");
120 EnumValues reportValues;
121 reportValues.add (actionNone).add (actionEdit).add (actionRemove).add (actionEditAndRemove);
122 declareEnum ("double", "Double Click", actionEdit).addValues (reportValues);
123 declareEnum ("double-s", "Shift Double Click", actionRemove).addValues (reportValues);
124 declareEnum ("double-c", "Control Double Click", actionEditAndRemove).addValues (reportValues);
125 declareEnum ("double-sc", "Shift Control Double Click", actionNone).addValues (reportValues);
126 declareBool("ignore-base-records", "Ignore base records in verifier", false);
127
128 declareCategory ("Search & Replace");
129 declareInt ("char-before", "Characters before search string", 10).
130 setTooltip ("Maximum number of character to display in search result before the searched text");
131 declareInt ("char-after", "Characters after search string", 10).
132 setTooltip ("Maximum number of character to display in search result after the searched text");
133 declareBool ("auto-delete", "Delete row from result table after a successful replace", true);
134
135 declareCategory ("Scripts");
136 declareBool ("show-linenum", "Show Line Numbers", true).
137 setTooltip ("Show line numbers to the left of the script editor window."
138 "The current row and column numbers of the text cursor are shown at the bottom.");
139 declareBool ("wrap-lines", "Wrap Lines", false).
140 setTooltip ("Wrap lines longer than width of script editor.");
141 declareBool ("mono-font", "Use monospace font", true);
142 declareInt ("tab-width", "Tab Width", 4).
143 setTooltip ("Number of characters for tab width").
144 setRange (1, 10);
145 EnumValue warningsNormal ("Normal", "Report warnings as warning");
146 declareEnum ("warnings", "Warning Mode", warningsNormal).
147 addValue ("Ignore", "Do not report warning").
148 addValue (warningsNormal).
149 addValue ("Strict", "Promote warning to an error");
150 declareBool ("toolbar", "Show toolbar", true);
151 declareInt ("compile-delay", "Delay between updating of source errors", 100).
152 setTooltip ("Delay in milliseconds").
153 setRange (0, 10000);
154 declareInt ("error-height", "Initial height of the error panel", 100).
155 setRange (100, 10000);
156 declareBool ("highlight-occurrences", "Highlight other occurrences of selected names", true);
157 declareColour ("colour-highlight", "Colour of highlighted occurrences", QColor("lightcyan"));
158 declareSeparator();
159 declareColour ("colour-int", "Highlight Colour: Integer Literals", QColor ("darkmagenta"));
160 declareColour ("colour-float", "Highlight Colour: Float Literals", QColor ("magenta"));
161 declareColour ("colour-name", "Highlight Colour: Names", QColor ("grey"));
162 declareColour ("colour-keyword", "Highlight Colour: Keywords", QColor ("red"));
163 declareColour ("colour-special", "Highlight Colour: Special Characters", QColor ("darkorange"));
164 declareColour ("colour-comment", "Highlight Colour: Comments", QColor ("green"));
165 declareColour ("colour-id", "Highlight Colour: IDs", QColor ("blue"));
166
167 declareCategory ("General Input");
168 declareBool ("cycle", "Cyclic next/previous", false).
169 setTooltip ("When using next/previous functions at the last/first item of a "
170 "list go to the first/last item");
171
172 declareCategory ("3D Scene Input");
173
174 declareDouble ("navi-wheel-factor", "Camera Zoom Sensitivity", 8).setRange(-100.0, 100.0);
175 declareDouble ("s-navi-sensitivity", "Secondary Camera Movement Sensitivity", 50.0).setRange(-1000.0, 1000.0);
176 declareSeparator();
177
178 declareDouble ("p-navi-free-sensitivity", "Free Camera Sensitivity", 1/650.).setPrecision(5).setRange(0.0, 1.0);
179 declareBool ("p-navi-free-invert", "Invert Free Camera Mouse Input", false);
180 declareDouble ("navi-free-lin-speed", "Free Camera Linear Speed", 1000.0).setRange(1.0, 10000.0);
181 declareDouble ("navi-free-rot-speed", "Free Camera Rotational Speed", 3.14 / 2).setRange(0.001, 6.28);
182 declareDouble ("navi-free-speed-mult", "Free Camera Speed Multiplier (from Modifier)", 8).setRange(0.001, 1000.0);
183 declareSeparator();
184
185 declareDouble ("p-navi-orbit-sensitivity", "Orbit Camera Sensitivity", 1/650.).setPrecision(5).setRange(0.0, 1.0);
186 declareBool ("p-navi-orbit-invert", "Invert Orbit Camera Mouse Input", false);
187 declareDouble ("navi-orbit-rot-speed", "Orbital Camera Rotational Speed", 3.14 / 4).setRange(0.001, 6.28);
188 declareDouble ("navi-orbit-speed-mult", "Orbital Camera Speed Multiplier (from Modifier)", 4).setRange(0.001, 1000.0);
189 declareBool ("navi-orbit-const-roll", "Keep camera roll constant for orbital camera", true);
190 declareSeparator();
191
192 declareBool ("context-select", "Context Sensitive Selection", false);
193 declareDouble ("drag-factor", "Mouse sensitivity during drag operations", 1.0).
194 setRange (0.001, 100.0);
195 declareDouble ("drag-wheel-factor", "Mouse wheel sensitivity during drag operations", 1.0).
196 setRange (0.001, 100.0);
197 declareDouble ("drag-shift-factor",
198 "Shift-acceleration factor during drag operations", 4.0).
199 setTooltip ("Acceleration factor during drag operations while holding down shift").
200 setRange (0.001, 100.0);
201 declareDouble ("rotate-factor", "Free rotation factor", 0.007).setPrecision(4).setRange(0.0001, 0.1);
202
203 declareCategory ("Rendering");
204 declareInt ("framerate-limit", "FPS limit", 60).
205 setTooltip("Framerate limit in 3D preview windows. Zero value means \"unlimited\".").
206 setRange(0, 10000);
207 declareInt ("camera-fov", "Camera FOV", 90).setRange(10, 170);
208 declareBool ("camera-ortho", "Orthographic projection for camera", false);
209 declareInt ("camera-ortho-size", "Orthographic projection size parameter", 100).
210 setTooltip("Size of the orthographic frustum, greater value will allow the camera to see more of the world.").
211 setRange(10, 10000);
212 declareDouble ("object-marker-alpha", "Object Marker Transparency", 0.5).setPrecision(2).setRange(0,1);
213 declareBool("scene-use-gradient", "Use Gradient Background", true);
214 declareColour ("scene-day-background-colour", "Day Background Colour", QColor (110, 120, 128, 255));
215 declareColour ("scene-day-gradient-colour", "Day Gradient Colour", QColor (47, 51, 51, 255)).
216 setTooltip("Sets the gradient color to use in conjunction with the day background color. Ignored if "
217 "the gradient option is disabled.");
218 declareColour ("scene-bright-background-colour", "Scene Bright Background Colour", QColor (79, 87, 92, 255));
219 declareColour ("scene-bright-gradient-colour", "Scene Bright Gradient Colour", QColor (47, 51, 51, 255)).
220 setTooltip("Sets the gradient color to use in conjunction with the bright background color. Ignored if "
221 "the gradient option is disabled.");
222 declareColour ("scene-night-background-colour", "Scene Night Background Colour", QColor (64, 77, 79, 255));
223 declareColour ("scene-night-gradient-colour", "Scene Night Gradient Colour", QColor (47, 51, 51, 255)).
224 setTooltip("Sets the gradient color to use in conjunction with the night background color. Ignored if "
225 "the gradient option is disabled.");
226
227 declareCategory ("Tooltips");
228 declareBool ("scene", "Show Tooltips in 3D scenes", true);
229 declareBool ("scene-hide-basic", "Hide basic 3D scenes tooltips", false);
230 declareInt ("scene-delay", "Tooltip delay in milliseconds", 500).
231 setMin (1);
232
233 EnumValue createAndInsert ("Create cell and insert");
234 EnumValue showAndInsert ("Show cell and insert");
235 EnumValue dontInsert ("Discard");
236 EnumValue insertAnyway ("Insert anyway");
237 EnumValues insertOutsideCell;
238 insertOutsideCell.add (createAndInsert).add (dontInsert).add (insertAnyway);
239 EnumValues insertOutsideVisibleCell;
240 insertOutsideVisibleCell.add (showAndInsert).add (dontInsert).add (insertAnyway);
241
242 EnumValue createAndLandEdit ("Create cell and land, then edit");
243 EnumValue showAndLandEdit ("Show cell and edit");
244 EnumValue dontLandEdit ("Discard");
245 EnumValues landeditOutsideCell;
246 landeditOutsideCell.add (createAndLandEdit).add (dontLandEdit);
247 EnumValues landeditOutsideVisibleCell;
248 landeditOutsideVisibleCell.add (showAndLandEdit).add (dontLandEdit);
249
250 EnumValue SelectOnly ("Select only");
251 EnumValue SelectAdd ("Add to selection");
252 EnumValue SelectRemove ("Remove from selection");
253 EnumValue selectInvert ("Invert selection");
254 EnumValues primarySelectAction;
255 primarySelectAction.add (SelectOnly).add (SelectAdd).add (SelectRemove).add (selectInvert);
256 EnumValues secondarySelectAction;
257 secondarySelectAction.add (SelectOnly).add (SelectAdd).add (SelectRemove).add (selectInvert);
258
259 declareCategory ("3D Scene Editing");
260 declareInt ("distance", "Drop Distance", 50).
261 setTooltip ("If an instance drop can not be placed against another object at the "
262 "insert point, it will be placed by this distance from the insert point instead");
263 declareEnum ("outside-drop", "Handling drops outside of cells", createAndInsert).
264 addValues (insertOutsideCell);
265 declareEnum ("outside-visible-drop", "Handling drops outside of visible cells", showAndInsert).
266 addValues (insertOutsideVisibleCell);
267 declareEnum ("outside-landedit", "Handling terrain edit outside of cells", createAndLandEdit).
268 setTooltip("Behavior of terrain editing, if land editing brush reaches an area without cell record.").
269 addValues (landeditOutsideCell);
270 declareEnum ("outside-visible-landedit", "Handling terrain edit outside of visible cells", showAndLandEdit).
271 setTooltip("Behavior of terrain editing, if land editing brush reaches an area that is not currently visible.").
272 addValues (landeditOutsideVisibleCell);
273 declareInt ("texturebrush-maximumsize", "Maximum texture brush size", 50).
274 setMin (1);
275 declareInt ("shapebrush-maximumsize", "Maximum height edit brush size", 100).
276 setTooltip("Setting for the slider range of brush size in terrain height editing.").
277 setMin (1);
278 declareBool ("landedit-post-smoothpainting", "Smooth land after painting height", false).
279 setTooltip("Raise and lower tools will leave bumpy finish without this option");
280 declareDouble ("landedit-post-smoothstrength", "Smoothing strength (post-edit)", 0.25).
281 setTooltip("If smoothing land after painting height is used, this is the percentage of smooth applied afterwards. "
282 "Negative values may be used to roughen instead of smooth.").
283 setMin (-1).
284 setMax (1);
285 declareBool ("open-list-view", "Open displays list view", false).
286 setTooltip ("When opening a reference from the scene view, it will open the"
287 " instance list view instead of the individual instance record view.");
288 declareEnum ("primary-select-action", "Action for primary select", SelectOnly).
289 setTooltip("Selection can be chosen between select only, add to selection, remove from selection and invert selection.").
290 addValues (primarySelectAction);
291 declareEnum ("secondary-select-action", "Action for secondary select", SelectAdd).
292 setTooltip("Selection can be chosen between select only, add to selection, remove from selection and invert selection.").
293 addValues (secondarySelectAction);
294
295 declareCategory ("Key Bindings");
296
297 declareSubcategory ("Document");
298 declareShortcut ("document-file-newgame", "New Game", QKeySequence(Qt::ControlModifier | Qt::Key_N));
299 declareShortcut ("document-file-newaddon", "New Addon", QKeySequence());
300 declareShortcut ("document-file-open", "Open", QKeySequence(Qt::ControlModifier | Qt::Key_O));
301 declareShortcut ("document-file-save", "Save", QKeySequence(Qt::ControlModifier | Qt::Key_S));
302 declareShortcut ("document-help-help", "Help", QKeySequence(Qt::Key_F1));
303 declareShortcut ("document-help-tutorial", "Tutorial", QKeySequence());
304 declareShortcut ("document-file-verify", "Verify", QKeySequence());
305 declareShortcut ("document-file-merge", "Merge", QKeySequence());
306 declareShortcut ("document-file-errorlog", "Open Load Error Log", QKeySequence());
307 declareShortcut ("document-file-metadata", "Meta Data", QKeySequence());
308 declareShortcut ("document-file-close", "Close Document", QKeySequence(Qt::ControlModifier | Qt::Key_W));
309 declareShortcut ("document-file-exit", "Exit Application", QKeySequence(Qt::ControlModifier | Qt::Key_Q));
310 declareShortcut ("document-edit-undo", "Undo", QKeySequence(Qt::ControlModifier | Qt::Key_Z));
311 declareShortcut ("document-edit-redo", "Redo", QKeySequence(Qt::ControlModifier | Qt::ShiftModifier | Qt::Key_Z));
312 declareShortcut ("document-edit-preferences", "Open Preferences", QKeySequence());
313 declareShortcut ("document-edit-search", "Search", QKeySequence(Qt::ControlModifier | Qt::Key_F));
314 declareShortcut ("document-view-newview", "New View", QKeySequence());
315 declareShortcut ("document-view-statusbar", "Toggle Status Bar", QKeySequence());
316 declareShortcut ("document-view-filters", "Open Filter List", QKeySequence());
317 declareShortcut ("document-world-regions", "Open Region List", QKeySequence());
318 declareShortcut ("document-world-cells", "Open Cell List", QKeySequence());
319 declareShortcut ("document-world-referencables", "Open Object List", QKeySequence());
320 declareShortcut ("document-world-references", "Open Instance List", QKeySequence());
321 declareShortcut ("document-world-lands", "Open Lands List", QKeySequence());
322 declareShortcut ("document-world-landtextures", "Open Land Textures List", QKeySequence());
323 declareShortcut ("document-world-pathgrid", "Open Pathgrid List", QKeySequence());
324 declareShortcut ("document-world-regionmap", "Open Region Map", QKeySequence());
325 declareShortcut ("document-mechanics-globals", "Open Global List", QKeySequence());
326 declareShortcut ("document-mechanics-gamesettings", "Open Game Settings", QKeySequence());
327 declareShortcut ("document-mechanics-scripts", "Open Script List", QKeySequence());
328 declareShortcut ("document-mechanics-spells", "Open Spell List", QKeySequence());
329 declareShortcut ("document-mechanics-enchantments", "Open Enchantment List", QKeySequence());
330 declareShortcut ("document-mechanics-magiceffects", "Open Magic Effect List", QKeySequence());
331 declareShortcut ("document-mechanics-startscripts", "Open Start Script List", QKeySequence());
332 declareShortcut ("document-character-skills", "Open Skill List", QKeySequence());
333 declareShortcut ("document-character-classes", "Open Class List", QKeySequence());
334 declareShortcut ("document-character-factions", "Open Faction List", QKeySequence());
335 declareShortcut ("document-character-races", "Open Race List", QKeySequence());
336 declareShortcut ("document-character-birthsigns", "Open Birthsign List", QKeySequence());
337 declareShortcut ("document-character-topics", "Open Topic List", QKeySequence());
338 declareShortcut ("document-character-journals", "Open Journal List", QKeySequence());
339 declareShortcut ("document-character-topicinfos", "Open Topic Info List", QKeySequence());
340 declareShortcut ("document-character-journalinfos", "Open Journal Info List", QKeySequence());
341 declareShortcut ("document-character-bodyparts", "Open Body Part List", QKeySequence());
342 declareShortcut ("document-assets-reload", "Reload Assets", QKeySequence(Qt::Key_F5));
343 declareShortcut ("document-assets-sounds", "Open Sound Asset List", QKeySequence());
344 declareShortcut ("document-assets-soundgens", "Open Sound Generator List", QKeySequence());
345 declareShortcut ("document-assets-meshes", "Open Mesh Asset List", QKeySequence());
346 declareShortcut ("document-assets-icons", "Open Icon Asset List", QKeySequence());
347 declareShortcut ("document-assets-music", "Open Music Asset List", QKeySequence());
348 declareShortcut ("document-assets-soundres", "Open Sound File List", QKeySequence());
349 declareShortcut ("document-assets-textures", "Open Texture Asset List", QKeySequence());
350 declareShortcut ("document-assets-videos", "Open Video Asset List", QKeySequence());
351 declareShortcut ("document-debug-run", "Run Debug", QKeySequence());
352 declareShortcut ("document-debug-shutdown", "Stop Debug", QKeySequence());
353 declareShortcut ("document-debug-profiles", "Debug Profiles", QKeySequence());
354 declareShortcut ("document-debug-runlog", "Open Run Log", QKeySequence());
355
356 declareSubcategory ("Table");
357 declareShortcut ("table-edit", "Edit Record", QKeySequence());
358 declareShortcut ("table-add", "Add Row/Record", QKeySequence(Qt::ShiftModifier | Qt::Key_A));
359 declareShortcut ("table-clone", "Clone Record", QKeySequence(Qt::ShiftModifier | Qt::Key_D));
360 declareShortcut ("touch-record", "Touch Record", QKeySequence());
361 declareShortcut ("table-revert", "Revert Record", QKeySequence());
362 declareShortcut ("table-remove", "Remove Row/Record", QKeySequence(Qt::Key_Delete));
363 declareShortcut ("table-moveup", "Move Record Up", QKeySequence());
364 declareShortcut ("table-movedown", "Move Record Down", QKeySequence());
365 declareShortcut ("table-view", "View Record", QKeySequence(Qt::ShiftModifier | Qt::Key_C));
366 declareShortcut ("table-preview", "Preview Record", QKeySequence(Qt::ShiftModifier | Qt::Key_V));
367 declareShortcut ("table-extendeddelete", "Extended Record Deletion", QKeySequence());
368 declareShortcut ("table-extendedrevert", "Extended Record Revertion", QKeySequence());
369
370 declareSubcategory ("Report Table");
371 declareShortcut ("reporttable-show", "Show Report", QKeySequence());
372 declareShortcut ("reporttable-remove", "Remove Report", QKeySequence(Qt::Key_Delete));
373 declareShortcut ("reporttable-replace", "Replace Report", QKeySequence());
374 declareShortcut ("reporttable-refresh", "Refresh Report", QKeySequence());
375
376 declareSubcategory ("Scene");
377 declareShortcut ("scene-navi-primary", "Camera Rotation From Mouse Movement", QKeySequence(Qt::LeftButton));
378 declareShortcut ("scene-navi-secondary", "Camera Translation From Mouse Movement",
379 QKeySequence(Qt::ControlModifier | (int)Qt::LeftButton));
380 declareShortcut ("scene-open-primary", "Primary Open", QKeySequence(Qt::ShiftModifier | (int)Qt::LeftButton));
381 declareShortcut ("scene-edit-primary", "Primary Edit", QKeySequence(Qt::RightButton));
382 declareShortcut ("scene-edit-secondary", "Secondary Edit",
383 QKeySequence(Qt::ControlModifier | (int)Qt::RightButton));
384 declareShortcut ("scene-select-primary", "Primary Select", QKeySequence(Qt::MiddleButton));
385 declareShortcut ("scene-select-secondary", "Secondary Select",
386 QKeySequence(Qt::ControlModifier | (int)Qt::MiddleButton));
387 declareModifier ("scene-speed-modifier", "Speed Modifier", Qt::Key_Shift);
388 declareShortcut ("scene-delete", "Delete Instance", QKeySequence(Qt::Key_Delete));
389 declareShortcut ("scene-instance-drop-terrain", "Drop to terrain level", QKeySequence(Qt::Key_G));
390 declareShortcut ("scene-instance-drop-collision", "Drop to collision", QKeySequence(Qt::Key_H));
391 declareShortcut ("scene-instance-drop-terrain-separately", "Drop to terrain level separately", QKeySequence());
392 declareShortcut ("scene-instance-drop-collision-separately", "Drop to collision separately", QKeySequence());
393 declareShortcut ("scene-load-cam-cell", "Load Camera Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_5));
394 declareShortcut ("scene-load-cam-eastcell", "Load East Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_6));
395 declareShortcut ("scene-load-cam-northcell", "Load North Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_8));
396 declareShortcut ("scene-load-cam-westcell", "Load West Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_4));
397 declareShortcut ("scene-load-cam-southcell", "Load South Cell", QKeySequence(Qt::KeypadModifier | Qt::Key_2));
398 declareShortcut ("scene-edit-abort", "Abort", QKeySequence(Qt::Key_Escape));
399 declareShortcut ("scene-focus-toolbar", "Toggle Toolbar Focus", QKeySequence(Qt::Key_T));
400 declareShortcut ("scene-render-stats", "Debug Rendering Stats", QKeySequence(Qt::Key_F3));
401
402 declareSubcategory ("1st/Free Camera");
403 declareShortcut ("free-forward", "Forward", QKeySequence(Qt::Key_W));
404 declareShortcut ("free-backward", "Backward", QKeySequence(Qt::Key_S));
405 declareShortcut ("free-left", "Left", QKeySequence(Qt::Key_A));
406 declareShortcut ("free-right", "Right", QKeySequence(Qt::Key_D));
407 declareShortcut ("free-roll-left", "Roll Left", QKeySequence(Qt::Key_Q));
408 declareShortcut ("free-roll-right", "Roll Right", QKeySequence(Qt::Key_E));
409 declareShortcut ("free-speed-mode", "Toggle Speed Mode", QKeySequence(Qt::Key_F));
410
411 declareSubcategory ("Orbit Camera");
412 declareShortcut ("orbit-up", "Up", QKeySequence(Qt::Key_W));
413 declareShortcut ("orbit-down", "Down", QKeySequence(Qt::Key_S));
414 declareShortcut ("orbit-left", "Left", QKeySequence(Qt::Key_A));
415 declareShortcut ("orbit-right", "Right", QKeySequence(Qt::Key_D));
416 declareShortcut ("orbit-roll-left", "Roll Left", QKeySequence(Qt::Key_Q));
417 declareShortcut ("orbit-roll-right", "Roll Right", QKeySequence(Qt::Key_E));
418 declareShortcut ("orbit-speed-mode", "Toggle Speed Mode", QKeySequence(Qt::Key_F));
419 declareShortcut ("orbit-center-selection", "Center On Selected", QKeySequence(Qt::Key_C));
420
421 declareSubcategory ("Script Editor");
422 declareShortcut ("script-editor-comment", "Comment Selection", QKeySequence());
423 declareShortcut ("script-editor-uncomment", "Uncomment Selection", QKeySequence());
424
425 declareCategory ("Models");
426 declareString ("baseanim", "base animations", "meshes/base_anim.nif").
427 setTooltip("3rd person base model with textkeys-data");
428 declareString ("baseanimkna", "base animations, kna", "meshes/base_animkna.nif").
429 setTooltip("3rd person beast race base model with textkeys-data");
430 declareString ("baseanimfemale", "base animations, female", "meshes/base_anim_female.nif").
431 setTooltip("3rd person female base model with textkeys-data");
432 declareString ("wolfskin", "base animations, wolf", "meshes/wolf/skin.nif").
433 setTooltip("3rd person werewolf skin");
434 }
435
declareCategory(const std::string & key)436 void CSMPrefs::State::declareCategory (const std::string& key)
437 {
438 std::map<std::string, Category>::iterator iter = mCategories.find (key);
439
440 if (iter!=mCategories.end())
441 {
442 mCurrentCategory = iter;
443 }
444 else
445 {
446 mCurrentCategory =
447 mCategories.insert (std::make_pair (key, Category (this, key))).first;
448 }
449 }
450
declareInt(const std::string & key,const std::string & label,int default_)451 CSMPrefs::IntSetting& CSMPrefs::State::declareInt (const std::string& key,
452 const std::string& label, int default_)
453 {
454 if (mCurrentCategory==mCategories.end())
455 throw std::logic_error ("no category for setting");
456
457 setDefault(key, std::to_string(default_));
458
459 default_ = mSettings.getInt (key, mCurrentCategory->second.getKey());
460
461 CSMPrefs::IntSetting *setting =
462 new CSMPrefs::IntSetting (&mCurrentCategory->second, &mSettings, &mMutex, key, label,
463 default_);
464
465 mCurrentCategory->second.addSetting (setting);
466
467 return *setting;
468 }
469
declareDouble(const std::string & key,const std::string & label,double default_)470 CSMPrefs::DoubleSetting& CSMPrefs::State::declareDouble (const std::string& key,
471 const std::string& label, double default_)
472 {
473 if (mCurrentCategory==mCategories.end())
474 throw std::logic_error ("no category for setting");
475
476 std::ostringstream stream;
477 stream << default_;
478 setDefault(key, stream.str());
479
480 default_ = mSettings.getFloat (key, mCurrentCategory->second.getKey());
481
482 CSMPrefs::DoubleSetting *setting =
483 new CSMPrefs::DoubleSetting (&mCurrentCategory->second, &mSettings, &mMutex,
484 key, label, default_);
485
486 mCurrentCategory->second.addSetting (setting);
487
488 return *setting;
489 }
490
declareBool(const std::string & key,const std::string & label,bool default_)491 CSMPrefs::BoolSetting& CSMPrefs::State::declareBool (const std::string& key,
492 const std::string& label, bool default_)
493 {
494 if (mCurrentCategory==mCategories.end())
495 throw std::logic_error ("no category for setting");
496
497 setDefault (key, default_ ? "true" : "false");
498
499 default_ = mSettings.getBool (key, mCurrentCategory->second.getKey());
500
501 CSMPrefs::BoolSetting *setting =
502 new CSMPrefs::BoolSetting (&mCurrentCategory->second, &mSettings, &mMutex, key, label,
503 default_);
504
505 mCurrentCategory->second.addSetting (setting);
506
507 return *setting;
508 }
509
declareEnum(const std::string & key,const std::string & label,EnumValue default_)510 CSMPrefs::EnumSetting& CSMPrefs::State::declareEnum (const std::string& key,
511 const std::string& label, EnumValue default_)
512 {
513 if (mCurrentCategory==mCategories.end())
514 throw std::logic_error ("no category for setting");
515
516 setDefault (key, default_.mValue);
517
518 default_.mValue = mSettings.getString (key, mCurrentCategory->second.getKey());
519
520 CSMPrefs::EnumSetting *setting =
521 new CSMPrefs::EnumSetting (&mCurrentCategory->second, &mSettings, &mMutex, key, label,
522 default_);
523
524 mCurrentCategory->second.addSetting (setting);
525
526 return *setting;
527 }
528
declareColour(const std::string & key,const std::string & label,QColor default_)529 CSMPrefs::ColourSetting& CSMPrefs::State::declareColour (const std::string& key,
530 const std::string& label, QColor default_)
531 {
532 if (mCurrentCategory==mCategories.end())
533 throw std::logic_error ("no category for setting");
534
535 setDefault (key, default_.name().toUtf8().data());
536
537 default_.setNamedColor (QString::fromUtf8 (mSettings.getString (key, mCurrentCategory->second.getKey()).c_str()));
538
539 CSMPrefs::ColourSetting *setting =
540 new CSMPrefs::ColourSetting (&mCurrentCategory->second, &mSettings, &mMutex, key, label,
541 default_);
542
543 mCurrentCategory->second.addSetting (setting);
544
545 return *setting;
546 }
547
declareShortcut(const std::string & key,const std::string & label,const QKeySequence & default_)548 CSMPrefs::ShortcutSetting& CSMPrefs::State::declareShortcut (const std::string& key, const std::string& label,
549 const QKeySequence& default_)
550 {
551 if (mCurrentCategory==mCategories.end())
552 throw std::logic_error ("no category for setting");
553
554 std::string seqStr = getShortcutManager().convertToString(default_);
555 setDefault (key, seqStr);
556
557 // Setup with actual data
558 QKeySequence sequence;
559
560 getShortcutManager().convertFromString(mSettings.getString(key, mCurrentCategory->second.getKey()), sequence);
561 getShortcutManager().setSequence(key, sequence);
562
563 CSMPrefs::ShortcutSetting *setting = new CSMPrefs::ShortcutSetting (&mCurrentCategory->second, &mSettings, &mMutex,
564 key, label);
565 mCurrentCategory->second.addSetting (setting);
566
567 return *setting;
568 }
569
declareString(const std::string & key,const std::string & label,std::string default_)570 CSMPrefs::StringSetting& CSMPrefs::State::declareString (const std::string& key, const std::string& label, std::string default_)
571 {
572 if (mCurrentCategory==mCategories.end())
573 throw std::logic_error ("no category for setting");
574
575 setDefault (key, default_);
576
577 default_ = mSettings.getString (key, mCurrentCategory->second.getKey());
578
579 CSMPrefs::StringSetting *setting =
580 new CSMPrefs::StringSetting (&mCurrentCategory->second, &mSettings, &mMutex, key, label,
581 default_);
582
583 mCurrentCategory->second.addSetting (setting);
584
585 return *setting;
586 }
587
declareModifier(const std::string & key,const std::string & label,int default_)588 CSMPrefs::ModifierSetting& CSMPrefs::State::declareModifier(const std::string& key, const std::string& label,
589 int default_)
590 {
591 if (mCurrentCategory==mCategories.end())
592 throw std::logic_error ("no category for setting");
593
594 std::string modStr = getShortcutManager().convertToString(default_);
595 setDefault (key, modStr);
596
597 // Setup with actual data
598 int modifier;
599
600 getShortcutManager().convertFromString(mSettings.getString(key, mCurrentCategory->second.getKey()), modifier);
601 getShortcutManager().setModifier(key, modifier);
602
603 CSMPrefs::ModifierSetting *setting = new CSMPrefs::ModifierSetting (&mCurrentCategory->second, &mSettings, &mMutex,
604 key, label);
605 mCurrentCategory->second.addSetting (setting);
606
607 return *setting;
608 }
609
declareSeparator()610 void CSMPrefs::State::declareSeparator()
611 {
612 if (mCurrentCategory==mCategories.end())
613 throw std::logic_error ("no category for setting");
614
615 CSMPrefs::Setting *setting =
616 new CSMPrefs::Setting (&mCurrentCategory->second, &mSettings, &mMutex, "", "");
617
618 mCurrentCategory->second.addSetting (setting);
619 }
620
declareSubcategory(const std::string & label)621 void CSMPrefs::State::declareSubcategory(const std::string& label)
622 {
623 if (mCurrentCategory==mCategories.end())
624 throw std::logic_error ("no category for setting");
625
626 CSMPrefs::Setting *setting =
627 new CSMPrefs::Setting (&mCurrentCategory->second, &mSettings, &mMutex, "", label);
628
629 mCurrentCategory->second.addSetting (setting);
630 }
631
setDefault(const std::string & key,const std::string & default_)632 void CSMPrefs::State::setDefault (const std::string& key, const std::string& default_)
633 {
634 Settings::CategorySetting fullKey (mCurrentCategory->second.getKey(), key);
635
636 Settings::CategorySettingValueMap::iterator iter =
637 mSettings.mDefaultSettings.find (fullKey);
638
639 if (iter==mSettings.mDefaultSettings.end())
640 mSettings.mDefaultSettings.insert (std::make_pair (fullKey, default_));
641 }
642
State(const Files::ConfigurationManager & configurationManager)643 CSMPrefs::State::State (const Files::ConfigurationManager& configurationManager)
644 : mConfigFile ("openmw-cs.cfg"), mDefaultConfigFile("defaults-cs.bin"), mConfigurationManager (configurationManager),
645 mCurrentCategory (mCategories.end())
646 {
647 if (sThis)
648 throw std::logic_error ("An instance of CSMPRefs::State already exists");
649
650 sThis = this;
651
652 load();
653 declare();
654 }
655
~State()656 CSMPrefs::State::~State()
657 {
658 sThis = nullptr;
659 }
660
save()661 void CSMPrefs::State::save()
662 {
663 boost::filesystem::path user = mConfigurationManager.getUserConfigPath() / mConfigFile;
664 mSettings.saveUser (user.string());
665 }
666
begin()667 CSMPrefs::State::Iterator CSMPrefs::State::begin()
668 {
669 return mCategories.begin();
670 }
671
end()672 CSMPrefs::State::Iterator CSMPrefs::State::end()
673 {
674 return mCategories.end();
675 }
676
getShortcutManager()677 CSMPrefs::ShortcutManager& CSMPrefs::State::getShortcutManager()
678 {
679 return mShortcutManager;
680 }
681
operator [](const std::string & key)682 CSMPrefs::Category& CSMPrefs::State::operator[] (const std::string& key)
683 {
684 Iterator iter = mCategories.find (key);
685
686 if (iter==mCategories.end())
687 throw std::logic_error ("Invalid user settings category: " + key);
688
689 return iter->second;
690 }
691
update(const Setting & setting)692 void CSMPrefs::State::update (const Setting& setting)
693 {
694 emit (settingChanged (&setting));
695 }
696
get()697 CSMPrefs::State& CSMPrefs::State::get()
698 {
699 if (!sThis)
700 throw std::logic_error ("No instance of CSMPrefs::State");
701
702 return *sThis;
703 }
704
resetCategory(const std::string & category)705 void CSMPrefs::State::resetCategory(const std::string& category)
706 {
707 for (Settings::CategorySettingValueMap::iterator i = mSettings.mUserSettings.begin();
708 i != mSettings.mUserSettings.end(); ++i)
709 {
710 // if the category matches
711 if (i->first.first == category)
712 {
713 // mark the setting as changed
714 mSettings.mChangedSettings.insert(std::make_pair(i->first.first, i->first.second));
715 // reset the value to the default
716 i->second = mSettings.mDefaultSettings[i->first];
717 }
718 }
719
720 Collection::iterator container = mCategories.find(category);
721 if (container != mCategories.end())
722 {
723 Category settings = container->second;
724 for (Category::Iterator i = settings.begin(); i != settings.end(); ++i)
725 {
726 (*i)->updateWidget();
727 update(**i);
728 }
729 }
730 }
731
resetAll()732 void CSMPrefs::State::resetAll()
733 {
734 for (Collection::iterator iter = mCategories.begin(); iter != mCategories.end(); ++iter)
735 {
736 resetCategory(iter->first);
737 }
738 }
739
740
get()741 CSMPrefs::State& CSMPrefs::get()
742 {
743 return State::get();
744 }
745