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