scummvm/gui/downloaddialog.cpp
2016-08-24 16:07:55 +06:00

261 lines
8.4 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "gui/downloaddialog.h"
#include "backends/cloud/cloudmanager.h"
#include "common/config-manager.h"
#include "common/translation.h"
#include "engines/metaengine.h"
#include "gui/browser.h"
#include "gui/chooser.h"
#include "gui/editgamedialog.h"
#include "gui/message.h"
#include "gui/remotebrowser.h"
#include "gui/widgets/edittext.h"
#include "gui/widgets/list.h"
namespace GUI {
enum {
kDownloadDialogButtonCmd = 'Dldb'
};
DownloadDialog::DownloadDialog(uint32 storageId):
Dialog("GlobalOptions_Cloud_DownloadDialog"), _close(false) {
_backgroundType = GUI::ThemeEngine::kDialogBackgroundPlain;
_browser = new BrowserDialog(_("Select directory where to download game data"), true);
_remoteBrowser = new RemoteBrowserDialog(_("Select directory with game data"));
_remoteDirectoryLabel = new StaticTextWidget(this, "GlobalOptions_Cloud_DownloadDialog.RemoteDirectory", _("From: "));
_localDirectoryLabel = new StaticTextWidget(this, "GlobalOptions_Cloud_DownloadDialog.LocalDirectory", _("To: "));
uint32 progress = (uint32)(100 * CloudMan.getDownloadingProgress());
_progressBar = new SliderWidget(this, "GlobalOptions_Cloud_DownloadDialog.ProgressBar");
_progressBar->setMinValue(0);
_progressBar->setMaxValue(100);
_progressBar->setValue(progress);
_progressBar->setEnabled(false);
_percentLabel = new StaticTextWidget(this, "GlobalOptions_Cloud_DownloadDialog.PercentText", Common::String::format("%u %%", progress));
if (g_system->getOverlayWidth() > 320)
_cancelButton = new ButtonWidget(this, "GlobalOptions_Cloud_DownloadDialog.MainButton", _("Cancel download"), 0, kDownloadDialogButtonCmd);
else
_cancelButton = new ButtonWidget(this, "GlobalOptions_Cloud_DownloadDialog.MainButton", _c("Cancel download", "lowres"), 0, kDownloadDialogButtonCmd);
_closeButton = new ButtonWidget(this, "GlobalOptions_Cloud_DownloadDialog.CloseButton", _("OK"), 0, kCloseCmd);
refreshWidgets();
CloudMan.setDownloadTarget(this);
}
DownloadDialog::~DownloadDialog() {
CloudMan.setDownloadTarget(nullptr);
}
void DownloadDialog::open() {
Dialog::open();
CloudMan.setDownloadTarget(this);
if (!CloudMan.isDownloading())
if (!selectDirectories())
close();
reflowLayout();
draw();
}
void DownloadDialog::close() {
CloudMan.setDownloadTarget(nullptr);
Dialog::close();
}
void DownloadDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
switch (cmd) {
case kDownloadDialogButtonCmd: {
CloudMan.setDownloadTarget(nullptr);
CloudMan.cancelDownload();
close();
break;
}
case kDownloadProgressCmd:
if (!_close) {
refreshWidgets();
draw();
}
break;
case kDownloadEndedCmd:
_close = true;
break;
default:
Dialog::handleCommand(sender, cmd, data);
}
}
bool DownloadDialog::selectDirectories() {
//first user should select remote directory to download
if (_remoteBrowser->runModal() <= 0) return false;
Cloud::StorageFile remoteDirectory = _remoteBrowser->getResult();
//now user should select local directory to download into
if (_browser->runModal() <= 0) return false;
Common::FSNode dir(_browser->getResult());
Common::FSList files;
if (!dir.getChildren(files, Common::FSNode::kListAll)) {
MessageDialog alert(_("ScummVM couldn't open the specified directory!"));
alert.runModal();
return false;
}
//check that there is no file with the remote directory's name in the local one
for (Common::FSList::iterator i = files.begin(); i != files.end(); ++i) {
if (i->getName().equalsIgnoreCase(remoteDirectory.name())) {
//if there is, ask user whether it's OK
if (!i->isDirectory()) {
GUI::MessageDialog alert(_("Cannot create a directory to download - the specified directory has a file with the same name."), _("OK"));
alert.runModal();
return false;
}
GUI::MessageDialog alert(
Common::String::format(_("The \"%s\" already exists in the specified directory.\nDo you really want to download files into that directory?"), remoteDirectory.name().c_str()),
_("Yes"),
_("No")
);
if (alert.runModal() != GUI::kMessageOK) return false;
break;
}
}
//make a local path
Common::String localPath = dir.getPath();
//simple heuristic to determine which path separator to use
if (localPath.size() && localPath.lastChar() != '/' && localPath.lastChar() != '\\') {
int backslashes = 0;
for (uint32 i = 0; i < localPath.size(); ++i)
if (localPath[i] == '/') --backslashes;
else if (localPath[i] == '\\') ++backslashes;
if (backslashes > 0) localPath += '\\' + remoteDirectory.name();
else localPath += '/' + remoteDirectory.name();
} else localPath += remoteDirectory.name();
CloudMan.startDownload(remoteDirectory.path(), localPath);
CloudMan.setDownloadTarget(this);
_localDirectory = localPath;
return true;
}
void DownloadDialog::handleTickle() {
if (_close) {
addGame();
close();
_close = false;
return;
}
Dialog::handleTickle();
}
void DownloadDialog::addGame() {
// Allow user to add a new game to the list.
// 2) try to auto detect which game is in the directory, if we cannot
// determine it uniquely present a list of candidates to the user
// to pick from
// 3) Display the 'Edit' dialog for that item, letting the user specify
// an alternate description (to distinguish multiple versions of the
// game, e.g. 'Monkey German' and 'Monkey English') and set default
// options for that game
// 4) If no game is found in the specified directory, return to the
// dialog.
// User made his choice...
Common::FSNode dir(_localDirectory);
Common::FSList files;
if (!dir.getChildren(files, Common::FSNode::kListAll)) {
MessageDialog alert(_("ScummVM couldn't open the specified directory!"));
alert.runModal();
return;
}
// ...so let's determine a list of candidates, games that
// could be contained in the specified directory.
GameList candidates(EngineMan.detectGames(files));
int idx;
if (candidates.empty()) {
// No game was found in the specified directory
MessageDialog alert(_("ScummVM could not find any game in the specified directory!"));
alert.runModal();
return;
}
if (candidates.size() == 1) {
// Exact match
idx = 0;
} else {
// Display the candidates to the user and let her/him pick one
Common::StringArray list;
for (idx = 0; idx < (int)candidates.size(); idx++)
list.push_back(candidates[idx].description());
ChooserDialog dialog(_("Pick the game:"));
dialog.setList(list);
idx = dialog.runModal();
}
if (0 <= idx && idx < (int)candidates.size()) {
GameDescriptor result = candidates[idx];
// TODO: Change the detectors to set "path" !
result["path"] = dir.getPath();
Common::String domain = addGameToConf(result);
// Display edit dialog for the new entry
EditGameDialog editDialog(domain, result.description());
if (editDialog.runModal() > 0) {
// User pressed OK, so make changes permanent
// Write config to disk
ConfMan.flushToDisk();
} else {
// User aborted, remove the the new domain again
ConfMan.removeGameDomain(domain);
}
}
}
void DownloadDialog::reflowLayout() {
Dialog::reflowLayout();
refreshWidgets();
}
void DownloadDialog::refreshWidgets() {
_localDirectory = CloudMan.getDownloadLocalDirectory();
_remoteDirectoryLabel->setLabel(_("From: ") + CloudMan.getDownloadRemoteDirectory());
_localDirectoryLabel->setLabel(_("To: ") + _localDirectory);
uint32 progress = (uint32)(100 * CloudMan.getDownloadingProgress());
_percentLabel->setLabel(Common::String::format("%u %%", progress));
_progressBar->setValue(progress);
}
} // End of namespace GUI