File indexing completed on 2024-05-05 04:46:58
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 namespace Maui 0018 { 0019 class PlatformTheme; 0020 } 0021 0022 /** 0023 * Class for rendering an icon in UI. 0024 */ 0025 class Icon : public QQuickItem 0026 { 0027 Q_OBJECT 0028 QML_NAMED_ELEMENT(PrivateIcon) 0029 0030 /** 0031 * The source of this icon. An `Icon` can pull from: 0032 * 0033 * * The icon theme: 0034 * @include icon/IconThemeSource.qml 0035 * * The filesystem: 0036 * @include icon/FilesystemSource.qml 0037 * * Remote URIs: 0038 * @include icon/InternetSource.qml 0039 * * Custom providers: 0040 * @include icon/CustomSource.qml 0041 * * Your application's bundled resources: 0042 * @include icon/ResourceSource.qml 0043 * 0044 * @note See https://doc.qt.io/qt-5/qtquickcontrols2-icons.html for how to 0045 * bundle icon themes in your application to refer to them by name instead of 0046 * by resource URL. 0047 * 0048 * @note Use `fallback` to provide a fallback theme name for icons. 0049 * 0050 * @note Cuttlefish is a KDE application that lets you view all the icons that 0051 * you can use for your application. It offers a number of useful features such 0052 * as previews of their appearance across different installed themes, previews 0053 * at different sizes, and more. You might find it a useful tool when deciding 0054 * on which icons to use in your application. 0055 */ 0056 Q_PROPERTY(QVariant source READ source WRITE setSource NOTIFY sourceChanged) 0057 0058 /** 0059 * The name of a fallback icon to load from the icon theme when the `source` 0060 * cannot be found. The default fallback icon is `"unknown"`. 0061 * 0062 * @include icon/Fallback.qml 0063 * 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 * The name of an icon from the icon theme to show while the icon set in `source` is 0070 * being loaded. This is primarily relevant for remote sources, or those using slow- 0071 * loading image providers. The default temporary icon is `"image-x-icon"` 0072 * 0073 * @note This will only be loaded if the source is a type which can be so long-loading 0074 * that a temporary image makes sense (e.g. a remote image, or from an ImageProvider 0075 * of the type QQmlImageProviderBase::ImageResponse) 0076 * 0077 * @since 5.15 0078 */ 0079 Q_PROPERTY(QString placeholder READ placeholder WRITE setPlaceholder NOTIFY placeholderChanged) 0080 0081 /** 0082 * Whether this icon will use the QIcon::Active mode when drawing the icon, 0083 * resulting in a graphical effect being applied to the icon to indicate that 0084 * it is currently active. 0085 * 0086 * This is typically used to indicate when an item is being hovered or pressed. 0087 * 0088 * @image html icon/active.png 0089 * 0090 * The color differences under the default KDE color palette, Breeze. Note 0091 * that a dull highlight background is typically displayed behind active icons and 0092 * it is recommended to add one if you are creating a custom component. 0093 */ 0094 Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged) 0095 0096 /** 0097 * Whether this icon's `source` is valid and it is being used. 0098 */ 0099 Q_PROPERTY(bool valid READ valid NOTIFY validChanged) 0100 0101 /** 0102 * Whether this icon will use the QIcon::Selected mode when drawing the icon, 0103 * resulting in a graphical effect being applied to the icon to indicate that 0104 * it is currently selected. 0105 * 0106 * This is typically used to indicate when a list item is currently selected. 0107 * 0108 * @image html icon/selected.png 0109 * 0110 * The color differences under the default KDE color palette, Breeze. Note 0111 * that a blue background is typically displayed behind selected elements. 0112 */ 0113 Q_PROPERTY(bool selected READ selected WRITE setSelected NOTIFY selectedChanged) 0114 0115 /** 0116 * Whether this icon will be treated as a mask. When an icon is being used 0117 * as a mask, all non-transparent colors are replaced with the color provided in the Icon's 0118 * @link Icon::color color @endlink property. 0119 * 0120 * @see color 0121 */ 0122 Q_PROPERTY(bool isMask READ isMask WRITE setIsMask NOTIFY isMaskChanged) 0123 0124 /** 0125 * The color to use when drawing this icon when `isMask` is enabled. 0126 * If this property is not set or is `Qt::transparent`, the icon will use 0127 * the text or the selected text color, depending on if `selected` is set to 0128 * true. 0129 */ 0130 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) 0131 0132 /** 0133 * Whether the icon is correctly loaded, is asynchronously loading or there was an error. 0134 * Note that image loading will not be initiated until the item is shown, so if the Icon is not visible, 0135 * it can only have Null or Loading states. 0136 * @since 5.15 0137 */ 0138 Q_PROPERTY(Icon::Status status READ status NOTIFY statusChanged) 0139 0140 /** 0141 * The width of the painted area measured in pixels. This will be smaller than or 0142 * equal to the width of the area taken up by the Item itself. This can be 0. 0143 * 0144 * @since 5.15 0145 */ 0146 Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedAreaChanged) 0147 0148 /** 0149 * The height of the painted area measured in pixels. This will be smaller than or 0150 * equal to the height of the area taken up by the Item itself. This can be 0. 0151 * 0152 * @since 5.15 0153 */ 0154 Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedAreaChanged) 0155 public: 0156 enum Status { 0157 Null = 0, /// No icon has been set 0158 Ready, /// The icon loaded correctly 0159 Loading, // The icon is being loaded, but not ready yet 0160 Error, /// There was an error while loading the icon, for instance a non existent themed name, or an invalid url 0161 }; 0162 Q_ENUM(Status) 0163 0164 Icon(QQuickItem *parent = nullptr); 0165 ~Icon() override; 0166 0167 void setSource(const QVariant &source); 0168 QVariant source() const; 0169 0170 void setActive(bool active = true); 0171 bool active() const; 0172 0173 bool valid() const; 0174 0175 void setSelected(bool selected = true); 0176 bool selected() const; 0177 0178 void setIsMask(bool mask); 0179 bool isMask() const; 0180 0181 void setColor(const QColor &color); 0182 QColor color() const; 0183 0184 QString fallback() const; 0185 void setFallback(const QString &fallback); 0186 0187 QString placeholder() const; 0188 void setPlaceholder(const QString &placeholder); 0189 0190 Status status() const; 0191 0192 qreal paintedWidth() const; 0193 qreal paintedHeight() const; 0194 0195 QSGNode *updatePaintNode(QSGNode *node, UpdatePaintNodeData *data) override; 0196 0197 public Q_SLOTS: 0198 void refresh(); 0199 0200 Q_SIGNALS: 0201 void sourceChanged(); 0202 void activeChanged(); 0203 void validChanged(); 0204 void selectedChanged(); 0205 void isMaskChanged(); 0206 void colorChanged(); 0207 void fallbackChanged(const QString &fallback); 0208 void placeholderChanged(const QString &placeholder); 0209 void statusChanged(); 0210 void paintedAreaChanged(); 0211 0212 protected: 0213 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0214 void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; 0215 #else 0216 void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; 0217 #endif 0218 QImage findIcon(const QSize &size); 0219 void handleFinished(QNetworkReply *reply); 0220 void handleRedirect(QNetworkReply *reply); 0221 QIcon::Mode iconMode() const; 0222 bool guessMonochrome(const QImage &img); 0223 void setStatus(Status status); 0224 void updatePolish() override; 0225 void updatePaintedGeometry(); 0226 void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) override; 0227 0228 private: 0229 Maui::PlatformTheme *m_theme = nullptr; 0230 QPointer<QNetworkReply> m_networkReply; 0231 QHash<int, bool> m_monochromeHeuristics; 0232 QVariant m_source; 0233 Status m_status = Null; 0234 bool m_changed; 0235 bool m_active; 0236 bool m_selected; 0237 bool m_isMask; 0238 bool m_isMaskHeuristic = false; 0239 QImage m_loadedImage; 0240 QColor m_color = Qt::transparent; 0241 QString m_fallback = QStringLiteral("unknown"); 0242 QString m_placeholder = QStringLiteral("image-png"); 0243 qreal m_paintedWidth = 0.0; 0244 qreal m_paintedHeight = 0.0; 0245 0246 QImage m_icon; 0247 0248 };