diff --git a/cockatrice/src/dlg_settings.cpp b/cockatrice/src/dlg_settings.cpp index 5a0c3298..5a397d5d 100644 --- a/cockatrice/src/dlg_settings.cpp +++ b/cockatrice/src/dlg_settings.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -291,10 +292,12 @@ AppearanceSettingsPage::AppearanceSettingsPage() } connect(&themeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(themeBoxChanged(int))); + connect(&openThemeButton, SIGNAL(clicked()), this, SLOT(openThemeLocation())); auto *themeGrid = new QGridLayout; themeGrid->addWidget(&themeLabel, 0, 0); themeGrid->addWidget(&themeBox, 0, 1); + themeGrid->addWidget(&openThemeButton, 1, 1); themeGroupBox = new QGroupBox; themeGroupBox->setLayout(themeGrid); @@ -370,10 +373,24 @@ void AppearanceSettingsPage::themeBoxChanged(int index) SettingsCache::instance().setThemeName(themeDirs.at(index)); } +void AppearanceSettingsPage::openThemeLocation() +{ + QString dir = SettingsCache::instance().getThemesPath(); + QDir dirDir = dir; + dirDir.cdUp(); + // open if dir exists, create if parent dir does exist + if (dirDir.exists() && dirDir.mkpath(dir)) { + QDesktopServices::openUrl(QUrl::fromLocalFile(dir)); + } else { + QMessageBox::critical(this, tr("Error"), tr("Could not create themes directory at '%1'.").arg(dir)); + } +} + void AppearanceSettingsPage::retranslateUi() { themeGroupBox->setTitle(tr("Theme settings")); themeLabel.setText(tr("Current theme:")); + openThemeButton.setText(tr("Open themes folder")); cardsGroupBox->setTitle(tr("Card rendering")); displayCardNamesCheckBox.setText(tr("Display card names on cards having a picture")); diff --git a/cockatrice/src/dlg_settings.h b/cockatrice/src/dlg_settings.h index bf80db42..d742b383 100644 --- a/cockatrice/src/dlg_settings.h +++ b/cockatrice/src/dlg_settings.h @@ -79,10 +79,12 @@ class AppearanceSettingsPage : public AbstractSettingsPage Q_OBJECT private slots: void themeBoxChanged(int index); + void openThemeLocation(); private: QLabel themeLabel; QComboBox themeBox; + QPushButton openThemeButton; QLabel minPlayersForMultiColumnLayoutLabel; QLabel maxFontSizeForCardsLabel; QCheckBox displayCardNamesCheckBox; diff --git a/cockatrice/src/settingscache.cpp b/cockatrice/src/settingscache.cpp index 32ed3427..65ba0fb0 100644 --- a/cockatrice/src/settingscache.cpp +++ b/cockatrice/src/settingscache.cpp @@ -197,6 +197,7 @@ SettingsCache::SettingsCache() deckPath = getSafeConfigPath("paths/decks", dataPath + "/decks/"); replaysPath = getSafeConfigPath("paths/replays", dataPath + "/replays/"); + themesPath = getSafeConfigPath("paths/themes", dataPath + "/themes/"); picsPath = getSafeConfigPath("paths/pics", dataPath + "/pics/"); // this has never been exposed as an user-configurable setting if (picsPath.endsWith("/")) { @@ -388,6 +389,13 @@ void SettingsCache::setReplaysPath(const QString &_replaysPath) settings->setValue("paths/replays", replaysPath); } +void SettingsCache::setThemesPath(const QString &_themesPath) +{ + themesPath = _themesPath; + settings->setValue("paths/themes", themesPath); + emit themeChanged(); +} + void SettingsCache::setCustomCardDatabasePath(const QString &_customCardDatabasePath) { customCardDatabasePath = _customCardDatabasePath; diff --git a/cockatrice/src/settingscache.h b/cockatrice/src/settingscache.h index d42cde18..e9478d76 100644 --- a/cockatrice/src/settingscache.h +++ b/cockatrice/src/settingscache.h @@ -66,7 +66,7 @@ private: QByteArray mainWindowGeometry; QByteArray tokenDialogGeometry; QString lang; - QString deckPath, replaysPath, picsPath, customPicsPath, cardDatabasePath, customCardDatabasePath, + QString deckPath, replaysPath, picsPath, customPicsPath, cardDatabasePath, customCardDatabasePath, themesPath, spoilerDatabasePath, tokenDatabasePath, themeName; bool notifyAboutUpdates; bool notifyAboutNewVersion; @@ -157,6 +157,10 @@ public: { return replaysPath; } + QString getThemesPath() const + { + return themesPath; + } QString getPicsPath() const { return picsPath; @@ -479,6 +483,7 @@ public slots: void setSeenTips(const QList &_seenTips); void setDeckPath(const QString &_deckPath); void setReplaysPath(const QString &_replaysPath); + void setThemesPath(const QString &_themesPath); void setCustomCardDatabasePath(const QString &_customCardDatabasePath); void setPicsPath(const QString &_picsPath); void setCardDatabasePath(const QString &_cardDatabasePath); diff --git a/cockatrice/src/thememanager.cpp b/cockatrice/src/thememanager.cpp index ee05f355..e51b0314 100644 --- a/cockatrice/src/thememanager.cpp +++ b/cockatrice/src/thememanager.cpp @@ -9,12 +9,17 @@ #include #include -#define DEFAULT_THEME_NAME "Default" +#define NONE_THEME_NAME "None " #define STYLE_CSS_NAME "style.css" #define HANDZONE_BG_NAME "handzone" #define PLAYERZONE_BG_NAME "playerzone" #define STACKZONE_BG_NAME "stackzone" #define TABLEZONE_BG_NAME "tablezone" +static const QColor HANDZONE_BG_DEFAULT = QColor(80, 100, 50); +static const QColor TABLEZONE_BG_DEFAULT = QColor(70, 50, 100); +static const QColor PLAYERZONE_BG_DEFAULT = QColor(200, 200, 200); +static const QColor STACKZONE_BG_DEFAULT = QColor(113, 43, 43); +static const QStringList DEFAULT_RESOURCE_PATHS = {":/resources"}; ThemeManager::ThemeManager(QObject *parent) : QObject(parent) { @@ -28,7 +33,7 @@ void ThemeManager::ensureThemeDirectoryExists() if (SettingsCache::instance().getThemeName().isEmpty() || !getAvailableThemes().contains(SettingsCache::instance().getThemeName())) { qDebug() << "Theme name not set, setting default value"; - SettingsCache::instance().setThemeName(DEFAULT_THEME_NAME); + SettingsCache::instance().setThemeName(NONE_THEME_NAME); } } @@ -37,12 +42,16 @@ QStringMap &ThemeManager::getAvailableThemes() QDir dir; availableThemes.clear(); - // load themes from user profile dir - dir.setPath(SettingsCache::instance().getDataPath() + "/themes"); + // add default value + availableThemes.insert(NONE_THEME_NAME, QString()); - foreach (QString themeName, dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) { - if (!availableThemes.contains(themeName)) + // load themes from user profile dir + dir.setPath(SettingsCache::instance().getThemesPath()); + + for (QString themeName : dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) { + if (!availableThemes.contains(themeName)) { availableThemes.insert(themeName, dir.absoluteFilePath(themeName)); + } } // load themes from cockatrice system dir @@ -56,9 +65,10 @@ QStringMap &ThemeManager::getAvailableThemes() #endif ); - foreach (QString themeName, dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) { - if (!availableThemes.contains(themeName)) + for (QString themeName : dir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot, QDir::Name)) { + if (!availableThemes.contains(themeName)) { availableThemes.insert(themeName, dir.absoluteFilePath(themeName)); + } } return availableThemes; @@ -97,26 +107,36 @@ void ThemeManager::themeChangedSlot() QString themeName = SettingsCache::instance().getThemeName(); qDebug() << "Theme changed:" << themeName; - QDir dir = getAvailableThemes().value(themeName); + QString dirPath = getAvailableThemes().value(themeName); + QDir dir = dirPath; // css - if (dir.exists(STYLE_CSS_NAME)) - + if (!dirPath.isEmpty() && dir.exists(STYLE_CSS_NAME)) { qApp->setStyleSheet("file:///" + dir.absoluteFilePath(STYLE_CSS_NAME)); - else + } else { qApp->setStyleSheet(""); + } - // resources - QStringList resources; - resources << dir.absolutePath() << ":/resources"; - QDir::setSearchPaths("theme", resources); + if (dirPath.isEmpty()) { + // set default values + QDir::setSearchPaths("theme", DEFAULT_RESOURCE_PATHS); + handBgBrush = HANDZONE_BG_DEFAULT; + tableBgBrush = TABLEZONE_BG_DEFAULT; + playerBgBrush = PLAYERZONE_BG_DEFAULT; + stackBgBrush = STACKZONE_BG_DEFAULT; + } else { + // resources + QStringList resources; + resources << dir.absolutePath() << DEFAULT_RESOURCE_PATHS; + QDir::setSearchPaths("theme", resources); - // zones bg - dir.cd("zones"); - handBgBrush = loadBrush(HANDZONE_BG_NAME, QColor(80, 100, 50)); - tableBgBrush = loadBrush(TABLEZONE_BG_NAME, QColor(70, 50, 100)); - playerBgBrush = loadBrush(PLAYERZONE_BG_NAME, QColor(200, 200, 200)); - stackBgBrush = loadBrush(STACKZONE_BG_NAME, QColor(113, 43, 43)); + // zones bg + dir.cd("zones"); + handBgBrush = loadBrush(HANDZONE_BG_NAME, HANDZONE_BG_DEFAULT); + tableBgBrush = loadBrush(TABLEZONE_BG_NAME, TABLEZONE_BG_DEFAULT); + playerBgBrush = loadBrush(PLAYERZONE_BG_NAME, PLAYERZONE_BG_DEFAULT); + stackBgBrush = loadBrush(STACKZONE_BG_NAME, STACKZONE_BG_DEFAULT); + } tableBgBrushesCache.clear(); stackBgBrushesCache.clear(); playerBgBrushesCache.clear(); diff --git a/cockatrice/themes/CMakeLists.txt b/cockatrice/themes/CMakeLists.txt index 2ec2ae87..c417dfa2 100644 --- a/cockatrice/themes/CMakeLists.txt +++ b/cockatrice/themes/CMakeLists.txt @@ -3,7 +3,6 @@ # add themes subfolders SET(defthemes - Default Fabric Leather Plasma diff --git a/cockatrice/themes/Default/.gitignore b/cockatrice/themes/Default/.gitignore deleted file mode 100644 index 86d0cb27..00000000 --- a/cockatrice/themes/Default/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore \ No newline at end of file diff --git a/dbconverter/src/mocks.cpp b/dbconverter/src/mocks.cpp index d1994af3..82e732e7 100644 --- a/dbconverter/src/mocks.cpp +++ b/dbconverter/src/mocks.cpp @@ -96,6 +96,9 @@ void SettingsCache::setDeckPath(const QString &/* _deckPath */) void SettingsCache::setReplaysPath(const QString &/* _replaysPath */) { } +void SettingsCache::setThemesPath(const QString &/* _themesPath */) +{ +} void SettingsCache::setPicsPath(const QString &/* _picsPath */) { } diff --git a/tests/carddatabase/mocks.cpp b/tests/carddatabase/mocks.cpp index b9a530f5..1edd57bd 100644 --- a/tests/carddatabase/mocks.cpp +++ b/tests/carddatabase/mocks.cpp @@ -100,6 +100,9 @@ void SettingsCache::setDeckPath(const QString &/* _deckPath */) void SettingsCache::setReplaysPath(const QString &/* _replaysPath */) { } +void SettingsCache::setThemesPath(const QString &/* _themesPath */) +{ +} void SettingsCache::setPicsPath(const QString &/* _picsPath */) { }