File indexing completed on 2024-05-05 07:57:43
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Arjen Hiemstra <ahiemstra@heimr.nl> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #ifndef TOOLBARLAYOUT_H 0008 #define TOOLBARLAYOUT_H 0009 0010 #include <QQuickItem> 0011 #include <memory> 0012 0013 class ToolBarLayoutPrivate; 0014 0015 /** 0016 * Attached property for ToolBarLayout delegates. 0017 */ 0018 class ToolBarLayoutAttached : public QObject 0019 { 0020 Q_OBJECT 0021 /** 0022 * The action this delegate was created for. 0023 */ 0024 Q_PROPERTY(QObject *action READ action CONSTANT FINAL) 0025 public: 0026 ToolBarLayoutAttached(QObject *parent = nullptr); 0027 0028 QObject *action() const; 0029 void setAction(QObject *action); 0030 0031 private: 0032 QObject *m_action = nullptr; 0033 }; 0034 0035 /** 0036 * An item that creates delegates for actions and lays them out in a row. 0037 * 0038 * This effectively combines RowLayout and Repeater in a single item, with the 0039 * addition of some extra performance enhancing tweaks. It will create instances 0040 * of ::fullDelegate and ::itemDelegate for each action in ::actions . These are 0041 * then positioned horizontally. Any action that ends up being placed outside 0042 * the width of the item is hidden and will be part of ::hiddenActions. 0043 * 0044 * The items created as delegates are always created asynchronously, to avoid 0045 * creation lag spikes. Each delegate has access to the action it was created 0046 * for through the ToolBarLayoutAttached attached property. 0047 */ 0048 class ToolBarLayout : public QQuickItem 0049 { 0050 Q_OBJECT 0051 QML_ELEMENT 0052 QML_ATTACHED(ToolBarLayoutAttached) 0053 /** 0054 * The actions this layout should create delegates for. 0055 */ 0056 Q_PROPERTY(QQmlListProperty<QObject> actions READ actionsProperty NOTIFY actionsChanged FINAL) 0057 /** 0058 * A list of actions that do not fit in the current view and are thus hidden. 0059 */ 0060 Q_PROPERTY(QList<QObject *> hiddenActions READ hiddenActions NOTIFY hiddenActionsChanged FINAL) 0061 /** 0062 * A component that is used to create full-size delegates from. 0063 * 0064 * Each delegate has three states, it can be full-size, icon-only or hidden. 0065 * By default, the full-size delegate is used. When the action has the 0066 * DisplayHint::IconOnly hint set, it will always use the iconDelegate. When 0067 * it has the DisplayHint::KeepVisible hint set, it will use the full-size 0068 * delegate when it fits. If not, it will use the iconDelegate, unless even 0069 * that does not fit, in which case it will still be hidden. 0070 */ 0071 Q_PROPERTY(QQmlComponent *fullDelegate READ fullDelegate WRITE setFullDelegate NOTIFY fullDelegateChanged FINAL) 0072 /** 0073 * A component that is used to create icon-only delegates from. 0074 * 0075 * \sa fullDelegate 0076 */ 0077 Q_PROPERTY(QQmlComponent *iconDelegate READ iconDelegate WRITE setIconDelegate NOTIFY iconDelegateChanged FINAL) 0078 /** 0079 * A component that is used to create the "more button" item from. 0080 * 0081 * The more button is shown when there are actions that do not fit the 0082 * current view. It is intended to have functionality to show these hidden 0083 * actions, like popup a menu with them showing. 0084 */ 0085 Q_PROPERTY(QQmlComponent *moreButton READ moreButton WRITE setMoreButton NOTIFY moreButtonChanged FINAL) 0086 /** 0087 * The amount of spacing between individual delegates. 0088 */ 0089 Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged FINAL) 0090 /** 0091 * How to align the delegates within this layout. 0092 * 0093 * When there is more space available than required by the visible delegates, 0094 * we need to determine how to place the delegates. This property determines 0095 * how to do that. Note that the moreButton, if visible, will always be 0096 * placed at the end of the layout. 0097 */ 0098 Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged FINAL) 0099 /** 0100 * The combined width of visible delegates in this layout. 0101 */ 0102 Q_PROPERTY(qreal visibleWidth READ visibleWidth NOTIFY visibleWidthChanged FINAL) 0103 /** 0104 * The minimum width this layout can have. 0105 * 0106 * This is equal to the width of the moreButton. 0107 */ 0108 Q_PROPERTY(qreal minimumWidth READ minimumWidth NOTIFY minimumWidthChanged FINAL) 0109 /** 0110 * Which direction to layout in. 0111 * 0112 * This is primarily intended to support right-to-left layouts. When set to 0113 * LeftToRight, delegates will be layout with the first item on the left and 0114 * following items to the right of that. The more button will be placed at 0115 * the rightmost position. Alignment flags work normally. 0116 * 0117 * When set to RightToLeft, delegates will be layout with the first item on 0118 * the right and following items to the left of that. The more button will 0119 * be placed at the leftmost position. Alignment flags are inverted, so 0120 * AlignLeft will align items to the right, and vice-versa. 0121 */ 0122 Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged FINAL) 0123 /** 0124 * How to handle items that do not match the toolbar's height. 0125 * 0126 * When toolbar items do not match the height of the toolbar, there are 0127 * several ways we can deal with this. This property sets the preferred way. 0128 * 0129 * The default is HeightMode::ConstrainIfLarger . 0130 * 0131 * \sa HeightMode 0132 */ 0133 Q_PROPERTY(HeightMode heightMode READ heightMode WRITE setHeightMode NOTIFY heightModeChanged FINAL) 0134 0135 public: 0136 using ActionsProperty = QQmlListProperty<QObject>; 0137 0138 /** 0139 * An enum describing several modes that can be used to deal with items with 0140 * a height that does not match the toolbar's height. 0141 */ 0142 enum HeightMode { 0143 AlwaysCenter, ///< Always center items, allowing them to go outside the bounds of the layout if they are larger. 0144 AlwaysFill, ///< Always match the height of the layout. Larger items will be reduced in height, smaller items will be increased. 0145 ConstrainIfLarger, ///< If the item is larger than the toolbar, reduce its height. Otherwise center it in the toolbar. 0146 }; 0147 Q_ENUM(HeightMode) 0148 0149 ToolBarLayout(QQuickItem *parent = nullptr); 0150 ~ToolBarLayout() override; 0151 0152 ActionsProperty actionsProperty() const; 0153 /** 0154 * Add an action to the list of actions. 0155 * 0156 * \param action The action to add. 0157 */ 0158 void addAction(QObject *action); 0159 /** 0160 * Remove an action from the list of actions. 0161 * 0162 * \param action The action to remove. 0163 */ 0164 void removeAction(QObject *action); 0165 /** 0166 * Clear the list of actions. 0167 */ 0168 void clearActions(); 0169 Q_SIGNAL void actionsChanged(); 0170 0171 QList<QObject *> hiddenActions() const; 0172 Q_SIGNAL void hiddenActionsChanged(); 0173 0174 QQmlComponent *fullDelegate() const; 0175 void setFullDelegate(QQmlComponent *newFullDelegate); 0176 Q_SIGNAL void fullDelegateChanged(); 0177 0178 QQmlComponent *iconDelegate() const; 0179 void setIconDelegate(QQmlComponent *newIconDelegate); 0180 Q_SIGNAL void iconDelegateChanged(); 0181 0182 QQmlComponent *moreButton() const; 0183 void setMoreButton(QQmlComponent *newMoreButton); 0184 Q_SIGNAL void moreButtonChanged(); 0185 0186 qreal spacing() const; 0187 void setSpacing(qreal newSpacing); 0188 Q_SIGNAL void spacingChanged(); 0189 0190 Qt::Alignment alignment() const; 0191 void setAlignment(Qt::Alignment newAlignment); 0192 Q_SIGNAL void alignmentChanged(); 0193 0194 qreal visibleWidth() const; 0195 Q_SIGNAL void visibleWidthChanged(); 0196 0197 qreal minimumWidth() const; 0198 Q_SIGNAL void minimumWidthChanged(); 0199 0200 Qt::LayoutDirection layoutDirection() const; 0201 void setLayoutDirection(Qt::LayoutDirection &newLayoutDirection); 0202 Q_SIGNAL void layoutDirectionChanged(); 0203 0204 HeightMode heightMode() const; 0205 void setHeightMode(HeightMode newHeightMode); 0206 Q_SIGNAL void heightModeChanged(); 0207 0208 /** 0209 * Queue a relayout of this layout. 0210 * 0211 * \note The layouting happens during the next scene graph polishing phase. 0212 */ 0213 Q_SLOT void relayout(); 0214 0215 static ToolBarLayoutAttached *qmlAttachedProperties(QObject *object) 0216 { 0217 return new ToolBarLayoutAttached(object); 0218 } 0219 0220 protected: 0221 void componentComplete() override; 0222 void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; 0223 void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data) override; 0224 void updatePolish() override; 0225 0226 private: 0227 friend class ToolBarLayoutPrivate; 0228 const std::unique_ptr<ToolBarLayoutPrivate> d; 0229 }; 0230 0231 QML_DECLARE_TYPEINFO(ToolBarLayout, QML_HAS_ATTACHED_PROPERTIES) 0232 0233 #endif // TOOLBARLAYOUT_H