Commit 34415946 authored by Orgad Shaneh's avatar Orgad Shaneh Committed by Orgad Shaneh
Browse files

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: default avatarEike Ziller <eike.ziller@theqtcompany.com>
parent 3ec16fe4
......@@ -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");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment