scummvm/gui/remotebrowser.cpp
2016-09-04 23:25:54 +01:00

233 lines
6.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/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 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<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