aboutsummaryrefslogtreecommitdiffstats
path: root/src/quickcontrols/universal/qquickuniversalstyle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quickcontrols/universal/qquickuniversalstyle.cpp')
-rw-r--r--src/quickcontrols/universal/qquickuniversalstyle.cpp589
1 files changed, 589 insertions, 0 deletions
diff --git a/src/quickcontrols/universal/qquickuniversalstyle.cpp b/src/quickcontrols/universal/qquickuniversalstyle.cpp
new file mode 100644
index 0000000000..9710bc2a4b
--- /dev/null
+++ b/src/quickcontrols/universal/qquickuniversalstyle.cpp
@@ -0,0 +1,589 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qquickuniversalstyle_p.h"
+
+#include <QtCore/qdebug.h>
+#if QT_CONFIG(settings)
+#include <QtCore/qsettings.h>
+#endif
+#include <QtQml/qqmlinfo.h>
+#include <QtQuickControls2/private/qquickstyle_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static QRgb qquickuniversal_light_color(QQuickUniversalStyle::SystemColor role)
+{
+ static const QRgb colors[] = {
+ 0xFFFFFFFF, // SystemAltHighColor
+ 0x33FFFFFF, // SystemAltLowColor
+ 0x99FFFFFF, // SystemAltMediumColor
+ 0xCCFFFFFF, // SystemAltMediumHighColor
+ 0x66FFFFFF, // SystemAltMediumLowColor
+ 0xFF000000, // SystemBaseHighColor
+ 0x33000000, // SystemBaseLowColor
+ 0x99000000, // SystemBaseMediumColor
+ 0xCC000000, // SystemBaseMediumHighColor
+ 0x66000000, // SystemBaseMediumLowColor
+ 0xFF171717, // SystemChromeAltLowColor
+ 0xFF000000, // SystemChromeBlackHighColor
+ 0x33000000, // SystemChromeBlackLowColor
+ 0x66000000, // SystemChromeBlackMediumLowColor
+ 0xCC000000, // SystemChromeBlackMediumColor
+ 0xFFCCCCCC, // SystemChromeDisabledHighColor
+ 0xFF7A7A7A, // SystemChromeDisabledLowColor
+ 0xFFCCCCCC, // SystemChromeHighColor
+ 0xFFF2F2F2, // SystemChromeLowColor
+ 0xFFE6E6E6, // SystemChromeMediumColor
+ 0xFFF2F2F2, // SystemChromeMediumLowColor
+ 0xFFFFFFFF, // SystemChromeWhiteColor
+ 0x19000000, // SystemListLowColor
+ 0x33000000 // SystemListMediumColor
+ };
+ return colors[role];
+}
+
+static QRgb qquickuniversal_dark_color(QQuickUniversalStyle::SystemColor role)
+{
+ static const QRgb colors[] = {
+ 0xFF000000, // SystemAltHighColor
+ 0x33000000, // SystemAltLowColor
+ 0x99000000, // SystemAltMediumColor
+ 0xCC000000, // SystemAltMediumHighColor
+ 0x66000000, // SystemAltMediumLowColor
+ 0xFFFFFFFF, // SystemBaseHighColor
+ 0x33FFFFFF, // SystemBaseLowColor
+ 0x99FFFFFF, // SystemBaseMediumColor
+ 0xCCFFFFFF, // SystemBaseMediumHighColor
+ 0x66FFFFFF, // SystemBaseMediumLowColor
+ 0xFFF2F2F2, // SystemChromeAltLowColor
+ 0xFF000000, // SystemChromeBlackHighColor
+ 0x33000000, // SystemChromeBlackLowColor
+ 0x66000000, // SystemChromeBlackMediumLowColor
+ 0xCC000000, // SystemChromeBlackMediumColor
+ 0xFF333333, // SystemChromeDisabledHighColor
+ 0xFF858585, // SystemChromeDisabledLowColor
+ 0xFF767676, // SystemChromeHighColor
+ 0xFF171717, // SystemChromeLowColor
+ 0xFF1F1F1F, // SystemChromeMediumColor
+ 0xFF2B2B2B, // SystemChromeMediumLowColor
+ 0xFFFFFFFF, // SystemChromeWhiteColor
+ 0x19FFFFFF, // SystemListLowColor
+ 0x33FFFFFF // SystemListMediumColor
+ };
+ return colors[role];
+}
+
+static QRgb qquickuniversal_accent_color(QQuickUniversalStyle::Color accent)
+{
+ static const QRgb colors[] = {
+ 0xFFA4C400, // Lime
+ 0xFF60A917, // Green
+ 0xFF008A00, // Emerald
+ 0xFF00ABA9, // Teal
+ 0xFF1BA1E2, // Cyan
+ 0xFF3E65FF, // Cobalt
+ 0xFF6A00FF, // Indigo
+ 0xFFAA00FF, // Violet
+ 0xFFF472D0, // Pink
+ 0xFFD80073, // Magenta
+ 0xFFA20025, // Crimson
+ 0xFFE51400, // Red
+ 0xFFFA6800, // Orange
+ 0xFFF0A30A, // Amber
+ 0xFFE3C800, // Yellow
+ 0xFF825A2C, // Brown
+ 0xFF6D8764, // Olive
+ 0xFF647687, // Steel
+ 0xFF76608A, // Mauve
+ 0xFF87794E // Taupe
+ };
+ return colors[accent];
+}
+
+static QQuickUniversalStyle::Theme qquickuniversal_effective_theme(QQuickUniversalStyle::Theme theme)
+{
+ if (theme == QQuickUniversalStyle::System)
+ theme = QQuickStylePrivate::isDarkSystemTheme() ? QQuickUniversalStyle::Dark : QQuickUniversalStyle::Light;
+ return theme;
+}
+
+// If no value was inherited from a parent or explicitly set, the "global" values are used.
+// The initial, default values of the globals are hard-coded here, but the environment
+// variables and .conf file override them if specified.
+static QQuickUniversalStyle::Theme GlobalTheme = QQuickUniversalStyle::Light;
+static QRgb GlobalAccent = qquickuniversal_accent_color(QQuickUniversalStyle::Cobalt);
+static QRgb GlobalForeground = qquickuniversal_light_color(QQuickUniversalStyle::BaseHigh);
+static QRgb GlobalBackground = qquickuniversal_light_color(QQuickUniversalStyle::AltHigh);
+// These represent whether a global foreground/background was set.
+// Each style's m_hasForeground/m_hasBackground are initialized to these values.
+static bool HasGlobalForeground = false;
+static bool HasGlobalBackground = false;
+
+QQuickUniversalStyle::QQuickUniversalStyle(QObject *parent) : QQuickAttachedPropertyPropagator(parent),
+ m_hasForeground(HasGlobalForeground), m_hasBackground(HasGlobalBackground), m_theme(GlobalTheme),
+ m_accent(GlobalAccent), m_foreground(GlobalForeground), m_background(GlobalBackground)
+{
+ initialize();
+}
+
+QQuickUniversalStyle *QQuickUniversalStyle::qmlAttachedProperties(QObject *object)
+{
+ return new QQuickUniversalStyle(object);
+}
+
+QQuickUniversalStyle::Theme QQuickUniversalStyle::theme() const
+{
+ return m_theme;
+}
+
+void QQuickUniversalStyle::setTheme(Theme theme)
+{
+ theme = qquickuniversal_effective_theme(theme);
+ m_explicitTheme = true;
+ if (m_theme == theme)
+ return;
+
+ m_theme = theme;
+ propagateTheme();
+ emit themeChanged();
+ emit paletteChanged();
+ emit foregroundChanged();
+ emit backgroundChanged();
+}
+
+void QQuickUniversalStyle::inheritTheme(Theme theme)
+{
+ if (m_explicitTheme || m_theme == theme)
+ return;
+
+ m_theme = theme;
+ propagateTheme();
+ emit themeChanged();
+ emit paletteChanged();
+ emit foregroundChanged();
+ emit backgroundChanged();
+}
+
+void QQuickUniversalStyle::propagateTheme()
+{
+ const auto styles = attachedChildren();
+ for (QQuickAttachedPropertyPropagator *child : styles) {
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(child);
+ if (universal)
+ universal->inheritTheme(m_theme);
+ }
+}
+
+void QQuickUniversalStyle::resetTheme()
+{
+ if (!m_explicitTheme)
+ return;
+
+ m_explicitTheme = false;
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(attachedParent());
+ inheritTheme(universal ? universal->theme() : GlobalTheme);
+}
+
+QVariant QQuickUniversalStyle::accent() const
+{
+ return QColor::fromRgba(m_accent);
+}
+
+void QQuickUniversalStyle::setAccent(const QVariant &var)
+{
+ QRgb accent = 0;
+ if (!variantToRgba(var, "accent", &accent))
+ return;
+
+ m_explicitAccent = true;
+ if (m_accent == accent)
+ return;
+
+ m_accent = accent;
+ propagateAccent();
+ emit accentChanged();
+}
+
+void QQuickUniversalStyle::inheritAccent(QRgb accent)
+{
+ if (m_explicitAccent || m_accent == accent)
+ return;
+
+ m_accent = accent;
+ propagateAccent();
+ emit accentChanged();
+}
+
+void QQuickUniversalStyle::propagateAccent()
+{
+ const auto styles = attachedChildren();
+ for (QQuickAttachedPropertyPropagator *child : styles) {
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(child);
+ if (universal)
+ universal->inheritAccent(m_accent);
+ }
+}
+
+void QQuickUniversalStyle::resetAccent()
+{
+ if (!m_explicitAccent)
+ return;
+
+ m_explicitAccent = false;
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(attachedParent());
+ inheritAccent(universal ? universal->m_accent : GlobalAccent);
+}
+
+QVariant QQuickUniversalStyle::foreground() const
+{
+ if (m_hasForeground)
+ return QColor::fromRgba(m_foreground);
+ return baseHighColor();
+}
+
+void QQuickUniversalStyle::setForeground(const QVariant &var)
+{
+ QRgb foreground = 0;
+ if (!variantToRgba(var, "foreground", &foreground))
+ return;
+
+ m_hasForeground = true;
+ m_explicitForeground = true;
+ if (m_foreground == foreground)
+ return;
+
+ m_foreground = foreground;
+ propagateForeground();
+ emit foregroundChanged();
+}
+
+void QQuickUniversalStyle::inheritForeground(QRgb foreground, bool has)
+{
+ if (m_explicitForeground || m_foreground == foreground)
+ return;
+
+ m_hasForeground = has;
+ m_foreground = foreground;
+ propagateForeground();
+ emit foregroundChanged();
+}
+
+void QQuickUniversalStyle::propagateForeground()
+{
+ const auto styles = attachedChildren();
+ for (QQuickAttachedPropertyPropagator *child : styles) {
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(child);
+ if (universal)
+ universal->inheritForeground(m_foreground, m_hasForeground);
+ }
+}
+
+void QQuickUniversalStyle::resetForeground()
+{
+ if (!m_explicitForeground)
+ return;
+
+ m_hasForeground = false;
+ m_explicitForeground = false;
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(attachedParent());
+ inheritForeground(universal ? universal->m_foreground : GlobalForeground, universal ? universal->m_hasForeground : false);
+}
+
+QVariant QQuickUniversalStyle::background() const
+{
+ if (m_hasBackground)
+ return QColor::fromRgba(m_background);
+ return altHighColor();
+}
+
+void QQuickUniversalStyle::setBackground(const QVariant &var)
+{
+ QRgb background = 0;
+ if (!variantToRgba(var, "background", &background))
+ return;
+
+ m_hasBackground = true;
+ m_explicitBackground = true;
+ if (m_background == background)
+ return;
+
+ m_background = background;
+ propagateBackground();
+ emit backgroundChanged();
+}
+
+void QQuickUniversalStyle::inheritBackground(QRgb background, bool has)
+{
+ if (m_explicitBackground || m_background == background)
+ return;
+
+ m_hasBackground = has;
+ m_background = background;
+ propagateBackground();
+ emit backgroundChanged();
+}
+
+void QQuickUniversalStyle::propagateBackground()
+{
+ const auto styles = attachedChildren();
+ for (QQuickAttachedPropertyPropagator *child : styles) {
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(child);
+ if (universal)
+ universal->inheritBackground(m_background, m_hasBackground);
+ }
+}
+
+void QQuickUniversalStyle::resetBackground()
+{
+ if (!m_explicitBackground)
+ return;
+
+ m_hasBackground = false;
+ m_explicitBackground = false;
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(attachedParent());
+ inheritBackground(universal ? universal->m_background : GlobalBackground, universal ? universal->m_hasBackground : false);
+}
+
+QColor QQuickUniversalStyle::color(Color color) const
+{
+ return qquickuniversal_accent_color(color);
+}
+
+QColor QQuickUniversalStyle::altHighColor() const
+{
+ return systemColor(AltHigh);
+}
+
+QColor QQuickUniversalStyle::altLowColor() const
+{
+ return systemColor(AltLow);
+}
+
+QColor QQuickUniversalStyle::altMediumColor() const
+{
+ return systemColor(AltMedium);
+}
+
+QColor QQuickUniversalStyle::altMediumHighColor() const
+{
+ return systemColor(AltMediumHigh);
+}
+
+QColor QQuickUniversalStyle::altMediumLowColor() const
+{
+ return systemColor(AltMediumLow);
+}
+
+QColor QQuickUniversalStyle::baseHighColor() const
+{
+ return systemColor(BaseHigh);
+}
+
+QColor QQuickUniversalStyle::baseLowColor() const
+{
+ return systemColor(BaseLow);
+}
+
+QColor QQuickUniversalStyle::baseMediumColor() const
+{
+ return systemColor(BaseMedium);
+}
+
+QColor QQuickUniversalStyle::baseMediumHighColor() const
+{
+ return systemColor(BaseMediumHigh);
+}
+
+QColor QQuickUniversalStyle::baseMediumLowColor() const
+{
+ return systemColor(BaseMediumLow);
+}
+
+QColor QQuickUniversalStyle::chromeAltLowColor() const
+{
+ return systemColor(ChromeAltLow);
+}
+
+QColor QQuickUniversalStyle::chromeBlackHighColor() const
+{
+ return systemColor(ChromeBlackHigh);
+}
+
+QColor QQuickUniversalStyle::chromeBlackLowColor() const
+{
+ return systemColor(ChromeBlackLow);
+}
+
+QColor QQuickUniversalStyle::chromeBlackMediumLowColor() const
+{
+ return systemColor(ChromeBlackMediumLow);
+}
+
+QColor QQuickUniversalStyle::chromeBlackMediumColor() const
+{
+ return systemColor(ChromeBlackMedium);
+}
+
+QColor QQuickUniversalStyle::chromeDisabledHighColor() const
+{
+ return systemColor(ChromeDisabledHigh);
+}
+
+QColor QQuickUniversalStyle::chromeDisabledLowColor() const
+{
+ return systemColor(ChromeDisabledLow);
+}
+
+QColor QQuickUniversalStyle::chromeHighColor() const
+{
+ return systemColor(ChromeHigh);
+}
+
+QColor QQuickUniversalStyle::chromeLowColor() const
+{
+ return systemColor(ChromeLow);
+}
+
+QColor QQuickUniversalStyle::chromeMediumColor() const
+{
+ return systemColor(ChromeMedium);
+}
+
+QColor QQuickUniversalStyle::chromeMediumLowColor() const
+{
+ return systemColor(ChromeMediumLow);
+}
+
+QColor QQuickUniversalStyle::chromeWhiteColor() const
+{
+ return systemColor(ChromeWhite);
+}
+
+QColor QQuickUniversalStyle::listLowColor() const
+{
+ return systemColor(ListLow);
+}
+
+QColor QQuickUniversalStyle::listMediumColor() const
+{
+ return systemColor(ListMedium);
+}
+
+QColor QQuickUniversalStyle::systemColor(SystemColor role) const
+{
+ return QColor::fromRgba(m_theme == QQuickUniversalStyle::Dark ? qquickuniversal_dark_color(role) : qquickuniversal_light_color(role));
+}
+
+void QQuickUniversalStyle::attachedParentChange(QQuickAttachedPropertyPropagator *newParent, QQuickAttachedPropertyPropagator *oldParent)
+{
+ Q_UNUSED(oldParent);
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(newParent);
+ if (universal) {
+ inheritTheme(universal->theme());
+ inheritAccent(universal->m_accent);
+ inheritForeground(universal->m_foreground, universal->m_hasForeground);
+ inheritBackground(universal->m_background, universal->m_hasBackground);
+ }
+}
+
+template <typename Enum>
+static Enum toEnumValue(const QByteArray &value, bool *ok)
+{
+ QMetaEnum enumeration = QMetaEnum::fromType<Enum>();
+ return static_cast<Enum>(enumeration.keyToValue(value, ok));
+}
+
+static QByteArray resolveSetting(const QByteArray &env, const QSharedPointer<QSettings> &settings, const QString &name)
+{
+ QByteArray value = qgetenv(env);
+#if QT_CONFIG(settings)
+ if (value.isNull() && !settings.isNull())
+ value = settings->value(name).toByteArray();
+#endif
+ return value;
+}
+
+void QQuickUniversalStyle::initGlobals()
+{
+ QSharedPointer<QSettings> settings = QQuickStylePrivate::settings(QStringLiteral("Universal"));
+
+ bool ok = false;
+ QByteArray themeValue = resolveSetting("QT_QUICK_CONTROLS_UNIVERSAL_THEME", settings, QStringLiteral("Theme"));
+ Theme themeEnum = toEnumValue<Theme>(themeValue, &ok);
+ if (ok)
+ GlobalTheme = qquickuniversal_effective_theme(themeEnum);
+ else if (!themeValue.isEmpty())
+ qWarning().nospace().noquote() << "Universal: unknown theme value: " << themeValue;
+
+ QByteArray accentValue = resolveSetting("QT_QUICK_CONTROLS_UNIVERSAL_ACCENT", settings, QStringLiteral("Accent"));
+ Color accentEnum = toEnumValue<Color>(accentValue, &ok);
+ if (ok) {
+ GlobalAccent = qquickuniversal_accent_color(accentEnum);
+ } else if (!accentValue.isEmpty()) {
+ QColor color = QColor::fromString(accentValue);
+ if (color.isValid())
+ GlobalAccent = color.rgba();
+ else
+ qWarning().nospace().noquote() << "Universal: unknown accent value: " << accentValue;
+ }
+
+ QByteArray foregroundValue = resolveSetting("QT_QUICK_CONTROLS_UNIVERSAL_FOREGROUND", settings, QStringLiteral("Foreground"));
+ Color foregroundEnum = toEnumValue<Color>(foregroundValue, &ok);
+ if (ok) {
+ GlobalForeground = qquickuniversal_accent_color(foregroundEnum);
+ HasGlobalForeground = true;
+ } else if (!foregroundValue.isEmpty()) {
+ QColor color = QColor::fromString(foregroundValue);
+ if (color.isValid()) {
+ GlobalForeground = color.rgba();
+ HasGlobalForeground = true;
+ } else {
+ qWarning().nospace().noquote() << "Universal: unknown foreground value: " << foregroundValue;
+ }
+ }
+
+ QByteArray backgroundValue = resolveSetting("QT_QUICK_CONTROLS_UNIVERSAL_BACKGROUND", settings, QStringLiteral("Background"));
+ Color backgroundEnum = toEnumValue<Color>(backgroundValue, &ok);
+ if (ok) {
+ GlobalBackground = qquickuniversal_accent_color(backgroundEnum);
+ HasGlobalBackground = true;
+ } else if (!backgroundValue.isEmpty()) {
+ QColor color = QColor::fromString(backgroundValue);
+ if (color.isValid()) {
+ GlobalBackground = color.rgba();
+ HasGlobalBackground = true;
+ } else {
+ qWarning().nospace().noquote() << "Universal: unknown background value: " << backgroundValue;
+ }
+ }
+}
+
+bool QQuickUniversalStyle::variantToRgba(const QVariant &var, const char *name, QRgb *rgba) const
+{
+ if (var.metaType().id() == QMetaType::Int) {
+ int val = var.toInt();
+ if (val < Lime || val > Taupe) {
+ qmlWarning(parent()) << "unknown Universal." << name << " value: " << val;
+ return false;
+ }
+ *rgba = qquickuniversal_accent_color(static_cast<Color>(val));
+ } else {
+ int val = QMetaEnum::fromType<Color>().keyToValue(var.toByteArray());
+ if (val != -1) {
+ *rgba = qquickuniversal_accent_color(static_cast<Color>(val));
+ } else {
+ QColor color = QColor::fromString(var.toString());
+ if (!color.isValid()) {
+ qmlWarning(parent()) << "unknown Universal." << name << " value: " << var.toString();
+ return false;
+ }
+ *rgba = color.rgba();
+ }
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickuniversalstyle_p.cpp"