/**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the Qt Quick Controls 2 module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPLv3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or later as published by the Free ** Software Foundation and appearing in the file LICENSE.GPL included in ** the packaging of this file. Please review the following information to ** ensure the GNU General Public License version 2.0 requirements will be ** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qquickuniversalstyle_p.h" #include #include #include #include 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) : QQuickAttachedObject(parent), m_hasForeground(HasGlobalForeground), m_hasBackground(HasGlobalBackground), m_theme(GlobalTheme), m_accent(GlobalAccent), m_foreground(GlobalForeground), m_background(GlobalBackground) { init(); } 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 (QQuickAttachedObject *child : styles) { QQuickUniversalStyle *universal = qobject_cast(child); if (universal) universal->inheritTheme(m_theme); } } void QQuickUniversalStyle::resetTheme() { if (!m_explicitTheme) return; m_explicitTheme = false; QQuickUniversalStyle *universal = qobject_cast(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 (QQuickAttachedObject *child : styles) { QQuickUniversalStyle *universal = qobject_cast(child); if (universal) universal->inheritAccent(m_accent); } } void QQuickUniversalStyle::resetAccent() { if (!m_explicitAccent) return; m_explicitAccent = false; QQuickUniversalStyle *universal = qobject_cast(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 (QQuickAttachedObject *child : styles) { QQuickUniversalStyle *universal = qobject_cast(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(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 (QQuickAttachedObject *child : styles) { QQuickUniversalStyle *universal = qobject_cast(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(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(QQuickAttachedObject *newParent, QQuickAttachedObject *oldParent) { Q_UNUSED(oldParent); QQuickUniversalStyle *universal = qobject_cast(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 static Enum toEnumValue(const QByteArray &value, bool *ok) { QMetaEnum enumeration = QMetaEnum::fromType(); return static_cast(enumeration.keyToValue(value, ok)); } static QByteArray resolveSetting(const QByteArray &env, const QSharedPointer &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 settings = QQuickStylePrivate::settings(QStringLiteral("Universal")); bool ok = false; QByteArray themeValue = resolveSetting("QT_QUICK_CONTROLS_UNIVERSAL_THEME", settings, QStringLiteral("Theme")); Theme themeEnum = toEnumValue(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(accentValue, &ok); if (ok) { GlobalAccent = qquickuniversal_accent_color(accentEnum); } else if (!accentValue.isEmpty()) { QColor color(accentValue.constData()); 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(foregroundValue, &ok); if (ok) { GlobalForeground = qquickuniversal_accent_color(foregroundEnum); HasGlobalForeground = true; } else if (!foregroundValue.isEmpty()) { QColor color(foregroundValue.constData()); 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(backgroundValue, &ok); if (ok) { GlobalBackground = qquickuniversal_accent_color(backgroundEnum); HasGlobalBackground = true; } else if (!backgroundValue.isEmpty()) { QColor color(backgroundValue.constData()); 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.type() == QVariant::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(val)); } else { int val = QMetaEnum::fromType().keyToValue(var.toByteArray()); if (val != -1) { *rgba = qquickuniversal_accent_color(static_cast(val)); } else { QColor color(var.toString()); if (!color.isValid()) { qmlWarning(parent()) << "unknown Universal." << name << " value: " << var.toString(); return false; } *rgba = color.rgba(); } } return true; } QT_END_NAMESPACE