forked from qt-creator/qt-creator
Theming: Do not use absolute path for built-in themes
+ always set the global palette and base style on apply This is required for correctly using the selected theme with multiple installations of Qt Creator. Task-number: QTCREATORBUG-13203 Task-number: QTCREATORBUG-13396 Change-Id: I036b96721b6d184dae43d08c5e8bc9e6d1328a7b Reviewed-by: Eike Ziller <eike.ziller@theqtcompany.com>
This commit is contained in:
committed by
Orgad Shaneh
parent
3ec16fe4d8
commit
3441594636
@@ -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<QColor, QString> 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;
|
||||
|
||||
@@ -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<QColor, QString> readNamedColor(const QString &color) const;
|
||||
};
|
||||
|
||||
QTCREATOR_UTILS_EXPORT Theme *creatorTheme();
|
||||
QTCREATOR_UTILS_EXPORT void setCreatorTheme(Theme *theme);
|
||||
|
||||
} // namespace Utils
|
||||
|
||||
|
||||
@@ -55,6 +55,8 @@ public:
|
||||
QMap<QString, QColor> palette;
|
||||
};
|
||||
|
||||
QTCREATOR_UTILS_EXPORT void setCreatorTheme(Theme *theme);
|
||||
|
||||
} // namespace Utils
|
||||
|
||||
#endif // THEME_P_H
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include <utils/savefile.h>
|
||||
#include <utils/stringutils.h>
|
||||
#include <utils/theme/theme.h>
|
||||
#include <utils/theme/theme_p.h>
|
||||
|
||||
#include <QtPlugin>
|
||||
#include <QDebug>
|
||||
@@ -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
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
#include <extensionsystem/iplugin.h>
|
||||
|
||||
namespace Utils { class Theme; }
|
||||
|
||||
namespace Core {
|
||||
|
||||
class DesignMode;
|
||||
|
||||
@@ -139,6 +139,7 @@ signals:
|
||||
void coreAboutToClose();
|
||||
void contextAboutToChange(const QList<Core::IContext *> &context);
|
||||
void contextChanged(const QList<Core::IContext *> &context, const Core::Context &additionalContexts);
|
||||
void themeChanged();
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -31,9 +31,11 @@
|
||||
#include "themesettingswidget.h"
|
||||
#include "coreconstants.h"
|
||||
#include "icore.h"
|
||||
#include "manhattanstyle.h"
|
||||
#include "themeeditor/themesettingstablemodel.h"
|
||||
|
||||
#include <utils/theme/theme.h>
|
||||
#include <utils/theme/theme_p.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QDebug>
|
||||
@@ -41,6 +43,7 @@
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QSettings>
|
||||
#include <QStyleFactory>
|
||||
|
||||
#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<ThemeEntry> 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<ManhattanStyle *>(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
|
||||
|
||||
@@ -46,8 +46,6 @@ public:
|
||||
ThemeSettingsWidget(QWidget *parent = 0);
|
||||
~ThemeSettingsWidget();
|
||||
|
||||
static QString defaultThemeFileName(const QString &fileName = QString());
|
||||
|
||||
void apply();
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user