Improved 'Mass Detector': Now displays a dialog which displays the scan progress to the user, and can be cancelled (the whole thing still needs to be polished)
svn-id: r25697
This commit is contained in:
parent
e0a7c6d7a7
commit
94507bb44d
5 changed files with 298 additions and 60 deletions
|
@ -36,6 +36,7 @@
|
||||||
#include "gui/chooser.h"
|
#include "gui/chooser.h"
|
||||||
#include "gui/eval.h"
|
#include "gui/eval.h"
|
||||||
#include "gui/launcher.h"
|
#include "gui/launcher.h"
|
||||||
|
#include "gui/massadd.h"
|
||||||
#include "gui/message.h"
|
#include "gui/message.h"
|
||||||
#include "gui/newgui.h"
|
#include "gui/newgui.h"
|
||||||
#include "gui/options.h"
|
#include "gui/options.h"
|
||||||
|
@ -47,6 +48,7 @@
|
||||||
#include "sound/mididrv.h"
|
#include "sound/mididrv.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
using Common::ConfigManager;
|
using Common::ConfigManager;
|
||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
@ -605,34 +607,6 @@ void LauncherDialog::updateListing() {
|
||||||
updateButtons();
|
updateButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherDialog::addGameRecursive(FilesystemNode dir) {
|
|
||||||
FSList files;
|
|
||||||
if (!dir.listDir(files, FilesystemNode::kListAll)) {
|
|
||||||
error("browser returned a node that is not a directory: '%s'",
|
|
||||||
dir.path().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the detector on the dir
|
|
||||||
GameList candidates(PluginManager::instance().detectGames(files));
|
|
||||||
|
|
||||||
if (candidates.size() >= 1) {
|
|
||||||
// At least one match was found. For now we just take the first one...
|
|
||||||
// a more sophisticated solution would do something more clever here,
|
|
||||||
// e.g. ask the user which one to pick (make sure to display the
|
|
||||||
// path, too).
|
|
||||||
GameDescriptor result = candidates[0];
|
|
||||||
addGameToConf(dir, result, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Recurse into all subdirs
|
|
||||||
for (FSList::const_iterator file = files.begin(); file != files.end(); ++file) {
|
|
||||||
if (file->isDirectory()) {
|
|
||||||
addGameRecursive(*file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LauncherDialog::addGame() {
|
void LauncherDialog::addGame() {
|
||||||
bool massAdd = (_modifiers & OSystem::KBD_SHIFT) != 0;
|
bool massAdd = (_modifiers & OSystem::KBD_SHIFT) != 0;
|
||||||
|
|
||||||
|
@ -640,7 +614,8 @@ void LauncherDialog::addGame() {
|
||||||
MessageDialog alert("Do you really want to run the mass game detector? "
|
MessageDialog alert("Do you really want to run the mass game detector? "
|
||||||
"This could potentially add a huge number of games.", "Yes", "No");
|
"This could potentially add a huge number of games.", "Yes", "No");
|
||||||
if (alert.runModal() == GUI::kMessageOK && _browser->runModal() > 0) {
|
if (alert.runModal() == GUI::kMessageOK && _browser->runModal() > 0) {
|
||||||
addGameRecursive(_browser->getResult());
|
MassAddDialog massAddDlg(_browser->getResult());
|
||||||
|
massAddDlg.runModal();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -690,13 +665,34 @@ void LauncherDialog::addGame() {
|
||||||
}
|
}
|
||||||
if (0 <= idx && idx < (int)candidates.size()) {
|
if (0 <= idx && idx < (int)candidates.size()) {
|
||||||
GameDescriptor result = candidates[idx];
|
GameDescriptor result = candidates[idx];
|
||||||
addGameToConf(dir, result, false);
|
|
||||||
|
// TODO: Change the detectors to set "path" !
|
||||||
|
result["path"] = dir.path();
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
// Update the ListWidget, select the new item, and force a redraw
|
||||||
|
updateListing();
|
||||||
|
selectGame(domain);
|
||||||
|
draw();
|
||||||
|
} else {
|
||||||
|
// User aborted, remove the the new domain again
|
||||||
|
ConfMan.removeGameDomain(domain);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common::String addGameToConf(const GameDescriptor &result) {
|
||||||
void LauncherDialog::addGameToConf(const FilesystemNode &dir, const GameDescriptor &result, bool suppressEditDialog) {
|
|
||||||
// The auto detector or the user made a choice.
|
// The auto detector or the user made a choice.
|
||||||
// Pick a domain name which does not yet exist (after all, we
|
// Pick a domain name which does not yet exist (after all, we
|
||||||
// are *adding* a game to the config, not replacing).
|
// are *adding* a game to the config, not replacing).
|
||||||
|
@ -733,39 +729,26 @@ void LauncherDialog::addGameToConf(const FilesystemNode &dir, const GameDescript
|
||||||
// for the generic gameid description; it's not possible to obtain
|
// for the generic gameid description; it's not possible to obtain
|
||||||
// a description which contains extended information like language, etc.).
|
// a description which contains extended information like language, etc.).
|
||||||
if (!result.description().empty())
|
if (!result.description().empty())
|
||||||
ConfMan.set("description", result.description(), domain);
|
ConfMan.set("description", result["description"], domain);
|
||||||
|
|
||||||
ConfMan.set("gameid", result.gameid(), domain);
|
// TODO: Instead of only setting a few selected keys, we could just copy *all*
|
||||||
ConfMan.set("path", dir.path(), domain);
|
// non-empty key/value pairs from result (with the exception of "preferredtarget")
|
||||||
|
// to the config domain. This way detectors could specify many more
|
||||||
|
// settings w/o any further changes needed in the launcher code!
|
||||||
|
|
||||||
|
ConfMan.set("gameid", result["gameid"], domain);
|
||||||
|
|
||||||
|
ConfMan.set("path", result["path"], domain);
|
||||||
|
|
||||||
// Set language if specified
|
// Set language if specified
|
||||||
if (result.language() != Common::UNK_LANG)
|
if (result.language() != Common::UNK_LANG)
|
||||||
ConfMan.set("language", Common::getLanguageCode(result.language()), domain);
|
ConfMan.set("language", result["language"], domain);
|
||||||
|
|
||||||
// Set platform if specified
|
// Set platform if specified
|
||||||
if (result.platform() != Common::kPlatformUnknown)
|
if (result.platform() != Common::kPlatformUnknown)
|
||||||
ConfMan.set("platform", Common::getPlatformCode(result.platform()), domain);
|
ConfMan.set("platform", result["platform"], domain);
|
||||||
|
|
||||||
// Display edit dialog for the new entry
|
return domain;
|
||||||
bool saveit = true;
|
|
||||||
if (!suppressEditDialog) {
|
|
||||||
EditGameDialog editDialog(domain, result.description());
|
|
||||||
saveit = (editDialog.runModal() > 0);
|
|
||||||
}
|
|
||||||
if (saveit) {
|
|
||||||
// User pressed OK, so make changes permanent
|
|
||||||
|
|
||||||
// Write config to disk
|
|
||||||
ConfMan.flushToDisk();
|
|
||||||
|
|
||||||
// Update the ListWidget, select the new item, and force a redraw
|
|
||||||
updateListing();
|
|
||||||
selectGame(domain);
|
|
||||||
draw();
|
|
||||||
} else {
|
|
||||||
// User aborted, remove the the new domain again
|
|
||||||
ConfMan.removeGameDomain(domain);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LauncherDialog::removeGame(int item) {
|
void LauncherDialog::removeGame(int item) {
|
||||||
|
|
|
@ -31,6 +31,10 @@ class BrowserDialog;
|
||||||
class ListWidget;
|
class ListWidget;
|
||||||
class GraphicsWidget;
|
class GraphicsWidget;
|
||||||
|
|
||||||
|
|
||||||
|
Common::String addGameToConf(const GameDescriptor &result);
|
||||||
|
|
||||||
|
|
||||||
class LauncherDialog : public Dialog {
|
class LauncherDialog : public Dialog {
|
||||||
typedef Common::String String;
|
typedef Common::String String;
|
||||||
typedef Common::StringList StringList;
|
typedef Common::StringList StringList;
|
||||||
|
@ -68,9 +72,6 @@ protected:
|
||||||
void editGame(int item);
|
void editGame(int item);
|
||||||
|
|
||||||
void selectGame(const String &name);
|
void selectGame(const String &name);
|
||||||
|
|
||||||
void addGameToConf(const FilesystemNode &dir, const GameDescriptor &result, bool suppressEditDialog);
|
|
||||||
void addGameRecursive(FilesystemNode dir);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace GUI
|
} // End of namespace GUI
|
||||||
|
|
198
gui/massadd.cpp
Normal file
198
gui/massadd.cpp
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2002-2006 The ScummVM project
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/stdafx.h"
|
||||||
|
|
||||||
|
#include "engines/engine.h"
|
||||||
|
#include "base/game.h"
|
||||||
|
#include "base/plugins.h"
|
||||||
|
|
||||||
|
#include "gui/launcher.h" // For addGameToConf()
|
||||||
|
#include "gui/massadd.h"
|
||||||
|
#include "gui/newgui.h"
|
||||||
|
#include "gui/widget.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace GUI {
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO:
|
||||||
|
- Themify this dialog
|
||||||
|
- Add a ListWidget showing all the games we are going to add, and update it live
|
||||||
|
- Add a 'busy' mouse cursor (animated?) which indicates to the user that
|
||||||
|
something is in progress, and show this cursor while we scan
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum {
|
||||||
|
// Upper bound (im milliseconds) we want to spend in handleTickle.
|
||||||
|
// Setting this low makes the GUI more responsive but also slows
|
||||||
|
// down the scanning.
|
||||||
|
kMaxScanTime = 50
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kOkCmd = 'OK ',
|
||||||
|
kCancelCmd = 'CNCL'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
MassAddDialog::MassAddDialog(const FilesystemNode &startDir)
|
||||||
|
: Dialog(10, 20, 300, 174),
|
||||||
|
_dirsScanned(0),
|
||||||
|
_okButton(0),
|
||||||
|
_dirProgressText(0),
|
||||||
|
_gameProgressText(0) {
|
||||||
|
|
||||||
|
// The dir we start our scan at
|
||||||
|
_scanStack.push(startDir);
|
||||||
|
|
||||||
|
|
||||||
|
int buttonWidth, buttonHeight;
|
||||||
|
|
||||||
|
if (g_gui.getWidgetSize() == kBigWidgetSize) {
|
||||||
|
buttonWidth = kBigButtonWidth;
|
||||||
|
buttonHeight = kBigButtonHeight;
|
||||||
|
} else {
|
||||||
|
buttonWidth = kButtonWidth;
|
||||||
|
buttonHeight = kButtonHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create dialog items
|
||||||
|
// We need:
|
||||||
|
// - "OK" button, only enabled after the scan has finished
|
||||||
|
// - "Cancel" / "Abort" button, always active
|
||||||
|
// - static text as headline for the dialog
|
||||||
|
// - static text displaying the progress text
|
||||||
|
// - (future) a listbox showing all the games we added/are going to add
|
||||||
|
|
||||||
|
new StaticTextWidget(this, 10, 10 + 1 * kLineHeight, _w - 2*10, kLineHeight,
|
||||||
|
"Mass Add Dialog", kTextAlignCenter);
|
||||||
|
|
||||||
|
_dirProgressText = new StaticTextWidget(this, 10, 10 + 3 * kLineHeight, _w - 2*10, kLineHeight,
|
||||||
|
"... progress ...", kTextAlignCenter);
|
||||||
|
|
||||||
|
_gameProgressText = new StaticTextWidget(this, 10, 10 + 4 * kLineHeight, _w - 2*10, kLineHeight,
|
||||||
|
"... progress ...", kTextAlignCenter);
|
||||||
|
|
||||||
|
int okButtonPos = (_w - (buttonWidth * 2)) / 2;
|
||||||
|
int cancelButtonPos = ((_w - (buttonWidth * 2)) / 2) + buttonWidth + 10;
|
||||||
|
|
||||||
|
_okButton = addButton(this, okButtonPos, _h - buttonHeight - 8, "OK", kOkCmd, '\n');
|
||||||
|
_okButton->setEnabled(false);
|
||||||
|
|
||||||
|
addButton(this, cancelButtonPos, _h - buttonHeight - 8, "Cancel", kCancelCmd, '\27');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MassAddDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
|
||||||
|
// FIXME: It's a really bad thing that we use two arbitrary constants
|
||||||
|
if (cmd == kOkCmd) {
|
||||||
|
// Add all the detected games to the config
|
||||||
|
for (GameList::const_iterator iter = _games.begin(); iter != _games.end(); ++iter) {
|
||||||
|
printf(" Added gameid '%s', desc '%s'\n",
|
||||||
|
(*iter)["gameid"].c_str(),
|
||||||
|
(*iter)["description"].c_str());
|
||||||
|
addGameToConf(*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write everything to disk
|
||||||
|
ConfMan.flushToDisk();
|
||||||
|
|
||||||
|
close();
|
||||||
|
} else if (cmd == kCancelCmd) {
|
||||||
|
// User cancelled, so we don't do anything and just leave.
|
||||||
|
close();
|
||||||
|
} else {
|
||||||
|
Dialog::handleCommand(sender, cmd, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MassAddDialog::handleTickle() {
|
||||||
|
if (_scanStack.empty())
|
||||||
|
return; // We have finished scanning
|
||||||
|
|
||||||
|
uint32 t = g_system->getMillis();
|
||||||
|
|
||||||
|
// Perform a breadth-first scan of the filesystem.
|
||||||
|
while (!_scanStack.empty() && (g_system->getMillis() - t) < kMaxScanTime) {
|
||||||
|
FilesystemNode dir = _scanStack.pop();
|
||||||
|
|
||||||
|
FSList files;
|
||||||
|
if (!dir.listDir(files, FilesystemNode::kListAll)) {
|
||||||
|
error("browser returned a node that is not a directory: '%s'",
|
||||||
|
dir.path().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the detector on the dir
|
||||||
|
GameList candidates(PluginManager::instance().detectGames(files));
|
||||||
|
|
||||||
|
if (candidates.size() >= 1) {
|
||||||
|
// At least one match was found. For now we just take the first one...
|
||||||
|
// a more sophisticated solution would do something more clever here,
|
||||||
|
// e.g. ask the user which one to pick (make sure to display the
|
||||||
|
// path, too).
|
||||||
|
GameDescriptor result = candidates[0];
|
||||||
|
result["path"] = dir.path();
|
||||||
|
|
||||||
|
_games.push_back(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Recurse into all subdirs
|
||||||
|
for (FSList::const_iterator file = files.begin(); file != files.end(); ++file) {
|
||||||
|
if (file->isDirectory()) {
|
||||||
|
_scanStack.push(*file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_dirsScanned++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Update the dialog
|
||||||
|
char buf[256];
|
||||||
|
|
||||||
|
if (_scanStack.empty()) {
|
||||||
|
// Enable the OK button
|
||||||
|
_okButton->setEnabled(true);
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "Scan complete!", _dirsScanned);
|
||||||
|
_dirProgressText->setLabel(buf);
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "Discovered %d games.", _games.size());
|
||||||
|
_gameProgressText->setLabel(buf);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
snprintf(buf, sizeof(buf), "Scanned %d directories ...", _dirsScanned);
|
||||||
|
_dirProgressText->setLabel(buf);
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "Discovered %d games ...", _games.size());
|
||||||
|
_gameProgressText->setLabel(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // end of namespace GUI
|
||||||
|
|
55
gui/massadd.h
Normal file
55
gui/massadd.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/* ScummVM - Scumm Interpreter
|
||||||
|
* Copyright (C) 2002-2006 The ScummVM project
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MASSADD_DIALOG_H
|
||||||
|
#define MASSADD_DIALOG_H
|
||||||
|
|
||||||
|
#include "gui/dialog.h"
|
||||||
|
#include "common/fs.h"
|
||||||
|
#include "common/stack.h"
|
||||||
|
|
||||||
|
namespace GUI {
|
||||||
|
|
||||||
|
class StaticTextWidget;
|
||||||
|
|
||||||
|
class MassAddDialog : public Dialog {
|
||||||
|
public:
|
||||||
|
MassAddDialog(const FilesystemNode &startDir);
|
||||||
|
|
||||||
|
//void open();
|
||||||
|
void handleCommand(CommandSender *sender, uint32 cmd, uint32 data);
|
||||||
|
void handleTickle();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Common::Stack<FilesystemNode> _scanStack;
|
||||||
|
GameList _games;
|
||||||
|
|
||||||
|
int _dirsScanned;
|
||||||
|
|
||||||
|
Widget *_okButton;
|
||||||
|
StaticTextWidget *_dirProgressText;
|
||||||
|
StaticTextWidget *_gameProgressText;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // End of namespace GUI
|
||||||
|
|
||||||
|
#endif
|
|
@ -12,6 +12,7 @@ MODULE_OBJS := \
|
||||||
eval.o \
|
eval.o \
|
||||||
launcher.o \
|
launcher.o \
|
||||||
ListWidget.o \
|
ListWidget.o \
|
||||||
|
massadd.o \
|
||||||
message.o \
|
message.o \
|
||||||
newgui.o \
|
newgui.o \
|
||||||
options.o \
|
options.o \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue