ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

options.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "gui/browser.h"
00024 #include "gui/themebrowser.h"
00025 #include "gui/message.h"
00026 #include "gui/gui-manager.h"
00027 #include "gui/options.h"
00028 #include "gui/widgets/popup.h"
00029 #include "gui/widgets/tab.h"
00030 #include "gui/ThemeEval.h"
00031 #include "gui/launcher.h"
00032 
00033 #include "backends/keymapper/keymapper.h"
00034 #include "backends/keymapper/remap-widget.h"
00035 
00036 #include "common/achievements.h"
00037 #include "common/fs.h"
00038 #include "common/config-manager.h"
00039 #include "common/gui_options.h"
00040 #include "common/rendermode.h"
00041 #include "common/system.h"
00042 #include "common/textconsole.h"
00043 #include "common/translation.h"
00044 #include "common/updates.h"
00045 #include "common/util.h"
00046 #include "common/text-to-speech.h"
00047 
00048 #include "audio/mididrv.h"
00049 #include "audio/musicplugin.h"
00050 #include "audio/mixer.h"
00051 //#include "audio/fmopl.h" // ResidualVM removed
00052 #include "widgets/scrollcontainer.h"
00053 #include "widgets/edittext.h"
00054 
00055 #ifdef USE_CLOUD
00056 #ifdef USE_LIBCURL
00057 #include "backends/cloud/cloudmanager.h"
00058 #include "gui/downloaddialog.h"
00059 #endif
00060 
00061 #ifdef USE_SDL_NET
00062 #include "backends/networking/sdl_net/localwebserver.h"
00063 #endif
00064 #endif
00065 
00066 #include "graphics/renderer.h"  // ResidualVM specific
00067 
00068 namespace GUI {
00069 
00070 enum {
00071     kMidiGainChanged        = 'mgch',
00072     kMusicVolumeChanged     = 'muvc',
00073     kSfxVolumeChanged       = 'sfvc',
00074     kMuteAllChanged         = 'mute',
00075     kSubtitleToggle         = 'sttg',
00076     kSubtitleSpeedChanged   = 'stsc',
00077     kSpeechVolumeChanged    = 'vcvc',
00078     kChooseSoundFontCmd     = 'chsf',
00079     kClearSoundFontCmd      = 'clsf',
00080     kChooseSaveDirCmd       = 'chos',
00081     kSavePathClearCmd       = 'clsp',
00082     kChooseThemeDirCmd      = 'chth',
00083     kThemePathClearCmd      = 'clth',
00084     kChooseExtraDirCmd      = 'chex',
00085     kExtraPathClearCmd      = 'clex',
00086     kChoosePluginsDirCmd    = 'chpl',
00087     kPluginsPathClearCmd    = 'clpl',
00088     kChooseThemeCmd         = 'chtf',
00089     kUpdatesCheckCmd        = 'updc',
00090     kKbdMouseSpeedChanged   = 'kmsc',
00091     kJoystickDeadzoneChanged= 'jodc',
00092     kGraphicsTabContainerReflowCmd = 'gtcr',
00093     kFullscreenToggled      = 'oful'  // ResidualVM specific
00094 };
00095 
00096 enum {
00097     kSubtitlesSpeech,
00098     kSubtitlesSubs,
00099     kSubtitlesBoth
00100 };
00101 
00102 #ifdef GUI_ENABLE_KEYSDIALOG
00103 enum {
00104     kChooseKeyMappingCmd    = 'chma'
00105 };
00106 #endif
00107 
00108 #ifdef USE_FLUIDSYNTH
00109 enum {
00110     kFluidSynthSettingsCmd      = 'flst'
00111 };
00112 #endif
00113 
00114 #ifdef USE_CLOUD
00115 enum {
00116     kSyncSavesStorageCmd = 'ssst',
00117     kDownloadStorageCmd = 'dlst',
00118     kRunServerCmd = 'rnsv',
00119     kCloudTabContainerReflowCmd = 'ctcr',
00120     kServerPortClearCmd = 'spcl',
00121     kChooseRootDirCmd = 'chrp',
00122     kRootPathClearCmd = 'clrp',
00123     kConnectStorageCmd = 'Cnnt',
00124     kOpenUrlStorageCmd = 'OpUr',
00125     kPasteCodeStorageCmd = 'PsCd',
00126     kDisconnectStorageCmd = 'DcSt',
00127     kEnableStorageCmd = 'EnSt'
00128 };
00129 #endif
00130 
00131 enum {
00132     kApplyCmd = 'appl'
00133 };
00134 
00135 static const char *savePeriodLabels[] = { _s("Never"), _s("Every 5 mins"), _s("Every 10 mins"), _s("Every 15 mins"), _s("Every 30 mins"), nullptr };
00136 static const int savePeriodValues[] = { 0, 5 * 60, 10 * 60, 15 * 60, 30 * 60, -1 };
00137 // The keyboard mouse speed values range from 0 to 7 and correspond to speeds shown in the label
00138 // "10" (value 3) is the default speed corresponding to the speed before introduction of this control
00139 static const char *kbdMouseSpeedLabels[] = { "3", "5", "8", "10", "13", "15", "18", "20", nullptr };
00140 
00141 OptionsDialog::OptionsDialog(const Common::String &domain, int x, int y, int w, int h)
00142     : Dialog(x, y, w, h), _domain(domain), _graphicsTabId(-1), _midiTabId(-1), _pathsTabId(-1), _tabWidget(nullptr) {
00143     init();
00144 }
00145 
00146 OptionsDialog::OptionsDialog(const Common::String &domain, const Common::String &name)
00147     : Dialog(name), _domain(domain), _graphicsTabId(-1), _midiTabId(-1), _pathsTabId(-1), _tabWidget(nullptr) {
00148     init();
00149 }
00150 
00151 OptionsDialog::~OptionsDialog() {
00152     delete _subToggleGroup;
00153 }
00154 
00155 void OptionsDialog::init() {
00156     _enableControlSettings = false;
00157     _onscreenCheckbox = nullptr;
00158     _touchpadCheckbox = nullptr;
00159     _swapMenuAndBackBtnsCheckbox = nullptr;
00160     _kbdMouseSpeedDesc = nullptr;
00161     _kbdMouseSpeedSlider = nullptr;
00162     _kbdMouseSpeedLabel = nullptr;
00163     _joystickDeadzoneDesc = nullptr;
00164     _joystickDeadzoneSlider = nullptr;
00165     _joystickDeadzoneLabel = nullptr;
00166     _keymapperWidget = nullptr;
00167     _enableGraphicSettings = false;
00168     _gfxPopUp = nullptr;
00169     _gfxPopUpDesc = nullptr;
00170     _renderModePopUp = nullptr;
00171     _renderModePopUpDesc = nullptr;
00172     _stretchPopUp = nullptr;
00173     _stretchPopUpDesc = nullptr;
00174     _fullscreenCheckbox = nullptr;
00175     _filteringCheckbox = nullptr;
00176     _aspectCheckbox = nullptr;
00177     _enableShaderSettings = false;
00178     _shaderPopUpDesc = nullptr;
00179     _shaderPopUp = nullptr;
00180     _vsyncCheckbox = nullptr;  // ResidualVM specific
00181     _rendererTypePopUpDesc = nullptr; // ResidualVM specific
00182     _rendererTypePopUp = nullptr; // ResidualVM specific
00183     _antiAliasPopUpDesc = nullptr; // ResidualVM specific
00184     _antiAliasPopUp = nullptr; // ResidualVM specific
00185     _enableAudioSettings = false;
00186     _midiPopUp = nullptr;
00187     _midiPopUpDesc = nullptr;
00188     _oplPopUp = nullptr;
00189     _oplPopUpDesc = nullptr;
00190     _enableMIDISettings = false;
00191     _gmDevicePopUp = nullptr;
00192     _gmDevicePopUpDesc = nullptr;
00193     _soundFont = nullptr;
00194     _soundFontButton = nullptr;
00195     _soundFontClearButton = nullptr;
00196     _multiMidiCheckbox = nullptr;
00197     _midiGainDesc = nullptr;
00198     _midiGainSlider = nullptr;
00199     _midiGainLabel = nullptr;
00200     _enableMT32Settings = false;
00201     _mt32Checkbox = nullptr;
00202     _mt32DevicePopUp = nullptr;
00203     _mt32DevicePopUpDesc = nullptr;
00204     _enableGSCheckbox = nullptr;
00205     _enableVolumeSettings = false;
00206     _musicVolumeDesc = nullptr;
00207     _musicVolumeSlider = nullptr;
00208     _musicVolumeLabel = nullptr;
00209     _sfxVolumeDesc = nullptr;
00210     _sfxVolumeSlider = nullptr;
00211     _sfxVolumeLabel = nullptr;
00212     _speechVolumeDesc = nullptr;
00213     _speechVolumeSlider = nullptr;
00214     _speechVolumeLabel = nullptr;
00215     _muteCheckbox = nullptr;
00216     _enableSubtitleSettings = false;
00217     _subToggleDesc = nullptr;
00218     _subToggleGroup = nullptr;
00219     _subToggleSubOnly = nullptr;
00220     _subToggleSpeechOnly = nullptr;
00221     _subToggleSubBoth = nullptr;
00222     _subSpeedDesc = nullptr;
00223     _subSpeedSlider = nullptr;
00224     _subSpeedLabel = nullptr;
00225 
00226     // Retrieve game GUI options
00227     _guioptions.clear();
00228     if (ConfMan.hasKey("guioptions", _domain)) {
00229         _guioptionsString = ConfMan.get("guioptions", _domain);
00230         _guioptions = parseGameGUIOptions(_guioptionsString);
00231     }
00232 }
00233 
00234 void OptionsDialog::build() {
00235     // Retrieve game GUI options
00236     _guioptions.clear();
00237     if (ConfMan.hasKey("guioptions", _domain)) {
00238         _guioptionsString = ConfMan.get("guioptions", _domain);
00239         _guioptions = parseGameGUIOptions(_guioptionsString);
00240     }
00241 
00242     // Control options
00243     if (g_system->hasFeature(OSystem::kFeatureOnScreenControl)) {
00244         if (ConfMan.hasKey("onscreen_control", _domain)) {
00245             bool onscreenState =  g_system->getFeatureState(OSystem::kFeatureOnScreenControl);
00246             if (_onscreenCheckbox != nullptr)
00247                 _onscreenCheckbox->setState(onscreenState);
00248         }
00249     }
00250     if (g_system->hasFeature(OSystem::kFeatureTouchpadMode)) {
00251         if (ConfMan.hasKey("touchpad_mouse_mode", _domain)) {
00252             bool touchpadState =  g_system->getFeatureState(OSystem::kFeatureTouchpadMode);
00253             if (_touchpadCheckbox != nullptr)
00254                 _touchpadCheckbox->setState(touchpadState);
00255         }
00256     }
00257     if (g_system->hasFeature(OSystem::kFeatureSwapMenuAndBackButtons)) {
00258         if (ConfMan.hasKey("swap_menu_and_back_buttons", _domain)) {
00259             bool state =  g_system->getFeatureState(OSystem::kFeatureSwapMenuAndBackButtons);
00260             if (_swapMenuAndBackBtnsCheckbox != nullptr)
00261                 _swapMenuAndBackBtnsCheckbox->setState(state);
00262         }
00263     }
00264     if (g_system->hasFeature(OSystem::kFeatureKbdMouseSpeed)) {
00265         int value = ConfMan.getInt("kbdmouse_speed", _domain);
00266         if (_kbdMouseSpeedSlider && value < ARRAYSIZE(kbdMouseSpeedLabels) - 1 && value >= 0) {
00267             _kbdMouseSpeedSlider->setValue(value);
00268             _kbdMouseSpeedLabel->setLabel(_(kbdMouseSpeedLabels[value]));
00269         }
00270     }
00271     if (g_system->hasFeature(OSystem::kFeatureJoystickDeadzone)) {
00272         int value = ConfMan.getInt("joystick_deadzone", _domain);
00273         if (_joystickDeadzoneSlider != nullptr) {
00274             _joystickDeadzoneSlider->setValue(value);
00275             _joystickDeadzoneLabel->setValue(value);
00276         }
00277     }
00278 
00279     // Keymapper options
00280     if (_keymapperWidget) {
00281         _keymapperWidget->load();
00282     }
00283 
00284     // Graphic options
00285     if (_fullscreenCheckbox) {
00286 #if 0 // ResidualVM specific
00287         _gfxPopUp->setSelected(0);
00288 
00289         if (ConfMan.hasKey("gfx_mode", _domain)) {
00290             const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes();
00291             Common::String gfxMode(ConfMan.get("gfx_mode", _domain));
00292             int gfxCount = 1;
00293             while (gm->name) {
00294                 gfxCount++;
00295 
00296                 if (scumm_stricmp(gm->name, gfxMode.c_str()) == 0)
00297                     _gfxPopUp->setSelected(gfxCount);
00298 
00299                 gm++;
00300             }
00301         }
00302 
00303         _renderModePopUp->setSelected(0);
00304 
00305         if (ConfMan.hasKey("render_mode", _domain)) {
00306             const Common::RenderModeDescription *p = Common::g_renderModes;
00307             const Common::RenderMode renderMode = Common::parseRenderMode(ConfMan.get("render_mode", _domain));
00308             int sel = 0;
00309             for (int i = 0; p->code; ++p, ++i) {
00310                 if (renderMode == p->id)
00311                     sel = p->id;
00312             }
00313             _renderModePopUp->setSelectedTag(sel);
00314         }
00315 
00316         _stretchPopUp->setSelected(0);
00317 
00318         if (g_system->hasFeature(OSystem::kFeatureStretchMode)) {
00319             if (ConfMan.hasKey("stretch_mode", _domain)) {
00320                 const OSystem::GraphicsMode *sm = g_system->getSupportedStretchModes();
00321                 Common::String stretchMode(ConfMan.get("stretch_mode", _domain));
00322                 int stretchCount = 1;
00323                 while (sm->name) {
00324                     stretchCount++;
00325                     if (scumm_stricmp(sm->name, stretchMode.c_str()) == 0)
00326                         _stretchPopUp->setSelected(stretchCount);
00327                     sm++;
00328                 }
00329             }
00330         } else {
00331             _stretchPopUpDesc->setVisible(false);
00332             _stretchPopUp->setVisible(false);
00333         }
00334 
00335 #endif
00336         // Fullscreen setting
00337         if (g_system->hasFeature(OSystem::kFeatureFullscreenMode)) {
00338             _fullscreenCheckbox->setState(ConfMan.getBool("fullscreen", _domain));
00339         } else {
00340             _fullscreenCheckbox->setState(true);
00341             _fullscreenCheckbox->setEnabled(false);
00342         }
00343 
00344         // Filtering setting
00345         if (g_system->hasFeature(OSystem::kFeatureFilteringMode))
00346             _filteringCheckbox->setState(ConfMan.getBool("filtering", _domain));
00347         else
00348             _filteringCheckbox->setVisible(false);
00349 
00350         // Aspect ratio setting
00351         if (_guioptions.contains(GUIO_NOASPECT)) {
00352             _aspectCheckbox->setState(true); // ResidualVM specific change
00353             _aspectCheckbox->setEnabled(false);
00354         } else {
00355             _aspectCheckbox->setEnabled(true);
00356             _aspectCheckbox->setState(ConfMan.getBool("aspect_ratio", _domain));
00357         }
00358 
00359         // ResidualVM specific -- Start
00360         _vsyncCheckbox->setState(ConfMan.getBool("vsync", _domain));
00361 
00362         _rendererTypePopUp->setEnabled(true);
00363         _rendererTypePopUp->setSelectedTag(Graphics::parseRendererTypeCode(ConfMan.get("renderer", _domain)));
00364 
00365         _antiAliasPopUp->setEnabled(true);
00366         if (ConfMan.hasKey("antialiasing", _domain)) {
00367             _antiAliasPopUp->setSelectedTag(ConfMan.getInt("antialiasing", _domain));
00368         } else {
00369             _antiAliasPopUp->setSelectedTag(-1);
00370         }
00371         // ResidualVM specific -- End
00372     }
00373 
00374     // Shader options
00375     if (_shaderPopUp) {
00376         _shaderPopUp->setSelected(0);
00377 
00378         if (g_system->hasFeature(OSystem::kFeatureShader)) {
00379             if (ConfMan.hasKey("shader", _domain)) {
00380                 const OSystem::GraphicsMode *sm = g_system->getSupportedShaders();
00381                 Common::String shader(ConfMan.get("shader", _domain));
00382                 int shaderCount = 1;
00383                 while (sm->name) {
00384                     shaderCount++;
00385                     if (scumm_stricmp(sm->name, shader.c_str()) == 0)
00386                         _shaderPopUp->setSelected(shaderCount);
00387                     sm++;
00388                 }
00389             }
00390         } else {
00391             _shaderPopUpDesc->setVisible(false);
00392             _shaderPopUp->setVisible(false);
00393         }
00394     }
00395 
00396     // Audio options
00397     if (!loadMusicDeviceSetting(_midiPopUp, "music_driver"))
00398         _midiPopUp->setSelected(0);
00399 
00400 #if 0 // ResidualVM specific
00401     if (_oplPopUp) {
00402         OPL::Config::DriverId id = MAX<OPL::Config::DriverId>(OPL::Config::parse(ConfMan.get("opl_driver", _domain)), 0);
00403         _oplPopUp->setSelectedTag(id);
00404     }
00405 #endif
00406 
00407     if (_multiMidiCheckbox) {
00408         if (!loadMusicDeviceSetting(_gmDevicePopUp, "gm_device"))
00409             _gmDevicePopUp->setSelected(0);
00410 
00411         // Multi midi setting
00412         _multiMidiCheckbox->setState(ConfMan.getBool("multi_midi", _domain));
00413 
00414         Common::String soundFont(ConfMan.get("soundfont", _domain));
00415         if (soundFont.empty() || !ConfMan.hasKey("soundfont", _domain)) {
00416             _soundFont->setLabel(_c("None", "soundfont"));
00417             _soundFontClearButton->setEnabled(false);
00418         } else {
00419             _soundFont->setLabel(soundFont);
00420             _soundFontClearButton->setEnabled(true);
00421         }
00422 
00423         // MIDI gain setting
00424         _midiGainSlider->setValue(ConfMan.getInt("midi_gain", _domain));
00425         _midiGainLabel->setLabel(Common::String::format("%.2f", (double)_midiGainSlider->getValue() / 100.0));
00426     }
00427 
00428     // MT-32 options
00429     if (_mt32DevicePopUp) {
00430         if (!loadMusicDeviceSetting(_mt32DevicePopUp, "mt32_device"))
00431             _mt32DevicePopUp->setSelected(0);
00432 
00433         // Native mt32 setting
00434         _mt32Checkbox->setState(ConfMan.getBool("native_mt32", _domain));
00435 
00436         // GS extensions setting
00437         _enableGSCheckbox->setState(ConfMan.getBool("enable_gs", _domain));
00438     }
00439 
00440     // Volume options
00441     if (_musicVolumeSlider) {
00442         int vol;
00443 
00444         vol = ConfMan.getInt("music_volume", _domain);
00445         _musicVolumeSlider->setValue(vol);
00446         _musicVolumeLabel->setValue(vol);
00447 
00448         vol = ConfMan.getInt("sfx_volume", _domain);
00449         _sfxVolumeSlider->setValue(vol);
00450         _sfxVolumeLabel->setValue(vol);
00451 
00452         vol = ConfMan.getInt("speech_volume", _domain);
00453         _speechVolumeSlider->setValue(vol);
00454         _speechVolumeLabel->setValue(vol);
00455 
00456         bool val = false;
00457         if (ConfMan.hasKey("mute", _domain)) {
00458             val = ConfMan.getBool("mute", _domain);
00459         } else {
00460             ConfMan.setBool("mute", false);
00461         }
00462         _muteCheckbox->setState(val);
00463     }
00464 
00465     // Subtitle options
00466     if (_subToggleGroup) {
00467         int speed;
00468         int sliderMaxValue = _subSpeedSlider->getMaxValue();
00469 
00470         int subMode = getSubtitleMode(ConfMan.getBool("subtitles", _domain), ConfMan.getBool("speech_mute", _domain));
00471         _subToggleGroup->setValue(subMode);
00472 
00473         // Engines that reuse the subtitle speed widget set their own max value.
00474         // Scale the config value accordingly (see addSubtitleControls)
00475         speed = (ConfMan.getInt("talkspeed", _domain) * sliderMaxValue + 255 / 2) / 255;
00476         _subSpeedSlider->setValue(speed);
00477         _subSpeedLabel->setValue(speed);
00478     }
00479 }
00480 
00481 void OptionsDialog::clean() {
00482     delete _subToggleGroup;
00483     while (_firstWidget) {
00484         Widget* w = _firstWidget;
00485         removeWidget(w);
00486         // This is called from rebuild() which may result from handleCommand being called by
00487         // a child widget sendCommand call. In such a case sendCommand is still being executed
00488         // so we should not delete yet the child widget. Thus delay the deletion.
00489         g_gui.addToTrash(w, this);
00490     }
00491     init();
00492 }
00493 
00494 void OptionsDialog::rebuild() {
00495     int currentTab = _tabWidget->getActiveTab();
00496     clean();
00497     build();
00498     reflowLayout();
00499     _tabWidget->setActiveTab(currentTab);
00500     setDefaultFocusedWidget();
00501 }
00502 
00503 void OptionsDialog::open() {
00504     build();
00505 
00506     Dialog::open();
00507 
00508     // Reset result value
00509     setResult(0);
00510 }
00511 
00512 void OptionsDialog::apply() {
00513     bool graphicsModeChanged = false;
00514 
00515     // Graphic options
00516     if (_fullscreenCheckbox) {
00517         if (_enableGraphicSettings) {
00518             if (ConfMan.getBool("filtering", _domain) != _filteringCheckbox->getState())
00519                 graphicsModeChanged = true;
00520             if (ConfMan.getBool("fullscreen", _domain) != _fullscreenCheckbox->getState())
00521                 graphicsModeChanged = true;
00522             if (ConfMan.getBool("aspect_ratio", _domain) != _aspectCheckbox->getState())
00523                 graphicsModeChanged = true;
00524             if (ConfMan.getBool("vsync", _domain) != _vsyncCheckbox->getState()) // ResidualVM specific
00525                 graphicsModeChanged = true; // ResidualVM specific
00526             
00527             ConfMan.setBool("filtering", _filteringCheckbox->getState(), _domain);
00528             ConfMan.setBool("fullscreen", _fullscreenCheckbox->getState(), _domain);
00529             ConfMan.setBool("aspect_ratio", _aspectCheckbox->getState(), _domain);
00530             ConfMan.setBool("vsync", _vsyncCheckbox->getState(), _domain); // ResidualVM specific
00531             
00532 #if 0 // ResidualVM specific
00533             bool isSet = false;
00534 
00535             if ((int32)_gfxPopUp->getSelectedTag() >= 0) {
00536                 const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes();
00537 
00538                 while (gm->name) {
00539                     if (gm->id == (int)_gfxPopUp->getSelectedTag()) {
00540                         if (ConfMan.get("gfx_mode", _domain) != gm->name)
00541                             graphicsModeChanged = true;
00542                         ConfMan.set("gfx_mode", gm->name, _domain);
00543                         isSet = true;
00544                         break;
00545                     }
00546                     gm++;
00547                 }
00548             }
00549             if (!isSet)
00550                 ConfMan.removeKey("gfx_mode", _domain);
00551 
00552             if ((int32)_renderModePopUp->getSelectedTag() >= 0)
00553                 ConfMan.set("render_mode", Common::getRenderModeCode((Common::RenderMode)_renderModePopUp->getSelectedTag()), _domain);
00554 
00555             isSet = false;
00556             if ((int32)_stretchPopUp->getSelectedTag() >= 0) {
00557                 const OSystem::GraphicsMode *sm = g_system->getSupportedStretchModes();
00558                 while (sm->name) {
00559                     if (sm->id == (int)_stretchPopUp->getSelectedTag()) {
00560                         if (ConfMan.get("stretch_mode", _domain) != sm->name)
00561                             graphicsModeChanged = true;
00562                         ConfMan.set("stretch_mode", sm->name, _domain);
00563                         isSet = true;
00564                         break;
00565                     }
00566                     sm++;
00567                 }
00568             }
00569             if (!isSet)
00570                 ConfMan.removeKey("stretch_mode", _domain);
00571 #endif
00572 
00573             // ResidualVM specific -- Start
00574             if (_rendererTypePopUp->getSelectedTag() > 0) {
00575                 Graphics::RendererType selected = (Graphics::RendererType) _rendererTypePopUp->getSelectedTag();
00576                 ConfMan.set("renderer", Graphics::getRendererTypeCode(selected), _domain);
00577             } else {
00578                 ConfMan.removeKey("renderer", _domain);
00579             }
00580 
00581             if (_antiAliasPopUp->getSelectedTag() != (uint32)-1) {
00582                 uint level = _antiAliasPopUp->getSelectedTag();
00583                 ConfMan.setInt("antialiasing", level, _domain);
00584             } else {
00585                 ConfMan.removeKey("antialiasing", _domain);
00586             }
00587             // ResidualVM specific -- End
00588 
00589         } else {
00590             ConfMan.removeKey("fullscreen", _domain);
00591             ConfMan.removeKey("filtering", _domain);
00592             ConfMan.removeKey("aspect_ratio", _domain);
00593 #if 0 // ResidualVM specific
00594             ConfMan.removeKey("gfx_mode", _domain);
00595             ConfMan.removeKey("stretch_mode", _domain);
00596             ConfMan.removeKey("render_mode", _domain);
00597 #endif
00598             ConfMan.removeKey("renderer", _domain); // ResidualVM specific
00599             ConfMan.removeKey("antialiasing", _domain); // ResidualVM specific
00600             ConfMan.removeKey("vsync", _domain); // ResidualVM specific
00601         }
00602     }
00603 
00604     // Shader options
00605     if (_shaderPopUp) {
00606         if (_enableShaderSettings) {
00607             bool isSet = false;
00608 
00609             if ((int32)_shaderPopUp->getSelectedTag() >= 0) {
00610                 const OSystem::GraphicsMode *sm = g_system->getSupportedShaders();
00611                 while (sm->name) {
00612                     if (sm->id == (int)_shaderPopUp->getSelectedTag()) {
00613                         if (ConfMan.get("shader", _domain) != sm->name)
00614                             graphicsModeChanged = true;
00615                         ConfMan.set("shader", sm->name, _domain);
00616                         isSet = true;
00617                         break;
00618                     }
00619                     sm++;
00620                 }
00621             }
00622             if (!isSet)
00623                 ConfMan.removeKey("shader", _domain);
00624         } else {
00625             ConfMan.removeKey("shader", _domain);
00626         }
00627     }
00628 
00629     // Setup graphics again if needed
00630     if (_domain == Common::ConfigManager::kApplicationDomain && graphicsModeChanged) {
00631         g_system->beginGFXTransaction();
00632         g_system->setGraphicsMode(ConfMan.get("gfx_mode", _domain).c_str());
00633 
00634         if (ConfMan.hasKey("stretch_mode"))
00635             g_system->setStretchMode(ConfMan.get("stretch_mode", _domain).c_str());
00636         if (ConfMan.hasKey("aspect_ratio"))
00637             g_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, ConfMan.getBool("aspect_ratio", _domain));
00638         if (ConfMan.hasKey("fullscreen"))
00639             g_system->setFeatureState(OSystem::kFeatureFullscreenMode, ConfMan.getBool("fullscreen", _domain));
00640         if (ConfMan.hasKey("filtering"))
00641             g_system->setFeatureState(OSystem::kFeatureFilteringMode, ConfMan.getBool("filtering", _domain));
00642         if (ConfMan.hasKey("shader"))
00643             g_system->setShader(ConfMan.get("shader", _domain).c_str());
00644 
00645         OSystem::TransactionError gfxError = g_system->endGFXTransaction();
00646 
00647         // Since this might change the screen resolution we need to give
00648         // the GUI a chance to update it's internal state. Otherwise we might
00649         // get a crash when the GUI tries to grab the overlay.
00650         //
00651         // This fixes bug #3303501 "Switching from HQ2x->HQ3x crashes ScummVM"
00652         //
00653         // It is important that this is called *before* any of the current
00654         // dialog's widgets are destroyed (for example before
00655         // Dialog::close) is called, to prevent crashes caused by invalid
00656         // widgets being referenced or similar errors.
00657         g_gui.checkScreenChange();
00658 
00659         if (gfxError != OSystem::kTransactionSuccess) {
00660             // Revert ConfMan to what OSystem is using.
00661             Common::String message = _("Failed to apply some of the graphic options changes:");
00662 
00663             if (gfxError & OSystem::kTransactionModeSwitchFailed) {
00664                 const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes();
00665                 while (gm->name) {
00666                     if (gm->id == g_system->getGraphicsMode()) {
00667                         ConfMan.set("gfx_mode", gm->name, _domain);
00668                         break;
00669                     }
00670                     gm++;
00671                 }
00672                 message += "\n";
00673                 message += _("the video mode could not be changed");
00674             }
00675 
00676             if (gfxError & OSystem::kTransactionStretchModeSwitchFailed) {
00677                 const OSystem::GraphicsMode *sm = g_system->getSupportedStretchModes();
00678                 while (sm->name) {
00679                     if (sm->id == g_system->getStretchMode()) {
00680                         ConfMan.set("stretch_mode", sm->name, _domain);
00681                         break;
00682                     }
00683                     sm++;
00684                 }
00685                 message += "\n";
00686                 message += _("the stretch mode could not be changed");
00687             }
00688 
00689             if (gfxError & OSystem::kTransactionAspectRatioFailed) {
00690                 ConfMan.setBool("aspect_ratio", g_system->getFeatureState(OSystem::kFeatureAspectRatioCorrection), _domain);
00691                 message += "\n";
00692                 message += _("the aspect ratio setting could not be changed");
00693             }
00694 
00695             if (gfxError & OSystem::kTransactionFullscreenFailed) {
00696                 ConfMan.setBool("fullscreen", g_system->getFeatureState(OSystem::kFeatureFullscreenMode), _domain);
00697                 message += "\n";
00698                 message += _("the fullscreen setting could not be changed");
00699             }
00700 
00701             if (gfxError & OSystem::kTransactionFilteringFailed) {
00702                 ConfMan.setBool("filtering", g_system->getFeatureState(OSystem::kFeatureFilteringMode), _domain);
00703                 message += "\n";
00704                 message += _("the filtering setting could not be changed");
00705             }
00706 
00707             // And display the error
00708             GUI::MessageDialog dialog(message);
00709             dialog.runModal();
00710         }
00711     }
00712 
00713     if (_keymapperWidget) {
00714         bool changes = _keymapperWidget->save();
00715         if (changes) {
00716             Common::Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
00717             keymapper->reloadAllMappings();
00718         }
00719     }
00720 
00721     // Control options
00722     if (_enableControlSettings) {
00723         if (g_system->hasFeature(OSystem::kFeatureOnScreenControl)) {
00724             if (ConfMan.getBool("onscreen_control", _domain) != _onscreenCheckbox->getState()) {
00725                 g_system->setFeatureState(OSystem::kFeatureOnScreenControl, _onscreenCheckbox->getState());
00726             }
00727         }
00728         if (g_system->hasFeature(OSystem::kFeatureTouchpadMode)) {
00729             if (ConfMan.getBool("touchpad_mouse_mode", _domain) != _touchpadCheckbox->getState()) {
00730                 g_system->setFeatureState(OSystem::kFeatureTouchpadMode, _touchpadCheckbox->getState());
00731             }
00732         }
00733         if (g_system->hasFeature(OSystem::kFeatureSwapMenuAndBackButtons)) {
00734             if (ConfMan.getBool("swap_menu_and_back_buttons", _domain) != _swapMenuAndBackBtnsCheckbox->getState()) {
00735                 g_system->setFeatureState(OSystem::kFeatureSwapMenuAndBackButtons, _swapMenuAndBackBtnsCheckbox->getState());
00736             }
00737         }
00738         if (g_system->hasFeature(OSystem::kFeatureKbdMouseSpeed)) {
00739             if (ConfMan.getInt("kbdmouse_speed", _domain) != _kbdMouseSpeedSlider->getValue()) {
00740                 ConfMan.setInt("kbdmouse_speed", _kbdMouseSpeedSlider->getValue(), _domain);
00741             }
00742         }
00743         if (g_system->hasFeature(OSystem::kFeatureJoystickDeadzone)) {
00744             if (ConfMan.getInt("joystick_deadzone", _domain) != _joystickDeadzoneSlider->getValue()) {
00745                 ConfMan.setInt("joystick_deadzone", _joystickDeadzoneSlider->getValue(), _domain);
00746             }
00747         }
00748     }
00749 
00750     // Volume options
00751     if (_musicVolumeSlider) {
00752         if (_enableVolumeSettings) {
00753             ConfMan.setInt("music_volume", _musicVolumeSlider->getValue(), _domain);
00754             ConfMan.setInt("sfx_volume", _sfxVolumeSlider->getValue(), _domain);
00755             ConfMan.setInt("speech_volume", _speechVolumeSlider->getValue(), _domain);
00756             ConfMan.setBool("mute", _muteCheckbox->getState(), _domain);
00757         } else {
00758             ConfMan.removeKey("music_volume", _domain);
00759             ConfMan.removeKey("sfx_volume", _domain);
00760             ConfMan.removeKey("speech_volume", _domain);
00761             ConfMan.removeKey("mute", _domain);
00762         }
00763     }
00764 
00765     // Audio options
00766     if (_midiPopUp) {
00767         if (_enableAudioSettings) {
00768             saveMusicDeviceSetting(_midiPopUp, "music_driver");
00769         } else {
00770             ConfMan.removeKey("music_driver", _domain);
00771         }
00772     }
00773 
00774 #if 0 // ResidualVM specific
00775     if (_oplPopUp) {
00776         if (_enableAudioSettings) {
00777             const OPL::Config::EmulatorDescription *ed = OPL::Config::findDriver(_oplPopUp->getSelectedTag());
00778 
00779             if (ed)
00780                 ConfMan.set("opl_driver", ed->name, _domain);
00781             else
00782                 ConfMan.removeKey("opl_driver", _domain);
00783         } else {
00784             ConfMan.removeKey("opl_driver", _domain);
00785         }
00786     }
00787 #endif
00788 
00789     // MIDI options
00790     if (_multiMidiCheckbox) {
00791         if (_enableMIDISettings) {
00792             saveMusicDeviceSetting(_gmDevicePopUp, "gm_device");
00793 
00794             ConfMan.setBool("multi_midi", _multiMidiCheckbox->getState(), _domain);
00795             ConfMan.setInt("midi_gain", _midiGainSlider->getValue(), _domain);
00796 
00797             Common::String soundFont(_soundFont->getLabel());
00798             if (!soundFont.empty() && (soundFont != _c("None", "soundfont")))
00799                 ConfMan.set("soundfont", soundFont, _domain);
00800             else
00801                 ConfMan.removeKey("soundfont", _domain);
00802         } else {
00803             ConfMan.removeKey("gm_device", _domain);
00804             ConfMan.removeKey("multi_midi", _domain);
00805             ConfMan.removeKey("midi_gain", _domain);
00806             ConfMan.removeKey("soundfont", _domain);
00807         }
00808     }
00809 
00810     // MT-32 options
00811     if (_mt32DevicePopUp) {
00812         if (_enableMT32Settings) {
00813             saveMusicDeviceSetting(_mt32DevicePopUp, "mt32_device");
00814             ConfMan.setBool("native_mt32", _mt32Checkbox->getState(), _domain);
00815             ConfMan.setBool("enable_gs", _enableGSCheckbox->getState(), _domain);
00816         } else {
00817             ConfMan.removeKey("mt32_device", _domain);
00818             ConfMan.removeKey("native_mt32", _domain);
00819             ConfMan.removeKey("enable_gs", _domain);
00820         }
00821     }
00822 
00823     // Subtitle options
00824     if (_subToggleGroup) {
00825         if (_enableSubtitleSettings) {
00826             bool subtitles, speech_mute;
00827             int talkspeed;
00828             int sliderMaxValue = _subSpeedSlider->getMaxValue();
00829 
00830             switch (_subToggleGroup->getValue()) {
00831                 case kSubtitlesSpeech:
00832                     subtitles = speech_mute = false;
00833                     break;
00834                 case kSubtitlesBoth:
00835                     subtitles = true;
00836                     speech_mute = false;
00837                     break;
00838                 case kSubtitlesSubs:
00839                 default:
00840                     subtitles = speech_mute = true;
00841                     break;
00842             }
00843 
00844             ConfMan.setBool("subtitles", subtitles, _domain);
00845             ConfMan.setBool("speech_mute", speech_mute, _domain);
00846 
00847             // Engines that reuse the subtitle speed widget set their own max value.
00848             // Scale the config value accordingly (see addSubtitleControls)
00849             talkspeed = (_subSpeedSlider->getValue() * 255 + sliderMaxValue / 2) / sliderMaxValue;
00850             ConfMan.setInt("talkspeed", talkspeed, _domain);
00851 
00852         } else {
00853             ConfMan.removeKey("subtitles", _domain);
00854             ConfMan.removeKey("talkspeed", _domain);
00855             ConfMan.removeKey("speech_mute", _domain);
00856         }
00857     }
00858 
00859     // Save config file
00860     ConfMan.flushToDisk();
00861 }
00862 
00863 void OptionsDialog::close() {
00864     if (getResult() > 0)
00865         apply();
00866 
00867     Dialog::close();
00868 }
00869 
00870 void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
00871     switch (cmd) {
00872     case kMidiGainChanged:
00873         _midiGainLabel->setLabel(Common::String::format("%.2f", (double)_midiGainSlider->getValue() / 100.0));
00874         _midiGainLabel->markAsDirty();
00875         break;
00876     case kMusicVolumeChanged: {
00877         const int newValue = _musicVolumeSlider->getValue();
00878         _musicVolumeLabel->setValue(newValue);
00879         _musicVolumeLabel->markAsDirty();
00880 
00881         if (_guioptions.contains(GUIO_LINKMUSICTOSFX)) {
00882             updateSfxVolume(newValue);
00883 
00884             if (_guioptions.contains(GUIO_LINKSPEECHTOSFX)) {
00885                 updateSpeechVolume(newValue);
00886             }
00887         }
00888 
00889         break;
00890     }
00891     case kSfxVolumeChanged: {
00892         const int newValue = _sfxVolumeSlider->getValue();
00893         _sfxVolumeLabel->setValue(_sfxVolumeSlider->getValue());
00894         _sfxVolumeLabel->markAsDirty();
00895 
00896         if (_guioptions.contains(GUIO_LINKMUSICTOSFX)) {
00897             updateMusicVolume(newValue);
00898         }
00899 
00900         if (_guioptions.contains(GUIO_LINKSPEECHTOSFX)) {
00901             updateSpeechVolume(newValue);
00902         }
00903 
00904         break;
00905     }
00906     case kSpeechVolumeChanged: {
00907         const int newValue = _speechVolumeSlider->getValue();
00908         _speechVolumeLabel->setValue(newValue);
00909         _speechVolumeLabel->markAsDirty();
00910 
00911         if (_guioptions.contains(GUIO_LINKSPEECHTOSFX)) {
00912             updateSfxVolume(newValue);
00913 
00914             if (_guioptions.contains(GUIO_LINKMUSICTOSFX)) {
00915                 updateMusicVolume(newValue);
00916             }
00917         }
00918 
00919         break;
00920     }
00921     case kMuteAllChanged:
00922         // 'true' because if control is disabled then event do not pass
00923         setVolumeSettingsState(true);
00924         break;
00925     case kSubtitleToggle:
00926         // We update the slider settings here, when there are sliders, to
00927         // disable the speech volume in case we are in subtitle only mode.
00928         if (_musicVolumeSlider)
00929             setVolumeSettingsState(true);
00930         break;
00931     case kSubtitleSpeedChanged:
00932         _subSpeedLabel->setValue(_subSpeedSlider->getValue());
00933         _subSpeedLabel->markAsDirty();
00934         break;
00935     case kClearSoundFontCmd:
00936         _soundFont->setLabel(_c("None", "soundfont"));
00937         _soundFontClearButton->setEnabled(false);
00938         g_gui.scheduleTopDialogRedraw();
00939         break;
00940     case kKbdMouseSpeedChanged:
00941         _kbdMouseSpeedLabel->setLabel(_(kbdMouseSpeedLabels[_kbdMouseSpeedSlider->getValue()]));
00942         _kbdMouseSpeedLabel->markAsDirty();
00943         break;
00944     case kJoystickDeadzoneChanged:
00945         _joystickDeadzoneLabel->setValue(_joystickDeadzoneSlider->getValue());
00946         _joystickDeadzoneLabel->markAsDirty();
00947         break;
00948     case kGraphicsTabContainerReflowCmd:
00949         setupGraphicsTab();
00950         break;
00951     case kApplyCmd:
00952         apply();
00953         break;
00954     case kOKCmd:
00955         setResult(1);
00956         close();
00957         break;
00958     case kCloseCmd:
00959         close();
00960         break;
00961     default:
00962         Dialog::handleCommand(sender, cmd, data);
00963     }
00964 }
00965 
00966 void OptionsDialog::handleTickle() {
00967     Dialog::handleTickle();
00968 
00969     if (_keymapperWidget) {
00970         _keymapperWidget->handleTickle();
00971     }
00972 }
00973 
00974 void OptionsDialog::handleOtherEvent(const Common::Event &event) {
00975     Dialog::handleOtherEvent(event);
00976 
00977     if (event.type == Common::EVENT_INPUT_CHANGED && _keymapperWidget) {
00978         _keymapperWidget->handleInputChanged();
00979     }
00980 }
00981 
00982 void OptionsDialog::setGraphicSettingsState(bool enabled) {
00983     _enableGraphicSettings = enabled;
00984 
00985 #if 0 // ResidualVM specific
00986     _gfxPopUpDesc->setEnabled(enabled);
00987     _gfxPopUp->setEnabled(enabled);
00988     _renderModePopUpDesc->setEnabled(enabled);
00989     _renderModePopUp->setEnabled(enabled);
00990     _stretchPopUpDesc->setEnabled(enabled);
00991     _stretchPopUp->setEnabled(enabled);
00992     _filteringCheckbox->setEnabled(enabled);
00993 #endif
00994 
00995     if (g_system->hasFeature(OSystem::kFeatureFullscreenMode))
00996         _fullscreenCheckbox->setEnabled(enabled);
00997     else
00998         _fullscreenCheckbox->setEnabled(false);
00999 
01000     if (_guioptions.contains(GUIO_NOASPECT))
01001         _aspectCheckbox->setEnabled(false);
01002     else
01003         _aspectCheckbox->setEnabled(enabled);
01004 }
01005 
01006 void OptionsDialog::setShaderSettingsState(bool enabled) {
01007     _enableShaderSettings = enabled;
01008 
01009     _shaderPopUpDesc->setEnabled(enabled);
01010     _shaderPopUp->setEnabled(enabled);
01011 }
01012 
01013 void OptionsDialog::setAudioSettingsState(bool enabled) {
01014     return; // ResidualVM specific
01015     _enableAudioSettings = enabled;
01016     _midiPopUpDesc->setEnabled(enabled);
01017     _midiPopUp->setEnabled(enabled);
01018 
01019     const Common::String allFlags = MidiDriver::musicType2GUIO((uint32)-1);
01020     bool hasMidiDefined = (strpbrk(_guioptions.c_str(), allFlags.c_str()) != nullptr);
01021 
01022     if (_domain != Common::ConfigManager::kApplicationDomain && // global dialog
01023         hasMidiDefined && // No flags are specified
01024         !(_guioptions.contains(GUIO_MIDIADLIB))) {
01025         _oplPopUpDesc->setEnabled(false);
01026         _oplPopUp->setEnabled(false);
01027     } else {
01028         _oplPopUpDesc->setEnabled(enabled);
01029         _oplPopUp->setEnabled(enabled);
01030     }
01031 }
01032 
01033 void OptionsDialog::setMIDISettingsState(bool enabled) {
01034     if (_guioptions.contains(GUIO_NOMIDI))
01035         enabled = false;
01036 
01037     _gmDevicePopUpDesc->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false);
01038     _gmDevicePopUp->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false);
01039 
01040     _enableMIDISettings = enabled;
01041 
01042     _soundFontButton->setEnabled(enabled);
01043     _soundFont->setEnabled(enabled);
01044 
01045     if (enabled && !_soundFont->getLabel().empty() && (_soundFont->getLabel() != _c("None", "soundfont")))
01046         _soundFontClearButton->setEnabled(enabled);
01047     else
01048         _soundFontClearButton->setEnabled(false);
01049 
01050     _multiMidiCheckbox->setEnabled(enabled);
01051     _midiGainDesc->setEnabled(enabled);
01052     _midiGainSlider->setEnabled(enabled);
01053     _midiGainLabel->setEnabled(enabled);
01054 }
01055 
01056 void OptionsDialog::setMT32SettingsState(bool enabled) {
01057     _enableMT32Settings = enabled;
01058 
01059     _mt32DevicePopUpDesc->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false);
01060     _mt32DevicePopUp->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false);
01061 
01062     _mt32Checkbox->setEnabled(enabled);
01063     _enableGSCheckbox->setEnabled(enabled);
01064 }
01065 
01066 void OptionsDialog::setVolumeSettingsState(bool enabled) {
01067     bool ena;
01068 
01069     _enableVolumeSettings = enabled;
01070 
01071     ena = enabled && !_muteCheckbox->getState();
01072     if (_guioptions.contains(GUIO_NOMUSIC))
01073         ena = false;
01074 
01075     _musicVolumeDesc->setEnabled(ena);
01076     _musicVolumeSlider->setEnabled(ena);
01077     _musicVolumeLabel->setEnabled(ena);
01078 
01079     ena = enabled && !_muteCheckbox->getState();
01080     if (_guioptions.contains(GUIO_NOSFX))
01081         ena = false;
01082 
01083     _sfxVolumeDesc->setEnabled(ena);
01084     _sfxVolumeSlider->setEnabled(ena);
01085     _sfxVolumeLabel->setEnabled(ena);
01086 
01087     ena = enabled && !_muteCheckbox->getState();
01088     // Disable speech volume slider, when we are in subtitle only mode.
01089     if (_subToggleGroup)
01090         ena = ena && _subToggleGroup->getValue() != kSubtitlesSubs;
01091     if (_guioptions.contains(GUIO_NOSPEECH) || _guioptions.contains(GUIO_NOSPEECHVOLUME))
01092         ena = false;
01093 
01094     _speechVolumeDesc->setEnabled(ena);
01095     _speechVolumeSlider->setEnabled(ena);
01096     _speechVolumeLabel->setEnabled(ena);
01097 
01098     _muteCheckbox->setEnabled(enabled);
01099 }
01100 
01101 void OptionsDialog::setSubtitleSettingsState(bool enabled) {
01102     bool ena;
01103     _enableSubtitleSettings = enabled;
01104 
01105     ena = enabled;
01106     if ((_guioptions.contains(GUIO_NOSUBTITLES)) || (_guioptions.contains(GUIO_NOSPEECH)))
01107         ena = false;
01108 
01109     _subToggleGroup->setEnabled(ena);
01110     _subToggleDesc->setEnabled(ena);
01111 
01112     ena = enabled;
01113     if (_guioptions.contains(GUIO_NOSUBTITLES))
01114         ena = false;
01115 
01116     _subSpeedDesc->setEnabled(ena);
01117     _subSpeedSlider->setEnabled(ena);
01118     _subSpeedLabel->setEnabled(ena);
01119 }
01120 
01121 void OptionsDialog::addControlControls(GuiObject *boss, const Common::String &prefix) {
01122     // Show On-Screen control
01123     if (g_system->hasFeature(OSystem::kFeatureOnScreenControl))
01124         _onscreenCheckbox = new CheckboxWidget(boss, prefix + "grOnScreenCheckbox", _("Show On-screen control"));
01125 
01126     // Touchpad Mouse mode
01127     if (g_system->hasFeature(OSystem::kFeatureTouchpadMode))
01128         _touchpadCheckbox = new CheckboxWidget(boss, prefix + "grTouchpadCheckbox", _("Touchpad mouse mode"));
01129 
01130     // Swap menu and back buttons
01131     if (g_system->hasFeature(OSystem::kFeatureSwapMenuAndBackButtons))
01132         _swapMenuAndBackBtnsCheckbox = new CheckboxWidget(boss, prefix + "grSwapMenuAndBackBtnsCheckbox", _("Swap Menu and Back buttons"));
01133 
01134     // Keyboard and joystick mouse speed
01135     if (g_system->hasFeature(OSystem::kFeatureKbdMouseSpeed)) {
01136         if (g_system->getOverlayWidth() > 320)
01137             _kbdMouseSpeedDesc = new StaticTextWidget(boss, prefix + "grKbdMouseSpeedDesc", _("Pointer Speed:"), _("Speed for keyboard/joystick mouse pointer control"));
01138         else
01139             _kbdMouseSpeedDesc = new StaticTextWidget(boss, prefix + "grKbdMouseSpeedDesc", _c("Pointer Speed:", "lowres"), _("Speed for keyboard/joystick mouse pointer control"));
01140         _kbdMouseSpeedSlider = new SliderWidget(boss, prefix + "grKbdMouseSpeedSlider", _("Speed for keyboard/joystick mouse pointer control"), kKbdMouseSpeedChanged);
01141         _kbdMouseSpeedLabel = new StaticTextWidget(boss, prefix + "grKbdMouseSpeedLabel", "  ");
01142         _kbdMouseSpeedSlider->setMinValue(0);
01143         _kbdMouseSpeedSlider->setMaxValue(7);
01144         _kbdMouseSpeedLabel->setFlags(WIDGET_CLEARBG);
01145     }
01146 
01147     // Joystick deadzone
01148     if (g_system->hasFeature(OSystem::kFeatureJoystickDeadzone)) {
01149         if (g_system->getOverlayWidth() > 320)
01150             _joystickDeadzoneDesc = new StaticTextWidget(boss, prefix + "grJoystickDeadzoneDesc", _("Joy Deadzone:"), _("Analog joystick Deadzone"));
01151         else
01152             _joystickDeadzoneDesc = new StaticTextWidget(boss, prefix + "grJoystickDeadzoneDesc", _c("Joy Deadzone:", "lowres"), _("Analog joystick Deadzone"));
01153         _joystickDeadzoneSlider = new SliderWidget(boss, prefix + "grJoystickDeadzoneSlider", _("Analog joystick Deadzone"), kJoystickDeadzoneChanged);
01154         _joystickDeadzoneLabel = new StaticTextWidget(boss, prefix + "grJoystickDeadzoneLabel", "  ");
01155         _joystickDeadzoneSlider->setMinValue(1);
01156         _joystickDeadzoneSlider->setMaxValue(10);
01157         _joystickDeadzoneLabel->setFlags(WIDGET_CLEARBG);
01158     }
01159     _enableControlSettings = true;
01160 }
01161 
01162 void OptionsDialog::addKeyMapperControls(GuiObject *boss, const Common::String &prefix, const Common::KeymapArray &keymaps, const Common::String &domain) {
01163     Common::Keymapper *mapper = g_system->getEventManager()->getKeymapper();
01164     for (uint i = 0; i < keymaps.size(); i++) {
01165         mapper->initKeymap(keymaps[i], ConfMan.getDomain(domain));
01166     }
01167 
01168     _keymapperWidget = new Common::RemapWidget(boss, prefix + "Container", keymaps);
01169 }
01170 
01171 void OptionsDialog::addAchievementsControls(GuiObject *boss, const Common::String &prefix, const Common::AchievementsInfo &info) {
01172     Common::String achDomainId = ConfMan.get("achievements", _domain);
01173     AchMan.setActiveDomain(info.platform, info.appId);
01174 
01175     GUI::ScrollContainerWidget *scrollContainer;
01176     scrollContainer = new GUI::ScrollContainerWidget(boss, prefix + "Container", "");
01177     scrollContainer->setBackgroundType(GUI::ThemeEngine::kWidgetBackgroundNo);
01178 
01179     uint16 nAchieved = 0;
01180     uint16 nHidden = 0;
01181     uint16 nMax = info.descriptions.size();
01182 
01183     uint16 lineHeight = g_gui.xmlEval()->getVar("Globals.Line.Height");
01184     uint16 yStep = lineHeight;
01185     uint16 ySmallStep = yStep/3;
01186     uint16 yPos = lineHeight + yStep*3;
01187     uint16 progressBarWidth = 240;
01188     uint16 width = g_system->getOverlayWidth() <= 320 ? 240 : 410;
01189     uint16 descrDelta = g_system->getOverlayWidth() <= 320 ? 25 : 30;
01190 
01191     for (int16 viewAchieved = 1; viewAchieved >= 0; viewAchieved--) {
01192         // run this twice, first view all achieved, then view all non-hidden & non-achieved
01193 
01194         for (uint16 idx = 0; idx < nMax ; idx++) {
01195             int16 isAchieved = AchMan.isAchieved(info.descriptions[idx].id) ? 1 : 0;
01196 
01197             if (isAchieved != viewAchieved) {
01198                 continue;
01199             }
01200 
01201             if (isAchieved) {
01202                 nAchieved++;
01203             }
01204 
01205             if (!isAchieved && info.descriptions[idx].isHidden) {
01206                 nHidden++;
01207                 continue;
01208             }
01209 
01210             CheckboxWidget *checkBox;
01211             checkBox = new CheckboxWidget(scrollContainer, lineHeight, yPos, width, yStep, info.descriptions[idx].title);
01212             checkBox->setEnabled(false);
01213             checkBox->setState(isAchieved);
01214             yPos += yStep;
01215 
01216             if (info.descriptions[idx].comment && strlen(info.descriptions[idx].comment) > 0) {
01217                 new StaticTextWidget(scrollContainer, lineHeight + descrDelta, yPos, width - descrDelta, yStep, info.descriptions[idx].comment, Graphics::kTextAlignLeft, "", ThemeEngine::kFontStyleNormal);
01218                 yPos += yStep;
01219             }
01220 
01221             yPos += ySmallStep;
01222         }
01223     }
01224 
01225     if (nHidden) {
01226         Common::String hiddenStr = Common::String::format(_("%d hidden achievements remaining"), nHidden);
01227         new StaticTextWidget(scrollContainer, lineHeight, yPos, width, yStep, hiddenStr.c_str(), Graphics::kTextAlignLeft);
01228     }
01229 
01230     if (nMax) {
01231         Common::String totalStr = Common::String::format(_("Achievements unlocked: %d/%d"), nAchieved, nMax);
01232         new StaticTextWidget(scrollContainer, lineHeight, lineHeight, width, yStep, totalStr.c_str(), Graphics::kTextAlignLeft);
01233 
01234         SliderWidget *progressBar;
01235         progressBar = new SliderWidget(scrollContainer, lineHeight, lineHeight*2, progressBarWidth, lineHeight);
01236         progressBar->setMinValue(0);
01237         progressBar->setValue(nAchieved);
01238         progressBar->setMaxValue(nMax);
01239         progressBar->setEnabled(false);
01240     }
01241 }
01242 
01243 void OptionsDialog::addShaderControls(GuiObject *boss, const Common::String &prefix) {
01244     Common::String context;
01245     if (g_system->getOverlayWidth() <= 320)
01246         context = "lowres";
01247 
01248     // Shader selector
01249     if (g_system->getOverlayWidth() > 320)
01250         _shaderPopUpDesc = new StaticTextWidget(boss, prefix + "grShaderPopUpDesc", _("HW Shader:"), _("Different hardware shaders give different visual effects"));
01251     else
01252         _shaderPopUpDesc = new StaticTextWidget(boss, prefix + "grShaderPopUpDesc", _c("HW Shader:", "lowres"), _("Different hardware shaders give different visual effects"));
01253     _shaderPopUp = new PopUpWidget(boss, prefix + "grShaderPopUp", _("Different shaders give different visual effects"));
01254     const OSystem::GraphicsMode *p = g_system->getSupportedShaders();
01255 
01256     _shaderPopUp->appendEntry(_("<default>"));
01257     _shaderPopUp->appendEntry("");
01258     while (p->name) {
01259         _shaderPopUp->appendEntry(_c(p->description, context), p->id);
01260         p++;
01261     }
01262 
01263     _enableShaderSettings = true;
01264 }
01265 
01266 void OptionsDialog::addGraphicControls(GuiObject *boss, const Common::String &prefix) {
01267 #if 0 // ResidualVM specific
01268     const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes();
01269     Common::String context;
01270     if (g_system->getOverlayWidth() <= 320)
01271         context = "lowres";
01272 
01273     // The GFX mode popup
01274     _gfxPopUpDesc = new StaticTextWidget(boss, prefix + "grModePopupDesc", _("Graphics mode:"));
01275     _gfxPopUp = new PopUpWidget(boss, prefix + "grModePopup");
01276 
01277     _gfxPopUp->appendEntry(_("<default>"));
01278     _gfxPopUp->appendEntry("");
01279     while (gm->name) {
01280         _gfxPopUp->appendEntry(_c(gm->description, context), gm->id);
01281         gm++;
01282     }
01283 
01284     // RenderMode popup
01285     const Common::String allFlags = Common::allRenderModesGUIOs();
01286     bool renderingTypeDefined = (strpbrk(_guioptions.c_str(), allFlags.c_str()) != nullptr);
01287 
01288     _renderModePopUpDesc = new StaticTextWidget(boss, prefix + "grRenderPopupDesc", _("Render mode:"), _("Special dithering modes supported by some games"));
01289     _renderModePopUp = new PopUpWidget(boss, prefix + "grRenderPopup", _("Special dithering modes supported by some games"));
01290     _renderModePopUp->appendEntry(_("<default>"), Common::kRenderDefault);
01291     _renderModePopUp->appendEntry("");
01292     const Common::RenderModeDescription *rm = Common::g_renderModes;
01293     for (; rm->code; ++rm) {
01294         Common::String renderGuiOption = Common::renderMode2GUIO(rm->id);
01295         if ((_domain == Common::ConfigManager::kApplicationDomain) || (_domain != Common::ConfigManager::kApplicationDomain && !renderingTypeDefined) || (_guioptions.contains(renderGuiOption)))
01296             _renderModePopUp->appendEntry(_c(rm->description, context), rm->id);
01297     }
01298 
01299     // The Stretch mode popup
01300     const OSystem::GraphicsMode *sm = g_system->getSupportedStretchModes();
01301     _stretchPopUpDesc = new StaticTextWidget(boss, prefix + "grStretchModePopupDesc", _("Stretch mode:"));
01302     _stretchPopUp = new PopUpWidget(boss, prefix + "grStretchModePopup");
01303 
01304     _stretchPopUp->appendEntry(_("<default>"));
01305     _stretchPopUp->appendEntry("");
01306     while (sm->name) {
01307         _stretchPopUp->appendEntry(_c(sm->description, context), sm->id);
01308         sm++;
01309     }
01310 
01311     // Fullscreen checkbox
01312     _fullscreenCheckbox = new CheckboxWidget(boss, prefix + "grFullscreenCheckbox", _("Fullscreen mode"));
01313 #endif
01314     // Fullscreen checkbox
01315     _fullscreenCheckbox = new CheckboxWidget(boss, prefix + "grFullscreenCheckbox", _("Fullscreen mode"), 0, kFullscreenToggled);
01316 
01317     // ResidualVM specific description
01318     _aspectCheckbox = new CheckboxWidget(boss, prefix + "grAspectCheckbox", _("Preserve aspect ratio"), _("Preserve the aspect ratio in fullscreen mode"));
01319 
01320     // ResidualVM specific -- Start
01321     _vsyncCheckbox = new CheckboxWidget(boss, prefix + "grVSyncCheckbox", _("V-Sync"), _("Wait for the vertical sync to refresh the screen"));
01322 
01323     _rendererTypePopUpDesc = new StaticTextWidget(boss, prefix + "grRendererTypePopupDesc", _("Game Renderer:"));
01324     _rendererTypePopUp = new PopUpWidget(boss, prefix + "grRendererTypePopup");
01325     _rendererTypePopUp->appendEntry(_("<default>"), Graphics::kRendererTypeDefault);
01326     _rendererTypePopUp->appendEntry("");
01327     const Graphics::RendererTypeDescription *rt = Graphics::listRendererTypes();
01328     for (; rt->code; ++rt) {
01329         _rendererTypePopUp->appendEntry(_(rt->description), rt->id);
01330     }
01331 
01332     _antiAliasPopUpDesc = new StaticTextWidget(boss, prefix + "grAntiAliasPopupDesc", _("Anti-aliasing:"));
01333     _antiAliasPopUp = new PopUpWidget(boss, prefix + "grAntiAliasPopup");
01334     _antiAliasPopUp->appendEntry(_("<default>"), -1);
01335     _antiAliasPopUp->appendEntry("");
01336     _antiAliasPopUp->appendEntry(_("Disabled"), 0);
01337     const Common::Array<uint> levels = g_system->getSupportedAntiAliasingLevels();
01338     for (uint i = 0; i < levels.size(); i++) {
01339         _antiAliasPopUp->appendEntry(Common::String::format("%dx", levels[i]), levels[i]);
01340     }
01341     if (levels.empty()) {
01342         // Don't show the anti-aliasing selection menu when it is not supported
01343         _antiAliasPopUpDesc->setVisible(false);
01344         _antiAliasPopUp->setVisible(false);
01345     }
01346     // ResidualVM specific -- End
01347 
01348     // Filtering checkbox
01349     _filteringCheckbox = new CheckboxWidget(boss, prefix + "grFilteringCheckbox", _("Filter graphics"), _("Use linear filtering when scaling graphics"));
01350 
01351 #if 0 // not used by ResidualVM
01352     // Aspect ratio checkbox
01353     _aspectCheckbox = new CheckboxWidget(boss, prefix + "grAspectCheckbox", _("Aspect ratio correction"), _("Correct aspect ratio for 320x200 games"));
01354 #endif
01355     _enableGraphicSettings = true;
01356 }
01357 
01358 void OptionsDialog::addAudioControls(GuiObject *boss, const Common::String &prefix) {
01359     // The MIDI mode popup & a label
01360     if (g_system->getOverlayWidth() > 320)
01361         _midiPopUpDesc = new StaticTextWidget(boss, prefix + "auMidiPopupDesc", _domain == Common::ConfigManager::kApplicationDomain ? _("Preferred device:") : _("Music device:"), _domain == Common::ConfigManager::kApplicationDomain ? _("Specifies preferred sound device or sound card emulator") : _("Specifies output sound device or sound card emulator"));
01362     else
01363         _midiPopUpDesc = new StaticTextWidget(boss, prefix + "auMidiPopupDesc", _domain == Common::ConfigManager::kApplicationDomain ? _c("Preferred dev.:", "lowres") : _c("Music device:", "lowres"), _domain == Common::ConfigManager::kApplicationDomain ? _("Specifies preferred sound device or sound card emulator") : _("Specifies output sound device or sound card emulator"));
01364     _midiPopUp = new PopUpWidget(boss, prefix + "auMidiPopup", _("Specifies output sound device or sound card emulator"));
01365 
01366     // Populate it
01367     const Common::String allFlags = MidiDriver::musicType2GUIO((uint32)-1);
01368     bool hasMidiDefined = (strpbrk(_guioptions.c_str(), allFlags.c_str()) != nullptr);
01369 
01370     const PluginList p = MusicMan.getPlugins();
01371     for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
01372         MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
01373         for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
01374             Common::String deviceGuiOption = MidiDriver::musicType2GUIO(d->getMusicType());
01375 
01376             if ((_domain == Common::ConfigManager::kApplicationDomain && d->getMusicType() != MT_TOWNS  // global dialog - skip useless FM-Towns, C64, Amiga, AppleIIGS options there
01377                  && d->getMusicType() != MT_C64 && d->getMusicType() != MT_AMIGA && d->getMusicType() != MT_APPLEIIGS && d->getMusicType() != MT_PC98)
01378                 || (_domain != Common::ConfigManager::kApplicationDomain && !hasMidiDefined) // No flags are specified
01379                 || (_guioptions.contains(deviceGuiOption)) // flag is present
01380                 // HACK/FIXME: For now we have to show GM devices, even when the game only has GUIO_MIDIMT32 set,
01381                 // else we would not show for example external devices connected via ALSA, since they are always
01382                 // marked as General MIDI device.
01383                 || (deviceGuiOption.contains(GUIO_MIDIGM) && (_guioptions.contains(GUIO_MIDIMT32)))
01384                 || d->getMusicDriverId() == "auto" || d->getMusicDriverId() == "null") // always add default and null device
01385                 _midiPopUp->appendEntry(d->getCompleteName(), d->getHandle());
01386         }
01387     }
01388 
01389     // The OPL emulator popup & a label
01390     _oplPopUpDesc = new StaticTextWidget(boss, prefix + "auOPLPopupDesc", _("AdLib emulator:"), _("AdLib is used for music in many games"));
01391     _oplPopUp = new PopUpWidget(boss, prefix + "auOPLPopup", _("AdLib is used for music in many games"));
01392 
01393     // Populate it
01394 #if 0 // ResidualVM specific
01395     const OPL::Config::EmulatorDescription *ed = OPL::Config::getAvailable();
01396     while (ed->name) {
01397         _oplPopUp->appendEntry(_(ed->description), ed->id);
01398         ++ed;
01399     }
01400 #endif
01401 
01402     _enableAudioSettings = true;
01403 }
01404 
01405 void OptionsDialog::addMIDIControls(GuiObject *boss, const Common::String &prefix) {
01406     _gmDevicePopUpDesc = new StaticTextWidget(boss, prefix + "auPrefGmPopupDesc", _("GM device:"), _("Specifies default sound device for General MIDI output"));
01407     _gmDevicePopUp = new PopUpWidget(boss, prefix + "auPrefGmPopup");
01408 
01409     // Populate
01410     const PluginList p = MusicMan.getPlugins();
01411     // Make sure the null device is the first one in the list to avoid undesired
01412     // auto detection for users who don't have a saved setting yet.
01413     for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
01414         MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
01415         for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
01416             if (d->getMusicDriverId() == "null")
01417                 _gmDevicePopUp->appendEntry(_("Don't use General MIDI music"), d->getHandle());
01418         }
01419     }
01420     // Now we add the other devices.
01421     for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
01422         MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
01423         for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
01424             if (d->getMusicType() >= MT_GM) {
01425                 if (d->getMusicType() != MT_MT32)
01426                     _gmDevicePopUp->appendEntry(d->getCompleteName(), d->getHandle());
01427             } else if (d->getMusicDriverId() == "auto") {
01428                 _gmDevicePopUp->appendEntry(_("Use first available device"), d->getHandle());
01429             }
01430         }
01431     }
01432 
01433     if (!_domain.equals(Common::ConfigManager::kApplicationDomain)) {
01434         _gmDevicePopUpDesc->setEnabled(false);
01435         _gmDevicePopUp->setEnabled(false);
01436     }
01437 
01438     // SoundFont
01439     if (g_system->getOverlayWidth() > 320)
01440         _soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", _("SoundFont:"), _("SoundFont is supported by some audio cards, FluidSynth and Timidity"), kChooseSoundFontCmd);
01441     else
01442         _soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", _c("SoundFont:", "lowres"), _("SoundFont is supported by some audio cards, FluidSynth and Timidity"), kChooseSoundFontCmd);
01443     _soundFont = new StaticTextWidget(boss, prefix + "mcFontPath", _c("None", "soundfont"), _("SoundFont is supported by some audio cards, FluidSynth and Timidity"));
01444 
01445     _soundFontClearButton = addClearButton(boss, prefix + "mcFontClearButton", kClearSoundFontCmd);
01446 
01447     // Multi midi setting
01448     _multiMidiCheckbox = new CheckboxWidget(boss, prefix + "mcMixedCheckbox", _("Mixed AdLib/MIDI mode"), _("Use both MIDI and AdLib sound generation"));
01449 
01450     // MIDI gain setting (FluidSynth uses this)
01451     _midiGainDesc = new StaticTextWidget(boss, prefix + "mcMidiGainText", _("MIDI gain:"));
01452     _midiGainSlider = new SliderWidget(boss, prefix + "mcMidiGainSlider", nullptr, kMidiGainChanged);
01453     _midiGainSlider->setMinValue(0);
01454     _midiGainSlider->setMaxValue(1000);
01455     _midiGainLabel = new StaticTextWidget(boss, prefix + "mcMidiGainLabel", "1.00");
01456 
01457     _enableMIDISettings = true;
01458 }
01459 
01460 void OptionsDialog::addMT32Controls(GuiObject *boss, const Common::String &prefix) {
01461     _mt32DevicePopUpDesc = new StaticTextWidget(boss, prefix + "auPrefMt32PopupDesc", _("MT-32 Device:"), _("Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"));
01462     _mt32DevicePopUp = new PopUpWidget(boss, prefix + "auPrefMt32Popup");
01463 
01464     // Native mt32 setting
01465     if (g_system->getOverlayWidth() > 320)
01466         _mt32Checkbox = new CheckboxWidget(boss, prefix + "mcMt32Checkbox", _("True Roland MT-32 (disable GM emulation)"), _("Check if you want to use your real hardware Roland-compatible sound device connected to your computer"));
01467     else
01468         _mt32Checkbox = new CheckboxWidget(boss, prefix + "mcMt32Checkbox", _c("True Roland MT-32 (no GM emulation)", "lowres"), _("Check if you want to use your real hardware Roland-compatible sound device connected to your computer"));
01469 
01470     // GS Extensions setting
01471     _enableGSCheckbox = new CheckboxWidget(boss, prefix + "mcGSCheckbox", _("Roland GS device (enable MT-32 mappings)"), _("Check if you want to enable patch mappings to emulate an MT-32 on a Roland GS device"));
01472 
01473     const PluginList p = MusicMan.getPlugins();
01474     // Make sure the null device is the first one in the list to avoid undesired
01475     // auto detection for users who don't have a saved setting yet.
01476     for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
01477         MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
01478         for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
01479             if (d->getMusicDriverId() == "null")
01480                 _mt32DevicePopUp->appendEntry(_("Don't use Roland MT-32 music"), d->getHandle());
01481         }
01482     }
01483     // Now we add the other devices.
01484     for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
01485         MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
01486         for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
01487             if (d->getMusicType() >= MT_GM)
01488                 _mt32DevicePopUp->appendEntry(d->getCompleteName(), d->getHandle());
01489             else if (d->getMusicDriverId() == "auto")
01490                 _mt32DevicePopUp->appendEntry(_("Use first available device"), d->getHandle());
01491         }
01492     }
01493 
01494     if (!_domain.equals(Common::ConfigManager::kApplicationDomain)) {
01495         _mt32DevicePopUpDesc->setEnabled(false);
01496         _mt32DevicePopUp->setEnabled(false);
01497     }
01498 
01499     _enableMT32Settings = true;
01500 }
01501 
01502 // The function has an extra slider range parameter, since both the launcher and SCUMM engine
01503 // make use of the widgets. The launcher range is 0-255. SCUMM's 0-9
01504 void OptionsDialog::addSubtitleControls(GuiObject *boss, const Common::String &prefix, int maxSliderVal) {
01505 
01506     if (g_system->getOverlayWidth() > 320) {
01507         _subToggleDesc = new StaticTextWidget(boss, prefix + "subToggleDesc", _("Text and speech:"));
01508 
01509         _subToggleGroup = new RadiobuttonGroup(boss, kSubtitleToggle);
01510 
01511         _subToggleSpeechOnly = new RadiobuttonWidget(boss, prefix + "subToggleSpeechOnly", _subToggleGroup, kSubtitlesSpeech, _("Speech"));
01512         _subToggleSubOnly = new RadiobuttonWidget(boss, prefix + "subToggleSubOnly", _subToggleGroup, kSubtitlesSubs, _("Subtitles"));
01513         _subToggleSubBoth = new RadiobuttonWidget(boss, prefix + "subToggleSubBoth", _subToggleGroup, kSubtitlesBoth, _("Both"));
01514 
01515         _subSpeedDesc = new StaticTextWidget(boss, prefix + "subSubtitleSpeedDesc", _("Subtitle speed:"));
01516     } else {
01517         _subToggleDesc = new StaticTextWidget(boss, prefix + "subToggleDesc", _c("Text and speech:", "lowres"));
01518 
01519         _subToggleGroup = new RadiobuttonGroup(boss, kSubtitleToggle);
01520 
01521         _subToggleSpeechOnly = new RadiobuttonWidget(boss, prefix + "subToggleSpeechOnly", _subToggleGroup, kSubtitlesSpeech, _("Spch"), _("Speech"));
01522         _subToggleSubOnly = new RadiobuttonWidget(boss, prefix + "subToggleSubOnly", _subToggleGroup, kSubtitlesSubs, _("Subs"), _("Subtitles"));
01523         _subToggleSubBoth = new RadiobuttonWidget(boss, prefix + "subToggleSubBoth", _subToggleGroup, kSubtitlesBoth, _c("Both", "lowres"), _("Show subtitles and play speech"));
01524 
01525         _subSpeedDesc = new StaticTextWidget(boss, prefix + "subSubtitleSpeedDesc", _c("Subtitle speed:", "lowres"));
01526     }
01527 
01528     // Subtitle speed
01529     _subSpeedSlider = new SliderWidget(boss, prefix + "subSubtitleSpeedSlider", nullptr, kSubtitleSpeedChanged);
01530     _subSpeedLabel = new StaticTextWidget(boss, prefix + "subSubtitleSpeedLabel", "100%");
01531     _subSpeedSlider->setMinValue(0); _subSpeedSlider->setMaxValue(maxSliderVal);
01532     _subSpeedLabel->setFlags(WIDGET_CLEARBG);
01533 
01534     _enableSubtitleSettings = true;
01535 }
01536 
01537 void OptionsDialog::addVolumeControls(GuiObject *boss, const Common::String &prefix) {
01538 
01539     // Volume controllers
01540     if (g_system->getOverlayWidth() > 320)
01541         _musicVolumeDesc = new StaticTextWidget(boss, prefix + "vcMusicText", _("Music volume:"));
01542     else
01543         _musicVolumeDesc = new StaticTextWidget(boss, prefix + "vcMusicText", _c("Music volume:", "lowres"));
01544     _musicVolumeSlider = new SliderWidget(boss, prefix + "vcMusicSlider", nullptr, kMusicVolumeChanged);
01545     _musicVolumeLabel = new StaticTextWidget(boss, prefix + "vcMusicLabel", "100%");
01546     _musicVolumeSlider->setMinValue(0);
01547     _musicVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume);
01548     _musicVolumeLabel->setFlags(WIDGET_CLEARBG);
01549 
01550     _muteCheckbox = new CheckboxWidget(boss, prefix + "vcMuteCheckbox", _("Mute all"), nullptr, kMuteAllChanged);
01551 
01552     if (g_system->getOverlayWidth() > 320)
01553         _sfxVolumeDesc = new StaticTextWidget(boss, prefix + "vcSfxText", _("SFX volume:"), _("Special sound effects volume"));
01554     else
01555         _sfxVolumeDesc = new StaticTextWidget(boss, prefix + "vcSfxText", _c("SFX volume:", "lowres"), _("Special sound effects volume"));
01556     _sfxVolumeSlider = new SliderWidget(boss, prefix + "vcSfxSlider", _("Special sound effects volume"), kSfxVolumeChanged);
01557     _sfxVolumeLabel = new StaticTextWidget(boss, prefix + "vcSfxLabel", "100%");
01558     _sfxVolumeSlider->setMinValue(0);
01559     _sfxVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume);
01560     _sfxVolumeLabel->setFlags(WIDGET_CLEARBG);
01561 
01562     if (g_system->getOverlayWidth() > 320)
01563         _speechVolumeDesc = new StaticTextWidget(boss, prefix + "vcSpeechText" , _("Speech volume:"));
01564     else
01565         _speechVolumeDesc = new StaticTextWidget(boss, prefix + "vcSpeechText" , _c("Speech volume:", "lowres"));
01566     _speechVolumeSlider = new SliderWidget(boss, prefix + "vcSpeechSlider", nullptr, kSpeechVolumeChanged);
01567     _speechVolumeLabel = new StaticTextWidget(boss, prefix + "vcSpeechLabel", "100%");
01568     _speechVolumeSlider->setMinValue(0);
01569     _speechVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume);
01570     _speechVolumeLabel->setFlags(WIDGET_CLEARBG);
01571 
01572     _enableVolumeSettings = true;
01573 }
01574 
01575 bool OptionsDialog::loadMusicDeviceSetting(PopUpWidget *popup, Common::String setting, MusicType preferredType) {
01576     if (!popup || !popup->isEnabled())
01577         return true;
01578 
01579     if (_domain != Common::ConfigManager::kApplicationDomain || ConfMan.hasKey(setting, _domain) || preferredType) {
01580         const Common::String drv = ConfMan.get(setting, (_domain != Common::ConfigManager::kApplicationDomain && !ConfMan.hasKey(setting, _domain)) ? Common::ConfigManager::kApplicationDomain : _domain);
01581         const PluginList p = MusicMan.getPlugins();
01582 
01583         for (PluginList::const_iterator m = p.begin(); m != p.end(); ++m) {
01584             MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
01585             for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
01586                 if (setting.empty() ? (preferredType == d->getMusicType()) : (drv == d->getCompleteId())) {
01587                     popup->setSelectedTag(d->getHandle());
01588                     return popup->getSelected() != -1;
01589                 }
01590             }
01591         }
01592     }
01593 
01594     return false;
01595 }
01596 
01597 void OptionsDialog::saveMusicDeviceSetting(PopUpWidget *popup, Common::String setting) {
01598     if (!popup || !_enableAudioSettings)
01599         return;
01600 
01601     const PluginList p = MusicMan.getPlugins();
01602     bool found = false;
01603     for (PluginList::const_iterator m = p.begin(); m != p.end() && !found; ++m) {
01604         MusicDevices i = (*m)->get<MusicPluginObject>().getDevices();
01605         for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) {
01606             if (d->getHandle() == popup->getSelectedTag()) {
01607                 ConfMan.set(setting, d->getCompleteId(), _domain);
01608                 found = true;
01609                 break;
01610             }
01611         }
01612     }
01613 
01614     if (!found)
01615         ConfMan.removeKey(setting, _domain);
01616 }
01617 
01618 int OptionsDialog::getSubtitleMode(bool subtitles, bool speech_mute) {
01619     if (_guioptions.contains(GUIO_NOSUBTITLES))
01620         return kSubtitlesSpeech; // Speech only
01621     if (_guioptions.contains(GUIO_NOSPEECH))
01622         return kSubtitlesSubs; // Subtitles only
01623 
01624     if (!subtitles && !speech_mute) // Speech only
01625         return kSubtitlesSpeech;
01626     else if (subtitles && !speech_mute) // Speech and subtitles
01627         return kSubtitlesBoth;
01628     else if (subtitles && speech_mute) // Subtitles only
01629         return kSubtitlesSubs;
01630     else
01631         warning("Wrong configuration: Both subtitles and speech are off. Assuming subtitles only");
01632     return kSubtitlesSubs;
01633 }
01634 
01635 void OptionsDialog::updateMusicVolume(const int newValue) const {
01636     _musicVolumeLabel->setValue(newValue);
01637     _musicVolumeSlider->setValue(newValue);
01638     _musicVolumeLabel->markAsDirty();
01639     _musicVolumeSlider->markAsDirty();
01640 }
01641 
01642 void OptionsDialog::updateSfxVolume(const int newValue) const {
01643     _sfxVolumeLabel->setValue(newValue);
01644     _sfxVolumeSlider->setValue(newValue);
01645     _sfxVolumeLabel->markAsDirty();
01646     _sfxVolumeSlider->markAsDirty();
01647 }
01648 
01649 void OptionsDialog::updateSpeechVolume(const int newValue) const {
01650     _speechVolumeLabel->setValue(newValue);
01651     _speechVolumeSlider->setValue(newValue);
01652     _speechVolumeLabel->markAsDirty();
01653     _speechVolumeSlider->markAsDirty();
01654 }
01655 
01656 void OptionsDialog::reflowLayout() {
01657     if (_graphicsTabId != -1 && _tabWidget)
01658         _tabWidget->setTabTitle(_graphicsTabId, g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX"));
01659 
01660     Dialog::reflowLayout();
01661     setupGraphicsTab();
01662 }
01663 
01664 void OptionsDialog::setupGraphicsTab() {
01665     if (!_fullscreenCheckbox)
01666         return;
01667 #if 0 // ResidualVM specific
01668     _gfxPopUpDesc->setVisible(true);
01669     _gfxPopUp->setVisible(true);
01670     if (g_system->hasFeature(OSystem::kFeatureStretchMode)) {
01671         _stretchPopUpDesc->setVisible(true);
01672         _stretchPopUp->setVisible(true);
01673     } else {
01674         _stretchPopUpDesc->setVisible(false);
01675         _stretchPopUp->setVisible(false);
01676     }
01677 #endif
01678     _fullscreenCheckbox->setVisible(true);
01679 #if 0 // ResidualVM specific
01680     if (g_system->hasFeature(OSystem::kFeatureFilteringMode))
01681         _filteringCheckbox->setVisible(true);
01682     else
01683         _filteringCheckbox->setVisible(false);
01684 #endif
01685     _aspectCheckbox->setVisible(true);
01686 #if 0 // ResidualVM specific
01687     _renderModePopUpDesc->setVisible(true);
01688     _renderModePopUp->setVisible(true);
01689 #endif
01690 }
01691 
01692 #pragma mark -
01693 
01694 
01695 GlobalOptionsDialog::GlobalOptionsDialog(LauncherDialog *launcher)
01696     : OptionsDialog(Common::ConfigManager::kApplicationDomain, "GlobalOptions"), CommandSender(nullptr), _launcher(launcher) {
01697 #ifdef GUI_ENABLE_KEYSDIALOG
01698     _keysDialog = nullptr;
01699 #endif
01700 #ifdef USE_FLUIDSYNTH
01701     _fluidSynthSettingsDialog = nullptr;
01702 #endif
01703     _savePath = nullptr;
01704     _savePathClearButton = nullptr;
01705     _themePath = nullptr;
01706     _themePathClearButton = nullptr;
01707     _extraPath = nullptr;
01708     _extraPathClearButton = nullptr;
01709 #ifdef DYNAMIC_MODULES
01710     _pluginsPath = nullptr;
01711     _pluginsPathClearButton = nullptr;
01712 #endif
01713     _curTheme = nullptr;
01714     _rendererPopUpDesc = nullptr;
01715     _rendererPopUp = nullptr;
01716     _autosavePeriodPopUpDesc = nullptr;
01717     _autosavePeriodPopUp = nullptr;
01718     _guiLanguagePopUpDesc = nullptr;
01719     _guiLanguagePopUp = nullptr;
01720     _guiLanguageUseGameLanguageCheckbox = nullptr;
01721     _useSystemDialogsCheckbox = nullptr;
01722 #ifdef USE_UPDATES
01723     _updatesPopUpDesc = nullptr;
01724     _updatesPopUp = nullptr;
01725 #endif
01726 #ifdef USE_CLOUD
01727 #ifdef USE_LIBCURL
01728     _selectedStorageIndex = CloudMan.getStorageIndex();
01729     _storagePopUpDesc = nullptr;
01730     _storagePopUp = nullptr;
01731     _storageDisabledHint = nullptr;
01732     _storageEnableButton = nullptr;
01733     _storageUsernameDesc = nullptr;
01734     _storageUsername = nullptr;
01735     _storageUsedSpaceDesc = nullptr;
01736     _storageUsedSpace = nullptr;
01737     _storageSyncHint = nullptr;
01738     _storageLastSyncDesc = nullptr;
01739     _storageLastSync = nullptr;
01740     _storageSyncSavesButton = nullptr;
01741     _storageDownloadHint = nullptr;
01742     _storageDownloadButton = nullptr;
01743     _storageDisconnectHint = nullptr;
01744     _storageDisconnectButton = nullptr;
01745 
01746     _connectingStorage = false;
01747     _storageWizardNotConnectedHint = nullptr;
01748     _storageWizardOpenLinkHint = nullptr;
01749     _storageWizardLink = nullptr;
01750     _storageWizardCodeHint = nullptr;
01751     _storageWizardCodeBox = nullptr;
01752     _storageWizardPasteButton = nullptr;
01753     _storageWizardConnectButton = nullptr;
01754     _storageWizardConnectionStatusHint = nullptr;
01755     _redrawCloudTab = false;
01756 #endif
01757 #ifdef USE_SDL_NET
01758     _runServerButton = nullptr;
01759     _serverInfoLabel = nullptr;
01760     _rootPathButton = nullptr;
01761     _rootPath = nullptr;
01762     _rootPathClearButton = nullptr;
01763     _serverPortDesc = nullptr;
01764     _serverPort = nullptr;
01765     _serverPortClearButton = nullptr;
01766     _featureDescriptionLine1 = nullptr;
01767     _featureDescriptionLine2 = nullptr;
01768     _serverWasRunning = false;
01769 #endif
01770 #endif
01771 #ifdef USE_TTS
01772     _enableTTS = false;
01773     _ttsCheckbox = nullptr;
01774     _ttsVoiceSelectionPopUp = nullptr;
01775 #endif
01776 }
01777 
01778 GlobalOptionsDialog::~GlobalOptionsDialog() {
01779 #ifdef GUI_ENABLE_KEYSDIALOG
01780     delete _keysDialog;
01781 #endif
01782 
01783 #ifdef USE_FLUIDSYNTH
01784     delete _fluidSynthSettingsDialog;
01785 #endif
01786 }
01787 
01788 void GlobalOptionsDialog::build() {
01789     // The tab widget
01790     TabWidget *tab = new TabWidget(this, "GlobalOptions.TabWidget");
01791 
01792     //
01793     // 1) The graphics tab
01794     //
01795     _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX"), "GlobalOptions_Graphics");
01796     ScrollContainerWidget *graphicsContainer = new ScrollContainerWidget(tab, "GlobalOptions_Graphics.Container", "GlobalOptions_Graphics_Container", kGraphicsTabContainerReflowCmd);
01797     graphicsContainer->setTarget(this);
01798     graphicsContainer->setBackgroundType(ThemeEngine::kWidgetBackgroundNo);
01799     addGraphicControls(graphicsContainer, "GlobalOptions_Graphics_Container.");
01800 
01801     //
01802     // The shader tab (currently visible only for Vita platform), visibility checking by features
01803     //
01804 
01805     if (g_system->hasFeature(OSystem::kFeatureShader)) {
01806         tab->addTab(_("Shader"), "GlobalOptions_Shader");
01807         addShaderControls(tab, "GlobalOptions_Shader.");
01808     }
01809 
01810     //
01811     // The control tab (currently visible only for AndroidSDL, SDL, and Vita platform, visibility checking by features
01812     //
01813     if (g_system->hasFeature(OSystem::kFeatureTouchpadMode) ||
01814         g_system->hasFeature(OSystem::kFeatureOnScreenControl) ||
01815         g_system->hasFeature(OSystem::kFeatureSwapMenuAndBackButtons) ||
01816         g_system->hasFeature(OSystem::kFeatureKbdMouseSpeed) ||
01817         g_system->hasFeature(OSystem::kFeatureJoystickDeadzone)) {
01818         tab->addTab(_("Control"), "GlobalOptions_Control");
01819         addControlControls(tab, "GlobalOptions_Control.");
01820     }
01821 
01822     //
01823     // The Keymap tab
01824     //
01825     Common::KeymapArray keymaps;
01826 
01827     Common::Keymap *primaryGlobalKeymap = g_system->getEventManager()->getGlobalKeymap();
01828     if (primaryGlobalKeymap && !primaryGlobalKeymap->getActions().empty()) {
01829         keymaps.push_back(primaryGlobalKeymap);
01830     }
01831 
01832     keymaps.push_back(g_system->getGlobalKeymaps());
01833 
01834     Common::Keymap *guiKeymap = g_gui.getKeymap();
01835     if (guiKeymap && !guiKeymap->getActions().empty()) {
01836         keymaps.push_back(guiKeymap);
01837     }
01838 
01839     if (!keymaps.empty()) {
01840         tab->addTab(_("Keymaps"), "GlobalOptions_KeyMapper");
01841         addKeyMapperControls(tab, "GlobalOptions_KeyMapper.", keymaps, Common::ConfigManager::kKeymapperDomain);
01842     }
01843 
01844     //
01845     // 2) The audio tab
01846     //
01847     tab->addTab(_("Audio"), "GlobalOptions_Audio");
01848     addAudioControls(tab, "GlobalOptions_Audio.");
01849     addSubtitleControls(tab, "GlobalOptions_Audio.");
01850 
01851     if (g_system->getOverlayWidth() > 320)
01852         tab->addTab(_("Volume"), "GlobalOptions_Volume");
01853     else
01854         tab->addTab(_c("Volume", "lowres"), "GlobalOptions_Volume");
01855     addVolumeControls(tab, "GlobalOptions_Volume.");
01856 
01857     // TODO: cd drive setting
01858 
01859 #if 0 // ResidualVM does not use it
01860     //
01861     // 3) The MIDI tab
01862     //
01863     _midiTabId = tab->addTab(_("MIDI"), "GlobalOptions_MIDI");
01864     addMIDIControls(tab, "GlobalOptions_MIDI.");
01865 
01866     //
01867     // 4) The MT-32 tab
01868     //
01869     tab->addTab(_("MT-32"), "GlobalOptions_MT32");
01870     addMT32Controls(tab, "GlobalOptions_MT32.");
01871 #endif
01872 
01873     //
01874     // 5) The Paths tab
01875     //
01876     if (g_system->getOverlayWidth() > 320)
01877         _pathsTabId = tab->addTab(_("Paths"), "GlobalOptions_Paths");
01878     else
01879         _pathsTabId = tab->addTab(_c("Paths", "lowres"), "GlobalOptions_Paths");
01880     addPathsControls(tab, "GlobalOptions_Paths.", g_system->getOverlayWidth() <= 320);
01881 
01882     //
01883     // 6) The miscellaneous tab
01884     //
01885     if (g_system->getOverlayWidth() > 320)
01886         tab->addTab(_("Misc"), "GlobalOptions_Misc");
01887     else
01888         tab->addTab(_c("Misc", "lowres"), "GlobalOptions_Misc");
01889     ScrollContainerWidget *miscContainer = new ScrollContainerWidget(tab, "GlobalOptions_Misc.Container", "GlobalOptions_Misc_Container");
01890     miscContainer->setTarget(this);
01891     miscContainer->setBackgroundType(ThemeEngine::kWidgetBackgroundNo);
01892     addMiscControls(miscContainer, "GlobalOptions_Misc_Container.", g_system->getOverlayWidth() <= 320);
01893 
01894 #ifdef USE_CLOUD
01895 #ifdef USE_LIBCURL
01896     //
01897     // 7) The Cloud tab (remote storages)
01898     //
01899     if (g_system->getOverlayWidth() > 320)
01900         tab->addTab(_("Cloud"), "GlobalOptions_Cloud");
01901     else
01902         tab->addTab(_c("Cloud", "lowres"), "GlobalOptions_Cloud");
01903 
01904     ScrollContainerWidget *container = new ScrollContainerWidget(tab, "GlobalOptions_Cloud.Container", "GlobalOptions_Cloud_Container", kCloudTabContainerReflowCmd);
01905     container->setTarget(this);
01906     container->setBackgroundType(ThemeEngine::kWidgetBackgroundNo);
01907     setTarget(container);
01908 
01909     addCloudControls(container, "GlobalOptions_Cloud_Container.", g_system->getOverlayWidth() <= 320);
01910 #endif // USE_LIBCURL
01911 #ifdef USE_SDL_NET
01912     //
01913     // 8) The LAN tab (local "cloud" webserver)
01914     //
01915     if (g_system->getOverlayWidth() > 320)
01916         tab->addTab(_("LAN"), "GlobalOptions_Network");
01917     else
01918         tab->addTab(_c("LAN", "lowres"), "GlobalOptions_Network");
01919     addNetworkControls(tab, "GlobalOptions_Network.", g_system->getOverlayWidth() <= 320);
01920 #endif // USE_SDL_NET
01921 #endif // USE_CLOUD
01922 
01923     //Accessibility
01924 #ifdef USE_TTS
01925     if (g_system->getOverlayWidth() > 320)
01926         tab->addTab(_("Accessibility"), "GlobalOptions_Accessibility");
01927     else
01928         tab->addTab(_c("Accessibility", "lowres"), "GlobalOptions_Accessibility");
01929     addAccessibilityControls(tab, "GlobalOptions_Accessibility.");
01930 #endif // USE_TTS
01931 
01932     // Activate the first tab
01933     tab->setActiveTab(0);
01934     _tabWidget = tab;
01935 
01936     // Add OK & Cancel buttons
01937     new ButtonWidget(this, "GlobalOptions.Cancel", _("Cancel"), nullptr, kCloseCmd);
01938     new ButtonWidget(this, "GlobalOptions.Apply", _("Apply"), nullptr, kApplyCmd);
01939     new ButtonWidget(this, "GlobalOptions.Ok", _("OK"), nullptr, kOKCmd);
01940 
01941 #ifdef GUI_ENABLE_KEYSDIALOG
01942     _keysDialog = new KeysDialog();
01943 #endif
01944 
01945 #ifdef USE_FLUIDSYNTH
01946     _fluidSynthSettingsDialog = new FluidSynthSettingsDialog();
01947 #endif
01948 
01949     OptionsDialog::build();
01950 
01951 #if !defined(__DC__)
01952     // Set _savePath to the current save path
01953     Common::String savePath(ConfMan.get("savepath", _domain));
01954     Common::String themePath(ConfMan.get("themepath", _domain));
01955     Common::String extraPath(ConfMan.get("extrapath", _domain));
01956 
01957     if (savePath.empty() || !ConfMan.hasKey("savepath", _domain)) {
01958         _savePath->setLabel(_("Default"));
01959     } else {
01960         _savePath->setLabel(savePath);
01961     }
01962 
01963     if (themePath.empty() || !ConfMan.hasKey("themepath", _domain)) {
01964         _themePath->setLabel(_c("None", "path"));
01965     } else {
01966         _themePath->setLabel(themePath);
01967     }
01968 
01969     if (extraPath.empty() || !ConfMan.hasKey("extrapath", _domain)) {
01970         _extraPath->setLabel(_c("None", "path"));
01971     } else {
01972         _extraPath->setLabel(extraPath);
01973     }
01974 
01975 #ifdef DYNAMIC_MODULES
01976     Common::String pluginsPath(ConfMan.get("pluginspath", _domain));
01977     if (pluginsPath.empty() || !ConfMan.hasKey("pluginspath", _domain)) {
01978         _pluginsPath->setLabel(_c("None", "path"));
01979     } else {
01980         _pluginsPath->setLabel(pluginsPath);
01981     }
01982 #endif
01983 #endif
01984 
01985     // Misc Tab
01986     _autosavePeriodPopUp->setSelected(1);
01987     int value = ConfMan.getInt("autosave_period");
01988     for (int i = 0; savePeriodLabels[i]; i++) {
01989         if (value == savePeriodValues[i])
01990             _autosavePeriodPopUp->setSelected(i);
01991     }
01992 
01993     ThemeEngine::GraphicsMode mode = ThemeEngine::findMode(ConfMan.get("gui_renderer"));
01994     if (mode == ThemeEngine::kGfxDisabled)
01995         mode = ThemeEngine::_defaultRendererMode;
01996     _rendererPopUp->setSelectedTag(mode);
01997 
01998 #ifdef USE_CLOUD
01999 #ifdef USE_SDL_NET
02000     Common::String rootPath(ConfMan.get("rootpath", "cloud"));
02001     if (rootPath.empty() || !ConfMan.hasKey("rootpath", "cloud")) {
02002         _rootPath->setLabel(_c("None", "path"));
02003     } else {
02004         _rootPath->setLabel(rootPath);
02005     }
02006 #endif
02007 #endif
02008 }
02009 
02010 void GlobalOptionsDialog::clean() {
02011 #ifdef GUI_ENABLE_KEYSDIALOG
02012     delete _keysDialog;
02013     _keysDialog = nullptr;
02014 #endif
02015 
02016 #ifdef USE_FLUIDSYNTH
02017     delete _fluidSynthSettingsDialog;
02018     _fluidSynthSettingsDialog = nullptr;
02019 #endif
02020 
02021     OptionsDialog::clean();
02022 }
02023 
02024 void GlobalOptionsDialog::addMIDIControls(GuiObject *boss, const Common::String &prefix) {
02025     OptionsDialog::addMIDIControls(boss, prefix);
02026 
02027 #ifdef USE_FLUIDSYNTH
02028     new ButtonWidget(boss, prefix + "mcFluidSynthSettings", _("FluidSynth Settings"), nullptr, kFluidSynthSettingsCmd);
02029 #endif
02030 }
02031 
02032 void GlobalOptionsDialog::addPathsControls(GuiObject *boss, const Common::String &prefix, bool lowres) {
02033 #if !defined(__DC__)
02034     // These two buttons have to be extra wide, or the text will be
02035     // truncated in the small version of the GUI.
02036 
02037     // Save game path
02038     if (!lowres)
02039         new ButtonWidget(boss, prefix + "SaveButton", _("Save Path:"), _("Specifies where your saved games are put"), kChooseSaveDirCmd);
02040     else
02041         new ButtonWidget(boss, prefix + "SaveButton", _c("Save Path:", "lowres"), _("Specifies where your saved games are put"), kChooseSaveDirCmd);
02042     _savePath = new StaticTextWidget(boss, prefix + "SavePath", "/foo/bar", _("Specifies where your saved games are put"));
02043 
02044     _savePathClearButton = addClearButton(boss, prefix + "SavePathClearButton", kSavePathClearCmd);
02045 
02046     if (!lowres)
02047         new ButtonWidget(boss, prefix + "ThemeButton", _("Theme Path:"), nullptr, kChooseThemeDirCmd);
02048     else
02049         new ButtonWidget(boss, prefix + "ThemeButton", _c("Theme Path:", "lowres"), nullptr, kChooseThemeDirCmd);
02050     _themePath = new StaticTextWidget(boss, prefix + "ThemePath", _c("None", "path"));
02051 
02052     _themePathClearButton = addClearButton(boss, prefix + "ThemePathClearButton", kThemePathClearCmd);
02053 
02054     if (!lowres)
02055         new ButtonWidget(boss, prefix + "ExtraButton", _("Extra Path:"), _("Specifies path to additional data used by all games or ResidualVM"), kChooseExtraDirCmd);
02056     else
02057         new ButtonWidget(boss, prefix + "ExtraButton", _c("Extra Path:", "lowres"), _("Specifies path to additional data used by all games or ResidualVM"), kChooseExtraDirCmd);
02058     _extraPath = new StaticTextWidget(boss, prefix + "ExtraPath", _c("None", "path"), _("Specifies path to additional data used by all games or ResidualVM"));
02059 
02060     _extraPathClearButton = addClearButton(boss, prefix + "ExtraPathClearButton", kExtraPathClearCmd);
02061 
02062 #ifdef DYNAMIC_MODULES
02063     if (!lowres)
02064         new ButtonWidget(boss, prefix + "PluginsButton", _("Plugins Path:"), nullptr, kChoosePluginsDirCmd);
02065     else
02066         new ButtonWidget(boss, prefix + "PluginsButton", _c("Plugins Path:", "lowres"), nullptr, kChoosePluginsDirCmd);
02067     _pluginsPath = new StaticTextWidget(boss, prefix + "PluginsPath", _c("None", "path"));
02068 
02069     _pluginsPathClearButton = addClearButton(boss, "GlobalOptions_Paths.PluginsPathClearButton", kPluginsPathClearCmd);
02070 #endif
02071 #endif
02072 }
02073 
02074 void GlobalOptionsDialog::addMiscControls(GuiObject *boss, const Common::String &prefix, bool lowres) {
02075     new ButtonWidget(boss, prefix + "ThemeButton", _("Theme:"), nullptr, kChooseThemeCmd);
02076     _curTheme = new StaticTextWidget(boss, prefix + "CurTheme", g_gui.theme()->getThemeName());
02077 
02078 
02079     _rendererPopUpDesc = new StaticTextWidget(boss, prefix + "RendererPopupDesc", _("GUI renderer:"));
02080     _rendererPopUp = new PopUpWidget(boss, prefix + "RendererPopup");
02081 
02082     if (!lowres) {
02083         for (uint i = 1; i < GUI::ThemeEngine::_rendererModesSize; ++i)
02084             _rendererPopUp->appendEntry(_(GUI::ThemeEngine::_rendererModes[i].name), GUI::ThemeEngine::_rendererModes[i].mode);
02085     } else {
02086         for (uint i = 1; i < GUI::ThemeEngine::_rendererModesSize; ++i)
02087             _rendererPopUp->appendEntry(_(GUI::ThemeEngine::_rendererModes[i].shortname), GUI::ThemeEngine::_rendererModes[i].mode);
02088     }
02089 
02090     if (!lowres)
02091         _autosavePeriodPopUpDesc = new StaticTextWidget(boss, prefix + "AutosavePeriodPopupDesc", _("Autosave:"));
02092     else
02093         _autosavePeriodPopUpDesc = new StaticTextWidget(boss, prefix + "AutosavePeriodPopupDesc", _c("Autosave:", "lowres"));
02094     _autosavePeriodPopUp = new PopUpWidget(boss, prefix + "AutosavePeriodPopup");
02095 
02096     for (int i = 0; savePeriodLabels[i]; i++) {
02097         _autosavePeriodPopUp->appendEntry(_(savePeriodLabels[i]), savePeriodValues[i]);
02098     }
02099 
02100 #ifdef GUI_ENABLE_KEYSDIALOG
02101     new ButtonWidget(boss, prefix + "KeysButton", _("Keys"), nullptr, kChooseKeyMappingCmd);
02102 #endif
02103 
02104     // TODO: joystick setting
02105 
02106 
02107 #ifdef USE_TRANSLATION
02108     _guiLanguagePopUpDesc = new StaticTextWidget(boss, prefix + "GuiLanguagePopupDesc", _("GUI language:"), _("Language of ResidualVM GUI"));
02109     _guiLanguagePopUp = new PopUpWidget(boss, prefix + "GuiLanguagePopup");
02110 #ifdef USE_DETECTLANG
02111     _guiLanguagePopUp->appendEntry(_("<default>"), Common::kTranslationAutodetectId);
02112 #endif // USE_DETECTLANG
02113     _guiLanguagePopUp->appendEntry("English", Common::kTranslationBuiltinId);
02114     _guiLanguagePopUp->appendEntry("", 0);
02115     Common::TLangArray languages = TransMan.getSupportedLanguageNames();
02116     Common::TLangArray::iterator lang = languages.begin();
02117     while (lang != languages.end()) {
02118         _guiLanguagePopUp->appendEntry(lang->name, lang->id);
02119         lang++;
02120     }
02121 
02122     // Select the currently configured language or default/English if
02123     // nothing is specified.
02124     if (ConfMan.hasKey("gui_language") && !ConfMan.get("gui_language").empty())
02125         _guiLanguagePopUp->setSelectedTag(TransMan.parseLanguage(ConfMan.get("gui_language")));
02126     else
02127 #ifdef USE_DETECTLANG
02128         _guiLanguagePopUp->setSelectedTag(Common::kTranslationAutodetectId);
02129 #else // !USE_DETECTLANG
02130         _guiLanguagePopUp->setSelectedTag(Common::kTranslationBuiltinId);
02131 #endif // USE_DETECTLANG
02132 
02133     _guiLanguageUseGameLanguageCheckbox = new CheckboxWidget(boss, prefix + "GuiLanguageUseGameLanguage",
02134             _("Switch the GUI language to the game language"),
02135             _("When starting a game, change the GUI language to the game language."
02136             "That way, if a game uses the ResidualVM save and load dialogs, they are "
02137             "in the same language as the game.")
02138     );
02139 
02140     if (ConfMan.hasKey("gui_use_game_language")) {
02141         _guiLanguageUseGameLanguageCheckbox->setState(ConfMan.getBool("gui_use_game_language", _domain));
02142     }
02143 
02144 #endif // USE_TRANSLATION
02145 
02146     if (g_system->hasFeature(OSystem::kFeatureSystemBrowserDialog)) {
02147         _useSystemDialogsCheckbox = new CheckboxWidget(boss, prefix + "UseSystemDialogs",
02148             _("Use native system file browser"),
02149             _("Use the native system file browser instead of the ResidualVM one to select a file or directory.")
02150         );
02151 
02152         _useSystemDialogsCheckbox->setState(ConfMan.getBool("gui_browser_native", _domain));
02153     }
02154 
02155 #ifdef USE_UPDATES
02156     _updatesPopUpDesc = new StaticTextWidget(boss, prefix + "UpdatesPopupDesc", _("Update check:"), _("How often to check ResidualVM updates"));
02157     _updatesPopUp = new PopUpWidget(boss, prefix + "UpdatesPopup");
02158 
02159     const int *vals = Common::UpdateManager::getUpdateIntervals();
02160 
02161     while (*vals != -1) {
02162         _updatesPopUp->appendEntry(Common::UpdateManager::updateIntervalToString(*vals), *vals);
02163         vals++;
02164     }
02165 
02166     _updatesPopUp->setSelectedTag(Common::UpdateManager::normalizeInterval(ConfMan.getInt("updates_check")));
02167 
02168     new ButtonWidget(boss, prefix + "UpdatesCheckManuallyButton", _("Check now"), nullptr, kUpdatesCheckCmd);
02169 #endif
02170 }
02171 
02172 #ifdef USE_CLOUD
02173 #ifdef USE_LIBCURL
02174 void GlobalOptionsDialog::addCloudControls(GuiObject *boss, const Common::String &prefix, bool lowres) {
02175     _storagePopUpDesc = new StaticTextWidget(boss, prefix + "StoragePopupDesc", _("Active storage:"), _("Active cloud storage"));
02176     _storagePopUp = new PopUpWidget(boss, prefix + "StoragePopup");
02177     Common::StringArray list = CloudMan.listStorages();
02178     for (uint32 i = 0; i < list.size(); ++i) {
02179         _storagePopUp->appendEntry(_(list[i]), i);
02180     }
02181     _storagePopUp->setSelected(_selectedStorageIndex);
02182 
02183     if (lowres)
02184         _storageDisabledHint = new StaticTextWidget(boss, prefix + "StorageDisabledHint", _c("4. Storage is not yet enabled. Verify that username is correct and enable it:", "lowres"));
02185     else
02186         _storageDisabledHint = new StaticTextWidget(boss, prefix + "StorageDisabledHint", _("4. Storage is not yet enabled. Verify that username is correct and enable it:"));
02187     _storageEnableButton = new ButtonWidget(boss, prefix + "StorageEnableButton", _("Enable storage"), _("Confirm you want to use this account for this storage"), kEnableStorageCmd);
02188 
02189     _storageUsernameDesc = new StaticTextWidget(boss, prefix + "StorageUsernameDesc", _("Username:"), _("Username used by this storage"));
02190     _storageUsername = new StaticTextWidget(boss, prefix + "StorageUsernameLabel", _("<none>"), "", ThemeEngine::kFontStyleNormal);
02191 
02192     _storageUsedSpaceDesc = new StaticTextWidget(boss, prefix + "StorageUsedSpaceDesc", _("Used space:"), _("Space used by ResidualVM's saved games on this storage"));
02193     _storageUsedSpace = new StaticTextWidget(boss, prefix + "StorageUsedSpaceLabel", "0 bytes", "", ThemeEngine::kFontStyleNormal);
02194 
02195     _storageLastSyncDesc = new StaticTextWidget(boss, prefix + "StorageLastSyncDesc", _("Last sync:"), _("When was the last time saved games were synced with this storage"));
02196     _storageLastSync = new StaticTextWidget(boss, prefix + "StorageLastSyncLabel", _("<never>"), "", ThemeEngine::kFontStyleNormal);
02197     if (lowres)
02198         _storageSyncHint = new StaticTextWidget(boss, prefix + "StorageSyncHint", _c("Saved games sync automatically on launch, after saving and on loading.", "lowres"), "", ThemeEngine::kFontStyleNormal);
02199     else
02200         _storageSyncHint = new StaticTextWidget(boss, prefix + "StorageSyncHint", _("Saved games sync automatically on launch, after saving and on loading."), "", ThemeEngine::kFontStyleNormal);
02201     _storageSyncSavesButton = new ButtonWidget(boss, prefix + "SyncSavesButton", _("Sync now"), _("Start saved games sync"), kSyncSavesStorageCmd);
02202 
02203     if (lowres)
02204         _storageDownloadHint = new StaticTextWidget(boss, prefix + "StorageDownloadHint", _c("You can download game files from your cloud ResidualVM folder:", "lowres"));
02205     else
02206         _storageDownloadHint = new StaticTextWidget(boss, prefix + "StorageDownloadHint", _("You can download game files from your cloud ResidualVM folder:"));
02207     _storageDownloadButton = new ButtonWidget(boss, prefix + "DownloadButton", _("Download game files"), _("Open downloads manager dialog"), kDownloadStorageCmd);
02208 
02209     if (lowres)
02210         _storageDisconnectHint = new StaticTextWidget(boss, prefix + "StorageDisconnectHint", _c("To change account for this storage, disconnect and connect again:", "lowres"));
02211     else
02212         _storageDisconnectHint = new StaticTextWidget(boss, prefix + "StorageDisconnectHint", _("To change account for this storage, disconnect and connect again:"));
02213     _storageDisconnectButton = new ButtonWidget(boss, prefix + "DisconnectButton", _("Disconnect"), _("Stop using this storage on this device"), kDisconnectStorageCmd);
02214 
02215     if (lowres)
02216         _storageWizardNotConnectedHint = new StaticTextWidget(boss, prefix + "StorageWizardNotConnectedHint", _c("This storage is not connected yet! To connect,", "lowres"));
02217     else
02218         _storageWizardNotConnectedHint = new StaticTextWidget(boss, prefix + "StorageWizardNotConnectedHint", _("This storage is not connected yet! To connect,"));
02219     _storageWizardOpenLinkHint = new StaticTextWidget(boss, prefix + "StorageWizardOpenLinkHint", _("1. Open this link:"));
02220     _storageWizardLink = new ButtonWidget(boss, prefix + "StorageWizardLink", "https://cloud.residualvm.org/", _("Open URL"), kOpenUrlStorageCmd);
02221     if (lowres)
02222         _storageWizardCodeHint = new StaticTextWidget(boss, prefix + "StorageWizardCodeHint", _c("2. Get the code and enter it here:", "lowres"));
02223     else
02224         _storageWizardCodeHint = new StaticTextWidget(boss, prefix + "StorageWizardCodeHint", _("2. Get the code and enter it here:"));
02225     _storageWizardCodeBox = new EditTextWidget(boss, prefix + "StorageWizardCodeBox", "", nullptr, 0, 0, ThemeEngine::kFontStyleConsole);
02226     _storageWizardPasteButton = new ButtonWidget(boss, prefix + "StorageWizardPasteButton", _("Paste"), _("Paste code from clipboard"), kPasteCodeStorageCmd);
02227     _storageWizardConnectButton = new ButtonWidget(boss, prefix + "StorageWizardConnectButton", _("3. Connect"), _("Connect your cloud storage account"), kConnectStorageCmd);
02228     _storageWizardConnectionStatusHint = new StaticTextWidget(boss, prefix + "StorageWizardConnectionStatusHint", "...");
02229 
02230     setupCloudTab();
02231 }
02232 #endif // USE_LIBCURL
02233 
02234 #ifdef USE_SDL_NET
02235 void GlobalOptionsDialog::addNetworkControls(GuiObject *boss, const Common::String &prefix, bool lowres) {
02236     _runServerButton = new ButtonWidget(boss, prefix + "RunServerButton", _("Run server"), _("Run local webserver"), kRunServerCmd);
02237     _serverInfoLabel = new StaticTextWidget(boss, prefix + "ServerInfoLabel", _("Not running"));
02238 
02239     // Root path
02240     if (lowres)
02241         _rootPathButton = new ButtonWidget(boss, prefix + "RootPathButton", _c("/root/ Path:", "lowres"), _("Select which directory will be shown as /root/ in the Files Manager"), kChooseRootDirCmd);
02242     else
02243         _rootPathButton = new ButtonWidget(boss, prefix + "RootPathButton", _("/root/ Path:"), _("Select which directory will be shown as /root/ in the Files Manager"), kChooseRootDirCmd);
02244     _rootPath = new StaticTextWidget(boss, prefix + "RootPath", "/foo/bar", _("Select which directory will be shown as /root/ in the Files Manager"));
02245     _rootPathClearButton = addClearButton(boss, prefix + "RootPathClearButton", kRootPathClearCmd);
02246 
02247     uint32 port = Networking::LocalWebserver::getPort();
02248 
02249     _serverPortDesc = new StaticTextWidget(boss, prefix + "ServerPortDesc", _("Server's port:"), _("Port for server to use"));
02250     _serverPort = new EditTextWidget(boss, prefix + "ServerPortEditText", Common::String::format("%u", port), nullptr);
02251     _serverPortClearButton = addClearButton(boss, prefix + "ServerPortClearButton", kServerPortClearCmd);
02252 
02253     if (lowres) {
02254         _featureDescriptionLine1 = new StaticTextWidget(boss, prefix + "FeatureDescriptionLine1", _c("Run server to manage files with browser (in the same network).", "lowres"), "", ThemeEngine::kFontStyleNormal);
02255         _featureDescriptionLine2 = new StaticTextWidget(boss, prefix + "FeatureDescriptionLine2", _c("Closing options dialog will stop the server.", "lowres"), "", ThemeEngine::kFontStyleNormal);
02256     } else {
02257         _featureDescriptionLine1 = new StaticTextWidget(boss, prefix + "FeatureDescriptionLine1", _("Run server to manage files with browser (in the same network)."), "", ThemeEngine::kFontStyleNormal);
02258         _featureDescriptionLine2 = new StaticTextWidget(boss, prefix + "FeatureDescriptionLine2", _("Closing options dialog will stop the server."), "", ThemeEngine::kFontStyleNormal);
02259     }
02260 
02261     reflowNetworkTabLayout();
02262 
02263 }
02264 #endif // USE_SDL_NET
02265 #endif // USE_CLOUD
02266 
02267 #ifdef USE_TTS
02268 void GlobalOptionsDialog::addAccessibilityControls(GuiObject *boss, const Common::String &prefix) {
02269     _ttsCheckbox = new CheckboxWidget(boss, prefix + "TTSCheckbox",
02270             _("Use Text to speech"), _("Will read text in gui on mouse over."));
02271     if (ConfMan.hasKey("tts_enabled"))
02272         _ttsCheckbox->setState(ConfMan.getBool("tts_enabled", _domain));
02273     else
02274         _ttsCheckbox->setState(false);
02275 
02276     _ttsVoiceSelectionPopUp = new PopUpWidget(boss, prefix + "TTSVoiceSelection");
02277     Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
02278     Common::Array<Common::TTSVoice> voices;
02279     if (ttsMan != nullptr)
02280         voices = ttsMan->getVoicesArray();
02281 
02282     for(unsigned i = 0; i < voices.size(); i++) {
02283         _ttsVoiceSelectionPopUp->appendEntry(voices[i].getDescription(), i);
02284     }
02285     if (voices.empty())
02286         _ttsVoiceSelectionPopUp->appendEntry(_("None"), 0);
02287 
02288     if (ConfMan.hasKey("tts_voice") && (unsigned) ConfMan.getInt("tts_voice", _domain) < voices.size())
02289         _ttsVoiceSelectionPopUp->setSelectedTag(ConfMan.getInt("tts_voice", _domain)) ;
02290     else
02291         _ttsVoiceSelectionPopUp->setSelectedTag(0);
02292 }
02293 #endif
02294 
02295 void GlobalOptionsDialog::apply() {
02296     OptionsDialog::apply();
02297 
02298     bool isRebuildNeeded = false;
02299 
02300     Common::String savePath(_savePath->getLabel());
02301     if (!savePath.empty() && (savePath != _("Default")))
02302         ConfMan.set("savepath", savePath, _domain);
02303     else
02304         ConfMan.removeKey("savepath", _domain);
02305 
02306     Common::String themePath(_themePath->getLabel());
02307     if (!themePath.empty() && (themePath != _c("None", "path")))
02308         ConfMan.set("themepath", themePath, _domain);
02309     else
02310         ConfMan.removeKey("themepath", _domain);
02311 
02312     Common::String extraPath(_extraPath->getLabel());
02313     if (!extraPath.empty() && (extraPath != _c("None", "path")))
02314         ConfMan.set("extrapath", extraPath, _domain);
02315     else
02316         ConfMan.removeKey("extrapath", _domain);
02317 
02318 #ifdef DYNAMIC_MODULES
02319     Common::String pluginsPath(_pluginsPath->getLabel());
02320     if (!pluginsPath.empty() && (pluginsPath != _c("None", "path")))
02321         ConfMan.set("pluginspath", pluginsPath, _domain);
02322     else
02323         ConfMan.removeKey("pluginspath", _domain);
02324 #endif
02325 
02326 #ifdef USE_CLOUD
02327 #ifdef USE_SDL_NET
02328     Common::String rootPath(_rootPath->getLabel());
02329     if (!rootPath.empty() && (rootPath != _c("None", "path")))
02330         ConfMan.set("rootpath", rootPath, "cloud");
02331     else
02332         ConfMan.removeKey("rootpath", "cloud");
02333 #endif
02334 #endif
02335 
02336     ConfMan.setInt("autosave_period", _autosavePeriodPopUp->getSelectedTag(), _domain);
02337 
02338 #ifdef USE_UPDATES
02339     ConfMan.setInt("updates_check", _updatesPopUp->getSelectedTag());
02340 
02341     if (g_system->getUpdateManager()) {
02342         if (_updatesPopUp->getSelectedTag() == Common::UpdateManager::kUpdateIntervalNotSupported) {
02343             g_system->getUpdateManager()->setAutomaticallyChecksForUpdates(Common::UpdateManager::kUpdateStateDisabled);
02344         } else {
02345             g_system->getUpdateManager()->setAutomaticallyChecksForUpdates(Common::UpdateManager::kUpdateStateEnabled);
02346             g_system->getUpdateManager()->setUpdateCheckInterval(_updatesPopUp->getSelectedTag());
02347         }
02348     }
02349 #endif
02350 
02351 #ifdef USE_CLOUD
02352 #ifdef USE_LIBCURL
02353     if (CloudMan.getStorageIndex() != _selectedStorageIndex) {
02354         if (!CloudMan.switchStorage(_selectedStorageIndex)) {
02355             bool anotherStorageIsWorking = CloudMan.isWorking();
02356             Common::String message = _("Failed to change cloud storage!");
02357             if (anotherStorageIsWorking) {
02358                 message += "\n";
02359                 message += _("Another cloud storage is already active.");
02360             }
02361             MessageDialog dialog(message);
02362             dialog.runModal();
02363         }
02364     }
02365 #endif // USE_LIBCURL
02366 
02367 #ifdef USE_SDL_NET
02368 #ifdef NETWORKING_LOCALWEBSERVER_ENABLE_PORT_OVERRIDE
02369     // save server's port
02370     uint32 port = Networking::LocalWebserver::getPort();
02371     if (_serverPort) {
02372         uint64 contents = _serverPort->getEditString().asUint64();
02373         if (contents != 0)
02374             port = contents;
02375     }
02376     ConfMan.setInt("local_server_port", port);
02377 #endif // NETWORKING_LOCALWEBSERVER_ENABLE_PORT_OVERRIDE
02378 #endif // USE_SDL_NET
02379 #endif // USE_CLOUD
02380 
02381     Common::String oldThemeId = g_gui.theme()->getThemeId();
02382     Common::String oldThemeName = g_gui.theme()->getThemeName();
02383     if (!_newTheme.empty()) {
02384         ConfMan.set("gui_theme", _newTheme);
02385     }
02386 
02387 #ifdef USE_TRANSLATION
02388     int selectedLang = _guiLanguagePopUp->getSelectedTag();
02389     Common::String oldLang = ConfMan.get("gui_language");
02390     Common::String newLang = TransMan.getLangById(selectedLang);
02391     Common::String newCharset;
02392     if (newLang != oldLang) {
02393         TransMan.setLanguage(newLang);
02394         ConfMan.set("gui_language", newLang);
02395         newCharset = TransMan.getCurrentCharset();
02396         isRebuildNeeded = true;
02397     }
02398 
02399     bool guiUseGameLanguage = _guiLanguageUseGameLanguageCheckbox->getState();
02400     ConfMan.setBool("gui_use_game_language", guiUseGameLanguage, _domain);
02401 #endif
02402 
02403     if (_useSystemDialogsCheckbox) {
02404         ConfMan.setBool("gui_browser_native", _useSystemDialogsCheckbox->getState(), _domain);
02405     }
02406 
02407     GUI::ThemeEngine::GraphicsMode gfxMode = (GUI::ThemeEngine::GraphicsMode)_rendererPopUp->getSelectedTag();
02408     Common::String oldGfxConfig = ConfMan.get("gui_renderer");
02409     Common::String newGfxConfig = GUI::ThemeEngine::findModeConfigName(gfxMode);
02410     if (newGfxConfig != oldGfxConfig) {
02411         ConfMan.set("gui_renderer", newGfxConfig, _domain);
02412     }
02413 
02414     if (_newTheme.empty())
02415         _newTheme = oldThemeId;
02416 
02417     if (!g_gui.loadNewTheme(_newTheme, gfxMode, true)) {
02418         Common::String errorMessage;
02419 
02420         _curTheme->setLabel(oldThemeName);
02421         _newTheme = oldThemeId;
02422         ConfMan.set("gui_theme", _newTheme);
02423         gfxMode = GUI::ThemeEngine::findMode(oldGfxConfig);
02424         _rendererPopUp->setSelectedTag(gfxMode);
02425         newGfxConfig = oldGfxConfig;
02426         ConfMan.set("gui_renderer", newGfxConfig, _domain);
02427 #ifdef USE_TRANSLATION
02428         bool isCharsetEqual = (newCharset == TransMan.getCurrentCharset());
02429         TransMan.setLanguage(oldLang);
02430         _guiLanguagePopUp->setSelectedTag(selectedLang);
02431         ConfMan.set("gui_language", oldLang);
02432 
02433         if (!isCharsetEqual)
02434             errorMessage = _("Theme does not support selected language!");
02435         else
02436 #endif
02437             errorMessage = _("Theme cannot be loaded!");
02438 
02439         g_gui.loadNewTheme(_newTheme, gfxMode, true);
02440         errorMessage += _("\nMisc settings will be restored.");
02441         MessageDialog error(errorMessage);
02442         error.runModal();
02443     }
02444 #ifdef USE_TTS
02445     Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
02446     if (ttsMan) {
02447         if (newLang != oldLang) {
02448             if (newLang == "C")
02449                 ttsMan->setLanguage("en");
02450             else {
02451                 ttsMan->setLanguage(newLang);
02452             }
02453             _ttsVoiceSelectionPopUp->setSelectedTag(0);
02454         }
02455         int volume = (ConfMan.getInt("speech_volume", "residualvm") * 100) / 256;
02456         if (ConfMan.hasKey("mute", "residualvm") && ConfMan.getBool("mute", "residualvm"))
02457             volume = 0;
02458         ttsMan->setVolume(volume);
02459         ConfMan.setBool("tts_enabled", _ttsCheckbox->getState(), _domain);
02460         int selectedVoice = _ttsVoiceSelectionPopUp->getSelectedTag();
02461         ConfMan.setInt("tts_voice", selectedVoice, _domain);
02462         ttsMan->setVoice(selectedVoice);
02463     }
02464 #endif
02465 
02466     if (isRebuildNeeded) {
02467         if (_launcher != nullptr)
02468             _launcher->rebuild();
02469         rebuild();
02470     }
02471 
02472     _newTheme.clear();
02473 
02474     // Save config file
02475     ConfMan.flushToDisk();
02476 }
02477 
02478 void GlobalOptionsDialog::close() {
02479 #if defined(USE_CLOUD) && defined(USE_SDL_NET)
02480     if (LocalServer.isRunning()) {
02481         LocalServer.stop();
02482     }
02483 #endif
02484     OptionsDialog::close();
02485 }
02486 
02487 void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
02488     switch (cmd) {
02489     case kChooseSaveDirCmd: {
02490         BrowserDialog browser(_("Select directory for saved games"), true);
02491         if (browser.runModal() > 0) {
02492             // User made his choice...
02493             Common::FSNode dir(browser.getResult());
02494             if (dir.isWritable()) {
02495                 _savePath->setLabel(dir.getPath());
02496             } else {
02497                 MessageDialog error(_("The chosen directory cannot be written to. Please select another one."));
02498                 error.runModal();
02499                 return;
02500             }
02501             g_gui.scheduleTopDialogRedraw();
02502         }
02503         break;
02504     }
02505     case kChooseThemeDirCmd: {
02506         BrowserDialog browser(_("Select directory for GUI themes"), true);
02507         if (browser.runModal() > 0) {
02508             // User made his choice...
02509             Common::FSNode dir(browser.getResult());
02510             _themePath->setLabel(dir.getPath());
02511             g_gui.scheduleTopDialogRedraw();
02512         }
02513         break;
02514     }
02515     case kChooseExtraDirCmd: {
02516         BrowserDialog browser(_("Select directory for extra files"), true);
02517         if (browser.runModal() > 0) {
02518             // User made his choice...
02519             Common::FSNode dir(browser.getResult());
02520             _extraPath->setLabel(dir.getPath());
02521             g_gui.scheduleTopDialogRedraw();
02522         }
02523         break;
02524     }
02525 #ifdef DYNAMIC_MODULES
02526     case kChoosePluginsDirCmd: {
02527         BrowserDialog browser(_("Select directory for plugins"), true);
02528         if (browser.runModal() > 0) {
02529             // User made his choice...
02530             Common::FSNode dir(browser.getResult());
02531             _pluginsPath->setLabel(dir.getPath());
02532             g_gui.scheduleTopDialogRedraw();
02533         }
02534         break;
02535     }
02536 #endif
02537 #ifdef USE_CLOUD
02538 #ifdef USE_SDL_NET
02539     case kChooseRootDirCmd: {
02540         BrowserDialog browser(_("Select directory for Files Manager /root/"), true);
02541         if (browser.runModal() > 0) {
02542             // User made his choice...
02543             Common::FSNode dir(browser.getResult());
02544             Common::String path = dir.getPath();
02545             if (path.empty())
02546                 path = "/"; // absolute root
02547             _rootPath->setLabel(path);
02548             g_gui.scheduleTopDialogRedraw();
02549         }
02550         break;
02551     }
02552 #endif
02553 #endif
02554     case kThemePathClearCmd:
02555         _themePath->setLabel(_c("None", "path"));
02556         break;
02557     case kExtraPathClearCmd:
02558         _extraPath->setLabel(_c("None", "path"));
02559         break;
02560     case kSavePathClearCmd:
02561         _savePath->setLabel(_("Default"));
02562         break;
02563 #ifdef DYNAMIC_MODULES
02564     case kPluginsPathClearCmd:
02565         _pluginsPath->setLabel(_c("None", "path"));
02566         break;
02567 #endif
02568 #ifdef USE_CLOUD
02569 #ifdef USE_SDL_NET
02570     case kRootPathClearCmd:
02571         _rootPath->setLabel(_c("None", "path"));
02572         break;
02573 #endif
02574 #endif
02575     case kChooseSoundFontCmd: {
02576         BrowserDialog browser(_("Select SoundFont"), false);
02577         if (browser.runModal() > 0) {
02578             // User made his choice...
02579             Common::FSNode file(browser.getResult());
02580             _soundFont->setLabel(file.getPath());
02581 
02582             if (!file.getPath().empty() && (file.getPath() != _c("None", "path")))
02583                 _soundFontClearButton->setEnabled(true);
02584             else
02585                 _soundFontClearButton->setEnabled(false);
02586 
02587             g_gui.scheduleTopDialogRedraw();
02588         }
02589         break;
02590     }
02591     case kChooseThemeCmd:
02592     {
02593         ThemeBrowser browser;
02594         if (browser.runModal() > 0) {
02595             // User made his choice...
02596             _newTheme = browser.getSelected();
02597             _curTheme->setLabel(browser.getSelectedName());
02598         }
02599         break;
02600     }
02601 #ifdef USE_CLOUD
02602 #ifdef USE_LIBCURL
02603     case kCloudTabContainerReflowCmd: {
02604         setupCloudTab();
02605         break;
02606     }
02607     case kPopUpItemSelectedCmd: {
02608         if (_storageWizardCodeBox)
02609             _storageWizardCodeBox->setEditString("");
02610         // update container's scrollbar
02611         reflowLayout();
02612         break;
02613     }
02614     case kEnableStorageCmd: {
02615         CloudMan.enableStorage();
02616         _redrawCloudTab = true;
02617 
02618         // also, automatically start saves sync when user enables the storage
02619     }
02620     // fall through
02621     case kSyncSavesStorageCmd: {
02622         CloudMan.syncSaves(
02623             new Common::Callback<GlobalOptionsDialog, Cloud::Storage::BoolResponse>(this, &GlobalOptionsDialog::storageSavesSyncedCallback)
02624         );
02625         break;
02626     }
02627     case kDownloadStorageCmd: {
02628         DownloadDialog dialog(_selectedStorageIndex, _launcher);
02629         dialog.runModal();
02630         break;
02631     }
02632     case kOpenUrlStorageCmd: {
02633         Common::String url = "https://cloud.residualvm.org/";
02634         switch (_selectedStorageIndex) {
02635         case Cloud::kStorageDropboxId:
02636             url += "dropbox";
02637             break;
02638         case Cloud::kStorageOneDriveId:
02639             url += "onedrive";
02640             break;
02641         case Cloud::kStorageGoogleDriveId:
02642             url += "gdrive";
02643             break;
02644         case Cloud::kStorageBoxId:
02645             url += "box";
02646             break;
02647         default:
02648             break;
02649         }
02650 
02651         if (!g_system->openUrl(url)) {
02652             MessageDialog alert(_("Failed to open URL!\nPlease navigate to this page manually."));
02653             alert.runModal();
02654         }
02655         break;
02656     }
02657     case kPasteCodeStorageCmd: {
02658         if (g_system->hasTextInClipboard()) {
02659             Common::String message = g_system->getTextFromClipboard();
02660             if (!message.empty()) {
02661                 _storageWizardCodeBox->setEditString(message);
02662                 _redrawCloudTab = true;
02663             }
02664         }
02665         break;
02666     }
02667     case kConnectStorageCmd: {
02668         Common::String code = "";
02669         if (_storageWizardCodeBox)
02670             code = _storageWizardCodeBox->getEditString();
02671         if (code.size() == 0)
02672             return;
02673 
02674         if (CloudMan.isWorking()) {
02675             bool cancel = true;
02676 
02677             MessageDialog alert(_("Another Storage is working now. Do you want to interrupt it?"), _("Yes"), _("No"));
02678             if (alert.runModal() == GUI::kMessageOK) {
02679                 if (CloudMan.isDownloading())
02680                     CloudMan.cancelDownload();
02681                 if (CloudMan.isSyncing())
02682                     CloudMan.cancelSync();
02683 
02684                 // I believe it still would return `true` here, but just in case
02685                 if (CloudMan.isWorking()) {
02686                     MessageDialog alert2(_("Wait until current Storage finishes up and try again."));
02687                     alert2.runModal();
02688                 } else {
02689                     cancel = false;
02690                 }
02691             }
02692 
02693             if (cancel) {
02694                 return;
02695             }
02696         }
02697 
02698         if (_storageWizardConnectionStatusHint)
02699             _storageWizardConnectionStatusHint->setLabel(_("Connecting..."));
02700         CloudMan.connectStorage(
02701             _selectedStorageIndex, code,
02702             new Common::Callback<GlobalOptionsDialog, Networking::ErrorResponse>(this, &GlobalOptionsDialog::storageConnectionCallback)
02703         );
02704         _connectingStorage = true;
02705         _redrawCloudTab = true;
02706         break;
02707     }
02708     case kDisconnectStorageCmd: {
02709         if (_storageWizardCodeBox)
02710             _storageWizardCodeBox->setEditString("");
02711 
02712         if (_selectedStorageIndex == CloudMan.getStorageIndex() && CloudMan.isWorking()) {
02713             bool cancel = true;
02714 
02715             MessageDialog alert(_("This Storage is working now. Do you want to interrupt it?"), _("Yes"), _("No"));
02716             if (alert.runModal() == GUI::kMessageOK) {
02717                 if (CloudMan.isDownloading())
02718                     CloudMan.cancelDownload();
02719                 if (CloudMan.isSyncing())
02720                     CloudMan.cancelSync();
02721 
02722                 // I believe it still would return `true` here, but just in case
02723                 if (CloudMan.isWorking()) {
02724                     MessageDialog alert2(_("Wait until current Storage finishes up and try again."));
02725                     alert2.runModal();
02726                 } else {
02727                     cancel = false;
02728                 }
02729             }
02730 
02731             if (cancel) {
02732                 return;
02733             }
02734         }
02735 
02736         CloudMan.disconnectStorage(_selectedStorageIndex);
02737         _redrawCloudTab = true;
02738         sendCommand(kSetPositionCmd, 0);
02739         break;
02740     }
02741 #endif // USE_LIBCURL
02742 #ifdef USE_SDL_NET
02743     case kRunServerCmd: {
02744 #ifdef NETWORKING_LOCALWEBSERVER_ENABLE_PORT_OVERRIDE
02745         // save server's port
02746         uint32 port = Networking::LocalWebserver::getPort();
02747         if (_serverPort) {
02748             uint64 contents = _serverPort->getEditString().asUint64();
02749             if (contents != 0)
02750                 port = contents;
02751         }
02752         ConfMan.setInt("local_server_port", port);
02753         ConfMan.flushToDisk();
02754 #endif // NETWORKING_LOCALWEBSERVER_ENABLE_PORT_OVERRIDE
02755 
02756         if (LocalServer.isRunning())
02757             LocalServer.stopOnIdle();
02758         else
02759             LocalServer.start();
02760 
02761         break;
02762     }
02763     case kServerPortClearCmd: {
02764         if (_serverPort) {
02765             _serverPort->setEditString(Common::String::format("%u", Networking::LocalWebserver::DEFAULT_SERVER_PORT));
02766         }
02767         g_gui.scheduleTopDialogRedraw();
02768         break;
02769     }
02770 #endif // USE_SDL_NET
02771 #endif // USE_CLOUD
02772 #ifdef GUI_ENABLE_KEYSDIALOG
02773     case kChooseKeyMappingCmd:
02774         _keysDialog->runModal();
02775         break;
02776 #endif
02777 #ifdef USE_FLUIDSYNTH
02778     case kFluidSynthSettingsCmd:
02779         _fluidSynthSettingsDialog->runModal();
02780         break;
02781 #endif
02782 #ifdef USE_UPDATES
02783     case kUpdatesCheckCmd:
02784         if (g_system->getUpdateManager())
02785             g_system->getUpdateManager()->checkForUpdates();
02786         break;
02787 #endif
02788     default:
02789         OptionsDialog::handleCommand(sender, cmd, data);
02790     }
02791 }
02792 
02793 void GlobalOptionsDialog::handleTickle() {
02794     OptionsDialog::handleTickle();
02795 #ifdef USE_CLOUD
02796 #ifdef USE_LIBCURL
02797     if (_redrawCloudTab) {
02798         reflowLayout(); // recalculates scrollbar as well
02799         _redrawCloudTab = false;
02800     }
02801 #endif // USE_LIBCURL
02802 #ifdef USE_SDL_NET
02803     if (LocalServer.isRunning() != _serverWasRunning) {
02804         _serverWasRunning = !_serverWasRunning;
02805         reflowNetworkTabLayout();
02806     }
02807 #endif // USE_SDL_NET
02808 #endif // USE_CLOUD
02809 }
02810 
02811 void GlobalOptionsDialog::reflowLayout() {
02812     int firstVisible = _tabWidget->getFirstVisible();
02813     int activeTab = _tabWidget->getActiveTab();
02814 
02815     if (_midiTabId != -1) {
02816         _tabWidget->setActiveTab(_midiTabId);
02817 
02818         _tabWidget->removeWidget(_soundFontClearButton);
02819         _soundFontClearButton->setNext(nullptr);
02820         delete _soundFontClearButton;
02821         _soundFontClearButton = addClearButton(_tabWidget, "GlobalOptions_MIDI.mcFontClearButton", kClearSoundFontCmd);
02822     }
02823 
02824     if (_pathsTabId != -1) {
02825         _tabWidget->setActiveTab(_pathsTabId);
02826 
02827         _tabWidget->removeWidget(_savePathClearButton);
02828         _savePathClearButton->setNext(nullptr);
02829         delete _savePathClearButton;
02830         _savePathClearButton = addClearButton(_tabWidget, "GlobalOptions_Paths.SavePathClearButton", kSavePathClearCmd);
02831 
02832         _tabWidget->removeWidget(_themePathClearButton);
02833         _themePathClearButton->setNext(nullptr);
02834         delete _themePathClearButton;
02835         _themePathClearButton = addClearButton(_tabWidget, "GlobalOptions_Paths.ThemePathClearButton", kThemePathClearCmd);
02836 
02837         _tabWidget->removeWidget(_extraPathClearButton);
02838         _extraPathClearButton->setNext(nullptr);
02839         delete _extraPathClearButton;
02840         _extraPathClearButton = addClearButton(_tabWidget, "GlobalOptions_Paths.ExtraPathClearButton", kExtraPathClearCmd);
02841     }
02842 
02843     _tabWidget->setActiveTab(activeTab);
02844     _tabWidget->setFirstVisible(firstVisible);
02845 
02846     OptionsDialog::reflowLayout();
02847 #ifdef USE_CLOUD
02848 #ifdef USE_LIBCURL
02849     setupCloudTab();
02850 #endif // USE_LIBCURL
02851 #ifdef USE_SDL_NET
02852     reflowNetworkTabLayout();
02853 #endif // USE_SDL_NET
02854 #endif // USE_CLOUD
02855 }
02856 
02857 #ifdef USE_CLOUD
02858 #ifdef USE_LIBCURL
02859 void GlobalOptionsDialog::setupCloudTab() {
02860     _selectedStorageIndex = (_storagePopUp ? _storagePopUp->getSelectedTag() : (uint32)Cloud::kStorageNoneId);
02861 
02862     if (_storagePopUpDesc) _storagePopUpDesc->setVisible(true);
02863     if (_storagePopUp) _storagePopUp->setVisible(true);
02864 
02865     Common::String username = CloudMan.getStorageUsername(_selectedStorageIndex);
02866     bool storageConnected = (username != "");
02867     bool shown = (_selectedStorageIndex != Cloud::kStorageNoneId);
02868     bool shownConnectedInfo = (shown && storageConnected);
02869     bool showingCurrentStorage = (shownConnectedInfo && _selectedStorageIndex == CloudMan.getStorageIndex());
02870     bool enabled = (shownConnectedInfo && CloudMan.isStorageEnabled());
02871 
02872     // there goes layout for connected Storage
02873 
02874     if (_storageDisabledHint) _storageDisabledHint->setVisible(showingCurrentStorage && !enabled);
02875     if (_storageEnableButton) _storageEnableButton->setVisible(showingCurrentStorage && !enabled);
02876 
02877     // calculate shift
02878     int16 x, y;
02879     int16 w, h;
02880     int16 shiftUp = 0;
02881     if (!showingCurrentStorage || enabled) {
02882         // "storage is disabled" hint is not shown, shift everything up
02883         if (!g_gui.xmlEval()->getWidgetData("GlobalOptions_Cloud_Container.StorageDisabledHint", x, y, w, h))
02884             warning("GlobalOptions_Cloud_Container.StorageUsernameDesc's position is undefined");
02885         shiftUp = y;
02886         if (!g_gui.xmlEval()->getWidgetData("GlobalOptions_Cloud_Container.StorageUsernameDesc", x, y, w, h))
02887             warning("GlobalOptions_Cloud_Container.StorageWizardNotConnectedHint's position is undefined");
02888         shiftUp = y - shiftUp;
02889     }
02890 
02891     if (_storageUsernameDesc) _storageUsernameDesc->setVisible(shownConnectedInfo);
02892     if (_storageUsername) {
02893         _storageUsername->setLabel(username);
02894         _storageUsername->setVisible(shownConnectedInfo);
02895     }
02896     if (_storageUsedSpaceDesc) _storageUsedSpaceDesc->setVisible(shownConnectedInfo);
02897     if (_storageUsedSpace) {
02898         uint64 usedSpace = CloudMan.getStorageUsedSpace(_selectedStorageIndex);
02899         Common::String usedSpaceNumber, usedSpaceUnits;
02900         usedSpaceNumber = Common::getHumanReadableBytes(usedSpace, usedSpaceUnits);
02901         _storageUsedSpace->setLabel(Common::String::format("%s %s", usedSpaceNumber.c_str(), _(usedSpaceUnits.c_str())));
02902         _storageUsedSpace->setVisible(shownConnectedInfo);
02903     }
02904     if (_storageSyncHint) {
02905         _storageSyncHint->setVisible(shownConnectedInfo);
02906         _storageSyncHint->setEnabled(false);
02907     }
02908     if (_storageLastSyncDesc) _storageLastSyncDesc->setVisible(shownConnectedInfo);
02909     if (_storageLastSync) {
02910         Common::String sync = CloudMan.getStorageLastSync(_selectedStorageIndex);
02911         if (sync == "") {
02912             if (_selectedStorageIndex == CloudMan.getStorageIndex() && CloudMan.isSyncing())
02913                 sync = _("<right now>");
02914             else
02915                 sync = _("<never>");
02916         }
02917         _storageLastSync->setLabel(sync);
02918         _storageLastSync->setVisible(shownConnectedInfo);
02919     }
02920     if (_storageSyncSavesButton) {
02921         _storageSyncSavesButton->setVisible(showingCurrentStorage);
02922         _storageSyncSavesButton->setEnabled(enabled);
02923     }
02924 
02925     bool showDownloadButton = (showingCurrentStorage && _selectedStorageIndex != Cloud::kStorageGoogleDriveId); // cannot download via Google Drive
02926     if (_storageDownloadHint) _storageDownloadHint->setVisible(showDownloadButton);
02927     if (_storageDownloadButton) {
02928         _storageDownloadButton->setVisible(showDownloadButton);
02929         _storageDownloadButton->setEnabled(enabled);
02930     }
02931     if (_storageDisconnectHint) _storageDisconnectHint->setVisible(shownConnectedInfo);
02932     if (_storageDisconnectButton) _storageDisconnectButton->setVisible(shownConnectedInfo);
02933 
02934     int16 disconnectWidgetsAdditionalShift = 0;
02935     if (!showDownloadButton) {
02936         if (!g_gui.xmlEval()->getWidgetData("GlobalOptions_Cloud_Container.StorageDownloadHint", x, y, w, h))
02937             warning("GlobalOptions_Cloud_Container.StorageDownloadHint's position is undefined");
02938         disconnectWidgetsAdditionalShift = y;
02939         if (!g_gui.xmlEval()->getWidgetData("GlobalOptions_Cloud_Container.StorageDisconnectHint", x, y, w, h))
02940             warning("GlobalOptions_Cloud_Container.DownloadButton's position is undefined");
02941         disconnectWidgetsAdditionalShift = y - disconnectWidgetsAdditionalShift;
02942     }
02943 
02944     shiftWidget(_storageUsernameDesc, "GlobalOptions_Cloud_Container.StorageUsernameDesc", 0, -shiftUp);
02945     shiftWidget(_storageUsername, "GlobalOptions_Cloud_Container.StorageUsernameLabel", 0, -shiftUp);
02946     shiftWidget(_storageUsedSpaceDesc, "GlobalOptions_Cloud_Container.StorageUsedSpaceDesc", 0, -shiftUp);
02947     shiftWidget(_storageUsedSpace, "GlobalOptions_Cloud_Container.StorageUsedSpaceLabel", 0, -shiftUp);
02948     shiftWidget(_storageSyncHint, "GlobalOptions_Cloud_Container.StorageSyncHint", 0, -shiftUp);
02949     shiftWidget(_storageLastSyncDesc, "GlobalOptions_Cloud_Container.StorageLastSyncDesc", 0, -shiftUp);
02950     shiftWidget(_storageLastSync, "GlobalOptions_Cloud_Container.StorageLastSyncLabel", 0, -shiftUp);
02951     shiftWidget(_storageSyncSavesButton, "GlobalOptions_Cloud_Container.SyncSavesButton", 0, -shiftUp);
02952     shiftWidget(_storageDownloadHint, "GlobalOptions_Cloud_Container.StorageDownloadHint", 0, -shiftUp);
02953     shiftWidget(_storageDownloadButton, "GlobalOptions_Cloud_Container.DownloadButton", 0, -shiftUp);
02954     shiftWidget(_storageDisconnectHint, "GlobalOptions_Cloud_Container.StorageDisconnectHint", 0, -shiftUp - disconnectWidgetsAdditionalShift);
02955     shiftWidget(_storageDisconnectButton, "GlobalOptions_Cloud_Container.DisconnectButton", 0, -shiftUp - disconnectWidgetsAdditionalShift);
02956 
02957     // there goes layout for non-connected Storage (connection wizard)
02958 
02959     shown = (!shownConnectedInfo && shown);
02960     bool wizardEnabled = !_connectingStorage;
02961     if (_storageWizardNotConnectedHint) _storageWizardNotConnectedHint->setVisible(shown);
02962     if (_storageWizardOpenLinkHint) _storageWizardOpenLinkHint->setVisible(shown);
02963     if (_storageWizardLink) {
02964         _storageWizardLink->setVisible(shown);
02965         _storageWizardLink->setEnabled(g_system->hasFeature(OSystem::kFeatureOpenUrl) && wizardEnabled);
02966     }
02967     if (_storageWizardCodeHint) _storageWizardCodeHint->setVisible(shown);
02968     if (_storageWizardCodeBox) {
02969         _storageWizardCodeBox->setVisible(shown);
02970         _storageWizardCodeBox->setEnabled(wizardEnabled);
02971     }
02972     if (_storageWizardPasteButton) {
02973         _storageWizardPasteButton->setVisible(shown && g_system->hasFeature(OSystem::kFeatureClipboardSupport));
02974         _storageWizardPasteButton->setEnabled(wizardEnabled);
02975     }
02976     if (_storageWizardConnectButton) {
02977         _storageWizardConnectButton->setVisible(shown);
02978         _storageWizardConnectButton->setEnabled(wizardEnabled);
02979     }
02980     if (_storageWizardConnectionStatusHint) {
02981         _storageWizardConnectionStatusHint->setVisible(shown && _storageWizardConnectionStatusHint->getLabel() != "...");
02982         _storageWizardConnectionStatusHint->setEnabled(wizardEnabled);
02983     }
02984 
02985     if (!shownConnectedInfo) {
02986         if (!g_gui.xmlEval()->getWidgetData("GlobalOptions_Cloud_Container.StorageDisabledHint", x, y, w, h))
02987             warning("GlobalOptions_Cloud_Container.StorageUsernameDesc's position is undefined");
02988         shiftUp = y;
02989         if (!g_gui.xmlEval()->getWidgetData("GlobalOptions_Cloud_Container.StorageWizardNotConnectedHint", x, y, w, h))
02990             warning("GlobalOptions_Cloud_Container.StorageWizardNotConnectedHint's position is undefined");
02991         shiftUp = y - shiftUp;
02992 
02993         shiftWidget(_storageWizardNotConnectedHint, "GlobalOptions_Cloud_Container.StorageWizardNotConnectedHint", 0, -shiftUp);
02994         shiftWidget(_storageWizardOpenLinkHint, "GlobalOptions_Cloud_Container.StorageWizardOpenLinkHint", 0, -shiftUp);
02995         shiftWidget(_storageWizardLink, "GlobalOptions_Cloud_Container.StorageWizardLink", 0, -shiftUp);
02996         shiftWidget(_storageWizardCodeHint, "GlobalOptions_Cloud_Container.StorageWizardCodeHint", 0, -shiftUp);
02997         shiftWidget(_storageWizardCodeBox, "GlobalOptions_Cloud_Container.StorageWizardCodeBox", 0, -shiftUp);
02998         shiftWidget(_storageWizardPasteButton, "GlobalOptions_Cloud_Container.StorageWizardPasteButton", 0, -shiftUp);
02999         shiftWidget(_storageWizardConnectButton, "GlobalOptions_Cloud_Container.StorageWizardConnectButton", 0, -shiftUp);
03000         shiftWidget(_storageWizardConnectionStatusHint, "GlobalOptions_Cloud_Container.StorageWizardConnectionStatusHint", 0, -shiftUp);
03001     }
03002 }
03003 
03004 void GlobalOptionsDialog::shiftWidget(Widget *widget, const char *widgetName, int32 xOffset, int32 yOffset) {
03005     if (!widget) return;
03006 
03007     int16 x, y;
03008     int16 w, h;
03009     if (!g_gui.xmlEval()->getWidgetData(widgetName, x, y, w, h))
03010         warning("%s's position is undefined", widgetName);
03011 
03012     widget->setPos(x + xOffset, y + yOffset);
03013 }
03014 #endif // USE_LIBCURL
03015 
03016 #ifdef USE_SDL_NET
03017 void GlobalOptionsDialog::reflowNetworkTabLayout() {
03018     bool serverIsRunning = LocalServer.isRunning();
03019 
03020     if (_runServerButton) {
03021         _runServerButton->setVisible(true);
03022         _runServerButton->setLabel(_(serverIsRunning ? "Stop server" : "Run server"));
03023         _runServerButton->setTooltip(_(serverIsRunning ? "Stop local webserver" : "Run local webserver"));
03024     }
03025     if (_serverInfoLabel) {
03026         _serverInfoLabel->setVisible(true);
03027         if (serverIsRunning)
03028             _serverInfoLabel->setLabel(LocalServer.getAddress());
03029         else
03030             _serverInfoLabel->setLabel(_("Not running"));
03031     }
03032     if (_rootPathButton) _rootPathButton->setVisible(true);
03033     if (_rootPath) _rootPath->setVisible(true);
03034     if (_rootPathClearButton) _rootPathClearButton->setVisible(true);
03035 #ifdef NETWORKING_LOCALWEBSERVER_ENABLE_PORT_OVERRIDE
03036     if (_serverPortDesc) {
03037         _serverPortDesc->setVisible(true);
03038         _serverPortDesc->setEnabled(!serverIsRunning);
03039     }
03040     if (_serverPort) {
03041         _serverPort->setVisible(true);
03042         _serverPort->setEnabled(!serverIsRunning);
03043     }
03044     if (_serverPortClearButton) {
03045         _serverPortClearButton->setVisible(true);
03046         _serverPortClearButton->setEnabled(!serverIsRunning);
03047     }
03048 #else // NETWORKING_LOCALWEBSERVER_ENABLE_PORT_OVERRIDE
03049     if (_serverPortDesc)
03050         _serverPortDesc->setVisible(false);
03051     if (_serverPort)
03052         _serverPort->setVisible(false);
03053     if (_serverPortClearButton)
03054         _serverPortClearButton->setVisible(false);
03055 #endif // NETWORKING_LOCALWEBSERVER_ENABLE_PORT_OVERRIDE
03056 
03057     // if port override isn't supported, there will be a gap between these lines and options -- it's OK
03058 
03059     if (_featureDescriptionLine1) {
03060         _featureDescriptionLine1->setVisible(true);
03061         _featureDescriptionLine1->setEnabled(false);
03062     }
03063     if (_featureDescriptionLine2) {
03064         _featureDescriptionLine2->setVisible(true);
03065         _featureDescriptionLine2->setEnabled(false);
03066     }
03067 }
03068 #endif // USE_SDL_NET
03069 
03070 #ifdef USE_LIBCURL
03071 void GlobalOptionsDialog::storageConnectionCallback(Networking::ErrorResponse response) {
03072     Common::String message = "...";
03073     if (!response.failed && !response.interrupted) {
03074         // success
03075         g_system->displayMessageOnOSD(_("Storage connected."));
03076     } else {
03077         message = _("Failed to connect storage.");
03078         if (response.failed) {
03079             message = Common::String(_("Failed to connect storage: ")) + _(response.response.c_str());
03080         }
03081     }
03082 
03083     if (_storageWizardConnectionStatusHint)
03084         _storageWizardConnectionStatusHint->setLabel(message);
03085 
03086     _redrawCloudTab = true;
03087     _connectingStorage = false;
03088 }
03089 
03090 void GlobalOptionsDialog::storageSavesSyncedCallback(Cloud::Storage::BoolResponse response) {
03091     _redrawCloudTab = true;
03092 }
03093 
03094 void GlobalOptionsDialog::storageErrorCallback(Networking::ErrorResponse response) {
03095     debug(9, "GlobalOptionsDialog: error response (%s, %ld):", (response.failed ? "failed" : "interrupted"), response.httpResponseCode);
03096     debug(9, "%s", response.response.c_str());
03097 
03098     if (!response.interrupted)
03099         g_system->displayMessageOnOSD(_("Request failed.\nCheck your Internet connection."));
03100 }
03101 #endif // USE_LIBCURL
03102 #endif // USE_CLOUD
03103 
03104 } // End of namespace GUI


Generated on Sat May 23 2020 05:00:44 for ResidualVM by doxygen 1.7.1
curved edge   curved edge