diff options
Diffstat (limited to 'gui/remotebrowser.cpp')
-rw-r--r-- | gui/remotebrowser.cpp | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/gui/remotebrowser.cpp b/gui/remotebrowser.cpp new file mode 100644 index 0000000000..b87fc60f7e --- /dev/null +++ b/gui/remotebrowser.cpp @@ -0,0 +1,232 @@ +/* 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/remotebrowser.h" +#include "gui/widgets/list.h" + +#include "common/config-manager.h" +#include "common/system.h" +#include "common/algorithm.h" + +#include "common/translation.h" +#include <backends/networking/curl/request.h> +#include <backends/cloud/storage.h> +#include <backends/cloud/cloudmanager.h> +#include "message.h" + +namespace GUI { + +enum { + kChooseCmd = 'Chos', + kGoUpCmd = 'GoUp' +}; + +RemoteBrowserDialog::RemoteBrowserDialog(const char *title): + Dialog("Browser"), _navigationLocked(false), _updateList(false), _showError(false), + _workingRequest(nullptr), _ignoreCallback(false) { + _backgroundType = GUI::ThemeEngine::kDialogBackgroundPlain; + + new StaticTextWidget(this, "Browser.Headline", title); + _currentPath = new StaticTextWidget(this, "Browser.Path", "DUMMY"); + + _fileList = new ListWidget(this, "Browser.List"); + _fileList->setNumberingMode(kListNumberingOff); + _fileList->setEditable(false); + + if (g_system->getOverlayWidth() > 320) + new ButtonWidget(this, "Browser.Up", _("Go up"), _("Go to previous directory level"), kGoUpCmd); + else + new ButtonWidget(this, "Browser.Up", _c("Go up", "lowres"), _("Go to previous directory level"), kGoUpCmd); + new ButtonWidget(this, "Browser.Cancel", _("Cancel"), 0, kCloseCmd); + new ButtonWidget(this, "Browser.Choose", _("Choose"), 0, kChooseCmd); +} + +RemoteBrowserDialog::~RemoteBrowserDialog() { + if (_workingRequest) { + _ignoreCallback = true; + _workingRequest->finish(); + } +} + +void RemoteBrowserDialog::open() { + Dialog::open(); + listDirectory(Cloud::StorageFile()); +} + +void RemoteBrowserDialog::close() { + Dialog::close(); + if (_workingRequest) { + _ignoreCallback = true; + _workingRequest->finish(); + _ignoreCallback = false; + } +} + +void RemoteBrowserDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { + switch (cmd) { + case kChooseCmd: { + // If nothing is selected in the list widget, choose the current dir. + // Else, choose the dir that is selected. + int selection = _fileList->getSelected(); + if (selection >= 0) + _choice = _nodeContent[selection]; + else + _choice = _node; + setResult(1); + close(); + break; + } + case kGoUpCmd: + goUp(); + break; + case kListItemActivatedCmd: + case kListItemDoubleClickedCmd: + if (_nodeContent[data].isDirectory()) { + _rememberedNodeContents[_node.path()] = _nodeContent; + listDirectory(_nodeContent[data]); + } + break; + case kListSelectionChangedCmd: + // We do not allow selecting directories, + // thus we will invalidate the selection + // when the user selects a directory over here. + if (data != (uint32)-1 && !_nodeContent[data].isDirectory()) + _fileList->setSelected(-1); + break; + default: + Dialog::handleCommand(sender, cmd, data); + } +} + +void RemoteBrowserDialog::handleTickle() { + if (_updateList) { + updateListing(); + _updateList = false; + } + + if (_showError) { + _showError = false; + MessageDialog alert(_("ScummVM couldn't list the directory!")); + alert.runModal(); + } + + Dialog::handleTickle(); +} + +void RemoteBrowserDialog::updateListing() { + // Update the path display + Common::String path = _node.path(); + if (path.empty()) + path = "/"; //root + if (_navigationLocked) + path = "Loading... " + path; + _currentPath->setLabel(path); + + if (!_navigationLocked) { + // Populate the ListWidget + ListWidget::StringArray list; + ListWidget::ColorList colors; + for (Common::Array<Cloud::StorageFile>::iterator i = _nodeContent.begin(); i != _nodeContent.end(); ++i) { + if (i->isDirectory()) { + list.push_back(i->name() + "/"); + colors.push_back(ThemeEngine::kFontColorNormal); + } else { + list.push_back(i->name()); + colors.push_back(ThemeEngine::kFontColorAlternate); + } + } + + _fileList->setList(list, &colors); + _fileList->scrollTo(0); + } + + _fileList->setEnabled(!_navigationLocked); + + // Finally, redraw + draw(); +} + +void RemoteBrowserDialog::goUp() { + if (_rememberedNodeContents.contains(_node.path())) + _rememberedNodeContents.erase(_node.path()); + + Common::String path = _node.path(); + if (path.size() && (path.lastChar() == '/' || path.lastChar() == '\\')) + path.deleteLastChar(); + if (path.empty()) { + _rememberedNodeContents.erase(""); + } else { + for (int i = path.size() - 1; i >= 0; --i) + if (i == 0 || path[i] == '/' || path[i] == '\\') { + path.erase(i); + break; + } + } + + listDirectory(Cloud::StorageFile(path, 0, 0, true)); +} + +void RemoteBrowserDialog::listDirectory(Cloud::StorageFile node) { + if (_navigationLocked || _workingRequest) + return; + + if (_rememberedNodeContents.contains(node.path())) { + _nodeContent = _rememberedNodeContents[node.path()]; + } else { + _navigationLocked = true; + + _workingRequest = CloudMan.listDirectory( + node.path(), + new Common::Callback<RemoteBrowserDialog, Cloud::Storage::ListDirectoryResponse>(this, &RemoteBrowserDialog::directoryListedCallback), + new Common::Callback<RemoteBrowserDialog, Networking::ErrorResponse>(this, &RemoteBrowserDialog::directoryListedErrorCallback), + false + ); + } + + _backupNode = _node; + _node = node; + updateListing(); +} + +void RemoteBrowserDialog::directoryListedCallback(Cloud::Storage::ListDirectoryResponse response) { + _workingRequest = nullptr; + if (_ignoreCallback) + return; + + _navigationLocked = false; + _nodeContent = response.value; + Common::sort(_nodeContent.begin(), _nodeContent.end(), FileListOrder()); + _updateList = true; +} + +void RemoteBrowserDialog::directoryListedErrorCallback(Networking::ErrorResponse error) { + _workingRequest = nullptr; + if (_ignoreCallback) + return; + + _navigationLocked = false; + _node = _backupNode; + _updateList = true; + _showError = true; +} + +} // End of namespace GUI |