|
From: Tapio V. <aa...@us...> - 2012-01-31 11:17:48
|
Author: Tapio Vierros <tap...@gm...>
Date: Tue Jan 31 13:14:36 2012 +0200
GUI theme switcher.
* Screen switching is currently needed to apply the new theme
* Uses enum config type
--> So might pick wrong saved theme when they are added or deleted
* Needs more testing
---
data/schema.xml | 7 ++++---
game/cache.cc | 2 +-
game/configuration.cc | 17 +++++++++++++++++
game/configuration.hh | 1 +
game/fs.cc | 31 +++++++++++++++++++++++++++++--
game/fs.hh | 3 +++
6 files changed, 55 insertions(+), 6 deletions(-)
diff --git a/data/schema.xml b/data/schema.xml
index 29b420c..a51b769 100644
--- a/data/schema.xml
+++ b/data/schema.xml
@@ -42,10 +42,11 @@ to save the current settings to XML.
<short>Pitch waves</short>
<long>Enable singing pitch display (when not in karaoke mode).</long>
</entry>
- <entry name="game/theme" type="string">
- <stringvalue>default</stringvalue>
+ <entry name="game/theme" type="int" value="-1">
+ <limits min="-1" max="-1" step="0" />
+ <!-- Enum options added dynamically by scanning theme folders -->
<short>Theme</short>
- <long>Name of the theme to use or absolute path to theme folder.</long>
+ <long>Name of the theme to use.</long>
</entry>
<entry name="game/keyboard_guitar" type="bool" value="true">
<short>Keyboard as guitar</short>
diff --git a/game/cache.cc b/game/cache.cc
index 0f1edd0..5fd637f 100644
--- a/game/cache.cc
+++ b/game/cache.cc
@@ -16,7 +16,7 @@ namespace cache {
#endif
if (isThemeResource(svgfilename)) {
- std::string const theme_name = (config["game/theme"].s().empty() ? "default" : config["game/theme"].s());
+ std::string const theme_name = (config["game/theme"].getEnumName().empty() ? "default" : config["game/theme"].getEnumName());
cache_filename = getCacheDir() / "themes" / theme_name / cache_basename;
} else {
// We use the full path under cache to avoid name collisions
diff --git a/game/configuration.cc b/game/configuration.cc
index de92d67..ec747db 100644
--- a/game/configuration.cc
+++ b/game/configuration.cc
@@ -152,6 +152,12 @@ void ConfigItem::addEnum(std::string name) {
m_step = 1;
}
+std::string ConfigItem::getEnumName() {
+ int val = i();
+ if (val >= 0 && val < m_enums.size()) return m_enums[val];
+ return "";
+}
+
template <typename T> void ConfigItem::updateNumeric(xmlpp::Element& elem, int mode) {
xmlpp::NodeSet ns = elem.find("limits");
if (!ns.empty()) setLimits<T>(dynamic_cast<xmlpp::Element&>(*ns[0]), m_min, m_max, m_step);
@@ -367,4 +373,15 @@ void readConfig() {
readConfigXML(schemafile, 0); // Read schema and defaults
readConfigXML(systemConfFile, 1); // Update defaults with system config
readConfigXML(userConfFile, 2); // Read user settings
+ { // Populate themes
+ ConfigItem& ci = config["game/theme"];
+ std::vector<std::string> themes = getThemes();
+ bool useDefaultTheme = (ci.i() == -1);
+ for (int i = 0; i < themes.size(); ++i) {
+ ci.addEnum(themes[i]);
+ // Select the default theme is no other is selected
+ if (useDefaultTheme && themes[i] == "default")
+ ci.i() = i;
+ }
+ }
}
diff --git a/game/configuration.hh b/game/configuration.hh
index 93278f8..3122ddd 100644
--- a/game/configuration.hh
+++ b/game/configuration.hh
@@ -38,6 +38,7 @@ class ConfigItem {
std::string const& getShortDesc() const { return m_shortDesc; } ///< get the short description for this ConfigItem
std::string const& getLongDesc() const { return m_longDesc; } ///< get the long description for this ConfigItem
void addEnum(std::string name); ///< Dynamically adds an enum to all values
+ std::string getEnumName(); ///< Returns the selected enum option's text
private:
template <typename T> void updateNumeric(xmlpp::Element& elem, int mode); ///< Used internally for loading XML
diff --git a/game/fs.cc b/game/fs.cc
index 545206e..cb59487 100644
--- a/game/fs.cc
+++ b/game/fs.cc
@@ -98,7 +98,7 @@ fs::path getCacheDir() {
}
fs::path getThemeDir() {
- std::string theme = config["game/theme"].s();
+ std::string theme = config["game/theme"].getEnumName();
static const std::string defaultTheme = "default";
if (theme.empty()) theme = defaultTheme;
return getDataDir() / "themes" / theme;
@@ -117,7 +117,7 @@ fs::path pathMangle(fs::path const& dir) {
}
std::string getThemePath(std::string const& filename) {
- std::string theme = config["game/theme"].s();
+ std::string theme = config["game/theme"].getEnumName();
static const std::string defaultTheme = "default";
if (theme.empty()) theme = defaultTheme;
// Try current theme and if that fails, try default theme and finally data dir
@@ -126,6 +126,33 @@ std::string getThemePath(std::string const& filename) {
return getPath(filename);
}
+std::vector<std::string> getThemes() {
+ std::vector<std::string> themes;
+ // Search all paths for themes folders and add them
+ Paths const& paths = getPaths();
+ for (Paths::const_iterator it = paths.begin(); it != paths.end(); ++it) {
+ fs::path p = *it;
+ p /= fs::path("themes");
+ if (fs::is_directory(p)) {
+ // Gather the themes in this folder
+ for (fs::directory_iterator dirIt(p), dirEnd; dirIt != dirEnd; ++dirIt) {
+ fs::path p2 = dirIt->path();
+ if (fs::is_directory(p2)) {
+ #if BOOST_FILESYSTEM_VERSION < 3
+ themes.push_back(p2.leaf());
+ #else
+ themes.push_back(p2.filename().string());
+ #endif
+ }
+ }
+ }
+ }
+ // No duplicates allowed
+ std::sort(themes.begin(), themes.end());
+ std::unique(themes.begin(), themes.end());
+ return themes;
+}
+
bool isThemeResource(fs::path filename){
try {
#if BOOST_FILESYSTEM_VERSION < 3
diff --git a/game/fs.hh b/game/fs.hh
index 2743425..a77265a 100644
--- a/game/fs.hh
+++ b/game/fs.hh
@@ -33,6 +33,9 @@ fs::path pathMangle(fs::path const& dir);
/** Get full path to a file from the current theme **/
std::string getThemePath(std::string const& filename);
+/** Get available theme names **/
+std::vector<std::string> getThemes();
+
/** Get full path to a share file **/
std::string getPath(fs::path const& filename);
|