2007-05-30 21:56:52 +00:00
|
|
|
/* 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.
|
2007-02-18 18:23:52 +00:00
|
|
|
*
|
2021-12-26 17:47:58 +00:00
|
|
|
* 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 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
2007-02-18 18:23:52 +00:00
|
|
|
*
|
|
|
|
* 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
|
2021-12-26 17:47:58 +00:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2014-02-18 01:34:20 +00:00
|
|
|
*
|
2007-02-18 18:23:52 +00:00
|
|
|
*/
|
|
|
|
|
2008-05-13 10:41:32 +00:00
|
|
|
#include "engines/metaengine.h"
|
2008-07-29 16:29:28 +00:00
|
|
|
#include "common/algorithm.h"
|
2008-06-11 06:22:02 +00:00
|
|
|
#include "common/config-manager.h"
|
2011-04-24 08:34:27 +00:00
|
|
|
#include "common/debug.h"
|
|
|
|
#include "common/system.h"
|
2011-03-31 10:35:43 +00:00
|
|
|
#include "common/taskbar.h"
|
2010-06-15 10:44:51 +00:00
|
|
|
#include "common/translation.h"
|
2007-02-18 18:23:52 +00:00
|
|
|
|
|
|
|
#include "gui/massadd.h"
|
|
|
|
|
2011-05-21 14:45:51 +00:00
|
|
|
#ifndef DISABLE_MASS_ADD
|
2007-02-18 18:23:52 +00:00
|
|
|
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'
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2008-10-02 16:58:59 +00:00
|
|
|
MassAddDialog::MassAddDialog(const Common::FSNode &startDir)
|
2008-10-14 17:53:52 +00:00
|
|
|
: Dialog("MassAdd"),
|
2007-02-18 18:23:52 +00:00
|
|
|
_dirsScanned(0),
|
2011-05-02 11:39:34 +00:00
|
|
|
_oldGamesCount(0),
|
2011-03-31 10:35:43 +00:00
|
|
|
_dirTotal(0),
|
2020-01-05 16:48:04 +00:00
|
|
|
_okButton(nullptr),
|
|
|
|
_dirProgressText(nullptr),
|
|
|
|
_gameProgressText(nullptr) {
|
2007-02-18 18:23:52 +00:00
|
|
|
|
2021-11-10 14:56:44 +00:00
|
|
|
Common::U32StringArray l;
|
2009-06-06 17:49:59 +00:00
|
|
|
|
2007-02-18 18:23:52 +00:00
|
|
|
// The dir we start our scan at
|
|
|
|
_scanStack.push(startDir);
|
|
|
|
|
2011-04-04 16:49:49 +00:00
|
|
|
// Removed for now... Why would you put a title on mass add dialog called "Mass Add Dialog"?
|
|
|
|
// new StaticTextWidget(this, "massadddialog_caption", "Mass Add Dialog");
|
2007-02-18 18:23:52 +00:00
|
|
|
|
2008-10-14 17:53:52 +00:00
|
|
|
_dirProgressText = new StaticTextWidget(this, "MassAdd.DirProgressText",
|
GUI: U32: Downscale changes of U32, fix review issues
This commit addresses a range of changes, within scummvm subproject.
- Audio files, like mididrv, remove U32String based name and identifier, because ASCII only.
- mididrv.cpp had some wrong format for warning messages, fix those
- Message dialogs were modified to use default arguments more often, but reverting back to the orignal to minimize changes.
- SetTooltip has a fake constructor that takes in a string, and use it.
- U32Format had some break statements missing, add those.
- RemapWidget: Use fake constructor for setLabel and setTooltip, to make minimal changes
- SDL: setting text in clipboard no longer uses SDL_iconv_string
- TTS: Override base class "say" with strings, so tts->say can be used with normal strings too.
- About dialog: fix incorrect code for u32string variables
- Fix some extra brackets
- Some buttons were incorrectly removed from using translated labels, revert those
- Message Dialog: Pass default and alt buttons as const references
- Saveload Dialog: Use translations in missing places, use const-references. Also, use translations in a correct manner.
- Use const references for tooltip in GraphicsWidget, EditTextWidget, error.cpp
- DomainEditTextWidget: Use U32String for text
2020-07-20 12:36:37 +00:00
|
|
|
_("... progress ..."));
|
2007-02-18 18:23:52 +00:00
|
|
|
|
2008-10-14 17:53:52 +00:00
|
|
|
_gameProgressText = new StaticTextWidget(this, "MassAdd.GameProgressText",
|
GUI: U32: Downscale changes of U32, fix review issues
This commit addresses a range of changes, within scummvm subproject.
- Audio files, like mididrv, remove U32String based name and identifier, because ASCII only.
- mididrv.cpp had some wrong format for warning messages, fix those
- Message dialogs were modified to use default arguments more often, but reverting back to the orignal to minimize changes.
- SetTooltip has a fake constructor that takes in a string, and use it.
- U32Format had some break statements missing, add those.
- RemapWidget: Use fake constructor for setLabel and setTooltip, to make minimal changes
- SDL: setting text in clipboard no longer uses SDL_iconv_string
- TTS: Override base class "say" with strings, so tts->say can be used with normal strings too.
- About dialog: fix incorrect code for u32string variables
- Fix some extra brackets
- Some buttons were incorrectly removed from using translated labels, revert those
- Message Dialog: Pass default and alt buttons as const references
- Saveload Dialog: Use translations in missing places, use const-references. Also, use translations in a correct manner.
- Use const references for tooltip in GraphicsWidget, EditTextWidget, error.cpp
- DomainEditTextWidget: Use U32String for text
2020-07-20 12:36:37 +00:00
|
|
|
_("... progress ..."));
|
2008-12-22 11:22:15 +00:00
|
|
|
|
2008-10-14 17:53:52 +00:00
|
|
|
_dirProgressText->setAlign(Graphics::kTextAlignCenter);
|
|
|
|
_gameProgressText->setAlign(Graphics::kTextAlignCenter);
|
2007-02-18 18:23:52 +00:00
|
|
|
|
2009-06-06 17:49:59 +00:00
|
|
|
_list = new ListWidget(this, "MassAdd.GameList");
|
|
|
|
_list->setEditable(false);
|
|
|
|
_list->setNumberingMode(kListNumberingOff);
|
|
|
|
_list->setList(l);
|
|
|
|
|
2020-11-15 18:15:58 +00:00
|
|
|
_okButton = new ButtonWidget(this, "MassAdd.Ok", _("OK"), Common::U32String(), kOkCmd, Common::ASCII_RETURN);
|
2007-02-18 18:23:52 +00:00
|
|
|
_okButton->setEnabled(false);
|
|
|
|
|
2020-11-15 18:15:58 +00:00
|
|
|
new ButtonWidget(this, "MassAdd.Cancel", _("Cancel"), Common::U32String(), kCancelCmd, Common::ASCII_ESCAPE);
|
2007-02-18 18:23:52 +00:00
|
|
|
|
2008-06-11 06:22:02 +00:00
|
|
|
// Build a map from all configured game paths to the targets using them
|
|
|
|
const Common::ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
|
|
|
|
Common::ConfigManager::DomainMap::const_iterator iter;
|
|
|
|
for (iter = domains.begin(); iter != domains.end(); ++iter) {
|
2010-03-29 20:31:23 +00:00
|
|
|
Common::String path(iter->_value.getVal("path"));
|
2008-06-11 06:22:02 +00:00
|
|
|
// Remove trailing slash, so that "/foo" and "/foo/" match.
|
|
|
|
// This works around a bug in the POSIX FS code (and others?)
|
|
|
|
// where paths are not normalized (so FSNodes refering to identical
|
|
|
|
// FS objects may return different values in path()).
|
|
|
|
while (path != "/" && path.lastChar() == '/')
|
|
|
|
path.deleteLastChar();
|
|
|
|
if (!path.empty())
|
|
|
|
_pathToTargets[path].push_back(iter->_key);
|
|
|
|
}
|
2007-02-18 18:23:52 +00:00
|
|
|
}
|
|
|
|
|
2009-06-06 17:49:59 +00:00
|
|
|
struct GameTargetLess {
|
2018-05-06 13:51:03 +00:00
|
|
|
bool operator()(const DetectedGame &x, const DetectedGame &y) const {
|
2017-12-03 11:19:08 +00:00
|
|
|
return x.preferredTarget.compareToIgnoreCase(y.preferredTarget) < 0;
|
2008-07-29 16:29:28 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-06-06 17:49:59 +00:00
|
|
|
struct GameDescLess {
|
2018-05-06 13:51:03 +00:00
|
|
|
bool operator()(const DetectedGame &x, const DetectedGame &y) const {
|
2017-12-03 11:19:08 +00:00
|
|
|
return x.description.compareToIgnoreCase(y.description) < 0;
|
2009-06-06 17:49:59 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2007-02-18 18:23:52 +00:00
|
|
|
|
|
|
|
void MassAddDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) {
|
2011-04-29 16:15:49 +00:00
|
|
|
#if defined(USE_TASKBAR)
|
2011-04-04 16:49:49 +00:00
|
|
|
// Remove progress bar and count from taskbar
|
2011-03-31 10:35:43 +00:00
|
|
|
g_system->getTaskbarManager()->setProgressState(Common::TaskbarManager::kTaskbarNoProgress);
|
2011-04-04 16:49:49 +00:00
|
|
|
g_system->getTaskbarManager()->setCount(0);
|
2011-04-29 16:15:49 +00:00
|
|
|
#endif
|
2011-03-31 10:35:43 +00:00
|
|
|
|
2007-02-18 18:23:52 +00:00
|
|
|
// FIXME: It's a really bad thing that we use two arbitrary constants
|
|
|
|
if (cmd == kOkCmd) {
|
2008-07-29 16:29:28 +00:00
|
|
|
// Sort the detected games. This is not strictly necessary, but nice for
|
|
|
|
// people who want to edit their config file by hand after a mass add.
|
2017-12-03 11:19:08 +00:00
|
|
|
Common::sort(_games.begin(), _games.end(), GameTargetLess());
|
2007-02-18 18:23:52 +00:00
|
|
|
// Add all the detected games to the config
|
2018-05-06 13:51:03 +00:00
|
|
|
for (DetectedGames::iterator iter = _games.begin(); iter != _games.end(); ++iter) {
|
2009-12-15 08:19:34 +00:00
|
|
|
debug(1, " Added gameid '%s', desc '%s'\n",
|
2017-12-03 11:19:08 +00:00
|
|
|
iter->gameId.c_str(),
|
|
|
|
iter->description.c_str());
|
2018-02-04 07:46:12 +00:00
|
|
|
iter->gameId = EngineMan.createTargetForGame(*iter);
|
2007-02-18 18:23:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Write everything to disk
|
|
|
|
ConfMan.flushToDisk();
|
|
|
|
|
2009-06-06 17:49:59 +00:00
|
|
|
// And scroll to first detected game
|
2009-09-15 14:34:21 +00:00
|
|
|
if (!_games.empty()) {
|
2017-12-03 11:19:08 +00:00
|
|
|
Common::sort(_games.begin(), _games.end(), GameDescLess());
|
|
|
|
ConfMan.set("temp_selection", _games.front().gameId);
|
2009-09-15 14:34:21 +00:00
|
|
|
}
|
2009-06-06 17:49:59 +00:00
|
|
|
|
2007-02-18 18:23:52 +00:00
|
|
|
close();
|
|
|
|
} else if (cmd == kCancelCmd) {
|
|
|
|
// User cancelled, so we don't do anything and just leave.
|
2009-12-15 08:19:34 +00:00
|
|
|
_games.clear();
|
2007-02-18 18:23:52 +00:00
|
|
|
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) {
|
2008-10-02 16:58:59 +00:00
|
|
|
Common::FSNode dir = _scanStack.pop();
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2008-09-03 11:22:51 +00:00
|
|
|
Common::FSList files;
|
2008-10-02 16:58:59 +00:00
|
|
|
if (!dir.getChildren(files, Common::FSNode::kListAll)) {
|
2009-02-17 21:02:47 +00:00
|
|
|
continue;
|
2007-02-18 18:23:52 +00:00
|
|
|
}
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2007-02-18 18:23:52 +00:00
|
|
|
// Run the detector on the dir
|
2017-12-02 16:14:22 +00:00
|
|
|
DetectionResults detectionResults = EngineMan.detectGames(files);
|
|
|
|
|
|
|
|
if (detectionResults.foundUnknownGames()) {
|
2020-07-21 23:23:38 +00:00
|
|
|
Common::U32String report = detectionResults.generateUnknownGameReport(false, 80);
|
|
|
|
g_system->logMessage(LogMessageType::kInfo, report.encode().c_str());
|
2017-12-02 16:14:22 +00:00
|
|
|
}
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2008-03-29 23:20:53 +00:00
|
|
|
// Just add all detected games / game variants. If we get more than one,
|
|
|
|
// that either means the directory contains multiple games, or the detector
|
|
|
|
// could not fully determine which game variant it was seeing. In either
|
|
|
|
// case, let the user choose which entries he wants to keep.
|
2008-06-11 06:22:02 +00:00
|
|
|
//
|
|
|
|
// However, we only add games which are not already in the config file.
|
2017-12-02 16:14:22 +00:00
|
|
|
DetectedGames candidates = detectionResults.listRecognizedGames();
|
|
|
|
for (DetectedGames::const_iterator cand = candidates.begin(); cand != candidates.end(); ++cand) {
|
2018-05-06 13:51:03 +00:00
|
|
|
const DetectedGame &result = *cand;
|
|
|
|
|
2008-06-11 06:22:02 +00:00
|
|
|
Common::String path = dir.getPath();
|
|
|
|
|
|
|
|
// Remove trailing slashes
|
|
|
|
while (path != "/" && path.lastChar() == '/')
|
|
|
|
path.deleteLastChar();
|
|
|
|
|
2016-09-15 16:39:45 +00:00
|
|
|
// Check for existing config entries for this path/engineid/gameid/lang/platform combination
|
2008-06-11 06:22:02 +00:00
|
|
|
if (_pathToTargets.contains(path)) {
|
2018-06-30 17:12:56 +00:00
|
|
|
Common::String resultPlatformCode = Common::getPlatformCode(result.platform);
|
|
|
|
Common::String resultLanguageCode = Common::getLanguageCode(result.language);
|
2017-12-03 11:19:08 +00:00
|
|
|
|
2008-06-11 06:22:02 +00:00
|
|
|
bool duplicate = false;
|
2021-11-10 14:56:44 +00:00
|
|
|
const Common::StringArray &targets = _pathToTargets[path];
|
|
|
|
for (Common::StringArray::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) {
|
2016-09-15 16:39:45 +00:00
|
|
|
// If the engineid, gameid, platform and language match -> skip it
|
2008-06-11 06:22:02 +00:00
|
|
|
Common::ConfigManager::Domain *dom = ConfMan.getDomain(*iter);
|
|
|
|
assert(dom);
|
|
|
|
|
2016-09-15 16:39:45 +00:00
|
|
|
if ((*dom)["engineid"] == result.engineId &&
|
|
|
|
(*dom)["gameid"] == result.gameId &&
|
2021-04-28 10:52:25 +00:00
|
|
|
dom->getValOrDefault("platform") == resultPlatformCode &&
|
2021-04-27 22:40:34 +00:00
|
|
|
dom->getValOrDefault("language") == resultLanguageCode) {
|
2008-06-11 06:22:02 +00:00
|
|
|
duplicate = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-05-02 11:39:34 +00:00
|
|
|
if (duplicate) {
|
|
|
|
_oldGamesCount++;
|
2018-09-23 05:00:11 +00:00
|
|
|
continue; // Skip duplicates
|
2011-05-02 11:39:34 +00:00
|
|
|
}
|
2008-06-11 06:22:02 +00:00
|
|
|
}
|
2007-02-18 18:23:52 +00:00
|
|
|
_games.push_back(result);
|
2009-06-06 17:49:59 +00:00
|
|
|
|
2017-12-03 11:19:08 +00:00
|
|
|
_list->append(result.description);
|
2007-02-18 18:23:52 +00:00
|
|
|
}
|
2007-09-19 08:40:12 +00:00
|
|
|
|
|
|
|
|
2007-02-18 18:23:52 +00:00
|
|
|
// Recurse into all subdirs
|
2008-09-03 11:22:51 +00:00
|
|
|
for (Common::FSList::const_iterator file = files.begin(); file != files.end(); ++file) {
|
2007-02-18 18:23:52 +00:00
|
|
|
if (file->isDirectory()) {
|
|
|
|
_scanStack.push(*file);
|
2011-03-31 10:35:43 +00:00
|
|
|
|
|
|
|
_dirTotal++;
|
2007-02-18 18:23:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_dirsScanned++;
|
2011-03-31 10:35:43 +00:00
|
|
|
|
2011-04-29 16:15:49 +00:00
|
|
|
#if defined(USE_TASKBAR)
|
2011-03-31 10:35:43 +00:00
|
|
|
g_system->getTaskbarManager()->setProgressValue(_dirsScanned, _dirTotal);
|
2011-04-04 16:49:49 +00:00
|
|
|
g_system->getTaskbarManager()->setCount(_games.size());
|
2011-04-29 16:15:49 +00:00
|
|
|
#endif
|
2007-02-18 18:23:52 +00:00
|
|
|
}
|
2007-09-19 08:40:12 +00:00
|
|
|
|
|
|
|
|
2007-02-18 18:23:52 +00:00
|
|
|
// Update the dialog
|
2020-06-13 16:42:25 +00:00
|
|
|
Common::U32String buf;
|
2007-02-18 18:23:52 +00:00
|
|
|
|
|
|
|
if (_scanStack.empty()) {
|
|
|
|
// Enable the OK button
|
|
|
|
_okButton->setEnabled(true);
|
|
|
|
|
2011-06-01 22:07:18 +00:00
|
|
|
buf = _("Scan complete!");
|
2007-02-18 18:23:52 +00:00
|
|
|
_dirProgressText->setLabel(buf);
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2020-06-20 18:04:23 +00:00
|
|
|
buf = Common::U32String::format(_("Discovered %d new games, ignored %d previously added games."), _games.size(), _oldGamesCount);
|
2007-02-18 18:23:52 +00:00
|
|
|
_gameProgressText->setLabel(buf);
|
|
|
|
|
|
|
|
} else {
|
2020-06-20 18:04:23 +00:00
|
|
|
buf = Common::U32String::format(_("Scanned %d directories ..."), _dirsScanned);
|
2007-02-18 18:23:52 +00:00
|
|
|
_dirProgressText->setLabel(buf);
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2020-06-20 18:04:23 +00:00
|
|
|
buf = Common::U32String::format(_("Discovered %d new games, ignored %d previously added games ..."), _games.size(), _oldGamesCount);
|
2007-02-18 18:23:52 +00:00
|
|
|
_gameProgressText->setLabel(buf);
|
|
|
|
}
|
|
|
|
|
2009-06-06 17:49:59 +00:00
|
|
|
if (_games.size() > 0) {
|
|
|
|
_list->scrollToEnd();
|
|
|
|
}
|
|
|
|
|
2018-01-07 09:39:22 +00:00
|
|
|
drawDialog(kDrawLayerForeground);
|
2007-02-18 18:23:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-04 21:26:33 +00:00
|
|
|
} // End of namespace GUI
|
2007-02-18 18:23:52 +00:00
|
|
|
|
2011-05-21 14:45:51 +00:00
|
|
|
#endif // DISABLE_MASS_ADD
|