File indexing completed on 2024-05-12 05:38:56

0001 /* SPDX-FileCopyrightText: 2017 The Qt Company Ltd.
0002  * SPDX-FileCopyrightText: 2020 Noah Davis <noahadvs@gmail.com>
0003  * SPDX-License-Identifier: LGPL-3.0-only OR GPL-2.0-or-later
0004  */
0005 
0006 #ifndef ICONLABELLAYOUT_H
0007 #define ICONLABELLAYOUT_H
0008 
0009 #include "qquickicon_p.h"
0010 #include <QQuickItem>
0011 #include <memory>
0012 
0013 class IconLabelLayoutPrivate;
0014 
0015 /**
0016  * An item that is meant to show, hide and position an icon item and a label item based on an AbstractButton's display property.
0017  *
0018  * You can also set the alignment of the icon and label as a group.
0019  *
0020  * For example, this aligns the icon and label to the left side and vertical center of this item.
0021  *
0022  * ```qml
0023  * alignment: Qt.AlignLeft | Qt.AlignVCenter
0024  * ```
0025  *
0026  * The result will look like this if there is enough availableWidth and the display type is TextUnderIcon:
0027  *
0028  * ```
0029  * +-----------------+
0030  * |                 |
0031  * |   ▶             |
0032  * | label           |
0033  * |                 |
0034  * +-----------------+
0035  * ```
0036  *
0037  * The default alignment is Qt.AlignCenter and the default display type is TextBesideIcon, which looks like this:
0038  *
0039  * ```
0040  * +-----------------+
0041  * |                 |
0042  * |     ▶ label     |
0043  * |                 |
0044  * +-----------------+
0045  * ```
0046  *
0047  * You cannot separate the icon and label from each other.
0048  * They will always move together in the orientation specified by the display property.
0049  *
0050  * @note: This class was adapted from QtQuick.Control.impl IconLabel
0051  */
0052 class IconLabelLayout : public QQuickItem
0053 {
0054     Q_OBJECT
0055     /* Using components because I don't want anyone to mess with the icon or label items externally.
0056      * Unfortunately, it's not possible to just create items directly.
0057      * For the icon, I could reimplement Kirigami Icon, but that would be more work and code to manage.
0058      * There's no point in using this layout if you're not going to define both, so both are required.
0059      * There's also no point in allowing the components to be read externally.
0060      */
0061     Q_PROPERTY(QQmlComponent *iconComponent READ iconComponent WRITE setIconComponent FINAL REQUIRED)
0062     Q_PROPERTY(QQmlComponent *labelComponent READ labelComponent WRITE setLabelComponent FINAL REQUIRED)
0063 
0064     Q_PROPERTY(bool hasIcon READ hasIcon NOTIFY hasIconChanged FINAL)
0065     Q_PROPERTY(bool hasLabel READ hasLabel NOTIFY hasLabelChanged FINAL)
0066 
0067     // qqc2-breeze-style has its own copy/pasted implementation of QQuickIcon
0068     Q_PROPERTY(Breeze::QQuickIcon icon READ icon WRITE setIcon NOTIFY iconChanged FINAL)
0069     Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
0070     Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
0071     Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
0072 
0073     // convenient for aligning things with the icon or label
0074     Q_PROPERTY(QRectF iconRect READ iconRect NOTIFY iconRectChanged FINAL)
0075     Q_PROPERTY(QRectF labelRect READ labelRect NOTIFY labelRectChanged FINAL)
0076 
0077     // The width or height of IconLabelLayout, minus left and right padding or top and bottom padding
0078     Q_PROPERTY(qreal availableWidth READ availableWidth NOTIFY availableWidthChanged FINAL)
0079     Q_PROPERTY(qreal availableHeight READ availableHeight NOTIFY availableHeightChanged FINAL)
0080 
0081     // The amount of space between the icon and the label.
0082     Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged FINAL)
0083 
0084     // The minimum amount of space around the icon and label.
0085     Q_PROPERTY(qreal leftPadding READ leftPadding WRITE setLeftPadding NOTIFY leftPaddingChanged FINAL)
0086     Q_PROPERTY(qreal rightPadding READ rightPadding WRITE setRightPadding NOTIFY rightPaddingChanged FINAL)
0087     Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding NOTIFY topPaddingChanged FINAL)
0088     Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding NOTIFY bottomPaddingChanged FINAL)
0089 
0090     // Whether or not a right to left layout should be used
0091     Q_PROPERTY(bool mirrored READ mirrored WRITE setMirrored NOTIFY mirroredChanged FINAL)
0092 
0093     // The position of the icon and label as a group within IconLabelLayout.
0094     Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged FINAL)
0095 
0096     // The visibility and position of icon and label relative to each other.
0097     Q_PROPERTY(Display display READ display WRITE setDisplay NOTIFY displayChanged FINAL)
0098 
0099     // Convenience functions to check what display type is being used
0100     Q_PROPERTY(bool iconOnly READ iconOnly NOTIFY iconOnlyChanged FINAL)
0101     Q_PROPERTY(bool textOnly READ textOnly NOTIFY textOnlyChanged FINAL)
0102     Q_PROPERTY(bool textBesideIcon READ textBesideIcon NOTIFY textBesideIconChanged FINAL)
0103     Q_PROPERTY(bool textUnderIcon READ textUnderIcon NOTIFY textUnderIconChanged FINAL)
0104 
0105     QML_NAMED_ELEMENT(IconLabelLayout)
0106 
0107 public:
0108     enum Display {
0109         IconOnly,
0110         TextOnly,
0111         TextBesideIcon,
0112         TextUnderIcon,
0113     };
0114     Q_ENUM(Display)
0115 
0116     explicit IconLabelLayout(QQuickItem *parent = nullptr);
0117     ~IconLabelLayout();
0118 
0119     QQmlComponent *iconComponent() const;
0120     void setIconComponent(QQmlComponent *iconComponent);
0121 
0122     QQmlComponent *labelComponent() const;
0123     void setLabelComponent(QQmlComponent *labelComponent);
0124 
0125     bool hasIcon() const;
0126     void setHasIcon();
0127     bool hasLabel() const;
0128     void setHasLabel();
0129 
0130     Breeze::QQuickIcon icon() const;
0131     void setIcon(const Breeze::QQuickIcon &icon);
0132 
0133     QString text() const;
0134     void setText(const QString &text);
0135 
0136     QFont font() const;
0137     void setFont(const QFont &font);
0138 
0139     QColor color() const;
0140     void setColor(const QColor &color);
0141 
0142     QRectF iconRect() const;
0143     void setIconRect(const QRectF &rect);
0144     QRectF labelRect() const;
0145     void setLabelRect(const QRectF &rect);
0146 
0147     qreal availableWidth() const;
0148     void setAvailableWidth();
0149     qreal availableHeight() const;
0150     void setAvailableHeight();
0151 
0152     qreal spacing() const;
0153     void setSpacing(qreal spacing);
0154     void resetSpacing();
0155 
0156     qreal leftPadding() const;
0157     void setLeftPadding(qreal leftPadding);
0158     void resetLeftPadding();
0159 
0160     qreal rightPadding() const;
0161     void setRightPadding(qreal rightPadding);
0162     void resetRightPadding();
0163 
0164     qreal topPadding() const;
0165     void setTopPadding(qreal topPadding);
0166     void resetTopPadding();
0167 
0168     qreal bottomPadding() const;
0169     void setBottomPadding(qreal bottomPadding);
0170     void resetBottomPadding();
0171 
0172     bool mirrored() const;
0173     void setMirrored(bool mirrored);
0174 
0175     Qt::Alignment alignment() const;
0176     void setAlignment(Qt::Alignment alignment);
0177 
0178     Display display() const;
0179     void setDisplay(Display display);
0180 
0181     bool iconOnly() const;
0182     bool textOnly() const;
0183     bool textBesideIcon() const;
0184     bool textUnderIcon() const;
0185 
0186 Q_SIGNALS:
0187     void iconComponentChanged();
0188     void labelComponentChanged();
0189     void hasIconChanged();
0190     void hasLabelChanged();
0191     void iconChanged();
0192     void textChanged(const QString &text);
0193     void fontChanged(const QFont &font);
0194     void colorChanged();
0195     void iconRectChanged();
0196     void labelRectChanged();
0197 
0198     void availableWidthChanged();
0199     void availableHeightChanged();
0200 
0201     void spacingChanged();
0202     void topPaddingChanged();
0203     void leftPaddingChanged();
0204     void rightPaddingChanged();
0205     void bottomPaddingChanged();
0206 
0207     void mirroredChanged();
0208     void alignmentChanged();
0209     void displayChanged();
0210     void iconOnlyChanged();
0211     void textOnlyChanged();
0212     void textBesideIconChanged();
0213     void textUnderIconChanged();
0214 
0215 public:
0216     Q_SLOT void relayout();
0217 
0218 protected:
0219     void componentComplete() override;
0220     void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override;
0221 
0222 private:
0223     const QScopedPointer<IconLabelLayoutPrivate> d_ptr;
0224     Q_DECLARE_PRIVATE(IconLabelLayout)
0225     Q_DISABLE_COPY(IconLabelLayout)
0226 };
0227 
0228 QML_DECLARE_TYPE(IconLabelLayout)
0229 
0230 #endif