diff options
Diffstat (limited to 'gui/saveload-dialog.cpp')
-rw-r--r-- | gui/saveload-dialog.cpp | 224 |
1 files changed, 203 insertions, 21 deletions
diff --git a/gui/saveload-dialog.cpp b/gui/saveload-dialog.cpp index a333c5fe57..4bd71d39cf 100644 --- a/gui/saveload-dialog.cpp +++ b/gui/saveload-dialog.cpp @@ -21,6 +21,13 @@ */ #include "gui/saveload-dialog.h" + +#if defined(USE_CLOUD) && defined(USE_LIBCURL) +#include "backends/cloud/cloudmanager.h" +#include "backends/cloud/savessyncrequest.h" +#include "backends/networking/curl/connectionmanager.h" +#endif + #include "common/translation.h" #include "common/config-manager.h" @@ -30,9 +37,68 @@ #include "gui/widgets/edittext.h" #include "graphics/scaler.h" +#include <common/savefile.h> namespace GUI { +#if defined(USE_CLOUD) && defined(USE_LIBCURL) + +enum { + kCancelSyncCmd = 'PDCS', + kBackgroundSyncCmd = 'PDBS' +}; + +SaveLoadCloudSyncProgressDialog::SaveLoadCloudSyncProgressDialog(bool canRunInBackground): Dialog("SaveLoadCloudSyncProgress"), _close(false) { + _label = new StaticTextWidget(this, "SaveLoadCloudSyncProgress.TitleText", "Downloading saves..."); + uint32 progress = (uint32)(100 * CloudMan.getSyncDownloadingProgress()); + _progressBar = new SliderWidget(this, "SaveLoadCloudSyncProgress.ProgressBar"); + _progressBar->setMinValue(0); + _progressBar->setMaxValue(100); + _progressBar->setValue(progress); + _progressBar->setEnabled(false); + _percentLabel = new StaticTextWidget(this, "SaveLoadCloudSyncProgress.PercentText", Common::String::format("%u %%", progress)); + new ButtonWidget(this, "SaveLoadCloudSyncProgress.Cancel", "Cancel", 0, kCancelSyncCmd, Common::ASCII_ESCAPE); // Cancel dialog + ButtonWidget *backgroundButton = new ButtonWidget(this, "SaveLoadCloudSyncProgress.Background", "Run in background", 0, kBackgroundSyncCmd, Common::ASCII_RETURN); // Confirm dialog + backgroundButton->setEnabled(canRunInBackground); + draw(); +} + +SaveLoadCloudSyncProgressDialog::~SaveLoadCloudSyncProgressDialog() { + CloudMan.setSyncTarget(nullptr); //not that dialog, at least +} + +void SaveLoadCloudSyncProgressDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { + switch(cmd) { + case kSavesSyncProgressCmd: + _percentLabel->setLabel(Common::String::format("%u%%", data)); + _progressBar->setValue(data); + _progressBar->draw(); + break; + + case kCancelSyncCmd: + setResult(kCancelSyncCmd); + close(); + break; + + case kSavesSyncEndedCmd: + case kBackgroundSyncCmd: + _close = true; + break; + } + + Dialog::handleCommand(sender, cmd, data); +} + +void SaveLoadCloudSyncProgressDialog::handleTickle() { + if (_close) { + setResult(kBackgroundSyncCmd); + close(); + } + + Dialog::handleTickle(); +} +#endif + #ifndef DISABLE_SAVELOADCHOOSER_GRID SaveLoadChooserType getRequestedSaveLoadDialog(const MetaEngine &metaEngine) { const Common::String &userConfig = ConfMan.get("gui_saveload_chooser", Common::ConfigManager::kApplicationDomain); @@ -45,9 +111,9 @@ SaveLoadChooserType getRequestedSaveLoadDialog(const MetaEngine &metaEngine) { g_gui.checkScreenChange(); if (g_gui.getWidth() >= 640 && g_gui.getHeight() >= 400 - && metaEngine.hasFeature(MetaEngine::kSavesSupportMetaInfo) - && metaEngine.hasFeature(MetaEngine::kSavesSupportThumbnail) - && userConfig.equalsIgnoreCase("grid")) { + && metaEngine.hasFeature(MetaEngine::kSavesSupportMetaInfo) + && metaEngine.hasFeature(MetaEngine::kSavesSupportThumbnail) + && userConfig.equalsIgnoreCase("grid")) { // In case we are 640x400 or higher, this dialog is not in save mode, // the user requested the grid dialog and the engines supports it we // try to set it up. @@ -66,7 +132,8 @@ enum { SaveLoadChooserDialog::SaveLoadChooserDialog(const Common::String &dialogName, const bool saveMode) : Dialog(dialogName), _metaEngine(0), _delSupport(false), _metaInfoSupport(false), - _thumbnailSupport(false), _saveDateSupport(false), _playTimeSupport(false), _saveMode(saveMode) + _thumbnailSupport(false), _saveDateSupport(false), _playTimeSupport(false), _saveMode(saveMode), + _dialogWasShown(false) #ifndef DISABLE_SAVELOADCHOOSER_GRID , _listButton(0), _gridButton(0) #endif // !DISABLE_SAVELOADCHOOSER_GRID @@ -78,7 +145,8 @@ SaveLoadChooserDialog::SaveLoadChooserDialog(const Common::String &dialogName, c SaveLoadChooserDialog::SaveLoadChooserDialog(int x, int y, int w, int h, const bool saveMode) : Dialog(x, y, w, h), _metaEngine(0), _delSupport(false), _metaInfoSupport(false), - _thumbnailSupport(false), _saveDateSupport(false), _playTimeSupport(false), _saveMode(saveMode) + _thumbnailSupport(false), _saveDateSupport(false), _playTimeSupport(false), _saveMode(saveMode), + _dialogWasShown(false) #ifndef DISABLE_SAVELOADCHOOSER_GRID , _listButton(0), _gridButton(0) #endif // !DISABLE_SAVELOADCHOOSER_GRID @@ -88,12 +156,27 @@ SaveLoadChooserDialog::SaveLoadChooserDialog(int x, int y, int w, int h, const b #endif // !DISABLE_SAVELOADCHOOSER_GRID } +SaveLoadChooserDialog::~SaveLoadChooserDialog() { +#if defined(USE_CLOUD) && defined(USE_LIBCURL) + CloudMan.setSyncTarget(nullptr); //not that dialog, at least +#endif +} + void SaveLoadChooserDialog::open() { Dialog::open(); // So that quitting ScummVM will not cause the dialog result to say a // saved game was selected. setResult(-1); + + _dialogWasShown = false; +} + +void SaveLoadChooserDialog::close() { +#if defined(USE_CLOUD) && defined(USE_LIBCURL) + CloudMan.setSyncTarget(nullptr); //not that dialog, at least +#endif + Dialog::close(); } int SaveLoadChooserDialog::run(const Common::String &target, const MetaEngine *metaEngine) { @@ -132,9 +215,53 @@ void SaveLoadChooserDialog::handleCommand(CommandSender *sender, uint32 cmd, uin } #endif // !DISABLE_SAVELOADCHOOSER_GRID +#if defined(USE_CLOUD) && defined(USE_LIBCURL) + if (cmd == kSavesSyncProgressCmd || cmd == kSavesSyncEndedCmd) { + //this dialog only gets these commands if the progress dialog was shown and user clicked "run in background" + return updateSaveList(); + } +#endif + return Dialog::handleCommand(sender, cmd, data); } +#if defined(USE_CLOUD) && defined(USE_LIBCURL) +void SaveLoadChooserDialog::runSaveSync(bool hasSavepathOverride) { + if (!CloudMan.isSyncing()) { + if (hasSavepathOverride) { + CloudMan.showCloudDisabledIcon(); + } else { + Cloud::SavesSyncRequest *request = CloudMan.syncSaves(); + if (request) + request->setTarget(this); + } + } +} +#endif + +void SaveLoadChooserDialog::handleTickle() { +#if defined(USE_CLOUD) && defined(USE_LIBCURL) + if (!_dialogWasShown && CloudMan.isSyncing()) { + Common::Array<Common::String> files = CloudMan.getSyncingFiles(); + if (!files.empty()) { + { + SaveLoadCloudSyncProgressDialog dialog(_metaEngine ? _metaEngine->hasFeature(MetaEngine::kSimpleSavesNames) : false); + CloudMan.setSyncTarget(&dialog); + int result = dialog.runModal(); + if (result == kCancelSyncCmd) { + CloudMan.cancelSync(); + } + } + //dialog changes syncTarget to nullptr after that } + CloudMan.setSyncTarget(this); + _dialogWasShown = true; + updateSaveList(); + } + } +#endif + Dialog::handleTickle(); +} + void SaveLoadChooserDialog::reflowLayout() { #ifndef DISABLE_SAVELOADCHOOSER_GRID addChooserButtons(); @@ -152,6 +279,46 @@ void SaveLoadChooserDialog::reflowLayout() { Dialog::reflowLayout(); } +void SaveLoadChooserDialog::updateSaveList() { +#if defined(USE_CLOUD) && defined(USE_LIBCURL) + Common::Array<Common::String> files = CloudMan.getSyncingFiles(); //returns empty array if not syncing + g_system->getSavefileManager()->updateSavefilesList(files); +#endif + listSaves(); +} + +void SaveLoadChooserDialog::listSaves() { + if (!_metaEngine) return; //very strange + _saveList = _metaEngine->listSaves(_target.c_str()); + +#if defined(USE_CLOUD) && defined(USE_LIBCURL) + //if there is Cloud support, add currently synced files as "locked" saves in the list + if (_metaEngine->hasFeature(MetaEngine::kSimpleSavesNames)) { + Common::String pattern = _target + ".###"; + Common::Array<Common::String> files = CloudMan.getSyncingFiles(); //returns empty array if not syncing + for (uint32 i = 0; i < files.size(); ++i) { + if (!files[i].matchString(pattern, true)) + continue; + + //make up some slot number + int slotNum = 0; + for (uint32 j = (files[i].size() > 3 ? files[i].size() - 3 : 0); j < files[i].size(); ++j) { //3 last chars + char c = files[i][j]; + if (c < '0' || c > '9') + continue; + slotNum = slotNum * 10 + (c - '0'); + } + + SaveStateDescriptor slot(slotNum, files[i]); + slot.setLocked(true); + _saveList.push_back(slot); + } + + Common::sort(_saveList.begin(), _saveList.end(), SaveStateDescriptorSlotComparator()); + } +#endif +} + #ifndef DISABLE_SAVELOADCHOOSER_GRID void SaveLoadChooserDialog::addChooserButtons() { if (_listButton) { @@ -353,6 +520,7 @@ void SaveLoadChooserSimple::updateSelection(bool redraw) { bool isDeletable = _delSupport; bool isWriteProtected = false; bool startEditMode = _list->isEditable(); + bool isLocked = false; // We used to support letting the themes specify the fill color with our // initial theme based GUI. But this support was dropped. @@ -362,10 +530,11 @@ void SaveLoadChooserSimple::updateSelection(bool redraw) { _playtime->setLabel(_("No playtime saved")); if (selItem >= 0 && _metaInfoSupport) { - SaveStateDescriptor desc = _metaEngine->querySaveMetaInfos(_target.c_str(), _saveList[selItem].getSaveSlot()); + SaveStateDescriptor desc = (_saveList[selItem].getLocked() ? _saveList[selItem] : _metaEngine->querySaveMetaInfos(_target.c_str(), _saveList[selItem].getSaveSlot())); isDeletable = desc.getDeletableFlag() && _delSupport; isWriteProtected = desc.getWriteProtectedFlag(); + isLocked = desc.getLocked(); // Don't allow the user to change the description of write protected games if (isWriteProtected) @@ -398,27 +567,27 @@ void SaveLoadChooserSimple::updateSelection(bool redraw) { if (_list->isEditable()) { - // Disable the save button if nothing is selected, or if the selected - // game is write protected - _chooseButton->setEnabled(selItem >= 0 && !isWriteProtected); + // Disable the save button if slot is locked, nothing is selected, + // or if the selected game is write protected + _chooseButton->setEnabled(!isLocked && selItem >= 0 && !isWriteProtected); if (startEditMode) { _list->startEditMode(); - if (_chooseButton->isEnabled() && _list->getSelectedString() == _("Untitled savestate") && + if (_chooseButton->isEnabled() && _list->getSelectedString() == _("Untitled saved game") && _list->getSelectionColor() == ThemeEngine::kFontColorAlternate) { _list->setEditString(""); _list->setEditColor(ThemeEngine::kFontColorNormal); } } } else { - // Disable the load button if nothing is selected, or if an empty - // list item is selected. - _chooseButton->setEnabled(selItem >= 0 && !_list->getSelectedString().empty()); + // Disable the load button if slot is locked, nothing is selected, + // or if an empty list item is selected. + _chooseButton->setEnabled(!isLocked && selItem >= 0 && !_list->getSelectedString().empty()); } // Delete will always be disabled if the engine doesn't support it. - _deleteButton->setEnabled(isDeletable && (selItem >= 0) && (!_list->getSelectedString().empty())); + _deleteButton->setEnabled(isDeletable && !isLocked && (selItem >= 0) && (!_list->getSelectedString().empty())); if (redraw) { _gfxWidget->draw(); @@ -463,7 +632,7 @@ void SaveLoadChooserSimple::close() { } void SaveLoadChooserSimple::updateSaveList() { - _saveList = _metaEngine->listSaves(_target.c_str()); + SaveLoadChooserDialog::updateSaveList(); int curSlot = 0; int saveSlot = 0; @@ -488,15 +657,15 @@ void SaveLoadChooserSimple::updateSaveList() { } } - // Show "Untitled savestate" for empty/whitespace saved game descriptions + // Show "Untitled saved game" for empty/whitespace saved game descriptions Common::String description = x->getDescription(); Common::String trimmedDescription = description; trimmedDescription.trim(); if (trimmedDescription.empty()) { - description = _("Untitled savestate"); + description = _("Untitled saved game"); colors.push_back(ThemeEngine::kFontColorAlternate); } else { - colors.push_back(ThemeEngine::kFontColorNormal); + colors.push_back((x->getLocked() ? ThemeEngine::kFontColorAlternate : ThemeEngine::kFontColorNormal)); } saveNames.push_back(description); @@ -524,6 +693,7 @@ void SaveLoadChooserSimple::updateSaveList() { } _list->setList(saveNames, &colors); + draw(); } // SaveLoadChooserGrid implementation @@ -619,10 +789,16 @@ void SaveLoadChooserGrid::handleMouseWheel(int x, int y, int direction) { } } +void SaveLoadChooserGrid::updateSaveList() { + SaveLoadChooserDialog::updateSaveList(); + updateSaves(); + draw(); +} + void SaveLoadChooserGrid::open() { SaveLoadChooserDialog::open(); - _saveList = _metaEngine->listSaves(_target.c_str()); + listSaves(); _resultString.clear(); // Load information to restore the last page the user had open. @@ -745,7 +921,7 @@ void SaveLoadChooserGrid::reflowLayout() { // In the save mode we will always create a new save button as the first button. if (_saveMode && curLine == 0 && curColumn == 0) { _newSaveContainer = new ContainerWidget(this, curX, y, containerWidth, containerHeight); - ButtonWidget *newSave = new ButtonWidget(_newSaveContainer, dstX, dstY, buttonWidth, buttonHeight, _("New Save"), _("Create a new save game"), kNewSaveCmd); + ButtonWidget *newSave = new ButtonWidget(_newSaveContainer, dstX, dstY, buttonWidth, buttonHeight, _("New Save"), _("Create a new saved game"), kNewSaveCmd); // In case no more slots are free, we will disable the new save button if (_nextFreeSaveSlot == -1) { newSave->setEnabled(false); @@ -863,7 +1039,7 @@ void SaveLoadChooserGrid::updateSaves() { for (uint i = _curPage * _entriesPerPage, curNum = 0; i < _saveList.size() && curNum < _entriesPerPage; ++i, ++curNum) { const uint saveSlot = _saveList[i].getSaveSlot(); - SaveStateDescriptor desc = _metaEngine->querySaveMetaInfos(_target.c_str(), saveSlot); + SaveStateDescriptor desc = (_saveList[i].getLocked() ? _saveList[i] : _metaEngine->querySaveMetaInfos(_target.c_str(), saveSlot)); SlotButton &curButton = _buttons[curNum]; curButton.setVisible(true); const Graphics::Surface *thumbnail = desc.getThumbnail(); @@ -908,6 +1084,10 @@ void SaveLoadChooserGrid::updateSaves() { } else { curButton.button->setEnabled(true); } + + //that would make it look "disabled" if slot is locked + curButton.button->setEnabled(!desc.getLocked()); + curButton.description->setEnabled(!desc.getLocked()); } const uint numPages = (_entriesPerPage != 0 && !_saveList.empty()) ? ((_saveList.size() + _entriesPerPage - 1) / _entriesPerPage) : 1; @@ -932,6 +1112,8 @@ SavenameDialog::SavenameDialog() new ButtonWidget(this, "SavenameDialog.Ok", _("OK"), 0, kOKCmd); _description = new EditTextWidget(this, "SavenameDialog.Description", Common::String(), 0, 0, kOKCmd); + + _targetSlot = 0; } void SavenameDialog::setDescription(const Common::String &desc) { |