2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
2022-12-21 10:12:09 +01:00
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
#include "manhattanstyle.h"
|
2008-12-02 14:09:21 +01:00
|
|
|
|
2023-04-21 14:45:54 +02:00
|
|
|
#include "generalsettings.h"
|
|
|
|
|
|
2015-05-21 16:58:21 +02:00
|
|
|
#include <utils/algorithm.h>
|
2023-03-24 15:24:58 +02:00
|
|
|
#include <utils/fancymainwindow.h>
|
2013-03-14 10:44:46 +01:00
|
|
|
#include <utils/hostosinfo.h>
|
2023-05-09 13:20:04 +02:00
|
|
|
#include <utils/itemviews.h>
|
2023-03-24 15:24:58 +02:00
|
|
|
#include <utils/qtcassert.h>
|
|
|
|
|
#include <utils/styleanimator.h>
|
2009-07-15 12:38:45 +02:00
|
|
|
#include <utils/stylehelper.h>
|
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>
2014-10-14 19:09:48 +02:00
|
|
|
#include <utils/theme/theme.h>
|
2016-08-03 17:55:54 +02:00
|
|
|
#include <utils/utilsicons.h>
|
2010-03-22 13:20:31 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QApplication>
|
2021-09-28 10:01:51 +02:00
|
|
|
#include <QCheckBox>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QComboBox>
|
|
|
|
|
#include <QDockWidget>
|
2015-05-07 16:17:10 +02:00
|
|
|
#include <QFormLayout>
|
2020-07-28 11:58:23 +02:00
|
|
|
#include <QGroupBox>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QLabel>
|
|
|
|
|
#include <QLineEdit>
|
2012-10-19 13:13:57 +02:00
|
|
|
#include <QMenuBar>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QPainter>
|
2020-03-12 09:26:58 +01:00
|
|
|
#include <QPainterPath>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QPixmap>
|
2023-01-20 14:06:19 +02:00
|
|
|
#include <QPixmapCache>
|
2023-04-24 09:41:09 +02:00
|
|
|
#include <QScrollArea>
|
2021-09-28 09:42:37 +09:00
|
|
|
#include <QSpinBox>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QStatusBar>
|
|
|
|
|
#include <QStyleFactory>
|
|
|
|
|
#include <QStyleOption>
|
|
|
|
|
#include <QToolBar>
|
|
|
|
|
#include <QToolButton>
|
2008-12-09 15:25:01 +01:00
|
|
|
|
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>
2014-10-14 19:09:48 +02:00
|
|
|
using namespace Utils;
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
// We define a currently unused state for indicating animations
|
2012-05-21 09:19:16 +02:00
|
|
|
const QStyle::State State_Animating = QStyle::State(0x00000040);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
// Because designer needs to disable this for widget previews
|
|
|
|
|
// we have a custom property that is inherited
|
|
|
|
|
bool styleEnabled(const QWidget *widget)
|
|
|
|
|
{
|
|
|
|
|
const QWidget *p = widget;
|
|
|
|
|
while (p) {
|
|
|
|
|
if (p->property("_q_custom_style_disabled").toBool())
|
|
|
|
|
return false;
|
2014-05-19 18:29:38 +03:00
|
|
|
p = p->parentWidget();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-12 00:28:19 +02:00
|
|
|
static bool isInUnstyledDialogOrPopup(const QWidget *widget)
|
2021-10-07 11:57:29 +02:00
|
|
|
{
|
2021-10-12 00:28:19 +02:00
|
|
|
// Do not style contents of dialogs or popups without "panelwidget" property
|
|
|
|
|
const QWidget *window = widget->window();
|
2023-05-09 13:20:04 +02:00
|
|
|
if (window->property(StyleHelper::C_PANEL_WIDGET).toBool())
|
2021-10-12 00:28:19 +02:00
|
|
|
return false;
|
|
|
|
|
const Qt::WindowType windowType = window->windowType();
|
2021-10-07 11:57:29 +02:00
|
|
|
return (windowType == Qt::Dialog || windowType == Qt::Popup);
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
// Consider making this a QStyle state
|
|
|
|
|
bool panelWidget(const QWidget *widget)
|
|
|
|
|
{
|
2009-12-11 12:41:13 +01:00
|
|
|
if (!widget)
|
|
|
|
|
return false;
|
|
|
|
|
|
2021-10-12 00:28:19 +02:00
|
|
|
if (isInUnstyledDialogOrPopup(widget))
|
2009-12-11 12:41:13 +01:00
|
|
|
return false;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-02-03 23:48:19 +02:00
|
|
|
if (qobject_cast<const FancyMainWindow *>(widget))
|
2010-03-22 13:20:31 +01:00
|
|
|
return true;
|
|
|
|
|
|
2010-03-23 13:51:32 +01:00
|
|
|
if (qobject_cast<const QTabBar *>(widget))
|
|
|
|
|
return styleEnabled(widget);
|
|
|
|
|
|
2023-05-09 13:20:04 +02:00
|
|
|
if (qobject_cast<const QScrollArea *>(widget)) // See DebuggerMainWindowPrivate
|
|
|
|
|
return widget->property(StyleHelper::C_PANEL_WIDGET_SINGLE_ROW).toBool();
|
2023-04-24 09:41:09 +02:00
|
|
|
|
2009-12-11 12:41:13 +01:00
|
|
|
const QWidget *p = widget;
|
2008-12-02 12:01:29 +01:00
|
|
|
while (p) {
|
2009-12-11 17:16:17 +01:00
|
|
|
if (qobject_cast<const QToolBar *>(p) ||
|
|
|
|
|
qobject_cast<const QStatusBar *>(p) ||
|
2012-10-19 13:13:57 +02:00
|
|
|
qobject_cast<const QMenuBar *>(p) ||
|
2023-05-09 13:20:04 +02:00
|
|
|
p->property(StyleHelper::C_PANEL_WIDGET).toBool())
|
2009-12-11 17:16:17 +01:00
|
|
|
return styleEnabled(widget);
|
2008-12-02 12:01:29 +01:00
|
|
|
p = p->parentWidget();
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-20 14:06:19 +02:00
|
|
|
// Consider making this a QStyle state
|
|
|
|
|
static bool isQmlEditorMenu(const QWidget *widget)
|
|
|
|
|
{
|
|
|
|
|
const QMenu *menu = qobject_cast<const QMenu *> (widget);
|
|
|
|
|
if (!menu)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const QWidget *p = widget;
|
|
|
|
|
while (p) {
|
|
|
|
|
if (p->property("qmlEditorMenu").toBool())
|
|
|
|
|
return styleEnabled(widget);
|
|
|
|
|
p = p->parentWidget();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-19 09:54:29 +01:00
|
|
|
// Consider making this a QStyle state
|
|
|
|
|
bool lightColored(const QWidget *widget)
|
|
|
|
|
{
|
|
|
|
|
if (!widget)
|
|
|
|
|
return false;
|
|
|
|
|
|
2021-10-12 00:28:19 +02:00
|
|
|
if (isInUnstyledDialogOrPopup(widget))
|
2010-02-19 09:54:29 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const QWidget *p = widget;
|
|
|
|
|
while (p) {
|
2023-05-09 13:20:04 +02:00
|
|
|
if (p->property(StyleHelper::C_LIGHT_COLORED).toBool())
|
2010-02-19 09:54:29 +01:00
|
|
|
return true;
|
|
|
|
|
p = p->parentWidget();
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-28 11:58:23 +02:00
|
|
|
static bool isDarkFusionStyle(const QStyle *style)
|
|
|
|
|
{
|
|
|
|
|
return creatorTheme()->flag(Theme::DarkUserInterface)
|
|
|
|
|
&& strcmp(style->metaObject()->className(), "QFusionStyle") == 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-20 14:06:19 +02:00
|
|
|
QColor qmlEditorTextColor(bool enabled,
|
|
|
|
|
bool active,
|
|
|
|
|
bool checked)
|
|
|
|
|
{
|
|
|
|
|
Theme::Color themePenColorId = enabled ? (active
|
|
|
|
|
? (checked ? Theme::DSsubPanelBackground
|
|
|
|
|
: Theme::DSpanelBackground)
|
|
|
|
|
: Theme::DStextColor)
|
|
|
|
|
: Theme::DStextColorDisabled;
|
|
|
|
|
|
|
|
|
|
return creatorTheme()->color(themePenColorId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QPixmap getDeletePixmap(bool enabled,
|
|
|
|
|
bool active,
|
|
|
|
|
const QSize &sizeLimit)
|
|
|
|
|
{
|
|
|
|
|
using Utils::Theme;
|
|
|
|
|
using Utils::creatorTheme;
|
2023-05-11 13:15:55 +02:00
|
|
|
using namespace Utils::StyleHelper;
|
2023-01-20 14:06:19 +02:00
|
|
|
|
|
|
|
|
const double xRatio = 19;
|
|
|
|
|
const double yRatio = 9;
|
|
|
|
|
double sizeConst = std::min(xRatio * sizeLimit.height(), yRatio * sizeLimit.width());
|
|
|
|
|
sizeConst = std::max(xRatio, sizeConst);
|
|
|
|
|
|
|
|
|
|
const int height = sizeConst/xRatio;
|
|
|
|
|
const int width = sizeConst/yRatio;
|
|
|
|
|
QPixmap retval(width, height);
|
|
|
|
|
QPainter p(&retval);
|
|
|
|
|
const qreal devicePixelRatio = p.device()->devicePixelRatio();
|
|
|
|
|
|
|
|
|
|
QPixmap pixmap;
|
|
|
|
|
QString pixmapName = QLatin1String("StyleHelper::drawDelete")
|
|
|
|
|
+ "-" + QString::number(sizeConst)
|
|
|
|
|
+ "-" + QString::number(enabled)
|
|
|
|
|
+ "-" + QString::number(active)
|
|
|
|
|
+ "-" + QString::number(devicePixelRatio);
|
|
|
|
|
|
|
|
|
|
if (!QPixmapCache::find(pixmapName, &pixmap)) {
|
|
|
|
|
QImage image(width * devicePixelRatio, height * devicePixelRatio, QImage::Format_ARGB32_Premultiplied);
|
|
|
|
|
image.fill(Qt::transparent);
|
|
|
|
|
QPainter painter(&image);
|
|
|
|
|
|
|
|
|
|
auto drawDelete = [&painter, yRatio](const QRect &rect, const QColor &color) -> void
|
|
|
|
|
{
|
|
|
|
|
static const QStyle* const style = QApplication::style();
|
|
|
|
|
if (!style)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
const int height = rect.height();
|
|
|
|
|
const int width = rect.width();
|
|
|
|
|
const int insideW = height / 2;
|
|
|
|
|
const int penWidth = std::ceil(height / yRatio);
|
|
|
|
|
const int pixelGuard = penWidth / 2;
|
|
|
|
|
const QRect xRect = {insideW + (4 * penWidth),
|
|
|
|
|
2 * penWidth,
|
|
|
|
|
4 * penWidth,
|
|
|
|
|
5 * penWidth};
|
|
|
|
|
|
|
|
|
|
// Workaround for QTCREATORBUG-28470
|
|
|
|
|
painter.save();
|
|
|
|
|
painter.setOpacity(color.alphaF());
|
|
|
|
|
|
|
|
|
|
QPen pen(color, penWidth);
|
|
|
|
|
pen.setJoinStyle(Qt::MiterJoin);
|
|
|
|
|
painter.setPen(pen);
|
|
|
|
|
|
|
|
|
|
QPainterPath pp(QPointF(pixelGuard, insideW));
|
|
|
|
|
pp.lineTo(insideW, pixelGuard);
|
|
|
|
|
pp.lineTo(width - pixelGuard, pixelGuard);
|
|
|
|
|
pp.lineTo(width - pixelGuard, height - pixelGuard);
|
|
|
|
|
pp.lineTo(insideW, height - pixelGuard);
|
|
|
|
|
pp.lineTo(pixelGuard, insideW);
|
|
|
|
|
|
|
|
|
|
painter.drawPath(pp);
|
|
|
|
|
|
|
|
|
|
// drawing X
|
|
|
|
|
painter.setPen(QPen(color, 1));
|
|
|
|
|
QPoint stepOver(penWidth, 0);
|
|
|
|
|
|
|
|
|
|
pp.clear();
|
|
|
|
|
pp.moveTo(xRect.topLeft());
|
|
|
|
|
pp.lineTo(xRect.topLeft() + stepOver);
|
|
|
|
|
pp.lineTo(xRect.bottomRight());
|
|
|
|
|
pp.lineTo(xRect.bottomRight() - stepOver);
|
|
|
|
|
pp.lineTo(xRect.topLeft());
|
|
|
|
|
painter.fillPath(pp, QBrush(color));
|
|
|
|
|
|
|
|
|
|
pp.clear();
|
|
|
|
|
pp.moveTo(xRect.topRight());
|
|
|
|
|
pp.lineTo(xRect.topRight() - stepOver);
|
|
|
|
|
pp.lineTo(xRect.bottomLeft());
|
|
|
|
|
pp.lineTo(xRect.bottomLeft() + stepOver);
|
|
|
|
|
pp.lineTo(xRect.topRight());
|
|
|
|
|
painter.fillPath(pp, QBrush(color));
|
|
|
|
|
|
|
|
|
|
painter.restore();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (enabled && creatorTheme()->flag(Theme::ToolBarIconShadow))
|
|
|
|
|
drawDelete(image.rect().translated(0, devicePixelRatio), StyleHelper::toolBarDropShadowColor());
|
|
|
|
|
|
|
|
|
|
drawDelete(image.rect(), qmlEditorTextColor(enabled, active, false));
|
|
|
|
|
|
|
|
|
|
painter.end();
|
|
|
|
|
pixmap = QPixmap::fromImage(image);
|
|
|
|
|
pixmap.setDevicePixelRatio(devicePixelRatio);
|
|
|
|
|
QPixmapCache::insert(pixmapName, pixmap);
|
|
|
|
|
}
|
|
|
|
|
return pixmap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct ManhattanShortcut {
|
|
|
|
|
ManhattanShortcut(const QStyleOptionMenuItem *option,
|
|
|
|
|
const QString &shortcutText)
|
|
|
|
|
: shortcutText(shortcutText)
|
|
|
|
|
, enabled(option->state & QStyle::State_Enabled)
|
|
|
|
|
, active(option->state & QStyle::State_Selected)
|
|
|
|
|
, font(option->font)
|
|
|
|
|
, fm(font)
|
|
|
|
|
, defaultHeight(fm.height())
|
|
|
|
|
, palette(option->palette)
|
|
|
|
|
, spaceConst(fm.boundingRect(".").width())
|
|
|
|
|
{
|
|
|
|
|
reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QSize getSize()
|
|
|
|
|
{
|
|
|
|
|
if (isFirstParticle)
|
|
|
|
|
calcResult();
|
|
|
|
|
return _size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QPixmap getPixmap()
|
|
|
|
|
{
|
|
|
|
|
if (!isFirstParticle && !_pixmap.isNull())
|
|
|
|
|
return _pixmap;
|
|
|
|
|
|
|
|
|
|
_pixmap = QPixmap(getSize());
|
|
|
|
|
_pixmap.fill(Qt::transparent);
|
|
|
|
|
QPainter painter(&_pixmap);
|
|
|
|
|
painter.setFont(font);
|
|
|
|
|
QPen pPen = painter.pen();
|
|
|
|
|
pPen.setColor(qmlEditorTextColor(enabled, active, false));
|
|
|
|
|
painter.setPen(pPen);
|
|
|
|
|
calcResult(&painter);
|
|
|
|
|
painter.end();
|
|
|
|
|
|
|
|
|
|
return _pixmap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void applySize(const QSize &itemSize) {
|
|
|
|
|
width += itemSize.width();
|
|
|
|
|
height = std::max(height, itemSize.height());
|
|
|
|
|
if (isFirstParticle)
|
|
|
|
|
isFirstParticle = false;
|
|
|
|
|
else
|
|
|
|
|
width += spaceConst;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void addText(const QString &txt, QPainter *painter = nullptr)
|
|
|
|
|
{
|
|
|
|
|
if (txt.size()) {
|
|
|
|
|
int textWidth = fm.boundingRect(txt).width();
|
|
|
|
|
QSize itemSize = {textWidth, defaultHeight};
|
|
|
|
|
if (painter) {
|
|
|
|
|
QRect placeRect({width, 0}, itemSize);
|
|
|
|
|
painter->drawText(placeRect, txt, textOption);
|
|
|
|
|
}
|
|
|
|
|
applySize(itemSize);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void addPixmap(const QPixmap &pixmap, QPainter *painter = nullptr)
|
|
|
|
|
{
|
|
|
|
|
if (painter)
|
|
|
|
|
painter->drawPixmap(QRect({width, 0}, pixmap.size()), pixmap);
|
|
|
|
|
|
|
|
|
|
applySize(pixmap.size());
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void calcResult(QPainter *painter = nullptr)
|
|
|
|
|
{
|
|
|
|
|
reset();
|
|
|
|
|
#ifndef QT_NO_SHORTCUT
|
|
|
|
|
if (!shortcutText.isEmpty()) {
|
|
|
|
|
int fwdIndex = 0;
|
|
|
|
|
QRegularExpressionMatch mMatch = backspaceDetect.match(shortcutText);
|
|
|
|
|
int matchCount = mMatch.lastCapturedIndex();
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i <= matchCount; ++i) {
|
|
|
|
|
QString mStr = mMatch.captured(i);
|
|
|
|
|
QPixmap pixmap = getDeletePixmap(enabled,
|
|
|
|
|
active,
|
|
|
|
|
{defaultHeight * 3, defaultHeight});
|
|
|
|
|
|
|
|
|
|
int lIndex = shortcutText.indexOf(mStr, fwdIndex);
|
|
|
|
|
int diffChars = lIndex - fwdIndex;
|
|
|
|
|
addText(shortcutText.mid(fwdIndex, diffChars), painter);
|
|
|
|
|
addPixmap(pixmap, painter);
|
|
|
|
|
fwdIndex = lIndex + mStr.size();
|
|
|
|
|
}
|
|
|
|
|
addText(shortcutText.mid(fwdIndex), painter);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
_size = {width, height};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void reset()
|
|
|
|
|
{
|
|
|
|
|
isFirstParticle = true;
|
|
|
|
|
width = 0;
|
|
|
|
|
height = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QString shortcutText;
|
|
|
|
|
const bool enabled;
|
|
|
|
|
const bool active;
|
|
|
|
|
const QFont font;
|
|
|
|
|
const QFontMetrics fm;
|
|
|
|
|
const int defaultHeight;
|
|
|
|
|
const QPalette palette;
|
|
|
|
|
const int spaceConst;
|
|
|
|
|
static const QTextOption textOption;
|
|
|
|
|
static const QRegularExpression backspaceDetect;
|
|
|
|
|
bool isFirstParticle = true;
|
|
|
|
|
|
|
|
|
|
int width = 0;
|
|
|
|
|
int height = 0;
|
|
|
|
|
QSize _size;
|
|
|
|
|
QPixmap _pixmap;
|
|
|
|
|
};
|
|
|
|
|
const QRegularExpression ManhattanShortcut::backspaceDetect("\\+*backspace\\+*",
|
|
|
|
|
QRegularExpression::CaseInsensitiveOption);
|
|
|
|
|
const QTextOption ManhattanShortcut::textOption(Qt::AlignLeft | Qt::AlignVCenter);
|
|
|
|
|
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
class ManhattanStylePrivate
|
|
|
|
|
{
|
|
|
|
|
public:
|
2010-02-23 12:42:04 +01:00
|
|
|
explicit ManhattanStylePrivate();
|
2008-12-02 12:01:29 +01:00
|
|
|
void init();
|
2008-12-09 15:25:01 +01:00
|
|
|
|
|
|
|
|
public:
|
2019-12-10 14:01:15 +01:00
|
|
|
const QIcon extButtonIcon;
|
2010-02-10 10:47:34 +01:00
|
|
|
const QPixmap closeButtonPixmap;
|
2008-12-02 12:01:29 +01:00
|
|
|
StyleAnimator animator;
|
|
|
|
|
};
|
|
|
|
|
|
2010-02-23 12:42:04 +01:00
|
|
|
ManhattanStylePrivate::ManhattanStylePrivate() :
|
2019-12-10 14:01:15 +01:00
|
|
|
extButtonIcon(Utils::Icons::TOOLBAR_EXTENSION.icon()),
|
2016-08-03 17:55:54 +02:00
|
|
|
closeButtonPixmap(Utils::Icons::CLOSE_FOREGROUND.pixmap())
|
2010-02-10 10:47:34 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
ManhattanStyle::ManhattanStyle(const QString &baseStyleName)
|
2010-02-23 12:42:04 +01:00
|
|
|
: QProxyStyle(QStyleFactory::create(baseStyleName)),
|
|
|
|
|
d(new ManhattanStylePrivate())
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2023-04-21 14:45:54 +02:00
|
|
|
Core::Internal::GeneralSettings::applyToolbarStyleFromSettings();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ManhattanStyle::~ManhattanStyle()
|
|
|
|
|
{
|
|
|
|
|
delete d;
|
2018-07-21 21:11:46 +02:00
|
|
|
d = nullptr;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QPixmap ManhattanStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const
|
|
|
|
|
{
|
2010-02-23 12:42:04 +01:00
|
|
|
return QProxyStyle::generatedIconPixmap(iconMode, pixmap, opt);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QSize ManhattanStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
|
|
|
|
|
const QSize &size, const QWidget *widget) const
|
|
|
|
|
{
|
2010-02-23 12:42:04 +01:00
|
|
|
QSize newSize = QProxyStyle::sizeFromContents(type, option, size, widget);
|
2009-01-26 18:10:53 +01:00
|
|
|
|
2023-01-20 14:06:19 +02:00
|
|
|
switch (type) {
|
|
|
|
|
case CT_Splitter:
|
2023-05-09 13:20:04 +02:00
|
|
|
if (widget && widget->property(StyleHelper::C_MINI_SPLITTER).toBool())
|
2023-01-20 14:06:19 +02:00
|
|
|
newSize = QSize(1, 1);
|
|
|
|
|
break;
|
|
|
|
|
case CT_ComboBox:
|
|
|
|
|
if (panelWidget(widget))
|
|
|
|
|
newSize += QSize(14, 0);
|
|
|
|
|
break;
|
|
|
|
|
case CT_MenuItem:
|
|
|
|
|
if (isQmlEditorMenu(widget)) {
|
|
|
|
|
if (const auto mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
|
2023-01-31 13:29:19 +02:00
|
|
|
const int leftMargin = pixelMetric(QStyle::PM_LayoutLeftMargin, option, widget);
|
|
|
|
|
const int rightMargin = pixelMetric(QStyle::PM_LayoutRightMargin, option, widget);
|
2023-01-20 14:06:19 +02:00
|
|
|
const int horizontalSpacing = pixelMetric(QStyle::PM_LayoutHorizontalSpacing, option, widget);
|
|
|
|
|
const int iconHeight = pixelMetric(QStyle::PM_SmallIconSize, option, widget) + horizontalSpacing;
|
2023-01-31 13:29:19 +02:00
|
|
|
int width = leftMargin + rightMargin;
|
2023-01-20 14:06:19 +02:00
|
|
|
if (mbi->menuHasCheckableItems || mbi->maxIconWidth)
|
|
|
|
|
width += iconHeight + horizontalSpacing;
|
|
|
|
|
|
2023-01-31 13:29:19 +02:00
|
|
|
if (!mbi->text.isEmpty()) {
|
|
|
|
|
QString itemText = mbi->text;
|
|
|
|
|
QString shortcutText;
|
|
|
|
|
int tabIndex = itemText.indexOf("\t");
|
|
|
|
|
if (tabIndex > -1) {
|
|
|
|
|
shortcutText = itemText.mid(tabIndex + 1);
|
|
|
|
|
itemText = itemText.left(tabIndex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (itemText.size())
|
|
|
|
|
width += option->fontMetrics.boundingRect(itemText).width() + horizontalSpacing;
|
|
|
|
|
|
|
|
|
|
if (shortcutText.size()) {
|
|
|
|
|
QSize shortcutSize = ManhattanShortcut(mbi, shortcutText).getSize();
|
|
|
|
|
width += shortcutSize.width() + 2 * horizontalSpacing;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-01-20 14:06:19 +02:00
|
|
|
|
|
|
|
|
if (mbi->menuItemType == QStyleOptionMenuItem::SubMenu)
|
|
|
|
|
width += iconHeight + horizontalSpacing;
|
|
|
|
|
|
|
|
|
|
newSize.setWidth(width);
|
|
|
|
|
|
|
|
|
|
switch (mbi->menuItemType) {
|
|
|
|
|
case QStyleOptionMenuItem::Normal:
|
|
|
|
|
case QStyleOptionMenuItem::DefaultItem:
|
2023-01-31 13:29:19 +02:00
|
|
|
case QStyleOptionMenuItem::SubMenu:
|
|
|
|
|
newSize.setHeight(19);
|
2023-01-20 14:06:19 +02:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
newSize += QSize(0, 7);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2009-01-26 18:10:53 +01:00
|
|
|
return newSize;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QRect ManhattanStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
|
|
|
|
|
{
|
2010-02-23 12:42:04 +01:00
|
|
|
return QProxyStyle::subElementRect(element, option, widget);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QRect ManhattanStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
|
|
|
|
|
SubControl subControl, const QWidget *widget) const
|
|
|
|
|
{
|
2022-03-07 22:30:20 +01:00
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 5)
|
|
|
|
|
// Workaround for QTBUG-101581, can be removed when building with Qt 6.2.5 or higher
|
|
|
|
|
if (control == CC_ScrollBar) {
|
|
|
|
|
const auto scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option);
|
|
|
|
|
if (scrollbar && qint64(scrollbar->maximum) - scrollbar->minimum > INT_MAX)
|
|
|
|
|
return QRect(); // breaks the scrollbar, but avoids the crash
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2023-02-16 17:04:53 +02:00
|
|
|
|
|
|
|
|
QRect retval = QProxyStyle::subControlRect(control, option, subControl, widget);;
|
2023-02-20 19:02:43 +02:00
|
|
|
if (panelWidget(widget)) {
|
2023-02-16 17:04:53 +02:00
|
|
|
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
|
|
|
|
|
switch (subControl) {
|
|
|
|
|
case SubControl::SC_SliderGroove:
|
|
|
|
|
return option->rect;
|
|
|
|
|
case SubControl::SC_SliderHandle:
|
|
|
|
|
{
|
|
|
|
|
int thickness = 2;
|
|
|
|
|
QPoint center = retval.center();
|
|
|
|
|
const QRect &rect = slider->rect;
|
|
|
|
|
if (slider->orientation == Qt::Horizontal)
|
|
|
|
|
return QRect(center.x() - thickness, rect.top(), (thickness * 2) + 1, rect.height());
|
|
|
|
|
else
|
|
|
|
|
return QRect(rect.left(), center.y() - thickness, rect.width(), (thickness * 2) + 1);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return retval;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStyle::SubControl ManhattanStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option,
|
|
|
|
|
const QPoint &pos, const QWidget *widget) const
|
|
|
|
|
{
|
2010-02-23 12:42:04 +01:00
|
|
|
return QProxyStyle::hitTestComplexControl(control, option, pos, widget);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ManhattanStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
|
|
|
|
|
{
|
2023-01-20 14:06:19 +02:00
|
|
|
int retval = QProxyStyle::pixelMetric(metric, option, widget);
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
switch (metric) {
|
2023-02-23 15:21:26 +01:00
|
|
|
#ifdef Q_OS_MACOS
|
|
|
|
|
case PM_MenuButtonIndicator:
|
|
|
|
|
if (widget && option->type == QStyleOption::SO_ToolButton)
|
|
|
|
|
return 12;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
2008-12-02 12:01:29 +01:00
|
|
|
case PM_SplitterWidth:
|
2023-05-09 13:20:04 +02:00
|
|
|
if (widget && widget->property(StyleHelper::C_MINI_SPLITTER).toBool())
|
2008-12-02 12:01:29 +01:00
|
|
|
retval = 1;
|
|
|
|
|
break;
|
|
|
|
|
case PM_ToolBarIconSize:
|
2015-12-23 12:14:33 +01:00
|
|
|
case PM_ButtonIconSize:
|
2008-12-02 12:01:29 +01:00
|
|
|
if (panelWidget(widget))
|
|
|
|
|
retval = 16;
|
|
|
|
|
break;
|
2016-04-21 16:57:54 +02:00
|
|
|
case PM_SmallIconSize:
|
2023-01-20 14:06:19 +02:00
|
|
|
if (isQmlEditorMenu(widget))
|
|
|
|
|
retval = 10;
|
|
|
|
|
else
|
|
|
|
|
retval = 16;
|
2016-04-21 16:57:54 +02:00
|
|
|
break;
|
2010-03-18 17:46:30 +01:00
|
|
|
case PM_DockWidgetHandleExtent:
|
2010-03-16 16:55:56 +01:00
|
|
|
case PM_DockWidgetSeparatorExtent:
|
|
|
|
|
return 1;
|
2023-01-31 13:29:19 +02:00
|
|
|
case PM_LayoutLeftMargin:
|
|
|
|
|
case PM_LayoutRightMargin:
|
|
|
|
|
if (isQmlEditorMenu(widget))
|
|
|
|
|
retval = 7;
|
|
|
|
|
break;
|
2023-01-20 14:06:19 +02:00
|
|
|
case PM_LayoutHorizontalSpacing:
|
|
|
|
|
if (isQmlEditorMenu(widget))
|
2023-01-31 13:29:19 +02:00
|
|
|
retval = 12;
|
2023-01-20 14:06:19 +02:00
|
|
|
break;
|
|
|
|
|
case PM_MenuHMargin:
|
|
|
|
|
if (isQmlEditorMenu(widget))
|
2023-01-31 13:29:19 +02:00
|
|
|
retval = 5;
|
|
|
|
|
break;
|
|
|
|
|
case PM_SubMenuOverlap:
|
|
|
|
|
if (isQmlEditorMenu(widget))
|
|
|
|
|
retval = 10;
|
2023-01-20 14:06:19 +02:00
|
|
|
break;
|
2012-10-19 13:13:57 +02:00
|
|
|
case PM_MenuPanelWidth:
|
|
|
|
|
case PM_MenuBarHMargin:
|
|
|
|
|
case PM_MenuBarVMargin:
|
2008-12-02 12:01:29 +01:00
|
|
|
case PM_ToolBarFrameWidth:
|
2023-01-20 14:06:19 +02:00
|
|
|
if (panelWidget(widget) || isQmlEditorMenu(widget))
|
2008-12-02 12:01:29 +01:00
|
|
|
retval = 1;
|
|
|
|
|
break;
|
|
|
|
|
case PM_ButtonShiftVertical:
|
|
|
|
|
case PM_ButtonShiftHorizontal:
|
2012-10-19 13:13:57 +02:00
|
|
|
case PM_MenuBarPanelWidth:
|
2008-12-02 12:01:29 +01:00
|
|
|
case PM_ToolBarItemMargin:
|
2023-01-30 17:25:10 +01:00
|
|
|
if (StyleHelper::isQDSTheme()) {
|
|
|
|
|
retval = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
[[fallthrough]];
|
2008-12-02 12:01:29 +01:00
|
|
|
case PM_ToolBarItemSpacing:
|
|
|
|
|
if (panelWidget(widget))
|
|
|
|
|
retval = 0;
|
2023-01-30 17:25:10 +01:00
|
|
|
if (StyleHelper::isQDSTheme())
|
|
|
|
|
retval = 4;
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
|
|
|
|
case PM_DefaultFrameWidth:
|
|
|
|
|
if (qobject_cast<const QLineEdit*>(widget) && panelWidget(widget))
|
|
|
|
|
return 1;
|
|
|
|
|
break;
|
2023-02-21 11:22:27 +01:00
|
|
|
case PM_ToolBarExtensionExtent:
|
|
|
|
|
if (StyleHelper::isQDSTheme())
|
|
|
|
|
retval = 29;
|
|
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QPalette ManhattanStyle::standardPalette() const
|
|
|
|
|
{
|
2010-02-23 12:42:04 +01:00
|
|
|
return QProxyStyle::standardPalette();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ManhattanStyle::polish(QApplication *app)
|
|
|
|
|
{
|
2017-04-14 12:06:24 +02:00
|
|
|
QProxyStyle::polish(app);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ManhattanStyle::unpolish(QApplication *app)
|
|
|
|
|
{
|
2017-04-14 12:06:24 +02:00
|
|
|
QProxyStyle::unpolish(app);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2010-02-19 09:54:29 +01:00
|
|
|
QPalette panelPalette(const QPalette &oldPalette, bool lightColored = false)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2014-10-18 22:43:02 +03:00
|
|
|
QColor color = creatorTheme()->color(lightColored ? Theme::PanelTextColorDark
|
|
|
|
|
: Theme::PanelTextColorLight);
|
2008-12-02 12:01:29 +01:00
|
|
|
QPalette pal = oldPalette;
|
|
|
|
|
pal.setBrush(QPalette::All, QPalette::WindowText, color);
|
|
|
|
|
pal.setBrush(QPalette::All, QPalette::ButtonText, color);
|
2016-04-16 20:59:42 +02:00
|
|
|
if (lightColored)
|
|
|
|
|
color.setAlpha(100);
|
|
|
|
|
else
|
|
|
|
|
color = creatorTheme()->color(Theme::IconsDisabledColor);
|
2008-12-02 12:01:29 +01:00
|
|
|
pal.setBrush(QPalette::Disabled, QPalette::WindowText, color);
|
|
|
|
|
pal.setBrush(QPalette::Disabled, QPalette::ButtonText, color);
|
|
|
|
|
return pal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ManhattanStyle::polish(QWidget *widget)
|
|
|
|
|
{
|
2010-02-23 12:42:04 +01:00
|
|
|
QProxyStyle::polish(widget);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-03-18 17:46:30 +01:00
|
|
|
// OxygenStyle forces a rounded widget mask on toolbars and dock widgets
|
2011-10-14 13:02:37 +02:00
|
|
|
if (baseStyle()->inherits("OxygenStyle") || baseStyle()->inherits("Oxygen::Style")) {
|
2010-03-18 17:46:30 +01:00
|
|
|
if (qobject_cast<QToolBar*>(widget) || qobject_cast<QDockWidget*>(widget)) {
|
2010-02-23 12:42:04 +01:00
|
|
|
widget->removeEventFilter(baseStyle());
|
2010-03-18 17:46:30 +01:00
|
|
|
widget->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
if (panelWidget(widget)) {
|
2010-03-23 13:51:32 +01:00
|
|
|
|
|
|
|
|
// Oxygen and possibly other styles override this
|
|
|
|
|
if (qobject_cast<QDockWidget*>(widget))
|
|
|
|
|
widget->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
|
2009-07-15 16:23:07 +02:00
|
|
|
widget->setAttribute(Qt::WA_LayoutUsesWidgetRect, true);
|
2021-06-14 11:56:27 +02:00
|
|
|
// So that text isn't cutoff in line-edits, comboboxes... etc.
|
|
|
|
|
const int height = qMax(StyleHelper::navigationWidgetHeight(), QApplication::fontMetrics().height());
|
2023-04-21 14:49:26 +02:00
|
|
|
if (qobject_cast<QToolButton*>(widget)) {
|
|
|
|
|
widget->setMinimumWidth(
|
|
|
|
|
StyleHelper::toolbarStyle() == StyleHelper::ToolbarStyleCompact ? 24 : 28);
|
2008-12-02 12:01:29 +01:00
|
|
|
widget->setAttribute(Qt::WA_Hover);
|
2021-06-14 11:56:27 +02:00
|
|
|
widget->setMaximumHeight(height - 2);
|
2023-04-21 14:49:26 +02:00
|
|
|
} else if (qobject_cast<QLineEdit*>(widget)) {
|
|
|
|
|
widget->setAttribute(Qt::WA_Hover);
|
|
|
|
|
widget->setFixedHeight(height - (StyleHelper::toolbarStyle()
|
|
|
|
|
== StyleHelper::ToolbarStyleCompact ? 1 : 3));
|
2021-09-28 10:01:51 +02:00
|
|
|
} else if (qobject_cast<QLabel*>(widget) || qobject_cast<QSpinBox*>(widget)
|
|
|
|
|
|| qobject_cast<QCheckBox*>(widget)) {
|
2014-08-01 14:44:28 +02:00
|
|
|
widget->setPalette(panelPalette(widget->palette(), lightColored(widget)));
|
2023-04-24 09:41:09 +02:00
|
|
|
} else if ((qobject_cast<QToolBar*>(widget) && !StyleHelper::isQDSTheme())
|
2023-05-09 13:20:04 +02:00
|
|
|
|| widget->property(StyleHelper::C_PANEL_WIDGET_SINGLE_ROW).toBool()) {
|
2021-06-14 11:56:27 +02:00
|
|
|
widget->setFixedHeight(height);
|
2013-07-17 00:01:45 +03:00
|
|
|
} else if (qobject_cast<QStatusBar*>(widget)) {
|
2023-04-24 09:41:09 +02:00
|
|
|
const bool flatAndNotCompact =
|
|
|
|
|
StyleHelper::toolbarStyle() != StyleHelper::ToolbarStyleCompact
|
|
|
|
|
&& creatorTheme()->flag(Theme::FlatToolBars);
|
|
|
|
|
widget->setFixedHeight(height + (flatAndNotCompact ? 3 : 2));
|
2013-07-17 00:01:45 +03:00
|
|
|
} else if (qobject_cast<QComboBox*>(widget)) {
|
2018-01-31 16:42:41 +01:00
|
|
|
const bool isLightColored = lightColored(widget);
|
|
|
|
|
QPalette palette = panelPalette(widget->palette(), isLightColored);
|
|
|
|
|
if (!isLightColored)
|
2019-08-29 11:40:38 +02:00
|
|
|
palette.setBrush(QPalette::All, QPalette::WindowText,
|
2018-01-31 16:42:41 +01:00
|
|
|
creatorTheme()->color(Theme::ComboBoxTextColor));
|
|
|
|
|
widget->setPalette(palette);
|
2021-06-14 11:56:27 +02:00
|
|
|
widget->setMaximumHeight(height - 2);
|
2009-02-10 15:09:24 +01:00
|
|
|
widget->setAttribute(Qt::WA_Hover);
|
2023-04-24 09:41:09 +02:00
|
|
|
} else if (qobject_cast<QScrollArea*>(widget)
|
2023-05-09 13:20:04 +02:00
|
|
|
&& widget->property(StyleHelper::C_PANEL_WIDGET_SINGLE_ROW).toBool()) {
|
2023-04-24 09:41:09 +02:00
|
|
|
widget->setFixedHeight(height);
|
2009-02-10 15:09:24 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ManhattanStyle::unpolish(QWidget *widget)
|
|
|
|
|
{
|
2010-02-23 12:42:04 +01:00
|
|
|
QProxyStyle::unpolish(widget);
|
2008-12-02 12:01:29 +01:00
|
|
|
if (panelWidget(widget)) {
|
2009-07-15 16:23:07 +02:00
|
|
|
widget->setAttribute(Qt::WA_LayoutUsesWidgetRect, false);
|
2019-10-31 15:34:50 +01:00
|
|
|
if (qobject_cast<QTabBar*>(widget)
|
|
|
|
|
|| qobject_cast<QToolBar*>(widget)
|
|
|
|
|
|| qobject_cast<QComboBox*>(widget)) {
|
2009-02-10 15:09:24 +01:00
|
|
|
widget->setAttribute(Qt::WA_Hover, false);
|
2019-10-31 15:34:50 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ManhattanStyle::polish(QPalette &pal)
|
|
|
|
|
{
|
2010-02-23 12:42:04 +01:00
|
|
|
QProxyStyle::polish(pal);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QPixmap ManhattanStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt,
|
|
|
|
|
const QWidget *widget) const
|
|
|
|
|
{
|
2009-01-26 15:46:11 +01:00
|
|
|
if (widget && !panelWidget(widget))
|
2010-02-23 12:42:04 +01:00
|
|
|
return QProxyStyle::standardPixmap(standardPixmap, opt, widget);
|
2009-01-26 15:46:11 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
QPixmap pixmap;
|
|
|
|
|
switch (standardPixmap) {
|
2010-02-10 10:47:34 +01:00
|
|
|
case QStyle::SP_TitleBarCloseButton:
|
|
|
|
|
pixmap = d->closeButtonPixmap;
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
|
|
|
|
default:
|
2010-02-23 12:42:04 +01:00
|
|
|
pixmap = QProxyStyle::standardPixmap(standardPixmap, opt, widget);
|
2010-02-10 10:47:34 +01:00
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
return pixmap;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 16:58:21 +02:00
|
|
|
QIcon ManhattanStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const
|
|
|
|
|
{
|
2019-12-10 14:01:15 +01:00
|
|
|
QIcon icon;
|
|
|
|
|
switch (standardIcon) {
|
|
|
|
|
case QStyle::SP_ToolBarHorizontalExtensionButton:
|
|
|
|
|
icon = d->extButtonIcon;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
icon = QProxyStyle::standardIcon(standardIcon, option, widget);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-21 16:58:21 +02:00
|
|
|
if (standardIcon == QStyle::SP_ComputerIcon) {
|
|
|
|
|
// Ubuntu has in some versions a 16x16 icon, see QTCREATORBUG-12832
|
|
|
|
|
const QList<QSize> &sizes = icon.availableSizes();
|
2016-10-27 10:54:54 +03:00
|
|
|
if (Utils::allOf(sizes, [](const QSize &size) { return size.width() < 32;}))
|
|
|
|
|
icon = QIcon(":/utils/images/Desktop.png");
|
2015-05-21 16:58:21 +02:00
|
|
|
}
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
int ManhattanStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
|
|
|
|
|
QStyleHintReturn *returnData) const
|
|
|
|
|
{
|
2010-02-23 12:42:04 +01:00
|
|
|
int ret = QProxyStyle::styleHint(hint, option, widget, returnData);
|
2008-12-02 12:01:29 +01:00
|
|
|
switch (hint) {
|
|
|
|
|
case QStyle::SH_EtchDisabledText:
|
2015-03-21 13:13:59 +01:00
|
|
|
if (panelWidget(widget) || qobject_cast<const QMenu *> (widget) )
|
2009-01-27 10:09:37 +01:00
|
|
|
ret = false;
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
2010-02-02 14:29:07 +01:00
|
|
|
case QStyle::SH_ItemView_ArrowKeysNavigateIntoChildren:
|
|
|
|
|
ret = true;
|
|
|
|
|
break;
|
2014-04-07 17:40:43 +02:00
|
|
|
case QStyle::SH_ItemView_ActivateItemOnSingleClick:
|
|
|
|
|
// default depends on the style
|
|
|
|
|
if (widget) {
|
2023-05-09 13:20:04 +02:00
|
|
|
QVariant activationMode = widget->property(activationModeC);
|
2014-04-07 17:40:43 +02:00
|
|
|
if (activationMode.isValid())
|
|
|
|
|
ret = activationMode.toBool();
|
|
|
|
|
}
|
2015-05-13 10:15:26 +02:00
|
|
|
break;
|
2015-05-07 16:17:10 +02:00
|
|
|
case QStyle::SH_FormLayoutFieldGrowthPolicy:
|
|
|
|
|
// The default in QMacStyle, FieldsStayAtSizeHint, is just always the wrong thing
|
|
|
|
|
// Use the same as on all other shipped styles
|
|
|
|
|
if (Utils::HostOsInfo::isMacHost())
|
|
|
|
|
ret = QFormLayout::AllNonFixedFieldsGrow;
|
2015-05-13 10:15:26 +02:00
|
|
|
break;
|
2020-10-30 22:19:37 +01:00
|
|
|
case QStyle::SH_Widget_Animation_Duration:
|
2022-04-27 09:40:43 +02:00
|
|
|
if (widget && widget->inherits("QTreeView"))
|
2020-10-30 22:19:37 +01:00
|
|
|
ret = 0;
|
|
|
|
|
break;
|
2022-08-26 21:01:34 +09:00
|
|
|
case QStyle::SH_ComboBox_AllowWheelScrolling:
|
2023-01-02 14:00:02 +01:00
|
|
|
// Turn this on only when simultaneously pressing Ctrl, to prevent accidental current
|
|
|
|
|
// index change, e.g. on a scroll view
|
|
|
|
|
ret = QGuiApplication::keyboardModifiers()
|
|
|
|
|
== (HostOsInfo::isMacHost() ? Qt::MetaModifier : Qt::ControlModifier);
|
2022-08-26 21:01:34 +09:00
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
default:
|
2009-01-27 10:09:37 +01:00
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-28 11:58:23 +02:00
|
|
|
static void drawPrimitiveTweakedForDarkTheme(QStyle::PrimitiveElement element,
|
|
|
|
|
const QStyleOption *option,
|
|
|
|
|
QPainter *painter, const QWidget *widget)
|
|
|
|
|
{
|
|
|
|
|
const bool hasFocus = option->state & QStyle::State_HasFocus;
|
|
|
|
|
const bool isChecked = option->state & QStyle::State_On;
|
|
|
|
|
const bool isPartiallyChecked = option->state & QStyle::State_NoChange;
|
|
|
|
|
const bool isEnabled = option->state & QStyle::State_Enabled;
|
|
|
|
|
const bool isSunken = option->state & QStyle::State_Sunken;
|
|
|
|
|
|
|
|
|
|
const QColor frameColor = isEnabled ? option->palette.color(QPalette::Mid).darker(132)
|
|
|
|
|
: creatorTheme()->color(Theme::BackgroundColorDisabled);
|
|
|
|
|
const QColor indicatorColor = isEnabled ? option->palette.color(QPalette::Mid).darker(90)
|
|
|
|
|
: creatorTheme()->color(Theme::BackgroundColorDisabled);
|
|
|
|
|
const QColor bgColor = isSunken ? option->palette.color(QPalette::Mid).darker()
|
|
|
|
|
: option->palette.color(QPalette::Window);
|
|
|
|
|
const QColor hlColor = option->palette.color(QPalette::Highlight);
|
|
|
|
|
|
|
|
|
|
QPen framePen(hasFocus ? hlColor : frameColor, 1);
|
|
|
|
|
framePen.setJoinStyle(Qt::MiterJoin);
|
|
|
|
|
QPen indicatorPen(indicatorColor, 1);
|
|
|
|
|
indicatorPen.setJoinStyle(Qt::MiterJoin);
|
|
|
|
|
|
|
|
|
|
painter->save();
|
|
|
|
|
painter->setRenderHint(QPainter::Antialiasing);
|
|
|
|
|
|
|
|
|
|
switch (element) {
|
|
|
|
|
case QStyle::PE_Frame: {
|
|
|
|
|
const QRectF frameRectF = QRectF(option->rect).adjusted(0.5, 0.5, -0.5, -0.5);
|
|
|
|
|
painter->setPen(framePen);
|
|
|
|
|
painter->drawRect(frameRectF);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case QStyle::PE_FrameLineEdit: {
|
2020-11-25 12:25:24 +01:00
|
|
|
const bool isComboBox = widget && widget->inherits("QComboBox");
|
2020-07-28 11:58:23 +02:00
|
|
|
const QRectF frameRectF =
|
|
|
|
|
QRectF(option->rect).adjusted(0.5, 0.5, isComboBox ? -8.5 : -0.5, -0.5);
|
|
|
|
|
painter->setPen(framePen);
|
|
|
|
|
painter->drawRect(frameRectF);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case QStyle::PE_FrameGroupBox: {
|
|
|
|
|
// Snippet from QFusionStyle::drawPrimitive - BEGIN
|
|
|
|
|
static const int groupBoxTopMargin = 3;
|
|
|
|
|
int topMargin = 0;
|
|
|
|
|
auto control = dynamic_cast<const QGroupBox *>(widget);
|
|
|
|
|
if (control && !control->isCheckable() && control->title().isEmpty()) {
|
|
|
|
|
// Shrinking the topMargin if Not checkable AND title is empty
|
|
|
|
|
topMargin = groupBoxTopMargin;
|
|
|
|
|
} else {
|
2020-11-25 12:25:24 +01:00
|
|
|
const int exclusiveIndicatorHeight = widget ? widget->style()->pixelMetric(QStyle::PM_ExclusiveIndicatorHeight) : 0;
|
|
|
|
|
topMargin = qMax(exclusiveIndicatorHeight,
|
2020-07-28 11:58:23 +02:00
|
|
|
option->fontMetrics.height()) + groupBoxTopMargin;
|
|
|
|
|
}
|
|
|
|
|
// Snippet from QFusionStyle::drawPrimitive - END
|
|
|
|
|
|
|
|
|
|
const QRectF frameRectF = QRectF(option->rect).adjusted(0.5, topMargin + 0.5, -0.5, -0.5);
|
|
|
|
|
painter->setPen(framePen);
|
|
|
|
|
if (isEnabled)
|
|
|
|
|
painter->setOpacity(0.5);
|
|
|
|
|
painter->drawRect(frameRectF);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case QStyle::PE_IndicatorRadioButton: {
|
|
|
|
|
const double lineWidth = 1.666;
|
|
|
|
|
const double o = lineWidth / 2;
|
|
|
|
|
indicatorPen.setWidth(lineWidth);
|
|
|
|
|
painter->setPen(framePen);
|
|
|
|
|
if (isEnabled)
|
|
|
|
|
painter->setBrush(bgColor);
|
|
|
|
|
painter->drawRoundedRect(QRectF(option->rect).adjusted(o, o, -o, -o),
|
|
|
|
|
100, 100, Qt::RelativeSize);
|
|
|
|
|
|
|
|
|
|
if (isChecked) {
|
|
|
|
|
painter->setPen(Qt::NoPen);
|
|
|
|
|
painter->setBrush(indicatorColor);
|
|
|
|
|
const double o = 4.25;
|
|
|
|
|
painter->drawRoundedRect(QRectF(option->rect).adjusted(o, o, -o, -o),
|
|
|
|
|
100, 100, Qt::RelativeSize);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case QStyle::PE_IndicatorCheckBox: {
|
|
|
|
|
const QRectF frameRectF = QRectF(option->rect).adjusted(0.5, 0.5, -0.5, -0.5);
|
|
|
|
|
painter->setPen(framePen);
|
|
|
|
|
if (isEnabled)
|
|
|
|
|
painter->setBrush(bgColor);
|
|
|
|
|
painter->drawRect(frameRectF);
|
|
|
|
|
|
|
|
|
|
if (isPartiallyChecked) {
|
|
|
|
|
QPen outline(indicatorColor, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
|
|
|
|
|
painter->setPen(outline);
|
|
|
|
|
QColor fill(frameColor);
|
2021-07-09 14:32:41 +02:00
|
|
|
fill.setAlphaF(0.8f);
|
2020-07-28 11:58:23 +02:00
|
|
|
painter->setBrush(fill);
|
|
|
|
|
const double o = 3.5;
|
|
|
|
|
painter->drawRect(QRectF(option->rect).adjusted(o, o, -o, -o));
|
|
|
|
|
} else if (isChecked) {
|
|
|
|
|
const double o = 3;
|
|
|
|
|
const QRectF r = QRectF(option->rect).adjusted(o, o, -o, -o);
|
|
|
|
|
QPen checkMarkPen(indicatorColor, 1.75, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
|
|
|
|
|
painter->setPen(checkMarkPen);
|
|
|
|
|
painter->drawPolyline(QPolygonF({QPointF(r.left(), r.top() + r.height() / 2),
|
|
|
|
|
QPointF(r.left() + r.width() / 2.3, r.bottom()),
|
|
|
|
|
r.topRight()}));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case QStyle::PE_IndicatorTabClose: {
|
2020-11-25 12:25:24 +01:00
|
|
|
QWindow *window = widget ? widget->window()->windowHandle() : nullptr;
|
2020-07-28 11:58:23 +02:00
|
|
|
QRect iconRect = QRect(0, 0, 16, 16);
|
|
|
|
|
iconRect.moveCenter(option->rect.center());
|
|
|
|
|
const QIcon::Mode mode = !isEnabled ? QIcon::Disabled : QIcon::Normal;
|
|
|
|
|
const static QIcon closeIcon = Utils::Icons::CLOSE_FOREGROUND.icon();
|
2020-11-25 12:25:24 +01:00
|
|
|
if (option->state & QStyle::State_MouseOver && widget)
|
2020-07-28 11:58:23 +02:00
|
|
|
widget->style()->drawPrimitive(QStyle::PE_PanelButtonCommand, option, painter, widget);
|
2020-11-25 12:25:24 +01:00
|
|
|
const int devicePixelRatio = widget ? widget->devicePixelRatio() : 1;
|
2020-07-28 11:58:23 +02:00
|
|
|
const QPixmap iconPx =
|
2020-11-25 12:25:24 +01:00
|
|
|
closeIcon.pixmap(window, iconRect.size() * devicePixelRatio, mode);
|
2020-07-28 11:58:23 +02:00
|
|
|
painter->drawPixmap(iconRect, iconPx);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
QTC_ASSERT_STRING("Unhandled QStyle::PrimitiveElement case");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
painter->restore();
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
|
|
|
|
|
QPainter *painter, const QWidget *widget) const
|
|
|
|
|
{
|
2023-01-20 14:06:19 +02:00
|
|
|
if (panelWidget(widget)) {
|
|
|
|
|
drawPrimitiveForPanelWidget(element, option, painter, widget);
|
|
|
|
|
} else if (isQmlEditorMenu(widget)) {
|
|
|
|
|
drawPrimitiveForQmlEditor(element, option, painter, widget);
|
|
|
|
|
} else {
|
2020-07-28 11:58:23 +02:00
|
|
|
const bool tweakDarkTheme =
|
|
|
|
|
(element == PE_Frame
|
|
|
|
|
|| element == PE_FrameLineEdit
|
|
|
|
|
|| element == PE_FrameGroupBox
|
|
|
|
|
|| element == PE_IndicatorRadioButton
|
|
|
|
|
|| element == PE_IndicatorCheckBox
|
|
|
|
|
|| element == PE_IndicatorTabClose)
|
|
|
|
|
&& isDarkFusionStyle(baseStyle());
|
|
|
|
|
if (tweakDarkTheme)
|
|
|
|
|
drawPrimitiveTweakedForDarkTheme(element, option, painter, widget);
|
|
|
|
|
else
|
|
|
|
|
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
2017-04-14 12:06:24 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2023-01-20 14:06:19 +02:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2023-01-20 14:06:19 +02:00
|
|
|
void ManhattanStyle::drawPrimitiveForPanelWidget(PrimitiveElement element,
|
|
|
|
|
const QStyleOption *option,
|
|
|
|
|
QPainter *painter,
|
|
|
|
|
const QWidget *widget) const
|
|
|
|
|
{
|
2008-12-02 12:01:29 +01:00
|
|
|
bool animating = (option->state & State_Animating);
|
|
|
|
|
int state = option->state;
|
|
|
|
|
QRect rect = option->rect;
|
|
|
|
|
QRect oldRect;
|
|
|
|
|
QRect newRect;
|
|
|
|
|
if (widget && (element == PE_PanelButtonTool) && !animating) {
|
2018-07-21 21:11:46 +02:00
|
|
|
auto w = const_cast<QWidget *> (widget);
|
2008-12-02 12:01:29 +01:00
|
|
|
int oldState = w->property("_q_stylestate").toInt();
|
|
|
|
|
oldRect = w->property("_q_stylerect").toRect();
|
|
|
|
|
newRect = w->rect();
|
|
|
|
|
w->setProperty("_q_stylestate", (int)option->state);
|
|
|
|
|
w->setProperty("_q_stylerect", w->rect());
|
|
|
|
|
|
|
|
|
|
// Determine the animated transition
|
|
|
|
|
bool doTransition = ((state & State_On) != (oldState & State_On) ||
|
|
|
|
|
(state & State_MouseOver) != (oldState & State_MouseOver));
|
|
|
|
|
if (oldRect != newRect)
|
|
|
|
|
{
|
|
|
|
|
doTransition = false;
|
|
|
|
|
d->animator.stopAnimation(widget);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (doTransition) {
|
|
|
|
|
QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
|
|
|
|
|
QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
|
|
|
|
|
Animation *anim = d->animator.widgetAnimation(widget);
|
|
|
|
|
QStyleOption opt = *option;
|
|
|
|
|
opt.state = (QStyle::State)oldState;
|
2012-05-21 09:19:16 +02:00
|
|
|
opt.state |= State_Animating;
|
2008-12-02 12:01:29 +01:00
|
|
|
startImage.fill(0);
|
2018-07-21 21:11:46 +02:00
|
|
|
auto t = new Transition;
|
2008-12-02 12:01:29 +01:00
|
|
|
t->setWidget(w);
|
|
|
|
|
QPainter startPainter(&startImage);
|
|
|
|
|
if (!anim) {
|
|
|
|
|
drawPrimitive(element, &opt, &startPainter, widget);
|
|
|
|
|
} else {
|
|
|
|
|
anim->paint(&startPainter, &opt);
|
|
|
|
|
d->animator.stopAnimation(widget);
|
|
|
|
|
}
|
|
|
|
|
QStyleOption endOpt = *option;
|
2012-05-21 09:19:16 +02:00
|
|
|
endOpt.state |= State_Animating;
|
2008-12-02 12:01:29 +01:00
|
|
|
t->setStartImage(startImage);
|
|
|
|
|
d->animator.startAnimation(t);
|
|
|
|
|
endImage.fill(0);
|
|
|
|
|
QPainter endPainter(&endImage);
|
|
|
|
|
drawPrimitive(element, &endOpt, &endPainter, widget);
|
|
|
|
|
t->setEndImage(endImage);
|
2009-07-20 18:56:50 +02:00
|
|
|
if (oldState & State_MouseOver)
|
|
|
|
|
t->setDuration(150);
|
|
|
|
|
else
|
|
|
|
|
t->setDuration(75);
|
2008-12-02 12:01:29 +01:00
|
|
|
t->setStartTime(QTime::currentTime());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (element) {
|
2010-03-18 17:46:30 +01:00
|
|
|
case PE_IndicatorDockWidgetResizeHandle:
|
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>
2014-10-14 19:09:48 +02:00
|
|
|
painter->fillRect(option->rect, creatorTheme()->color(Theme::DockWidgetResizeHandleColor));
|
2010-03-18 17:46:30 +01:00
|
|
|
break;
|
|
|
|
|
case PE_FrameDockWidget:
|
|
|
|
|
QCommonStyle::drawPrimitive(element, option, painter, widget);
|
|
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
case PE_PanelLineEdit:
|
|
|
|
|
{
|
|
|
|
|
painter->save();
|
2009-08-31 15:02:16 +02:00
|
|
|
|
|
|
|
|
// Fill the line edit background
|
2016-02-26 16:29:01 +01:00
|
|
|
QRectF backgroundRect = option->rect;
|
2016-04-27 12:16:30 +02:00
|
|
|
const bool enabled = option->state & State_Enabled;
|
2016-06-15 17:41:33 +02:00
|
|
|
if (Utils::creatorTheme()->flag(Theme::FlatToolBars)) {
|
|
|
|
|
painter->save();
|
|
|
|
|
if (!enabled)
|
|
|
|
|
painter->setOpacity(0.75);
|
2023-02-20 21:47:13 +02:00
|
|
|
QBrush baseBrush = option->palette.base();
|
|
|
|
|
if (widget && qobject_cast<const QSpinBox *>(widget->parentWidget()))
|
|
|
|
|
baseBrush = creatorTheme()->color(Theme::DScontrolBackgroundDisabled);
|
|
|
|
|
painter->fillRect(backgroundRect, baseBrush);
|
2016-06-15 17:41:33 +02:00
|
|
|
painter->restore();
|
|
|
|
|
} else {
|
2016-02-26 16:29:01 +01:00
|
|
|
backgroundRect.adjust(1, 1, -1, -1);
|
|
|
|
|
painter->setBrushOrigin(backgroundRect.topLeft());
|
|
|
|
|
painter->fillRect(backgroundRect, option->palette.base());
|
|
|
|
|
|
2016-03-12 23:29:27 +01:00
|
|
|
static const QImage bg(StyleHelper::dpiSpecificImageFile(
|
2016-10-07 12:44:39 +02:00
|
|
|
QLatin1String(":/utils/images/inputfield.png")));
|
2016-03-12 23:29:27 +01:00
|
|
|
static const QImage bg_disabled(StyleHelper::dpiSpecificImageFile(
|
2016-10-07 12:44:39 +02:00
|
|
|
QLatin1String(":/utils/images/inputfield_disabled.png")));
|
2016-03-12 23:29:27 +01:00
|
|
|
|
|
|
|
|
StyleHelper::drawCornerImage(enabled ? bg : bg_disabled,
|
2016-02-26 16:29:01 +01:00
|
|
|
painter, option->rect, 5, 5, 5, 5);
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-02-26 16:29:01 +01:00
|
|
|
const bool hasFocus = state & State_HasFocus;
|
2016-04-27 12:16:30 +02:00
|
|
|
if (enabled && (hasFocus || state & State_MouseOver)) {
|
2015-02-03 23:48:19 +02:00
|
|
|
QColor hover = StyleHelper::baseColor();
|
2016-02-26 16:29:01 +01:00
|
|
|
hover.setAlpha(hasFocus ? 100 : 50);
|
|
|
|
|
painter->setPen(QPen(hover, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
|
|
|
|
|
painter->drawRect(backgroundRect.adjusted(0.5, 0.5, -0.5, -0.5));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
painter->restore();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PE_FrameStatusBarItem:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PE_PanelButtonTool: {
|
|
|
|
|
Animation *anim = d->animator.widgetAnimation(widget);
|
|
|
|
|
if (!animating && anim) {
|
|
|
|
|
anim->paint(painter, option);
|
|
|
|
|
} else {
|
2023-04-21 14:49:26 +02:00
|
|
|
const bool pressed = option->state & State_Sunken || option->state & State_On
|
2023-05-09 13:20:04 +02:00
|
|
|
|| (widget && widget->property(StyleHelper::C_HIGHLIGHT_WIDGET)
|
|
|
|
|
.toBool());
|
2016-04-02 20:24:00 +02:00
|
|
|
painter->setPen(StyleHelper::sidebarShadow());
|
2008-12-02 12:01:29 +01:00
|
|
|
if (pressed) {
|
2023-04-21 14:49:26 +02:00
|
|
|
StyleHelper::drawPanelBgRect(
|
|
|
|
|
painter, rect, creatorTheme()->color(Theme::FancyToolButtonSelectedColor));
|
|
|
|
|
if (StyleHelper::toolbarStyle() == StyleHelper::ToolbarStyleCompact
|
|
|
|
|
&& !creatorTheme()->flag(Theme::FlatToolBars)) {
|
2016-04-02 20:24:00 +02:00
|
|
|
const QRectF borderRect = QRectF(rect).adjusted(0.5, 0.5, -0.5, -0.5);
|
|
|
|
|
painter->drawLine(borderRect.topLeft() + QPointF(1, 0), borderRect.topRight() - QPointF(1, 0));
|
|
|
|
|
painter->drawLine(borderRect.topLeft(), borderRect.bottomLeft());
|
|
|
|
|
painter->drawLine(borderRect.topRight(), borderRect.bottomRight());
|
|
|
|
|
}
|
2013-10-17 14:52:26 +02:00
|
|
|
} else if (option->state & State_Enabled && option->state & State_MouseOver) {
|
2023-04-21 14:49:26 +02:00
|
|
|
StyleHelper::drawPanelBgRect(
|
|
|
|
|
painter, rect, creatorTheme()->color(Theme::FancyToolButtonHoverColor));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2010-03-01 14:51:48 +01:00
|
|
|
if (option->state & State_HasFocus && (option->state & State_KeyboardFocusChange)) {
|
|
|
|
|
QColor highlight = option->palette.highlight().color();
|
2021-07-09 14:32:41 +02:00
|
|
|
highlight.setAlphaF(0.4f);
|
2010-03-01 14:51:48 +01:00
|
|
|
painter->setPen(QPen(highlight.lighter(), 1));
|
2021-07-09 14:32:41 +02:00
|
|
|
highlight.setAlphaF(0.3f);
|
2010-03-01 14:51:48 +01:00
|
|
|
painter->setBrush(highlight);
|
|
|
|
|
painter->setRenderHint(QPainter::Antialiasing);
|
2014-09-18 12:33:44 +03:00
|
|
|
const QRectF rect = option->rect;
|
|
|
|
|
painter->drawRoundedRect(rect.adjusted(2.5, 2.5, -2.5, -2.5), 2, 2);
|
2010-03-01 14:51:48 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PE_PanelStatusBar:
|
|
|
|
|
{
|
2016-07-19 17:27:23 +02:00
|
|
|
const QRectF borderRect = QRectF(rect).adjusted(0.5, 0.5, -0.5, -0.5);
|
|
|
|
|
painter->save();
|
2016-06-15 17:41:33 +02:00
|
|
|
if (creatorTheme()->flag(Theme::FlatToolBars)) {
|
|
|
|
|
painter->fillRect(rect, StyleHelper::baseColor());
|
|
|
|
|
} else {
|
2015-02-03 23:48:19 +02:00
|
|
|
QLinearGradient grad = StyleHelper::statusBarGradient(rect);
|
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>
2014-10-14 19:09:48 +02:00
|
|
|
painter->fillRect(rect, grad);
|
|
|
|
|
painter->setPen(QColor(255, 255, 255, 60));
|
2015-10-20 14:58:28 +02:00
|
|
|
painter->drawLine(borderRect.topLeft() + QPointF(0, 1),
|
|
|
|
|
borderRect.topRight()+ QPointF(0, 1));
|
2015-02-03 23:48:19 +02:00
|
|
|
painter->setPen(StyleHelper::borderColor().darker(110)); //TODO: make themable
|
2015-10-20 14:58:28 +02:00
|
|
|
painter->drawLine(borderRect.topLeft(), borderRect.topRight());
|
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>
2014-10-14 19:09:48 +02:00
|
|
|
}
|
2016-07-19 17:27:23 +02:00
|
|
|
if (creatorTheme()->flag(Theme::DrawToolBarBorders)) {
|
2016-07-19 18:24:25 +02:00
|
|
|
painter->setPen(StyleHelper::toolBarBorderColor());
|
2016-07-19 17:27:23 +02:00
|
|
|
painter->drawLine(borderRect.topLeft(), borderRect.topRight());
|
|
|
|
|
}
|
|
|
|
|
painter->restore();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PE_IndicatorToolBarSeparator:
|
2023-01-30 17:25:10 +01:00
|
|
|
if (!StyleHelper::isQDSTheme()) {
|
2016-03-02 18:25:42 +01:00
|
|
|
QRect separatorRect = rect;
|
|
|
|
|
separatorRect.setLeft(rect.width() / 2);
|
|
|
|
|
separatorRect.setWidth(1);
|
|
|
|
|
drawButtonSeparator(painter, separatorRect, false);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PE_IndicatorToolBarHandle:
|
|
|
|
|
{
|
|
|
|
|
bool horizontal = option->state & State_Horizontal;
|
|
|
|
|
painter->save();
|
|
|
|
|
QPainterPath path;
|
2011-06-04 20:47:29 +02:00
|
|
|
int x = option->rect.x() + (horizontal ? 2 : 6);
|
|
|
|
|
int y = option->rect.y() + (horizontal ? 6 : 2);
|
2008-12-02 12:01:29 +01:00
|
|
|
static const int RectHeight = 2;
|
|
|
|
|
if (horizontal) {
|
|
|
|
|
while (y < option->rect.height() - RectHeight - 6) {
|
|
|
|
|
path.moveTo(x, y);
|
|
|
|
|
path.addRect(x, y, RectHeight, RectHeight);
|
|
|
|
|
y += 6;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
while (x < option->rect.width() - RectHeight - 6) {
|
|
|
|
|
path.moveTo(x, y);
|
|
|
|
|
path.addRect(x, y, RectHeight, RectHeight);
|
|
|
|
|
x += 6;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
painter->setPen(Qt::NoPen);
|
2015-02-03 23:48:19 +02:00
|
|
|
QColor dark = StyleHelper::borderColor();
|
2021-07-09 14:32:41 +02:00
|
|
|
dark.setAlphaF(0.4f);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-02-03 23:48:19 +02:00
|
|
|
QColor light = StyleHelper::baseColor();
|
2021-07-09 14:32:41 +02:00
|
|
|
light.setAlphaF(0.4f);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
painter->fillPath(path, light);
|
|
|
|
|
painter->save();
|
|
|
|
|
painter->translate(1, 1);
|
|
|
|
|
painter->fillPath(path, dark);
|
|
|
|
|
painter->restore();
|
|
|
|
|
painter->translate(3, 3);
|
|
|
|
|
painter->fillPath(path, light);
|
|
|
|
|
painter->translate(1, 1);
|
|
|
|
|
painter->fillPath(path, dark);
|
|
|
|
|
painter->restore();
|
|
|
|
|
}
|
|
|
|
|
break;
|
2009-01-26 15:46:11 +01:00
|
|
|
case PE_IndicatorArrowUp:
|
|
|
|
|
case PE_IndicatorArrowDown:
|
|
|
|
|
case PE_IndicatorArrowRight:
|
|
|
|
|
case PE_IndicatorArrowLeft:
|
2019-03-11 12:28:41 +01:00
|
|
|
if (qobject_cast<const QMenu *>(widget)) // leave submenu arrow painting alone
|
|
|
|
|
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
|
|
|
|
else
|
2015-02-03 23:48:19 +02:00
|
|
|
StyleHelper::drawArrow(element, painter, option);
|
2009-01-26 15:46:11 +01:00
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
default:
|
2010-02-23 12:42:04 +01:00
|
|
|
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-20 14:06:19 +02:00
|
|
|
void ManhattanStyle::drawPrimitiveForQmlEditor(PrimitiveElement element,
|
|
|
|
|
const QStyleOption *option,
|
|
|
|
|
QPainter *painter,
|
|
|
|
|
const QWidget *widget) const
|
|
|
|
|
{
|
|
|
|
|
const auto mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option);
|
|
|
|
|
if (!mbi) {
|
|
|
|
|
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (element) {
|
|
|
|
|
case PE_IndicatorArrowUp:
|
|
|
|
|
case PE_IndicatorArrowDown:
|
|
|
|
|
{
|
|
|
|
|
QStyleOptionMenuItem item = *mbi;
|
|
|
|
|
item.palette = QPalette(Qt::white);
|
|
|
|
|
StyleHelper::drawMinimalArrow(element, painter, &item);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case PE_IndicatorArrowRight:
|
|
|
|
|
drawQmlEditorIcon(element, option, "cascadeIconRight", painter, widget);
|
|
|
|
|
break;
|
|
|
|
|
case PE_IndicatorArrowLeft:
|
|
|
|
|
drawQmlEditorIcon(element, option, "cascadeIconLeft", painter, widget);
|
|
|
|
|
break;
|
|
|
|
|
case PE_PanelButtonCommand:
|
|
|
|
|
break;
|
|
|
|
|
case PE_IndicatorMenuCheckMark:
|
|
|
|
|
drawQmlEditorIcon(element, option, "tickIcon", painter, widget);
|
|
|
|
|
break;
|
|
|
|
|
case PE_FrameMenu:
|
|
|
|
|
case PE_PanelMenu:
|
|
|
|
|
{
|
|
|
|
|
painter->save();
|
|
|
|
|
painter->setBrush(creatorTheme()->color(Theme::DSsubPanelBackground));
|
|
|
|
|
painter->setPen(Qt::NoPen);
|
|
|
|
|
painter->drawRect(option->rect);
|
|
|
|
|
painter->restore();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ManhattanStyle::drawControlForQmlEditor(ControlElement element,
|
|
|
|
|
const QStyleOption *option,
|
|
|
|
|
QPainter *painter,
|
|
|
|
|
const QWidget *widget) const
|
|
|
|
|
{
|
2023-01-30 17:25:10 +01:00
|
|
|
Q_UNUSED(element)
|
2023-01-20 14:06:19 +02:00
|
|
|
if (const auto mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
|
|
|
|
|
painter->save();
|
|
|
|
|
const int iconHeight = pixelMetric(QStyle::PM_SmallIconSize, option, widget);
|
|
|
|
|
const int horizontalSpacing = pixelMetric(QStyle::PM_LayoutHorizontalSpacing, option, widget);
|
|
|
|
|
const int iconWidth = iconHeight;
|
|
|
|
|
const bool isActive = mbi->state & State_Selected;
|
|
|
|
|
const bool isDisabled = !(mbi->state & State_Enabled);
|
|
|
|
|
const bool isCheckable = mbi->checkType != QStyleOptionMenuItem::NotCheckable;
|
|
|
|
|
const bool isChecked = isCheckable ? mbi->checked : false;
|
2023-01-31 13:29:19 +02:00
|
|
|
int startMargin = pixelMetric(QStyle::PM_LayoutLeftMargin, option, widget);
|
|
|
|
|
int endMargin = pixelMetric(QStyle::PM_LayoutRightMargin, option, widget);
|
2023-01-20 14:06:19 +02:00
|
|
|
int forwardX = 0;
|
|
|
|
|
|
2023-01-31 13:29:19 +02:00
|
|
|
if (option->direction == Qt::RightToLeft)
|
|
|
|
|
std::swap(startMargin, endMargin);
|
|
|
|
|
|
2023-01-20 14:06:19 +02:00
|
|
|
QStyleOptionMenuItem item = *mbi;
|
|
|
|
|
|
|
|
|
|
if (isActive) {
|
|
|
|
|
painter->fillRect(item.rect, creatorTheme()->color(Theme::DSinteraction));
|
|
|
|
|
}
|
2023-01-31 13:29:19 +02:00
|
|
|
forwardX += startMargin;
|
2023-01-20 14:06:19 +02:00
|
|
|
|
|
|
|
|
if (item.menuItemType == QStyleOptionMenuItem::Separator) {
|
|
|
|
|
int commonHeight = item.rect.center().y();
|
|
|
|
|
int additionalMargin = forwardX /*hmargin*/;
|
|
|
|
|
QLineF separatorLine (item.rect.left() + additionalMargin,
|
|
|
|
|
commonHeight,
|
|
|
|
|
item.rect.right() - additionalMargin,
|
|
|
|
|
commonHeight);
|
|
|
|
|
|
|
|
|
|
painter->setPen(creatorTheme()->color(Theme::DSstateSeparatorColor));
|
|
|
|
|
painter->drawLine(separatorLine);
|
|
|
|
|
item.text.clear();
|
|
|
|
|
painter->restore();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QPixmap iconPixmap;
|
|
|
|
|
QIcon::Mode mode = isDisabled ? QIcon::Disabled : ((isActive) ? QIcon::Active : QIcon::Normal);
|
|
|
|
|
QIcon::State state = isChecked ? QIcon::On : QIcon::Off;
|
|
|
|
|
QColor themePenColor = qmlEditorTextColor(!isDisabled, isActive, isChecked);
|
|
|
|
|
|
|
|
|
|
if (!item.icon.isNull()) {
|
|
|
|
|
iconPixmap = item.icon.pixmap(QSize(iconHeight, iconHeight), mode, state);
|
|
|
|
|
} else if (isCheckable) {
|
|
|
|
|
iconPixmap = QPixmap(iconHeight, iconHeight);
|
|
|
|
|
iconPixmap.fill(Qt::transparent);
|
|
|
|
|
|
|
|
|
|
if (item.checked) {
|
|
|
|
|
QStyleOptionMenuItem so = item;
|
|
|
|
|
so.rect = iconPixmap.rect();
|
|
|
|
|
QPainter dPainter(&iconPixmap);
|
|
|
|
|
dPainter.setPen(themePenColor);
|
|
|
|
|
drawPrimitive(PE_IndicatorMenuCheckMark, &so, &dPainter, widget);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!iconPixmap.isNull()) {
|
|
|
|
|
QRect vCheckRect = visualRect(item.direction,
|
|
|
|
|
item.rect,
|
|
|
|
|
QRect(item.rect.x() + forwardX,
|
|
|
|
|
item.rect.y(),
|
|
|
|
|
iconWidth,
|
|
|
|
|
item.rect.height()));
|
|
|
|
|
|
|
|
|
|
QRect pmr(QPoint(0, 0), iconPixmap.deviceIndependentSize().toSize());
|
|
|
|
|
pmr.moveCenter(vCheckRect.center());
|
|
|
|
|
painter->setPen(themePenColor);
|
|
|
|
|
painter->drawPixmap(pmr.topLeft(), iconPixmap);
|
|
|
|
|
|
|
|
|
|
item.checkType = QStyleOptionMenuItem::NotCheckable;
|
|
|
|
|
item.checked = false;
|
|
|
|
|
item.icon = {};
|
|
|
|
|
}
|
|
|
|
|
if (item.menuHasCheckableItems || item.maxIconWidth > 0) {
|
|
|
|
|
forwardX += iconWidth + horizontalSpacing;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString shortcutText;
|
|
|
|
|
int tabIndex = item.text.indexOf("\t");
|
|
|
|
|
if (tabIndex > -1) {
|
|
|
|
|
shortcutText = item.text.mid(tabIndex + 1);
|
|
|
|
|
item.text = item.text.left(tabIndex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item.text.size()) {
|
|
|
|
|
painter->save();
|
|
|
|
|
|
|
|
|
|
QRect vTextRect = visualRect(item.direction,
|
|
|
|
|
item.rect,
|
|
|
|
|
item.rect.adjusted(forwardX, 0 , 0 , 0));
|
|
|
|
|
|
|
|
|
|
Qt::Alignment alignmentFlags = item.direction == Qt::LeftToRight ? Qt::AlignLeft
|
|
|
|
|
: Qt::AlignRight;
|
|
|
|
|
alignmentFlags |= Qt::AlignVCenter;
|
|
|
|
|
|
|
|
|
|
int textFlags = Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
|
|
|
|
|
if (!proxy()->styleHint(SH_UnderlineShortcut, &item, widget))
|
|
|
|
|
textFlags |= Qt::TextHideMnemonic;
|
|
|
|
|
textFlags |= alignmentFlags;
|
|
|
|
|
|
|
|
|
|
painter->setPen(themePenColor);
|
|
|
|
|
painter->drawText(vTextRect, textFlags, item.text);
|
|
|
|
|
painter->restore();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item.menuItemType == QStyleOptionMenuItem::SubMenu) {
|
|
|
|
|
PrimitiveElement dropDirElement = item.direction == Qt::LeftToRight ? PE_IndicatorArrowRight
|
|
|
|
|
: PE_IndicatorArrowLeft;
|
|
|
|
|
|
|
|
|
|
QSize elSize(iconHeight, iconHeight);
|
2023-01-31 13:29:19 +02:00
|
|
|
int xOffset = iconHeight + endMargin;
|
2023-01-20 14:06:19 +02:00
|
|
|
int yOffset = (item.rect.height() - iconHeight) / 2;
|
|
|
|
|
QRect dropRect(item.rect.topRight(), elSize);
|
|
|
|
|
dropRect.adjust(-xOffset, yOffset, -xOffset, yOffset);
|
|
|
|
|
|
|
|
|
|
QStyleOptionMenuItem so = item;
|
|
|
|
|
so.rect = visualRect(item.direction,
|
|
|
|
|
item.rect,
|
|
|
|
|
dropRect);
|
|
|
|
|
|
|
|
|
|
drawPrimitive(dropDirElement, &so, painter, widget);
|
|
|
|
|
} else if (!shortcutText.isEmpty()) {
|
|
|
|
|
QPixmap pix = ManhattanShortcut(&item, shortcutText).getPixmap();
|
|
|
|
|
|
|
|
|
|
if (pix.width()) {
|
2023-01-31 13:29:19 +02:00
|
|
|
int xOffset = pix.width() + (iconHeight / 2) + endMargin;
|
2023-01-20 14:06:19 +02:00
|
|
|
QRect shortcutRect = item.rect.translated({item.rect.width() - xOffset, 0});
|
|
|
|
|
shortcutRect.setSize({pix.width(), item.rect.height()});
|
|
|
|
|
shortcutRect = visualRect(item.direction,
|
|
|
|
|
item.rect,
|
|
|
|
|
shortcutRect);
|
|
|
|
|
drawItemPixmap(painter,
|
|
|
|
|
shortcutRect,
|
|
|
|
|
Qt::AlignRight | Qt::AlignVCenter,
|
|
|
|
|
pix);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
painter->restore();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ManhattanStyle::drawQmlEditorIcon(PrimitiveElement element,
|
|
|
|
|
const QStyleOption *option,
|
|
|
|
|
const char *propertyName,
|
|
|
|
|
QPainter *painter,
|
|
|
|
|
const QWidget *widget) const
|
|
|
|
|
{
|
|
|
|
|
if (option->styleObject && option->styleObject->property(propertyName).isValid()) {
|
|
|
|
|
const auto mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option);
|
|
|
|
|
if (mbi) {
|
|
|
|
|
const bool checkable = mbi->checkType != QStyleOptionMenuItem::NotCheckable;
|
|
|
|
|
const bool isDisabled = !(mbi->state & State_Enabled);
|
|
|
|
|
const bool isActive = mbi->state & State_Selected;
|
|
|
|
|
QIcon icon = mbi->styleObject->property(propertyName).value<QIcon>();
|
|
|
|
|
QIcon::Mode mode = isDisabled ? QIcon::Disabled : ((isActive) ? QIcon::Active : QIcon::Normal);
|
|
|
|
|
QIcon::State state = (checkable && mbi->checked) ? QIcon::On : QIcon::Off;
|
|
|
|
|
QPixmap pix = icon.pixmap(option->rect.size(), mode, state);
|
|
|
|
|
drawItemPixmap(painter, option->rect, Qt::AlignCenter, pix);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
QProxyStyle::drawPrimitive(element, option, painter, widget);
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void ManhattanStyle::drawControl(ControlElement element, const QStyleOption *option,
|
|
|
|
|
QPainter *painter, const QWidget *widget) const
|
|
|
|
|
{
|
2017-04-14 12:06:24 +02:00
|
|
|
if (!panelWidget(widget) && !qobject_cast<const QMenu *>(widget)) {
|
|
|
|
|
QProxyStyle::drawControl(element, option, painter, widget);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
switch (element) {
|
2015-03-21 13:13:59 +01:00
|
|
|
case CE_MenuItem:
|
|
|
|
|
painter->save();
|
2018-07-21 21:11:46 +02:00
|
|
|
if (const auto mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
|
2015-03-21 13:13:59 +01:00
|
|
|
const bool enabled = mbi->state & State_Enabled;
|
|
|
|
|
QStyleOptionMenuItem item = *mbi;
|
|
|
|
|
item.rect = mbi->rect;
|
|
|
|
|
const QColor color = creatorTheme()->color(enabled
|
|
|
|
|
? Theme::MenuItemTextColorNormal
|
|
|
|
|
: Theme::MenuItemTextColorDisabled);
|
|
|
|
|
if (color.isValid()) {
|
|
|
|
|
QPalette pal = mbi->palette;
|
|
|
|
|
pal.setBrush(QPalette::Text, color);
|
|
|
|
|
item.palette = pal;
|
|
|
|
|
}
|
2023-01-20 14:06:19 +02:00
|
|
|
|
|
|
|
|
if (isQmlEditorMenu(widget))
|
|
|
|
|
drawControlForQmlEditor(element, &item, painter, widget);
|
|
|
|
|
else
|
|
|
|
|
QProxyStyle::drawControl(element, &item, painter, widget);
|
2015-03-21 13:13:59 +01:00
|
|
|
}
|
|
|
|
|
painter->restore();
|
|
|
|
|
break;
|
|
|
|
|
|
2012-10-19 13:13:57 +02:00
|
|
|
case CE_MenuBarItem:
|
|
|
|
|
painter->save();
|
2018-07-21 21:11:46 +02:00
|
|
|
if (const auto mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
|
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>
2014-10-14 19:09:48 +02:00
|
|
|
const bool act = mbi->state & (State_Sunken | State_Selected);
|
|
|
|
|
const bool dis = !(mbi->state & State_Enabled);
|
|
|
|
|
|
2016-03-13 01:24:07 +01:00
|
|
|
if (creatorTheme()->flag(Theme::FlatMenuBar))
|
2016-03-21 12:48:06 +01:00
|
|
|
painter->fillRect(option->rect, StyleHelper::baseColor());
|
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>
2014-10-14 19:09:48 +02:00
|
|
|
else
|
2015-02-03 23:48:19 +02:00
|
|
|
StyleHelper::menuGradient(painter, option->rect, option->rect);
|
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>
2014-10-14 19:09:48 +02:00
|
|
|
|
2012-10-19 13:13:57 +02:00
|
|
|
QStyleOptionMenuItem item = *mbi;
|
|
|
|
|
item.rect = mbi->rect;
|
|
|
|
|
QPalette pal = mbi->palette;
|
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>
2014-10-14 19:09:48 +02:00
|
|
|
pal.setBrush(QPalette::ButtonText, dis
|
|
|
|
|
? creatorTheme()->color(Theme::MenuBarItemTextColorDisabled)
|
|
|
|
|
: creatorTheme()->color(Theme::MenuBarItemTextColorNormal));
|
2012-10-19 13:13:57 +02:00
|
|
|
item.palette = pal;
|
|
|
|
|
QCommonStyle::drawControl(element, &item, painter, widget);
|
|
|
|
|
|
|
|
|
|
if (act) {
|
|
|
|
|
// Fill|
|
2016-06-17 19:00:59 +02:00
|
|
|
const QColor fillColor = StyleHelper::alphaBlendedColors(
|
|
|
|
|
StyleHelper::baseColor(), creatorTheme()->color(Theme::FancyToolButtonHoverColor));
|
|
|
|
|
painter->fillRect(option->rect, fillColor);
|
2012-10-19 13:13:57 +02:00
|
|
|
|
|
|
|
|
QPalette pal = mbi->palette;
|
|
|
|
|
uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
|
|
|
|
|
if (!styleHint(SH_UnderlineShortcut, mbi, widget))
|
|
|
|
|
alignment |= Qt::TextHideMnemonic;
|
2016-06-17 19:00:59 +02:00
|
|
|
pal.setBrush(QPalette::Text, creatorTheme()->color(dis
|
|
|
|
|
? Theme::IconsDisabledColor
|
|
|
|
|
: Theme::PanelTextColorLight));
|
|
|
|
|
drawItemText(painter, item.rect, alignment, pal, !dis, mbi->text, QPalette::Text);
|
2012-10-19 13:13:57 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
painter->restore();
|
|
|
|
|
break;
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
case CE_ComboBoxLabel:
|
2018-07-21 21:11:46 +02:00
|
|
|
if (const auto cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
|
2008-12-02 12:01:29 +01:00
|
|
|
if (panelWidget(widget)) {
|
2010-03-09 11:14:19 +01:00
|
|
|
painter->save();
|
2008-12-02 12:01:29 +01:00
|
|
|
QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
|
|
|
|
|
QPalette customPal = cb->palette;
|
2023-05-09 13:20:04 +02:00
|
|
|
const bool drawIcon =
|
|
|
|
|
!(widget && widget->property(StyleHelper::C_HIDE_ICON).toBool());
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-12-09 16:45:49 +01:00
|
|
|
if (!cb->currentIcon.isNull() && drawIcon) {
|
2008-12-02 12:01:29 +01:00
|
|
|
QIcon::Mode mode = cb->state & State_Enabled ? QIcon::Normal
|
|
|
|
|
: QIcon::Disabled;
|
|
|
|
|
QPixmap pixmap = cb->currentIcon.pixmap(cb->iconSize, mode);
|
|
|
|
|
QRect iconRect(editRect);
|
|
|
|
|
iconRect.setWidth(cb->iconSize.width() + 4);
|
|
|
|
|
iconRect = alignedRect(cb->direction,
|
|
|
|
|
Qt::AlignLeft | Qt::AlignVCenter,
|
|
|
|
|
iconRect.size(), editRect);
|
|
|
|
|
if (cb->editable)
|
|
|
|
|
painter->fillRect(iconRect, customPal.brush(QPalette::Base));
|
|
|
|
|
drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
|
|
|
|
|
|
|
|
|
|
if (cb->direction == Qt::RightToLeft)
|
|
|
|
|
editRect.translate(-4 - cb->iconSize.width(), 0);
|
|
|
|
|
else
|
|
|
|
|
editRect.translate(cb->iconSize.width() + 4, 0);
|
2009-02-23 16:25:53 +01:00
|
|
|
|
|
|
|
|
// Reserve some space for the down-arrow
|
|
|
|
|
editRect.adjust(0, 0, -13, 0);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2022-11-23 11:07:42 +01:00
|
|
|
Qt::TextElideMode elideMode = Qt::ElideRight;
|
2023-05-09 13:20:04 +02:00
|
|
|
if (widget && widget->dynamicPropertyNames().contains(StyleHelper::C_ELIDE_MODE))
|
|
|
|
|
elideMode = widget->property(StyleHelper::C_ELIDE_MODE)
|
|
|
|
|
.value<Qt::TextElideMode>();
|
2022-11-23 11:07:42 +01:00
|
|
|
|
2012-10-11 11:18:26 +04:00
|
|
|
QLatin1Char asterisk('*');
|
|
|
|
|
int elideWidth = editRect.width();
|
|
|
|
|
|
2022-11-23 11:07:42 +01:00
|
|
|
bool notElideAsterisk = elideMode == Qt::ElideRight && widget
|
2023-05-09 13:20:04 +02:00
|
|
|
&& widget->property(StyleHelper::C_NOT_ELIDE_ASTERISK).toBool()
|
2012-10-11 11:18:26 +04:00
|
|
|
&& cb->currentText.endsWith(asterisk)
|
2022-11-23 11:07:42 +01:00
|
|
|
&& option->fontMetrics.horizontalAdvance(cb->currentText)
|
|
|
|
|
> elideWidth;
|
2012-10-11 11:18:26 +04:00
|
|
|
|
|
|
|
|
QString text;
|
|
|
|
|
if (notElideAsterisk) {
|
2019-02-11 10:32:46 +01:00
|
|
|
elideWidth -= option->fontMetrics.horizontalAdvance(asterisk);
|
2012-10-11 11:18:26 +04:00
|
|
|
text = asterisk;
|
|
|
|
|
}
|
2022-08-26 22:23:23 +09:00
|
|
|
text.prepend(option->fontMetrics.elidedText(cb->currentText, elideMode, elideWidth));
|
2012-10-11 11:18:26 +04:00
|
|
|
|
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>
2014-10-14 19:09:48 +02:00
|
|
|
if (creatorTheme()->flag(Theme::ComboBoxDrawTextShadow)
|
|
|
|
|
&& (option->state & State_Enabled))
|
|
|
|
|
{
|
2016-03-29 17:36:49 +02:00
|
|
|
painter->setPen(StyleHelper::toolBarDropShadowColor());
|
2010-04-28 12:32:20 +02:00
|
|
|
painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text);
|
2010-03-12 13:16:18 +01:00
|
|
|
}
|
2018-01-31 16:42:41 +01:00
|
|
|
painter->setPen((option->state & State_Enabled)
|
2019-08-29 11:40:38 +02:00
|
|
|
? option->palette.color(QPalette::WindowText)
|
2018-01-31 16:42:41 +01:00
|
|
|
: creatorTheme()->color(Theme::IconsDisabledColor));
|
2010-04-28 12:32:20 +02:00
|
|
|
painter->drawText(editRect.adjusted(1, 0, -1, 0), Qt::AlignLeft | Qt::AlignVCenter, text);
|
2010-03-09 11:14:19 +01:00
|
|
|
|
|
|
|
|
painter->restore();
|
2008-12-02 12:01:29 +01:00
|
|
|
} else {
|
2010-02-23 12:42:04 +01:00
|
|
|
QProxyStyle::drawControl(element, option, painter, widget);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case CE_SizeGrip: {
|
|
|
|
|
painter->save();
|
|
|
|
|
QColor dark = Qt::white;
|
2021-07-09 14:32:41 +02:00
|
|
|
dark.setAlphaF(0.1f);
|
2008-12-02 12:01:29 +01:00
|
|
|
int x, y, w, h;
|
|
|
|
|
option->rect.getRect(&x, &y, &w, &h);
|
|
|
|
|
int sw = qMin(h, w);
|
|
|
|
|
if (h > w)
|
|
|
|
|
painter->translate(0, h - w);
|
|
|
|
|
else
|
|
|
|
|
painter->translate(w - h, 0);
|
|
|
|
|
int sx = x;
|
|
|
|
|
int sy = y;
|
|
|
|
|
int s = 4;
|
|
|
|
|
painter->setPen(dark);
|
|
|
|
|
if (option->direction == Qt::RightToLeft) {
|
|
|
|
|
sx = x + sw;
|
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
|
painter->drawLine(x, sy, sx, sw);
|
|
|
|
|
sx -= s;
|
|
|
|
|
sy += s;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
|
painter->drawLine(sx, sw, sw, sy);
|
|
|
|
|
sx += s;
|
|
|
|
|
sy += s;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
painter->restore();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2012-10-19 13:13:57 +02:00
|
|
|
case CE_MenuBarEmptyArea: {
|
2016-07-04 13:57:19 +02:00
|
|
|
if (creatorTheme()->flag(Theme::FlatMenuBar))
|
2016-03-21 12:48:06 +01:00
|
|
|
painter->fillRect(option->rect, StyleHelper::baseColor());
|
2016-07-04 13:57:19 +02:00
|
|
|
else
|
|
|
|
|
StyleHelper::menuGradient(painter, option->rect, option->rect);
|
|
|
|
|
|
|
|
|
|
painter->save();
|
2016-07-19 18:24:25 +02:00
|
|
|
painter->setPen(StyleHelper::toolBarBorderColor());
|
2016-07-04 13:57:19 +02:00
|
|
|
painter->drawLine(option->rect.bottomLeft() + QPointF(0.5, 0.5),
|
|
|
|
|
option->rect.bottomRight() + QPointF(0.5, 0.5));
|
|
|
|
|
painter->restore();
|
2012-10-19 13:13:57 +02:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
2023-01-20 14:06:19 +02:00
|
|
|
case CE_MenuEmptyArea:
|
|
|
|
|
if (isQmlEditorMenu(widget))
|
|
|
|
|
drawPrimitive(PE_PanelMenu, option, painter, widget);
|
|
|
|
|
else
|
|
|
|
|
QProxyStyle::drawControl(element, option, painter, widget);
|
|
|
|
|
|
|
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
case CE_ToolBar:
|
|
|
|
|
{
|
|
|
|
|
QRect rect = option->rect;
|
2015-10-20 14:58:28 +02:00
|
|
|
const QRectF borderRect = QRectF(rect).adjusted(0.5, 0.5, -0.5, -0.5);
|
2010-02-19 09:54:29 +01:00
|
|
|
bool horizontal = option->state & State_Horizontal;
|
2010-03-19 17:47:45 +01:00
|
|
|
|
|
|
|
|
// Map offset for global window gradient
|
|
|
|
|
QRect gradientSpan;
|
2014-05-06 00:04:22 +03:00
|
|
|
if (widget) {
|
|
|
|
|
QPoint offset = widget->window()->mapToGlobal(option->rect.topLeft()) -
|
|
|
|
|
widget->mapToGlobal(option->rect.topLeft());
|
2010-03-19 17:47:45 +01:00
|
|
|
gradientSpan = QRect(offset, widget->window()->size());
|
2014-05-06 00:04:22 +03:00
|
|
|
}
|
2010-03-19 17:47:45 +01:00
|
|
|
|
|
|
|
|
bool drawLightColored = lightColored(widget);
|
2015-06-30 22:31:49 +03:00
|
|
|
// draws the background of the 'Type hierarchy', 'Projects' headers
|
2016-06-15 17:41:33 +02:00
|
|
|
if (creatorTheme()->flag(Theme::FlatToolBars))
|
2023-01-30 17:25:10 +01:00
|
|
|
painter->fillRect(rect, StyleHelper::toolbarBaseColor(drawLightColored));
|
2015-06-30 22:31:49 +03:00
|
|
|
else if (horizontal)
|
|
|
|
|
StyleHelper::horizontalGradient(painter, gradientSpan, rect, drawLightColored);
|
|
|
|
|
else
|
|
|
|
|
StyleHelper::verticalGradient(painter, gradientSpan, rect, drawLightColored);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2016-03-04 11:08:46 +01:00
|
|
|
if (creatorTheme()->flag(Theme::DrawToolBarHighlights)) {
|
|
|
|
|
if (!drawLightColored)
|
2016-07-19 18:24:25 +02:00
|
|
|
painter->setPen(StyleHelper::toolBarBorderColor());
|
2016-03-04 11:08:46 +01:00
|
|
|
else
|
|
|
|
|
painter->setPen(QColor(0x888888));
|
|
|
|
|
|
|
|
|
|
if (horizontal) {
|
|
|
|
|
// Note: This is a hack to determine if the
|
|
|
|
|
// toolbar should draw the top or bottom outline
|
|
|
|
|
// (needed for the find toolbar for instance)
|
2016-06-15 17:41:33 +02:00
|
|
|
const QColor hightLight = creatorTheme()->flag(Theme::FlatToolBars)
|
|
|
|
|
? creatorTheme()->color(Theme::FancyToolBarSeparatorColor)
|
|
|
|
|
: StyleHelper::sidebarHighlight();
|
2016-03-04 11:08:46 +01:00
|
|
|
const QColor borderColor = drawLightColored
|
|
|
|
|
? QColor(255, 255, 255, 180) : hightLight;
|
2023-05-09 13:20:04 +02:00
|
|
|
if (widget && widget->property(StyleHelper::C_TOP_BORDER).toBool()) {
|
2016-03-04 11:08:46 +01:00
|
|
|
painter->drawLine(borderRect.topLeft(), borderRect.topRight());
|
|
|
|
|
painter->setPen(borderColor);
|
|
|
|
|
painter->drawLine(borderRect.topLeft() + QPointF(0, 1), borderRect.topRight() + QPointF(0, 1));
|
|
|
|
|
} else {
|
|
|
|
|
painter->drawLine(borderRect.bottomLeft(), borderRect.bottomRight());
|
|
|
|
|
painter->setPen(borderColor);
|
|
|
|
|
painter->drawLine(borderRect.topLeft(), borderRect.topRight());
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
} else {
|
2016-03-04 11:08:46 +01:00
|
|
|
painter->drawLine(borderRect.topLeft(), borderRect.bottomLeft());
|
|
|
|
|
painter->drawLine(borderRect.topRight(), borderRect.bottomRight());
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
}
|
2016-07-19 17:27:23 +02:00
|
|
|
if (creatorTheme()->flag(Theme::DrawToolBarBorders)) {
|
2016-07-19 18:24:25 +02:00
|
|
|
painter->setPen(StyleHelper::toolBarBorderColor());
|
2023-05-09 13:20:04 +02:00
|
|
|
if (widget && widget->property(StyleHelper::C_TOP_BORDER).toBool())
|
2016-07-19 17:27:23 +02:00
|
|
|
painter->drawLine(borderRect.topLeft(), borderRect.topRight());
|
|
|
|
|
else
|
|
|
|
|
painter->drawLine(borderRect.bottomLeft(), borderRect.bottomRight());
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
break;
|
2020-03-10 13:25:50 +01:00
|
|
|
case CE_ToolButtonLabel:
|
|
|
|
|
// Directly use QCommonStyle to circumvent funny painting in QMacStyle
|
|
|
|
|
// which ignores the palette and adds an alpha
|
|
|
|
|
QCommonStyle::drawControl(element, option, painter, widget);
|
|
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
default:
|
2010-02-23 12:42:04 +01:00
|
|
|
QProxyStyle::drawControl(element, option, painter, widget);
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
|
|
|
|
|
QPainter *painter, const QWidget *widget) const
|
|
|
|
|
{
|
|
|
|
|
if (!panelWidget(widget))
|
2023-02-20 19:02:43 +02:00
|
|
|
return QProxyStyle::drawComplexControl(control, option, painter, widget);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
QRect rect = option->rect;
|
|
|
|
|
switch (control) {
|
|
|
|
|
case CC_ToolButton:
|
2018-07-21 21:11:46 +02:00
|
|
|
if (const auto toolbutton = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
|
2011-12-05 13:28:56 +01:00
|
|
|
bool reverse = option->direction == Qt::RightToLeft;
|
2023-05-09 13:20:04 +02:00
|
|
|
const bool drawborder =
|
|
|
|
|
(widget && widget->property(StyleHelper::C_SHOW_BORDER).toBool());
|
2011-12-05 13:28:56 +01:00
|
|
|
|
|
|
|
|
if (drawborder)
|
|
|
|
|
drawButtonSeparator(painter, rect, reverse);
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
QRect button, menuarea;
|
|
|
|
|
button = subControlRect(control, toolbutton, SC_ToolButton, widget);
|
|
|
|
|
menuarea = subControlRect(control, toolbutton, SC_ToolButtonMenu, widget);
|
|
|
|
|
|
|
|
|
|
State bflags = toolbutton->state;
|
|
|
|
|
if (bflags & State_AutoRaise) {
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
if (!(bflags & State_MouseOver))
|
2008-12-02 12:01:29 +01:00
|
|
|
bflags &= ~State_Raised;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
State mflags = bflags;
|
2009-01-05 10:42:42 +01:00
|
|
|
if (toolbutton->state & State_Sunken) {
|
|
|
|
|
if (toolbutton->activeSubControls & SC_ToolButton)
|
|
|
|
|
bflags |= State_Sunken;
|
|
|
|
|
if (toolbutton->activeSubControls & SC_ToolButtonMenu)
|
|
|
|
|
mflags |= State_Sunken;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
QStyleOption tool(0);
|
|
|
|
|
tool.palette = toolbutton->palette;
|
|
|
|
|
if (toolbutton->subControls & SC_ToolButton) {
|
2009-07-17 13:13:12 +02:00
|
|
|
tool.rect = button;
|
|
|
|
|
tool.state = bflags;
|
|
|
|
|
drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStyleOptionToolButton label = *toolbutton;
|
2010-02-19 09:54:29 +01:00
|
|
|
|
|
|
|
|
label.palette = panelPalette(option->palette, lightColored(widget));
|
2023-05-09 13:20:04 +02:00
|
|
|
if (widget && widget->property(StyleHelper::C_HIGHLIGHT_WIDGET).toBool()) {
|
2020-01-22 17:58:24 +01:00
|
|
|
label.palette.setColor(QPalette::ButtonText,
|
|
|
|
|
creatorTheme()->color(Theme::IconsWarningToolBarColor));
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
int fw = pixelMetric(PM_DefaultFrameWidth, option, widget);
|
|
|
|
|
label.rect = button.adjusted(fw, fw, -fw, -fw);
|
2010-02-19 09:54:29 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
drawControl(CE_ToolButtonLabel, &label, painter, widget);
|
|
|
|
|
|
|
|
|
|
if (toolbutton->subControls & SC_ToolButtonMenu) {
|
|
|
|
|
tool.state = mflags;
|
|
|
|
|
tool.rect = menuarea.adjusted(1, 1, -1, -1);
|
|
|
|
|
if (mflags & (State_Sunken | State_On | State_Raised)) {
|
|
|
|
|
painter->setPen(Qt::gray);
|
2016-04-07 16:28:03 +02:00
|
|
|
const QRectF lineRect = QRectF(tool.rect).adjusted(-0.5, 2.5, 0, -2.5);
|
|
|
|
|
painter->drawLine(lineRect.topLeft(), lineRect.bottomLeft());
|
2008-12-02 12:01:29 +01:00
|
|
|
if (mflags & (State_Sunken)) {
|
|
|
|
|
QColor shade(0, 0, 0, 50);
|
|
|
|
|
painter->fillRect(tool.rect.adjusted(0, -1, 1, 1), shade);
|
2015-02-03 23:48:19 +02:00
|
|
|
} else if (!HostOsInfo::isMacHost() && (mflags & State_MouseOver)) {
|
2008-12-02 12:01:29 +01:00
|
|
|
QColor shade(255, 255, 255, 50);
|
|
|
|
|
painter->fillRect(tool.rect.adjusted(0, -1, 1, 1), shade);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
tool.rect = tool.rect.adjusted(2, 2, -2, -2);
|
|
|
|
|
drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget);
|
2010-04-28 16:09:48 +02:00
|
|
|
} else if (toolbutton->features & QStyleOptionToolButton::HasMenu
|
2023-05-09 13:20:04 +02:00
|
|
|
&& widget && !widget->property(StyleHelper::C_NO_ARROW).toBool()) {
|
2009-01-02 09:33:47 +01:00
|
|
|
int arrowSize = 6;
|
2008-12-02 12:01:29 +01:00
|
|
|
QRect ir = toolbutton->rect.adjusted(1, 1, -1, -1);
|
|
|
|
|
QStyleOptionToolButton newBtn = *toolbutton;
|
|
|
|
|
newBtn.palette = panelPalette(option->palette);
|
2009-01-02 09:33:47 +01:00
|
|
|
newBtn.rect = QRect(ir.right() - arrowSize - 1,
|
|
|
|
|
ir.height() - arrowSize - 2, arrowSize, arrowSize);
|
2009-01-26 15:46:11 +01:00
|
|
|
drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case CC_ComboBox:
|
2018-07-21 21:11:46 +02:00
|
|
|
if (const auto cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
|
2008-12-02 12:01:29 +01:00
|
|
|
painter->save();
|
2009-02-23 16:25:53 +01:00
|
|
|
bool isEmpty = cb->currentText.isEmpty() && cb->currentIcon.isNull();
|
|
|
|
|
bool reverse = option->direction == Qt::RightToLeft;
|
2023-05-09 13:20:04 +02:00
|
|
|
const bool drawborder =
|
|
|
|
|
!(widget && widget->property(StyleHelper::C_HIDE_BORDER).toBool());
|
|
|
|
|
const bool drawleftborder =
|
|
|
|
|
(widget && widget->property(StyleHelper::C_DRAW_LEFT_BORDER).toBool());
|
|
|
|
|
const bool alignarrow =
|
|
|
|
|
!(widget && widget->property(StyleHelper::C_ALIGN_ARROW).toBool());
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-07-14 16:19:40 +02:00
|
|
|
if (drawborder) {
|
2011-12-05 13:28:56 +01:00
|
|
|
drawButtonSeparator(painter, rect, reverse);
|
2014-07-14 16:19:40 +02:00
|
|
|
if (drawleftborder)
|
|
|
|
|
drawButtonSeparator(painter, rect.adjusted(0, 0, -rect.width() + 2, 0), reverse);
|
|
|
|
|
}
|
2011-12-05 13:28:56 +01:00
|
|
|
|
2009-02-10 15:09:24 +01:00
|
|
|
QStyleOption toolbutton = *option;
|
2009-02-23 16:25:53 +01:00
|
|
|
if (isEmpty)
|
|
|
|
|
toolbutton.state &= ~(State_Enabled | State_Sunken);
|
2009-02-23 17:11:41 +01:00
|
|
|
painter->save();
|
2014-07-14 16:19:40 +02:00
|
|
|
if (drawborder) {
|
|
|
|
|
int leftClipAdjust = 0;
|
|
|
|
|
if (drawleftborder)
|
|
|
|
|
leftClipAdjust = 2;
|
|
|
|
|
painter->setClipRect(toolbutton.rect.adjusted(leftClipAdjust, 0, -2, 0));
|
|
|
|
|
}
|
2009-02-10 15:09:24 +01:00
|
|
|
drawPrimitive(PE_PanelButtonTool, &toolbutton, painter, widget);
|
2009-02-23 17:11:41 +01:00
|
|
|
painter->restore();
|
2008-12-02 12:01:29 +01:00
|
|
|
// Draw arrow
|
2009-01-26 18:10:53 +01:00
|
|
|
int menuButtonWidth = 12;
|
2008-12-02 12:01:29 +01:00
|
|
|
int left = !reverse ? rect.right() - menuButtonWidth : rect.left();
|
|
|
|
|
int right = !reverse ? rect.right() : rect.left() + menuButtonWidth;
|
2009-02-23 16:25:53 +01:00
|
|
|
QRect arrowRect((left + right) / 2 + (reverse ? 6 : -6), rect.center().y() - 3, 9, 9);
|
2010-02-24 19:23:40 +01:00
|
|
|
|
|
|
|
|
if (!alignarrow) {
|
2019-02-11 10:32:46 +01:00
|
|
|
int labelwidth = option->fontMetrics.horizontalAdvance(cb->currentText);
|
2010-04-28 12:32:20 +02:00
|
|
|
if (reverse)
|
|
|
|
|
arrowRect.moveLeft(qMax(rect.width() - labelwidth - menuButtonWidth - 2, 4));
|
|
|
|
|
else
|
|
|
|
|
arrowRect.moveLeft(qMin(labelwidth + menuButtonWidth - 2, rect.width() - menuButtonWidth - 4));
|
2010-02-24 19:23:40 +01:00
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
if (option->state & State_On)
|
2010-02-23 12:42:04 +01:00
|
|
|
arrowRect.translate(QProxyStyle::pixelMetric(PM_ButtonShiftHorizontal, option, widget),
|
|
|
|
|
QProxyStyle::pixelMetric(PM_ButtonShiftVertical, option, widget));
|
2009-02-23 16:25:53 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
QStyleOption arrowOpt = *option;
|
|
|
|
|
arrowOpt.rect = arrowRect;
|
2009-02-23 16:25:53 +01:00
|
|
|
if (isEmpty)
|
|
|
|
|
arrowOpt.state &= ~(State_Enabled | State_Sunken);
|
|
|
|
|
|
2009-02-10 15:09:24 +01:00
|
|
|
if (styleHint(SH_ComboBox_Popup, option, widget)) {
|
|
|
|
|
arrowOpt.rect.translate(0, -3);
|
|
|
|
|
drawPrimitive(PE_IndicatorArrowUp, &arrowOpt, painter, widget);
|
|
|
|
|
arrowOpt.rect.translate(0, 6);
|
|
|
|
|
drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget);
|
|
|
|
|
} else {
|
|
|
|
|
drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget);
|
|
|
|
|
}
|
2010-03-01 14:51:48 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
painter->restore();
|
|
|
|
|
}
|
|
|
|
|
break;
|
2023-02-16 17:04:53 +02:00
|
|
|
case CC_Slider:
|
2023-02-20 21:47:13 +02:00
|
|
|
if (const auto *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
|
2023-02-16 17:04:53 +02:00
|
|
|
QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
|
|
|
|
|
QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
|
|
|
|
|
|
|
|
|
|
bool horizontal = slider->orientation == Qt::Horizontal;
|
|
|
|
|
bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
|
|
|
|
|
bool ticksBelow = slider->tickPosition & QSlider::TicksBelow;
|
|
|
|
|
bool enabled = option->state & QStyle::State_Enabled;
|
2023-02-20 19:02:43 +02:00
|
|
|
bool grooveHover = slider->activeSubControls & SC_SliderGroove;
|
|
|
|
|
bool handleHover = slider->activeSubControls & SC_SliderHandle;
|
|
|
|
|
bool interaction = option->state & State_Sunken;
|
2023-02-16 17:04:53 +02:00
|
|
|
bool activeFocus = option->state & State_HasFocus && option->state & State_KeyboardFocusChange;
|
|
|
|
|
|
|
|
|
|
int sliderPaintingOffset = horizontal
|
|
|
|
|
? handle.center().x()
|
|
|
|
|
: handle.center().y();
|
|
|
|
|
|
2023-02-20 19:02:43 +02:00
|
|
|
int borderRadius = 4;
|
2010-04-28 16:09:48 +02:00
|
|
|
|
2023-02-16 17:04:53 +02:00
|
|
|
painter->save();
|
|
|
|
|
painter->setRenderHint(QPainter::RenderHint::Antialiasing);
|
|
|
|
|
|
|
|
|
|
int lineWidth = pixelMetric(QStyle::PM_DefaultFrameWidth, option, widget);
|
|
|
|
|
Theme::Color themeframeColor = enabled
|
2023-02-20 19:02:43 +02:00
|
|
|
? interaction
|
|
|
|
|
? Theme::DSstateControlBackgroundColor_hover // Pressed
|
|
|
|
|
: grooveHover
|
|
|
|
|
? Theme::DSstateSeparatorColor // GrooveHover
|
|
|
|
|
: Theme::DSpopupBackground // Idle
|
|
|
|
|
: Theme::DSpopupBackground; // Disabled
|
|
|
|
|
|
2023-02-16 17:04:53 +02:00
|
|
|
QColor frameColor = creatorTheme()->color(themeframeColor);
|
|
|
|
|
|
|
|
|
|
if ((option->subControls & SC_SliderGroove) && groove.isValid()) {
|
2023-02-20 19:02:43 +02:00
|
|
|
Theme::Color bgPlusColor = enabled
|
|
|
|
|
? interaction
|
|
|
|
|
? Theme::DSstateControlBackgroundColor_hover // Pressed
|
|
|
|
|
: grooveHover
|
|
|
|
|
? Theme::DSstateSeparatorColor // GrooveHover
|
|
|
|
|
: Theme::DStoolbarBackground // Idle
|
|
|
|
|
: Theme::DStoolbarBackground; // Disabled
|
|
|
|
|
Theme::Color bgMinusColor = Theme::DSpopupBackground;
|
2023-02-16 17:04:53 +02:00
|
|
|
|
|
|
|
|
QRect minusRect(groove);
|
|
|
|
|
QRect plusRect(groove);
|
|
|
|
|
|
|
|
|
|
if (horizontal) {
|
|
|
|
|
if (slider->upsideDown) {
|
|
|
|
|
minusRect.setLeft(sliderPaintingOffset);
|
|
|
|
|
plusRect.setRight(sliderPaintingOffset);
|
|
|
|
|
} else {
|
|
|
|
|
minusRect.setRight(sliderPaintingOffset);
|
|
|
|
|
plusRect.setLeft(sliderPaintingOffset);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (slider->upsideDown) {
|
|
|
|
|
minusRect.setBottom(sliderPaintingOffset);
|
|
|
|
|
plusRect.setTop(sliderPaintingOffset);
|
|
|
|
|
} else {
|
|
|
|
|
minusRect.setTop(sliderPaintingOffset);
|
|
|
|
|
plusRect.setBottom(sliderPaintingOffset);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-20 19:02:43 +02:00
|
|
|
painter->save();
|
2023-02-16 17:04:53 +02:00
|
|
|
painter->setPen(Qt::NoPen);
|
2023-02-20 19:02:43 +02:00
|
|
|
painter->setBrush(creatorTheme()->color(bgPlusColor));
|
|
|
|
|
painter->drawRoundedRect(plusRect, borderRadius, borderRadius);
|
|
|
|
|
painter->setBrush(creatorTheme()->color(bgMinusColor));
|
|
|
|
|
painter->drawRoundedRect(minusRect, borderRadius, borderRadius);
|
|
|
|
|
painter->restore();
|
2023-02-16 17:04:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (option->subControls & SC_SliderTickmarks) {
|
|
|
|
|
Theme::Color tickPen = enabled
|
|
|
|
|
? activeFocus
|
|
|
|
|
? Theme::DSstateBackgroundColor_hover
|
|
|
|
|
: Theme::DSBackgroundColorAlternate
|
|
|
|
|
: Theme::DScontrolBackgroundDisabled;
|
|
|
|
|
|
|
|
|
|
painter->setPen(tickPen);
|
|
|
|
|
int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
|
|
|
|
|
int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
|
|
|
|
|
int interval = slider->tickInterval;
|
|
|
|
|
if (interval <= 0) {
|
|
|
|
|
interval = slider->singleStep;
|
|
|
|
|
if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval,
|
|
|
|
|
available)
|
|
|
|
|
- QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
|
|
|
|
|
0, available) < 3)
|
|
|
|
|
interval = slider->pageStep;
|
|
|
|
|
}
|
|
|
|
|
if (interval <= 0)
|
|
|
|
|
interval = 1;
|
|
|
|
|
|
|
|
|
|
int v = slider->minimum;
|
|
|
|
|
int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
|
|
|
|
|
while (v <= slider->maximum + 1) {
|
|
|
|
|
if (v == slider->maximum + 1 && interval == 1)
|
|
|
|
|
break;
|
|
|
|
|
const int v_ = qMin(v, slider->maximum);
|
|
|
|
|
int pos = sliderPositionFromValue(slider->minimum, slider->maximum,
|
|
|
|
|
v_, (horizontal
|
|
|
|
|
? slider->rect.width()
|
|
|
|
|
: slider->rect.height()) - len,
|
|
|
|
|
slider->upsideDown) + len / 2;
|
|
|
|
|
int extra = 2 - ((v_ == slider->minimum || v_ == slider->maximum) ? 1 : 0);
|
|
|
|
|
|
|
|
|
|
if (horizontal) {
|
|
|
|
|
if (ticksAbove) {
|
|
|
|
|
painter->drawLine(pos, slider->rect.top() + extra,
|
|
|
|
|
pos, slider->rect.top() + tickSize);
|
|
|
|
|
}
|
|
|
|
|
if (ticksBelow) {
|
|
|
|
|
painter->drawLine(pos, slider->rect.bottom() - extra,
|
|
|
|
|
pos, slider->rect.bottom() - tickSize);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (ticksAbove) {
|
|
|
|
|
painter->drawLine(slider->rect.left() + extra, pos,
|
|
|
|
|
slider->rect.left() + tickSize, pos);
|
|
|
|
|
}
|
|
|
|
|
if (ticksBelow) {
|
|
|
|
|
painter->drawLine(slider->rect.right() - extra, pos,
|
|
|
|
|
slider->rect.right() - tickSize, pos);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// in the case where maximum is max int
|
|
|
|
|
int nextInterval = v + interval;
|
|
|
|
|
if (nextInterval < v)
|
|
|
|
|
break;
|
|
|
|
|
v = nextInterval;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// draw handle
|
|
|
|
|
if ((option->subControls & SC_SliderHandle) ) {
|
|
|
|
|
Theme::Color handleColor = enabled
|
2023-02-20 19:02:43 +02:00
|
|
|
? interaction
|
|
|
|
|
? Theme::DSinteraction // Interaction
|
|
|
|
|
: grooveHover || handleHover
|
|
|
|
|
? Theme::DStabActiveText // Hover
|
|
|
|
|
: Theme::PalettePlaceholderText // Idle
|
|
|
|
|
: Theme::DStoolbarIcon_blocked; // Disabled
|
2023-02-16 17:04:53 +02:00
|
|
|
|
|
|
|
|
int halfSliderThickness = horizontal
|
|
|
|
|
? handle.width() / 2
|
|
|
|
|
: handle.height() / 2;
|
|
|
|
|
painter->setBrush(creatorTheme()->color(handleColor));
|
2023-02-20 19:02:43 +02:00
|
|
|
painter->setPen(Qt::NoPen);
|
2023-02-16 17:04:53 +02:00
|
|
|
painter->drawRoundedRect(handle,
|
|
|
|
|
halfSliderThickness,
|
|
|
|
|
halfSliderThickness);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (groove.isValid()) {
|
|
|
|
|
painter->setBrush(Qt::NoBrush);
|
|
|
|
|
painter->setPen(QPen(frameColor, lineWidth));
|
2023-02-20 19:02:43 +02:00
|
|
|
painter->drawRoundedRect(groove, borderRadius, borderRadius);
|
2023-02-16 17:04:53 +02:00
|
|
|
}
|
|
|
|
|
painter->restore();
|
|
|
|
|
}
|
|
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
default:
|
2010-02-23 12:42:04 +01:00
|
|
|
QProxyStyle::drawComplexControl(control, option, painter, widget);
|
2008-12-02 12:01:29 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-12-05 13:28:56 +01:00
|
|
|
|
2020-12-10 00:59:50 +01:00
|
|
|
void ManhattanStyle::drawButtonSeparator(QPainter *painter, const QRect &rect, bool reverse)
|
2011-12-05 13:28:56 +01:00
|
|
|
{
|
2015-10-20 14:58:28 +02:00
|
|
|
const QRectF borderRect = QRectF(rect).adjusted(0.5, 0.5, -0.5, -0.5);
|
2016-06-15 17:41:33 +02:00
|
|
|
if (creatorTheme()->flag(Theme::FlatToolBars)) {
|
2016-03-03 12:28:27 +01:00
|
|
|
const int margin = 3;
|
|
|
|
|
painter->setPen(creatorTheme()->color(Theme::FancyToolBarSeparatorColor));
|
|
|
|
|
painter->drawLine(borderRect.topRight() + QPointF(0, margin),
|
|
|
|
|
borderRect.bottomRight() - QPointF(0, margin));
|
2016-03-02 18:25:42 +01:00
|
|
|
} else {
|
|
|
|
|
QLinearGradient grad(rect.topRight(), rect.bottomRight());
|
|
|
|
|
grad.setColorAt(0, QColor(255, 255, 255, 20));
|
|
|
|
|
grad.setColorAt(0.4, QColor(255, 255, 255, 60));
|
|
|
|
|
grad.setColorAt(0.7, QColor(255, 255, 255, 50));
|
|
|
|
|
grad.setColorAt(1, QColor(255, 255, 255, 40));
|
|
|
|
|
painter->setPen(QPen(grad, 1));
|
|
|
|
|
painter->drawLine(borderRect.topRight(), borderRect.bottomRight());
|
|
|
|
|
grad.setColorAt(0, QColor(0, 0, 0, 30));
|
|
|
|
|
grad.setColorAt(0.4, QColor(0, 0, 0, 70));
|
|
|
|
|
grad.setColorAt(0.7, QColor(0, 0, 0, 70));
|
|
|
|
|
grad.setColorAt(1, QColor(0, 0, 0, 40));
|
|
|
|
|
painter->setPen(QPen(grad, 1));
|
|
|
|
|
if (!reverse)
|
|
|
|
|
painter->drawLine(borderRect.topRight() - QPointF(1, 0), borderRect.bottomRight() - QPointF(1, 0));
|
|
|
|
|
else
|
|
|
|
|
painter->drawLine(borderRect.topLeft(), borderRect.bottomLeft());
|
|
|
|
|
}
|
2011-12-05 13:28:56 +01:00
|
|
|
}
|