aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schickel2009-01-02 20:03:45 +0000
committerJohannes Schickel2009-01-02 20:03:45 +0000
commit1b0f94547120435cbda18387ff4d936ed84d9276 (patch)
treea9f356df5d611b2f5a05ffe88907cbc2ebed2e95
parent90d762c2612028892133d4aaf616b9eede9e397f (diff)
downloadscummvm-rg350-1b0f94547120435cbda18387ff4d936ed84d9276.tar.gz
scummvm-rg350-1b0f94547120435cbda18387ff4d936ed84d9276.tar.bz2
scummvm-rg350-1b0f94547120435cbda18387ff4d936ed84d9276.zip
- Added support selection of themes via a basename again (This should fix bugs #2473213 "GUI: Theme selection oddities and regressions" and #2219605 "GUI: theme detection")
- Changed default value to "scummmodern" instead of "scummmodern.zip" for "gui_theme" - Moved theme listing code from ThemeBrowser to GuiManager svn-id: r35680
-rw-r--r--gui/GuiManager.cpp163
-rw-r--r--gui/GuiManager.h16
-rw-r--r--gui/themebrowser.cpp103
-rw-r--r--gui/themebrowser.h16
4 files changed, 194 insertions, 104 deletions
diff --git a/gui/GuiManager.cpp b/gui/GuiManager.cpp
index 00babbea17..fc2b2c1a4b 100644
--- a/gui/GuiManager.cpp
+++ b/gui/GuiManager.cpp
@@ -26,6 +26,7 @@
#include "common/system.h"
#include "common/util.h"
#include "common/config-manager.h"
+#include "common/algorithm.h"
#include "gui/GuiManager.h"
#include "gui/dialog.h"
@@ -34,6 +35,10 @@
#include "graphics/cursorman.h"
+#ifdef MACOSX
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
DECLARE_SINGLETON(GUI::GuiManager);
namespace GUI {
@@ -56,10 +61,8 @@ GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled),
memset(_cursor, 0xFF, sizeof(_cursor));
- ConfMan.registerDefault("gui_theme", "scummmodern.zip");
+ ConfMan.registerDefault("gui_theme", "scummmodern");
Common::String themefile(ConfMan.get("gui_theme"));
- if (themefile.compareToIgnoreCase("default") == 0)
- themefile = "builtin";
ConfMan.registerDefault("gui_renderer", ThemeEngine::findModeConfigName(ThemeEngine::_defaultRendererMode));
ThemeEngine::GraphicsMode gfxMode = (ThemeEngine::GraphicsMode)ThemeEngine::findMode(ConfMan.get("gui_renderer"));
@@ -80,6 +83,13 @@ GuiManager::~GuiManager() {
}
bool GuiManager::loadNewTheme(Common::String filename, ThemeEngine::GraphicsMode gfx) {
+ // We currently allow two different ways of theme selection in our config file:
+ // 1) Via full path
+ // 2) Via a basename, which will need to be translated into a full path
+ // This function assures we have a correct path to pass to the ThemeEngine
+ // constructor.
+ filename = findThemeFile(filename);
+
// If we are asked to reload the currently active theme, just do nothing
// FIXME: Actually, why? It might be desirable at times to force a theme reload...
if (_theme && filename == _theme->getThemeId() && gfx == _theme->getGraphicsMode())
@@ -130,6 +140,153 @@ bool GuiManager::loadNewTheme(Common::String filename, ThemeEngine::GraphicsMode
return true;
}
+namespace {
+
+struct TDComparator {
+ const Common::String _id;
+ TDComparator(const Common::String &id) : _id(id) {}
+
+ bool operator()(const GuiManager::ThemeDescriptor &r) { return _id == r.id; }
+};
+
+} // end of anonymous namespace
+
+void GuiManager::listUseableThemes(Common::List<ThemeDescriptor> &list) {
+ ThemeDescriptor th;
+ th.name = "ScummVM Classic Theme (Builtin Version)";
+ th.id = "builtin";
+ th.filename = "builtin";
+ list.push_back(th);
+
+ if (ConfMan.hasKey("themepath"))
+ listUseableThemes(Common::FSNode(ConfMan.get("themepath")), list);
+
+#ifdef DATA_PATH
+ listUseableThemes(Common::FSNode(DATA_PATH), list);
+#endif
+
+#ifdef MACOSX
+ CFURLRef resourceUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
+ if (resourceUrl) {
+ char buf[256];
+ if (CFURLGetFileSystemRepresentation(resourceUrl, true, (UInt8 *)buf, 256)) {
+ Common::FSNode resourcePath(buf);
+ listUseableThemes(resourcePath, list);
+ }
+ CFRelease(resourceUrl);
+ }
+#endif
+
+ if (ConfMan.hasKey("extrapath"))
+ listUseableThemes(Common::FSNode(ConfMan.get("extrapath")), list);
+
+ listUseableThemes(Common::FSNode("."), list);
+
+ // Now we need to strip all duplicates
+ // TODO: It might not be the best idea to strip duplicates. The user might
+ // have different versions of a specific theme in his paths, thus this code
+ // might show him the wrong version. The problem is we have no ways of checking
+ // a theme version currently. Also since we want to avoid saving the full path
+ // in the config file we can not do any better currently.
+ Common::List<ThemeDescriptor> output;
+
+ for (Common::List<ThemeDescriptor>::const_iterator i = list.begin(); i != list.end(); ++i) {
+ if (find_if(output.begin(), output.end(), TDComparator(i->id)) == output.end())
+ output.push_back(*i);
+ }
+
+ list = output;
+ output.clear();
+}
+
+void GuiManager::listUseableThemes(Common::FSNode node, Common::List<ThemeDescriptor> &list) {
+ if (!node.exists() || !node.isReadable() || !node.isDirectory())
+ return;
+
+ ThemeDescriptor td;
+
+ // Check whether we point to a valid theme directory.
+ if (ThemeEngine::themeConfigUseable(node, td.name)) {
+ td.filename = node.getPath();
+ td.id = node.getName();
+
+ list.push_back(td);
+
+ // A theme directory should never contain any other themes
+ // thus we just return to the caller here.
+ return;
+ }
+
+ Common::FSList fileList;
+#ifdef USE_ZLIB
+ // Check all files. We need this to find all themes inside ZIP archives.
+ if (!node.getChildren(fileList, Common::FSNode::kListFilesOnly))
+ return;
+
+ for (Common::FSList::iterator i = fileList.begin(); i != fileList.end(); ++i) {
+ // We will only process zip files for now
+ if (!i->getPath().hasSuffix(".zip"))
+ continue;
+
+ td.name.clear();
+ if (ThemeEngine::themeConfigUseable(*i, td.name)) {
+ td.filename = i->getPath();
+ td.id = i->getName();
+
+ // If the name of the node object also contains
+ // the ".zip" suffix, we will strip it.
+ if (td.id.hasSuffix(".zip")) {
+ for (int j = 0; j < 4; ++j)
+ td.id.deleteLastChar();
+ }
+
+ list.push_back(td);
+ }
+ }
+
+ fileList.clear();
+#endif
+
+ // As next step we will search all subdirectories
+ if (!node.getChildren(fileList, Common::FSNode::kListDirectoriesOnly))
+ return;
+
+ for (Common::FSList::iterator i = fileList.begin(); i != fileList.end(); ++i)
+ listUseableThemes(*i, list);
+}
+
+Common::String GuiManager::findThemeFile(const Common::String &id) {
+ // FIXME: Actually "default" rather sounds like it should use
+ // our default theme which would me "scummmodern" instead
+ // of the builtin one.
+ if (id.equalsIgnoreCase("default"))
+ return "builtin";
+
+ Common::FSNode node(id);
+
+ // If the given id is a full path we'll just use it
+ if (node.exists() && (node.isDirectory() || (node.getName().hasSuffix(".zip") && !node.isDirectory())))
+ return id;
+
+ // FIXME:
+ // A very ugly hack to map a id to a filename, this will generate
+ // a complete theme list, thus it is slower than it could be.
+ // But it is the easiest solution for now.
+ Common::List<ThemeDescriptor> list;
+ listUseableThemes(list);
+
+ for (Common::List<ThemeDescriptor>::const_iterator i = list.begin(); i != list.end(); ++i) {
+ if (id.equalsIgnoreCase(i->id))
+ return i->filename;
+ }
+
+ warning("Could not find theme '%s' falling back to builtin", id.c_str());
+
+ // If no matching id has been found we will
+ // just fall back to the builtin theme
+ return "builtin";
+}
+
void GuiManager::redraw() {
int i;
diff --git a/gui/GuiManager.h b/gui/GuiManager.h
index c2ec61dd34..5e97fd82a2 100644
--- a/gui/GuiManager.h
+++ b/gui/GuiManager.h
@@ -29,6 +29,9 @@
#include "common/singleton.h"
#include "common/stack.h"
#include "common/str.h"
+#include "common/list.h"
+#include "common/fs.h"
+
#include "graphics/fontman.h"
#include "gui/widget.h"
@@ -90,6 +93,16 @@ public:
*/
bool checkScreenChange();
+ struct ThemeDescriptor {
+ Common::String name;
+ Common::String id;
+ Common::String filename;
+ };
+
+ /**
+ * Lists all theme files useable.
+ */
+ void listUseableThemes(Common::List<ThemeDescriptor> &list);
protected:
enum RedrawStatus {
kRedrawDisabled = 0,
@@ -144,6 +157,9 @@ protected:
Dialog *getTopDialog() const;
void screenChange();
+
+ Common::String findThemeFile(const Common::String &id);
+ void listUseableThemes(Common::FSNode node, Common::List<ThemeDescriptor> &list);
};
} // End of namespace GUI
diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp
index be79f300ed..7fc35e9bf0 100644
--- a/gui/themebrowser.cpp
+++ b/gui/themebrowser.cpp
@@ -25,13 +25,6 @@
#include "gui/themebrowser.h"
#include "gui/ListWidget.h"
#include "gui/widget.h"
-#include "common/config-manager.h"
-
-#include "common/fs.h"
-
-#ifdef MACOSX
-#include "CoreFoundation/CoreFoundation.h"
-#endif
namespace GUI {
@@ -78,7 +71,18 @@ void ThemeBrowser::handleCommand(CommandSender *sender, uint32 cmd, uint32 data)
int selection = _fileList->getSelected();
if (selection < 0)
break;
- _select = _themes[selection].file;
+
+ // TODO:
+ // Currently GuiManager::listUseableThemes uses a
+ // list. Thus we can not use operator[] here but
+ // need to iterate through the list. We might want
+ // to think of changing it, but it should not be
+ // of high importance anyway.
+ ThemeDescList::const_iterator sel = _themes.begin();
+ for (int i = 0; i < selection; ++i)
+ ++sel;
+
+ _select = sel->id;
setResult(1);
close();
break;
@@ -91,43 +95,9 @@ void ThemeBrowser::handleCommand(CommandSender *sender, uint32 cmd, uint32 data)
void ThemeBrowser::updateListing() {
_themes.clear();
- // classic is always built-in
- ThemeDescriptor th;
- th.name = "ScummVM Classic Theme (Builtin Version)";
- th.file = "builtin";
- _themes.push_back(th);
-
- // we are using only the paths 'themepath', 'extrapath', DATA_PATH and '.'
- // since these are the default locations for the theme files
- // files in other places are ignored in this dialog
- // TODO: let the user browse the complete FS too/only the FS?
- if (ConfMan.hasKey("themepath"))
- addDir(_themes, Common::FSNode(ConfMan.get("themepath")));
-
-#ifdef DATA_PATH
- addDir(_themes, Common::FSNode(DATA_PATH));
-#endif
-
-#ifdef MACOSX
- CFURLRef resourceUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
- if (resourceUrl) {
- char buf[256];
- if (CFURLGetFileSystemRepresentation(resourceUrl, true, (UInt8 *)buf, 256)) {
- Common::FSNode resourcePath(buf);
- addDir(_themes, resourcePath);
- }
- CFRelease(resourceUrl);
- }
-#endif
-
- if (ConfMan.hasKey("extrapath"))
- addDir(_themes, Common::FSNode(ConfMan.get("extrapath")));
-
- addDir(_themes, Common::FSNode("."));
+ g_gui.listUseableThemes(_themes);
- // Populate the ListWidget
Common::StringList list;
-
for (ThemeDescList::const_iterator i = _themes.begin(); i != _themes.end(); ++i)
list.push_back(i->name);
@@ -138,52 +108,5 @@ void ThemeBrowser::updateListing() {
draw();
}
-
-void ThemeBrowser::addDir(ThemeDescList &list, const Common::FSNode &node) {
- if (!node.exists() || !node.isReadable())
- return;
-
- // Scan this dir, all files and all subdirs in it for themes
- Common::FSList fslist;
- if (!node.getChildren(fslist, Common::FSNode::kListAll))
- return;
- fslist.push_back(node); // Yup, also scan the dir itself
-
- for (Common::FSList::const_iterator i = fslist.begin(); i != fslist.end(); ++i) {
-
- ThemeDescriptor th;
- if (isTheme(*i, th)) {
- bool add = true;
-
- for (ThemeDescList::const_iterator p = list.begin(); p != list.end(); ++p) {
- if (p->name == th.name || p->file == th.file) {
- add = false;
- break;
- }
- }
-
- if (add)
- list.push_back(th);
- }
- }
-}
-
-bool ThemeBrowser::isTheme(const Common::FSNode &node, ThemeDescriptor &out) {
- out.file = node.getPath();
-
-#ifdef USE_ZLIB
- if (!out.file.hasSuffix(".zip") && !node.isDirectory())
- return false;
-#else
- if (!node.isDirectory())
- return false;
-#endif
-
- if (!ThemeEngine::themeConfigUseable(node, out.name))
- return false;
-
- return true;
-}
-
} // end of namespace GUI
diff --git a/gui/themebrowser.h b/gui/themebrowser.h
index 477034d5be..b6327253ca 100644
--- a/gui/themebrowser.h
+++ b/gui/themebrowser.h
@@ -26,9 +26,10 @@
#define GUI_THEMEBROWSER_H
#include "gui/dialog.h"
+#include "gui/GuiManager.h"
+
#include "common/str.h"
-#include "common/fs.h"
-#include "common/array.h"
+#include "common/list.h"
namespace GUI {
@@ -44,20 +45,13 @@ public:
const Common::String &getSelected() const { return _select; }
private:
- struct ThemeDescriptor {
- Common::String name;
- Common::String file;
- };
-
ListWidget *_fileList;
Common::String _select;
- typedef Common::Array<ThemeDescriptor> ThemeDescList;
+
+ typedef Common::List<GuiManager::ThemeDescriptor> ThemeDescList;
ThemeDescList _themes;
void updateListing();
-
- void addDir(ThemeDescList &list, const Common::FSNode &node);
- bool isTheme(const Common::FSNode &node, ThemeDescriptor &out);
};
} // end of namespace GUI