From 99c2418d1a270c4496b21d6d6c8035b6ef73e8a1 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Thu, 18 Jul 2019 23:10:49 +0700 Subject: GUI: Rewrite Cloud tab - StorageWizardDialog is removed, along with bmps it was using; - EditTextWidget now accepts custom font in constructor; - ScrollContainer scrollbar now jumps to top when content height changes so it's "overscrolled"; - IndexPageHandler now does not awaits for `code` GET-parameter, as local webserver is no longer used to connect Storages; - CloudManager and all corresponding Storages are updated to support disconnecting and to notify about successful connection. --- backends/cloud/basestorage.cpp | 21 +- backends/cloud/basestorage.h | 6 +- backends/cloud/box/boxstorage.cpp | 9 +- backends/cloud/box/boxstorage.h | 7 +- backends/cloud/cloudmanager.cpp | 52 ++- backends/cloud/cloudmanager.h | 10 +- backends/cloud/dropbox/dropboxstorage.cpp | 8 +- backends/cloud/dropbox/dropboxstorage.h | 7 +- backends/cloud/googledrive/googledrivestorage.cpp | 9 +- backends/cloud/googledrive/googledrivestorage.h | 7 +- backends/cloud/onedrive/onedrivestorage.cpp | 9 +- backends/cloud/onedrive/onedrivestorage.h | 7 +- .../sdl_net/handlers/indexpagehandler.cpp | 32 +- .../networking/sdl_net/handlers/indexpagehandler.h | 2 - gui/ThemeEngine.cpp | 4 - gui/ThemeEngine.h | 4 - gui/module.mk | 3 +- gui/options.cpp | 397 ++++++++++++++++----- gui/options.h | 23 +- gui/storagewizarddialog.cpp | 224 ------------ gui/storagewizarddialog.h | 83 ----- gui/themes/scummclassic.zip | Bin 131213 -> 135889 bytes gui/themes/scummclassic/classic_layout.stx | 229 ++++++------ gui/themes/scummclassic/classic_layout_lowres.stx | 233 ++++++------ gui/themes/scummmodern.zip | Bin 407826 -> 264656 bytes gui/themes/scummmodern/box.bmp | Bin 35806 -> 0 bytes gui/themes/scummmodern/dropbox.bmp | Bin 35806 -> 0 bytes gui/themes/scummmodern/googledrive.bmp | Bin 35806 -> 0 bytes gui/themes/scummmodern/onedrive.bmp | Bin 35806 -> 0 bytes gui/themes/scummmodern/scummmodern_gfx.stx | 4 - gui/themes/scummmodern/scummmodern_layout.stx | 229 ++++++------ .../scummmodern/scummmodern_layout_lowres.stx | 233 ++++++------ gui/themes/scummremastered.zip | Bin 407763 -> 264593 bytes gui/themes/scummremastered/box.bmp | Bin 35806 -> 0 bytes gui/themes/scummremastered/dropbox.bmp | Bin 35806 -> 0 bytes gui/themes/scummremastered/googledrive.bmp | Bin 35806 -> 0 bytes gui/themes/scummremastered/onedrive.bmp | Bin 35806 -> 0 bytes gui/themes/scummremastered/remastered_gfx.stx | 4 - gui/themes/scummremastered/remastered_layout.stx | 229 ++++++------ .../scummremastered/remastered_layout_lowres.stx | 233 ++++++------ gui/widgets/edittext.cpp | 8 +- gui/widgets/edittext.h | 4 +- gui/widgets/scrollcontainer.cpp | 1 + 43 files changed, 1142 insertions(+), 1189 deletions(-) delete mode 100644 gui/storagewizarddialog.cpp delete mode 100644 gui/storagewizarddialog.h delete mode 100644 gui/themes/scummmodern/box.bmp delete mode 100644 gui/themes/scummmodern/dropbox.bmp delete mode 100644 gui/themes/scummmodern/googledrive.bmp delete mode 100644 gui/themes/scummmodern/onedrive.bmp delete mode 100644 gui/themes/scummremastered/box.bmp delete mode 100644 gui/themes/scummremastered/dropbox.bmp delete mode 100644 gui/themes/scummremastered/googledrive.bmp delete mode 100644 gui/themes/scummremastered/onedrive.bmp diff --git a/backends/cloud/basestorage.cpp b/backends/cloud/basestorage.cpp index 805cb472a2..bb198120ff 100644 --- a/backends/cloud/basestorage.cpp +++ b/backends/cloud/basestorage.cpp @@ -37,18 +37,19 @@ BaseStorage::BaseStorage(Common::String token, Common::String refreshToken): BaseStorage::~BaseStorage() {} -void BaseStorage::getAccessToken(Common::String code) { - Networking::JsonCallback callback = new Common::Callback(this, &BaseStorage::codeFlowComplete); - Networking::ErrorCallback errorCallback = new Common::Callback(this, &BaseStorage::codeFlowFailed); +void BaseStorage::getAccessToken(Common::String code, Networking::ErrorCallback callback) { + Networking::JsonCallback innerCallback = new Common::CallbackBridge(this, &BaseStorage::codeFlowComplete, callback); + Networking::ErrorCallback errorCallback = new Common::CallbackBridge(this, &BaseStorage::codeFlowFailed, callback); Common::String url = Common::String::format("https://cloud.scummvm.org/%s/token/%s", cloudProvider().c_str(), code.c_str()); - Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, errorCallback, url); + Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorCallback, url); addRequest(request); } -void BaseStorage::codeFlowComplete(Networking::JsonResponse response) { +void BaseStorage::codeFlowComplete(Networking::ErrorCallback callback, Networking::JsonResponse response) { bool success = true; + Common::String callbackMessage = "OK"; Common::JSONValue *json = (Common::JSONValue *)response.value; if (json == nullptr) { @@ -78,6 +79,7 @@ void BaseStorage::codeFlowComplete(Networking::JsonResponse response) { } warning("BaseStorage: response says error occurred: %s", errorMessage.c_str()); success = false; + callbackMessage = errorMessage; } if (success && !Networking::CurlJsonRequest::jsonContainsObject(result, "oauth", "BaseStorage::codeFlowComplete")) { @@ -110,13 +112,20 @@ void BaseStorage::codeFlowComplete(Networking::JsonResponse response) { if (!success) CloudMan.removeStorage(this); + if (callback) + (*callback)(Networking::ErrorResponse(nullptr, false, !success, callbackMessage, -1)); delete json; + delete callback; } -void BaseStorage::codeFlowFailed(Networking::ErrorResponse error) { +void BaseStorage::codeFlowFailed(Networking::ErrorCallback callback, Networking::ErrorResponse error) { debug(9, "BaseStorage: code flow failed (%s, %ld):", (error.failed ? "failed" : "interrupted"), error.httpResponseCode); debug(9, "%s", error.response.c_str()); CloudMan.removeStorage(this); + + if (callback) + (*callback)(error); + delete callback; } void BaseStorage::refreshAccessToken(BoolCallback callback, Networking::ErrorCallback errorCallback) { diff --git a/backends/cloud/basestorage.h b/backends/cloud/basestorage.h index 243e7f4bcc..aae1a6ec2f 100644 --- a/backends/cloud/basestorage.h +++ b/backends/cloud/basestorage.h @@ -37,19 +37,19 @@ protected: * Gets token from cloud.scummvm.org using given code. * Base implementation for storages with common auth procedure. */ - virtual void getAccessToken(Common::String code); + virtual void getAccessToken(Common::String code, Networking::ErrorCallback callback); /** * Handles JSON response which should contain access token requested * with getAccessToken(). */ - virtual void codeFlowComplete(Networking::JsonResponse response); + virtual void codeFlowComplete(Networking::ErrorCallback callback, Networking::JsonResponse response); /** * Handles network errors occurred while getting access token requested * with getAccessToken(). */ - virtual void codeFlowFailed(Networking::ErrorResponse error); + virtual void codeFlowFailed(Networking::ErrorCallback callback, Networking::ErrorResponse error); /** * Return cloud provider name, used in cloud.scummvm.org endpoints. diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp index f76fa3ac23..13046a08e0 100644 --- a/backends/cloud/box/boxstorage.cpp +++ b/backends/cloud/box/boxstorage.cpp @@ -45,8 +45,8 @@ namespace Box { BoxStorage::BoxStorage(Common::String token, Common::String refreshToken): IdStorage(token, refreshToken) {} -BoxStorage::BoxStorage(Common::String code) { - getAccessToken(code); +BoxStorage::BoxStorage(Common::String code, Networking::ErrorCallback cb) { + getAccessToken(code, cb); } BoxStorage::~BoxStorage() {} @@ -227,6 +227,11 @@ BoxStorage *BoxStorage::loadFromConfig(Common::String keyPrefix) { return new BoxStorage(accessToken, refreshToken); } +void BoxStorage::removeFromConfig(Common::String keyPrefix) { + ConfMan.removeKey(keyPrefix + "access_token", ConfMan.kCloudDomain); + ConfMan.removeKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain); +} + Common::String BoxStorage::getRootDirectoryId() { return "0"; } diff --git a/backends/cloud/box/boxstorage.h b/backends/cloud/box/boxstorage.h index a8fd32c404..ce77192bfa 100644 --- a/backends/cloud/box/boxstorage.h +++ b/backends/cloud/box/boxstorage.h @@ -55,7 +55,7 @@ protected: public: /** This constructor uses OAuth code flow to get tokens. */ - BoxStorage(Common::String code); + BoxStorage(Common::String code, Networking::ErrorCallback cb); virtual ~BoxStorage(); /** @@ -104,6 +104,11 @@ public: */ static BoxStorage *loadFromConfig(Common::String keyPrefix); + /** + * Remove all BoxStorage-related data from config. + */ + static void removeFromConfig(Common::String keyPrefix); + virtual Common::String getRootDirectoryId(); Common::String accessToken() const { return _token; } diff --git a/backends/cloud/cloudmanager.cpp b/backends/cloud/cloudmanager.cpp index 20c279323c..432a63b040 100644 --- a/backends/cloud/cloudmanager.cpp +++ b/backends/cloud/cloudmanager.cpp @@ -148,6 +148,12 @@ void CloudManager::replaceStorage(Storage *storage, uint32 index) { } _activeStorage = storage; _currentStorageIndex = index; + if (_storages[index].username == "") { + // options' Cloud tab believes Storage is connected once it has non-empty username + _storages[index].username = _(""); + _storages[index].lastSyncDate = _(""); + _storages[index].usedBytes = 0; + } save(); //do what should be done on first Storage connect @@ -250,21 +256,21 @@ void CloudManager::setStorageLastSync(uint32 index, Common::String date) { save(); } -void CloudManager::connectStorage(uint32 index, Common::String code) { +void CloudManager::connectStorage(uint32 index, Common::String code, Networking::ErrorCallback cb) { freeStorages(); switch (index) { case kStorageDropboxId: - new Dropbox::DropboxStorage(code); + new Dropbox::DropboxStorage(code, cb); break; case kStorageOneDriveId: - new OneDrive::OneDriveStorage(code); + new OneDrive::OneDriveStorage(code, cb); break; case kStorageGoogleDriveId: - new GoogleDrive::GoogleDriveStorage(code); + new GoogleDrive::GoogleDriveStorage(code, cb); break; case kStorageBoxId: - new Box::BoxStorage(code); + new Box::BoxStorage(code, cb); break; } // in these constructors Storages request token using the passed code @@ -273,6 +279,42 @@ void CloudManager::connectStorage(uint32 index, Common::String code) { // thus, no memory leak happens } +void CloudManager::disconnectStorage(uint32 index) { + if (index >= kStorageTotal) + error("CloudManager::disconnectStorage: invalid index passed"); + + Common::String name = getStorageConfigName(index); + switch (index) { + case kStorageDropboxId: + Dropbox::DropboxStorage::removeFromConfig(kStoragePrefix + name + "_"); + break; + case kStorageOneDriveId: + OneDrive::OneDriveStorage::removeFromConfig(kStoragePrefix + name + "_"); + break; + case kStorageGoogleDriveId: + GoogleDrive::GoogleDriveStorage::removeFromConfig(kStoragePrefix + name + "_"); + break; + case kStorageBoxId: + Box::BoxStorage::removeFromConfig(kStoragePrefix + name + "_"); + break; + } + + switchStorage(kStorageNoneId); + + ConfMan.removeKey(kStoragePrefix + name + "_username", ConfMan.kCloudDomain); + ConfMan.removeKey(kStoragePrefix + name + "_lastSync", ConfMan.kCloudDomain); + ConfMan.removeKey(kStoragePrefix + name + "_usedBytes", ConfMan.kCloudDomain); + + StorageConfig config; + config.name = _(name); + config.username = ""; + config.lastSyncDate = ""; + config.usedBytes = 0; + + _storages[index] = config; +} + + Networking::Request *CloudManager::listDirectory(Common::String path, Storage::ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive) { Storage *storage = getCurrentStorage(); if (storage) { diff --git a/backends/cloud/cloudmanager.h b/backends/cloud/cloudmanager.h index eb882a63af..131af9bb8f 100644 --- a/backends/cloud/cloudmanager.h +++ b/backends/cloud/cloudmanager.h @@ -204,8 +204,16 @@ public: * * @param index Storage's index * @param code OAuth2 code received from user + * @param cb callback to notify of success or error */ - void connectStorage(uint32 index, Common::String code); + void connectStorage(uint32 index, Common::String code, Networking::ErrorCallback cb = nullptr); + + /** + * Remove Storage with a given index from config. + * + * @param index Storage's index + */ + void disconnectStorage(uint32 index); /** Returns ListDirectoryResponse with list of files. */ Networking::Request *listDirectory(Common::String path, Storage::ListDirectoryCallback callback, Networking::ErrorCallback errorCallback, bool recursive = false); diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp index c12dec9968..5d8b9e0425 100644 --- a/backends/cloud/dropbox/dropboxstorage.cpp +++ b/backends/cloud/dropbox/dropboxstorage.cpp @@ -42,8 +42,8 @@ namespace Dropbox { DropboxStorage::DropboxStorage(Common::String accessToken, bool unused): BaseStorage(accessToken, "") {} -DropboxStorage::DropboxStorage(Common::String code): BaseStorage() { - getAccessToken(code); +DropboxStorage::DropboxStorage(Common::String code, Networking::ErrorCallback cb): BaseStorage() { + getAccessToken(code, cb); } DropboxStorage::~DropboxStorage() {} @@ -112,5 +112,9 @@ DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) { return new DropboxStorage(accessToken, true); } +void DropboxStorage::removeFromConfig(Common::String keyPrefix) { + ConfMan.removeKey(keyPrefix + "access_token", ConfMan.kCloudDomain); +} + } // End of namespace Dropbox } // End of namespace Cloud diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h index bca83d2b5a..0b76bb5c4a 100644 --- a/backends/cloud/dropbox/dropboxstorage.h +++ b/backends/cloud/dropbox/dropboxstorage.h @@ -51,7 +51,7 @@ protected: public: /** This constructor uses OAuth code flow to get tokens. */ - DropboxStorage(Common::String code); + DropboxStorage(Common::String code, Networking::ErrorCallback cb); virtual ~DropboxStorage(); /** @@ -98,6 +98,11 @@ public: * @return pointer to the newly created DropboxStorage or 0 if some problem occured. */ static DropboxStorage *loadFromConfig(Common::String keyPrefix); + + /** + * Remove all DropboxStorage-related data from config. + */ + static void removeFromConfig(Common::String keyPrefix); }; } // End of namespace Dropbox diff --git a/backends/cloud/googledrive/googledrivestorage.cpp b/backends/cloud/googledrive/googledrivestorage.cpp index 67d157748a..a6e17e6ad3 100644 --- a/backends/cloud/googledrive/googledrivestorage.cpp +++ b/backends/cloud/googledrive/googledrivestorage.cpp @@ -46,8 +46,8 @@ namespace GoogleDrive { GoogleDriveStorage::GoogleDriveStorage(Common::String token, Common::String refreshToken): IdStorage(token, refreshToken) {} -GoogleDriveStorage::GoogleDriveStorage(Common::String code) { - getAccessToken(code); +GoogleDriveStorage::GoogleDriveStorage(Common::String code, Networking::ErrorCallback cb) { + getAccessToken(code, cb); } GoogleDriveStorage::~GoogleDriveStorage() {} @@ -231,6 +231,11 @@ GoogleDriveStorage *GoogleDriveStorage::loadFromConfig(Common::String keyPrefix) return new GoogleDriveStorage(accessToken, refreshToken); } +void GoogleDriveStorage::removeFromConfig(Common::String keyPrefix) { + ConfMan.removeKey(keyPrefix + "access_token", ConfMan.kCloudDomain); + ConfMan.removeKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain); +} + Common::String GoogleDriveStorage::getRootDirectoryId() { return "root"; } diff --git a/backends/cloud/googledrive/googledrivestorage.h b/backends/cloud/googledrive/googledrivestorage.h index 21e027c4a7..db47e7cd3c 100644 --- a/backends/cloud/googledrive/googledrivestorage.h +++ b/backends/cloud/googledrive/googledrivestorage.h @@ -58,7 +58,7 @@ protected: public: /** This constructor uses OAuth code flow to get tokens. */ - GoogleDriveStorage(Common::String code); + GoogleDriveStorage(Common::String code, Networking::ErrorCallback cb); virtual ~GoogleDriveStorage(); /** @@ -106,6 +106,11 @@ public: */ static GoogleDriveStorage *loadFromConfig(Common::String keyPrefix); + /** + * Remove all GoogleDriveStorage-related data from config. + */ + static void removeFromConfig(Common::String keyPrefix); + virtual Common::String getRootDirectoryId(); Common::String accessToken() const { return _token; } diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp index 48c3a10d82..6d05d84c39 100644 --- a/backends/cloud/onedrive/onedrivestorage.cpp +++ b/backends/cloud/onedrive/onedrivestorage.cpp @@ -45,8 +45,8 @@ namespace OneDrive { OneDriveStorage::OneDriveStorage(Common::String token, Common::String refreshToken): BaseStorage(token, refreshToken) {} -OneDriveStorage::OneDriveStorage(Common::String code) { - getAccessToken(code); +OneDriveStorage::OneDriveStorage(Common::String code, Networking::ErrorCallback cb) { + getAccessToken(code, cb); } OneDriveStorage::~OneDriveStorage() {} @@ -209,5 +209,10 @@ OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) { return new OneDriveStorage(accessToken, refreshToken); } +void OneDriveStorage::removeFromConfig(Common::String keyPrefix) { + ConfMan.removeKey(keyPrefix + "access_token", ConfMan.kCloudDomain); + ConfMan.removeKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain); +} + } // End of namespace OneDrive } // End of namespace Cloud diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h index 4b18929d73..cc46772282 100644 --- a/backends/cloud/onedrive/onedrivestorage.h +++ b/backends/cloud/onedrive/onedrivestorage.h @@ -55,7 +55,7 @@ protected: public: /** This constructor uses OAuth code flow to get tokens. */ - OneDriveStorage(Common::String code); + OneDriveStorage(Common::String code, Networking::ErrorCallback cb); virtual ~OneDriveStorage(); /** @@ -103,6 +103,11 @@ public: */ static OneDriveStorage *loadFromConfig(Common::String keyPrefix); + /** + * Remove all OneDriveStorage-related data from config. + */ + static void removeFromConfig(Common::String keyPrefix); + Common::String accessToken() const { return _token; } }; diff --git a/backends/networking/sdl_net/handlers/indexpagehandler.cpp b/backends/networking/sdl_net/handlers/indexpagehandler.cpp index 17e5159768..876bdde9ce 100644 --- a/backends/networking/sdl_net/handlers/indexpagehandler.cpp +++ b/backends/networking/sdl_net/handlers/indexpagehandler.cpp @@ -24,7 +24,6 @@ #include "backends/networking/sdl_net/handlerutils.h" #include "backends/networking/sdl_net/localwebserver.h" #include "common/translation.h" -#include "gui/storagewizarddialog.h" namespace Networking { @@ -34,28 +33,17 @@ IndexPageHandler::~IndexPageHandler() {} /// public -Common::String IndexPageHandler::code() const { return _code; } - void IndexPageHandler::handle(Client &client) { - Common::String queryCode = client.queryParameter("code"); - - if (queryCode == "") { - // redirect to "/filesAJAX" - HandlerUtils::setMessageHandler( - client, - Common::String::format( - "%s
%s", - _("This is a local webserver index page."), - _("Open Files manager") - ), - "/filesAJAX" - ); - return; - } - - _code = queryCode; - sendCommand(GUI::kStorageCodePassedCmd, 0); - HandlerUtils::setMessageHandler(client, _("ScummVM got the code and already connects to your cloud storage!")); + // redirect to "/filesAJAX" + HandlerUtils::setMessageHandler( + client, + Common::String::format( + "%s
%s", + _("This is a local webserver index page."), + _("Open Files manager") + ), + "/filesAJAX" + ); } bool IndexPageHandler::minimalModeSupported() { diff --git a/backends/networking/sdl_net/handlers/indexpagehandler.h b/backends/networking/sdl_net/handlers/indexpagehandler.h index 0d8e616395..b4841bcdca 100644 --- a/backends/networking/sdl_net/handlers/indexpagehandler.h +++ b/backends/networking/sdl_net/handlers/indexpagehandler.h @@ -30,12 +30,10 @@ namespace Networking { class LocalWebserver; class IndexPageHandler: public BaseHandler, public GUI::CommandSender { - Common::String _code; public: IndexPageHandler(); virtual ~IndexPageHandler(); - Common::String code() const; virtual void handle(Client &client); virtual bool minimalModeSupported(); }; diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index 8117fbe1ab..7e42bc0ab3 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -61,10 +61,6 @@ const char *const ThemeEngine::kImageStopSmallButton = "stopbtn_small.bmp"; const char *const ThemeEngine::kImageEditSmallButton = "editbtn_small.bmp"; const char *const ThemeEngine::kImageSwitchModeSmallButton = "switchbtn_small.bmp"; const char *const ThemeEngine::kImageFastReplaySmallButton = "fastreplay_small.bmp"; -const char *const ThemeEngine::kImageDropboxLogo = "dropbox.bmp"; -const char *const ThemeEngine::kImageOneDriveLogo = "onedrive.bmp"; -const char *const ThemeEngine::kImageGoogleDriveLogo = "googledrive.bmp"; -const char *const ThemeEngine::kImageBoxLogo = "box.bmp"; struct TextDrawData { const Graphics::Font *_fontPtr; diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h index 0fd7e9ecb5..367f5cb2c6 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -263,10 +263,6 @@ public: static const char *const kImageEditSmallButton; ///< Edit recording metadata in recorder onscreen dialog (for 320xY) static const char *const kImageSwitchModeSmallButton; ///< Switch mode button in recorder onscreen dialog (for 320xY) static const char *const kImageFastReplaySmallButton; ///< Fast playback mode button in recorder onscreen dialog (for 320xY) - static const char *const kImageDropboxLogo; ///< Dropbox logo used in the StorageWizardDialog - static const char *const kImageOneDriveLogo; ///< OneDrive logo used in the StorageWizardDialog - static const char *const kImageGoogleDriveLogo; ///< Google Drive logo used in the StorageWizardDialog - static const char *const kImageBoxLogo; ///< Box logo used in the StorageWizardDialog /** * Graphics mode enumeration. diff --git a/gui/module.mk b/gui/module.mk index 87f8dec3b2..799c4e7d61 100644 --- a/gui/module.mk +++ b/gui/module.mk @@ -43,8 +43,7 @@ ifdef USE_CLOUD ifdef USE_LIBCURL MODULE_OBJS += \ downloaddialog.o \ - remotebrowser.o \ - storagewizarddialog.o + remotebrowser.o endif endif diff --git a/gui/options.cpp b/gui/options.cpp index 5d90b70813..38bfc3bc72 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -51,7 +51,6 @@ #ifdef USE_LIBCURL #include "backends/cloud/cloudmanager.h" #include "gui/downloaddialog.h" -#include "gui/storagewizarddialog.h" #endif #ifdef USE_SDL_NET @@ -105,14 +104,17 @@ enum { #ifdef USE_CLOUD enum { - kConfigureStorageCmd = 'cfst', - kRefreshStorageCmd = 'rfst', + kSyncSavesStorageCmd = 'ssst', kDownloadStorageCmd = 'dlst', kRunServerCmd = 'rnsv', kCloudTabContainerReflowCmd = 'ctcr', kServerPortClearCmd = 'spcl', kChooseRootDirCmd = 'chrp', - kRootPathClearCmd = 'clrp' + kRootPathClearCmd = 'clrp', + kConnectStorageCmd = 'Cnnt', + kOpenUrlStorageCmd = 'OpUr', + kPasteCodeStorageCmd = 'PsCd', + kDisconnectStorageCmd = 'DcSt', }; #endif @@ -1486,11 +1488,25 @@ GlobalOptionsDialog::GlobalOptionsDialog(LauncherDialog *launcher) _storageUsername = 0; _storageUsedSpaceDesc = 0; _storageUsedSpace = 0; + _storageSyncHint = 0; _storageLastSyncDesc = 0; _storageLastSync = 0; - _storageConnectButton = 0; - _storageRefreshButton = 0; + _storageSyncSavesButton = 0; + _storageDownloadHint = 0; _storageDownloadButton = 0; + _storageDisconnectHint = 0; + _storageDisconnectButton = 0; + + _connectingStorage = false; + _storageWizardNotConnectedHint = 0; + _storageWizardOpenLinkHint = 0; + _storageWizardLink = 0; + _storageWizardCodeHint = 0; + _storageWizardCodeBox = 0; + _storageWizardPasteButton = 0; + _storageWizardConnectButton = 0; + _storageWizardConnectionStatusHint = 0; + _runServerButton = 0; _serverInfoLabel = 0; _rootPathButton = 0; @@ -1744,7 +1760,7 @@ void GlobalOptionsDialog::build() { container->setTarget(this); container->setBackgroundType(ThemeEngine::kDialogBackgroundNone); - _storagePopUpDesc = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StoragePopupDesc", _("Storage:"), _("Active cloud storage")); + _storagePopUpDesc = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StoragePopupDesc", _("Active storage:"), _("Active cloud storage")); _storagePopUp = new PopUpWidget(container, "GlobalOptions_Cloud_Container.StoragePopup"); #ifdef USE_LIBCURL Common::StringArray list = CloudMan.listStorages(); @@ -1755,27 +1771,39 @@ void GlobalOptionsDialog::build() { #endif _storagePopUp->setSelected(_selectedStorageIndex); + const char* context = (g_system->getOverlayWidth() > 320 ? nullptr : "lowres"); + _storageUsernameDesc = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageUsernameDesc", _("Username:"), _("Username used by this storage")); - _storageUsername = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageUsernameLabel", ""); + _storageUsername = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageUsernameLabel", "", "", ThemeEngine::kFontStyleNormal); _storageUsedSpaceDesc = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageUsedSpaceDesc", _("Used space:"), _("Space used by ScummVM's saved games on this storage")); - _storageUsedSpace = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageUsedSpaceLabel", "0 bytes"); - - _storageLastSyncDesc = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageLastSyncDesc", _("Last sync time:"), _("When the last saved games sync for this storage occured")); - _storageLastSync = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageLastSyncLabel", ""); - - _storageConnectButton = new ButtonWidget(container, "GlobalOptions_Cloud_Container.ConnectButton", _("Connect"), _("Open wizard dialog to connect your cloud storage account"), kConfigureStorageCmd); - _storageRefreshButton = new ButtonWidget(container, "GlobalOptions_Cloud_Container.RefreshButton", _("Refresh"), _("Refresh current cloud storage information (username and usage)"), kRefreshStorageCmd); - _storageDownloadButton = new ButtonWidget(container, "GlobalOptions_Cloud_Container.DownloadButton", _("Download"), _("Open downloads manager dialog"), kDownloadStorageCmd); + _storageUsedSpace = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageUsedSpaceLabel", "0 bytes", "", ThemeEngine::kFontStyleNormal); + + _storageLastSyncDesc = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageLastSyncDesc", _("Last sync:"), _("When was the last time saved games were synced with this storage")); + _storageLastSync = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageLastSyncLabel", "", "", ThemeEngine::kFontStyleNormal); + _storageSyncHint = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageSyncHint", _c("Saves sync automatically on launch, after saving and on loading.", context), "", ThemeEngine::kFontStyleNormal); + _storageSyncSavesButton = new ButtonWidget(container, "GlobalOptions_Cloud_Container.SyncSavesButton", _("Sync now"), _("Start saves sync"), kSyncSavesStorageCmd); + + _storageDownloadHint = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageDownloadHint", _c("You can download game files from your cloud ScummVM folder:", context)); + _storageDownloadButton = new ButtonWidget(container, "GlobalOptions_Cloud_Container.DownloadButton", _("Download game files"), _("Open downloads manager dialog"), kDownloadStorageCmd); + + _storageDisconnectHint = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageDisconnectHint", _c("To change account for this storage, disconnect and connect again:", context)); + _storageDisconnectButton = new ButtonWidget(container, "GlobalOptions_Cloud_Container.DisconnectButton", _("Disconnect"), _("Stop using this storage on this device"), kDisconnectStorageCmd); + + _storageWizardNotConnectedHint = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageWizardNotConnectedHint", _c("This storage is not connected yet! To connect,", context)); + _storageWizardOpenLinkHint = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageWizardOpenLinkHint", "1. Open this link:"); + _storageWizardLink = new ButtonWidget(container, "GlobalOptions_Cloud_Container.StorageWizardLink", "https://cloud.scummvm.org/", _("Open URL"), kOpenUrlStorageCmd); + _storageWizardCodeHint = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageWizardCodeHint", _c("2. Get the code and enter it here:", context)); + _storageWizardCodeBox = new EditTextWidget(container, "GlobalOptions_Cloud_Container.StorageWizardCodeBox", "", 0, 0, 0, ThemeEngine::kFontStyleConsole); + _storageWizardPasteButton = new ButtonWidget(container, "GlobalOptions_Cloud_Container.StorageWizardPasteButton", _("Paste"), _("Paste code from clipboard"), kPasteCodeStorageCmd); + _storageWizardConnectButton = new ButtonWidget(container, "GlobalOptions_Cloud_Container.StorageWizardConnectButton", _("3. Connect"), _("Connect your cloud storage account"), kConnectStorageCmd); + _storageWizardConnectionStatusHint = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.StorageWizardConnectionStatusHint", "..."); _runServerButton = new ButtonWidget(container, "GlobalOptions_Cloud_Container.RunServerButton", _("Run server"), _("Run local webserver"), kRunServerCmd); _serverInfoLabel = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.ServerInfoLabel", _("Not running")); // Root path - if (g_system->getOverlayWidth() > 320) - _rootPathButton = new ButtonWidget(container, "GlobalOptions_Cloud_Container.RootPathButton", _("/root/ Path:"), _("Specifies which directory the Files Manager can access"), kChooseRootDirCmd); - else - _rootPathButton = new ButtonWidget(container, "GlobalOptions_Cloud_Container.RootPathButton", _c("/root/ Path:", "lowres"), _("Specifies which directory the Files Manager can access"), kChooseRootDirCmd); + _rootPathButton = new ButtonWidget(container, "GlobalOptions_Cloud_Container.RootPathButton", _c("/root/ Path:", context), _("Specifies which directory the Files Manager can access"), kChooseRootDirCmd); _rootPath = new StaticTextWidget(container, "GlobalOptions_Cloud_Container.RootPath", "/foo/bar", _("Specifies which directory the Files Manager can access")); _rootPathClearButton = addClearButton(container, "GlobalOptions_Cloud_Container.RootPathClearButton", kRootPathClearCmd); @@ -1882,6 +1910,17 @@ void GlobalOptionsDialog::clean() { OptionsDialog::clean(); } +void GlobalOptionsDialog::shiftWidget(Widget *widget, const char *widgetName, int32 xOffset, int32 yOffset) { + if (!widget) return; + + int16 x, y; + uint16 w, h; + if (!g_gui.xmlEval()->getWidgetData(widgetName, x, y, w, h)) + warning("%s's position is undefined", widgetName); + + widget->setPos(x + xOffset, y + yOffset); +} + void GlobalOptionsDialog::apply() { OptionsDialog::apply(); @@ -2167,47 +2206,120 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 reflowLayout(); break; } - case kConfigureStorageCmd: - { -#ifdef NETWORKING_LOCALWEBSERVER_ENABLE_PORT_OVERRIDE - // save server's port - uint32 port = Networking::LocalWebserver::getPort(); - if (_serverPort) { - uint64 contents = _serverPort->getEditString().asUint64(); - if (contents != 0) - port = contents; - } - ConfMan.setInt("local_server_port", port); - ConfMan.flushToDisk(); -#endif // NETWORKING_LOCALWEBSERVER_ENABLE_PORT_OVERRIDE - StorageWizardDialog dialog(_selectedStorageIndex); + case kSyncSavesStorageCmd: { + CloudMan.syncSaves( + new Common::Callback(this, &GlobalOptionsDialog::storageSavesSyncedCallback) + ); + break; + } + case kDownloadStorageCmd: { + DownloadDialog dialog(_selectedStorageIndex, _launcher); dialog.runModal(); - //update container's scrollbar - reflowLayout(); break; } - case kRefreshStorageCmd: - { - CloudMan.info( - new Common::Callback(this, &GlobalOptionsDialog::storageInfoCallback), - new Common::Callback(this, &GlobalOptionsDialog::storageErrorCallback) - ); - Common::String dir = CloudMan.savesDirectoryPath(); - if (dir.lastChar() == '/') - dir.deleteLastChar(); - CloudMan.listDirectory( - dir, - new Common::Callback(this, &GlobalOptionsDialog::storageListDirectoryCallback), - new Common::Callback(this, &GlobalOptionsDialog::storageErrorCallback) + case kOpenUrlStorageCmd: { + Common::String url = "https://cloud.scummvm.org/"; + switch (_selectedStorageIndex) { + case Cloud::kStorageDropboxId: + url += "dropbox"; + break; + case Cloud::kStorageOneDriveId: + url += "onedrive"; + break; + case Cloud::kStorageGoogleDriveId: + url += "gdrive"; + break; + case Cloud::kStorageBoxId: + url += "box"; + break; + } + + if (!g_system->openUrl(url)) { + MessageDialog alert(_("Failed to open URL!\nPlease navigate to this page manually.")); + alert.runModal(); + } + break; + } + case kPasteCodeStorageCmd: { + if (g_system->hasTextInClipboard()) { + Common::String message = g_system->getTextFromClipboard(); + if (!message.empty()) { + _storageWizardCodeBox->setEditString(message); + _redrawCloudTab = true; + } + } + break; + } + case kConnectStorageCmd: { + Common::String code = ""; + if (_storageWizardCodeBox) + code = _storageWizardCodeBox->getEditString(); + if (code.size() == 0) + return; + + if (CloudMan.isWorking()) { + bool cancel = true; + + MessageDialog alert(_("Another Storage is working now. Do you want to interrupt it?"), _("Yes"), _("No")); + if (alert.runModal() == GUI::kMessageOK) { + if (CloudMan.isDownloading()) + CloudMan.cancelDownload(); + if (CloudMan.isSyncing()) + CloudMan.cancelSync(); + + // I believe it still would return `true` here, but just in case + if (CloudMan.isWorking()) { + MessageDialog alert2(_("Wait until current Storage finishes up and try again.")); + alert2.runModal(); + } else { + cancel = false; + } + } + + if (cancel) { + return; + } + } + + if (_storageWizardConnectionStatusHint) + _storageWizardConnectionStatusHint->setLabel(_("Connecting...")); + CloudMan.connectStorage( + _selectedStorageIndex, code, + new Common::Callback(this, &GlobalOptionsDialog::storageConnectionCallback) ); + _connectingStorage = true; + _redrawCloudTab = true; break; } - case kDownloadStorageCmd: - { - DownloadDialog dialog(_selectedStorageIndex, _launcher); - dialog.runModal(); - break; + case kDisconnectStorageCmd: { + if (_selectedStorageIndex == CloudMan.getStorageIndex() && CloudMan.isWorking()) { + bool cancel = true; + + MessageDialog alert(_("This Storage is working now. Do you want to interrupt it?"), _("Yes"), _("No")); + if (alert.runModal() == GUI::kMessageOK) { + if (CloudMan.isDownloading()) + CloudMan.cancelDownload(); + if (CloudMan.isSyncing()) + CloudMan.cancelSync(); + + // I believe it still would return `true` here, but just in case + if (CloudMan.isWorking()) { + MessageDialog alert2(_("Wait until current Storage finishes up and try again.")); + alert2.runModal(); + } else { + cancel = false; + } + } + + if (cancel) { + return; + } } + + CloudMan.disconnectStorage(_selectedStorageIndex); + _redrawCloudTab = true; + break; + } #endif // USE_LIBCURL #ifdef USE_SDL_NET case kRunServerCmd: @@ -2329,24 +2441,29 @@ void GlobalOptionsDialog::setupCloudTab() { if (_storagePopUpDesc) _storagePopUpDesc->setVisible(true); if (_storagePopUp) _storagePopUp->setVisible(true); + Common::String username = CloudMan.getStorageUsername(_selectedStorageIndex); + bool storageConnected = (username != ""); bool shown = (_selectedStorageIndex != Cloud::kStorageNoneId); - if (_storageUsernameDesc) _storageUsernameDesc->setVisible(shown); + bool shownConnectedInfo = (shown && storageConnected); + + if (_storageUsernameDesc) _storageUsernameDesc->setVisible(shownConnectedInfo); if (_storageUsername) { - Common::String username = CloudMan.getStorageUsername(_selectedStorageIndex); - if (username == "") - username = _(""); _storageUsername->setLabel(username); - _storageUsername->setVisible(shown); + _storageUsername->setVisible(shownConnectedInfo); } - if (_storageUsedSpaceDesc) _storageUsedSpaceDesc->setVisible(shown); + if (_storageUsedSpaceDesc) _storageUsedSpaceDesc->setVisible(shownConnectedInfo); if (_storageUsedSpace) { uint64 usedSpace = CloudMan.getStorageUsedSpace(_selectedStorageIndex); Common::String usedSpaceNumber, usedSpaceUnits; usedSpaceNumber = Common::getHumanReadableBytes(usedSpace, usedSpaceUnits); _storageUsedSpace->setLabel(Common::String::format("%s %s", usedSpaceNumber.c_str(), _(usedSpaceUnits.c_str()))); - _storageUsedSpace->setVisible(shown); + _storageUsedSpace->setVisible(shownConnectedInfo); } - if (_storageLastSyncDesc) _storageLastSyncDesc->setVisible(shown); + if (_storageSyncHint) { + _storageSyncHint->setVisible(shownConnectedInfo); + _storageSyncHint->setEnabled(false); + } + if (_storageLastSyncDesc) _storageLastSyncDesc->setVisible(shownConnectedInfo); if (_storageLastSync) { Common::String sync = CloudMan.getStorageLastSync(_selectedStorageIndex); if (sync == "") { @@ -2356,16 +2473,96 @@ void GlobalOptionsDialog::setupCloudTab() { sync = _(""); } _storageLastSync->setLabel(sync); - _storageLastSync->setVisible(shown); + _storageLastSync->setVisible(shownConnectedInfo); + } + if (_storageSyncSavesButton) + _storageSyncSavesButton->setVisible(shownConnectedInfo && _selectedStorageIndex == CloudMan.getStorageIndex()); + + { + int16 x, y; + uint16 w, h; + int16 downloadHintY, downloadButtonY, disconnectHintY; + if (!g_gui.xmlEval()->getWidgetData("GlobalOptions_Cloud_Container.StorageDownloadHint", x, y, w, h)) + warning("GlobalOptions_Cloud_Container.StorageDownloadHint's position is undefined"); + downloadHintY = y; + if (!g_gui.xmlEval()->getWidgetData("GlobalOptions_Cloud_Container.DownloadButton", x, y, w, h)) + warning("GlobalOptions_Cloud_Container.DownloadButton's position is undefined"); + downloadButtonY = y; + if (!g_gui.xmlEval()->getWidgetData("GlobalOptions_Cloud_Container.StorageDisconnectHint", x, y, w, h)) + warning("GlobalOptions_Cloud_Container.StorageDisconnectHint's position is undefined"); + disconnectHintY = y; + + bool showDownloadButton = (shownConnectedInfo && _selectedStorageIndex == CloudMan.getStorageIndex() && _selectedStorageIndex != Cloud::kStorageGoogleDriveId); // cannot download via Google Drive + if (_storageDownloadHint) _storageDownloadHint->setVisible(showDownloadButton); + if (_storageDownloadButton) _storageDownloadButton->setVisible(showDownloadButton); + if (_storageDisconnectHint) _storageDisconnectHint->setVisible(shownConnectedInfo); + if (_storageDisconnectButton) _storageDisconnectButton->setVisible(shownConnectedInfo); + + if (showDownloadButton) { + if (_storageDownloadHint) _storageDownloadHint->setPos(_storageDownloadHint->getRelX(), downloadHintY); + if (_storageDownloadButton) _storageDownloadButton->setPos(_storageDownloadButton->getRelX(), downloadButtonY); + if (_storageDisconnectHint) _storageDisconnectHint->setPos(_storageDisconnectHint->getRelX(), disconnectHintY); + if (_storageDisconnectButton)_storageDisconnectButton->setPos(_storageDisconnectButton->getRelX(), disconnectHintY + downloadButtonY - downloadHintY); + } else { + if (_storageDisconnectHint) _storageDisconnectHint->setPos(_storageDisconnectHint->getRelX(), downloadHintY); + if (_storageDisconnectButton)_storageDisconnectButton->setPos(_storageDisconnectButton->getRelX(), downloadButtonY); + } + + if (!shownConnectedInfo) { + bool connecting = _connectingStorage; + if (_storageWizardNotConnectedHint) _storageWizardNotConnectedHint->setVisible(shown); + if (_storageWizardOpenLinkHint) _storageWizardOpenLinkHint->setVisible(shown); + if (_storageWizardLink) { + _storageWizardLink->setVisible(shown); + _storageWizardLink->setEnabled(g_system->hasFeature(OSystem::kFeatureOpenUrl) && !connecting); + } + if (_storageWizardCodeHint) _storageWizardCodeHint->setVisible(shown); + if (_storageWizardCodeBox) { + _storageWizardCodeBox->setVisible(shown); + _storageWizardCodeBox->setEnabled(!connecting); + } + if (_storageWizardPasteButton) { + _storageWizardPasteButton->setVisible(shown && g_system->hasFeature(OSystem::kFeatureClipboardSupport)); + _storageWizardPasteButton->setEnabled(!connecting); + } + if (_storageWizardConnectButton) { + _storageWizardConnectButton->setVisible(shown); + _storageWizardConnectButton->setEnabled(!connecting); + } + if (_storageWizardConnectionStatusHint) { + _storageWizardConnectionStatusHint->setVisible(shown && _storageWizardConnectionStatusHint->getLabel() != "..."); + _storageWizardConnectionStatusHint->setEnabled(!connecting); + } + + int16 x2, y2; + uint16 w2, h2; + int16 shiftUp; + if (!g_gui.xmlEval()->getWidgetData("GlobalOptions_Cloud_Container.StorageUsernameDesc", x2, y2, w2, h2)) + warning("GlobalOptions_Cloud_Container.StorageUsernameDesc's position is undefined"); + shiftUp = y2; + if (!g_gui.xmlEval()->getWidgetData("GlobalOptions_Cloud_Container.StorageWizardNotConnectedHint", x2, y2, w2, h2)) + warning("GlobalOptions_Cloud_Container.StorageWizardNotConnectedHint's position is undefined"); + shiftUp = y2 - shiftUp; + + shiftWidget(_storageWizardNotConnectedHint, "GlobalOptions_Cloud_Container.StorageWizardNotConnectedHint", 0, -shiftUp); + shiftWidget(_storageWizardOpenLinkHint, "GlobalOptions_Cloud_Container.StorageWizardOpenLinkHint", 0, -shiftUp); + shiftWidget(_storageWizardLink, "GlobalOptions_Cloud_Container.StorageWizardLink", 0, -shiftUp); + shiftWidget(_storageWizardCodeHint, "GlobalOptions_Cloud_Container.StorageWizardCodeHint", 0, -shiftUp); + shiftWidget(_storageWizardCodeBox, "GlobalOptions_Cloud_Container.StorageWizardCodeBox", 0, -shiftUp); + shiftWidget(_storageWizardPasteButton, "GlobalOptions_Cloud_Container.StorageWizardPasteButton", 0, -shiftUp); + shiftWidget(_storageWizardConnectButton, "GlobalOptions_Cloud_Container.StorageWizardConnectButton", 0, -shiftUp); + shiftWidget(_storageWizardConnectionStatusHint, "GlobalOptions_Cloud_Container.StorageWizardConnectionStatusHint", 0, -shiftUp); + } + + if (!shown) + serverLabelPosition = (_storageUsernameDesc ? _storageUsernameDesc->getRelY() : 0); + else { + if (shownConnectedInfo) + serverLabelPosition = (_storageDisconnectButton ? _storageDisconnectButton->getRelY() + _storageDisconnectButton->getHeight() + 16 : 0); + else + serverLabelPosition = (_storageWizardConnectButton ? _storageWizardConnectButton->getRelY() + _storageWizardConnectButton->getHeight() + 16 : 0); + } } - if (_storageConnectButton) - _storageConnectButton->setVisible(shown); - if (_storageRefreshButton) - _storageRefreshButton->setVisible(shown && _selectedStorageIndex == CloudMan.getStorageIndex()); - if (_storageDownloadButton) - _storageDownloadButton->setVisible(shown && _selectedStorageIndex == CloudMan.getStorageIndex()); - if (!shown) - serverLabelPosition = (_storageUsernameDesc ? _storageUsernameDesc->getRelY() : 0); #else // USE_LIBCURL _selectedStorageIndex = 0; @@ -2387,10 +2584,10 @@ void GlobalOptionsDialog::setupCloudTab() { _storageLastSyncDesc->setVisible(false); if (_storageLastSync) _storageLastSync->setVisible(false); - if (_storageConnectButton) - _storageConnectButton->setVisible(false); - if (_storageRefreshButton) - _storageRefreshButton->setVisible(false); + if (_storageDisconnectButton) + _storageDisconnectButton->setVisible(false); + if (_storageSyncSavesButton) + _storageSyncSavesButton->setVisible(false); if (_storageDownloadButton) _storageDownloadButton->setVisible(false); @@ -2504,23 +2701,51 @@ void GlobalOptionsDialog::setupCloudTab() { if (_serverPortClearButton) _serverPortClearButton->setVisible(false); #endif // USE_SDL_NET + + // temporary hide all local server-related info to see how Cloud looks without it + /* + if (_runServerButton) + _runServerButton->setVisible(false); + if (_serverInfoLabel) { + _serverInfoLabel->setPos(_serverInfoLabel->getRelX(), serverLabelPosition); + _serverInfoLabel->setVisible(false); + } + if (_rootPathButton) + _rootPathButton->setVisible(false); + if (_rootPath) + _rootPath->setVisible(false); + if (_rootPathClearButton) + _rootPathClearButton->setVisible(false); + if (_serverPortDesc) + _serverPortDesc->setVisible(false); + if (_serverPort) + _serverPort->setVisible(false); + if (_serverPortClearButton) + _serverPortClearButton->setVisible(false); + */ } #ifdef USE_LIBCURL -void GlobalOptionsDialog::storageInfoCallback(Cloud::Storage::StorageInfoResponse response) { - //we could've used response.value.email() - //but Storage already notified CloudMan - //so we just set the flag to redraw our cloud tab +void GlobalOptionsDialog::storageConnectionCallback(Networking::ErrorResponse response) { + Common::String message = "..."; + if (!response.failed && !response.interrupted) { + // success + g_system->displayMessageOnOSD(_("Storage connected.")); + } else { + message = _("Failed to connect storage."); + if (response.failed) { + message = Common::String(_("Failed to connect storage: ")) + _(response.response.c_str()); + } + } + + if (_storageWizardConnectionStatusHint) + _storageWizardConnectionStatusHint->setLabel(message); + _redrawCloudTab = true; + _connectingStorage = false; } -void GlobalOptionsDialog::storageListDirectoryCallback(Cloud::Storage::ListDirectoryResponse response) { - Common::Array &files = response.value; - uint64 totalSize = 0; - for (uint32 i = 0; i < files.size(); ++i) - if (!files[i].isDirectory()) - totalSize += files[i].size(); - CloudMan.setStorageUsedSpace(CloudMan.getStorageIndex(), totalSize); +void GlobalOptionsDialog::storageSavesSyncedCallback(Cloud::Storage::BoolResponse response) { _redrawCloudTab = true; } diff --git a/gui/options.h b/gui/options.h index ad9cb2aed9..13983c1657 100644 --- a/gui/options.h +++ b/gui/options.h @@ -301,11 +301,25 @@ protected: StaticTextWidget *_storageUsername; StaticTextWidget *_storageUsedSpaceDesc; StaticTextWidget *_storageUsedSpace; + StaticTextWidget *_storageSyncHint; StaticTextWidget *_storageLastSyncDesc; StaticTextWidget *_storageLastSync; - ButtonWidget *_storageConnectButton; - ButtonWidget *_storageRefreshButton; + ButtonWidget *_storageSyncSavesButton; + StaticTextWidget *_storageDownloadHint; ButtonWidget *_storageDownloadButton; + StaticTextWidget *_storageDisconnectHint; + ButtonWidget *_storageDisconnectButton; + + bool _connectingStorage; + StaticTextWidget *_storageWizardNotConnectedHint; + StaticTextWidget *_storageWizardOpenLinkHint; + StaticTextWidget *_storageWizardLink; + StaticTextWidget *_storageWizardCodeHint; + EditTextWidget *_storageWizardCodeBox; + ButtonWidget *_storageWizardPasteButton; + ButtonWidget *_storageWizardConnectButton; + StaticTextWidget *_storageWizardConnectionStatusHint; + ButtonWidget *_runServerButton; StaticTextWidget *_serverInfoLabel; ButtonWidget *_rootPathButton; @@ -319,11 +333,12 @@ protected: bool _serverWasRunning; #endif + void shiftWidget(Widget *widget, const char *widgetName, int32 xOffset, int32 yOffset); void setupCloudTab(); #ifdef USE_LIBCURL - void storageInfoCallback(Cloud::Storage::StorageInfoResponse response); - void storageListDirectoryCallback(Cloud::Storage::ListDirectoryResponse response); + void storageConnectionCallback(Networking::ErrorResponse response); + void storageSavesSyncedCallback(Cloud::Storage::BoolResponse response); void storageErrorCallback(Networking::ErrorResponse response); #endif #endif // USE_CLOUD diff --git a/gui/storagewizarddialog.cpp b/gui/storagewizarddialog.cpp deleted file mode 100644 index b01d4422b8..0000000000 --- a/gui/storagewizarddialog.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "gui/storagewizarddialog.h" -#include "gui/gui-manager.h" -#include "gui/message.h" -#include "gui/widget.h" -#include "gui/widgets/edittext.h" -#include "gui/widgets/scrollcontainer.h" -#include "backends/cloud/cloudmanager.h" -#ifdef USE_SDL_NET -#include "backends/networking/sdl_net/localwebserver.h" -#endif -#include "common/translation.h" - -namespace GUI { - -enum { - kConnectCmd = 'Cnnt', - kCodeBoxCmd = 'CdBx', - kOpenUrlCmd = 'OpUr', - kPasteCodeCmd = 'PsCd', - kStorageWizardContainerReflowCmd = 'SWCr' -}; - -StorageWizardDialog::StorageWizardDialog(uint32 storageId): - Dialog("GlobalOptions_Cloud_ConnectionWizard"), _storageId(storageId), _close(false) { -#ifdef USE_SDL_NET - _stopServerOnClose = false; -#endif - _backgroundType = GUI::ThemeEngine::kDialogBackgroundPlain; - - ScrollContainerWidget *container = new ScrollContainerWidget(this, "GlobalOptions_Cloud_ConnectionWizard.Container", kStorageWizardContainerReflowCmd); - container->setTarget(this); - - Common::String headline = Common::String::format(_("%s Storage Connection Wizard"), CloudMan.listStorages()[_storageId].c_str()); - _headlineWidget = new StaticTextWidget(container, "GlobalOptions_Cloud_ConnectionWizard_Container.Headline", headline); - - _navigateLineWidget = new StaticTextWidget(container, "GlobalOptions_Cloud_ConnectionWizard_Container.NavigateLine", _("Navigate to the following URL:")); - _urlLineWidget = new StaticTextWidget(container, "GlobalOptions_Cloud_ConnectionWizard_Container.URLLine", getUrl()); - - _returnLine1 = new StaticTextWidget(container, "GlobalOptions_Cloud_ConnectionWizard_Container.ReturnLine1", _("Obtain the code from the storage, enter it")); - _returnLine2 = new StaticTextWidget(container, "GlobalOptions_Cloud_ConnectionWizard_Container.ReturnLine2", _("in the following field and press 'Connect':")); - _codeWidget = new EditTextWidget(container, "GlobalOptions_Cloud_ConnectionWizard_Container.CodeBox1", "", 0, kCodeBoxCmd); - _messageWidget = new StaticTextWidget(container, "GlobalOptions_Cloud_ConnectionWizard_Container.MessageLine", ""); - - // Buttons - _cancelWidget = new ButtonWidget(container, "GlobalOptions_Cloud_ConnectionWizard_Container.CancelButton", _("Cancel"), 0, kCloseCmd); - _openUrlWidget = new ButtonWidget(container, "GlobalOptions_Cloud_ConnectionWizard_Container.OpenUrlButton", _("Open URL"), 0, kOpenUrlCmd); - _pasteCodeWidget = new ButtonWidget(container, "GlobalOptions_Cloud_ConnectionWizard_Container.PasteCodeButton", _("Paste"), _("Pastes clipboard contents into fields"), kPasteCodeCmd); - _connectWidget = new ButtonWidget(container, "GlobalOptions_Cloud_ConnectionWizard_Container.ConnectButton", _("Connect"), 0, kConnectCmd); - - // Initialy the code is empty, so disable the connect button - _connectWidget->setEnabled(false); - - _picture = new GraphicsWidget(container, "GlobalOptions_Cloud_ConnectionWizard_Container.Picture"); -#ifndef DISABLE_FANCY_THEMES - if (g_gui.theme()->supportsImages()) { - _picture->useThemeTransparency(true); - switch (_storageId) { - case Cloud::kStorageDropboxId: - _picture->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageDropboxLogo)); - break; - case Cloud::kStorageOneDriveId: - _picture->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageOneDriveLogo)); - break; - case Cloud::kStorageGoogleDriveId: - _picture->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageGoogleDriveLogo)); - break; - case Cloud::kStorageBoxId: - _picture->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageBoxLogo)); - break; - } - } -#endif - - containerWidgetsReflow(); -} - -void StorageWizardDialog::open() { - Dialog::open(); - - if (CloudMan.isWorking()) { - bool doClose = true; - - MessageDialog alert(_("Another Storage is active. Do you want to interrupt it?"), _("Yes"), _("No")); - if (alert.runModal() == GUI::kMessageOK) { - if (CloudMan.isDownloading()) - CloudMan.cancelDownload(); - if (CloudMan.isSyncing()) - CloudMan.cancelSync(); - - // I believe it still would return `true` here, but just in case - if (CloudMan.isWorking()) { - MessageDialog alert2(_("Wait until current Storage finishes up and try again.")); - alert2.runModal(); - } else { - doClose = false; - } - } - - if (doClose) { - close(); - } - } -} - -void StorageWizardDialog::close() { - Dialog::close(); -} - -void StorageWizardDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { - switch (cmd) { - case kCodeBoxCmd: { - Common::String code = _codeWidget->getEditString(); - bool ok = (code.size() > 0); - _connectWidget->setEnabled(ok); - _messageWidget->setLabel(""); - break; - } - case kOpenUrlCmd: { - if (!g_system->openUrl(getUrl())) { - MessageDialog alert(_("Failed to open URL!\nPlease navigate to this page manually.")); - alert.runModal(); - } - break; - } - case kPasteCodeCmd: { - if (g_system->hasTextInClipboard()) { - Common::String message = g_system->getTextFromClipboard(); - if (!message.empty()) { - _codeWidget->setEditString(message); - } - handleCommand(sender, kCodeBoxCmd, data); - g_gui.scheduleTopDialogRedraw(); - } - break; - } - case kConnectCmd: { - Common::String code = _codeWidget->getEditString(); - if (code.size() == 0) - return; - - CloudMan.connectStorage(_storageId, code); - setResult(1); - close(); - break; - } -#ifdef USE_SDL_NET - case kStorageCodePassedCmd: - CloudMan.connectStorage(_storageId, LocalServer.indexPageHandler().code()); - _close = true; - break; -#endif - case kStorageWizardContainerReflowCmd: - containerWidgetsReflow(); - break; - default: - Dialog::handleCommand(sender, cmd, data); - } -} - -void StorageWizardDialog::handleTickle() { - if (_close) { - setResult(1); - close(); - } - - Dialog::handleTickle(); -} - -void StorageWizardDialog::containerWidgetsReflow() { - // contents - if (_headlineWidget) _headlineWidget->setVisible(true); - if (_navigateLineWidget) _navigateLineWidget->setVisible(true); - if (_urlLineWidget) _urlLineWidget->setVisible(true); - if (_returnLine1) _returnLine1->setVisible(true); - if (_returnLine2) _returnLine2->setVisible(true); - - _codeWidget->setVisible(true); - _messageWidget->setVisible(true); - - // left column / first bottom row - if (_picture) { - _picture->setVisible(g_system->getOverlayWidth() > 320); - } - if (_openUrlWidget) { - bool visible = g_system->hasFeature(OSystem::kFeatureOpenUrl); - _openUrlWidget->setVisible(visible); - } - if (_pasteCodeWidget) { - bool visible = g_system->hasFeature(OSystem::kFeatureClipboardSupport); - _pasteCodeWidget->setVisible(visible); - } - - // bottom row - if (_cancelWidget) _cancelWidget->setVisible(true); - if (_connectWidget) _connectWidget->setVisible(true); -} - -Common::String StorageWizardDialog::getUrl() const { - return "https://cloud.scummvm.org/"; -} - -} // End of namespace GUI diff --git a/gui/storagewizarddialog.h b/gui/storagewizarddialog.h deleted file mode 100644 index ede37505ee..0000000000 --- a/gui/storagewizarddialog.h +++ /dev/null @@ -1,83 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#ifndef GUI_STORAGEWIZARDDIALOG_H -#define GUI_STORAGEWIZARDDIALOG_H - -#include "gui/dialog.h" -#include "common/str.h" - -namespace GUI { - -class CommandSender; -class EditTextWidget; -class StaticTextWidget; -class ButtonWidget; -class GraphicsWidget; - -#ifdef USE_SDL_NET -enum StorageWizardDialogCommands { - kStorageCodePassedCmd = 'SWDC' -}; -#endif - -class StorageWizardDialog : public Dialog { - uint32 _storageId; - - StaticTextWidget *_headlineWidget; - StaticTextWidget *_navigateLineWidget; - StaticTextWidget *_urlLineWidget; - StaticTextWidget *_returnLine1; - StaticTextWidget *_returnLine2; - EditTextWidget *_codeWidget; - StaticTextWidget *_messageWidget; - - GraphicsWidget *_picture; - ButtonWidget *_openUrlWidget; - ButtonWidget *_pasteCodeWidget; - - ButtonWidget *_cancelWidget; - ButtonWidget *_connectWidget; - - bool _close; -#ifdef USE_SDL_NET - bool _stopServerOnClose; -#endif - - /** Hides/shows widgets for Container to work with them correctly. */ - void containerWidgetsReflow(); - - /** Return short scummvm.org URL for user to navigate to. */ - Common::String getUrl() const; - -public: - StorageWizardDialog(uint32 storageId); - - virtual void open(); - virtual void close(); - virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); - virtual void handleTickle(); -}; - -} // End of namespace GUI - -#endif diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip index 6bd0fc9522..78229c36c1 100644 Binary files a/gui/themes/scummclassic.zip and b/gui/themes/scummclassic.zip differ diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx index c92c4d1718..3929af9e81 100644 --- a/gui/themes/scummclassic/classic_layout.stx +++ b/gui/themes/scummclassic/classic_layout.stx @@ -58,6 +58,12 @@ + + + @@ -602,49 +611,126 @@ + + + + + + + + - - + + + + + + + + - - + + + + + + + + + - - + + + + - + + + + + + + + - + + + + + + + + + + - - + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + @@ -605,58 +614,128 @@ - + + + + + + + + + - - + + + + + + + + - - + + + + + + + + + - - + + + + - + + + + + + + + - + + + + + + + + + + - - + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx index d6c927c251..b1d4e28015 100644 --- a/gui/themes/scummmodern/scummmodern_layout.stx +++ b/gui/themes/scummmodern/scummmodern_layout.stx @@ -65,10 +65,19 @@ + + + + + + + + + + + - - + + + + + + + + - - + + + + + + + + + - - + + + + - + + + + + + + + - + + + + + + + + + + - - + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + @@ -603,58 +612,128 @@ - + + + + + + + + + - - + + + + + + + + - - + + + + + + + + + - - + + + + - + + + + + + + + - + + + + + + + + + + - - + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/gui/themes/scummremastered/remastered_layout.stx b/gui/themes/scummremastered/remastered_layout.stx index d6c927c251..b1d4e28015 100644 --- a/gui/themes/scummremastered/remastered_layout.stx +++ b/gui/themes/scummremastered/remastered_layout.stx @@ -65,10 +65,19 @@ + + + + + + + + + + + - - + + + + + + + + - - + + + + + + + + + - - + + + + - + + + + + + + + - + + + + + + + + + + - - + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + @@ -603,58 +612,128 @@ - + + + + + + + + + - - + + + + + + + + - - + + + + + + + + + - - + + + + - + + + + + + + + - + + + + + + + + + + - - + + + + + + + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - h - _limitH) _scrolledY = 0; _verticalScroll->_numEntries = h; _verticalScroll->_currentPos = _scrolledY; -- cgit v1.2.3