diff --git a/src/libs/utils/theme/theme.cpp b/src/libs/utils/theme/theme.cpp index ccfba5f6fcc..b73510e9d62 100644 --- a/src/libs/utils/theme/theme.cpp +++ b/src/libs/utils/theme/theme.cpp @@ -65,10 +65,11 @@ void setCreatorTheme(Theme *theme) m_creatorTheme = theme; } -Theme::Theme(QObject *parent) +Theme::Theme(const QString &name, QObject *parent) : QObject(parent) , d(new ThemePrivate) { + d->name = name; } Theme::~Theme() @@ -121,11 +122,16 @@ QPair Theme::readNamedColor(const QString &color) const return qMakePair(QColor::fromRgba(rgba), QString()); } -QString Theme::fileName() const +QString Theme::filePath() const { return d->fileName; } +QString Theme::name() const +{ + return d->name; +} + void Theme::setName(const QString &name) { d->name = name; diff --git a/src/libs/utils/theme/theme.h b/src/libs/utils/theme/theme.h index 8c6aa9bf630..d75962eb69e 100644 --- a/src/libs/utils/theme/theme.h +++ b/src/libs/utils/theme/theme.h @@ -54,7 +54,7 @@ class QTCREATOR_UTILS_EXPORT Theme : public QObject Q_ENUMS(WidgetStyle) public: - Theme(QObject *parent = 0); + Theme(const QString &name, QObject *parent = 0); ~Theme(); enum Color { @@ -203,7 +203,8 @@ public: QPalette palette() const; QStringList preferredStyles() const; - QString fileName() const; + QString filePath() const; + QString name() const; void setName(const QString &name); QVariantHash values() const; @@ -215,15 +216,11 @@ public: ThemePrivate *d; -signals: - void changed(); - private: QPair readNamedColor(const QString &color) const; }; QTCREATOR_UTILS_EXPORT Theme *creatorTheme(); -QTCREATOR_UTILS_EXPORT void setCreatorTheme(Theme *theme); } // namespace Utils diff --git a/src/libs/utils/theme/theme_p.h b/src/libs/utils/theme/theme_p.h index bf78904e7ed..48a9a669bd1 100644 --- a/src/libs/utils/theme/theme_p.h +++ b/src/libs/utils/theme/theme_p.h @@ -55,6 +55,8 @@ public: QMap palette; }; +QTCREATOR_UTILS_EXPORT void setCreatorTheme(Theme *theme); + } // namespace Utils #endif // THEME_P_H diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp index e84be25ac64..3b6d055c991 100644 --- a/src/plugins/coreplugin/coreplugin.cpp +++ b/src/plugins/coreplugin/coreplugin.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -90,11 +91,36 @@ CorePlugin::~CorePlugin() setCreatorTheme(0); } +static QString absoluteThemePath(const QString &themeName) +{ + if (themeName.isEmpty()) + return themeName; + QString res = QDir::fromNativeSeparators(themeName); + QFileInfo fi(res); + // Try the given name + if (fi.exists()) + return fi.absoluteFilePath(); + const QString suffix = QLatin1String("creatortheme"); + // Try name.creatortheme + if (fi.suffix() != suffix) { + res = themeName + QLatin1Char('.') + suffix; + fi.setFile(res); + if (fi.exists()) + return fi.absoluteFilePath(); + } + if (fi.path().isEmpty()) + return QString(); // absolute/relative path, but not found + // If only name was given, look it up in qtcreator/themes + res.prepend(ICore::resourcePath() + QLatin1String("/themes/")); + return QFileInfo::exists(res) ? res : QString(); +} + void CorePlugin::parseArguments(const QStringList &arguments) { - QString themeName = QLatin1String("default"); + const QString defaultTheme = QLatin1String("default"); + QString themeName = ICore::settings()->value( + QLatin1String(Constants::SETTINGS_THEME), defaultTheme).toString(); QColor overrideColor; - bool overrideTheme = false; bool presentationMode = false; for (int i = 0; i < arguments.size(); ++i) { @@ -106,34 +132,27 @@ void CorePlugin::parseArguments(const QStringList &arguments) if (arguments.at(i) == QLatin1String("-presentationMode")) presentationMode = true; if (arguments.at(i) == QLatin1String("-theme")) { - overrideTheme = true; themeName = arguments.at(i + 1); i++; } } - QSettings *settings = Core::ICore::settings(); - QString themeURI = settings->value(QLatin1String(Core::Constants::SETTINGS_THEME)).toString(); - - if (!QFileInfo::exists(themeURI) || overrideTheme) { - const QString builtInTheme = QStringLiteral("%1/themes/%2.creatortheme") - .arg(ICore::resourcePath()).arg(themeName); - if (QFile::exists(builtInTheme)) { - themeURI = builtInTheme; - } else if (themeName.endsWith(QLatin1String(".creatortheme"))) { - themeURI = themeName; - } else { // TODO: Fallback to default theme + QString themeURI = absoluteThemePath(themeName); + if (themeURI.isEmpty()) { + themeName = defaultTheme; + themeURI = QStringLiteral("%1/themes/%2.creatortheme").arg(ICore::resourcePath()).arg(themeName); + if (themeURI.isEmpty()) { qCritical("%s", qPrintable(QCoreApplication::translate("Application", "No valid theme '%1'") .arg(themeName))); } } QSettings themeSettings(themeURI, QSettings::IniFormat); - Theme *theme = new Theme(qApp); + Theme *theme = new Theme(themeName, qApp); theme->readSettings(themeSettings); - setCreatorTheme(theme); if (theme->flag(Theme::ApplyThemePaletteGlobally)) - QApplication::setPalette(creatorTheme()->palette()); + QApplication::setPalette(theme->palette()); + setCreatorTheme(theme); // defer creation of these widgets until here, // because they need a valid theme set diff --git a/src/plugins/coreplugin/coreplugin.h b/src/plugins/coreplugin/coreplugin.h index fafc896a0c7..ffc8df457e0 100644 --- a/src/plugins/coreplugin/coreplugin.h +++ b/src/plugins/coreplugin/coreplugin.h @@ -33,6 +33,8 @@ #include +namespace Utils { class Theme; } + namespace Core { class DesignMode; diff --git a/src/plugins/coreplugin/icore.h b/src/plugins/coreplugin/icore.h index 8014b1548e3..ce7fcd16587 100644 --- a/src/plugins/coreplugin/icore.h +++ b/src/plugins/coreplugin/icore.h @@ -139,6 +139,7 @@ signals: void coreAboutToClose(); void contextAboutToChange(const QList &context); void contextChanged(const QList &context, const Core::Context &additionalContexts); + void themeChanged(); }; } // namespace Core diff --git a/src/plugins/coreplugin/themeeditor/themesettingstablemodel.cpp b/src/plugins/coreplugin/themeeditor/themesettingstablemodel.cpp index 87826f87bb4..ef921417594 100644 --- a/src/plugins/coreplugin/themeeditor/themesettingstablemodel.cpp +++ b/src/plugins/coreplugin/themeeditor/themesettingstablemodel.cpp @@ -267,7 +267,6 @@ void ThemeSettingsTableModel::toTheme(Theme *t) const theme->widgetStyle = m_widgetStyle; theme->name = m_name; theme->preferredStyles = m_preferredStyles; - emit t->changed(); } Qt::ItemFlags ThemeSettingsTableModel::sectionHeaderFlags(int section) const diff --git a/src/plugins/coreplugin/themesettingswidget.cpp b/src/plugins/coreplugin/themesettingswidget.cpp index fd29e643639..200888762bd 100644 --- a/src/plugins/coreplugin/themesettingswidget.cpp +++ b/src/plugins/coreplugin/themesettingswidget.cpp @@ -31,9 +31,11 @@ #include "themesettingswidget.h" #include "coreconstants.h" #include "icore.h" +#include "manhattanstyle.h" #include "themeeditor/themesettingstablemodel.h" #include +#include #include #include @@ -41,6 +43,7 @@ #include #include #include +#include #include "ui_themesettings.h" @@ -53,9 +56,7 @@ const char themeNameKey[] = "ThemeName"; static QString customThemesPath() { - QString path = Core::ICore::userResourcePath(); - path.append(QLatin1String("/themes/")); - return path; + return ICore::userResourcePath() + QLatin1String("/themes/"); } static QString createThemeFileName(const QString &pattern) @@ -84,23 +85,27 @@ static QString createThemeFileName(const QString &pattern) struct ThemeEntry { ThemeEntry() {} - ThemeEntry(const QString &fileName, bool readOnly): - m_fileName(fileName), + ThemeEntry(const QString &name, const QString &filePath, bool readOnly): + m_name(name), + m_filePath(filePath), m_readOnly(readOnly) - { } + { + } - QString fileName() const { return m_fileName; } - QString name() const; + QString name() const { return m_name; } + QString displayName() const; + QString filePath() const { return m_filePath; } bool readOnly() const { return m_readOnly; } private: - QString m_fileName; + QString m_name; + QString m_filePath; bool m_readOnly; }; -QString ThemeEntry::name() const +QString ThemeEntry::displayName() const { - QSettings settings(m_fileName, QSettings::IniFormat); + QSettings settings(filePath(), QSettings::IniFormat); QString n = settings.value(QLatin1String(themeNameKey), QCoreApplication::tr("unnamed")).toString(); return m_readOnly ? QCoreApplication::tr("%1 (built-in)").arg(n) : n; } @@ -122,7 +127,7 @@ public: QVariant data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) - return m_themes.at(index.row()).name(); + return m_themes.at(index.row()).displayName(); return QVariant(); } @@ -168,7 +173,7 @@ ThemeSettingsPrivate::ThemeSettingsPrivate(QWidget *widget) , m_refreshingThemeList(false) , m_ui(new Ui::ThemeSettings) { - m_currentTheme = ThemeEntry(creatorTheme()->fileName(), true); + m_currentTheme = ThemeEntry(creatorTheme()->name(), creatorTheme()->filePath(), true); m_ui->setupUi(widget); m_ui->editor->hide(); // TODO: Restore after improving the editor m_ui->themeComboBox->setModel(m_themeListModel); @@ -203,22 +208,24 @@ void ThemeSettingsWidget::refreshThemeList() { QList themes; - QString resourcePath = Core::ICore::resourcePath(); - QDir themeDir(resourcePath + QLatin1String("/themes")); + QDir themeDir(ICore::resourcePath() + QLatin1String("/themes")); themeDir.setNameFilters(QStringList() << QLatin1String("*.creatortheme")); themeDir.setFilter(QDir::Files); int selected = 0; QStringList themeList = themeDir.entryList(); - QString defaultTheme = QFileInfo(defaultThemeFileName()).fileName(); - if (themeList.removeAll(defaultTheme)) + const QString defaultTheme = QLatin1String("default.creatortheme"); + if (themeList.removeOne(defaultTheme)) themeList.prepend(defaultTheme); - foreach (const QString &file, themeList) { - const QString fileName = themeDir.absoluteFilePath(file); - if (d->m_currentTheme.fileName() == fileName) - selected = themes.size(); - themes.append(ThemeEntry(fileName, true)); + const QLatin1String extension(".creatortheme"); + for (int i = 0, total = themeList.count(); i < total; ++i) { + const QString fileName = themeList.at(i); + if (d->m_currentTheme.name() + extension == fileName) + selected = i; + QString name = fileName; + name.remove(extension); + themes.append(ThemeEntry(name, themeDir.absoluteFilePath(fileName), true)); } if (themes.isEmpty()) @@ -227,9 +234,9 @@ void ThemeSettingsWidget::refreshThemeList() themeDir.setPath(customThemesPath()); foreach (const QString &file, themeDir.entryList()) { const QString fileName = themeDir.absoluteFilePath(file); - if (d->m_currentTheme.fileName() == fileName) + if (d->m_currentTheme.name() == fileName) selected = themes.size(); - themes.append(ThemeEntry(fileName, false)); + themes.append(ThemeEntry(fileName, fileName, false)); } d->m_currentTheme = themes[selected]; @@ -240,19 +247,6 @@ void ThemeSettingsWidget::refreshThemeList() d->m_refreshingThemeList = false; } -QString ThemeSettingsWidget::defaultThemeFileName(const QString &fileName) -{ - QString defaultScheme = Core::ICore::resourcePath(); - defaultScheme += QLatin1String("/themes/"); - - if (!fileName.isEmpty() && QFile::exists(defaultScheme + fileName)) - defaultScheme += fileName; - else - defaultScheme += QLatin1String("default.creatortheme"); - - return defaultScheme; -} - void ThemeSettingsWidget::themeSelected(int index) { bool readOnly = true; @@ -265,8 +259,8 @@ void ThemeSettingsWidget::themeSelected(int index) readOnly = entry.readOnly(); d->m_currentTheme = entry; - QSettings settings(entry.fileName(), QSettings::IniFormat); - Theme theme; + QSettings settings(entry.filePath(), QSettings::IniFormat); + Theme theme(entry.name()); theme.readSettings(settings); d->m_ui->editor->initFrom(&theme); } @@ -288,7 +282,7 @@ void ThemeSettingsWidget::confirmDeleteTheme() QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning, tr("Delete Theme"), - tr("Are you sure you want to delete the theme '%1' permanently?").arg(entry.name()), + tr("Are you sure you want to delete the theme '%1' permanently?").arg(entry.displayName()), QMessageBox::Discard | QMessageBox::Cancel, d->m_ui->deleteButton->window()); @@ -312,7 +306,7 @@ void ThemeSettingsWidget::deleteTheme() const ThemeEntry &entry = d->m_themeListModel->themeAt(index); QTC_ASSERT(!entry.readOnly(), return); - if (QFile::remove(entry.fileName())) + if (QFile::remove(entry.filePath())) d->m_themeListModel->removeTheme(index); } @@ -339,7 +333,7 @@ void ThemeSettingsWidget::maybeSaveTheme() QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning, tr("Theme Changed"), tr("The theme \"%1\" was modified, do you want to save the changes?") - .arg(d->m_currentTheme.name()), + .arg(d->m_currentTheme.displayName()), QMessageBox::Discard | QMessageBox::Save, d->m_ui->themeComboBox->window()); @@ -350,9 +344,9 @@ void ThemeSettingsWidget::maybeSaveTheme() messageBox->setDefaultButton(QMessageBox::Save); if (messageBox->exec() == QMessageBox::Save) { - Theme newTheme; + Theme newTheme(d->m_currentTheme.name()); d->m_ui->editor->model()->toTheme(&newTheme); - newTheme.writeSettings(d->m_currentTheme.fileName()); + newTheme.writeSettings(d->m_currentTheme.filePath()); } } @@ -378,10 +372,10 @@ void ThemeSettingsWidget::renameTheme() return; // overwrite file with new name - Theme newTheme; + Theme newTheme(entry.name()); d->m_ui->editor->model()->toTheme(&newTheme); newTheme.setName(newName); - newTheme.writeSettings(entry.fileName()); + newTheme.writeSettings(entry.filePath()); refreshThemeList(); } @@ -394,7 +388,7 @@ void ThemeSettingsWidget::copyThemeByName(const QString &name) const ThemeEntry &entry = d->m_themeListModel->themeAt(index); - QString baseFileName = QFileInfo(entry.fileName()).completeBaseName(); + QString baseFileName = QFileInfo(entry.filePath()).completeBaseName(); baseFileName += QLatin1String("_copy%1.creatortheme"); QString fileName = createThemeFileName(baseFileName); @@ -404,36 +398,46 @@ void ThemeSettingsWidget::copyThemeByName(const QString &name) // Ask about saving any existing modifactions maybeSaveTheme(); - Theme newTheme; + Theme newTheme(fileName); d->m_ui->editor->model()->toTheme(&newTheme); newTheme.setName(name); newTheme.writeSettings(fileName); - d->m_currentTheme = ThemeEntry(fileName, true); + d->m_currentTheme = ThemeEntry(fileName, fileName, true); refreshThemeList(); } void ThemeSettingsWidget::apply() { - { - d->m_ui->editor->model()->toTheme(creatorTheme()); - if (creatorTheme()->flag(Theme::ApplyThemePaletteGlobally)) - QApplication::setPalette(creatorTheme()->palette()); - foreach (QWidget *w, QApplication::topLevelWidgets()) - w->update(); + const QString themeName = d->m_currentTheme.name(); + Theme *newTheme = new Theme(themeName); + if (d->m_currentTheme.readOnly()) { + QSettings themeSettings(d->m_currentTheme.filePath(), QSettings::IniFormat); + newTheme->readSettings(themeSettings); + } else { + d->m_ui->editor->model()->toTheme(newTheme); + newTheme->writeSettings(d->m_currentTheme.filePath()); } - - // save definition of theme - if (!d->m_currentTheme.readOnly()) { - Theme newTheme; - d->m_ui->editor->model()->toTheme(&newTheme); - newTheme.writeSettings(d->m_currentTheme.fileName()); + setCreatorTheme(newTheme); + emit ICore::instance()->themeChanged(); + QPalette pal = newTheme->flag(Theme::ApplyThemePaletteGlobally) ? newTheme->palette() + : Theme::initialPalette(); + QApplication::setPalette(pal); + if (ManhattanStyle *style = qobject_cast(QApplication::style())) { + QStyle *baseStyle = 0; + foreach (const QString &s, creatorTheme()->preferredStyles()) { + if ((baseStyle = QStyleFactory::create(s))) + break; + } + style->setBaseStyle(baseStyle); } + foreach (QWidget *w, QApplication::topLevelWidgets()) + w->update(); // save filename of selected theme in global config QSettings *settings = Core::ICore::settings(); - settings->setValue(QLatin1String(Core::Constants::SETTINGS_THEME), d->m_currentTheme.fileName()); + settings->setValue(QLatin1String(Core::Constants::SETTINGS_THEME), themeName); } } // namespace Internal diff --git a/src/plugins/coreplugin/themesettingswidget.h b/src/plugins/coreplugin/themesettingswidget.h index 8ed5dd882d1..24ce6a2f01d 100644 --- a/src/plugins/coreplugin/themesettingswidget.h +++ b/src/plugins/coreplugin/themesettingswidget.h @@ -46,8 +46,6 @@ public: ThemeSettingsWidget(QWidget *parent = 0); ~ThemeSettingsWidget(); - static QString defaultThemeFileName(const QString &fileName = QString()); - void apply(); private slots: diff --git a/src/plugins/welcome/welcomeplugin.cpp b/src/plugins/welcome/welcomeplugin.cpp index c4d64f6d439..0364836925f 100644 --- a/src/plugins/welcome/welcomeplugin.cpp +++ b/src/plugins/welcome/welcomeplugin.cpp @@ -258,7 +258,7 @@ void WelcomeMode::initPlugins() ctx->setContextProperty(QLatin1String("pagesModel"), QVariant::fromValue(m_pluginList)); onThemeChanged(); - connect(creatorTheme(), &Theme::changed, this, &WelcomeMode::onThemeChanged); + connect(Core::ICore::instance(), &Core::ICore::themeChanged, this, &WelcomeMode::onThemeChanged); ctx->setContextProperty(QLatin1String("creatorTheme"), &m_themeProperties); QString path = resourcePath() + QLatin1String("/welcomescreen/welcomescreen.qml");