diff options
author | Max Horn | 2007-02-18 18:23:52 +0000 |
---|---|---|
committer | Max Horn | 2007-02-18 18:23:52 +0000 |
commit | 94507bb44dc38bfaffc5a293f1160f35f56dd9b7 (patch) | |
tree | 36b0ce59297a7779f5f7e8a291806de8275e8688 /gui | |
parent | e0a7c6d7a78f306b7aa2a60eec9c698119090515 (diff) | |
download | scummvm-rg350-94507bb44dc38bfaffc5a293f1160f35f56dd9b7.tar.gz scummvm-rg350-94507bb44dc38bfaffc5a293f1160f35f56dd9b7.tar.bz2 scummvm-rg350-94507bb44dc38bfaffc5a293f1160f35f56dd9b7.zip |
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
Diffstat (limited to 'gui')
-rw-r--r-- | gui/launcher.cpp | 97 | ||||
-rw-r--r-- | gui/launcher.h | 7 | ||||
-rw-r--r-- | gui/massadd.cpp | 198 | ||||
-rw-r--r-- | gui/massadd.h | 55 | ||||
-rw-r--r-- | gui/module.mk | 1 |
5 files changed, 298 insertions, 60 deletions
diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 19a8b3062f..0c0c1649fb 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -36,6 +36,7 @@ #include "gui/chooser.h" #include "gui/eval.h" #include "gui/launcher.h" +#include "gui/massadd.h" #include "gui/message.h" #include "gui/newgui.h" #include "gui/options.h" @@ -47,6 +48,7 @@ #include "sound/mididrv.h" + using Common::ConfigManager; namespace GUI { @@ -605,34 +607,6 @@ void LauncherDialog::updateListing() { 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() { 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? " "This could potentially add a huge number of games.", "Yes", "No"); if (alert.runModal() == GUI::kMessageOK && _browser->runModal() > 0) { - addGameRecursive(_browser->getResult()); + MassAddDialog massAddDlg(_browser->getResult()); + massAddDlg.runModal(); } return; } @@ -690,13 +665,34 @@ void LauncherDialog::addGame() { } if (0 <= idx && idx < (int)candidates.size()) { 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); + } + } } } - -void LauncherDialog::addGameToConf(const FilesystemNode &dir, const GameDescriptor &result, bool suppressEditDialog) { +Common::String addGameToConf(const GameDescriptor &result) { // The auto detector or the user made a choice. // Pick a domain name which does not yet exist (after all, we // 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 // a description which contains extended information like language, etc.). if (!result.description().empty()) - ConfMan.set("description", result.description(), domain); + ConfMan.set("description", result["description"], domain); + + // TODO: Instead of only setting a few selected keys, we could just copy *all* + // 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", dir.path(), domain); + ConfMan.set("gameid", result["gameid"], domain); + + ConfMan.set("path", result["path"], domain); // Set language if specified if (result.language() != Common::UNK_LANG) - ConfMan.set("language", Common::getLanguageCode(result.language()), domain); + ConfMan.set("language", result["language"], domain); // Set platform if specified 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 - 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); - } + return domain; } void LauncherDialog::removeGame(int item) { diff --git a/gui/launcher.h b/gui/launcher.h index 1730fea622..41550db992 100644 --- a/gui/launcher.h +++ b/gui/launcher.h @@ -31,6 +31,10 @@ class BrowserDialog; class ListWidget; class GraphicsWidget; + +Common::String addGameToConf(const GameDescriptor &result); + + class LauncherDialog : public Dialog { typedef Common::String String; typedef Common::StringList StringList; @@ -68,9 +72,6 @@ protected: void editGame(int item); void selectGame(const String &name); - - void addGameToConf(const FilesystemNode &dir, const GameDescriptor &result, bool suppressEditDialog); - void addGameRecursive(FilesystemNode dir); }; } // End of namespace GUI diff --git a/gui/massadd.cpp b/gui/massadd.cpp new file mode 100644 index 0000000000..10b72b2639 --- /dev/null +++ b/gui/massadd.cpp @@ -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 + diff --git a/gui/massadd.h b/gui/massadd.h new file mode 100644 index 0000000000..7fd2d2f10d --- /dev/null +++ b/gui/massadd.h @@ -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 diff --git a/gui/module.mk b/gui/module.mk index d447820ad6..b352a1ec86 100644 --- a/gui/module.mk +++ b/gui/module.mk @@ -12,6 +12,7 @@ MODULE_OBJS := \ eval.o \ launcher.o \ ListWidget.o \ + massadd.o \ message.o \ newgui.o \ options.o \ |