aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/utils
diff options
context:
space:
mode:
authorThorben Kroeger <thorbenkroeger@gmail.com>2014-10-14 19:09:48 +0200
committerhjk <hjk121@nokiamail.com>2014-10-15 17:21:10 +0200
commit84f5585b5d958c3cdad4cce93244d43a360352c2 (patch)
treebeee12b956afd5cb86ad0cc03d73e3144a426f61 /src/libs/utils
parentfd8fcd29a1d70a10864fc5a6e5c6dc5cf1c96ecf (diff)
Implement theming for QtCreator
Adds a 'Theme' tab to the environment settings and a '-theme' command line option. A theme is a combination of colors, gradients, flags and style information. There are two themes: - 'default': preserves the current default look - 'dark': uses a more flat for many widgets, dark color theme for everything This does not use a stylesheet (too limited), but rather sets the palette via C++ and modifies drawing behavior. Overall, the look is more flat (removed some gradients and bevels). Tested on Ubuntu 14.04 using Qt 5.4 and running on a KDE Desktop (Oxygen base style). For a screenshot, see https://gist.github.com/thorbenk/5ab06bea726de0aa7473 Changes: - Introduce class Theme, defining the interface how to access theme specific settings. The class reads a .creatortheme file (INI file, via QSettings) - Define named colors in the [Palette] section (see dark.creatortheme for example usage) - Use either named colors of AARRGGBB (hex) in the [Colors] section - A file ending with .creatortheme may be supplied to the '-theme' command line option - A global Theme instance can be accessed via creatorTheme() - Query colors, gradients, icons and flags from the theme were possible (TODO: use this in more places...) - There are very many color roles. It seems better to me to describe the role clearly, and then to consolidate later in the actual theme by assigning the same color. For example, one can set the text color of the output pane button individualy. - Many elements are also drawn differently. For the dark theme, I wanted to have a flatter look. - Introduce Theme::WidgetStyle enum, for now {Original, Flat}. - The theme specifies which kind of widget style it wants. - The drawing code queries the theme's style flag and switches between the original, gradient based look and the new, flat look. - Create some custom icons which look better on dark background (wip, currently folder/file icons) - Let ManhattanStyle draw some elements for non-panelwidgets, too (open/close arrows in QTreeView, custom folder/file icons) - For the welcomescreen, pass the WelcomeTheme class. WelcomeTheme exposes theme colors as Q_PROPERTY accessible from .qml - Themes can be modified via the 'Themes' tab in the environment settings. TODO: * Unify image handling * Avoid style name references * Fix gradients Change-Id: I92c2050ab0fb327649ea1eff4adec973d2073944 Reviewed-by: Thomas Hartmann <Thomas.Hartmann@digia.com> Reviewed-by: hjk <hjk121@nokiamail.com>
Diffstat (limited to 'src/libs/utils')
-rw-r--r--src/libs/utils/detailsbutton.cpp54
-rw-r--r--src/libs/utils/detailswidget.cpp32
-rw-r--r--src/libs/utils/outputformatter.cpp21
-rw-r--r--src/libs/utils/outputformatter.h2
-rw-r--r--src/libs/utils/theme/theme.cpp356
-rw-r--r--src/libs/utils/theme/theme.h217
-rw-r--r--src/libs/utils/theme/theme_p.cpp47
-rw-r--r--src/libs/utils/theme/theme_p.h59
-rw-r--r--src/libs/utils/theme/welcometheme.cpp87
-rw-r--r--src/libs/utils/theme/welcometheme.h87
-rw-r--r--src/libs/utils/utils-lib.pri10
-rw-r--r--src/libs/utils/utils.qbs13
12 files changed, 932 insertions, 53 deletions
diff --git a/src/libs/utils/detailsbutton.cpp b/src/libs/utils/detailsbutton.cpp
index cfbfc1044f..3e36c12cb4 100644
--- a/src/libs/utils/detailsbutton.cpp
+++ b/src/libs/utils/detailsbutton.cpp
@@ -29,8 +29,8 @@
****************************************************************************/
#include "detailsbutton.h"
-
-#include <utils/hostosinfo.h>
+#include "hostosinfo.h"
+#include "theme/theme.h"
#include <QGraphicsOpacityEffect>
#include <QGuiApplication>
@@ -122,8 +122,15 @@ void DetailsButton::paintEvent(QPaintEvent *e)
QPainter p(this);
// draw hover animation
- if (!HostOsInfo::isMacHost() && !isDown() && m_fader > 0)
- p.fillRect(rect().adjusted(1, 1, -2, -2), QColor(255, 255, 255, int(m_fader*180)));
+ if (!HostOsInfo::isMacHost() && !isDown() && m_fader > 0) {
+ QColor c = creatorTheme()->color(Theme::DetailsButtonBackgroundColorHover);
+ c.setAlpha (int(m_fader * c.alpha()));
+
+ QRect r = rect();
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault)
+ r.adjust(1, 1, -2, -2);
+ p.fillRect(r, c);
+ }
if (isChecked()) {
if (m_checkedPixmap.isNull() || m_checkedPixmap.size() / m_checkedPixmap.devicePixelRatio() != contentsRect().size())
@@ -148,10 +155,6 @@ void DetailsButton::paintEvent(QPaintEvent *e)
QPixmap DetailsButton::cacheRendering(const QSize &size, bool checked)
{
- QLinearGradient lg;
- lg.setCoordinateMode(QGradient::ObjectBoundingMode);
- lg.setFinalStop(0, 1);
-
const qreal pixelRatio = devicePixelRatio();
QPixmap pixmap(size * pixelRatio);
pixmap.setDevicePixelRatio(pixelRatio);
@@ -159,23 +162,30 @@ QPixmap DetailsButton::cacheRendering(const QSize &size, bool checked)
QPainter p(&pixmap);
p.setRenderHint(QPainter::Antialiasing, true);
p.translate(0.5, 0.5);
- p.setPen(Qt::NoPen);
- if (!checked) {
- lg.setColorAt(0, QColor(0, 0, 0, 10));
- lg.setColorAt(1, QColor(0, 0, 0, 16));
+
+ if (creatorTheme()->widgetStyle() == Theme::StyleDefault) {
+ QLinearGradient lg;
+ lg.setCoordinateMode(QGradient::ObjectBoundingMode);
+ lg.setFinalStop(0, 1);
+ if (!checked) {
+ lg.setColorAt(0, QColor(0, 0, 0, 10));
+ lg.setColorAt(1, QColor(0, 0, 0, 16));
+ } else {
+ lg.setColorAt(0, QColor(255, 255, 255, 0));
+ lg.setColorAt(1, QColor(255, 255, 255, 50));
+ }
+ p.setBrush(lg);
+ p.setPen(QColor(255,255,255,140));
+ p.drawRoundedRect(1, 1, size.width()-3, size.height()-3, 1, 1);
+ p.setPen(QPen(QColor(0, 0, 0, 40)));
+ p.drawLine(0, 1, 0, size.height() - 2);
+ if (checked)
+ p.drawLine(1, size.height() - 1, size.width() - 1, size.height() - 1);
} else {
- lg.setColorAt(0, QColor(255, 255, 255, 0));
- lg.setColorAt(1, QColor(255, 255, 255, 50));
+ p.setPen(Qt::NoPen);
+ p.drawRoundedRect(0, 0, size.width(), size.height(), 1, 1);
}
- p.setBrush(lg);
- p.setPen(QColor(255,255,255,140));
- p.drawRoundedRect(1, 1, size.width()-3, size.height()-3, 1, 1);
- p.setPen(QPen(QColor(0, 0, 0, 40)));
- p.drawLine(0, 1, 0, size.height() - 2);
- if (checked)
- p.drawLine(1, size.height() - 1, size.width() - 1, size.height() - 1);
-
p.setPen(palette().color(QPalette::Text));
QRect textRect = p.fontMetrics().boundingRect(text());
diff --git a/src/libs/utils/detailswidget.cpp b/src/libs/utils/detailswidget.cpp
index 68320d76c5..5218916cf7 100644
--- a/src/libs/utils/detailswidget.cpp
+++ b/src/libs/utils/detailswidget.cpp
@@ -31,6 +31,7 @@
#include "detailswidget.h"
#include "detailsbutton.h"
#include "hostosinfo.h"
+#include "theme/theme.h"
#include <QGridLayout>
#include <QLabel>
@@ -148,21 +149,22 @@ QPixmap DetailsWidget::createBackground(const QSize &size, int topHeight, QWidge
if (HostOsInfo::isMacHost())
p.fillRect(fullRect, qApp->palette().window().color());
else
- p.fillRect(fullRect, QColor(255, 255, 255, 40));
-
- QLinearGradient lg(topRect.topLeft(), topRect.bottomLeft());
- lg.setColorAt(0, QColor(255, 255, 255, 130));
- lg.setColorAt(1, QColor(255, 255, 255, 0));
- p.fillRect(topRect, lg);
- p.setRenderHint(QPainter::Antialiasing, true);
- p.translate(0.5, 0.5);
- p.setPen(QColor(0, 0, 0, 40));
- p.setBrush(Qt::NoBrush);
- p.drawRoundedRect(fullRect.adjusted(0, 0, -1, -1), 2, 2);
- p.setBrush(Qt::NoBrush);
- p.setPen(QColor(255,255,255,140));
- p.drawRoundedRect(fullRect.adjusted(1, 1, -2, -2), 2, 2);
- p.setPen(QPen(widget->palette().color(QPalette::Mid)));
+ p.fillRect(fullRect, creatorTheme()->color(Theme::DetailsWidgetBackgroundColor));
+
+ if (creatorTheme()->widgetStyle () == Theme::StyleDefault) {
+ QLinearGradient lg(topRect.topLeft(), topRect.bottomLeft());
+ lg.setStops(creatorTheme()->gradient(Theme::DetailsWidgetHeaderGradient));
+ p.fillRect(topRect, lg);
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.translate(0.5, 0.5);
+ p.setPen(QColor(0, 0, 0, 40));
+ p.setBrush(Qt::NoBrush);
+ p.drawRoundedRect(fullRect.adjusted(0, 0, -1, -1), 2, 2);
+ p.setBrush(Qt::NoBrush);
+ p.setPen(QColor(255,255,255,140));
+ p.drawRoundedRect(fullRect.adjusted(1, 1, -2, -2), 2, 2);
+ p.setPen(QPen(widget->palette().color(QPalette::Mid)));
+ }
return pixmap;
}
diff --git a/src/libs/utils/outputformatter.cpp b/src/libs/utils/outputformatter.cpp
index 5d952d2ed9..ca745e3f8a 100644
--- a/src/libs/utils/outputformatter.cpp
+++ b/src/libs/utils/outputformatter.cpp
@@ -28,10 +28,11 @@
**
****************************************************************************/
+#include "ansiescapecodehandler.h"
#include "outputformatter.h"
+#include "theme/theme.h"
#include <QPlainTextEdit>
-#include <utils/ansiescapecodehandler.h>
using namespace Utils;
@@ -110,12 +111,6 @@ void OutputFormatter::clearLastLine()
cursor.removeSelectedText();
}
-QColor OutputFormatter::mixColors(const QColor &a, const QColor &b)
-{
- return QColor((a.red() + 2 * b.red()) / 3, (a.green() + 2 * b.green()) / 3,
- (a.blue() + 2* b.blue()) / 3, (a.alpha() + 2 * b.alpha()) / 3);
-}
-
void OutputFormatter::initFormats()
{
if (!plainTextEdit())
@@ -127,26 +122,28 @@ void OutputFormatter::initFormats()
m_formats = new QTextCharFormat[NumberOfFormats];
+ Theme *theme = creatorTheme();
+
// NormalMessageFormat
m_formats[NormalMessageFormat].setFont(boldFont);
- m_formats[NormalMessageFormat].setForeground(mixColors(p.color(QPalette::Text), QColor(Qt::blue)));
+ m_formats[NormalMessageFormat].setForeground(theme->color(Theme::OutputFormatter_NormalMessageTextColor));
// ErrorMessageFormat
m_formats[ErrorMessageFormat].setFont(boldFont);
- m_formats[ErrorMessageFormat].setForeground(mixColors(p.color(QPalette::Text), QColor(Qt::red)));
+ m_formats[ErrorMessageFormat].setForeground(theme->color(Theme::OutputFormatter_ErrorMessageTextColor));
// StdOutFormat
m_formats[StdOutFormat].setFont(m_font);
- m_formats[StdOutFormat].setForeground(p.color(QPalette::Text));
+ m_formats[StdOutFormat].setForeground(theme->color(Theme::OutputFormatter_StdOutTextColor));
m_formats[StdOutFormatSameLine] = m_formats[StdOutFormat];
// StdErrFormat
m_formats[StdErrFormat].setFont(m_font);
- m_formats[StdErrFormat].setForeground(mixColors(p.color(QPalette::Text), QColor(Qt::red)));
+ m_formats[StdErrFormat].setForeground(theme->color(Theme::OutputFormatter_StdErrTextColor));
m_formats[StdErrFormatSameLine] = m_formats[StdErrFormat];
m_formats[DebugFormat].setFont(m_font);
- m_formats[DebugFormat].setForeground(mixColors(p.color(QPalette::Text), QColor(Qt::magenta)));
+ m_formats[DebugFormat].setForeground(theme->color(Theme::OutputFormatter_DebugTextColor));
}
void OutputFormatter::handleLink(const QString &href)
diff --git a/src/libs/utils/outputformatter.h b/src/libs/utils/outputformatter.h
index 2f29a195bf..6dba8e5f10 100644
--- a/src/libs/utils/outputformatter.h
+++ b/src/libs/utils/outputformatter.h
@@ -73,8 +73,6 @@ protected:
QTextCharFormat charFormat(OutputFormat format) const;
void append(QTextCursor &cursor, const QString &text, const QTextCharFormat &format);
- static QColor mixColors(const QColor &a, const QColor &b);
-
private:
QPlainTextEdit *m_plainTextEdit;
QTextCharFormat *m_formats;
diff --git a/src/libs/utils/theme/theme.cpp b/src/libs/utils/theme/theme.cpp
new file mode 100644
index 0000000000..97d1627115
--- /dev/null
+++ b/src/libs/utils/theme/theme.cpp
@@ -0,0 +1,356 @@
+/****************************************************************************
+**
+** 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 "theme.h"
+#include "theme_p.h"
+#include "qtcassert.h"
+
+#include <QApplication>
+#include <QFileInfo>
+#include <QMetaEnum>
+#include <QSettings>
+
+namespace Utils {
+
+static Theme *m_creatorTheme = 0;
+
+Theme *creatorTheme()
+{
+ return m_creatorTheme;
+}
+
+void setCreatorTheme(Theme *theme)
+{
+ // TODO: memory management of theme object
+ m_creatorTheme = theme;
+}
+
+Theme::Theme(QObject *parent)
+ : QObject(parent)
+ , d(new ThemePrivate)
+{
+}
+
+Theme::~Theme()
+{
+ delete d;
+}
+
+void Theme::drawIndicatorBranch(QPainter *painter, const QRect &rect, QStyle::State state) const
+{
+ Q_UNUSED(painter);
+ Q_UNUSED(rect);
+ Q_UNUSED(state);
+}
+
+Theme::WidgetStyle Theme::widgetStyle() const
+{
+ return d->widgetStyle;
+}
+
+bool Theme::flag(Theme::Flag f) const
+{
+ return d->flags[f];
+}
+
+QColor Theme::color(Theme::ColorRole role) const
+{
+ return d->colors[role].first;
+}
+
+QGradientStops Theme::gradient(Theme::GradientRole role) const
+{
+ return d->gradientStops[role];
+}
+
+QString Theme::iconOverlay(Theme::MimeType mimetype) const
+{
+ return d->iconOverlays[mimetype];
+}
+
+QString Theme::dpiSpecificImageFile(const QString &fileName) const
+{
+ return dpiSpecificImageFile(fileName, QLatin1String(""));
+}
+
+QString Theme::dpiSpecificImageFile(const QString &fileName, const QString &themePrefix) const
+{
+ // See QIcon::addFile()
+ const QFileInfo fi(fileName);
+
+ bool at2x = (qApp->devicePixelRatio() > 1.0);
+
+ const QString at2xFileName = fi.path() + QStringLiteral("/")
+ + fi.completeBaseName() + QStringLiteral("@2x.") + fi.suffix();
+ const QString themedAt2xFileName = fi.path() + QStringLiteral("/") + themePrefix
+ + fi.completeBaseName() + QStringLiteral("@2x.") + fi.suffix();
+ const QString themedFileName = fi.path() + QStringLiteral("/") + themePrefix
+ + fi.completeBaseName() + QStringLiteral(".") + fi.suffix();
+
+ if (at2x) {
+ if (QFile::exists(themedAt2xFileName))
+ return themedAt2xFileName;
+ else if (QFile::exists(themedFileName))
+ return themedFileName;
+ else if (QFile::exists(at2xFileName))
+ return at2xFileName;
+ return fileName;
+ } else {
+ if (QFile::exists(themedFileName))
+ return themedFileName;
+ return fileName;
+ }
+}
+
+QPair<QColor, QString> Theme::readNamedColor(const QString &color) const
+{
+ if (d->palette.contains(color))
+ return qMakePair(d->palette[color], color);
+
+ bool ok = true;
+ const QRgb rgba = color.toLongLong(&ok, 16);
+ if (!ok) {
+ qWarning("Color '%s' is neither a named color nor a valid color", qPrintable(color));
+ return qMakePair(Qt::black, QString());
+ }
+ return qMakePair(QColor::fromRgba(rgba), QString());
+}
+
+QString Theme::imageFile(const QString &fileName) const
+{
+ return fileName;
+}
+
+QString Theme::fileName() const
+{
+ return d->fileName;
+}
+
+void Theme::setName(const QString &name)
+{
+ d->name = name;
+}
+
+static QColor readColor(const QString &color)
+{
+ bool ok = true;
+ const QRgb rgba = color.toLongLong(&ok, 16);
+ return QColor::fromRgba(rgba);
+}
+
+static QString writeColor(const QColor &color)
+{
+ return QString::number(color.rgba(), 16);
+}
+
+// reading, writing of .creatortheme ini file ////////////////////////////////
+void Theme::writeSettings(const QString &filename) const
+{
+ QSettings settings(filename, QSettings::IniFormat);
+
+ const QMetaObject &m = *metaObject();
+ {
+ settings.setValue(QLatin1String("ThemeName"), d->name);
+ }
+ {
+ settings.beginGroup(QLatin1String("Palette"));
+ for (int i = 0, total = d->colors.size(); i < total; ++i) {
+ const QPair<QColor, QString> var = d->colors[i];
+ if (var.second.isEmpty())
+ continue;
+ settings.setValue(var.second, writeColor(var.first));
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("Colors"));
+ const QMetaEnum e = m.enumerator(m.indexOfEnumerator("ColorRole"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ const QPair<QColor, QString> var = d->colors[i];
+ if (!var.second.isEmpty())
+ settings.setValue(key, var.second); // named color
+ else
+ settings.setValue(key, writeColor(var.first));
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("Gradients"));
+ const QMetaEnum e = m.enumerator(m.indexOfEnumerator("GradientRole"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ QGradientStops stops = gradient(static_cast<Theme::GradientRole>(i));
+ settings.beginWriteArray(key);
+ int k = 0;
+ foreach (const QGradientStop stop, stops) {
+ settings.setArrayIndex(k);
+ settings.setValue(QLatin1String("pos"), stop.first);
+ settings.setValue(QLatin1String("color"), writeColor(stop.second));
+ ++k;
+ }
+ settings.endArray();
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("IconOverlay"));
+ const QMetaEnum e = m.enumerator(m.indexOfEnumerator("MimeType"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ settings.setValue(key, iconOverlay(static_cast<Theme::MimeType>(i)));
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("Flags"));
+ const QMetaEnum e = m.enumerator(m.indexOfEnumerator("Flag"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ settings.setValue(key, flag(static_cast<Theme::Flag>(i)));
+ }
+ settings.endGroup();
+ }
+
+ {
+ settings.beginGroup(QLatin1String("Style"));
+ const QMetaEnum e = m.enumerator(m.indexOfEnumerator("WidgetStyle"));
+ settings.setValue(QLatin1String("WidgetStyle"), QLatin1String(e.valueToKey(widgetStyle ())));
+ settings.endGroup();
+ }
+}
+
+void Theme::readSettings(QSettings &settings)
+{
+ d->fileName = settings.fileName();
+ const QMetaObject &m = *metaObject();
+
+ {
+ d->name = settings.value(QLatin1String("ThemeName"), QLatin1String("unnamed")).toString();
+ }
+ {
+ settings.beginGroup(QLatin1String("Palette"));
+ foreach (const QString &key, settings.allKeys()) {
+ QColor c = readColor(settings.value(key).toString());
+ d->palette[key] = c;
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("Style"));
+ QMetaEnum e = m.enumerator(m.indexOfEnumerator("WidgetStyle"));
+ QString val = settings.value(QLatin1String("WidgetStyle")).toString();
+ d->widgetStyle = static_cast<Theme::WidgetStyle>(e.keysToValue (val.toLatin1().data()));
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("Colors"));
+ QMetaEnum e = m.enumerator(m.indexOfEnumerator("ColorRole"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ QTC_ASSERT(settings.contains(key), return);;
+ d->colors[i] = readNamedColor(settings.value(key).toString());
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("Gradients"));
+ QMetaEnum e = m.enumerator(m.indexOfEnumerator("GradientRole"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ QGradientStops stops;
+ int size = settings.beginReadArray(key);
+ for (int j = 0; j < size; ++j) {
+ settings.setArrayIndex(j);
+ QTC_ASSERT(settings.contains(QLatin1String("pos")), return);;
+ double pos = settings.value(QLatin1String("pos")).toDouble();
+ QTC_ASSERT(settings.contains(QLatin1String("color")), return);;
+ QColor c = readColor(settings.value(QLatin1String("color")).toString());
+ stops.append(qMakePair(pos, c));
+ }
+ settings.endArray();
+ d->gradientStops[i] = stops;
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("IconOverlay"));
+ QMetaEnum e = m.enumerator(m.indexOfEnumerator("MimeType"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ QTC_ASSERT(settings.contains(key), return);;
+ d->iconOverlays[i] = settings.value(key).toString();
+ }
+ settings.endGroup();
+ }
+ {
+ settings.beginGroup(QLatin1String("Flags"));
+ QMetaEnum e = m.enumerator(m.indexOfEnumerator("Flag"));
+ for (int i = 0, total = e.keyCount(); i < total; ++i) {
+ const QString key = QLatin1String(e.key(i));
+ QTC_ASSERT(settings.contains(key), return);;
+ d->flags[i] = settings.value(key).toBool();
+ }
+ settings.endGroup();
+ }
+}
+
+QIcon Theme::standardIcon(QStyle::StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const
+{
+ Q_UNUSED(standardPixmap);
+ Q_UNUSED(opt);
+ Q_UNUSED(widget);
+ return QIcon();
+}
+
+QPalette Theme::palette(const QPalette &base) const
+{
+ if (!flag(DerivePaletteFromTheme))
+ return base;
+
+ // FIXME: introduce some more color roles for this
+
+ QPalette pal = base;
+ pal.setColor(QPalette::All, QPalette::Window, color(Theme::BackgroundColorNormal));
+ pal.setBrush(QPalette::All, QPalette::WindowText, color(Theme::TextColorNormal));
+ pal.setColor(QPalette::All, QPalette::Base, color(Theme::BackgroundColorNormal));
+ pal.setColor(QPalette::All, QPalette::AlternateBase, color(Theme::BackgroundColorAlternate));
+ pal.setColor(QPalette::All, QPalette::Button, color(Theme::BackgroundColorDark));
+ pal.setColor(QPalette::All, QPalette::BrightText, Qt::red);
+ pal.setBrush(QPalette::All, QPalette::Text, color(Theme::TextColorNormal));
+ pal.setBrush(QPalette::All, QPalette::ButtonText, color(Theme::TextColorNormal));
+ pal.setBrush(QPalette::All, QPalette::ToolTipBase, color(Theme::BackgroundColorSelected));
+ pal.setColor(QPalette::Highlight, color(Theme::BackgroundColorSelected));
+ pal.setColor(QPalette::HighlightedText, Qt::white);
+ pal.setColor(QPalette::ToolTipText, color(Theme::TextColorNormal));
+ return pal;
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/theme/theme.h b/src/libs/utils/theme/theme.h
new file mode 100644
index 0000000000..4a55bdc409
--- /dev/null
+++ b/src/libs/utils/theme/theme.h
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** 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 THEME_H
+#define THEME_H
+
+#include "../utils_global.h"
+
+#include <QStyle>
+#include <QFlags>
+
+QT_FORWARD_DECLARE_CLASS(QSettings)
+
+namespace Utils {
+
+class ThemePrivate;
+
+class QTCREATOR_UTILS_EXPORT Theme : public QObject
+{
+ Q_OBJECT
+
+ Q_ENUMS(ColorRole)
+ Q_ENUMS(GradientRole)
+ Q_ENUMS(MimeType)
+ Q_ENUMS(Flag)
+ Q_ENUMS(WidgetStyle)
+
+public:
+ Theme(QObject *parent = 0);
+ ~Theme();
+
+ enum ColorRole {
+ BackgroundColorAlternate,
+ BackgroundColorDark,
+ BackgroundColorHover,
+ BackgroundColorNormal,
+ BackgroundColorSelected,
+ BadgeLabelBackgroundColorChecked,
+ BadgeLabelBackgroundColorUnchecked,
+ BadgeLabelTextColorChecked,
+ BadgeLabelTextColorUnchecked,
+ CanceledSearchTextColor,
+ ComboBoxArrowColor,
+ ComboBoxArrowColorDisabled,
+ ComboBoxTextColor,
+ DetailsWidgetBackgroundColor,
+ DetailsButtonBackgroundColorHover,
+ DockWidgetResizeHandleColor,
+ DoubleTabWidget1stEmptyAreaBackgroundColor,
+ DoubleTabWidget1stSeparatorColor,
+ DoubleTabWidget2ndSeparatorColor,
+ DoubleTabWidget1stTabBackgroundColor,
+ DoubleTabWidget2ndTabBackgroundColor,
+ DoubleTabWidget1stTabActiveTextColor,
+ DoubleTabWidget1stTabInactiveTextColor,
+ DoubleTabWidget2ndTabActiveTextColor,
+ DoubleTabWidget2ndTabInactiveTextColor,
+ EditorPlaceholderColor,
+ FancyTabBarBackgroundColor,
+ FancyTabWidgetEnabledSelectedTextColor,
+ FancyTabWidgetEnabledUnselectedTextColor,
+ FancyTabWidgetDisabledSelectedTextColor,
+ FancyTabWidgetDisabledUnselectedTextColor,
+ FancyToolButtonHoverColor,
+ FancyToolButtonSelectedColor,
+ FutureProgressBackgroundColor,
+ MenuBarEmptyAreaBackgroundColor,
+ MenuBarItemBackgroundColor,
+ MenuBarItemTextColorDisabled,
+ MenuBarItemTextColorNormal,
+ MiniProjectTargetSelectorBackgroundColor,
+ MiniProjectTargetSelectorBorderColor,
+ MiniProjectTargetSelectorSummaryBackgroundColor,
+ MiniProjectTargetSelectorTextColor,
+ OutputPaneButtonFlashColor,
+ OutputPaneToggleButtonTextColorChecked,
+ OutputPaneToggleButtonTextColorUnchecked,
+ PanelButtonToolBackgroundColorHover,
+ PanelTextColor,
+ PanelsWidgetSeparatorLineColor,
+ PanelStatusBarBackgroundColor,
+ ProgressBarTitleColor,
+ ProgressBarColorError,
+ ProgressBarColorFinished,
+ ProgressBarColorNormal,
+ SearchResultWidgetBackgroundColor,
+ SearchResultWidgetTextColor,
+ TextColorDisabled,
+ TextColorHighlight,
+ TextColorNormal,
+ TodoItemTextColor,
+ ToggleButtonBackgroundColor,
+ ToolBarBackgroundColor,
+ TreeViewArrowColorNormal,
+ TreeViewArrowColorSelected,
+
+ OutputFormatter_NormalMessageTextColor,
+ OutputFormatter_ErrorMessageTextColor,
+ OutputFormatter_StdOutTextColor,
+ OutputFormatter_StdErrTextColor,
+ OutputFormatter_DebugTextColor,
+
+ QtOutputFormatter_LinkTextColor,
+
+ /* Welcome Plugin */
+
+ Welcome_TextColorNormal,
+ Welcome_TextColorHeading, // #535353 // Sessions, Recent Projects
+ Welcome_BackgroundColorNormal, // #ffffff
+ Welcome_DividerColor, // #737373
+ Welcome_Button_BorderColor,
+ Welcome_Button_TextColorNormal,
+ Welcome_Button_TextColorPressed,
+ Welcome_Link_TextColorNormal,
+ Welcome_Link_TextColorActive,
+ Welcome_Link_BackgroundColor,
+ Welcome_Caption_TextColorNormal,
+ Welcome_SideBar_BackgroundColor,
+
+ Welcome_ProjectItem_TextColorFilepath,
+ Welcome_ProjectItem_BackgroundColorHover,
+
+ Welcome_SessionItem_BackgroundColorNormal,
+ Welcome_SessionItem_BackgroundColorHover,
+ Welcome_SessionItemExpanded_BackgroundColor
+ };
+
+ enum GradientRole {
+ DetailsWidgetHeaderGradient,
+ Welcome_Button_GradientNormal,
+ Welcome_Button_GradientPressed
+ };
+
+ enum MimeType {
+ CppSourceMimetype,
+ CSourceMimetype,
+ CppHeaderMimetype,
+ ProMimetype,
+ PriMimetype,
+ PrfMimetype
+ };
+
+ enum Flag {
+ DrawTargetSelectorBottom,
+ DrawSearchResultWidgetFrame,
+ DrawProgressBarSunken,
+ DrawIndicatorBranch,
+ ComboBoxDrawTextShadow,
+ DerivePaletteFromTheme
+ };
+
+ enum WidgetStyle {
+ StyleDefault,
+ StyleFlat
+ };
+
+ WidgetStyle widgetStyle() const;
+ bool flag(Flag f) const;
+ QColor color(ColorRole role) const;
+ QGradientStops gradient(GradientRole role) const;
+ QString iconOverlay(MimeType mimetype) const;
+ QPalette palette(const QPalette &base) const;
+ QString dpiSpecificImageFile(const QString &fileName) const;
+ void drawIndicatorBranch(QPainter *painter, const QRect &rect, QStyle::State state) const;
+ QIcon standardIcon(QStyle::StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const;
+ QString imageFile(const QString &fileName) const;
+
+ QString fileName() const;
+ void setName(const QString &name);
+
+ void writeSettings(const QString &filename) const;
+ void readSettings(QSettings &settings);
+ ThemePrivate *d;
+
+signals:
+ void changed();
+
+protected:
+ QString dpiSpecificImageFile(const QString &fileName, const QString &themePrefix) const;
+
+private:
+ QPair<QColor, QString> readNamedColor(const QString &color) const;
+};
+
+QTCREATOR_UTILS_EXPORT Theme *creatorTheme();
+QTCREATOR_UTILS_EXPORT void setCreatorTheme(Theme *theme);
+
+} // namespace Utils
+
+#endif // THEME_H
diff --git a/src/libs/utils/theme/theme_p.cpp b/src/libs/utils/theme/theme_p.cpp
new file mode 100644
index 0000000000..05c7916722
--- /dev/null
+++ b/src/libs/utils/theme/theme_p.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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 "theme_p.h"
+
+#include <QMetaEnum>
+
+namespace Utils {
+
+ThemePrivate::ThemePrivate()
+ : widgetStyle(Theme::StyleDefault)
+{
+ const QMetaObject &m = Theme::staticMetaObject;
+ colors.resize (m.enumerator(m.indexOfEnumerator("ColorRole")).keyCount());
+ gradientStops.resize (m.enumerator(m.indexOfEnumerator("GradientRole")).keyCount());
+ iconOverlays.resize (m.enumerator(m.indexOfEnumerator("MimeType")).keyCount());
+ flags.resize (m.enumerator(m.indexOfEnumerator("Flag")).keyCount());
+}
+
+} // namespace Utils
diff --git a/src/libs/utils/theme/theme_p.h b/src/libs/utils/theme/theme_p.h
new file mode 100644
index 0000000000..d507becafc
--- /dev/null
+++ b/src/libs/utils/theme/theme_p.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** 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 THEME_P_H
+#define THEME_P_H
+
+#include "theme.h"
+#include "../utils_global.h"
+
+#include <QColor>
+#include <QMap>
+
+namespace Utils {
+
+class QTCREATOR_UTILS_EXPORT ThemePrivate
+{
+public:
+ ThemePrivate();
+
+ QString fileName;
+ QString name;
+ QVector<QPair<QColor, QString> > colors;
+ QVector<QString> iconOverlays;
+ QVector<QGradientStops> gradientStops;
+ QVector<bool> flags;
+ Theme::WidgetStyle widgetStyle;
+ QMap<QString, QColor> palette;
+};
+
+} // namespace Utils
+
+#endif // THEME_P_H
diff --git a/src/libs/utils/theme/welcometheme.cpp b/src/libs/utils/theme/welcometheme.cpp
new file mode 100644
index 0000000000..e8581a7d7d
--- /dev/null
+++ b/src/libs/utils/theme/welcometheme.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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 "welcometheme.h"
+
+#include "theme.h"
+
+using namespace Utils;
+
+#define IMPL_COLOR_PROPERTY(propName, enumName) \
+ QColor WelcomeTheme::propName () const { \
+ return creatorTheme()->color(Theme::enumName); \
+ }
+
+#define GRADIENT(x) \
+ QGradient grad; \
+ grad.setStops(creatorTheme()->gradient(Theme::x)); \
+ return grad;
+
+WelcomeTheme::WelcomeTheme(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QString WelcomeTheme::widgetStyle() const
+{
+ switch (creatorTheme()->widgetStyle()) {
+ case Theme::StyleDefault:
+ return QLatin1String("default");
+ case Theme::StyleFlat:
+ return QLatin1String("flat");
+ }
+ return QString::null;
+}
+
+void WelcomeTheme::notifyThemeChanged()
+{
+ emit themeChanged();
+}
+
+IMPL_COLOR_PROPERTY(textColorNormal , Welcome_TextColorNormal )
+IMPL_COLOR_PROPERTY(textColorHeading , Welcome_TextColorHeading )
+IMPL_COLOR_PROPERTY(backgroundColorNormal , Welcome_BackgroundColorNormal )
+IMPL_COLOR_PROPERTY(dividerColor , Welcome_DividerColor )
+IMPL_COLOR_PROPERTY(button_BorderColor , Welcome_Button_BorderColor )
+IMPL_COLOR_PROPERTY(button_TextColorNormal , Welcome_Button_TextColorNormal )
+IMPL_COLOR_PROPERTY(button_TextColorPressed, Welcome_Button_TextColorPressed)
+IMPL_COLOR_PROPERTY(link_TextColorNormal , Welcome_Link_TextColorNormal )
+IMPL_COLOR_PROPERTY(link_TextColorActive , Welcome_Link_TextColorActive )
+IMPL_COLOR_PROPERTY(link_BackgroundColor , Welcome_Link_BackgroundColor )
+IMPL_COLOR_PROPERTY(caption_TextColorNormal, Welcome_Caption_TextColorNormal)
+IMPL_COLOR_PROPERTY(sideBar_BackgroundColor, Welcome_SideBar_BackgroundColor)
+IMPL_COLOR_PROPERTY(projectItem_TextColorFilepath, Welcome_ProjectItem_TextColorFilepath)
+IMPL_COLOR_PROPERTY(projectItem_BackgroundColorHover, Welcome_ProjectItem_BackgroundColorHover)
+IMPL_COLOR_PROPERTY(sessionItem_BackgroundColorNormal, Welcome_SessionItem_BackgroundColorNormal)
+IMPL_COLOR_PROPERTY(sessionItemExpanded_BackgroundColor, Welcome_SessionItemExpanded_BackgroundColor)
+IMPL_COLOR_PROPERTY(sessionItem_BackgroundColorHover, Welcome_SessionItem_BackgroundColorHover)
+
+QGradient WelcomeTheme::button_GradientNormal () const { GRADIENT(Welcome_Button_GradientNormal); }
+QGradient WelcomeTheme::button_GradientPressed () const { GRADIENT(Welcome_Button_GradientPressed); }
diff --git a/src/libs/utils/theme/welcometheme.h b/src/libs/utils/theme/welcometheme.h
new file mode 100644
index 0000000000..ec9f36c844
--- /dev/null
+++ b/src/libs/utils/theme/welcometheme.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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 WELCOMETHEME_H
+#define WELCOMETHEME_H
+
+#include "../utils_global.h"
+
+#include <QStyle>
+
+#define DECLARE_COLOR_PROPERTY(propName) \
+ Q_PROPERTY(QColor propName READ propName NOTIFY themeChanged) \
+ QColor propName () const;
+
+/*!
+ * Expose theme properties to QML (for welcomeplugin)
+ */
+class QTCREATOR_UTILS_EXPORT WelcomeTheme : public QObject
+{
+ Q_OBJECT
+
+public:
+ WelcomeTheme(QObject *parent);
+
+ DECLARE_COLOR_PROPERTY(textColorNormal)
+ DECLARE_COLOR_PROPERTY(textColorHeading)
+ DECLARE_COLOR_PROPERTY(backgroundColorNormal)
+ DECLARE_COLOR_PROPERTY(dividerColor)
+ DECLARE_COLOR_PROPERTY(button_BorderColor)
+ DECLARE_COLOR_PROPERTY(button_TextColorNormal)
+ DECLARE_COLOR_PROPERTY(button_TextColorPressed)
+ DECLARE_COLOR_PROPERTY(link_TextColorNormal)
+ DECLARE_COLOR_PROPERTY(link_TextColorActive)
+ DECLARE_COLOR_PROPERTY(link_BackgroundColor)
+ DECLARE_COLOR_PROPERTY(sideBar_BackgroundColor)
+ DECLARE_COLOR_PROPERTY(caption_TextColorNormal)
+ DECLARE_COLOR_PROPERTY(projectItem_TextColorFilepath)
+ DECLARE_COLOR_PROPERTY(projectItem_BackgroundColorHover)
+ DECLARE_COLOR_PROPERTY(sessionItem_BackgroundColorNormal)
+ DECLARE_COLOR_PROPERTY(sessionItemExpanded_BackgroundColor)
+ DECLARE_COLOR_PROPERTY(sessionItem_BackgroundColorHover)
+
+ Q_PROPERTY(QGradient button_GradientNormal READ button_GradientNormal NOTIFY themeChanged)
+ Q_PROPERTY(QGradient button_GradientPressed READ button_GradientPressed NOTIFY themeChanged)
+
+ Q_PROPERTY(QString widgetStyle READ widgetStyle CONSTANT)
+
+ QString widgetStyle() const;
+
+ QGradient button_GradientNormal () const;
+ QGradient button_GradientPressed () const;
+
+public slots:
+ void notifyThemeChanged();
+
+signals:
+ void themeChanged();
+};
+
+#endif // WELCOMETHEME_H
diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri
index 8b0257ba6e..087bcba89e 100644
--- a/src/libs/utils/utils-lib.pri
+++ b/src/libs/utils/utils-lib.pri
@@ -92,7 +92,10 @@ SOURCES += $$PWD/environment.cpp \
$$PWD/treemodel.cpp \
$$PWD/treeviewcombobox.cpp \
$$PWD/proxycredentialsdialog.cpp \
- $$PWD/macroexpander.cpp
+ $$PWD/macroexpander.cpp \
+ $$PWD/theme/theme.cpp \
+ $$PWD/theme/theme_p.cpp \
+ $$PWD/theme/welcometheme.cpp
win32:SOURCES += $$PWD/consoleprocess_win.cpp
else:SOURCES += $$PWD/consoleprocess_unix.cpp
@@ -189,7 +192,10 @@ HEADERS += \
$$PWD/algorithm.h \
$$PWD/QtConcurrentTools \
$$PWD/proxycredentialsdialog.h \
- $$PWD/macroexpander.h
+ $$PWD/macroexpander.h \
+ $$PWD/theme/theme.h \
+ $$PWD/theme/theme_p.h \
+ $$PWD/theme/welcometheme.h
FORMS += $$PWD/filewizardpage.ui \
$$PWD/projectintropage.ui \
diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs
index a665cfc3ba..a5a92af87a 100644
--- a/src/libs/utils/utils.qbs
+++ b/src/libs/utils/utils.qbs
@@ -205,6 +205,19 @@ QtcLibrary {
]
Group {
+ name: "Theme"
+ prefix: "theme/"
+ files: [
+ "theme.cpp",
+ "theme.h",
+ "theme_p.cpp",
+ "theme_p.h",
+ "welcometheme.cpp",
+ "welcometheme.h",
+ ]
+ }
+
+ Group {
name: "Tooltip"
prefix: "tooltip/"
files: [