[Scummvm-git-logs] scummvm master -> 722288474f3fc279fa0dd2d5a1a31ea4cb5b383e

sev- noreply at scummvm.org
Thu Nov 18 21:56:01 UTC 2021


This automated email contains information about 18 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
cf1b6c5eb6 BACKENDS: NETWORKING: Add session.cpp to compilation
a89cb7f85e BACKENDS: NETWORKING: Added binary mode to SessionRequest
768cac42f9 BACKENDS: NETWORKING: Make SessionRequest correctly process HTTP error codes
d8829fa4fd GUI: Initial code for Update Icons dialog
c82b1f88bc GUI: Properly check gui-icons.dat in themepath
ea10ec1c71 GUI: Compute the required icon packs download
65020829fc BACKENDS: CLOUD: Fix overridden methods
192b05930a COMMON: Mark human-readable bytes as translatable
f23e41d346 GUI: Better error handling in icons downloader
06f917cc6f GUI: Initial work on icon packs downloading. Streamlined the process.
cec059e5bf GUI: Persist Download Icons dialog
db7cec6935 CLOUD: SessionRequest now can save downloaded files to disk
570c77f309 GUI: Fixed progress bar in icons downloader
5df691a3a6 BACKENDS: NETWORKING: Properly signal end of downloaded file
4e32936376 GUI: Calculate download speed in Icons downloader
1507559a66 BACKENDS: NETWORKING: Fix local file downloading when stream is reused
8fc89ec10f GUI: Fix multiple icon packs downloading. We cannot fire all the requests at once
722288474f GUI: Synced all themes with Icons Downloader and bumped theme version


Commit: cf1b6c5eb6876e4f0983bcc69737c710c4c87bfe
    https://github.com/scummvm/scummvm/commit/cf1b6c5eb6876e4f0983bcc69737c710c4c87bfe
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:42+01:00

Commit Message:
BACKENDS: NETWORKING: Add session.cpp to compilation

Changed paths:
    backends/module.mk


diff --git a/backends/module.mk b/backends/module.mk
index c84334cfb9..e61c1d0b93 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -75,8 +75,9 @@ MODULE_OBJS += \
 	networking/curl/curlrequest.o \
 	networking/curl/curljsonrequest.o \
 	networking/curl/postrequest.o \
-	networking/curl/sessionrequest.o \
-	networking/curl/request.o
+	networking/curl/request.o \
+	networking/curl/session.o \
+	networking/curl/sessionrequest.o
 endif
 
 ifdef USE_SDL_NET


Commit: a89cb7f85eeb9ecd0215a0e811851750a0183a8a
    https://github.com/scummvm/scummvm/commit/a89cb7f85eeb9ecd0215a0e811851750a0183a8a
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:42+01:00

Commit Message:
BACKENDS: NETWORKING: Added binary mode to SessionRequest

Changed paths:
    backends/networking/curl/session.cpp
    backends/networking/curl/session.h
    backends/networking/curl/sessionrequest.cpp
    backends/networking/curl/sessionrequest.h


diff --git a/backends/networking/curl/session.cpp b/backends/networking/curl/session.cpp
index 260f6d85c8..958ede8c7b 100644
--- a/backends/networking/curl/session.cpp
+++ b/backends/networking/curl/session.cpp
@@ -33,7 +33,7 @@ Session::~Session() {
 	close();
 }
 
