summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>2014-11-06 09:31:56 +0200
committerOrgad Shaneh <orgads@gmail.com>2014-11-07 09:38:23 +0100
commitc1a76f8cc1e75ffbe2cf6917553d878a6fc433bf (patch)
treec84af830629658798722508b9aa3958568714890
parente871225057bce0374d04bf480d589086d3d0f5b1 (diff)
downloadqt-creator-c1a76f8cc1e75ffbe2cf6917553d878a6fc433bf.tar.gz
Core: Separate theme settings widget from options page
Change-Id: I6537e592f87969af5c2e53606a704fabec62fedc Reviewed-by: Alessandro Portale <alessandro.portale@digia.com>
-rw-r--r--src/plugins/coreplugin/coreplugin.pro2
-rw-r--r--src/plugins/coreplugin/coreplugin.qbs5
-rw-r--r--src/plugins/coreplugin/themesettings.cpp414
-rw-r--r--src/plugins/coreplugin/themesettings.h17
-rw-r--r--src/plugins/coreplugin/themesettingswidget.cpp438
-rw-r--r--src/plugins/coreplugin/themesettingswidget.h70
6 files changed, 525 insertions, 421 deletions
diff --git a/src/plugins/coreplugin/coreplugin.pro b/src/plugins/coreplugin/coreplugin.pro
index e822521e6a..8d43fb816b 100644
--- a/src/plugins/coreplugin/coreplugin.pro
+++ b/src/plugins/coreplugin/coreplugin.pro
@@ -17,6 +17,7 @@ SOURCES += corejsextensions.cpp \
fancytabwidget.cpp \
generalsettings.cpp \
themesettings.cpp \
+ themesettingswidget.cpp \
id.cpp \
icontext.cpp \
jsexpander.cpp \
@@ -121,6 +122,7 @@ HEADERS += corejsextensions.h \
fancytabwidget.h \
generalsettings.h \
themesettings.h \
+ themesettingswidget.h \
id.h \
jsexpander.h \
messagemanager.h \
diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs
index 426377e95e..f056dd100a 100644
--- a/src/plugins/coreplugin/coreplugin.qbs
+++ b/src/plugins/coreplugin/coreplugin.qbs
@@ -98,9 +98,8 @@ QtcPlugin {
"styleanimator.cpp", "styleanimator.h",
"tabpositionindicator.cpp", "tabpositionindicator.h",
"textdocument.cpp", "textdocument.h",
- "themesettings.cpp",
- "themesettings.h",
- "themesettings.ui",
+ "themesettings.cpp", "themesettings.h", "themesettings.ui",
+ "themesettingswidget.cpp", "themesettingswidget.h",
"toolsettings.cpp", "toolsettings.h",
"variablechooser.cpp", "variablechooser.h",
"vcsmanager.cpp", "vcsmanager.h",
diff --git a/src/plugins/coreplugin/themesettings.cpp b/src/plugins/coreplugin/themesettings.cpp
index 1332e59d86..1e2a768b2d 100644
--- a/src/plugins/coreplugin/themesettings.cpp
+++ b/src/plugins/coreplugin/themesettings.cpp
@@ -29,436 +29,44 @@
****************************************************************************/
#include "themesettings.h"
+#include "themesettingswidget.h"
#include "coreconstants.h"
-#include "icore.h"
-#include "editormanager/editormanager_p.h"
-#include "themeeditor/themesettingstablemodel.h"
-
-#include <utils/qtcassert.h>
-
-#include <QDebug>
-#include <QDir>
-#include <QInputDialog>
-#include <QMessageBox>
-#include <QSettings>
-
-#include "ui_themesettings.h"
-
-using namespace Utils;
namespace Core {
namespace Internal {
-const char themeNameKey[] = "ThemeName";
-
-static QString customThemesPath()
-{
- QString path = Core::ICore::userResourcePath();
- path.append(QLatin1String("/themes/"));
- return path;
-}
-
-static QString createThemeFileName(const QString &pattern)
-{
- const QString stylesPath = customThemesPath();
- QString baseFileName = stylesPath;
- baseFileName += pattern;
-
- // Find an available file name
- int i = 1;
- QString fileName;
- do {
- fileName = baseFileName.arg((i == 1) ? QString() : QString::number(i));
- ++i;
- } while (QFile::exists(fileName));
-
- // Create the base directory when it doesn't exist
- if (!QFile::exists(stylesPath) && !QDir().mkpath(stylesPath)) {
- qWarning() << "Failed to create theme directory:" << stylesPath;
- return QString();
- }
- return fileName;
-}
-
-
-struct ThemeEntry
-{
- ThemeEntry() {}
- ThemeEntry(const QString &fileName, bool readOnly):
- m_fileName(fileName),
- m_readOnly(readOnly)
- { }
-
- QString fileName() const { return m_fileName; }
- QString name() const;
- bool readOnly() const { return m_readOnly; }
-
-private:
- QString m_fileName;
- bool m_readOnly;
-};
-
-QString ThemeEntry::name() const
-{
- QSettings settings(m_fileName, QSettings::IniFormat);
- QString n = settings.value(QLatin1String(themeNameKey), QCoreApplication::tr("unnamed")).toString();
- return m_readOnly ? QCoreApplication::tr("%1 (built-in)").arg(n) : n;
-}
-
-
-class ThemeListModel : public QAbstractListModel
-{
-public:
- ThemeListModel(QObject *parent = 0):
- QAbstractListModel(parent)
- {
- }
-
- int rowCount(const QModelIndex &parent) const
- {
- return parent.isValid() ? 0 : m_themes.size();
- }
-
- QVariant data(const QModelIndex &index, int role) const
- {
- if (role == Qt::DisplayRole)
- return m_themes.at(index.row()).name();
- return QVariant();
- }
-
- void removeTheme(int index)
- {
- beginRemoveRows(QModelIndex(), index, index);
- m_themes.removeAt(index);
- endRemoveRows();
- }
-
- void setThemes(const QList<ThemeEntry> &themes)
- {
- beginResetModel();
- m_themes = themes;
- endResetModel();
- }
-
- const ThemeEntry &themeAt(int index) const
- {
- return m_themes.at(index);
- }
-
-private:
- QList<ThemeEntry> m_themes;
-};
-
-
-class ThemeSettingsPrivate
-{
-public:
- ThemeSettingsPrivate();
- ~ThemeSettingsPrivate();
-
-public:
- ThemeListModel *m_themeListModel;
- bool m_refreshingThemeList;
- Ui::ThemeSettings *m_ui;
- QPointer<QWidget> m_widget;
- ThemeEntry m_currentTheme;
-};
-
-ThemeSettingsPrivate::ThemeSettingsPrivate()
- : m_themeListModel(new ThemeListModel)
- , m_refreshingThemeList(false)
- , m_ui(0)
-{
- m_currentTheme = ThemeEntry(creatorTheme()->fileName(), true);
-}
-
-ThemeSettingsPrivate::~ThemeSettingsPrivate()
-{
- delete m_themeListModel;
-}
-
-ThemeSettings::ThemeSettings()
+ThemeSettings::ThemeSettings() :
+ m_widget(0)
{
setId(Core::Constants::SETTINGS_ID_ENVIRONMENT);
setDisplayName(tr("Theme"));
setCategory(Core::Constants::SETTINGS_CATEGORY_CORE);
setDisplayCategory(QCoreApplication::translate("Core", Core::Constants::SETTINGS_TR_CATEGORY_CORE));
setCategoryIcon(QLatin1String(Core::Constants::SETTINGS_CATEGORY_CORE_ICON));
-
- d = new ThemeSettingsPrivate();
}
ThemeSettings::~ThemeSettings()
{
- delete d;
-}
-
-void ThemeSettings::refreshThemeList()
-{
- QList<ThemeEntry> themes;
-
- QString resourcePath = Core::ICore::resourcePath();
- QDir themeDir(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))
- 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));
- }
-
- if (themes.isEmpty())
- qWarning() << "Warning: no themes found in path:" << themeDir.path();
-
- themeDir.setPath(customThemesPath());
- foreach (const QString &file, themeDir.entryList()) {
- const QString fileName = themeDir.absoluteFilePath(file);
- if (d->m_currentTheme.fileName() == fileName)
- selected = themes.size();
- themes.append(ThemeEntry(fileName, false));
- }
-
- d->m_currentTheme = themes[selected];
-
- d->m_refreshingThemeList = true;
- d->m_themeListModel->setThemes(themes);
- d->m_ui->themeComboBox->setCurrentIndex(selected);
- d->m_refreshingThemeList = false;
-}
-
-QString ThemeSettings::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 ThemeSettings::themeSelected(int index)
-{
- bool readOnly = true;
- if (index != -1) {
- // Check whether we're switching away from a changed theme
- if (!d->m_refreshingThemeList)
- maybeSaveTheme();
-
- const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
- readOnly = entry.readOnly();
- d->m_currentTheme = entry;
-
- QSettings settings(entry.fileName(), QSettings::IniFormat);
- Theme theme;
- theme.readSettings(settings);
- d->m_ui->editor->initFrom(&theme);
- }
- d->m_ui->copyButton->setEnabled(index != -1);
- d->m_ui->deleteButton->setEnabled(!readOnly);
- d->m_ui->renameButton->setEnabled(!readOnly);
- d->m_ui->editor->setReadOnly(readOnly);
+ delete m_widget;
}
QWidget *ThemeSettings::widget()
{
- if (!d->m_widget) {
- d->m_widget = new QWidget;
- d->m_ui = new Ui::ThemeSettings();
- d->m_ui->setupUi(d->m_widget);
- d->m_ui->themeComboBox->setModel(d->m_themeListModel);
-
- connect(d->m_ui->themeComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
- this, &ThemeSettings::themeSelected);
- connect(d->m_ui->copyButton, &QAbstractButton::clicked, this, &ThemeSettings::copyTheme);
- connect(d->m_ui->renameButton, &QAbstractButton::clicked, this, &ThemeSettings::renameTheme);
- connect(d->m_ui->deleteButton, &QAbstractButton::clicked, this, &ThemeSettings::confirmDeleteTheme);
-
- refreshThemeList();
- }
- return d->m_widget;
-}
-
-void ThemeSettings::confirmDeleteTheme()
-{
- const int index = d->m_ui->themeComboBox->currentIndex();
- if (index == -1)
- return;
-
- const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
- if (entry.readOnly())
- return;
-
- QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning,
- tr("Delete Theme"),
- tr("Are you sure you want to delete the theme '%1' permanently?").arg(entry.name()),
- QMessageBox::Discard | QMessageBox::Cancel,
- d->m_ui->deleteButton->window());
-
- // Change the text and role of the discard button
- QPushButton *deleteButton = static_cast<QPushButton*>(messageBox->button(QMessageBox::Discard));
- deleteButton->setText(tr("Delete"));
- messageBox->addButton(deleteButton, QMessageBox::AcceptRole);
- messageBox->setDefaultButton(deleteButton);
-
- connect(deleteButton, &QAbstractButton::clicked, messageBox, &QDialog::accept);
- connect(messageBox, &QDialog::accepted, this, &ThemeSettings::deleteTheme);
- messageBox->setAttribute(Qt::WA_DeleteOnClose);
- messageBox->open();
-}
-
-void ThemeSettings::deleteTheme()
-{
- const int index = d->m_ui->themeComboBox->currentIndex();
- QTC_ASSERT(index != -1, return);
-
- const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
- QTC_ASSERT(!entry.readOnly(), return);
-
- if (QFile::remove(entry.fileName()))
- d->m_themeListModel->removeTheme(index);
-}
-
-void ThemeSettings::copyTheme()
-{
- QInputDialog *dialog = new QInputDialog(d->m_ui->copyButton->window());
- dialog->setAttribute(Qt::WA_DeleteOnClose);
- dialog->setInputMode(QInputDialog::TextInput);
- dialog->setWindowTitle(tr("Copy Theme"));
- dialog->setLabelText(tr("Theme name:"));
-
- //TODO
- //dialog->setTextValue(tr("%1 (copy)").arg(d_ptr->m_value.colorScheme().displayName()));
-
- connect(dialog, &QInputDialog::textValueSelected, this, &ThemeSettings::copyThemeByName);
- dialog->open();
-}
-
-void ThemeSettings::maybeSaveTheme()
-{
- if (!d->m_ui->editor->model()->hasChanges())
- return;
-
- 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()),
- QMessageBox::Discard | QMessageBox::Save,
- d->m_ui->themeComboBox->window());
-
- // Change the text of the discard button
- QPushButton *discardButton = static_cast<QPushButton*>(messageBox->button(QMessageBox::Discard));
- discardButton->setText(tr("Discard"));
- messageBox->addButton(discardButton, QMessageBox::DestructiveRole);
- messageBox->setDefaultButton(QMessageBox::Save);
-
- if (messageBox->exec() == QMessageBox::Save) {
- Theme newTheme;
- d->m_ui->editor->model()->toTheme(&newTheme);
- newTheme.writeSettings(d->m_currentTheme.fileName());
- }
-}
-
-void ThemeSettings::renameTheme()
-{
- int index = d->m_ui->themeComboBox->currentIndex();
- if (index == -1)
- return;
- const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
-
- maybeSaveTheme();
-
- QInputDialog *dialog = new QInputDialog(d->m_ui->renameButton->window());
- dialog->setInputMode(QInputDialog::TextInput);
- dialog->setWindowTitle(tr("Rename Theme"));
- dialog->setLabelText(tr("Theme name:"));
- dialog->setTextValue(d->m_ui->editor->model()->m_name);
- int ret = dialog->exec();
- QString newName = dialog->textValue();
- delete dialog;
-
- if (ret != QDialog::Accepted || newName.isEmpty())
- return;
-
- // overwrite file with new name
- Theme newTheme;
- d->m_ui->editor->model()->toTheme(&newTheme);
- newTheme.setName(newName);
- newTheme.writeSettings(entry.fileName());
-
- refreshThemeList();
-}
-
-void ThemeSettings::copyThemeByName(const QString &name)
-{
- int index = d->m_ui->themeComboBox->currentIndex();
- if (index == -1)
- return;
-
- const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
-
- QString baseFileName = QFileInfo(entry.fileName()).completeBaseName();
- baseFileName += QLatin1String("_copy%1.creatortheme");
- QString fileName = createThemeFileName(baseFileName);
-
- if (fileName.isEmpty())
- return;
-
- // Ask about saving any existing modifactions
- maybeSaveTheme();
-
- Theme newTheme;
- d->m_ui->editor->model()->toTheme(&newTheme);
- newTheme.setName(name);
- newTheme.writeSettings(fileName);
-
- d->m_currentTheme = ThemeEntry(fileName, true);
-
- refreshThemeList();
+ if (!m_widget)
+ m_widget = new ThemeSettingsWidget;
+ return m_widget;
}
void ThemeSettings::apply()
{
- if (!d->m_ui) // wasn't shown, can't be changed
- return;
-
- {
- d->m_ui->editor->model()->toTheme(creatorTheme());
- if (creatorTheme()->flag(Theme::ApplyThemePaletteGlobally))
- QApplication::setPalette(creatorTheme()->palette(QApplication::palette()));
- foreach (QWidget *w, QApplication::topLevelWidgets())
- w->update();
- }
-
- // save definition of theme
- if (!d->m_currentTheme.readOnly()) {
- Theme newTheme;
- d->m_ui->editor->model()->toTheme(&newTheme);
- newTheme.writeSettings(d->m_currentTheme.fileName());
- }
-
- // save filename of selected theme in global config
- QSettings *settings = Core::ICore::settings();
- settings->setValue(QLatin1String(Core::Constants::SETTINGS_THEME), d->m_currentTheme.fileName());
+ if (m_widget)
+ m_widget->apply();
}
void ThemeSettings::finish()
{
- delete d->m_widget;
- if (!d->m_ui) // page was never shown
- return
- delete d->m_ui;
- d->m_ui = 0;
+ delete m_widget;
+ m_widget = 0;
}
} // namespace Internal
diff --git a/src/plugins/coreplugin/themesettings.h b/src/plugins/coreplugin/themesettings.h
index a204acd7a1..d5027711f7 100644
--- a/src/plugins/coreplugin/themesettings.h
+++ b/src/plugins/coreplugin/themesettings.h
@@ -36,7 +36,7 @@
namespace Core {
namespace Internal {
-class ThemeSettingsPrivate;
+class ThemeSettingsWidget;
class ThemeSettings : public IOptionsPage
{
@@ -50,20 +50,7 @@ public:
void apply();
void finish();
- static QString defaultThemeFileName(const QString &fileName = QString());
-
-private slots:
- void themeSelected(int index);
- void copyTheme();
- void renameTheme();
- void copyThemeByName(const QString &);
- void confirmDeleteTheme();
- void deleteTheme();
- void maybeSaveTheme();
-
-private:
- void refreshThemeList();
- ThemeSettingsPrivate *d;
+ ThemeSettingsWidget *m_widget;
};
} // namespace Internal
diff --git a/src/plugins/coreplugin/themesettingswidget.cpp b/src/plugins/coreplugin/themesettingswidget.cpp
new file mode 100644
index 0000000000..3ef6ef1a6f
--- /dev/null
+++ b/src/plugins/coreplugin/themesettingswidget.cpp
@@ -0,0 +1,438 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "themesettingswidget.h"
+#include "coreconstants.h"
+#include "icore.h"
+#include "themeeditor/themesettingstablemodel.h"
+
+#include <utils/theme/theme.h>
+#include <utils/qtcassert.h>
+
+#include <QDir>
+#include <QInputDialog>
+#include <QMessageBox>
+#include <QSettings>
+
+#include "ui_themesettings.h"
+
+using namespace Utils;
+
+namespace Core {
+namespace Internal {
+
+const char themeNameKey[] = "ThemeName";
+
+static QString customThemesPath()
+{
+ QString path = Core::ICore::userResourcePath();
+ path.append(QLatin1String("/themes/"));
+ return path;
+}
+
+static QString createThemeFileName(const QString &pattern)
+{
+ const QString stylesPath = customThemesPath();
+ QString baseFileName = stylesPath;
+ baseFileName += pattern;
+
+ // Find an available file name
+ int i = 1;
+ QString fileName;
+ do {
+ fileName = baseFileName.arg((i == 1) ? QString() : QString::number(i));
+ ++i;
+ } while (QFile::exists(fileName));
+
+ // Create the base directory when it doesn't exist
+ if (!QFile::exists(stylesPath) && !QDir().mkpath(stylesPath)) {
+ qWarning() << "Failed to create theme directory:" << stylesPath;
+ return QString();
+ }
+ return fileName;
+}
+
+
+struct ThemeEntry
+{
+ ThemeEntry() {}
+ ThemeEntry(const QString &fileName, bool readOnly):
+ m_fileName(fileName),
+ m_readOnly(readOnly)
+ { }
+
+ QString fileName() const { return m_fileName; }
+ QString name() const;
+ bool readOnly() const { return m_readOnly; }
+
+private:
+ QString m_fileName;
+ bool m_readOnly;
+};
+
+QString ThemeEntry::name() const
+{
+ QSettings settings(m_fileName, QSettings::IniFormat);
+ QString n = settings.value(QLatin1String(themeNameKey), QCoreApplication::tr("unnamed")).toString();
+ return m_readOnly ? QCoreApplication::tr("%1 (built-in)").arg(n) : n;
+}
+
+
+class ThemeListModel : public QAbstractListModel
+{
+public:
+ ThemeListModel(QObject *parent = 0):
+ QAbstractListModel(parent)
+ {
+ }
+
+ int rowCount(const QModelIndex &parent) const
+ {
+ return parent.isValid() ? 0 : m_themes.size();
+ }
+
+ QVariant data(const QModelIndex &index, int role) const
+ {
+ if (role == Qt::DisplayRole)
+ return m_themes.at(index.row()).name();
+ return QVariant();
+ }
+
+ void removeTheme(int index)
+ {
+ beginRemoveRows(QModelIndex(), index, index);
+ m_themes.removeAt(index);
+ endRemoveRows();
+ }
+
+ void setThemes(const QList<ThemeEntry> &themes)
+ {
+ beginResetModel();
+ m_themes = themes;
+ endResetModel();
+ }
+
+ const ThemeEntry &themeAt(int index) const
+ {
+ return m_themes.at(index);
+ }
+
+private:
+ QList<ThemeEntry> m_themes;
+};
+
+
+class ThemeSettingsPrivate
+{
+public:
+ ThemeSettingsPrivate(QWidget *widget);
+ ~ThemeSettingsPrivate();
+
+public:
+ ThemeListModel *m_themeListModel;
+ bool m_refreshingThemeList;
+ Ui::ThemeSettings *m_ui;
+ ThemeEntry m_currentTheme;
+};
+
+ThemeSettingsPrivate::ThemeSettingsPrivate(QWidget *widget)
+ : m_themeListModel(new ThemeListModel)
+ , m_refreshingThemeList(false)
+ , m_ui(new Ui::ThemeSettings)
+{
+ m_currentTheme = ThemeEntry(creatorTheme()->fileName(), true);
+ m_ui->setupUi(widget);
+ m_ui->themeComboBox->setModel(m_themeListModel);
+}
+
+ThemeSettingsPrivate::~ThemeSettingsPrivate()
+{
+ delete m_themeListModel;
+ delete m_ui;
+}
+
+ThemeSettingsWidget::ThemeSettingsWidget(QWidget *parent) :
+ QWidget(parent)
+{
+ d = new ThemeSettingsPrivate(this);
+
+ connect(d->m_ui->themeComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ this, &ThemeSettingsWidget::themeSelected);
+ connect(d->m_ui->copyButton, &QAbstractButton::clicked, this, &ThemeSettingsWidget::copyTheme);
+ connect(d->m_ui->renameButton, &QAbstractButton::clicked, this, &ThemeSettingsWidget::renameTheme);
+ connect(d->m_ui->deleteButton, &QAbstractButton::clicked, this, &ThemeSettingsWidget::confirmDeleteTheme);
+
+ refreshThemeList();
+}
+
+ThemeSettingsWidget::~ThemeSettingsWidget()
+{
+ delete d;
+}
+
+void ThemeSettingsWidget::refreshThemeList()
+{
+ QList<ThemeEntry> themes;
+
+ QString resourcePath = Core::ICore::resourcePath();
+ QDir themeDir(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))
+ 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));
+ }
+
+ if (themes.isEmpty())
+ qWarning() << "Warning: no themes found in path:" << themeDir.path();
+
+ themeDir.setPath(customThemesPath());
+ foreach (const QString &file, themeDir.entryList()) {
+ const QString fileName = themeDir.absoluteFilePath(file);
+ if (d->m_currentTheme.fileName() == fileName)
+ selected = themes.size();
+ themes.append(ThemeEntry(fileName, false));
+ }
+
+ d->m_currentTheme = themes[selected];
+
+ d->m_refreshingThemeList = true;
+ d->m_themeListModel->setThemes(themes);
+ d->m_ui->themeComboBox->setCurrentIndex(selected);
+ 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;
+ if (index != -1) {
+ // Check whether we're switching away from a changed theme
+ if (!d->m_refreshingThemeList)
+ maybeSaveTheme();
+
+ const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
+ readOnly = entry.readOnly();
+ d->m_currentTheme = entry;
+
+ QSettings settings(entry.fileName(), QSettings::IniFormat);
+ Theme theme;
+ theme.readSettings(settings);
+ d->m_ui->editor->initFrom(&theme);
+ }
+ d->m_ui->copyButton->setEnabled(index != -1);
+ d->m_ui->deleteButton->setEnabled(!readOnly);
+ d->m_ui->renameButton->setEnabled(!readOnly);
+ d->m_ui->editor->setReadOnly(readOnly);
+}
+
+void ThemeSettingsWidget::confirmDeleteTheme()
+{
+ const int index = d->m_ui->themeComboBox->currentIndex();
+ if (index == -1)
+ return;
+
+ const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
+ if (entry.readOnly())
+ return;
+
+ QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning,
+ tr("Delete Theme"),
+ tr("Are you sure you want to delete the theme '%1' permanently?").arg(entry.name()),
+ QMessageBox::Discard | QMessageBox::Cancel,
+ d->m_ui->deleteButton->window());
+
+ // Change the text and role of the discard button
+ QPushButton *deleteButton = static_cast<QPushButton*>(messageBox->button(QMessageBox::Discard));
+ deleteButton->setText(tr("Delete"));
+ messageBox->addButton(deleteButton, QMessageBox::AcceptRole);
+ messageBox->setDefaultButton(deleteButton);
+
+ connect(deleteButton, &QAbstractButton::clicked, messageBox, &QDialog::accept);
+ connect(messageBox, &QDialog::accepted, this, &ThemeSettingsWidget::deleteTheme);
+ messageBox->setAttribute(Qt::WA_DeleteOnClose);
+ messageBox->open();
+}
+
+void ThemeSettingsWidget::deleteTheme()
+{
+ const int index = d->m_ui->themeComboBox->currentIndex();
+ QTC_ASSERT(index != -1, return);
+
+ const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
+ QTC_ASSERT(!entry.readOnly(), return);
+
+ if (QFile::remove(entry.fileName()))
+ d->m_themeListModel->removeTheme(index);
+}
+
+void ThemeSettingsWidget::copyTheme()
+{
+ QInputDialog *dialog = new QInputDialog(d->m_ui->copyButton->window());
+ dialog->setAttribute(Qt::WA_DeleteOnClose);
+ dialog->setInputMode(QInputDialog::TextInput);
+ dialog->setWindowTitle(tr("Copy Theme"));
+ dialog->setLabelText(tr("Theme name:"));
+
+ //TODO
+ //dialog->setTextValue(tr("%1 (copy)").arg(d_ptr->m_value.colorScheme().displayName()));
+
+ connect(dialog, &QInputDialog::textValueSelected, this, &ThemeSettingsWidget::copyThemeByName);
+ dialog->open();
+}
+
+void ThemeSettingsWidget::maybeSaveTheme()
+{
+ if (!d->m_ui->editor->model()->hasChanges())
+ return;
+
+ 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()),
+ QMessageBox::Discard | QMessageBox::Save,
+ d->m_ui->themeComboBox->window());
+
+ // Change the text of the discard button
+ QPushButton *discardButton = static_cast<QPushButton*>(messageBox->button(QMessageBox::Discard));
+ discardButton->setText(tr("Discard"));
+ messageBox->addButton(discardButton, QMessageBox::DestructiveRole);
+ messageBox->setDefaultButton(QMessageBox::Save);
+
+ if (messageBox->exec() == QMessageBox::Save) {
+ Theme newTheme;
+ d->m_ui->editor->model()->toTheme(&newTheme);
+ newTheme.writeSettings(d->m_currentTheme.fileName());
+ }
+}
+
+void ThemeSettingsWidget::renameTheme()
+{
+ int index = d->m_ui->themeComboBox->currentIndex();
+ if (index == -1)
+ return;
+ const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
+
+ maybeSaveTheme();
+
+ QInputDialog *dialog = new QInputDialog(d->m_ui->renameButton->window());
+ dialog->setInputMode(QInputDialog::TextInput);
+ dialog->setWindowTitle(tr("Rename Theme"));
+ dialog->setLabelText(tr("Theme name:"));
+ dialog->setTextValue(d->m_ui->editor->model()->m_name);
+ int ret = dialog->exec();
+ QString newName = dialog->textValue();
+ delete dialog;
+
+ if (ret != QDialog::Accepted || newName.isEmpty())
+ return;
+
+ // overwrite file with new name
+ Theme newTheme;
+ d->m_ui->editor->model()->toTheme(&newTheme);
+ newTheme.setName(newName);
+ newTheme.writeSettings(entry.fileName());
+
+ refreshThemeList();
+}
+
+void ThemeSettingsWidget::copyThemeByName(const QString &name)
+{
+ int index = d->m_ui->themeComboBox->currentIndex();
+ if (index == -1)
+ return;
+
+ const ThemeEntry &entry = d->m_themeListModel->themeAt(index);
+
+ QString baseFileName = QFileInfo(entry.fileName()).completeBaseName();
+ baseFileName += QLatin1String("_copy%1.creatortheme");
+ QString fileName = createThemeFileName(baseFileName);
+
+ if (fileName.isEmpty())
+ return;
+
+ // Ask about saving any existing modifactions
+ maybeSaveTheme();
+
+ Theme newTheme;
+ d->m_ui->editor->model()->toTheme(&newTheme);
+ newTheme.setName(name);
+ newTheme.writeSettings(fileName);
+
+ d->m_currentTheme = ThemeEntry(fileName, true);
+
+ refreshThemeList();
+}
+
+void ThemeSettingsWidget::apply()
+{
+ {
+ d->m_ui->editor->model()->toTheme(creatorTheme());
+ if (creatorTheme()->flag(Theme::ApplyThemePaletteGlobally))
+ QApplication::setPalette(creatorTheme()->palette(QApplication::palette()));
+ foreach (QWidget *w, QApplication::topLevelWidgets())
+ w->update();
+ }
+
+ // save definition of theme
+ if (!d->m_currentTheme.readOnly()) {
+ Theme newTheme;
+ d->m_ui->editor->model()->toTheme(&newTheme);
+ newTheme.writeSettings(d->m_currentTheme.fileName());
+ }
+
+ // save filename of selected theme in global config
+ QSettings *settings = Core::ICore::settings();
+ settings->setValue(QLatin1String(Core::Constants::SETTINGS_THEME), d->m_currentTheme.fileName());
+}
+
+} // namespace Internal
+} // namespace Core
diff --git a/src/plugins/coreplugin/themesettingswidget.h b/src/plugins/coreplugin/themesettingswidget.h
new file mode 100644
index 0000000000..8ed5dd882d
--- /dev/null
+++ b/src/plugins/coreplugin/themesettingswidget.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Thorben Kroeger <thorbenkroeger@gmail.com>.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef THEMESETTINGSWIDGET_H
+#define THEMESETTINGSWIDGET_H
+
+#include <QWidget>
+
+namespace Core {
+namespace Internal {
+
+class ThemeSettingsPrivate;
+
+class ThemeSettingsWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ThemeSettingsWidget(QWidget *parent = 0);
+ ~ThemeSettingsWidget();
+
+ static QString defaultThemeFileName(const QString &fileName = QString());
+
+ void apply();
+
+private slots:
+ void themeSelected(int index);
+ void copyTheme();
+ void renameTheme();
+ void copyThemeByName(const QString &);
+ void confirmDeleteTheme();
+ void deleteTheme();
+ void maybeSaveTheme();
+
+private:
+ void refreshThemeList();
+ ThemeSettingsPrivate *d;
+};
+
+} // namespace Internal
+} // namespace Core
+
+#endif // THEMESETTINGSWIDGET_H