File indexing completed on 2024-04-28 03:55:58

0001 /*
0002  *  SPDX-FileCopyrightText: 2017 by Marco Martin <mart@kde.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #ifndef KIRIGAMI_PLATFORMTHEME_H
0008 #define KIRIGAMI_PLATFORMTHEME_H
0009 
0010 #include <QColor>
0011 #include <QIcon>
0012 #include <QObject>
0013 #include <QPalette>
0014 #include <QQuickItem>
0015 #include <qqmlregistration.h>
0016 
0017 #include "kirigamiplatform_export.h"
0018 
0019 namespace Kirigami
0020 {
0021 namespace Platform
0022 {
0023 class PlatformThemeData;
0024 class PlatformThemePrivate;
0025 
0026 /**
0027  * @class PlatformTheme platformtheme.h <Kirigami/PlatformTheme>
0028  *
0029  * This class is the base for color management in Kirigami,
0030  * different platforms can reimplement this class to integrate with
0031  * system platform colors of a given platform
0032  */
0033 class KIRIGAMIPLATFORM_EXPORT PlatformTheme : public QObject
0034 {
0035     Q_OBJECT
0036     QML_NAMED_ELEMENT(Theme)
0037     QML_ATTACHED(Kirigami::Platform::PlatformTheme)
0038     QML_UNCREATABLE("Attached Property")
0039 
0040     /**
0041      * This enumeration describes the color set for which a color is being selected.
0042      *
0043      * Color sets define a color "environment", suitable for drawing all parts of a
0044      * given region. Colors from different sets should not be combined.
0045      */
0046     Q_PROPERTY(ColorSet colorSet READ colorSet WRITE setColorSet NOTIFY colorSetChanged FINAL)
0047 
0048     /**
0049      * This enumeration describes the color group used to generate the colors.
0050      * The enum value is based upon QPalette::ColorGroup and has the same values.
0051      * It's redefined here in order to make it work with QML.
0052      * @since 4.43
0053      */
0054     Q_PROPERTY(ColorGroup colorGroup READ colorGroup WRITE setColorGroup NOTIFY colorGroupChanged FINAL)
0055 
0056     /**
0057      * If true, the colorSet will be inherited from the colorset of a theme of one
0058      * of the ancestor items
0059      * default: true
0060      */
0061     Q_PROPERTY(bool inherit READ inherit WRITE setInherit NOTIFY inheritChanged FINAL)
0062 
0063     // foreground colors
0064     /**
0065      * Color for normal foregrounds, usually text, but not limited to it,
0066      * anything that should be painted with a clear contrast should use this color
0067      */
0068     Q_PROPERTY(QColor textColor READ textColor WRITE setCustomTextColor RESET setCustomTextColor NOTIFY colorsChanged FINAL)
0069 
0070     /**
0071      * Foreground color for disabled areas, usually a mid-gray
0072      */
0073     Q_PROPERTY(QColor disabledTextColor READ disabledTextColor WRITE setCustomDisabledTextColor RESET setCustomDisabledTextColor NOTIFY colorsChanged FINAL)
0074 
0075     /**
0076      * Color for text that has been highlighted, often is a light color while normal text is dark
0077      */
0078     Q_PROPERTY(
0079         QColor highlightedTextColor READ highlightedTextColor WRITE setCustomHighlightedTextColor RESET setCustomHighlightedTextColor NOTIFY colorsChanged)
0080 
0081     /**
0082      * Foreground for areas that are active or requesting attention
0083      */
0084     Q_PROPERTY(QColor activeTextColor READ activeTextColor WRITE setCustomActiveTextColor RESET setCustomActiveTextColor NOTIFY colorsChanged FINAL)
0085 
0086     /**
0087      * Color for links
0088      */
0089     Q_PROPERTY(QColor linkColor READ linkColor WRITE setCustomLinkColor RESET setCustomLinkColor NOTIFY colorsChanged FINAL)
0090 
0091     /**
0092      * Color for visited links, usually a bit darker than linkColor
0093      */
0094     Q_PROPERTY(QColor visitedLinkColor READ visitedLinkColor WRITE setCustomVisitedLinkColor RESET setCustomVisitedLinkColor NOTIFY colorsChanged FINAL)
0095 
0096     /**
0097      * Foreground color for negative areas, such as critical error text
0098      */
0099     Q_PROPERTY(QColor negativeTextColor READ negativeTextColor WRITE setCustomNegativeTextColor RESET setCustomNegativeTextColor NOTIFY colorsChanged FINAL)
0100 
0101     /**
0102      * Foreground color for neutral areas, such as warning texts (but not critical)
0103      */
0104     Q_PROPERTY(QColor neutralTextColor READ neutralTextColor WRITE setCustomNeutralTextColor RESET setCustomNeutralTextColor NOTIFY colorsChanged FINAL)
0105 
0106     /**
0107      * Success messages, trusted content
0108      */
0109     Q_PROPERTY(QColor positiveTextColor READ positiveTextColor WRITE setCustomPositiveTextColor RESET setCustomPositiveTextColor NOTIFY colorsChanged FINAL)
0110 
0111     // background colors
0112     /**
0113      * The generic background color
0114      */
0115     Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setCustomBackgroundColor RESET setCustomBackgroundColor NOTIFY colorsChanged FINAL)
0116 
0117     /**
0118      * The generic background color
0119      * Alternate background; for example, for use in lists.
0120      * This color may be the same as BackgroundNormal,
0121      * especially in sets other than View and Window.
0122      */
0123     Q_PROPERTY(QColor alternateBackgroundColor READ alternateBackgroundColor WRITE setCustomAlternateBackgroundColor RESET setCustomAlternateBackgroundColor
0124                    NOTIFY colorsChanged)
0125 
0126     /**
0127      * The background color for selected areas
0128      */
0129     Q_PROPERTY(QColor highlightColor READ highlightColor WRITE setCustomHighlightColor RESET setCustomHighlightColor NOTIFY colorsChanged FINAL)
0130 
0131     /**
0132      * Background for areas that are active or requesting attention
0133      */
0134     Q_PROPERTY(
0135         QColor activeBackgroundColor READ activeBackgroundColor WRITE setCustomActiveBackgroundColor RESET setCustomActiveBackgroundColor NOTIFY colorsChanged)
0136 
0137     /**
0138      * Background color for links
0139      */
0140     Q_PROPERTY(
0141         QColor linkBackgroundColor READ linkBackgroundColor WRITE setCustomLinkBackgroundColor RESET setCustomLinkBackgroundColor NOTIFY colorsChanged FINAL)
0142 
0143     /**
0144      * Background color for visited links, usually a bit darker than linkBackgroundColor
0145      */
0146     Q_PROPERTY(QColor visitedLinkBackgroundColor READ visitedLinkBackgroundColor WRITE setCustomVisitedLinkBackgroundColor RESET
0147                    setCustomVisitedLinkBackgroundColor NOTIFY colorsChanged)
0148 
0149     /**
0150      * Background color for negative areas, such as critical errors and destructive actions
0151      */
0152     Q_PROPERTY(QColor negativeBackgroundColor READ negativeBackgroundColor WRITE setCustomNegativeBackgroundColor RESET setCustomNegativeBackgroundColor NOTIFY
0153                    colorsChanged)
0154 
0155     /**
0156      * Background color for neutral areas, such as warnings (but not critical)
0157      */
0158     Q_PROPERTY(QColor neutralBackgroundColor READ neutralBackgroundColor WRITE setCustomNeutralBackgroundColor RESET setCustomNeutralBackgroundColor NOTIFY
0159                    colorsChanged)
0160 
0161     /**
0162      * Background color for positive areas, such as success messages and trusted content
0163      */
0164     Q_PROPERTY(QColor positiveBackgroundColor READ positiveBackgroundColor WRITE setCustomPositiveBackgroundColor RESET setCustomPositiveBackgroundColor NOTIFY
0165                    colorsChanged)
0166 
0167     // decoration colors
0168     /**
0169      * A decoration color that indicates active focus
0170      */
0171     Q_PROPERTY(QColor focusColor READ focusColor WRITE setCustomFocusColor RESET setCustomFocusColor NOTIFY colorsChanged FINAL)
0172 
0173     /**
0174      * A decoration color that indicates mouse hovering
0175      */
0176     Q_PROPERTY(QColor hoverColor READ hoverColor WRITE setCustomHoverColor RESET setCustomHoverColor NOTIFY colorsChanged FINAL)
0177 
0178     /**
0179      * Hint for item views to actually make use of the alternate background color feature
0180      */
0181     Q_PROPERTY(
0182         bool useAlternateBackgroundColor READ useAlternateBackgroundColor WRITE setUseAlternateBackgroundColor NOTIFY useAlternateBackgroundColorChanged FINAL)
0183 
0184     // font and palette
0185     Q_PROPERTY(QFont defaultFont READ defaultFont NOTIFY defaultFontChanged FINAL)
0186 
0187     // small font
0188     Q_PROPERTY(QFont smallFont READ smallFont NOTIFY smallFontChanged FINAL)
0189 
0190     // Active palette
0191     Q_PROPERTY(QPalette palette READ palette NOTIFY paletteChanged FINAL)
0192 
0193     // Frame contrast value, usually used for separators and outlines
0194     // Value is between 0.0 and 1.0
0195     Q_PROPERTY(qreal frameContrast READ frameContrast CONSTANT FINAL)
0196 
0197     // Returns half of the frameContrast value; used by Separator.Weight.Light
0198     // Value is between 0.0 and 1.0
0199     Q_PROPERTY(qreal lightFrameContrast READ lightFrameContrast CONSTANT FINAL)
0200 
0201 public:
0202     enum ColorSet {
0203         View = 0, /** Color set for item views, usually the lightest of all */
0204         Window, /** Default Color set for windows and "chrome" areas */
0205         Button, /** Color set used by buttons */
0206         Selection, /** Color set used by selectged areas */
0207         Tooltip, /** Color set used by tooltips */
0208         Complementary, /** Color set meant to be complementary to Window: usually is a dark theme for light themes */
0209         Header, /** Color set to be used by heading areas of applications, such as toolbars */
0210 
0211         ColorSetCount, // Number of items in this enum, this should always be the last item.
0212     };
0213     Q_ENUM(ColorSet)
0214 
0215     enum ColorGroup {
0216         Disabled = QPalette::Disabled,
0217         Active = QPalette::Active,
0218         Inactive = QPalette::Inactive,
0219         Normal = QPalette::Normal,
0220 
0221         ColorGroupCount, // Number of items in this enum, this should always be the last item.
0222     };
0223     Q_ENUM(ColorGroup)
0224 
0225     explicit PlatformTheme(QObject *parent = nullptr);
0226     ~PlatformTheme() override;
0227 
0228     void setColorSet(PlatformTheme::ColorSet);
0229     PlatformTheme::ColorSet colorSet() const;
0230 
0231     void setColorGroup(PlatformTheme::ColorGroup);
0232     PlatformTheme::ColorGroup colorGroup() const;
0233 
0234     bool inherit() const;
0235     void setInherit(bool inherit);
0236 
0237     // foreground colors
0238     QColor textColor() const;
0239     QColor disabledTextColor() const;
0240     QColor highlightedTextColor() const;
0241     QColor activeTextColor() const;
0242     QColor linkColor() const;
0243     QColor visitedLinkColor() const;
0244     QColor negativeTextColor() const;
0245     QColor neutralTextColor() const;
0246     QColor positiveTextColor() const;
0247 
0248     // background colors
0249     QColor backgroundColor() const;
0250     QColor alternateBackgroundColor() const;
0251     QColor highlightColor() const;
0252     QColor activeBackgroundColor() const;
0253     QColor linkBackgroundColor() const;
0254     QColor visitedLinkBackgroundColor() const;
0255     QColor negativeBackgroundColor() const;
0256     QColor neutralBackgroundColor() const;
0257     QColor positiveBackgroundColor() const;
0258 
0259     // decoration colors
0260     QColor focusColor() const;
0261     QColor hoverColor() const;
0262 
0263     QFont defaultFont() const;
0264     QFont smallFont() const;
0265 
0266     // this may is used by the desktop QQC2 to set the styleoption palettes
0267     QPalette palette() const;
0268 
0269     qreal frameContrast() const;
0270     qreal lightFrameContrast() const;
0271 
0272     // this will be used by desktopicon to fetch icons with KIconLoader
0273     virtual Q_INVOKABLE QIcon iconFromTheme(const QString &name, const QColor &customColor = Qt::transparent);
0274 
0275     bool supportsIconColoring() const;
0276 
0277     // foreground colors
0278     void setCustomTextColor(const QColor &color = QColor());
0279     void setCustomDisabledTextColor(const QColor &color = QColor());
0280     void setCustomHighlightedTextColor(const QColor &color = QColor());
0281     void setCustomActiveTextColor(const QColor &color = QColor());
0282     void setCustomLinkColor(const QColor &color = QColor());
0283     void setCustomVisitedLinkColor(const QColor &color = QColor());
0284     void setCustomNegativeTextColor(const QColor &color = QColor());
0285     void setCustomNeutralTextColor(const QColor &color = QColor());
0286     void setCustomPositiveTextColor(const QColor &color = QColor());
0287     // background colors
0288     void setCustomBackgroundColor(const QColor &color = QColor());
0289     void setCustomAlternateBackgroundColor(const QColor &color = QColor());
0290     void setCustomHighlightColor(const QColor &color = QColor());
0291     void setCustomActiveBackgroundColor(const QColor &color = QColor());
0292     void setCustomLinkBackgroundColor(const QColor &color = QColor());
0293     void setCustomVisitedLinkBackgroundColor(const QColor &color = QColor());
0294     void setCustomNegativeBackgroundColor(const QColor &color = QColor());
0295     void setCustomNeutralBackgroundColor(const QColor &color = QColor());
0296     void setCustomPositiveBackgroundColor(const QColor &color = QColor());
0297     // decoration colors
0298     void setCustomFocusColor(const QColor &color = QColor());
0299     void setCustomHoverColor(const QColor &color = QColor());
0300 
0301     bool useAlternateBackgroundColor() const;
0302     void setUseAlternateBackgroundColor(bool alternate);
0303 
0304     // QML attached property
0305     static PlatformTheme *qmlAttachedProperties(QObject *object);
0306 
0307 Q_SIGNALS:
0308     void colorsChanged();
0309     void defaultFontChanged(const QFont &font);
0310     void smallFontChanged(const QFont &font);
0311     void colorSetChanged(Kirigami::Platform::PlatformTheme::ColorSet colorSet);
0312     void colorGroupChanged(Kirigami::Platform::PlatformTheme::ColorGroup colorGroup);
0313     void paletteChanged(const QPalette &pal);
0314     void inheritChanged(bool inherit);
0315     void useAlternateBackgroundColorChanged(bool alternate);
0316 
0317 protected:
0318     // Setters, not accessible from QML but from implementations
0319     void setSupportsIconColoring(bool support);
0320 
0321     // foreground colors
0322     void setTextColor(const QColor &color);
0323     void setDisabledTextColor(const QColor &color);
0324     void setHighlightedTextColor(const QColor &color);
0325     void setActiveTextColor(const QColor &color);
0326     void setLinkColor(const QColor &color);
0327     void setVisitedLinkColor(const QColor &color);
0328     void setNegativeTextColor(const QColor &color);
0329     void setNeutralTextColor(const QColor &color);
0330     void setPositiveTextColor(const QColor &color);
0331 
0332     // background colors
0333     void setBackgroundColor(const QColor &color);
0334     void setAlternateBackgroundColor(const QColor &color);
0335     void setHighlightColor(const QColor &color);
0336     void setActiveBackgroundColor(const QColor &color);
0337     void setLinkBackgroundColor(const QColor &color);
0338     void setVisitedLinkBackgroundColor(const QColor &color);
0339     void setNegativeBackgroundColor(const QColor &color);
0340     void setNeutralBackgroundColor(const QColor &color);
0341     void setPositiveBackgroundColor(const QColor &color);
0342 
0343     // decoration colors
0344     void setFocusColor(const QColor &color);
0345     void setHoverColor(const QColor &color);
0346 
0347     void setDefaultFont(const QFont &defaultFont);
0348     void setSmallFont(const QFont &smallFont);
0349 
0350     bool event(QEvent *event) override;
0351 
0352 private:
0353     KIRIGAMIPLATFORM_NO_EXPORT void update();
0354     KIRIGAMIPLATFORM_NO_EXPORT void updateChildren(QObject *item);
0355     KIRIGAMIPLATFORM_NO_EXPORT void emitSignals();
0356     KIRIGAMIPLATFORM_NO_EXPORT void emitColorChanged();
0357     KIRIGAMIPLATFORM_NO_EXPORT QObject *determineParent(QObject *object);
0358 
0359     PlatformThemePrivate *d;
0360     friend class PlatformThemePrivate;
0361     friend class PlatformThemeData;
0362 };
0363 
0364 namespace PlatformThemeEvents
0365 {
0366 // To avoid the overhead of Qt's signal/slot connections, we use custom events
0367 // to communicate with subclasses. This way, we can indicate what actually
0368 // changed without needing to add new virtual functions to PlatformTheme which
0369 // would break binary compatibility.
0370 //
0371 // To handle these events in your subclass, override QObject::event() and check
0372 // if you receive one of these events, then do what is needed. Finally, make
0373 // sure to call PlatformTheme::event() since that will also do some processing
0374 // of these events.
0375 
0376 template<typename T>
0377 class KIRIGAMIPLATFORM_EXPORT PropertyChangedEvent : public QEvent
0378 {
0379 public:
0380     PropertyChangedEvent(PlatformTheme *theme, const T &previous, const T &current)
0381         : QEvent(PropertyChangedEvent<T>::type)
0382         , sender(theme)
0383         , oldValue(previous)
0384         , newValue(current)
0385     {
0386     }
0387 
0388     PlatformTheme *sender;
0389     T oldValue;
0390     T newValue;
0391 
0392     static QEvent::Type type;
0393 };
0394 
0395 using DataChangedEvent = PropertyChangedEvent<std::shared_ptr<PlatformThemeData>>;
0396 using ColorSetChangedEvent = PropertyChangedEvent<PlatformTheme::ColorSet>;
0397 using ColorGroupChangedEvent = PropertyChangedEvent<PlatformTheme::ColorGroup>;
0398 using ColorChangedEvent = PropertyChangedEvent<QColor>;
0399 using FontChangedEvent = PropertyChangedEvent<QFont>;
0400 
0401 }
0402 
0403 }
0404 } // namespace Kirigami
0405 
0406 #endif // PLATFORMTHEME_H