File indexing completed on 2024-05-05 03:56:26

0001 /*
0002  * SPDX-FileCopyrightText: 2017 by Marco Martin <mart@kde.org>
0003  * SPDX-FileCopyrightText: 2021 Arjen Hiemstra <ahiemstra@heimr.nl>
0004  *
0005  * SPDX-License-Identifier: LGPL-2.0-or-later
0006  */
0007 
0008 #include "basictheme_p.h"
0009 #include "styleselector.h"
0010 
0011 #include <QFile>
0012 #include <QGuiApplication>
0013 
0014 #include "kirigamiplatform_logging.h"
0015 
0016 namespace Kirigami
0017 {
0018 namespace Platform
0019 {
0020 
0021 BasicThemeDefinition::BasicThemeDefinition(QObject *parent)
0022     : QObject(parent)
0023 {
0024     defaultFont = qGuiApp->font();
0025 
0026     smallFont = qGuiApp->font();
0027     smallFont.setPointSize(smallFont.pointSize() - 2);
0028 }
0029 
0030 void BasicThemeDefinition::syncToQml(PlatformTheme *object)
0031 {
0032     auto item = qobject_cast<QQuickItem *>(object->parent());
0033     if (item && qmlAttachedPropertiesObject<PlatformTheme>(item, false) == object) {
0034         Q_EMIT sync(item);
0035     }
0036 }
0037 
0038 BasicThemeInstance::BasicThemeInstance(QObject *parent)
0039     : QObject(parent)
0040 {
0041 }
0042 
0043 BasicThemeDefinition &BasicThemeInstance::themeDefinition(QQmlEngine *engine)
0044 {
0045     if (m_themeDefinition) {
0046         return *m_themeDefinition;
0047     }
0048 
0049     auto themeUrl = StyleSelector::componentUrl(QStringLiteral("Theme.qml"));
0050     QQmlComponent component(engine);
0051     component.loadUrl(themeUrl);
0052 
0053     if (!component.isError()) {
0054         auto result = component.create();
0055         if (auto themeDefinition = qobject_cast<BasicThemeDefinition *>(result)) {
0056             m_themeDefinition.reset(themeDefinition);
0057         } else {
0058             const auto errors = component.errors();
0059             for (auto error : errors) {
0060                 qCWarning(KirigamiPlatform) << error.toString();
0061             }
0062 
0063             qCWarning(KirigamiPlatform) << "Invalid Theme file, using default Basic theme.";
0064             m_themeDefinition = std::make_unique<BasicThemeDefinition>();
0065         }
0066     } else {
0067         qCDebug(KirigamiPlatform) << "No Theme file found, using default Basic theme";
0068         m_themeDefinition = std::make_unique<BasicThemeDefinition>();
0069     }
0070 
0071     connect(m_themeDefinition.get(), &BasicThemeDefinition::changed, this, &BasicThemeInstance::onDefinitionChanged);
0072 
0073     return *m_themeDefinition;
0074 }
0075 
0076 void BasicThemeInstance::onDefinitionChanged()
0077 {
0078     for (auto watcher : std::as_const(watchers)) {
0079         watcher->sync();
0080     }
0081 }
0082 
0083 Q_GLOBAL_STATIC(BasicThemeInstance, basicThemeInstance)
0084 
0085 BasicTheme::BasicTheme(QObject *parent)
0086     : PlatformTheme(parent)
0087 {
0088     basicThemeInstance()->watchers.append(this);
0089 
0090     sync();
0091 }
0092 
0093 BasicTheme::~BasicTheme()
0094 {
0095     basicThemeInstance()->watchers.removeOne(this);
0096 }
0097 
0098 void BasicTheme::sync()
0099 {
0100     auto &definition = basicThemeInstance()->themeDefinition(qmlEngine(parent()));
0101 
0102     switch (colorSet()) {
0103     case BasicTheme::Button:
0104         setTextColor(tint(definition.buttonTextColor));
0105         setBackgroundColor(tint(definition.buttonBackgroundColor));
0106         setAlternateBackgroundColor(tint(definition.buttonAlternateBackgroundColor));
0107         setHoverColor(tint(definition.buttonHoverColor));
0108         setFocusColor(tint(definition.buttonFocusColor));
0109         break;
0110     case BasicTheme::View:
0111         setTextColor(tint(definition.viewTextColor));
0112         setBackgroundColor(tint(definition.viewBackgroundColor));
0113         setAlternateBackgroundColor(tint(definition.viewAlternateBackgroundColor));
0114         setHoverColor(tint(definition.viewHoverColor));
0115         setFocusColor(tint(definition.viewFocusColor));
0116         break;
0117     case BasicTheme::Selection:
0118         setTextColor(tint(definition.selectionTextColor));
0119         setBackgroundColor(tint(definition.selectionBackgroundColor));
0120         setAlternateBackgroundColor(tint(definition.selectionAlternateBackgroundColor));
0121         setHoverColor(tint(definition.selectionHoverColor));
0122         setFocusColor(tint(definition.selectionFocusColor));
0123         break;
0124     case BasicTheme::Tooltip:
0125         setTextColor(tint(definition.tooltipTextColor));
0126         setBackgroundColor(tint(definition.tooltipBackgroundColor));
0127         setAlternateBackgroundColor(tint(definition.tooltipAlternateBackgroundColor));
0128         setHoverColor(tint(definition.tooltipHoverColor));
0129         setFocusColor(tint(definition.tooltipFocusColor));
0130         break;
0131     case BasicTheme::Complementary:
0132         setTextColor(tint(definition.complementaryTextColor));
0133         setBackgroundColor(tint(definition.complementaryBackgroundColor));
0134         setAlternateBackgroundColor(tint(definition.complementaryAlternateBackgroundColor));
0135         setHoverColor(tint(definition.complementaryHoverColor));
0136         setFocusColor(tint(definition.complementaryFocusColor));
0137         break;
0138     case BasicTheme::Window:
0139     default:
0140         setTextColor(tint(definition.textColor));
0141         setBackgroundColor(tint(definition.backgroundColor));
0142         setAlternateBackgroundColor(tint(definition.alternateBackgroundColor));
0143         setHoverColor(tint(definition.hoverColor));
0144         setFocusColor(tint(definition.focusColor));
0145         break;
0146     }
0147 
0148     setDisabledTextColor(tint(definition.disabledTextColor));
0149     setHighlightColor(tint(definition.highlightColor));
0150     setHighlightedTextColor(tint(definition.highlightedTextColor));
0151     setActiveTextColor(tint(definition.activeTextColor));
0152     setActiveBackgroundColor(tint(definition.activeBackgroundColor));
0153     setLinkColor(tint(definition.linkColor));
0154     setLinkBackgroundColor(tint(definition.linkBackgroundColor));
0155     setVisitedLinkColor(tint(definition.visitedLinkColor));
0156     setVisitedLinkBackgroundColor(tint(definition.visitedLinkBackgroundColor));
0157     setNegativeTextColor(tint(definition.negativeTextColor));
0158     setNegativeBackgroundColor(tint(definition.negativeBackgroundColor));
0159     setNeutralTextColor(tint(definition.neutralTextColor));
0160     setNeutralBackgroundColor(tint(definition.neutralBackgroundColor));
0161     setPositiveTextColor(tint(definition.positiveTextColor));
0162     setPositiveBackgroundColor(tint(definition.positiveBackgroundColor));
0163 
0164     setDefaultFont(definition.defaultFont);
0165     setSmallFont(definition.smallFont);
0166 }
0167 
0168 bool BasicTheme::event(QEvent *event)
0169 {
0170     if (event->type() == PlatformThemeEvents::DataChangedEvent::type) {
0171         sync();
0172     }
0173 
0174     if (event->type() == PlatformThemeEvents::ColorSetChangedEvent::type) {
0175         sync();
0176     }
0177 
0178     if (event->type() == PlatformThemeEvents::ColorGroupChangedEvent::type) {
0179         sync();
0180     }
0181 
0182     if (event->type() == PlatformThemeEvents::ColorChangedEvent::type) {
0183         basicThemeInstance()->themeDefinition(qmlEngine(parent())).syncToQml(this);
0184     }
0185 
0186     if (event->type() == PlatformThemeEvents::FontChangedEvent::type) {
0187         basicThemeInstance()->themeDefinition(qmlEngine(parent())).syncToQml(this);
0188     }
0189 
0190     return PlatformTheme::event(event);
0191 }
0192 
0193 QColor BasicTheme::tint(const QColor &color)
0194 {
0195     switch (colorGroup()) {
0196     case PlatformTheme::Inactive:
0197         return QColor::fromHsvF(color.hueF(), color.saturationF() * 0.5, color.valueF());
0198     case PlatformTheme::Disabled:
0199         return QColor::fromHsvF(color.hueF(), color.saturationF() * 0.5, color.valueF() * 0.8);
0200     default:
0201         return color;
0202     }
0203 }
0204 
0205 }
0206 }
0207 
0208 #include "moc_basictheme_p.cpp"