1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "gui/editgamedialog.h"
24
25 #include "backends/keymapper/keymapper.h"
26
27 #include "common/config-manager.h"
28 #include "common/gui_options.h"
29 #include "common/translation.h"
30 #include "common/system.h"
31
32 #include "gui/browser.h"
33 #include "gui/gui-manager.h"
34 #include "gui/message.h"
35 #ifdef ENABLE_EVENTRECORDER
36 #include "gui/onscreendialog.h"
37 #include "gui/recorderdialog.h"
38 #include "gui/EventRecorder.h"
39 #endif
40 #include "gui/widgets/edittext.h"
41 #include "gui/widgets/tab.h"
42 #include "gui/widgets/popup.h"
43 #include "gui/widgets/scrollcontainer.h"
44
45 #if defined(USE_CLOUD) && defined(USE_LIBCURL)
46 #include "backends/cloud/cloudmanager.h"
47 #endif
48
49 using Common::ConfigManager;
50
51 namespace GUI {
52
53 enum {
54 kStartCmd = 'STRT',
55 kAboutCmd = 'ABOU',
56 kOptionsCmd = 'OPTN',
57 kAddGameCmd = 'ADDG',
58 kEditGameCmd = 'EDTG',
59 kRemoveGameCmd = 'REMG',
60 kLoadGameCmd = 'LOAD',
61 kQuitCmd = 'QUIT',
62 kSearchCmd = 'SRCH',
63 kListSearchCmd = 'LSSR',
64 kSearchClearCmd = 'SRCL',
65
66 kCmdGlobalGraphicsOverride = 'OGFX',
67 kCmdGlobalShaderOverride = 'OSHD',
68 kCmdGlobalBackendOverride = 'OBAK',
69 kCmdGlobalAudioOverride = 'OSFX',
70 kCmdGlobalMIDIOverride = 'OMID',
71 kCmdGlobalMT32Override = 'OM32',
72 kCmdGlobalVolumeOverride = 'OVOL',
73
74 kCmdChooseSoundFontCmd = 'chsf',
75
76 kCmdExtraBrowser = 'PEXT',
77 kCmdExtraPathClear = 'PEXC',
78 kCmdGameBrowser = 'PGME',
79 kCmdSaveBrowser = 'PSAV',
80 kCmdSavePathClear = 'PSAC',
81
82 kGraphicsTabContainerReflowCmd = 'gtcr'
83 };
84
85 /*
86 * TODO: Clean up this ugly design: we subclass EditTextWidget to perform
87 * input validation. It would be much more elegant to use a decorator pattern,
88 * or a validation callback, or something like that.
89 */
90 class DomainEditTextWidget : public EditTextWidget {
91 public:
DomainEditTextWidget(GuiObject * boss,const String & name,const U32String & text,const U32String & tooltip=U32String ())92 DomainEditTextWidget(GuiObject *boss, const String &name, const U32String &text, const U32String &tooltip = U32String())
93 : EditTextWidget(boss, name, text, tooltip) {}
94
95 protected:
tryInsertChar(byte c,int pos)96 bool tryInsertChar(byte c, int pos) override {
97 if (Common::isAlnum(c) || c == '-' || c == '_') {
98 _editString.insertChar(c, pos);
99 return true;
100 }
101 return false;
102 }
103 };
104
EditGameDialog(const String & domain)105 EditGameDialog::EditGameDialog(const String &domain)
106 : OptionsDialog(domain, "GameOptions") {
107 EngineMan.upgradeTargetIfNecessary(domain);
108
109 _engineOptions = nullptr;
110
111 // Retrieve the plugin, since we need to access the engine's MetaEngine
112 // implementation.
113 const Plugin *metaEnginePlugin = nullptr;
114 const Plugin *enginePlugin = nullptr;
115 QualifiedGameDescriptor qgd = EngineMan.findTarget(domain, &metaEnginePlugin);
116 if (!metaEnginePlugin) {
117 warning("MetaEnginePlugin for target \"%s\" not found!", domain.c_str());
118 } else {
119 enginePlugin = PluginMan.getEngineFromMetaEngine(metaEnginePlugin);
120 if (!enginePlugin) {
121 warning("Engine Plugin for target \"%s\" not found! Game specific settings might be missing.", domain.c_str());
122 }
123 }
124
125 // GAME: Path to game data (r/o), extra data (r/o), and save data (r/w)
126 String gamePath(ConfMan.get("path", _domain));
127 String extraPath(ConfMan.get("extrapath", _domain));
128 String savePath(ConfMan.get("savepath", _domain));
129
130 // GAME: Determine the description string
131 String description(ConfMan.get("description", domain));
132 if (description.empty() && !qgd.description.empty()) {
133 description = qgd.description;
134 }
135
136 // GUI: Add tab widget
137 TabWidget *tab = new TabWidget(this, "GameOptions.TabWidget");
138
139 //
140 // 1) The game tab
141 //
142 tab->addTab(_("Game"), "GameOptions_Game");
143
144 // GUI: Label & edit widget for the game ID
145 if (g_system->getOverlayWidth() > 320)
146 new StaticTextWidget(tab, "GameOptions_Game.Id", _("ID:"), _("Short game identifier used for referring to saved games and running the game from the command line"));
147 else
148 new StaticTextWidget(tab, "GameOptions_Game.Id", _c("ID:", "lowres"), _("Short game identifier used for referring to saved games and running the game from the command line"));
149 _domainWidget = new DomainEditTextWidget(tab, "GameOptions_Game.Domain", _domain, _("Short game identifier used for referring to saved games and running the game from the command line"));
150
151 // GUI: Label & edit widget for the description
152 if (g_system->getOverlayWidth() > 320)
153 new StaticTextWidget(tab, "GameOptions_Game.Name", _("Name:"), _("Full title of the game"));
154 else
155 new StaticTextWidget(tab, "GameOptions_Game.Name", _c("Name:", "lowres"), _("Full title of the game"));
156 _descriptionWidget = new EditTextWidget(tab, "GameOptions_Game.Desc", description, _("Full title of the game"));
157
158 // Language popup
159 _langPopUpDesc = nullptr;
160 _langPopUp = nullptr;
161 if (!_guioptions.contains(GUIO_NOLANG)) {
162 _langPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.LangPopupDesc", _("Language:"), _("Language of the game. This will not turn your Spanish game version into English"));
163 _langPopUp = new PopUpWidget(tab, "GameOptions_Game.LangPopup", _("Language of the game. This will not turn your Spanish game version into English"));
164 _langPopUp->appendEntry(_("<default>"), (uint32)Common::UNK_LANG);
165 _langPopUp->appendEntry("", (uint32)Common::UNK_LANG);
166 const Common::LanguageDescription *l = Common::g_languages;
167 for (; l->code; ++l) {
168 if (checkGameGUIOptionLanguage(l->id, _guioptionsString))
169 _langPopUp->appendEntry(l->description, l->id);
170 }
171 }
172
173 // Platform popup
174 if (g_system->getOverlayWidth() > 320)
175 _platformPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.PlatformPopupDesc", _("Platform:"), _("Platform the game was originally designed for"));
176 else
177 _platformPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.PlatformPopupDesc", _c("Platform:", "lowres"), _("Platform the game was originally designed for"));
178 _platformPopUp = new PopUpWidget(tab, "GameOptions_Game.PlatformPopup", _("Platform the game was originally designed for"));
179 _platformPopUp->appendEntry(_("<default>"));
180 _platformPopUp->appendEntry("");
181 const Common::PlatformDescription *p = Common::g_platforms;
182 for (; p->code; ++p) {
183 _platformPopUp->appendEntry(p->description, p->id);
184 }
185
186 //
187 // 2) The engine tab (shown only if the engine implements one or there are custom engine options)
188 //
189
190 if (metaEnginePlugin) {
191 int tabId = tab->addTab(_("Engine"), "GameOptions_Engine");
192
193 const MetaEngineDetection &metaEngineDetection = metaEnginePlugin->get<MetaEngineDetection>();
194 metaEngineDetection.registerDefaultSettings(_domain);
195 if (enginePlugin)
196 _engineOptions = enginePlugin->get<MetaEngine>().buildEngineOptionsWidgetDynamic(tab, "GameOptions_Engine.Container", _domain);
197 if (!_engineOptions)
198 _engineOptions = metaEngineDetection.buildEngineOptionsWidgetStatic(tab, "GameOptions_Engine.Container", _domain);
199
200 if (_engineOptions) {
201 _engineOptions->setParentDialog(this);
202 } else {
203 tab->removeTab(tabId);
204 }
205 }
206
207 //
208 // 3) The graphics tab
209 //
210 _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX"), "GameOptions_Graphics");
211 ScrollContainerWidget *graphicsContainer = new ScrollContainerWidget(tab, "GameOptions_Graphics.Container", "GameOptions_Graphics_Container", kGraphicsTabContainerReflowCmd);
212 graphicsContainer->setBackgroundType(ThemeEngine::kWidgetBackgroundNo);
213 graphicsContainer->setTarget(this);
214
215 if (g_system->getOverlayWidth() > 320)
216 _globalGraphicsOverride = new CheckboxWidget(graphicsContainer, "GameOptions_Graphics_Container.EnableTabCheckbox", _("Override global graphic settings"), Common::U32String(), kCmdGlobalGraphicsOverride);
217 else
218 _globalGraphicsOverride = new CheckboxWidget(graphicsContainer, "GameOptions_Graphics_Container.EnableTabCheckbox", _c("Override global graphic settings", "lowres"), Common::U32String(), kCmdGlobalGraphicsOverride);
219
220 addGraphicControls(graphicsContainer, "GameOptions_Graphics_Container.");
221
222 //
223 // The shader tab (currently visible only for Vita platform), visibility checking by features
224 //
225
226 _globalShaderOverride = nullptr;
227 if (g_system->hasFeature(OSystem::kFeatureShader)) {
228 tab->addTab(_("Shader"), "GameOptions_Shader");
229
230 if (g_system->getOverlayWidth() > 320)
231 _globalShaderOverride = new CheckboxWidget(tab, "GameOptions_Shader.EnableTabCheckbox", _("Override global shader settings"), Common::U32String(), kCmdGlobalShaderOverride);
232 else
233 _globalShaderOverride = new CheckboxWidget(tab, "GameOptions_Shader.EnableTabCheckbox", _c("Override global shader settings", "lowres"), Common::U32String(), kCmdGlobalShaderOverride);
234
235 addShaderControls(tab, "GameOptions_Shader.");
236 }
237
238 //
239 // The Keymap tab
240 //
241 Common::KeymapArray keymaps;
242 if (enginePlugin) {
243 keymaps = enginePlugin->get<MetaEngine>().initKeymaps(domain.c_str());
244 }
245
246 if (!keymaps.empty()) {
247 tab->addTab(_("Keymaps"), "GameOptions_KeyMapper");
248 addKeyMapperControls(tab, "GameOptions_KeyMapper.", keymaps, domain);
249 }
250
251 //
252 // The backend tab (shown only if the backend implements one)
253 //
254 int backendTabId = tab->addTab(_("Backend"), "GameOptions_Backend");
255
256 if (g_system->getOverlayWidth() > 320)
257 _globalBackendOverride = new CheckboxWidget(tab, "GameOptions_Backend.EnableTabCheckbox", _("Override global backend settings"), Common::U32String(), kCmdGlobalBackendOverride);
258 else
259 _globalBackendOverride = new CheckboxWidget(tab, "GameOptions_Backend.EnableTabCheckbox", _c("Override global backend settings", "lowres"), Common::U32String(), kCmdGlobalBackendOverride);
260
261 g_system->registerDefaultSettings(_domain);
262 _backendOptions = g_system->buildBackendOptionsWidget(tab, "GameOptions_Backend.Container", _domain);
263
264 if (_backendOptions) {
265 _backendOptions->setParentDialog(this);
266 } else {
267 tab->removeTab(backendTabId);
268 }
269
270 //
271 // 4) The audio tab
272 //
273 tab->addTab(_("Audio"), "GameOptions_Audio");
274
275 if (g_system->getOverlayWidth() > 320)
276 _globalAudioOverride = new CheckboxWidget(tab, "GameOptions_Audio.EnableTabCheckbox", _("Override global audio settings"), Common::U32String(), kCmdGlobalAudioOverride);
277 else
278 _globalAudioOverride = new CheckboxWidget(tab, "GameOptions_Audio.EnableTabCheckbox", _c("Override global audio settings", "lowres"), Common::U32String(), kCmdGlobalAudioOverride);
279
280 addAudioControls(tab, "GameOptions_Audio.");
281 addSubtitleControls(tab, "GameOptions_Audio.");
282
283 //
284 // 5) The volume tab
285 //
286 if (g_system->getOverlayWidth() > 320)
287 tab->addTab(_("Volume"), "GameOptions_Volume");
288 else
289 tab->addTab(_c("Volume", "lowres"), "GameOptions_Volume");
290
291 if (g_system->getOverlayWidth() > 320)
292 _globalVolumeOverride = new CheckboxWidget(tab, "GameOptions_Volume.EnableTabCheckbox", _("Override global volume settings"), Common::U32String(), kCmdGlobalVolumeOverride);
293 else
294 _globalVolumeOverride = new CheckboxWidget(tab, "GameOptions_Volume.EnableTabCheckbox", _c("Override global volume settings", "lowres"), Common::U32String(), kCmdGlobalVolumeOverride);
295
296 addVolumeControls(tab, "GameOptions_Volume.");
297
298 bool showMidi = !_guioptions.contains(GUIO_NOMIDI) && !_guioptions.contains(GUIO_NOMUSIC);
299
300 //
301 // 6) The MIDI tab
302 //
303 _globalMIDIOverride = nullptr;
304 if (showMidi) {
305 tab->addTab(_("MIDI"), "GameOptions_MIDI");
306
307 if (g_system->getOverlayWidth() > 320)
308 _globalMIDIOverride = new CheckboxWidget(tab, "GameOptions_MIDI.EnableTabCheckbox", _("Override global MIDI settings"), Common::U32String(), kCmdGlobalMIDIOverride);
309 else
310 _globalMIDIOverride = new CheckboxWidget(tab, "GameOptions_MIDI.EnableTabCheckbox", _c("Override global MIDI settings", "lowres"), Common::U32String(), kCmdGlobalMIDIOverride);
311
312 addMIDIControls(tab, "GameOptions_MIDI.");
313 }
314
315 //
316 // 7) The MT-32 tab
317 //
318 _globalMT32Override = nullptr;
319 if (showMidi) {
320 tab->addTab(_("MT-32"), "GameOptions_MT32");
321
322 if (g_system->getOverlayWidth() > 320)
323 _globalMT32Override = new CheckboxWidget(tab, "GameOptions_MT32.EnableTabCheckbox", _("Override global MT-32 settings"), Common::U32String(), kCmdGlobalMT32Override);
324 else
325 _globalMT32Override = new CheckboxWidget(tab, "GameOptions_MT32.EnableTabCheckbox", _c("Override global MT-32 settings", "lowres"), Common::U32String(), kCmdGlobalMT32Override);
326
327 addMT32Controls(tab, "GameOptions_MT32.");
328 }
329
330 //
331 // 8) The Paths tab
332 //
333 if (g_system->getOverlayWidth() > 320)
334 tab->addTab(_("Paths"), "GameOptions_Paths");
335 else
336 tab->addTab(_c("Paths", "lowres"), "GameOptions_Paths");
337
338 // These buttons have to be extra wide, or the text will be truncated
339 // in the small version of the GUI.
340
341 // GUI: Button + Label for the game path
342 if (g_system->getOverlayWidth() > 320)
343 new ButtonWidget(tab, "GameOptions_Paths.Gamepath", _("Game Path:"), Common::U32String(), kCmdGameBrowser);
344 else
345 new ButtonWidget(tab, "GameOptions_Paths.Gamepath", _c("Game Path:", "lowres"), Common::U32String(), kCmdGameBrowser);
346 _gamePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.GamepathText", gamePath);
347
348 // GUI: Button + Label for the additional path
349 if (g_system->getOverlayWidth() > 320)
350 new ButtonWidget(tab, "GameOptions_Paths.Extrapath", _("Extra Path:"), _("Specifies path to additional data used by the game"), kCmdExtraBrowser);
351 else
352 new ButtonWidget(tab, "GameOptions_Paths.Extrapath", _c("Extra Path:", "lowres"), _("Specifies path to additional data used by the game"), kCmdExtraBrowser);
353 _extraPathWidget = new StaticTextWidget(tab, "GameOptions_Paths.ExtrapathText", extraPath, _("Specifies path to additional data used by the game"));
354
355 _extraPathClearButton = addClearButton(tab, "GameOptions_Paths.ExtraPathClearButton", kCmdExtraPathClear);
356
357 // GUI: Button + Label for the save path
358 if (g_system->getOverlayWidth() > 320)
359 new ButtonWidget(tab, "GameOptions_Paths.Savepath", _("Save Path:"), _("Specifies where your saved games are put"), kCmdSaveBrowser);
360 else
361 new ButtonWidget(tab, "GameOptions_Paths.Savepath", _c("Save Path:", "lowres"), _("Specifies where your saved games are put"), kCmdSaveBrowser);
362 _savePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.SavepathText", savePath, _("Specifies where your saved games are put"));
363
364 _savePathClearButton = addClearButton(tab, "GameOptions_Paths.SavePathClearButton", kCmdSavePathClear);
365
366 //
367 // 9) The Achievements & The Statistics tabs
368 //
369 if (enginePlugin) {
370 const MetaEngine &metaEngine = enginePlugin->get<MetaEngine>();
371 AchMan.setActiveDomain(metaEngine.getAchievementsInfo(domain));
372 if (AchMan.getAchievementCount()) {
373 tab->addTab(_("Achievements"), "GameOptions_Achievements");
374 addAchievementsControls(tab, "GameOptions_Achievements.");
375 }
376 if (AchMan.getStatCount()) {
377 tab->addTab(_("Statistics"), "GameOptions_Achievements");
378 addStatisticsControls(tab, "GameOptions_Achievements.");
379 }
380 }
381
382 // Activate the first tab
383 tab->setActiveTab(0);
384 _tabWidget = tab;
385
386 // Add OK & Cancel buttons
387 new ButtonWidget(this, "GameOptions.Cancel", _("Cancel"), Common::U32String(), kCloseCmd);
388 new ButtonWidget(this, "GameOptions.Ok", _("OK"), Common::U32String(), kOKCmd);
389 }
390
setupGraphicsTab()391 void EditGameDialog::setupGraphicsTab() {
392 OptionsDialog::setupGraphicsTab();
393 _globalGraphicsOverride->setVisible(true);
394 }
395
open()396 void EditGameDialog::open() {
397 OptionsDialog::open();
398
399 String extraPath(ConfMan.get("extrapath", _domain));
400 if (extraPath.empty() || !ConfMan.hasKey("extrapath", _domain)) {
401 _extraPathWidget->setLabel(_c("None", "path"));
402 }
403
404 String savePath(ConfMan.get("savepath", _domain));
405 if (savePath.empty() || !ConfMan.hasKey("savepath", _domain)) {
406 _savePathWidget->setLabel(_("Default"));
407 }
408
409 int sel, i;
410 bool e;
411
412 // En-/disable dialog items depending on whether overrides are active or not.
413
414 e = ConfMan.hasKey("gfx_mode", _domain) ||
415 ConfMan.hasKey("render_mode", _domain) ||
416 ConfMan.hasKey("stretch_mode", _domain) ||
417 ConfMan.hasKey("scaler", _domain) ||
418 ConfMan.hasKey("scale_factor", _domain) ||
419 ConfMan.hasKey("aspect_ratio", _domain) ||
420 ConfMan.hasKey("fullscreen", _domain) ||
421 ConfMan.hasKey("vsync", _domain) ||
422 ConfMan.hasKey("filtering", _domain) ||
423 ConfMan.hasKey("renderer", _domain) ||
424 ConfMan.hasKey("antialiasing", _domain);
425 _globalGraphicsOverride->setState(e);
426
427 if (g_system->hasFeature(OSystem::kFeatureShader)) {
428 e = ConfMan.hasKey("shader", _domain);
429 _globalShaderOverride->setState(e);
430 }
431
432 if (_backendOptions) {
433 e = _backendOptions->hasKeys();
434 _globalBackendOverride->setState(e);
435 }
436
437 e = ConfMan.hasKey("music_driver", _domain) ||
438 ConfMan.hasKey("output_rate", _domain) ||
439 ConfMan.hasKey("opl_driver", _domain) ||
440 ConfMan.hasKey("subtitles", _domain) ||
441 ConfMan.hasKey("talkspeed", _domain);
442 _globalAudioOverride->setState(e);
443
444 e = ConfMan.hasKey("music_volume", _domain) ||
445 ConfMan.hasKey("sfx_volume", _domain) ||
446 ConfMan.hasKey("speech_volume", _domain);
447 _globalVolumeOverride->setState(e);
448
449 if (!_guioptions.contains(GUIO_NOMIDI) && !_guioptions.contains(GUIO_NOMUSIC)) {
450 e = ConfMan.hasKey("soundfont", _domain) ||
451 ConfMan.hasKey("multi_midi", _domain) ||
452 ConfMan.hasKey("midi_gain", _domain);
453 _globalMIDIOverride->setState(e);
454
455 e = ConfMan.hasKey("native_mt32", _domain) ||
456 ConfMan.hasKey("enable_gs", _domain);
457 _globalMT32Override->setState(e);
458 }
459
460 // TODO: game path
461
462 if (_langPopUp != nullptr) {
463 const Common::Language lang = Common::parseLanguage(ConfMan.get("language", _domain));
464
465 if (ConfMan.hasKey("language", _domain)) {
466 _langPopUp->setSelectedTag(lang);
467 } else {
468 _langPopUp->setSelectedTag((uint32)Common::UNK_LANG);
469 }
470
471 if (_langPopUp->numEntries() <= 3) { // If only one language is avaliable
472 _langPopUpDesc->setEnabled(false);
473 _langPopUp->setEnabled(false);
474 }
475 }
476
477 if (_engineOptions) {
478 _engineOptions->load();
479 }
480
481 const Common::PlatformDescription *p = Common::g_platforms;
482 const Common::Platform platform = Common::parsePlatform(ConfMan.get("platform", _domain));
483 sel = 0;
484 for (i = 0; p->code; ++p, ++i) {
485 if (platform == p->id)
486 sel = i + 2;
487 }
488 _platformPopUp->setSelected(sel);
489 }
490
apply()491 void EditGameDialog::apply() {
492 ConfMan.set("description", _descriptionWidget->getEditString(), _domain);
493
494 if (_langPopUp != nullptr) {
495 Common::Language lang = (Common::Language)_langPopUp->getSelectedTag();
496 if (lang < 0)
497 ConfMan.removeKey("language", _domain);
498 else
499 ConfMan.set("language", Common::getLanguageCode(lang), _domain);
500 }
501
502 U32String gamePath(_gamePathWidget->getLabel());
503 if (!gamePath.empty())
504 ConfMan.set("path", gamePath, _domain);
505
506 U32String extraPath(_extraPathWidget->getLabel());
507 if (!extraPath.empty() && (extraPath != _c("None", "path")))
508 ConfMan.set("extrapath", extraPath, _domain);
509 else
510 ConfMan.removeKey("extrapath", _domain);
511
512 U32String savePath(_savePathWidget->getLabel());
513 if (!savePath.empty() && (savePath != _("Default")))
514 ConfMan.set("savepath", savePath, _domain);
515 else
516 ConfMan.removeKey("savepath", _domain);
517
518 Common::Platform platform = (Common::Platform)_platformPopUp->getSelectedTag();
519 if (platform < 0)
520 ConfMan.removeKey("platform", _domain);
521 else
522 ConfMan.set("platform", Common::getPlatformCode(platform), _domain);
523
524 if (_engineOptions) {
525 _engineOptions->save();
526 }
527
528 OptionsDialog::apply();
529 }
530
handleCommand(CommandSender * sender,uint32 cmd,uint32 data)531 void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
532 switch (cmd) {
533 case kCmdGlobalGraphicsOverride:
534 setGraphicSettingsState(data != 0);
535 g_gui.scheduleTopDialogRedraw();
536 break;
537 case kCmdGlobalShaderOverride:
538 setShaderSettingsState(data != 0);
539 g_gui.scheduleTopDialogRedraw();
540 break;
541 case kCmdGlobalBackendOverride:
542 _backendOptions->setEnabled(data != 0);
543 g_gui.scheduleTopDialogRedraw();
544 break;
545 case kCmdGlobalAudioOverride:
546 setAudioSettingsState(data != 0);
547 setSubtitleSettingsState(data != 0);
548 if (_globalVolumeOverride == nullptr)
549 setVolumeSettingsState(data != 0);
550 g_gui.scheduleTopDialogRedraw();
551 break;
552 case kCmdGlobalMIDIOverride:
553 setMIDISettingsState(data != 0);
554 g_gui.scheduleTopDialogRedraw();
555 break;
556 case kCmdGlobalMT32Override:
557 setMT32SettingsState(data != 0);
558 g_gui.scheduleTopDialogRedraw();
559 break;
560 case kCmdGlobalVolumeOverride:
561 setVolumeSettingsState(data != 0);
562 g_gui.scheduleTopDialogRedraw();
563 break;
564 case kCmdChooseSoundFontCmd:
565 {
566 BrowserDialog browser(_("Select SoundFont"), false);
567
568 if (browser.runModal() > 0) {
569 // User made this choice...
570 Common::FSNode file(browser.getResult());
571 _soundFont->setLabel(file.getPath());
572
573 if (!file.getPath().empty() && (file.getPath() != Common::convertFromU32String(_c("None", "path"))))
574 _soundFontClearButton->setEnabled(true);
575 else
576 _soundFontClearButton->setEnabled(false);
577
578 g_gui.scheduleTopDialogRedraw();
579 }
580 break;
581 }
582
583 // Change path for the game
584 case kCmdGameBrowser:
585 {
586 BrowserDialog browser(_("Select directory with game data"), true);
587 if (browser.runModal() > 0) {
588 // User made his choice...
589 Common::FSNode dir(browser.getResult());
590
591 // TODO: Verify the game can be found in the new directory... Best
592 // done with optional specific gameid to pluginmgr detectgames?
593 // FSList files = dir.listDir(FSNode::kListFilesOnly);
594
595 _gamePathWidget->setLabel(dir.getPath());
596 g_gui.scheduleTopDialogRedraw();
597 }
598 g_gui.scheduleTopDialogRedraw();
599 break;
600 }
601
602 // Change path for extra game data (eg, using sword cutscenes when playing via CD)
603 case kCmdExtraBrowser:
604 {
605 BrowserDialog browser(_("Select additional game directory"), true);
606 if (browser.runModal() > 0) {
607 // User made his choice...
608 Common::FSNode dir(browser.getResult());
609 _extraPathWidget->setLabel(dir.getPath());
610 g_gui.scheduleTopDialogRedraw();
611 }
612 g_gui.scheduleTopDialogRedraw();
613 break;
614 }
615 // Change path for stored save game (perm and temp) data
616 case kCmdSaveBrowser:
617 {
618 BrowserDialog browser(_("Select directory for saved games"), true);
619 if (browser.runModal() > 0) {
620 // User made his choice...
621 Common::FSNode dir(browser.getResult());
622 if (dir.isWritable()) {
623 _savePathWidget->setLabel(dir.getPath());
624 } else {
625 MessageDialog error(_("The chosen directory cannot be written to. Please select another one."));
626 error.runModal();
627 return;
628 }
629 #if defined(USE_CLOUD) && defined(USE_LIBCURL)
630 MessageDialog warningMessage(_("Saved games sync feature doesn't work with non-default directories. If you want your saved games to sync, use default directory."));
631 warningMessage.runModal();
632 #endif
633 g_gui.scheduleTopDialogRedraw();
634 }
635 g_gui.scheduleTopDialogRedraw();
636 break;
637 }
638
639 case kCmdExtraPathClear:
640 _extraPathWidget->setLabel(_c("None", "path"));
641 break;
642
643 case kCmdSavePathClear:
644 _savePathWidget->setLabel(_("Default"));
645 break;
646
647 case kOKCmd:
648 {
649 // Write back changes made to config object
650 String newDomain(Common::convertFromU32String(_domainWidget->getEditString()));
651 if (newDomain != _domain) {
652 if (newDomain.empty()
653 || newDomain.hasPrefix("_")
654 || newDomain == ConfigManager::kApplicationDomain
655 || ConfMan.hasGameDomain(newDomain)) {
656 MessageDialog alert(_("This game ID is already taken. Please choose another one."));
657 alert.runModal();
658 return;
659 }
660 ConfMan.renameGameDomain(_domain, newDomain);
661 _domain = newDomain;
662 if (_engineOptions) {
663 _engineOptions->setDomain(newDomain);
664 }
665 if (_backendOptions) {
666 _backendOptions->setDomain(newDomain);
667 }
668 }
669 }
670 // fall through
671 default:
672 OptionsDialog::handleCommand(sender, cmd, data);
673 }
674 }
675
676 } // End of namespace GUI
677