File indexing completed on 2024-04-28 15:27:44
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include <QQuickItem> 0010 #include <memory> 0011 0012 class PaintedRectangleItem; 0013 0014 /** 0015 * @brief Grouped property for rectangle border. 0016 * 0017 * Example usage: 0018 * @include shadowedrectangle.qml 0019 */ 0020 class BorderGroup : public QObject 0021 { 0022 Q_OBJECT 0023 /** 0024 * @brief This property holds the border's width in pixels. 0025 * 0026 * default: ``0``px 0027 */ 0028 Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY changed) 0029 /** 0030 * @brief This property holds the border's color. 0031 * 0032 * Full RGBA colors are supported. 0033 * 0034 * default: ``Qt::black`` 0035 */ 0036 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY changed) 0037 0038 public: 0039 explicit BorderGroup(QObject *parent = nullptr); 0040 0041 qreal width() const; 0042 void setWidth(qreal newWidth); 0043 0044 QColor color() const; 0045 void setColor(const QColor &newColor); 0046 0047 Q_SIGNAL void changed(); 0048 0049 inline bool isEnabled() const 0050 { 0051 return !qFuzzyIsNull(m_width); 0052 } 0053 0054 private: 0055 qreal m_width = 0.0; 0056 QColor m_color = Qt::black; 0057 }; 0058 0059 /** 0060 * @brief Grouped property for the rectangle's shadow. 0061 */ 0062 class ShadowGroup : public QObject 0063 { 0064 Q_OBJECT 0065 /** 0066 * @brief This property holds the shadow's approximate size in pixels. 0067 * @note The actual shadow size can be less than this value due to falloff. 0068 * 0069 * default: ``0``px 0070 */ 0071 Q_PROPERTY(qreal size READ size WRITE setSize NOTIFY changed) 0072 /** 0073 * @brief This property holds the shadow's offset in pixels on the X axis. 0074 * 0075 * default: ``0``px 0076 */ 0077 Q_PROPERTY(qreal xOffset READ xOffset WRITE setXOffset NOTIFY changed) 0078 /** 0079 * @brief This property holds the shadow's offset in pixels on the Y axis. 0080 * 0081 * default: ``0``px 0082 */ 0083 Q_PROPERTY(qreal yOffset READ yOffset WRITE setYOffset NOTIFY changed) 0084 /** 0085 * @brief This property holds the shadow's color. 0086 * 0087 * Full RGBA colors are supported. 0088 * 0089 * default: ``Qt::black`` 0090 */ 0091 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY changed) 0092 0093 public: 0094 explicit ShadowGroup(QObject *parent = nullptr); 0095 0096 qreal size() const; 0097 void setSize(qreal newSize); 0098 0099 qreal xOffset() const; 0100 void setXOffset(qreal newXOffset); 0101 0102 qreal yOffset() const; 0103 void setYOffset(qreal newYOffset); 0104 0105 QColor color() const; 0106 void setColor(const QColor &newShadowColor); 0107 0108 Q_SIGNAL void changed(); 0109 0110 private: 0111 qreal m_size = 0.0; 0112 qreal m_xOffset = 0.0; 0113 qreal m_yOffset = 0.0; 0114 QColor m_color = Qt::black; 0115 }; 0116 0117 /** 0118 * @brief Grouped property for corner radius. 0119 */ 0120 class CornersGroup : public QObject 0121 { 0122 Q_OBJECT 0123 /** 0124 * @brief This property holds the top-left corner's radius in pixels. 0125 * 0126 * Setting this to ``-1`` indicates that the value should be ignored. 0127 * 0128 * default: ``-1``px 0129 */ 0130 Q_PROPERTY(qreal topLeftRadius READ topLeft WRITE setTopLeft NOTIFY changed) 0131 0132 /** 0133 * @brief This property holds the top-right corner's radius in pixels. 0134 * 0135 * Setting this to ``-1`` indicates that the value should be ignored. 0136 * 0137 * default: ``-1``px 0138 */ 0139 Q_PROPERTY(qreal topRightRadius READ topRight WRITE setTopRight NOTIFY changed) 0140 0141 /** 0142 * @brief This property holds the bottom-left corner's radius in pixels. 0143 * 0144 * Setting this to ``-1`` indicates that the value should be ignored. 0145 * 0146 * default: ``-1``px 0147 */ 0148 Q_PROPERTY(qreal bottomLeftRadius READ bottomLeft WRITE setBottomLeft NOTIFY changed) 0149 0150 /** 0151 * @brief This property holds the bottom-right corner's radius in pixels. 0152 * 0153 * Setting this to ``-1`` indicates that the value should be ignored. 0154 * 0155 * default: ``-1``px 0156 */ 0157 Q_PROPERTY(qreal bottomRightRadius READ bottomRight WRITE setBottomRight NOTIFY changed) 0158 0159 public: 0160 explicit CornersGroup(QObject *parent = nullptr); 0161 0162 qreal topLeft() const; 0163 void setTopLeft(qreal newTopLeft); 0164 0165 qreal topRight() const; 0166 void setTopRight(qreal newTopRight); 0167 0168 qreal bottomLeft() const; 0169 void setBottomLeft(qreal newBottomLeft); 0170 0171 qreal bottomRight() const; 0172 void setBottomRight(qreal newBottomRight); 0173 0174 Q_SIGNAL void changed(); 0175 0176 QVector4D toVector4D(float all) const; 0177 0178 private: 0179 float m_topLeft = -1.0; 0180 float m_topRight = -1.0; 0181 float m_bottomLeft = -1.0; 0182 float m_bottomRight = -1.0; 0183 }; 0184 0185 /** 0186 * @brief A rectangle with a shadow behind it. 0187 * 0188 * This item will render a rectangle, with a shadow below it. The rendering is done 0189 * using distance fields, which provide greatly improved performance. The shadow is 0190 * rendered outside of the item's bounds, so the item's width and height are the 0191 * rectangle's width and height. 0192 * 0193 * @since KDE Frameworks 5.69 0194 * @since org.kde.kirigami 2.12 0195 */ 0196 class ShadowedRectangle : public QQuickItem 0197 { 0198 Q_OBJECT 0199 /** 0200 * @brief This property holds the radii of the rectangle's corners. 0201 * 0202 * This is the amount of rounding to apply to all of the rectangle's 0203 * corners, in pixels. Each corner can have a different radius. 0204 * 0205 * default: ``0`` 0206 * 0207 * @see ::corners 0208 */ 0209 Q_PROPERTY(qreal radius READ radius WRITE setRadius NOTIFY radiusChanged) 0210 0211 /** 0212 * @brief This property holds the rectangle's color. 0213 * 0214 * Full RGBA colors are supported. 0215 * 0216 * default: ``Qt::white`` 0217 */ 0218 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) 0219 0220 /** 0221 * @brief This property holds the border's grouped property. 0222 * 0223 * Example usage: 0224 * @code 0225 * Kirigami.ShadowedRectangle { 0226 * border.width: 2 0227 * border.color: Kirigami.Theme.textColor 0228 * } 0229 * @endcode 0230 * @see kirigami::BorderGroup 0231 */ 0232 Q_PROPERTY(BorderGroup *border READ border CONSTANT) 0233 0234 /** 0235 * @brief This property holds the shadow's grouped property. 0236 * 0237 * Example usage: 0238 * @code 0239 * Kirigami.ShadowedRectangle { 0240 * shadow.size: 20 0241 * shadow.xOffset: 5 0242 * shadow.yOffset: 5 0243 * } 0244 * @endcode 0245 * 0246 * @see kirigami::ShadowGroup 0247 */ 0248 Q_PROPERTY(ShadowGroup *shadow READ shadow CONSTANT) 0249 0250 /** 0251 * @brief This property holds the corners grouped property 0252 * 0253 * Note that the values from this group override \property radius for the 0254 * corner they affect. 0255 * 0256 * Example usage: 0257 * @code 0258 * Kirigami.ShadowedRectangle { 0259 * corners.topLeftRadius: 4 0260 * corners.topRightRadius: 5 0261 * corners.bottomLeftRadius: 2 0262 * corners.bottomRightRadius: 10 0263 * @endcode 0264 * 0265 * @see kirigami::CornersGroup 0266 */ 0267 Q_PROPERTY(CornersGroup *corners READ corners CONSTANT) 0268 0269 /** 0270 * @brief This property holds the rectangle's render mode. 0271 * 0272 * default: ``RenderType.Auto`` 0273 * 0274 * @see ::RenderType 0275 */ 0276 Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType CONSTANT) 0277 0278 /** 0279 * @brief This property specifies whether software rendering is being used. 0280 * 0281 * default: ``false`` 0282 */ 0283 Q_PROPERTY(bool softwareRendering READ isSoftwareRendering NOTIFY softwareRenderingChanged) 0284 0285 public: 0286 ShadowedRectangle(QQuickItem *parent = nullptr); 0287 ~ShadowedRectangle() override; 0288 0289 /** 0290 * @brief Available rendering types for ShadowedRectangle. 0291 */ 0292 enum RenderType { 0293 0294 /** 0295 * @brief Automatically determine the optimal rendering type. 0296 * 0297 * This will use the highest rendering quality possible, falling back to 0298 * lower quality if the hardware doesn't support it. It will use software 0299 * rendering if the QtQuick scene graph is set to use software rendering. 0300 */ 0301 Auto, 0302 0303 /** 0304 * @brief Use the highest rendering quality possible, even if the hardware might 0305 * not be able to handle it normally. 0306 */ 0307 HighQuality, 0308 0309 /** 0310 * @brief Use the lowest rendering quality, even if the hardware could handle 0311 * higher quality rendering. 0312 * 0313 * This might result in certain effects being omitted, like shadows. 0314 */ 0315 LowQuality, 0316 0317 /** 0318 * @brief Always use software rendering for this rectangle. 0319 * 0320 * Software rendering is intended as a fallback when the QtQuick scene 0321 * graph is configured to use software rendering. It will result in 0322 * a number of missing features, like shadows and multiple corner radii. 0323 */ 0324 Software 0325 }; 0326 Q_ENUM(RenderType) 0327 0328 BorderGroup *border() const; 0329 ShadowGroup *shadow() const; 0330 CornersGroup *corners() const; 0331 0332 qreal radius() const; 0333 void setRadius(qreal newRadius); 0334 Q_SIGNAL void radiusChanged(); 0335 0336 QColor color() const; 0337 void setColor(const QColor &newColor); 0338 Q_SIGNAL void colorChanged(); 0339 0340 RenderType renderType() const; 0341 void setRenderType(RenderType renderType); 0342 Q_SIGNAL void renderTypeChanged(); 0343 0344 void componentComplete() override; 0345 0346 bool isSoftwareRendering() const; 0347 0348 Q_SIGNALS: 0349 void softwareRenderingChanged(); 0350 0351 protected: 0352 PaintedRectangleItem *softwareItem() const; 0353 void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) override; 0354 QSGNode *updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *data) override; 0355 0356 private: 0357 void checkSoftwareItem(); 0358 const std::unique_ptr<BorderGroup> m_border; 0359 const std::unique_ptr<ShadowGroup> m_shadow; 0360 const std::unique_ptr<CornersGroup> m_corners; 0361 qreal m_radius = 0.0; 0362 QColor m_color = Qt::white; 0363 RenderType m_renderType = RenderType::Auto; 0364 PaintedRectangleItem *m_softwareItem = nullptr; 0365 };