/* 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/gui-manager.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 could not access 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::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 g_gui.scheduleTopDialogRedraw(); } 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(this, &RemoteBrowserDialog::directoryListedCallback), new Common::Callback(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