File indexing completed on 2024-04-28 15:27:44

0001 /*
0002  *  SPDX-FileCopyrightText: 2020 Carson Black <uhhadd@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 
0007 #pragma once
0008 
0009 #include <QMap>
0010 #include <QObject>
0011 #include <QPair>
0012 #include <QPointer>
0013 #include <QQmlListProperty>
0014 #include <QQmlParserStatus>
0015 #include <QQuickItem>
0016 
0017 /**
0018  * @brief SizeGroup is a utility object that makes groups of items request the
0019  * same size.
0020  *
0021  * This can be instantiated to automatically manage the height, width, or both
0022  * sizes of multiple items based on the item with the highest value. In other
0023  * words, if widths are synchronized, all items being managed by a SizeGroup
0024  * will have the same preferredWidth as the item with the largest implicitWidth.
0025  *
0026  * Pass a JavaScript array of ::items to be managed by this object, then set the
0027  * ::mode property to define which size to synchronize.
0028  *
0029  * @note Manually setting a width or height for items managed by a SizeGroup
0030  * will override the width or height calculated by the instantiated SizeGroup.
0031  *
0032  * @note All objects managed by a SizeGroup must belong to a Layout. This
0033  * includes Kirigami-specific Layouts such as org::kde::kirigami::FormLayout.
0034  *
0035  * @include sizegroup.qml
0036  */
0037 class SizeGroup : public QObject, public QQmlParserStatus
0038 {
0039     Q_OBJECT
0040     Q_INTERFACES(QQmlParserStatus)
0041 
0042 public:
0043     enum Mode {
0044         /**
0045          * @brief SizeGroup does nothing.
0046          */
0047         None = 0,
0048 
0049         /**
0050          * @brief SizeGroup syncs item widths.
0051          */
0052         Width = 1,
0053 
0054         /**
0055          * @brief SizeGroup syncs item heights.
0056          */
0057         Height = 2,
0058 
0059         /**
0060          * @brief SizeGroup syncs both item widths and heights
0061          */
0062         Both = 3,
0063     };
0064     Q_ENUM(Mode)
0065     Q_DECLARE_FLAGS(Modes, Mode)
0066 
0067 private:
0068     Mode m_mode = None;
0069     QList<QPointer<QQuickItem>> m_items;
0070     QMap<QQuickItem *, QPair<QMetaObject::Connection, QMetaObject::Connection>> m_connections;
0071 
0072 public:
0073     /**
0074      * @brief This property sets which dimensions this SizeGroup should sync.
0075      */
0076     Q_PROPERTY(Mode mode MEMBER m_mode NOTIFY modeChanged)
0077     Q_SIGNAL void modeChanged();
0078 
0079     /**
0080      * @brief This property holds a list of items this SizeGroup should adjust.
0081      */
0082     Q_PROPERTY(QQmlListProperty<QQuickItem> items READ items CONSTANT)
0083     QQmlListProperty<QQuickItem> items();
0084 
0085     void adjustItems(Mode whatChanged);
0086     void connectItem(QQuickItem *item);
0087 
0088     /**
0089      * @brief This method forces the SizeGroup to relayout its items.
0090      *
0091      * Normally this is never needed as the SizeGroup automatically relayouts
0092      * items as they're added and their sizes change.
0093      */
0094     Q_INVOKABLE void relayout();
0095 
0096     void classBegin() override
0097     {
0098     }
0099     void componentComplete() override;
0100 
0101 private:
0102     static void appendItem(QQmlListProperty<QQuickItem> *prop, QQuickItem *value);
0103 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0104     static int itemCount(QQmlListProperty<QQuickItem> *prop);
0105     static QQuickItem *itemAt(QQmlListProperty<QQuickItem> *prop, int index);
0106 #else
0107     static qsizetype itemCount(QQmlListProperty<QQuickItem> *prop);
0108     static QQuickItem *itemAt(QQmlListProperty<QQuickItem> *prop, qsizetype index);
0109 #endif
0110     static void clearItems(QQmlListProperty<QQuickItem> *prop);
0111 };