-SessionRequest *Session::get(Common::String url, DataCallback cb, ErrorCallback ecb) {
+SessionRequest *Session::get(Common::String url, DataCallback cb, ErrorCallback ecb, bool binary) {
 	// check url prefix
 	if (!_prefix.empty()) {
 		if (url.contains("://")) {
@@ -60,7 +60,7 @@ SessionRequest *Session::get(Common::String url, DataCallback cb, ErrorCallback
 	}
 
 	if (!_request) {
-		_request = new Networking::SessionRequest(url, cb, ecb); // automatically added to ConnMan
+		_request = new Networking::SessionRequest(url, cb, ecb, binary); // automatically added to ConnMan
 		_request->connectionKeepAlive();
 	} else {
 		_request->reuse(url, cb, ecb);
diff --git a/backends/networking/curl/session.h b/backends/networking/curl/session.h
index d3aa5807a7..c3e82ff63f 100644
--- a/backends/networking/curl/session.h
+++ b/backends/networking/curl/session.h
@@ -36,7 +36,7 @@ public:
 	Session(Common::String prefix = "");
 	~Session();
 
-	SessionRequest *get(Common::String url, DataCallback cb = nullptr, ErrorCallback ecb = nullptr);
+	SessionRequest *get(Common::String url, DataCallback cb = nullptr, ErrorCallback ecb = nullptr, bool binary = false);
 	void close();
 };
 
diff --git a/backends/networking/curl/sessionrequest.cpp b/backends/networking/curl/sessionrequest.cpp
index 368fd3bc36..dac4e64e8a 100644
--- a/backends/networking/curl/sessionrequest.cpp
+++ b/backends/networking/curl/sessionrequest.cpp
@@ -31,10 +31,10 @@
 
 namespace Networking {
 
-SessionRequest::SessionRequest(Common::String url, DataCallback cb, ErrorCallback ecb):
+SessionRequest::SessionRequest(Common::String url, DataCallback cb, ErrorCallback ecb, bool binary):
 	CurlRequest(cb, ecb, url), _contentsStream(DisposeAfterUse::YES),
 	_buffer(new byte[CURL_SESSION_REQUEST_BUFFER_SIZE]), _text(nullptr),
-	_started(false), _complete(false), _success(false) {
+	_started(false), _complete(false), _success(false), _binary(binary) {
 
 	// automatically go under ConnMan control so nobody would be able to leak the memory
 	// but, we don't need it to be working just yet
@@ -165,6 +165,9 @@ bool SessionRequest::success() {
 }
 
 char *SessionRequest::text() {
+	if (_binary)
+		return nullptr;
+
 	if (_text == nullptr)
 		_text = getPreparedContents();
 	return _text;
diff --git a/backends/networking/curl/sessionrequest.h b/backends/networking/curl/sessionrequest.h
index 53f5fd447b..41d3c84394 100644
--- a/backends/networking/curl/sessionrequest.h
+++ b/backends/networking/curl/sessionrequest.h
@@ -37,6 +37,7 @@ protected:
 	byte *_buffer;
 	char *_text;
 	bool _started, _complete, _success;
+	bool _binary;
 
 	bool reuseStream();
 
@@ -47,7 +48,7 @@ protected:
 	virtual void finishSuccess();
 
 public:
-	SessionRequest(Common::String url, DataCallback cb = nullptr, ErrorCallback ecb = nullptr);
+	SessionRequest(Common::String url, DataCallback cb = nullptr, ErrorCallback ecb = nullptr, bool binary = false);
 	virtual ~SessionRequest();
 
 	void start();
@@ -66,6 +67,10 @@ public:
 
 	char *text();
 	Common::JSONValue *json();
+
+	byte *getData() { return _contentsStream.getData(); }
+	uint32 getSize() { return _contentsStream.size(); }
+
 };
 
 } // End of namespace Networking


Commit: 768cac42f90197e59bc62f6dc317b4f5c2daee2b
    https://github.com/scummvm/scummvm/commit/768cac42f90197e59bc62f6dc317b4f5c2daee2b
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:42+01:00

Commit Message:
BACKENDS: NETWORKING: Make SessionRequest correctly process HTTP error codes

Changed paths:
    backends/networking/curl/request.cpp
    backends/networking/curl/request.h
    backends/networking/curl/sessionrequest.cpp
    backends/networking/curl/sessionrequest.h


diff --git a/backends/networking/curl/request.cpp b/backends/networking/curl/request.cpp
index b8393f7138..a9fed2a9bf 100644
--- a/backends/networking/curl/request.cpp
+++ b/backends/networking/curl/request.cpp
@@ -63,8 +63,8 @@ RequestState Request::state() const { return _state; }
 
 Common::String Request::date() const { return ""; }
 
-void Request::finishError(ErrorResponse error) {
-	_state = FINISHED;
+void Request::finishError(ErrorResponse error, RequestState state) {
+	_state = state;
 	if (_errorCallback)
 		(*_errorCallback)(error);
 }
diff --git a/backends/networking/curl/request.h b/backends/networking/curl/request.h
index efddd15075..3502920e33 100644
--- a/backends/networking/curl/request.h
+++ b/backends/networking/curl/request.h
@@ -149,7 +149,7 @@ protected:
 	uint32 _retryInSeconds;
 
 	/** Sets FINISHED state and calls the _errorCallback with given error. */
-	virtual void finishError(ErrorResponse error);
+	virtual void finishError(ErrorResponse error, RequestState state = FINISHED);
 
 	/** Sets FINISHED state. Implementations might extend it if needed. */
 	virtual void finishSuccess();
diff --git a/backends/networking/curl/sessionrequest.cpp b/backends/networking/curl/sessionrequest.cpp
index dac4e64e8a..c394309386 100644
--- a/backends/networking/curl/sessionrequest.cpp
+++ b/backends/networking/curl/sessionrequest.cpp
@@ -75,10 +75,10 @@ char *SessionRequest::getPreparedContents() {
 	return (char *)result;
 }
 
-void SessionRequest::finishError(ErrorResponse error) {
+void SessionRequest::finishError(ErrorResponse error, RequestState state) {
 	_complete = true;
 	_success = false;
-	CurlRequest::finishError(error);
+	CurlRequest::finishError(error, PAUSED);
 }
 
 void SessionRequest::finishSuccess() {
@@ -120,6 +120,12 @@ void SessionRequest::handle() {
 	if (!_stream) _stream = makeStream();
 
 	if (_stream) {
+		if (_stream->httpResponseCode() != 200 && _stream->httpResponseCode() != 0) {
+			warning("SessionRequest: HTTP response code is not 200 OK (it's %ld)", _stream->httpResponseCode());
+			ErrorResponse error(this, false, true, "HTTP response code is not 200 OK", _stream->httpResponseCode());
+			finishError(error);
+			return;
+		}
 		uint32 readBytes = _stream->read(_buffer, CURL_SESSION_REQUEST_BUFFER_SIZE);
 		if (readBytes != 0)
 			if (_contentsStream.write(_buffer, readBytes) != readBytes)
diff --git a/backends/networking/curl/sessionrequest.h b/backends/networking/curl/sessionrequest.h
index 41d3c84394..d3a1eca816 100644
--- a/backends/networking/curl/sessionrequest.h
+++ b/backends/networking/curl/sessionrequest.h
@@ -44,7 +44,7 @@ protected:
 	/** Prepares raw bytes from _contentsStream. */
 	char *getPreparedContents();
 
-	virtual void finishError(ErrorResponse error);
+	virtual void finishError(ErrorResponse error, RequestState state = PAUSED);
 	virtual void finishSuccess();
 
 public:


Commit: d8829fa4fd265ab46507a3067e93185a1adb7949
    https://github.com/scummvm/scummvm/commit/d8829fa4fd265ab46507a3067e93185a1adb7949
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:42+01:00

Commit Message:
GUI: Initial code for Update Icons dialog

- LIST downloading and parsing is done

Changed paths:
  A gui/downloadiconsdialog.cpp
  A gui/downloadiconsdialog.h
    gui/module.mk
    gui/options.cpp
    gui/themes/scummmodern.zip
    gui/themes/scummremastered.zip
    gui/themes/scummremastered/remastered_layout.stx
    gui/themes/scummremastered/remastered_layout_lowres.stx


diff --git a/gui/downloadiconsdialog.cpp b/gui/downloadiconsdialog.cpp
new file mode 100644
index 0000000000..ee7d7f1ff7
--- /dev/null
+++ b/gui/downloadiconsdialog.cpp
@@ -0,0 +1,209 @@
+/* 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 "backends/cloud/cloudmanager.h"
+#include "gui/downloadiconsdialog.h"
+#include "gui/downloaddialog.h"
+#include "backends/networking/curl/session.h"
+#include "common/config-manager.h"
+#include "common/translation.h"
+#include "common/util.h"
+#include "engines/metaengine.h"
+#include "gui/browser.h"
+#include "gui/chooser.h"
+#include "gui/editgamedialog.h"
+#include "gui/gui-manager.h"
+#include "gui/launcher.h"
+#include "gui/message.h"
+#include "gui/remotebrowser.h"
+#include "gui/widgets/edittext.h"
+#include "gui/widgets/list.h"
+
+namespace GUI {
+
+enum {
+	kDownloadIconsDialogButtonCmd = 'Dldb',
+	kListEndedCmd = 'DLLE'
+};
+
+static DownloadIconsDialog *g_dialog;
+
+DownloadIconsDialog::DownloadIconsDialog() :
+	Dialog("GlobalOptions_DownloadIconsDialog"), CommandSender(this), _close(false) {
+	g_dialog = this;
+
+	_backgroundType = GUI::ThemeEngine::kDialogBackgroundPlain;
+
+	uint32 progress = (uint32)(100 * CloudMan.getDownloadingProgress());
+	_progressBar = new SliderWidget(this, "GlobalOptions_DownloadIconsDialog.ProgressBar");
+	_progressBar->setMinValue(0);
+	_progressBar->setMaxValue(100);
+	_progressBar->setValue(progress);
+	_progressBar->setEnabled(false);
+	_percentLabel = new StaticTextWidget(this, "GlobalOptions_DownloadIconsDialog.PercentText", Common::String::format("%u %%", progress));
+	_downloadSizeLabel = new StaticTextWidget(this, "GlobalOptions_DownloadIconsDialog.DownloadSize", Common::U32String());
+	_downloadSpeedLabel = new StaticTextWidget(this, "GlobalOptions_DownloadIconsDialog.DownloadSpeed", Common::U32String());
+	if (g_system->getOverlayWidth() > 320)
+		_cancelButton = new ButtonWidget(this, "GlobalOptions_DownloadIconsDialog.MainButton", _("Cancel download"), Common::U32String(), kDownloadIconsDialogButtonCmd);
+	else
+		_cancelButton = new ButtonWidget(this, "GlobalOptions_DownloadIconsDialog.MainButton", _c("Cancel download", "lowres"), Common::U32String(), kDownloadIconsDialogButtonCmd);
+
+	_closeButton = new ButtonWidget(this, "GlobalOptions_DownloadIconsDialog.CloseButton", _("Hide"), Common::U32String(), kCloseCmd);
+	refreshWidgets();
+
+	CloudMan.setDownloadTarget(this);
+
+	_session = new Networking::Session();
+
+	downloadList();
+}
+
+DownloadIconsDialog::~DownloadIconsDialog() {
+	CloudMan.setDownloadTarget(nullptr);
+
+	_session->close();
+	delete _session;
+}
+
+void DownloadIconsDialog::open() {
+	Dialog::open();
+	reflowLayout();
+	g_gui.scheduleTopDialogRedraw();
+}
+
+void DownloadIconsDialog::close() {
+	CloudMan.setDownloadTarget(nullptr);
+	Dialog::close();
+}
+
+void DownloadIconsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
+	warning("CMD is: %s", tag2str(cmd));
+	switch (cmd) {
+	case kDownloadIconsDialogButtonCmd:
+		{
+			CloudMan.setDownloadTarget(nullptr);
+			CloudMan.cancelDownload();
+			close();
+			break;
+		}
+	case kDownloadProgressCmd:
+		if (!_close) {
+			refreshWidgets();
+			g_gui.scheduleTopDialogRedraw();
+		}
+		break;
+	case kDownloadEndedCmd:
+		_close = true;
+		break;
+	case kListEndedCmd:
+		warning("List download ended");
+		break;
+	default:
+		Dialog::handleCommand(sender, cmd, data);
+	}
+}
+
+void DownloadIconsDialog::handleTickle() {
+	if (_close) {
+		close();
+		_close = false;
+		return;
+	}
+
+	int32 progress = (int32)(100 * CloudMan.getDownloadingProgress());
+	if (_progressBar->getValue() != progress) {
+		refreshWidgets();
+		g_gui.scheduleTopDialogRedraw();
+	}
+
+	Dialog::handleTickle();
+}
+
+void DownloadIconsDialog::reflowLayout() {
+	Dialog::reflowLayout();
+	refreshWidgets();
+}
+
+Common::U32String DownloadIconsDialog::getSizeLabelText() {
+	Common::String downloaded, downloadedUnits, total, totalUnits;
+	downloaded = getHumanReadableBytes(CloudMan.getDownloadBytesNumber(), downloadedUnits);
+	total = getHumanReadableBytes(CloudMan.getDownloadTotalBytesNumber(), totalUnits);
+	return Common::U32String::format(_("Downloaded %s %S / %s %S"), downloaded.c_str(), _(downloadedUnits).c_str(), total.c_str(), _(totalUnits).c_str());
+}
+
+Common::U32String DownloadIconsDialog::getSpeedLabelText() {
+	Common::String speed, speedUnits;
+	speed = getHumanReadableBytes(CloudMan.getDownloadSpeed(), speedUnits);
+	speedUnits += "/s";
+	return Common::U32String::format(_("Download speed: %s %S"), speed.c_str(), _(speedUnits).c_str());
+}
+
+void DownloadIconsDialog::refreshWidgets() {
+	uint32 progress = (uint32)(100 * CloudMan.getDownloadingProgress());
+	_percentLabel->setLabel(Common::String::format("%u %%", progress));
+	_downloadSizeLabel->setLabel(getSizeLabelText());
+	_downloadSpeedLabel->setLabel(getSpeedLabelText());
+	_progressBar->setValue(progress);
+}
+
+void DownloadIconsDialog::downloadListCallback(Networking::DataResponse response) {
+	Networking::SessionRequest *req = dynamic_cast<Networking::SessionRequest *>(response.request);
+
+	Common::MemoryReadStream stream(req->getData(), req->getSize());
+
+	int nline = 0;
+
+	while (!stream.eos()) {
+		Common::String s = stream.readString('\n');
+
+		nline++;
+
+		if (s.empty())
+			continue;
+
+		size_t pos = s.findFirstOf(',');
+
+		if (pos == Common::String::npos) {
+			warning("DownloadIconsDialog: wrong string format at line %d: <%s>", nline, s.c_str());
+			continue;
+		}
+
+		g_dialog->_fileHash.setVal(s.substr(0, pos), atol(s.substr(pos + 1).c_str()));
+	}
+
+	sendCommand(kListEndedCmd, 0);
+}
+
+void DownloadIconsDialog::errorCallback(Networking::ErrorResponse error) {
+	warning("Error %ld: %s", error.httpResponseCode, error.response.c_str());
+}
+
+void DownloadIconsDialog::downloadList() {
+	Networking::SessionRequest *rq = _session->get("https://downloads.scummvm.org/frs/icons/LIST",
+		new Common::Callback<DownloadIconsDialog, Networking::DataResponse>(this, &DownloadIconsDialog::downloadListCallback),
+		new Common::Callback<DownloadIconsDialog, Networking::ErrorResponse>(this, &DownloadIconsDialog::errorCallback),
+		true);
+
+	rq->start();
+}
+
+} // End of namespace GUI
diff --git a/gui/downloadiconsdialog.h b/gui/downloadiconsdialog.h
new file mode 100644
index 0000000000..1903fea2f5
--- /dev/null
+++ b/gui/downloadiconsdialog.h
@@ -0,0 +1,80 @@
+/* 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_DOWNLOADICONSDIALOG_H
+#define GUI_DOWNLOADICONSDIALOG_H
+
+#include "gui/dialog.h"
+#include "common/str.h"
+#include "common/ustr.h"
+
+namespace Networking {
+class Session;
+};
+
+namespace GUI {
+class CommandSender;
+class StaticTextWidget;
+class ButtonWidget;
+class SliderWidget;
+
+class DownloadIconsDialog : public Dialog, public CommandSender {
+	StaticTextWidget *_percentLabel;
+	StaticTextWidget *_downloadSizeLabel;
+	StaticTextWidget *_downloadSpeedLabel;
+	SliderWidget *_progressBar;
+	ButtonWidget *_cancelButton;
+	ButtonWidget *_closeButton;
+
+	Common::String _localDirectory;
+	bool _close;
+
+	Common::U32String getSizeLabelText();
+	Common::U32String getSpeedLabelText();
+
+	void refreshWidgets();
+
+	Networking::Session *_session;
+
+public:
+	Common::HashMap<Common::String, uint32> _fileHash;
+
+public:
+	DownloadIconsDialog();
+	~DownloadIconsDialog() override;
+
+	void open() override;
+	void close() override;
+	void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) override;
+	void handleTickle() override;
+	void reflowLayout() override;
+
+	void downloadListCallback(Networking::DataResponse response);
+	void errorCallback(Networking::ErrorResponse error);
+
+private:
+	void downloadList();
+};
+
+} // End of namespace GUI
+
+#endif
diff --git a/gui/module.mk b/gui/module.mk
index 7c6f85a2eb..a4a87c4f88 100644
--- a/gui/module.mk
+++ b/gui/module.mk
@@ -46,6 +46,7 @@ ifdef USE_CLOUD
 ifdef USE_LIBCURL
 MODULE_OBJS += \
 	downloaddialog.o \
+	downloadiconsdialog.o \
 	remotebrowser.o
 endif
 endif
diff --git a/gui/options.cpp b/gui/options.cpp
index 5d89ab1fd2..92ec744d0d 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -57,6 +57,7 @@
 #ifdef USE_LIBCURL
 #include "backends/cloud/cloudmanager.h"
 #include "gui/downloaddialog.h"
+#include "gui/downloadiconsdialog.h"
 #endif
 
 #ifdef USE_SDL_NET
@@ -91,6 +92,7 @@ enum {
 	kChoosePluginsDirCmd	= 'chpl',
 	kPluginsPathClearCmd	= 'clpl',
 	kChooseThemeCmd			= 'chtf',
+	kUpdateIconsCmd			= 'upic',
 	kUpdatesCheckCmd		= 'updc',
 	kKbdMouseSpeedChanged	= 'kmsc',
 	kJoystickDeadzoneChanged= 'jodc',
@@ -2414,6 +2416,12 @@ void GlobalOptionsDialog::addMiscControls(GuiObject *boss, const Common::String
 		new ButtonWidget(boss, prefix + "UpdatesCheckManuallyButton", _("Check now"), Common::U32String(), kUpdatesCheckCmd);
 	}
 #endif // USE_UPDATES
+
+#ifdef USE_CLOUD
+#ifdef USE_LIBCURL
+	new ButtonWidget(boss, prefix + "UpdateIconsButton", _("Update Icons"), Common::U32String(), kUpdateIconsCmd);
+#endif
+#endif
 }
 
 #ifdef USE_CLOUD
@@ -2691,7 +2699,7 @@ void GlobalOptionsDialog::apply() {
 #ifdef USE_UPDATES
 	if (g_system->getUpdateManager()) {
 		ConfMan.setInt("updates_check", _updatesPopUp->getSelectedTag());
-		
+
 		if (_updatesPopUp->getSelectedTag() == Common::UpdateManager::kUpdateIntervalNotSupported) {
 			g_system->getUpdateManager()->setAutomaticallyChecksForUpdates(Common::UpdateManager::kUpdateStateDisabled);
 		} else {
@@ -2932,6 +2940,16 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
 		}
 		break;
 	}
+
+	case kUpdateIconsCmd: {
+		DownloadIconsDialog dia;
+
+		if (dia.runModal() > 0) {
+			warning("Success");
+		}
+
+		break;
+	}
 #endif
 #endif
 	case kThemePathClearCmd:
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index 0b1664756e..bb3f02604b 100644
Binary files a/gui/themes/scummmodern.zip and b/gui/themes/scummmodern.zip differ
diff --git a/gui/themes/scummremastered.zip b/gui/themes/scummremastered.zip
index 64aeaa0941..e414e2b5c6 100644
Binary files a/gui/themes/scummremastered.zip and b/gui/themes/scummremastered.zip differ
diff --git a/gui/themes/scummremastered/remastered_layout.stx b/gui/themes/scummremastered/remastered_layout.stx
index ff40e83cbe..a0b9a8167b 100644
--- a/gui/themes/scummremastered/remastered_layout.stx
+++ b/gui/themes/scummremastered/remastered_layout.stx
@@ -816,6 +816,9 @@
 						type = 'Checkbox'
 				/>
 			</layout>
+			<widget name = 'UpdateIconsButton'
+					type = 'Button'
+			/>
 			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
 				<widget name = 'DiscordRpc'
 						type = 'Checkbox'
@@ -1020,6 +1023,35 @@
 		</layout>
 	</dialog>
 
+	<dialog name = 'GlobalOptions_DownloadIconsDialog' overlays = 'Dialog.GlobalOptions'>
+		<layout type = 'vertical' padding = '16, 16, 16, 8' spacing = '8'>
+			<widget name = 'ProgressBar'
+					height = 'Globals.Button.Height'
+			/>
+			<space size = '1'/>
+			<widget name = 'PercentText'
+					height = 'Globals.Line.Height'
+					textalign = 'center'
+			/>
+			<widget name = 'DownloadSize'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'DownloadSpeed'
+					height = 'Globals.Line.Height'
+			/>
+			<space/>
+			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'>
+				<widget name = 'MainButton'
+						type = 'Button'
+				/>
+				<space/>
+				<widget name = 'CloseButton'
+						type = 'Button'
+				/>
+			</layout>
+		</layout>
+	</dialog>
+
 	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions'>
 		<layout type = 'vertical' padding = '16, 16, 16, 8' spacing = '8'>
 			<widget name = 'RemoteDirectory'
diff --git a/gui/themes/scummremastered/remastered_layout_lowres.stx b/gui/themes/scummremastered/remastered_layout_lowres.stx
index fe37910c08..ae2f46992e 100644
--- a/gui/themes/scummremastered/remastered_layout_lowres.stx
+++ b/gui/themes/scummremastered/remastered_layout_lowres.stx
@@ -789,6 +789,9 @@
 						type = 'Checkbox'
 				/>
 			</layout>
+			<widget name = 'UpdateIconsButton'
+					type = 'Button'
+			/>
 			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
 				<widget name = 'DiscordRpc'
 						type = 'Checkbox'
@@ -998,6 +1001,35 @@
 		</layout>
 	</dialog>
 
+	<dialog name = 'GlobalOptions_DownloadIconsDialog' overlays = 'Dialog.GlobalOptions'>
+		<layout type = 'vertical' padding = '8, 8, 8, 4' spacing = '8'>
+			<widget name = 'ProgressBar'
+					height = 'Globals.Button.Height'
+			/>
+			<space size = '1'/>
+			<widget name = 'PercentText'
+					height = 'Globals.Line.Height'
+					textalign = 'center'
+			/>
+			<widget name = 'DownloadSize'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'DownloadSpeed'
+					height = 'Globals.Line.Height'
+			/>
+			<space/>
+			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6'>
+				<widget name = 'MainButton'
+						type = 'Button'
+				/>
+				<space/>
+				<widget name = 'CloseButton'
+						type = 'Button'
+				/>
+			</layout>
+		</layout>
+	</dialog>
+
 	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions'>
 		<layout type = 'vertical' padding = '8, 8, 8, 4' spacing = '8'>
 			<widget name = 'RemoteDirectory'


Commit: c82b1f88bce176cacc3585781483bb281e26e838
    https://github.com/scummvm/scummvm/commit/c82b1f88bce176cacc3585781483bb281e26e838
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:42+01:00

Commit Message:
GUI: Properly check gui-icons.dat in themepath

themepath is never added to SearchMan, thus File::open() does
not work for it

Changed paths:
    gui/gui-manager.cpp


diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index ca3810841b..1dac0da788 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -138,19 +138,25 @@ void GuiManager::initIconsSet() {
 	}
 
 	const char fname[] = "gui-icons.dat";
-	Common::String path;
 	Common::File *file = new Common::File;
 
-	if (ConfMan.hasKey("themepath"))
-		file->open(normalizePath(ConfMan.get("themepath") + "/" + fname, '/'));
+	if (ConfMan.hasKey("themepath")) {
+		Common::FSNode *fs = new Common::FSNode(normalizePath(ConfMan.get("themepath") + "/" + fname, '/'));
 
-	if (!file->isOpen() && ConfMan.hasKey("iconspath"))
+		if (!fs->exists()) {
+			delete fs;
+		} else {
+			dat = Common::makeZipArchive(*fs);
+		}
+	}
+
+	if (!dat && !file->isOpen() && ConfMan.hasKey("iconspath"))
 		file->open(normalizePath(ConfMan.get("iconspath") + "/" + fname, '/'));
 
-	if (!file->isOpen())
+	if (!dat && !file->isOpen())
 		file->open(fname);
 
-	if (file->isOpen())
+	if (!dat && file->isOpen())
 		dat = Common::makeZipArchive(file);
 
 	if (!dat) {
@@ -159,9 +165,9 @@ void GuiManager::initIconsSet() {
 		return;
 	}
 
-	_iconsSet.add(path, dat, 0, false); // Do not autofree
+	_iconsSet.add(fname, dat, 0, false); // Do not autofree
 
-	debug(2, "GUI: Loaded icon file: %s", path.c_str());
+	debug(2, "GUI: Loaded icon file: %s", fname);
 }
 
 void GuiManager::computeScaleFactor() {


Commit: ea10ec1c71bd7e0cb648bd370c0e842d814793ee
    https://github.com/scummvm/scummvm/commit/ea10ec1c71bd7e0cb648bd370c0e842d814793ee
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:42+01:00

Commit Message:
GUI: Compute the required icon packs download

Changed paths:
    gui/downloadiconsdialog.cpp
    gui/downloadiconsdialog.h
    gui/themes/scummremastered.zip
    gui/themes/scummremastered/remastered_layout.stx
    gui/themes/scummremastered/remastered_layout_lowres.stx
    po/POTFILES


diff --git a/gui/downloadiconsdialog.cpp b/gui/downloadiconsdialog.cpp
index ee7d7f1ff7..4b450c5a78 100644
--- a/gui/downloadiconsdialog.cpp
+++ b/gui/downloadiconsdialog.cpp
@@ -53,6 +53,9 @@ DownloadIconsDialog::DownloadIconsDialog() :
 
 	_backgroundType = GUI::ThemeEngine::kDialogBackgroundPlain;
 
+	_statusText = new StaticTextWidget(this, "GlobalOptions_DownloadIconsDialog.StatusText", _("Downloading icons list..."));
+	_errorText = new StaticTextWidget(this, "GlobalOptions_DownloadIconsDialog.ErrorText", Common::U32String(""));
+
 	uint32 progress = (uint32)(100 * CloudMan.getDownloadingProgress());
 	_progressBar = new SliderWidget(this, "GlobalOptions_DownloadIconsDialog.ProgressBar");
 	_progressBar->setMinValue(0);
@@ -96,7 +99,6 @@ void DownloadIconsDialog::close() {
 }
 
 void DownloadIconsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
-	warning("CMD is: %s", tag2str(cmd));
 	switch (cmd) {
 	case kDownloadIconsDialogButtonCmd:
 		{
@@ -115,7 +117,8 @@ void DownloadIconsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
 		_close = true;
 		break;
 	case kListEndedCmd:
-		warning("List download ended");
+		_statusText->setLabel(Common::U32String::format(_("Downloading icons list... %d entries"), _fileHash.size()));
+		calculateList();
 		break;
 	default:
 		Dialog::handleCommand(sender, cmd, data);
@@ -206,4 +209,44 @@ void DownloadIconsDialog::downloadList() {
 	rq->start();
 }
 
+void DownloadIconsDialog::calculateList() {
+	if (!ConfMan.hasKey("iconspath")) {
+		_errorText->setLabel(_("ERROR: No icons path set"));
+		return;
+	}
+
+	// Scan all files in iconspath and remove present ones from the
+	// donwloaded files list
+	Common::FSDirectory *iconDir = new Common::FSDirectory(ConfMan.get("iconspath"));
+	Common::ArchiveMemberList iconFiles;
+
+	iconDir->listMatchingMembers(iconFiles, "gui-icons*.dat");
+
+	for (auto ic = iconFiles.begin(); ic != iconFiles.end(); ++ic) {
+		Common::String fname = (*ic)->getName();
+
+		if (_fileHash.contains(fname))
+			_fileHash.erase(fname);
+	}
+
+	delete iconDir;
+
+	// Now calculate the size of the missing files
+	uint32 totalsize = 0;
+	for (auto f = _fileHash.begin(); f != _fileHash.end(); ++f) {
+		totalsize += f->_value;
+	}
+
+	if (totalsize == 0) {
+		_statusText->setLabel(_("No new icons packs available"));
+		return;
+	}
+
+	Common::String size, sizeUnits;
+	size = getHumanReadableBytes(totalsize, sizeUnits);
+
+	_statusText->setLabel(Common::U32String::format(_("Need to download %d files, %s %S"), _fileHash.size(), size.c_str(), _(sizeUnits).c_str()));
+
+}
+
 } // End of namespace GUI
diff --git a/gui/downloadiconsdialog.h b/gui/downloadiconsdialog.h
index 1903fea2f5..d46127d447 100644
--- a/gui/downloadiconsdialog.h
+++ b/gui/downloadiconsdialog.h
@@ -38,6 +38,8 @@ class ButtonWidget;
 class SliderWidget;
 
 class DownloadIconsDialog : public Dialog, public CommandSender {
+	StaticTextWidget *_statusText;
+	StaticTextWidget *_errorText;
 	StaticTextWidget *_percentLabel;
 	StaticTextWidget *_downloadSizeLabel;
 	StaticTextWidget *_downloadSpeedLabel;
@@ -73,6 +75,7 @@ public:
 
 private:
 	void downloadList();
+	void calculateList();
 };
 
 } // End of namespace GUI
diff --git a/gui/themes/scummremastered.zip b/gui/themes/scummremastered.zip
index e414e2b5c6..a7573cc1b9 100644
Binary files a/gui/themes/scummremastered.zip and b/gui/themes/scummremastered.zip differ
diff --git a/gui/themes/scummremastered/remastered_layout.stx b/gui/themes/scummremastered/remastered_layout.stx
index a0b9a8167b..bc1b4c46f9 100644
--- a/gui/themes/scummremastered/remastered_layout.stx
+++ b/gui/themes/scummremastered/remastered_layout.stx
@@ -1025,6 +1025,12 @@
 
 	<dialog name = 'GlobalOptions_DownloadIconsDialog' overlays = 'Dialog.GlobalOptions'>
 		<layout type = 'vertical' padding = '16, 16, 16, 8' spacing = '8'>
+			<widget name = 'StatusText'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'ErrorText'
+					height = 'Globals.Line.Height'
+			/>
 			<widget name = 'ProgressBar'
 					height = 'Globals.Button.Height'
 			/>
diff --git a/gui/themes/scummremastered/remastered_layout_lowres.stx b/gui/themes/scummremastered/remastered_layout_lowres.stx
index ae2f46992e..9c6aa8dfb1 100644
--- a/gui/themes/scummremastered/remastered_layout_lowres.stx
+++ b/gui/themes/scummremastered/remastered_layout_lowres.stx
@@ -1003,6 +1003,12 @@
 
 	<dialog name = 'GlobalOptions_DownloadIconsDialog' overlays = 'Dialog.GlobalOptions'>
 		<layout type = 'vertical' padding = '8, 8, 8, 4' spacing = '8'>
+			<widget name = 'StatusText'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'ErrorText'
+					height = 'Globals.Line.Height'
+			/>
 			<widget name = 'ProgressBar'
 					height = 'Globals.Button.Height'
 			/>
diff --git a/po/POTFILES b/po/POTFILES
index 5045f00287..92d5e249b1 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -4,6 +4,7 @@ gui/about.cpp
 gui/browser.cpp
 gui/chooser.cpp
 gui/downloaddialog.cpp
+gui/downloadiconsdialog.cpp
 gui/editgamedialog.cpp
 gui/editrecorddialog.cpp
 gui/filebrowser-dialog.cpp


Commit: 65020829fc0cdcf7497672d9ac907a837592f735
    https://github.com/scummvm/scummvm/commit/65020829fc0cdcf7497672d9ac907a837592f735
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:42+01:00

Commit Message:
BACKENDS: CLOUD: Fix overridden methods

Changed paths:
    backends/cloud/downloadrequest.cpp
    backends/cloud/downloadrequest.h
    backends/cloud/savessyncrequest.cpp
    backends/cloud/savessyncrequest.h


diff --git a/backends/cloud/downloadrequest.cpp b/backends/cloud/downloadrequest.cpp
index 994a9b3457..cfebb2a8bf 100644
--- a/backends/cloud/downloadrequest.cpp
+++ b/backends/cloud/downloadrequest.cpp
@@ -123,7 +123,7 @@ void DownloadRequest::finishDownload(bool success) {
 		(*_boolCallback)(Storage::BoolResponse(this, success));
 }
 
-void DownloadRequest::finishError(Networking::ErrorResponse error) {
+void DownloadRequest::finishError(Networking::ErrorResponse error, Networking::RequestState state) {
 	if (_localFile)
 		_localFile->close();
 	Request::finishError(error);
diff --git a/backends/cloud/downloadrequest.h b/backends/cloud/downloadrequest.h
index a5698d89cb..03f98b5281 100644
--- a/backends/cloud/downloadrequest.h
+++ b/backends/cloud/downloadrequest.h
@@ -46,7 +46,7 @@ class DownloadRequest: public Networking::Request {
 	void streamCallback(Networking::NetworkReadStreamResponse response);
 	void streamErrorCallback(Networking::ErrorResponse error);
 	void finishDownload(bool success);
-	virtual void finishError(Networking::ErrorResponse error);
+	virtual void finishError(Networking::ErrorResponse error, Networking::RequestState state = Networking::FINISHED);
 
 public:
 	DownloadRequest(Storage *storage, Storage::BoolCallback callback, Networking::ErrorCallback ecb, Common::String remoteFileId, Common::DumpFile *dumpFile);
diff --git a/backends/cloud/savessyncrequest.cpp b/backends/cloud/savessyncrequest.cpp
index 439642b45c..5634bc7e5f 100644
--- a/backends/cloud/savessyncrequest.cpp
+++ b/backends/cloud/savessyncrequest.cpp
@@ -411,7 +411,7 @@ Common::Array<Common::String> SavesSyncRequest::getFilesToDownload() {
 	return result;
 }
 
-void SavesSyncRequest::finishError(Networking::ErrorResponse error) {
+void SavesSyncRequest::finishError(Networking::ErrorResponse error, Networking::RequestState state) {
 	debug(9, "SavesSync::finishError");
 	//if we were downloading a file - remember the name
 	//and make the Request close() it, so we can delete it
diff --git a/backends/cloud/savessyncrequest.h b/backends/cloud/savessyncrequest.h
index 501a46d582..c8100a2680 100644
--- a/backends/cloud/savessyncrequest.h
+++ b/backends/cloud/savessyncrequest.h
@@ -55,7 +55,7 @@ class SavesSyncRequest: public Networking::Request, public GUI::CommandSender {
 	void fileUploadedErrorCallback(Networking::ErrorResponse error);
 	void downloadNextFile();
 	void uploadNextFile();
-	virtual void finishError(Networking::ErrorResponse error);
+	virtual void finishError(Networking::ErrorResponse error, Networking::RequestState state = Networking::FINISHED);
 	void finishSync(bool success);
 
 public:


Commit: 192b05930a1009ea7c23ff2c88e9b9fbfa14cc5f
    https://github.com/scummvm/scummvm/commit/192b05930a1009ea7c23ff2c88e9b9fbfa14cc5f
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:43+01:00

Commit Message:
COMMON: Mark human-readable bytes as translatable

Changed paths:
    common/util.cpp
    common/util.h
    po/POTFILES


diff --git a/common/util.cpp b/common/util.cpp
index ef5b37b6bd..e270cd849c 100644
--- a/common/util.cpp
+++ b/common/util.cpp
@@ -24,6 +24,7 @@
 
 #include "common/util.h"
 #include "common/debug.h"
+#include "common/translation.h"
 
 namespace Common {
 
@@ -177,28 +178,33 @@ bool isBlank(int c) {
 #pragma mark -
 
 
-Common::String getHumanReadableBytes(uint64 bytes, Common::String &unitsOut) {
+Common::U32String getHumanReadableBytes(uint64 bytes, Common::String &unitsOut) {
 	if (bytes < 1024) {
-		unitsOut = "B";
+		// I18N: Abbreviation for 'bytes' as data size
+		unitsOut = _("B");
 		return Common::String::format("%lu", (unsigned long int)bytes);
 	}
 
 	double floating = bytes / 1024.0;
-	unitsOut = "KB";
+		// I18N: Abbreviation for 'kilobytes' as data size
+	unitsOut = _("KB");
 
 	if (floating >= 1024) {
 		floating /= 1024.0;
-		unitsOut = "MB";
+		// I18N: Abbreviation for 'megabytes' as data size
+		unitsOut = _("MB");
 	}
 
 	if (floating >= 1024) {
 		floating /= 1024.0;
-		unitsOut = "GB";
+		// I18N: Abbreviation for 'gigabytes' as data size
+		unitsOut = _("GB");
 	}
 
 	if (floating >= 1024) { // woah
 		floating /= 1024.0;
-		unitsOut = "TB";
+		// I18N: Abbreviation for 'terabytes' as data size
+		unitsOut = _("TB");
 	}
 
 	// print one digit after floating point
diff --git a/common/util.h b/common/util.h
index cf6d2a71d3..2a788f61b4 100644
--- a/common/util.h
+++ b/common/util.h
@@ -327,7 +327,7 @@ bool isBlank(int c);
  *
  * @return String with a floating point number representing the given size.
  */
-Common::String getHumanReadableBytes(uint64 bytes, Common::String &unitsOut);
+Common::U32String getHumanReadableBytes(uint64 bytes, Common::String &unitsOut);
 
 /** @} */
 
diff --git a/po/POTFILES b/po/POTFILES
index 92d5e249b1..29fde2ca97 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -33,6 +33,7 @@ common/achievements.cpp
 common/error.cpp
 common/rendermode.cpp
 common/updates.cpp
+common/util.cpp
 
 dists/scummvm.appdata.xml.cpp
 


Commit: f23e41d3466dc28e392af44e387ea687e5734c42
    https://github.com/scummvm/scummvm/commit/f23e41d3466dc28e392af44e387ea687e5734c42
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:43+01:00

Commit Message:
GUI: Better error handling in icons downloader

Changed paths:
    gui/downloadiconsdialog.cpp
    gui/downloadiconsdialog.h


diff --git a/gui/downloadiconsdialog.cpp b/gui/downloadiconsdialog.cpp
index 4b450c5a78..fc9478c7e0 100644
--- a/gui/downloadiconsdialog.cpp
+++ b/gui/downloadiconsdialog.cpp
@@ -71,6 +71,7 @@ DownloadIconsDialog::DownloadIconsDialog() :
 		_cancelButton = new ButtonWidget(this, "GlobalOptions_DownloadIconsDialog.MainButton", _c("Cancel download", "lowres"), Common::U32String(), kDownloadIconsDialogButtonCmd);
 
 	_closeButton = new ButtonWidget(this, "GlobalOptions_DownloadIconsDialog.CloseButton", _("Hide"), Common::U32String(), kCloseCmd);
+	_closeButton->setEnabled(false);
 	refreshWidgets();
 
 	CloudMan.setDownloadTarget(this);
@@ -196,8 +197,14 @@ void DownloadIconsDialog::downloadListCallback(Networking::DataResponse response
 	sendCommand(kListEndedCmd, 0);
 }
 
+void DownloadIconsDialog::setError(Common::U32String &msg) {
+	_errorText->setLabel(msg);
+}
+
 void DownloadIconsDialog::errorCallback(Networking::ErrorResponse error) {
-	warning("Error %ld: %s", error.httpResponseCode, error.response.c_str());
+	Common::U32String message = Common::U32String::format(_("ERROR %d: %s"), error.httpResponseCode, error.response.c_str());
+
+	g_dialog->setError(message);
 }
 
 void DownloadIconsDialog::downloadList() {
diff --git a/gui/downloadiconsdialog.h b/gui/downloadiconsdialog.h
index d46127d447..3c8f4e8483 100644
--- a/gui/downloadiconsdialog.h
+++ b/gui/downloadiconsdialog.h
@@ -73,6 +73,8 @@ public:
 	void downloadListCallback(Networking::DataResponse response);
 	void errorCallback(Networking::ErrorResponse error);
 
+	void setError(Common::U32String &msg);
+
 private:
 	void downloadList();
 	void calculateList();


Commit: 06f917cc6ff7b030d388819550f73c2c6930bba0
    https://github.com/scummvm/scummvm/commit/06f917cc6ff7b030d388819550f73c2c6930bba0
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:43+01:00

Commit Message:
GUI: Initial work on icon packs downloading. Streamlined the process.

Changed paths:
    gui/downloadiconsdialog.cpp
    gui/downloadiconsdialog.h
    gui/themes/scummremastered.zip
    gui/themes/scummremastered/remastered_layout.stx
    gui/themes/scummremastered/remastered_layout_lowres.stx


diff --git a/gui/downloadiconsdialog.cpp b/gui/downloadiconsdialog.cpp
index fc9478c7e0..7f743e9f5b 100644
--- a/gui/downloadiconsdialog.cpp
+++ b/gui/downloadiconsdialog.cpp
@@ -41,8 +41,9 @@
 namespace GUI {
 
 enum {
-	kDownloadIconsDialogButtonCmd = 'Dldb',
-	kListEndedCmd = 'DLLE'
+	kDownloadCancelCmd = 'Dlcn',
+	kDownloadProceedCmd = 'Dlpr',
+	kListDownloadFinishedCmd = 'DlLE'
 };
 
 static DownloadIconsDialog *g_dialog;
@@ -65,11 +66,7 @@ DownloadIconsDialog::DownloadIconsDialog() :
 	_percentLabel = new StaticTextWidget(this, "GlobalOptions_DownloadIconsDialog.PercentText", Common::String::format("%u %%", progress));
 	_downloadSizeLabel = new StaticTextWidget(this, "GlobalOptions_DownloadIconsDialog.DownloadSize", Common::U32String());
 	_downloadSpeedLabel = new StaticTextWidget(this, "GlobalOptions_DownloadIconsDialog.DownloadSpeed", Common::U32String());
-	if (g_system->getOverlayWidth() > 320)
-		_cancelButton = new ButtonWidget(this, "GlobalOptions_DownloadIconsDialog.MainButton", _("Cancel download"), Common::U32String(), kDownloadIconsDialogButtonCmd);
-	else
-		_cancelButton = new ButtonWidget(this, "GlobalOptions_DownloadIconsDialog.MainButton", _c("Cancel download", "lowres"), Common::U32String(), kDownloadIconsDialogButtonCmd);
-
+	_cancelButton = new ButtonWidget(this, "GlobalOptions_DownloadIconsDialog.MainButton", _("Cancel download"), Common::U32String(), kDownloadCancelCmd);
 	_closeButton = new ButtonWidget(this, "GlobalOptions_DownloadIconsDialog.CloseButton", _("Hide"), Common::U32String(), kCloseCmd);
 	_closeButton->setEnabled(false);
 	refreshWidgets();
@@ -101,7 +98,7 @@ void DownloadIconsDialog::close() {
 
 void DownloadIconsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
 	switch (cmd) {
-	case kDownloadIconsDialogButtonCmd:
+	case kDownloadCancelCmd:
 		{
 			CloudMan.setDownloadTarget(nullptr);
 			CloudMan.cancelDownload();
@@ -117,10 +114,13 @@ void DownloadIconsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
 	case kDownloadEndedCmd:
 		_close = true;
 		break;
-	case kListEndedCmd:
+	case kListDownloadFinishedCmd:
 		_statusText->setLabel(Common::U32String::format(_("Downloading icons list... %d entries"), _fileHash.size()));
 		calculateList();
 		break;
+	case kDownloadProceedCmd:
+		proceedDownload();
+		break;
 	default:
 		Dialog::handleCommand(sender, cmd, data);
 	}
@@ -194,11 +194,14 @@ void DownloadIconsDialog::downloadListCallback(Networking::DataResponse response
 		g_dialog->_fileHash.setVal(s.substr(0, pos), atol(s.substr(pos + 1).c_str()));
 	}
 
-	sendCommand(kListEndedCmd, 0);
+	sendCommand(kListDownloadFinishedCmd, 0);
 }
 
 void DownloadIconsDialog::setError(Common::U32String &msg) {
 	_errorText->setLabel(msg);
+
+	_cancelButton->setLabel(_("Close"));
+	_cancelButton->setCmd(kDownloadCancelCmd);
 }
 
 void DownloadIconsDialog::errorCallback(Networking::ErrorResponse error) {
@@ -218,7 +221,8 @@ void DownloadIconsDialog::downloadList() {
 
 void DownloadIconsDialog::calculateList() {
 	if (!ConfMan.hasKey("iconspath")) {
-		_errorText->setLabel(_("ERROR: No icons path set"));
+		Common::U32String str(_("ERROR: No icons path set"));
+		setError(str);
 		return;
 	}
 
@@ -252,8 +256,40 @@ void DownloadIconsDialog::calculateList() {
 	Common::String size, sizeUnits;
 	size = getHumanReadableBytes(totalsize, sizeUnits);
 
-	_statusText->setLabel(Common::U32String::format(_("Need to download %d files, %s %S"), _fileHash.size(), size.c_str(), _(sizeUnits).c_str()));
+	_statusText->setLabel(Common::U32String::format(_("Detected %d new packs, %s %S"), _fileHash.size(), size.c_str(), _(sizeUnits).c_str()));
 
+	_cancelButton->setLabel(_("Download"));
+	_cancelButton->setCmd(kDownloadProceedCmd);
+
+	_closeButton->setLabel(_("Cancel"));
+	_closeButton->setCmd(kDownloadCancelCmd);
+	_closeButton->setEnabled(true);
 }
 
+void DownloadIconsDialog::downloadFileCallback(Networking::DataResponse response) {
+	Networking::SessionRequest *req = dynamic_cast<Networking::SessionRequest *>(response.request);
+
+	warning("Got %d bytes", req->getSize());
+}
+
+void DownloadIconsDialog::proceedDownload() {
+	_cancelButton->setLabel(_("Cancel download"));
+	_cancelButton->setCmd(kDownloadCancelCmd);
+
+	_closeButton->setLabel(_("Hide"));
+	_closeButton->setCmd(kCloseCmd);
+
+	for (auto f = _fileHash.begin(); f != _fileHash.end(); ++f) {
+		Common::String url = Common::String::format("https://downloads.scummvm.org/frs/icons/%s", f->_key.c_str());
+
+		Networking::SessionRequest *rq = _session->get(url,
+			new Common::Callback<DownloadIconsDialog, Networking::DataResponse>(this, &DownloadIconsDialog::downloadFileCallback),
+			new Common::Callback<DownloadIconsDialog, Networking::ErrorResponse>(this, &DownloadIconsDialog::errorCallback),
+			true);
+
+		rq->start();
+	}
+}
+
+
 } // End of namespace GUI
diff --git a/gui/downloadiconsdialog.h b/gui/downloadiconsdialog.h
index 3c8f4e8483..fecb63dd86 100644
--- a/gui/downloadiconsdialog.h
+++ b/gui/downloadiconsdialog.h
@@ -71,6 +71,7 @@ public:
 	void reflowLayout() override;
 
 	void downloadListCallback(Networking::DataResponse response);
+	void downloadFileCallback(Networking::DataResponse response);
 	void errorCallback(Networking::ErrorResponse error);
 
 	void setError(Common::U32String &msg);
@@ -78,6 +79,7 @@ public:
 private:
 	void downloadList();
 	void calculateList();
+	void proceedDownload();
 };
 
 } // End of namespace GUI
diff --git a/gui/themes/scummremastered.zip b/gui/themes/scummremastered.zip
index a7573cc1b9..5208ba23aa 100644
Binary files a/gui/themes/scummremastered.zip and b/gui/themes/scummremastered.zip differ
diff --git a/gui/themes/scummremastered/remastered_layout.stx b/gui/themes/scummremastered/remastered_layout.stx
index bc1b4c46f9..b6df042bc3 100644
--- a/gui/themes/scummremastered/remastered_layout.stx
+++ b/gui/themes/scummremastered/remastered_layout.stx
@@ -1023,7 +1023,7 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_DownloadIconsDialog' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_DownloadIconsDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '16, 16, 16, 8' spacing = '8'>
 			<widget name = 'StatusText'
 					height = 'Globals.Line.Height'
@@ -1058,7 +1058,7 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '16, 16, 16, 8' spacing = '8'>
 			<widget name = 'RemoteDirectory'
 					height = 'Globals.Line.Height'
@@ -1093,7 +1093,7 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
 		</layout>
diff --git a/gui/themes/scummremastered/remastered_layout_lowres.stx b/gui/themes/scummremastered/remastered_layout_lowres.stx
index 9c6aa8dfb1..262c1d19fa 100644
--- a/gui/themes/scummremastered/remastered_layout_lowres.stx
+++ b/gui/themes/scummremastered/remastered_layout_lowres.stx
@@ -1001,7 +1001,7 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_DownloadIconsDialog' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_DownloadIconsDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '8, 8, 8, 4' spacing = '8'>
 			<widget name = 'StatusText'
 					height = 'Globals.Line.Height'
@@ -1036,7 +1036,7 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '8, 8, 8, 4' spacing = '8'>
 			<widget name = 'RemoteDirectory'
 					height = 'Globals.Line.Height'
@@ -1071,7 +1071,7 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
 		</layout>


Commit: cec059e5bfa15ba58ac3ecd1b7e0eebdfca95a9c
    https://github.com/scummvm/scummvm/commit/cec059e5bfa15ba58ac3ecd1b7e0eebdfca95a9c
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:43+01:00

Commit Message:
GUI: Persist Download Icons dialog

Changed paths:
    gui/downloadiconsdialog.cpp
    gui/downloadiconsdialog.h


diff --git a/gui/downloadiconsdialog.cpp b/gui/downloadiconsdialog.cpp
index 7f743e9f5b..096dcea7dd 100644
--- a/gui/downloadiconsdialog.cpp
+++ b/gui/downloadiconsdialog.cpp
@@ -46,11 +46,16 @@ enum {
 	kListDownloadFinishedCmd = 'DlLE'
 };
 
-static DownloadIconsDialog *g_dialog;
+struct DialogState {
+	DownloadIconsDialog *dialog;
+	Networking::Session session;
+	Common::HashMap<Common::String, uint32> fileHash;
+	IconProcessState state;
+	uint32 totalsize;
+} static *g_state;
 
 DownloadIconsDialog::DownloadIconsDialog() :
 	Dialog("GlobalOptions_DownloadIconsDialog"), CommandSender(this), _close(false) {
-	g_dialog = this;
 
 	_backgroundType = GUI::ThemeEngine::kDialogBackgroundPlain;
 
@@ -68,21 +73,28 @@ DownloadIconsDialog::DownloadIconsDialog() :
 	_downloadSpeedLabel = new StaticTextWidget(this, "GlobalOptions_DownloadIconsDialog.DownloadSpeed", Common::U32String());
 	_cancelButton = new ButtonWidget(this, "GlobalOptions_DownloadIconsDialog.MainButton", _("Cancel download"), Common::U32String(), kDownloadCancelCmd);
 	_closeButton = new ButtonWidget(this, "GlobalOptions_DownloadIconsDialog.CloseButton", _("Hide"), Common::U32String(), kCloseCmd);
-	_closeButton->setEnabled(false);
-	refreshWidgets();
 
 	CloudMan.setDownloadTarget(this);
 
-	_session = new Networking::Session();
+	if (!g_state) {
+		g_state = new DialogState;
+
+		g_state->dialog = this;
+
+		setState(kDownloadStateList);
+		refreshWidgets();
+
+		downloadList();
+	} else {
+		g_state->dialog = this;
 
-	downloadList();
+		setState(g_state->state);
+		refreshWidgets();
+	}
 }
 
 DownloadIconsDialog::~DownloadIconsDialog() {
 	CloudMan.setDownloadTarget(nullptr);
-
-	_session->close();
-	delete _session;
 }
 
 void DownloadIconsDialog::open() {
@@ -93,15 +105,70 @@ void DownloadIconsDialog::open() {
 
 void DownloadIconsDialog::close() {
 	CloudMan.setDownloadTarget(nullptr);
+
+	if (g_state)
+		g_state->dialog = nullptr;
+
 	Dialog::close();
 }
 
+void DownloadIconsDialog::setState(IconProcessState state) {
+	g_state->state = state;
+
+	switch (state) {
+	case kDownloadStateList:
+		_statusText->setLabel(_("Downloading icons list..."));
+		_cancelButton->setLabel(_("Cancel download"));
+		_cancelButton->setCmd(kDownloadCancelCmd);
+		_closeButton->setVisible(false);
+
+		g_state->totalsize = 0;
+		g_state->fileHash.clear();
+		break;
+
+	case kDownloadStateListDownloaded:
+		_statusText->setLabel(Common::U32String::format(_("Downloading icons list... %d entries"), g_state->fileHash.size()));
+		_cancelButton->setLabel(_("Cancel download"));
+		_cancelButton->setCmd(kDownloadCancelCmd);
+		_closeButton->setVisible(false);
+		break;
+
+	case kDownloadStateListCalculated: {
+			Common::String size, sizeUnits;
+			size = getHumanReadableBytes(g_state->totalsize, sizeUnits);
+
+			_statusText->setLabel(Common::U32String::format(_("Detected %d new packs, %s %S"), g_state->fileHash.size(), size.c_str(), _(sizeUnits).c_str()));
+
+			_cancelButton->setLabel(_("Download"));
+			_cancelButton->setCmd(kDownloadProceedCmd);
+
+			_closeButton->setVisible(true);
+			_closeButton->setLabel(_("Cancel"));
+			_closeButton->setCmd(kDownloadCancelCmd);
+			_closeButton->setEnabled(true);
+			break;
+		}
+
+	case kDownloadStateDownloading:
+		_cancelButton->setLabel(_("Cancel download"));
+		_cancelButton->setCmd(kDownloadCancelCmd);
+
+		_closeButton->setVisible(true);
+		_closeButton->setLabel(_("Hide"));
+		_closeButton->setCmd(kCloseCmd);
+		_closeButton->setEnabled(true);
+		break;
+	}
+}
+
 void DownloadIconsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
 	switch (cmd) {
 	case kDownloadCancelCmd:
 		{
-			CloudMan.setDownloadTarget(nullptr);
-			CloudMan.cancelDownload();
+			g_state->session.close();
+			delete g_state;
+			g_state = nullptr;
+
 			close();
 			break;
 		}
@@ -115,10 +182,11 @@ void DownloadIconsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
 		_close = true;
 		break;
 	case kListDownloadFinishedCmd:
-		_statusText->setLabel(Common::U32String::format(_("Downloading icons list... %d entries"), _fileHash.size()));
+		setState(kDownloadStateListDownloaded);
 		calculateList();
 		break;
 	case kDownloadProceedCmd:
+		setState(kDownloadStateDownloading);
 		proceedDownload();
 		break;
 	default:
@@ -191,7 +259,7 @@ void DownloadIconsDialog::downloadListCallback(Networking::DataResponse response
 			continue;
 		}
 
-		g_dialog->_fileHash.setVal(s.substr(0, pos), atol(s.substr(pos + 1).c_str()));
+		g_state->fileHash.setVal(s.substr(0, pos), atol(s.substr(pos + 1).c_str()));
 	}
 
 	sendCommand(kListDownloadFinishedCmd, 0);
@@ -207,11 +275,12 @@ void DownloadIconsDialog::setError(Common::U32String &msg) {
 void DownloadIconsDialog::errorCallback(Networking::ErrorResponse error) {
 	Common::U32String message = Common::U32String::format(_("ERROR %d: %s"), error.httpResponseCode, error.response.c_str());
 
-	g_dialog->setError(message);
+	if (g_state->dialog)
+		g_state->dialog->setError(message);
 }
 
 void DownloadIconsDialog::downloadList() {
-	Networking::SessionRequest *rq = _session->get("https://downloads.scummvm.org/frs/icons/LIST",
+	Networking::SessionRequest *rq = g_state->session.get("https://downloads.scummvm.org/frs/icons/LIST",
 		new Common::Callback<DownloadIconsDialog, Networking::DataResponse>(this, &DownloadIconsDialog::downloadListCallback),
 		new Common::Callback<DownloadIconsDialog, Networking::ErrorResponse>(this, &DownloadIconsDialog::errorCallback),
 		true);
@@ -236,34 +305,24 @@ void DownloadIconsDialog::calculateList() {
 	for (auto ic = iconFiles.begin(); ic != iconFiles.end(); ++ic) {
 		Common::String fname = (*ic)->getName();
 
-		if (_fileHash.contains(fname))
-			_fileHash.erase(fname);
+		if (g_state->fileHash.contains(fname))
+			g_state->fileHash.erase(fname);
 	}
 
 	delete iconDir;
 
 	// Now calculate the size of the missing files
-	uint32 totalsize = 0;
-	for (auto f = _fileHash.begin(); f != _fileHash.end(); ++f) {
-		totalsize += f->_value;
+	g_state->totalsize = 0;
+	for (auto f = g_state->fileHash.begin(); f != g_state->fileHash.end(); ++f) {
+		g_state->totalsize += f->_value;
 	}
 
-	if (totalsize == 0) {
+	if (g_state->totalsize == 0) {
 		_statusText->setLabel(_("No new icons packs available"));
 		return;
 	}
 
-	Common::String size, sizeUnits;
-	size = getHumanReadableBytes(totalsize, sizeUnits);
-
-	_statusText->setLabel(Common::U32String::format(_("Detected %d new packs, %s %S"), _fileHash.size(), size.c_str(), _(sizeUnits).c_str()));
-
-	_cancelButton->setLabel(_("Download"));
-	_cancelButton->setCmd(kDownloadProceedCmd);
-
-	_closeButton->setLabel(_("Cancel"));
-	_closeButton->setCmd(kDownloadCancelCmd);
-	_closeButton->setEnabled(true);
+	setState(kDownloadStateListCalculated);
 }
 
 void DownloadIconsDialog::downloadFileCallback(Networking::DataResponse response) {
@@ -273,16 +332,10 @@ void DownloadIconsDialog::downloadFileCallback(Networking::DataResponse response
 }
 
 void DownloadIconsDialog::proceedDownload() {
-	_cancelButton->setLabel(_("Cancel download"));
-	_cancelButton->setCmd(kDownloadCancelCmd);
-
-	_closeButton->setLabel(_("Hide"));
-	_closeButton->setCmd(kCloseCmd);
-
-	for (auto f = _fileHash.begin(); f != _fileHash.end(); ++f) {
+	for (auto f = g_state->fileHash.begin(); f != g_state->fileHash.end(); ++f) {
 		Common::String url = Common::String::format("https://downloads.scummvm.org/frs/icons/%s", f->_key.c_str());
 
-		Networking::SessionRequest *rq = _session->get(url,
+		Networking::SessionRequest *rq = g_state->session.get(url,
 			new Common::Callback<DownloadIconsDialog, Networking::DataResponse>(this, &DownloadIconsDialog::downloadFileCallback),
 			new Common::Callback<DownloadIconsDialog, Networking::ErrorResponse>(this, &DownloadIconsDialog::errorCallback),
 			true);
diff --git a/gui/downloadiconsdialog.h b/gui/downloadiconsdialog.h
index fecb63dd86..0acdd41ce3 100644
--- a/gui/downloadiconsdialog.h
+++ b/gui/downloadiconsdialog.h
@@ -37,6 +37,13 @@ class StaticTextWidget;
 class ButtonWidget;
 class SliderWidget;
 
+enum IconProcessState {
+	kDownloadStateList,
+	kDownloadStateListDownloaded,
+	kDownloadStateListCalculated,
+	kDownloadStateDownloading
+};
+
 class DownloadIconsDialog : public Dialog, public CommandSender {
 	StaticTextWidget *_statusText;
 	StaticTextWidget *_errorText;
@@ -55,11 +62,6 @@ class DownloadIconsDialog : public Dialog, public CommandSender {
 
 	void refreshWidgets();
 
-	Networking::Session *_session;
-
-public:
-	Common::HashMap<Common::String, uint32> _fileHash;
-
 public:
 	DownloadIconsDialog();
 	~DownloadIconsDialog() override;
@@ -80,6 +82,7 @@ private:
 	void downloadList();
 	void calculateList();
 	void proceedDownload();
+	void setState(IconProcessState state);
 };
 
 } // End of namespace GUI


Commit: db7cec6935a66ed1fda9b18286f7df040ac59cd4
    https://github.com/scummvm/scummvm/commit/db7cec6935a66ed1fda9b18286f7df040ac59cd4
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:43+01:00

Commit Message:
CLOUD: SessionRequest now can save downloaded files to disk

Changed paths:
    backends/networking/curl/session.cpp
    backends/networking/curl/session.h
    backends/networking/curl/sessionrequest.cpp
    backends/networking/curl/sessionrequest.h
    gui/downloadiconsdialog.cpp
    gui/downloadiconsdialog.h


diff --git a/backends/networking/curl/session.cpp b/backends/networking/curl/session.cpp
index 958ede8c7b..2a15d73727 100644
--- a/backends/networking/curl/session.cpp
+++ b/backends/networking/curl/session.cpp
@@ -33,17 +33,17 @@ Session::~Session() {
 	close();
 }
 
-SessionRequest *Session::get(Common::String url, DataCallback cb, ErrorCallback ecb, bool binary) {
+static Common::String constructUrl(Common::String prefix, Common::String url) {
 	// check url prefix
-	if (!_prefix.empty()) {
+	if (!prefix.empty()) {
 		if (url.contains("://")) {
-			if (url.size() < _prefix.size() || url.find(_prefix) != 0) {
-				warning("Session: given URL does not match the prefix!\n\t%s\n\t%s", url.c_str(), _prefix.c_str());
-				return nullptr;
+			if (url.size() < prefix.size() || url.find(prefix) != 0) {
+				warning("Session: given URL does not match the prefix!\n\t%s\n\t%s", url.c_str(), prefix.c_str());
+				return "";
 			}
 		} else {
 			// if no schema given, just append <url> to <_prefix>
-			Common::String newUrl = _prefix;
+			Common::String newUrl = prefix;
 			if (newUrl.lastChar() != '/' && (url.size() > 0 && url.firstChar() != '/'))
 				newUrl += "/";
 			newUrl += url;
@@ -51,6 +51,15 @@ SessionRequest *Session::get(Common::String url, DataCallback cb, ErrorCallback
 		}
 	}
 
+	return url;
+}
+
+SessionRequest *Session::get(Common::String url, Common::String localFile, DataCallback cb, ErrorCallback ecb, bool binary) {
+	url = constructUrl(_prefix, url);
+
+	if (url.empty())
+		return nullptr;
+
 	// check if request has finished (ready to be replaced)
 	if (_request) {
 		if (!_request->complete()) {
@@ -60,10 +69,10 @@ SessionRequest *Session::get(Common::String url, DataCallback cb, ErrorCallback
 	}
 
 	if (!_request) {
-		_request = new Networking::SessionRequest(url, cb, ecb, binary); // automatically added to ConnMan
+		_request = new SessionRequest(url, localFile, cb, ecb, binary); // automatically added to ConnMan
 		_request->connectionKeepAlive();
 	} else {
-		_request->reuse(url, cb, ecb);
+		_request->reuse(url, localFile, cb, ecb, binary);
 	}
 
 	return _request;
diff --git a/backends/networking/curl/session.h b/backends/networking/curl/session.h
index c3e82ff63f..da8c3ca05c 100644
--- a/backends/networking/curl/session.h
+++ b/backends/networking/curl/session.h
@@ -36,7 +36,7 @@ public:
 	Session(Common::String prefix = "");
 	~Session();
 
-	SessionRequest *get(Common::String url, DataCallback cb = nullptr, ErrorCallback ecb = nullptr, bool binary = false);
+	SessionRequest *get(Common::String url, Common::String localFile, DataCallback cb = nullptr, ErrorCallback ecb = nullptr, bool binary = false);
 	void close();
 };
 
diff --git a/backends/networking/curl/sessionrequest.cpp b/backends/networking/curl/sessionrequest.cpp
index c394309386..8ad933ea0e 100644
--- a/backends/networking/curl/sessionrequest.cpp
+++ b/backends/networking/curl/sessionrequest.cpp
@@ -27,15 +27,18 @@
 #include "backends/networking/curl/networkreadstream.h"
 #include "backends/networking/curl/sessionrequest.h"
 #include "common/debug.h"
+#include "common/file.h"
 #include "common/json.h"
 
 namespace Networking {
 
-SessionRequest::SessionRequest(Common::String url, DataCallback cb, ErrorCallback ecb, bool binary):
+SessionRequest::SessionRequest(Common::String url, Common::String localFile, DataCallback cb, ErrorCallback ecb, bool binary):
 	CurlRequest(cb, ecb, url), _contentsStream(DisposeAfterUse::YES),
-	_buffer(new byte[CURL_SESSION_REQUEST_BUFFER_SIZE]), _text(nullptr),
+	_buffer(new byte[CURL_SESSION_REQUEST_BUFFER_SIZE]), _text(nullptr), _localFile(nullptr),
 	_started(false), _complete(false), _success(false), _binary(binary) {
 
+	openLocalFile(localFile);
+
 	// automatically go under ConnMan control so nobody would be able to leak the memory
 	// but, we don't need it to be working just yet
 	_state = PAUSED;
@@ -46,6 +49,22 @@ SessionRequest::~SessionRequest() {
 	delete[] _buffer;
 }
 
+void SessionRequest::openLocalFile(Common::String localFile) {
+	if (localFile.empty())
+		return;
+
+	_localFile = new Common::DumpFile();
+	if (!_localFile->open(localFile, true)) {
+		warning("SessionRequestFile: unable to open file to download into");
+		ErrorResponse error(this, false, true, "SessionRequestFile: unable to open file to download into", -1);
+		finishError(error);
+		delete _localFile;
+		return;
+	}
+
+	_binary = true; // Enforce binary
+}
+
 bool SessionRequest::reuseStream() {
 	if (!_stream) {
 		return false;
@@ -86,8 +105,18 @@ void SessionRequest::finishSuccess() {
 	_complete = true;
 	_success = true;
 
-	if (_callback)
-		(*_callback)(DataResponse(this, text()));
+	if (_callback && !_localFile) {	// If localfile is present, we already called the callback
+		_response.buffer = _contentsStream.getData();
+		_response.len = _contentsStream.size();
+		_response.eos = true;
+
+		(*_callback)(DataResponse(this, &_response));
+	}
+
+	if (_localFile) {
+		_localFile->close();
+		_localFile = nullptr;
+	}
 }
 
 void SessionRequest::start() {
@@ -105,7 +134,7 @@ void SessionRequest::startAndWait() {
 	wait();
 }
 
-void SessionRequest::reuse(Common::String url, DataCallback cb, ErrorCallback ecb) {
+void SessionRequest::reuse(Common::String url, Common::String localFile, DataCallback cb, ErrorCallback ecb, bool binary) {
 	_url = url;
 
 	delete _callback;
@@ -113,6 +142,10 @@ void SessionRequest::reuse(Common::String url, DataCallback cb, ErrorCallback ec
 	_callback = cb;
 	_errorCallback = ecb;
 
+	_binary = binary;
+
+	openLocalFile(localFile);
+
 	restart();
 }
 
@@ -127,9 +160,25 @@ void SessionRequest::handle() {
 			return;
 		}
 		uint32 readBytes = _stream->read(_buffer, CURL_SESSION_REQUEST_BUFFER_SIZE);
-		if (readBytes != 0)
-			if (_contentsStream.write(_buffer, readBytes) != readBytes)
-				warning("SessionRequest: unable to write all the bytes into MemoryWriteStreamDynamic");
+		if (readBytes != 0) {
+			if (!_localFile) {
+				if (_contentsStream.write(_buffer, readBytes) != readBytes)
+					warning("SessionRequest: unable to write all the bytes into MemoryWriteStreamDynamic");
+			} else {
+				_response.buffer = _buffer;
+				_response.len = readBytes;
+				_response.eos = _stream->eos();
+
+				if (_localFile->write(_buffer, readBytes) != readBytes) {
+					warning("DownloadRequest: unable to write all received bytes into output file");
+					finishError(Networking::ErrorResponse(this, false, true, "DownloadRequest::handle: failed to write all bytes into a file", -1));
+					return;
+				}
+
+				if (_callback)
+					(*_callback)(DataResponse(this, &_response));
+			}
+		}
 
 		if (_stream->eos()) {
 			finishSuccess();
@@ -171,7 +220,7 @@ bool SessionRequest::success() {
 }
 
 char *SessionRequest::text() {
-	if (_binary)
+	if (_binary || _localFile)
 		return nullptr;
 
 	if (_text == nullptr)
@@ -180,6 +229,10 @@ char *SessionRequest::text() {
 }
 
 Common::JSONValue *SessionRequest::json() {
+	if (_binary)
+		error("SessionRequest::json() is called for binary stream");
+	if (_localFile)
+		error("SessionRequest::json() is called for localFile stream");
 	return Common::JSON::parse(text());
 }
 
diff --git a/backends/networking/curl/sessionrequest.h b/backends/networking/curl/sessionrequest.h
index d3a1eca816..7de34fafe1 100644
--- a/backends/networking/curl/sessionrequest.h
+++ b/backends/networking/curl/sessionrequest.h
@@ -25,12 +25,28 @@
 
 #include "backends/networking/curl/curlrequest.h"
 #include "common/memstream.h"
-#include "common/json.h"
+
+namespace Common {
+class DumpFile;
+class JSONValue;
+}
 
 namespace Networking {
 
 #define CURL_SESSION_REQUEST_BUFFER_SIZE 512 * 1024
 
+struct SessionFileResponse {
+	byte *buffer;
+	uint32 len;
+	bool eos;
+};
+
+/**
+ * @brief Class for reading file and storing locally
+ *
+ * @return Returns SessionFileResponse in the callback
+ */
+
 class SessionRequest: public CurlRequest {
 protected:
 	Common::MemoryWriteStreamDynamic _contentsStream;
@@ -38,6 +54,8 @@ protected:
 	char *_text;
 	bool _started, _complete, _success;
 	bool _binary;
+	Common::DumpFile *_localFile;
+	SessionFileResponse _response;
 
 	bool reuseStream();
 
@@ -46,15 +64,16 @@ protected:
 
 	virtual void finishError(ErrorResponse error, RequestState state = PAUSED);
 	virtual void finishSuccess();
+	void openLocalFile(Common::String localFile);
 
 public:
-	SessionRequest(Common::String url, DataCallback cb = nullptr, ErrorCallback ecb = nullptr, bool binary = false);
+	SessionRequest(Common::String url, Common::String localFile, DataCallback cb = nullptr, ErrorCallback ecb = nullptr, bool binary = false);
 	virtual ~SessionRequest();
 
 	void start();
 	void startAndWait();
 
-	void reuse(Common::String url, DataCallback cb = nullptr, ErrorCallback ecb = nullptr);
+	void reuse(Common::String url, Common::String localFile, DataCallback cb = nullptr, ErrorCallback ecb = nullptr, bool binary = false);
 
 	virtual void handle();
 	virtual void restart();
diff --git a/gui/downloadiconsdialog.cpp b/gui/downloadiconsdialog.cpp
index 096dcea7dd..5798ffb1c4 100644
--- a/gui/downloadiconsdialog.cpp
+++ b/gui/downloadiconsdialog.cpp
@@ -20,7 +20,7 @@
  *
  */
 
-#include "backends/cloud/cloudmanager.h"
+#include "backends/networking/curl/request.h"
 #include "gui/downloadiconsdialog.h"
 #include "gui/downloaddialog.h"
 #include "backends/networking/curl/session.h"
@@ -51,9 +51,23 @@ struct DialogState {
 	Networking::Session session;
 	Common::HashMap<Common::String, uint32> fileHash;
 	IconProcessState state;
+	uint32 downloadedsize;
 	uint32 totalsize;
+
+	DialogState() { state = kDownloadStateNone; downloadedsize = totalsize = 0; dialog = nullptr; }
 } static *g_state;
 
+static uint32 getDownloadingProgress() {
+	if (!g_state)
+		return 0;
+
+	return 100 * g_state->downloadedsize / (g_state->totalsize ? g_state->totalsize : 1);
+}
+
+static uint32 getDownloadSpeed() {
+	return 0;
+}
+
 DownloadIconsDialog::DownloadIconsDialog() :
 	Dialog("GlobalOptions_DownloadIconsDialog"), CommandSender(this), _close(false) {
 
@@ -62,7 +76,7 @@ DownloadIconsDialog::DownloadIconsDialog() :
 	_statusText = new StaticTextWidget(this, "GlobalOptions_DownloadIconsDialog.StatusText", _("Downloading icons list..."));
 	_errorText = new StaticTextWidget(this, "GlobalOptions_DownloadIconsDialog.ErrorText", Common::U32String(""));
 
-	uint32 progress = (uint32)(100 * CloudMan.getDownloadingProgress());
+	uint32 progress = getDownloadingProgress();
 	_progressBar = new SliderWidget(this, "GlobalOptions_DownloadIconsDialog.ProgressBar");
 	_progressBar->setMinValue(0);
 	_progressBar->setMaxValue(100);
@@ -74,8 +88,6 @@ DownloadIconsDialog::DownloadIconsDialog() :
 	_cancelButton = new ButtonWidget(this, "GlobalOptions_DownloadIconsDialog.MainButton", _("Cancel download"), Common::U32String(), kDownloadCancelCmd);
 	_closeButton = new ButtonWidget(this, "GlobalOptions_DownloadIconsDialog.CloseButton", _("Hide"), Common::U32String(), kCloseCmd);
 
-	CloudMan.setDownloadTarget(this);
-
 	if (!g_state) {
 		g_state = new DialogState;
 
@@ -94,7 +106,6 @@ DownloadIconsDialog::DownloadIconsDialog() :
 }
 
 DownloadIconsDialog::~DownloadIconsDialog() {
-	CloudMan.setDownloadTarget(nullptr);
 }
 
 void DownloadIconsDialog::open() {
@@ -104,8 +115,6 @@ void DownloadIconsDialog::open() {
 }
 
 void DownloadIconsDialog::close() {
-	CloudMan.setDownloadTarget(nullptr);
-
 	if (g_state)
 		g_state->dialog = nullptr;
 
@@ -116,6 +125,7 @@ void DownloadIconsDialog::setState(IconProcessState state) {
 	g_state->state = state;
 
 	switch (state) {
+	case kDownloadStateNone:
 	case kDownloadStateList:
 		_statusText->setLabel(_("Downloading icons list..."));
 		_cancelButton->setLabel(_("Cancel download"));
@@ -201,7 +211,7 @@ void DownloadIconsDialog::handleTickle() {
 		return;
 	}
 
-	int32 progress = (int32)(100 * CloudMan.getDownloadingProgress());
+	int32 progress = getDownloadingProgress();
 	if (_progressBar->getValue() != progress) {
 		refreshWidgets();
 		g_gui.scheduleTopDialogRedraw();
@@ -217,30 +227,30 @@ void DownloadIconsDialog::reflowLayout() {
 
 Common::U32String DownloadIconsDialog::getSizeLabelText() {
 	Common::String downloaded, downloadedUnits, total, totalUnits;
-	downloaded = getHumanReadableBytes(CloudMan.getDownloadBytesNumber(), downloadedUnits);
-	total = getHumanReadableBytes(CloudMan.getDownloadTotalBytesNumber(), totalUnits);
+	downloaded = getHumanReadableBytes(g_state->downloadedsize, downloadedUnits);
+	total = getHumanReadableBytes(g_state->totalsize, totalUnits);
 	return Common::U32String::format(_("Downloaded %s %S / %s %S"), downloaded.c_str(), _(downloadedUnits).c_str(), total.c_str(), _(totalUnits).c_str());
 }
 
 Common::U32String DownloadIconsDialog::getSpeedLabelText() {
 	Common::String speed, speedUnits;
-	speed = getHumanReadableBytes(CloudMan.getDownloadSpeed(), speedUnits);
+	speed = getHumanReadableBytes(getDownloadSpeed(), speedUnits);
 	speedUnits += "/s";
 	return Common::U32String::format(_("Download speed: %s %S"), speed.c_str(), _(speedUnits).c_str());
 }
 
 void DownloadIconsDialog::refreshWidgets() {
-	uint32 progress = (uint32)(100 * CloudMan.getDownloadingProgress());
+	uint32 progress = getDownloadingProgress();
 	_percentLabel->setLabel(Common::String::format("%u %%", progress));
 	_downloadSizeLabel->setLabel(getSizeLabelText());
 	_downloadSpeedLabel->setLabel(getSpeedLabelText());
 	_progressBar->setValue(progress);
 }
 
-void DownloadIconsDialog::downloadListCallback(Networking::DataResponse response) {
-	Networking::SessionRequest *req = dynamic_cast<Networking::SessionRequest *>(response.request);
+void DownloadIconsDialog::downloadListCallback(Networking::DataResponse r) {
+	Networking::SessionFileResponse *response = static_cast<Networking::SessionFileResponse *>(r.value);
 
-	Common::MemoryReadStream stream(req->getData(), req->getSize());
+	Common::MemoryReadStream stream(response->buffer, response->len);
 
 	int nline = 0;
 
@@ -280,7 +290,7 @@ void DownloadIconsDialog::errorCallback(Networking::ErrorResponse error) {
 }
 
 void DownloadIconsDialog::downloadList() {
-	Networking::SessionRequest *rq = g_state->session.get("https://downloads.scummvm.org/frs/icons/LIST",
+	Networking::SessionRequest *rq = g_state->session.get("https://downloads.scummvm.org/frs/icons/LIST", "",
 		new Common::Callback<DownloadIconsDialog, Networking::DataResponse>(this, &DownloadIconsDialog::downloadListCallback),
 		new Common::Callback<DownloadIconsDialog, Networking::ErrorResponse>(this, &DownloadIconsDialog::errorCallback),
 		true);
@@ -318,27 +328,35 @@ void DownloadIconsDialog::calculateList() {
 	}
 
 	if (g_state->totalsize == 0) {
-		_statusText->setLabel(_("No new icons packs available"));
+		Common::U32String error(_("No new icons packs available"));
+		setError(error);
 		return;
 	}
 
 	setState(kDownloadStateListCalculated);
 }
 
-void DownloadIconsDialog::downloadFileCallback(Networking::DataResponse response) {
-	Networking::SessionRequest *req = dynamic_cast<Networking::SessionRequest *>(response.request);
+void DownloadIconsDialog::downloadFileCallback(Networking::DataResponse r) {
+	Networking::SessionFileResponse *response = static_cast<Networking::SessionFileResponse *>(r.value);
+
+	warning("Read %u bytes", response->len);
+
+	if (response->eos) {
+		sendCommand(kDownloadEndedCmd, 0);
+		return;
+	}
 
-	warning("Got %d bytes", req->getSize());
+	sendCommand(kDownloadProgressCmd, 0);
 }
 
 void DownloadIconsDialog::proceedDownload() {
 	for (auto f = g_state->fileHash.begin(); f != g_state->fileHash.end(); ++f) {
 		Common::String url = Common::String::format("https://downloads.scummvm.org/frs/icons/%s", f->_key.c_str());
+		Common::String localFile = normalizePath(ConfMan.get("iconspath") + "/" + f->_key, '/');
 
-		Networking::SessionRequest *rq = g_state->session.get(url,
+		Networking::SessionRequest *rq = g_state->session.get(url, localFile,
 			new Common::Callback<DownloadIconsDialog, Networking::DataResponse>(this, &DownloadIconsDialog::downloadFileCallback),
-			new Common::Callback<DownloadIconsDialog, Networking::ErrorResponse>(this, &DownloadIconsDialog::errorCallback),
-			true);
+			new Common::Callback<DownloadIconsDialog, Networking::ErrorResponse>(this, &DownloadIconsDialog::errorCallback));
 
 		rq->start();
 	}
diff --git a/gui/downloadiconsdialog.h b/gui/downloadiconsdialog.h
index 0acdd41ce3..64e3fd6617 100644
--- a/gui/downloadiconsdialog.h
+++ b/gui/downloadiconsdialog.h
@@ -38,6 +38,7 @@ class ButtonWidget;
 class SliderWidget;
 
 enum IconProcessState {
+	kDownloadStateNone,
 	kDownloadStateList,
 	kDownloadStateListDownloaded,
 	kDownloadStateListCalculated,


Commit: 570c77f309761aaee6b78ea065c39d26a7c2bb24
    https://github.com/scummvm/scummvm/commit/570c77f309761aaee6b78ea065c39d26a7c2bb24
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:43+01:00

Commit Message:
GUI: Fixed progress bar in icons downloader

Changed paths:
    gui/downloadiconsdialog.cpp
    gui/downloadiconsdialog.h


diff --git a/gui/downloadiconsdialog.cpp b/gui/downloadiconsdialog.cpp
index 5798ffb1c4..3b44ded05e 100644
--- a/gui/downloadiconsdialog.cpp
+++ b/gui/downloadiconsdialog.cpp
@@ -58,10 +58,12 @@ struct DialogState {
 } static *g_state;
 
 static uint32 getDownloadingProgress() {
-	if (!g_state)
+	if (!g_state || g_state->totalsize == 0)
 		return 0;
 
-	return 100 * g_state->downloadedsize / (g_state->totalsize ? g_state->totalsize : 1);
+	uint32 progress = (uint32)(100 * ((double)g_state->downloadedsize / (double)g_state->totalsize));
+
+	return progress;
 }
 
 static uint32 getDownloadSpeed() {
@@ -168,6 +170,21 @@ void DownloadIconsDialog::setState(IconProcessState state) {
 		_closeButton->setCmd(kCloseCmd);
 		_closeButton->setEnabled(true);
 		break;
+
+	case kDownloadComplete: {
+			Common::String size, sizeUnits;
+			size = getHumanReadableBytes(g_state->totalsize, sizeUnits);
+			_statusText->setLabel(Common::U32String::format(_("Download complete, downloaded %d packs, %s %S"), g_state->fileHash.size(), size.c_str(), _(sizeUnits).c_str()));
+			_closeButton->setVisible(false);
+			_cancelButton->setLabel(_("Cancel download"));
+			_cancelButton->setCmd(kDownloadCancelCmd);
+
+			_closeButton->setVisible(true);
+			_closeButton->setLabel(_("Close"));
+			_closeButton->setCmd(kCloseCmd);
+			_closeButton->setEnabled(true);
+			break;
+		}
 	}
 }
 
@@ -189,7 +206,7 @@ void DownloadIconsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
 		}
 		break;
 	case kDownloadEndedCmd:
-		_close = true;
+		setState(kDownloadComplete);
 		break;
 	case kListDownloadFinishedCmd:
 		setState(kDownloadStateListDownloaded);
@@ -339,7 +356,7 @@ void DownloadIconsDialog::calculateList() {
 void DownloadIconsDialog::downloadFileCallback(Networking::DataResponse r) {
 	Networking::SessionFileResponse *response = static_cast<Networking::SessionFileResponse *>(r.value);
 
-	warning("Read %u bytes", response->len);
+	g_state->downloadedsize += response->len;
 
 	if (response->eos) {
 		sendCommand(kDownloadEndedCmd, 0);
diff --git a/gui/downloadiconsdialog.h b/gui/downloadiconsdialog.h
index 64e3fd6617..926bb1f5d8 100644
--- a/gui/downloadiconsdialog.h
+++ b/gui/downloadiconsdialog.h
@@ -42,7 +42,8 @@ enum IconProcessState {
 	kDownloadStateList,
 	kDownloadStateListDownloaded,
 	kDownloadStateListCalculated,
-	kDownloadStateDownloading
+	kDownloadStateDownloading,
+	kDownloadComplete
 };
 
 class DownloadIconsDialog : public Dialog, public CommandSender {


Commit: 5df691a3a681311576d032f06afc922c9847f5c7
    https://github.com/scummvm/scummvm/commit/5df691a3a681311576d032f06afc922c9847f5c7
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:43+01:00

Commit Message:
BACKENDS: NETWORKING: Properly signal end of downloaded file

Changed paths:
    backends/networking/curl/sessionrequest.cpp


diff --git a/backends/networking/curl/sessionrequest.cpp b/backends/networking/curl/sessionrequest.cpp
index 8ad933ea0e..2520d12b0d 100644
--- a/backends/networking/curl/sessionrequest.cpp
+++ b/backends/networking/curl/sessionrequest.cpp
@@ -105,7 +105,7 @@ void SessionRequest::finishSuccess() {
 	_complete = true;
 	_success = true;
 
-	if (_callback && !_localFile) {	// If localfile is present, we already called the callback
+	if (_callback) {	// If localfile is present, contentStream is empty, so it is fine
 		_response.buffer = _contentsStream.getData();
 		_response.len = _contentsStream.size();
 		_response.eos = true;


Commit: 4e32936376130f2ca64da7353570428bbb13df9d
    https://github.com/scummvm/scummvm/commit/4e32936376130f2ca64da7353570428bbb13df9d
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:44+01:00

Commit Message:
GUI: Calculate download speed in Icons downloader

Changed paths:
    gui/downloadiconsdialog.cpp


diff --git a/gui/downloadiconsdialog.cpp b/gui/downloadiconsdialog.cpp
index 3b44ded05e..9fd46f9a2a 100644
--- a/gui/downloadiconsdialog.cpp
+++ b/gui/downloadiconsdialog.cpp
@@ -51,23 +51,26 @@ struct DialogState {
 	Networking::Session session;
 	Common::HashMap<Common::String, uint32> fileHash;
 	IconProcessState state;
-	uint32 downloadedsize;
-	uint32 totalsize;
+	uint32 downloadedSize;
+	uint32 totalSize;
+	uint32 startTime;
 
-	DialogState() { state = kDownloadStateNone; downloadedsize = totalsize = 0; dialog = nullptr; }
+	DialogState() { state = kDownloadStateNone; downloadedSize = totalSize = 0; dialog = nullptr; }
 } static *g_state;
 
 static uint32 getDownloadingProgress() {
-	if (!g_state || g_state->totalsize == 0)
+	if (!g_state || g_state->totalSize == 0)
 		return 0;
 
-	uint32 progress = (uint32)(100 * ((double)g_state->downloadedsize / (double)g_state->totalsize));
+	uint32 progress = (uint32)(100 * ((double)g_state->downloadedSize / (double)g_state->totalSize));
 
 	return progress;
 }
 
 static uint32 getDownloadSpeed() {
-	return 0;
+	uint32 speed = 1000 * ((double)g_state->downloadedSize / (g_system->getMillis() - g_state->startTime));
+
+	return speed;
 }
 
 DownloadIconsDialog::DownloadIconsDialog() :
@@ -134,7 +137,7 @@ void DownloadIconsDialog::setState(IconProcessState state) {
 		_cancelButton->setCmd(kDownloadCancelCmd);
 		_closeButton->setVisible(false);
 
-		g_state->totalsize = 0;
+		g_state->totalSize = 0;
 		g_state->fileHash.clear();
 		break;
 
@@ -147,7 +150,7 @@ void DownloadIconsDialog::setState(IconProcessState state) {
 
 	case kDownloadStateListCalculated: {
 			Common::String size, sizeUnits;
-			size = getHumanReadableBytes(g_state->totalsize, sizeUnits);
+			size = getHumanReadableBytes(g_state->totalSize, sizeUnits);
 
 			_statusText->setLabel(Common::U32String::format(_("Detected %d new packs, %s %S"), g_state->fileHash.size(), size.c_str(), _(sizeUnits).c_str()));
 
@@ -173,9 +176,9 @@ void DownloadIconsDialog::setState(IconProcessState state) {
 
 	case kDownloadComplete: {
 			Common::String size, sizeUnits;
-			size = getHumanReadableBytes(g_state->totalsize, sizeUnits);
+			size = getHumanReadableBytes(g_state->totalSize, sizeUnits);
 			_statusText->setLabel(Common::U32String::format(_("Download complete, downloaded %d packs, %s %S"), g_state->fileHash.size(), size.c_str(), _(sizeUnits).c_str()));
-			_closeButton->setVisible(false);
+			_cancelButton->setVisible(false);
 			_cancelButton->setLabel(_("Cancel download"));
 			_cancelButton->setCmd(kDownloadCancelCmd);
 
@@ -244,8 +247,8 @@ void DownloadIconsDialog::reflowLayout() {
 
 Common::U32String DownloadIconsDialog::getSizeLabelText() {
 	Common::String downloaded, downloadedUnits, total, totalUnits;
-	downloaded = getHumanReadableBytes(g_state->downloadedsize, downloadedUnits);
-	total = getHumanReadableBytes(g_state->totalsize, totalUnits);
+	downloaded = getHumanReadableBytes(g_state->downloadedSize, downloadedUnits);
+	total = getHumanReadableBytes(g_state->totalSize, totalUnits);
 	return Common::U32String::format(_("Downloaded %s %S / %s %S"), downloaded.c_str(), _(downloadedUnits).c_str(), total.c_str(), _(totalUnits).c_str());
 }
 
@@ -339,12 +342,12 @@ void DownloadIconsDialog::calculateList() {
 	delete iconDir;
 
 	// Now calculate the size of the missing files
-	g_state->totalsize = 0;
+	g_state->totalSize = 0;
 	for (auto f = g_state->fileHash.begin(); f != g_state->fileHash.end(); ++f) {
-		g_state->totalsize += f->_value;
+		g_state->totalSize += f->_value;
 	}
 
-	if (g_state->totalsize == 0) {
+	if (g_state->totalSize == 0) {
 		Common::U32String error(_("No new icons packs available"));
 		setError(error);
 		return;
@@ -356,7 +359,7 @@ void DownloadIconsDialog::calculateList() {
 void DownloadIconsDialog::downloadFileCallback(Networking::DataResponse r) {
 	Networking::SessionFileResponse *response = static_cast<Networking::SessionFileResponse *>(r.value);
 
-	g_state->downloadedsize += response->len;
+	g_state->downloadedSize += response->len;
 
 	if (response->eos) {
 		sendCommand(kDownloadEndedCmd, 0);
@@ -367,6 +370,8 @@ void DownloadIconsDialog::downloadFileCallback(Networking::DataResponse r) {
 }
 
 void DownloadIconsDialog::proceedDownload() {
+	g_state->startTime = g_system->getMillis();
+
 	for (auto f = g_state->fileHash.begin(); f != g_state->fileHash.end(); ++f) {
 		Common::String url = Common::String::format("https://downloads.scummvm.org/frs/icons/%s", f->_key.c_str());
 		Common::String localFile = normalizePath(ConfMan.get("iconspath") + "/" + f->_key, '/');


Commit: 1507559a66855e7f4855c7085c081e520be03c79
    https://github.com/scummvm/scummvm/commit/1507559a66855e7f4855c7085c081e520be03c79
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:44+01:00

Commit Message:
BACKENDS: NETWORKING: Fix local file downloading when stream is reused

Changed paths:
    backends/networking/curl/sessionrequest.cpp


diff --git a/backends/networking/curl/sessionrequest.cpp b/backends/networking/curl/sessionrequest.cpp
index 2520d12b0d..3213c2dab9 100644
--- a/backends/networking/curl/sessionrequest.cpp
+++ b/backends/networking/curl/sessionrequest.cpp
@@ -62,6 +62,8 @@ void SessionRequest::openLocalFile(Common::String localFile) {
 		return;
 	}
 
+	debug(5, "SessionRequest: opened localfile %s", localFile.c_str());
+
 	_binary = true; // Enforce binary
 }
 
@@ -105,6 +107,11 @@ void SessionRequest::finishSuccess() {
 	_complete = true;
 	_success = true;
 
+	if (_localFile) {
+		_localFile->close();
+		_localFile = nullptr;
+	}
+
 	if (_callback) {	// If localfile is present, contentStream is empty, so it is fine
 		_response.buffer = _contentsStream.getData();
 		_response.len = _contentsStream.size();
@@ -112,11 +119,6 @@ void SessionRequest::finishSuccess() {
 
 		(*_callback)(DataResponse(this, &_response));
 	}
-
-	if (_localFile) {
-		_localFile->close();
-		_localFile = nullptr;
-	}
 }
 
 void SessionRequest::start() {


Commit: 8fc89ec10f95dc690555c6d9833653a5809c2521
    https://github.com/scummvm/scummvm/commit/8fc89ec10f95dc690555c6d9833653a5809c2521
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:38:44+01:00

Commit Message:
GUI: Fix multiple icon packs downloading. We cannot fire all the requests at once

Changed paths:
    gui/downloadiconsdialog.cpp
    gui/downloadiconsdialog.h


diff --git a/gui/downloadiconsdialog.cpp b/gui/downloadiconsdialog.cpp
index 9fd46f9a2a..59185fd8bf 100644
--- a/gui/downloadiconsdialog.cpp
+++ b/gui/downloadiconsdialog.cpp
@@ -53,9 +53,10 @@ struct DialogState {
 	IconProcessState state;
 	uint32 downloadedSize;
 	uint32 totalSize;
+	uint32 totalFiles;
 	uint32 startTime;
 
-	DialogState() { state = kDownloadStateNone; downloadedSize = totalSize = 0; dialog = nullptr; }
+	DialogState() { state = kDownloadStateNone; downloadedSize = totalSize = totalFiles = startTime = 0; dialog = nullptr; }
 } static *g_state;
 
 static uint32 getDownloadingProgress() {
@@ -177,7 +178,7 @@ void DownloadIconsDialog::setState(IconProcessState state) {
 	case kDownloadComplete: {
 			Common::String size, sizeUnits;
 			size = getHumanReadableBytes(g_state->totalSize, sizeUnits);
-			_statusText->setLabel(Common::U32String::format(_("Download complete, downloaded %d packs, %s %S"), g_state->fileHash.size(), size.c_str(), _(sizeUnits).c_str()));
+			_statusText->setLabel(Common::U32String::format(_("Download complete, downloaded %d packs, %s %S"), g_state->totalFiles, size.c_str(), _(sizeUnits).c_str()));
 			_cancelButton->setVisible(false);
 			_cancelButton->setLabel(_("Cancel download"));
 			_cancelButton->setCmd(kDownloadCancelCmd);
@@ -347,6 +348,8 @@ void DownloadIconsDialog::calculateList() {
 		g_state->totalSize += f->_value;
 	}
 
+	g_state->totalFiles = g_state->fileHash.size();
+
 	if (g_state->totalSize == 0) {
 		Common::U32String error(_("No new icons packs available"));
 		setError(error);
@@ -356,14 +359,38 @@ void DownloadIconsDialog::calculateList() {
 	setState(kDownloadStateListCalculated);
 }
 
+bool DownloadIconsDialog::takeOneFile() {
+	auto f = g_state->fileHash.begin();
+
+	if (f == g_state->fileHash.end())
+		return false;
+
+	Common::String fname = f->_key;
+
+	g_state->fileHash.erase(fname);
+
+	Common::String url = Common::String::format("https://downloads.scummvm.org/frs/icons/%s", fname.c_str());
+	Common::String localFile = normalizePath(ConfMan.get("iconspath") + "/" + fname, '/');
+
+	Networking::SessionRequest *rq = g_state->session.get(url, localFile,
+		new Common::Callback<DownloadIconsDialog, Networking::DataResponse>(this, &DownloadIconsDialog::downloadFileCallback),
+		new Common::Callback<DownloadIconsDialog, Networking::ErrorResponse>(this, &DownloadIconsDialog::errorCallback));
+
+	rq->start();
+
+	return true;
+}
+
 void DownloadIconsDialog::downloadFileCallback(Networking::DataResponse r) {
 	Networking::SessionFileResponse *response = static_cast<Networking::SessionFileResponse *>(r.value);
 
 	g_state->downloadedSize += response->len;
 
 	if (response->eos) {
-		sendCommand(kDownloadEndedCmd, 0);
-		return;
+		if (!takeOneFile()) {
+			sendCommand(kDownloadEndedCmd, 0);
+			return;
+		}
 	}
 
 	sendCommand(kDownloadProgressCmd, 0);
@@ -372,16 +399,7 @@ void DownloadIconsDialog::downloadFileCallback(Networking::DataResponse r) {
 void DownloadIconsDialog::proceedDownload() {
 	g_state->startTime = g_system->getMillis();
 
-	for (auto f = g_state->fileHash.begin(); f != g_state->fileHash.end(); ++f) {
-		Common::String url = Common::String::format("https://downloads.scummvm.org/frs/icons/%s", f->_key.c_str());
-		Common::String localFile = normalizePath(ConfMan.get("iconspath") + "/" + f->_key, '/');
-
-		Networking::SessionRequest *rq = g_state->session.get(url, localFile,
-			new Common::Callback<DownloadIconsDialog, Networking::DataResponse>(this, &DownloadIconsDialog::downloadFileCallback),
-			new Common::Callback<DownloadIconsDialog, Networking::ErrorResponse>(this, &DownloadIconsDialog::errorCallback));
-
-		rq->start();
-	}
+	takeOneFile();
 }
 
 
diff --git a/gui/downloadiconsdialog.h b/gui/downloadiconsdialog.h
index 926bb1f5d8..4dd9faadad 100644
--- a/gui/downloadiconsdialog.h
+++ b/gui/downloadiconsdialog.h
@@ -85,6 +85,7 @@ private:
 	void calculateList();
 	void proceedDownload();
 	void setState(IconProcessState state);
+	bool takeOneFile();
 };
 
 } // End of namespace GUI


Commit: 722288474f3fc279fa0dd2d5a1a31ea4cb5b383e
    https://github.com/scummvm/scummvm/commit/722288474f3fc279fa0dd2d5a1a31ea4cb5b383e
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2021-11-18T22:55:18+01:00

Commit Message:
GUI: Synced all themes with Icons Downloader and bumped theme version

Changed paths:
    gui/ThemeEngine.h
    gui/themes/default.inc
    gui/themes/residualvm.zip
    gui/themes/residualvm/THEMERC
    gui/themes/residualvm/remastered_layout.stx
    gui/themes/residualvm/remastered_layout_lowres.stx
    gui/themes/scummclassic.zip
    gui/themes/scummclassic/THEMERC
    gui/themes/scummclassic/classic_layout.stx
    gui/themes/scummclassic/classic_layout_lowres.stx
    gui/themes/scummmodern.zip
    gui/themes/scummmodern/THEMERC
    gui/themes/scummmodern/scummmodern_layout.stx
    gui/themes/scummmodern/scummmodern_layout_lowres.stx
    gui/themes/scummremastered.zip
    gui/themes/scummremastered/THEMERC


diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 07cc90af83..a85c662e43 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -37,7 +37,7 @@
 #include "graphics/pixelformat.h"
 
 
-#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.52"
+#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.53"
 
 class OSystem;
 
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 3b4ed6fbda..9f8490f794 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -2078,6 +2078,9 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "type='Checkbox' "
 "/>"
 "</layout>"
+"<widget name='UpdateIconsButton' "
+"type='Button' "
+"/>"
 "<layout type='horizontal' padding='0,0,0,0' spacing='10' align='center'>"
 "<widget name='DiscordRpc' "
 "type='Checkbox' "
@@ -2276,7 +2279,41 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "</layout>"
 "</layout>"
 "</dialog>"
-"<dialog name='GlobalOptions_Cloud_DownloadDialog' overlays='Dialog.GlobalOptions'>"
+"<dialog name='GlobalOptions_DownloadIconsDialog' overlays='Dialog.GlobalOptions' shading='dim'>"
+"<layout type='vertical' padding='16,16,16,8' spacing='8'>"
+"<widget name='StatusText' "
+"height='Globals.Line.Height' "
+"/>"
+"<widget name='ErrorText' "
+"height='Globals.Line.Height' "
+"/>"
+"<widget name='ProgressBar' "
+"height='Globals.Button.Height' "
+"/>"
+"<space size='1'/>"
+"<widget name='PercentText' "
+"height='Globals.Line.Height' "
+"textalign='center' "
+"/>"
+"<widget name='DownloadSize' "
+"height='Globals.Line.Height' "
+"/>"
+"<widget name='DownloadSpeed' "
+"height='Globals.Line.Height' "
+"/>"
+"<space/>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'>"
+"<widget name='MainButton' "
+"type='Button' "
+"/>"
+"<space/>"
+"<widget name='CloseButton' "
+"type='Button' "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='GlobalOptions_Cloud_DownloadDialog' overlays='Dialog.GlobalOptions' shading='dim'>"
 "<layout type='vertical' padding='16,16,16,8' spacing='8'>"
 "<widget name='RemoteDirectory' "
 "height='Globals.Line.Height' "
@@ -2310,7 +2347,7 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "</layout>"
 "</layout>"
 "</dialog>"
-"<dialog name='GlobalOptions_Cloud_ConnectionWizard' overlays='Dialog.GlobalOptions'>"
+"<dialog name='GlobalOptions_Cloud_ConnectionWizard' overlays='Dialog.GlobalOptions' shading='dim'>"
 "<layout type='vertical' padding='0,0,0,0'>"
 "<widget name='Container'/>"
 "</layout>"
@@ -3963,6 +4000,9 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "type='Checkbox' "
 "/>"
 "</layout>"
+"<widget name='UpdateIconsButton' "
+"type='Button' "
+"/>"
 "<layout type='horizontal' padding='0,0,0,0' spacing='10' align='center'>"
 "<widget name='DiscordRpc' "
 "type='Checkbox' "
@@ -4166,7 +4206,41 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "</layout>"
 "</layout>"
 "</dialog>"
-"<dialog name='GlobalOptions_Cloud_DownloadDialog' overlays='Dialog.GlobalOptions'>"
+"<dialog name='GlobalOptions_DownloadIconsDialog' overlays='Dialog.GlobalOptions' shading='dim'>"
+"<layout type='vertical' padding='8,8,8,4' spacing='8'>"
+"<widget name='StatusText' "
+"height='Globals.Line.Height' "
+"/>"
+"<widget name='ErrorText' "
+"height='Globals.Line.Height' "
+"/>"
+"<widget name='ProgressBar' "
+"height='Globals.Button.Height' "
+"/>"
+"<space size='1'/>"
+"<widget name='PercentText' "
+"height='Globals.Line.Height' "
+"textalign='center' "
+"/>"
+"<widget name='DownloadSize' "
+"height='Globals.Line.Height' "
+"/>"
+"<widget name='DownloadSpeed' "
+"height='Globals.Line.Height' "
+"/>"
+"<space/>"
+"<layout type='horizontal' padding='0,0,0,0' spacing='6'>"
+"<widget name='MainButton' "
+"type='Button' "
+"/>"
+"<space/>"
+"<widget name='CloseButton' "
+"type='Button' "
+"/>"
+"</layout>"
+"</layout>"
+"</dialog>"
+"<dialog name='GlobalOptions_Cloud_DownloadDialog' overlays='Dialog.GlobalOptions' shading='dim'>"
 "<layout type='vertical' padding='8,8,8,4' spacing='8'>"
 "<widget name='RemoteDirectory' "
 "height='Globals.Line.Height' "
@@ -4200,7 +4274,7 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "</layout>"
 "</layout>"
 "</dialog>"
-"<dialog name='GlobalOptions_Cloud_ConnectionWizard' overlays='Dialog.GlobalOptions'>"
+"<dialog name='GlobalOptions_Cloud_ConnectionWizard' overlays='Dialog.GlobalOptions' shading='dim'>"
 "<layout type='vertical' padding='0,0,0,0'>"
 "<widget name='Container'/>"
 "</layout>"
diff --git a/gui/themes/residualvm.zip b/gui/themes/residualvm.zip
index 81d0474601..8f919bb801 100644
Binary files a/gui/themes/residualvm.zip and b/gui/themes/residualvm.zip differ
diff --git a/gui/themes/residualvm/THEMERC b/gui/themes/residualvm/THEMERC
index 923dc07978..6d3bb76f38 100644
--- a/gui/themes/residualvm/THEMERC
+++ b/gui/themes/residualvm/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.52:ResidualVM Modern Theme Remastered:No Author]
+[SCUMMVM_STX0.8.53:ResidualVM Modern Theme Remastered:No Author]
diff --git a/gui/themes/residualvm/remastered_layout.stx b/gui/themes/residualvm/remastered_layout.stx
index ff40e83cbe..b6df042bc3 100644
--- a/gui/themes/residualvm/remastered_layout.stx
+++ b/gui/themes/residualvm/remastered_layout.stx
@@ -816,6 +816,9 @@
 						type = 'Checkbox'
 				/>
 			</layout>
+			<widget name = 'UpdateIconsButton'
+					type = 'Button'
+			/>
 			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
 				<widget name = 'DiscordRpc'
 						type = 'Checkbox'
@@ -1020,7 +1023,42 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_DownloadIconsDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
+		<layout type = 'vertical' padding = '16, 16, 16, 8' spacing = '8'>
+			<widget name = 'StatusText'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'ErrorText'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'ProgressBar'
+					height = 'Globals.Button.Height'
+			/>
+			<space size = '1'/>
+			<widget name = 'PercentText'
+					height = 'Globals.Line.Height'
+					textalign = 'center'
+			/>
+			<widget name = 'DownloadSize'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'DownloadSpeed'
+					height = 'Globals.Line.Height'
+			/>
+			<space/>
+			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'>
+				<widget name = 'MainButton'
+						type = 'Button'
+				/>
+				<space/>
+				<widget name = 'CloseButton'
+						type = 'Button'
+				/>
+			</layout>
+		</layout>
+	</dialog>
+
+	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '16, 16, 16, 8' spacing = '8'>
 			<widget name = 'RemoteDirectory'
 					height = 'Globals.Line.Height'
@@ -1055,7 +1093,7 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
 		</layout>
diff --git a/gui/themes/residualvm/remastered_layout_lowres.stx b/gui/themes/residualvm/remastered_layout_lowres.stx
index fe37910c08..262c1d19fa 100644
--- a/gui/themes/residualvm/remastered_layout_lowres.stx
+++ b/gui/themes/residualvm/remastered_layout_lowres.stx
@@ -789,6 +789,9 @@
 						type = 'Checkbox'
 				/>
 			</layout>
+			<widget name = 'UpdateIconsButton'
+					type = 'Button'
+			/>
 			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
 				<widget name = 'DiscordRpc'
 						type = 'Checkbox'
@@ -998,7 +1001,42 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_DownloadIconsDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
+		<layout type = 'vertical' padding = '8, 8, 8, 4' spacing = '8'>
+			<widget name = 'StatusText'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'ErrorText'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'ProgressBar'
+					height = 'Globals.Button.Height'
+			/>
+			<space size = '1'/>
+			<widget name = 'PercentText'
+					height = 'Globals.Line.Height'
+					textalign = 'center'
+			/>
+			<widget name = 'DownloadSize'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'DownloadSpeed'
+					height = 'Globals.Line.Height'
+			/>
+			<space/>
+			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6'>
+				<widget name = 'MainButton'
+						type = 'Button'
+				/>
+				<space/>
+				<widget name = 'CloseButton'
+						type = 'Button'
+				/>
+			</layout>
+		</layout>
+	</dialog>
+
+	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '8, 8, 8, 4' spacing = '8'>
 			<widget name = 'RemoteDirectory'
 					height = 'Globals.Line.Height'
@@ -1033,7 +1071,7 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
 		</layout>
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index 28ca127c28..5621bbdeaa 100644
Binary files a/gui/themes/scummclassic.zip and b/gui/themes/scummclassic.zip differ
diff --git a/gui/themes/scummclassic/THEMERC b/gui/themes/scummclassic/THEMERC
index a5b4bd514c..b0288b9dab 100644
--- a/gui/themes/scummclassic/THEMERC
+++ b/gui/themes/scummclassic/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.52:ScummVM Classic Theme:No Author]
+[SCUMMVM_STX0.8.53:ScummVM Classic Theme:No Author]
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index b172bc7f00..96e283e46a 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -702,6 +702,9 @@
 						type = 'Checkbox'
 				/>
 			</layout>
+			<widget name = 'UpdateIconsButton'
+					type = 'Button'
+			/>
 			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
 				<widget name = 'DiscordRpc'
 						type = 'Checkbox'
@@ -906,7 +909,42 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_DownloadIconsDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
+		<layout type = 'vertical' padding = '16, 16, 16, 8' spacing = '8'>
+			<widget name = 'StatusText'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'ErrorText'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'ProgressBar'
+					height = 'Globals.Button.Height'
+			/>
+			<space size = '1'/>
+			<widget name = 'PercentText'
+					height = 'Globals.Line.Height'
+					textalign = 'center'
+			/>
+			<widget name = 'DownloadSize'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'DownloadSpeed'
+					height = 'Globals.Line.Height'
+			/>
+			<space/>
+			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'>
+				<widget name = 'MainButton'
+						type = 'Button'
+				/>
+				<space/>
+				<widget name = 'CloseButton'
+						type = 'Button'
+				/>
+			</layout>
+		</layout>
+	</dialog>
+
+	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '16, 16, 16, 8' spacing = '8'>
 			<widget name = 'RemoteDirectory'
 					height = 'Globals.Line.Height'
@@ -941,7 +979,7 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
 		</layout>
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index 56c7367358..e214895463 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -706,6 +706,9 @@
 						type = 'Checkbox'
 				/>
 			</layout>
+			<widget name = 'UpdateIconsButton'
+					type = 'Button'
+			/>
 			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
 				<widget name = 'DiscordRpc'
 						type = 'Checkbox'
@@ -915,7 +918,42 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_DownloadIconsDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
+		<layout type = 'vertical' padding = '8, 8, 8, 4' spacing = '8'>
+			<widget name = 'StatusText'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'ErrorText'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'ProgressBar'
+					height = 'Globals.Button.Height'
+			/>
+			<space size = '1'/>
+			<widget name = 'PercentText'
+					height = 'Globals.Line.Height'
+					textalign = 'center'
+			/>
+			<widget name = 'DownloadSize'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'DownloadSpeed'
+					height = 'Globals.Line.Height'
+			/>
+			<space/>
+			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6'>
+				<widget name = 'MainButton'
+						type = 'Button'
+				/>
+				<space/>
+				<widget name = 'CloseButton'
+						type = 'Button'
+				/>
+			</layout>
+		</layout>
+	</dialog>
+
+	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '8, 8, 8, 4' spacing = '8'>
 			<widget name = 'RemoteDirectory'
 					height = 'Globals.Line.Height'
@@ -950,7 +988,7 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
 		</layout>
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index bb3f02604b..ac2d7208a3 100644
Binary files a/gui/themes/scummmodern.zip and b/gui/themes/scummmodern.zip differ
diff --git a/gui/themes/scummmodern/THEMERC b/gui/themes/scummmodern/THEMERC
index f90b72deb8..f50d108d02 100644
--- a/gui/themes/scummmodern/THEMERC
+++ b/gui/themes/scummmodern/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.52:ScummVM Modern Theme:No Author]
+[SCUMMVM_STX0.8.53:ScummVM Modern Theme:No Author]
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index 4812ff5717..42910e4e71 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -815,6 +815,9 @@
 						type = 'Checkbox'
 				/>
 			</layout>
+			<widget name = 'UpdateIconsButton'
+					type = 'Button'
+			/>
 			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
 				<widget name = 'DiscordRpc'
 						type = 'Checkbox'
@@ -1019,7 +1022,42 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_DownloadIconsDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
+		<layout type = 'vertical' padding = '16, 16, 16, 8' spacing = '8'>
+			<widget name = 'StatusText'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'ErrorText'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'ProgressBar'
+					height = 'Globals.Button.Height'
+			/>
+			<space size = '1'/>
+			<widget name = 'PercentText'
+					height = 'Globals.Line.Height'
+					textalign = 'center'
+			/>
+			<widget name = 'DownloadSize'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'DownloadSpeed'
+					height = 'Globals.Line.Height'
+			/>
+			<space/>
+			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'>
+				<widget name = 'MainButton'
+						type = 'Button'
+				/>
+				<space/>
+				<widget name = 'CloseButton'
+						type = 'Button'
+				/>
+			</layout>
+		</layout>
+	</dialog>
+
+	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '16, 16, 16, 8' spacing = '8'>
 			<widget name = 'RemoteDirectory'
 					height = 'Globals.Line.Height'
@@ -1054,7 +1092,7 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
 		</layout>
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index 2abc4667cd..7cd5b634a0 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -787,6 +787,9 @@
 						type = 'Checkbox'
 				/>
 			</layout>
+			<widget name = 'UpdateIconsButton'
+					type = 'Button'
+			/>
 			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
 				<widget name = 'DiscordRpc'
 						type = 'Checkbox'
@@ -996,7 +999,42 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_DownloadIconsDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
+		<layout type = 'vertical' padding = '8, 8, 8, 4' spacing = '8'>
+			<widget name = 'StatusText'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'ErrorText'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'ProgressBar'
+					height = 'Globals.Button.Height'
+			/>
+			<space size = '1'/>
+			<widget name = 'PercentText'
+					height = 'Globals.Line.Height'
+					textalign = 'center'
+			/>
+			<widget name = 'DownloadSize'
+					height = 'Globals.Line.Height'
+			/>
+			<widget name = 'DownloadSpeed'
+					height = 'Globals.Line.Height'
+			/>
+			<space/>
+			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6'>
+				<widget name = 'MainButton'
+						type = 'Button'
+				/>
+				<space/>
+				<widget name = 'CloseButton'
+						type = 'Button'
+				/>
+			</layout>
+		</layout>
+	</dialog>
+
+	<dialog name = 'GlobalOptions_Cloud_DownloadDialog' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '8, 8, 8, 4' spacing = '8'>
 			<widget name = 'RemoteDirectory'
 					height = 'Globals.Line.Height'
@@ -1031,7 +1069,7 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions'>
+	<dialog name = 'GlobalOptions_Cloud_ConnectionWizard' overlays = 'Dialog.GlobalOptions' shading = 'dim'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
 		</layout>
diff --git a/gui/themes/scummremastered.zip b/gui/themes/scummremastered.zip
index 5208ba23aa..c67194fe4e 100644
Binary files a/gui/themes/scummremastered.zip and b/gui/themes/scummremastered.zip differ
diff --git a/gui/themes/scummremastered/THEMERC b/gui/themes/scummremastered/THEMERC
index 8160375edd..b25824e24b 100644
--- a/gui/themes/scummremastered/THEMERC
+++ b/gui/themes/scummremastered/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.52:ScummVM Modern Theme Remastered:No Author]
+[SCUMMVM_STX0.8.53:ScummVM Modern Theme Remastered:No Author]




More information about the Scummvm-git-logs mailing list