File indexing completed on 2024-04-28 15:27:42
0001 /* 0002 * SPDX-FileCopyrightText: 2011 Marco Martin <mart@kde.org> 0003 * SPDX-FileCopyrightText: 2014 Aleix Pol Gonzalez <aleixpol@blue-systems.com> 0004 * SPDX-FileCopyrightText: 2020 Carson Black <uhhadd@gmail.com> 0005 * 0006 * SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #pragma once 0010 0011 #include <QIcon> 0012 #include <QPointer> 0013 #include <QQuickItem> 0014 #include <QVariant> 0015 0016 class QNetworkReply; 0017 0018 namespace Kirigami 0019 { 0020 class PlatformTheme; 0021 } 0022 0023 /** 0024 * Class for rendering an icon in UI. 0025 */ 0026 class Icon : public QQuickItem 0027 { 0028 Q_OBJECT 0029 0030 /** 0031 * @brief This property holds the source of this icon. 0032 * 0033 * The icon can be pulled from: 0034 * * The Freedesktop standard icon name: 0035 * @include icon/IconThemeSource.qml 0036 * * The filesystem: 0037 * @include icon/FilesystemSource.qml 0038 * * Remote URIs: 0039 * @include icon/InternetSource.qml 0040 * * Custom providers: 0041 * @include icon/CustomSource.qml 0042 * * Your application's bundled resources: 0043 * @include icon/ResourceSource.qml 0044 * 0045 * @note See https://doc.qt.io/qt-5/qtquickcontrols2-icons.html for how to 0046 * bundle icon themes in your application to refer to them by name instead of 0047 * by resource URL. 0048 * 0049 * @note Use `fallback` to provide a fallback theme name for icons. 0050 * 0051 * @note Cuttlefish is a KDE application that lets you view all the icons that 0052 * you can use for your application. It offers a number of useful features such 0053 * as previews of their appearance across different installed themes, previews 0054 * at different sizes, and more. You might find it a useful tool when deciding 0055 * on which icons to use in your application. 0056 */ 0057 Q_PROPERTY(QVariant source READ source WRITE setSource NOTIFY sourceChanged) 0058 0059 /** 0060 * @brief This property holds the name of an icon from the icon theme 0061 * as a fallback for when an icon set with the ``source`` property is not found. 0062 * 0063 * @include icon/Fallback.qml 0064 * @note This will only be loaded if source is unavailable (e.g. it doesn't exist, or network issues have prevented loading). 0065 */ 0066 Q_PROPERTY(QString fallback READ fallback WRITE setFallback NOTIFY fallbackChanged) 0067 0068 /** 0069 * @brief This property holds the name of an icon from the icon theme to show 0070 * while the icon set in `source` is being loaded. 0071 * 0072 * This will only be used if the source image is a type that can have such a 0073 * long loading time that showing a temporary image in its place makes sense 0074 * (e.g. a remote image, or an image from an ImageProvider of the type 0075 * QtQml.QQmlImageProviderBase.ImageResponse). 0076 * 0077 * default: ``"image-png"`` 0078 * 0079 * @since KDE Frameworks 5.15 0080 */ 0081 Q_PROPERTY(QString placeholder READ placeholder WRITE setPlaceholder NOTIFY placeholderChanged) 0082 0083 /** 0084 * @brief This property sets whether the icon will use the 0085 * @link QtGui.QIcon.Mode QIcon.Active @endlink mode, 0086 * resulting in a graphical effect being applied when the icon is currently active. 0087 * 0088 * @note This is typically used to indicate when an item is being hovered or pressed. 0089 * 0090 * @image html icon/active.png 0091 * 0092 * The color differences under the default KDE color palette, Breeze. Note 0093 * that a dull highlight background is typically displayed behind active icons and 0094 * it is recommended to add one if you are creating a custom component. 0095 * 0096 * default: ``false`` 0097 */ 0098 Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) 0099 0100 /** 0101 * @brief This property specifies whether the icon's `source` is valid and is being used. 0102 */ 0103 Q_PROPERTY(bool valid READ valid NOTIFY validChanged) 0104 0105 /** 0106 * @brief This property sets whether the icon will use the 0107 * @link QtGui.QIcon.Mode QIcon.Selected @endlink mode, 0108 * resulting in a graphical effect being applied when the icon is currently selected. 0109 * 0110 * This is typically used to indicate when a list item is currently selected. 0111 * 0112 * @image html icon/selected.png 0113 * 0114 * The color differences under the default KDE color palette, Breeze. Note 0115 * that a blue background is typically displayed behind selected elements. 0116 * 0117 * default: ``false`` 0118 */ 0119 Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectedChanged) 0120 0121 /** 0122 * @brief This property sets whether this icon will be treated as a mask. 0123 * 0124 * When an icon is being used as a mask, all non-transparent colors are replaced 0125 * with the color provided in the Icon's ::color property. 0126 * 0127 * default: ``false`` 0128 * 0129 * @see ::color 0130 */ 0131 Q_PROPERTY(bool isMask READ isMask WRITE setIsMask NOTIFY isMaskChanged) 0132 0133 /** 0134 * @brief This property holds the color to use when drawing the icon. 0135 * 0136 * This property is used only when ::isMask is set to true. 0137 * If this property is not set or is `Qt::transparent`, the icon will use 0138 * the text or the selected text color, depending on if ::selected is set to 0139 * true. 0140 * 0141 * default: ``Qt::transparent`` 0142 * @see Qt::GlobalColor 0143 */ 0144 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) 0145 0146 /** 0147 * @brief This property specifies the status of the icon. 0148 * 0149 * @note Image loading will not be initiated until the item is shown, so if the Icon is not visible, 0150 * it can only have Null or Loading states. 0151 * 0152 * default: ``Status::Null`` 0153 * 0154 * @since KDE Frameworks 5.15 0155 */ 0156 Q_PROPERTY(Icon::Status status READ status NOTIFY statusChanged) 0157 0158 /** 0159 * @brief This property holds the width of the painted area in pixels. 0160 * 0161 * This will be smaller than or equal to the width of the area 0162 * taken up by the Item itself. This can be 0. 0163 * 0164 * default: ``0.0`` 0165 * 0166 * @since KDE Frameworks 5.15 0167 */ 0168 Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedAreaChanged) 0169 0170 /** 0171 * @brief This property holds the height of the painted area in pixels. 0172 * 0173 * This will be smaller than or equal to the height of the area 0174 * taken up by the Item itself. This can be 0. 0175 * 0176 * default: ``0.0`` 0177 * 0178 * @since KDE Frameworks 5.15 0179 */ 0180 Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedAreaChanged) 0181 public: 0182 /** 0183 * @brief This enum indicates the current status of the icon. 0184 */ 0185 enum Status { 0186 /** 0187 * @brief No icon source has been set. 0188 */ 0189 Null = 0, 0190 0191 /** 0192 * @brief The icon has been loaded correctly. 0193 */ 0194 Ready, 0195 0196 /** 0197 * @brief The icon is currently being loaded. 0198 */ 0199 Loading, 0200 0201 /** 0202 * @brief There was an error while loading the icon, for instance 0203 * a non existent themed name, or an invalid url. 0204 */ 0205 Error, 0206 }; 0207 Q_ENUM(Status) 0208 0209 Icon(QQuickItem *parent = nullptr); 0210 ~Icon() override; 0211 0212 void setSource(const QVariant &source); 0213 QVariant source() const; 0214 0215 void setActive(bool active = true); 0216 bool active() const; 0217 0218 bool valid() const; 0219 0220 void setSelected(bool selected = true); 0221 bool selected() const; 0222 0223 void setIsMask(bool mask); 0224 bool isMask() const; 0225 0226 void setColor(const QColor &color); 0227 QColor color() const; 0228 0229 QString fallback() const; 0230 void setFallback(const QString &fallback); 0231 0232 QString placeholder() const; 0233 void setPlaceholder(const QString &placeholder); 0234 0235 Status status() const; 0236 0237 qreal paintedWidth() const; 0238 qreal paintedHeight() const; 0239 0240 QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *data) override; 0241 0242 Q_SIGNALS: 0243 void sourceChanged(); 0244 void activeChanged(); 0245 void validChanged(); 0246 void selectedChanged(); 0247 void isMaskChanged(); 0248 void colorChanged(); 0249 void fallbackChanged(const QString &fallback); 0250 void placeholderChanged(const QString &placeholder); 0251 void statusChanged(); 0252 void paintedAreaChanged(); 0253 0254 protected: 0255 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0256 void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; 0257 #else 0258 void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; 0259 #endif 0260 QImage findIcon(const QSize &size); 0261 void handleFinished(QNetworkReply *reply); 0262 void handleRedirect(QNetworkReply *reply); 0263 QIcon::Mode iconMode() const; 0264 bool guessMonochrome(const QImage &img); 0265 void setStatus(Status status); 0266 void updatePolish() override; 0267 void updatePaintedGeometry(); 0268 void updateIsMaskHeuristic(const QString &iconSource); 0269 void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) override; 0270 0271 private: 0272 Kirigami::PlatformTheme *m_theme = nullptr; 0273 QPointer<QNetworkReply> m_networkReply; 0274 QHash<int, bool> m_monochromeHeuristics; 0275 QVariant m_source; 0276 Status m_status = Null; 0277 bool m_changed; 0278 bool m_active; 0279 bool m_selected; 0280 bool m_isMask; 0281 bool m_isMaskHeuristic = false; 0282 QImage m_loadedImage; 0283 QColor m_color = Qt::transparent; 0284 QString m_fallback = QStringLiteral("unknown"); 0285 QString m_placeholder = QStringLiteral("image-png"); 0286 qreal m_paintedWidth = 0.0; 0287 qreal m_paintedHeight = 0.0; 0288 0289 QImage m_icon; 0290 };