File indexing completed on 2024-04-28 15:27:41
0001 /* 0002 * SPDX-FileCopyrightText: 2019 Marco Martin <mart@kde.org> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include <QPointer> 0010 #include <QQuickItem> 0011 #include <QVariant> 0012 0013 class ContentItem; 0014 class ColumnView; 0015 0016 class ScrollIntentionEvent : public QObject 0017 { 0018 Q_OBJECT 0019 Q_PROPERTY(QPointF delta MEMBER delta CONSTANT) 0020 Q_PROPERTY(bool accepted MEMBER accepted) 0021 public: 0022 ScrollIntentionEvent() 0023 { 0024 } 0025 ~ScrollIntentionEvent() override 0026 { 0027 } 0028 0029 QPointF delta; 0030 bool accepted = false; 0031 }; 0032 0033 /** 0034 * This attached property is available to every child Item of the ColumnView, 0035 * giving access to view and page information such as position and information for layouting. 0036 * @since org.kde.kirigami 2.7 0037 */ 0038 class ColumnViewAttached : public QObject 0039 { 0040 Q_OBJECT 0041 0042 /** 0043 * @brief The index position of the column in the view, starting from 0. 0044 */ 0045 Q_PROPERTY(int index READ index WRITE setIndex NOTIFY indexChanged) 0046 0047 /** 0048 * @brief This property sets whether the item will expand and take the whole viewport space minus the ::reservedSpace. 0049 */ 0050 Q_PROPERTY(bool fillWidth READ fillWidth WRITE setFillWidth NOTIFY fillWidthChanged) 0051 0052 /** 0053 * @brief This property holds the reserved space in pixels 0054 * applied to every item with ::fillWidth set to @c true. 0055 * 0056 * Every item that has ::fillWidth set to @c true will subtract this amount from the viewports width. 0057 */ 0058 Q_PROPERTY(qreal reservedSpace READ reservedSpace WRITE setReservedSpace NOTIFY reservedSpaceChanged) 0059 0060 /** 0061 * @brief This property sets whether the column view will manage input 0062 * events from its children. 0063 * 0064 * The ColumnView uses an 0065 * <a href="https://doc.qt.io/qt-5/eventsandfilters.html#event-filters">event filter</a> 0066 * to intercept information about its children like layouting information. 0067 * This may conflict with its children input events in special cases. 0068 * 0069 * If you want to guarantee that a child of the column view will not be 0070 * intercepted by this event filter and that input events are managed by the 0071 * child, set this to @c true. 0072 * 0073 * This is desirable in special cases where a component has a single purpose 0074 * and is managed solely via input events, such as a map or document viewer. 0075 * 0076 * @see <a href="https://doc.qt.io/qt-5/qml-qtquick-mousearea.html#preventStealing-prop">MouseArea.preventStealing</a> 0077 */ 0078 Q_PROPERTY(bool preventStealing READ preventStealing WRITE setPreventStealing NOTIFY preventStealingChanged) 0079 0080 /** 0081 * @brief This property sets whether this page will always be visible. 0082 * 0083 * When set to @c true, the page will either stay at the left or right side. 0084 */ 0085 Q_PROPERTY(bool pinned READ isPinned WRITE setPinned NOTIFY pinnedChanged) 0086 0087 /** 0088 * @brief This is an attached property for Items to directly access the ColumnView. 0089 */ 0090 Q_PROPERTY(ColumnView *view READ view NOTIFY viewChanged) 0091 0092 /** 0093 * @brief This property holds whether this column is at least partly visible in ColumnView's viewport. 0094 * @since KDE Frameworks 5.77 0095 */ 0096 Q_PROPERTY(bool inViewport READ inViewport NOTIFY inViewportChanged) 0097 0098 public: 0099 ColumnViewAttached(QObject *parent = nullptr); 0100 ~ColumnViewAttached() override; 0101 0102 void setIndex(int index); 0103 int index() const; 0104 0105 void setFillWidth(bool fill); 0106 bool fillWidth() const; 0107 0108 qreal reservedSpace() const; 0109 void setReservedSpace(qreal space); 0110 0111 ColumnView *view(); 0112 void setView(ColumnView *view); 0113 0114 // Private API, not for QML use 0115 QQuickItem *originalParent() const; 0116 void setOriginalParent(QQuickItem *parent); 0117 0118 bool shouldDeleteOnRemove() const; 0119 void setShouldDeleteOnRemove(bool del); 0120 0121 bool preventStealing() const; 0122 void setPreventStealing(bool prevent); 0123 0124 bool isPinned() const; 0125 void setPinned(bool pinned); 0126 0127 bool inViewport() const; 0128 void setInViewport(bool inViewport); 0129 0130 Q_SIGNALS: 0131 void indexChanged(); 0132 void fillWidthChanged(); 0133 void reservedSpaceChanged(); 0134 void viewChanged(); 0135 void preventStealingChanged(); 0136 void pinnedChanged(); 0137 void scrollIntention(ScrollIntentionEvent *event); 0138 void inViewportChanged(); 0139 0140 private: 0141 int m_index = -1; 0142 bool m_fillWidth = false; 0143 qreal m_reservedSpace = 0; 0144 QPointer<ColumnView> m_view; 0145 QPointer<QQuickItem> m_originalParent; 0146 bool m_customFillWidth = false; 0147 bool m_customReservedSpace = false; 0148 bool m_shouldDeleteOnRemove = true; 0149 bool m_preventStealing = false; 0150 bool m_pinned = false; 0151 bool m_inViewport = false; 0152 }; 0153 0154 /** 0155 * ColumnView is a container that lays out items horizontally in a row, 0156 * when not all items fit in the ColumnView, it will behave like a QtQuick.Flickable 0157 * and will be a scrollable view which shows only a determined number of columns. 0158 * The columns can either all have the same fixed size (recommended), 0159 * size themselves with QtQuick.QQuickItem.implicitWidth, 0160 * or automatically expand to take all the available width: by default the last column will always be the expanding one. 0161 * Items inside the ColumnView can access info of the view and set layouting hints via ColumnViewAttached. 0162 * 0163 * This is the base for the implementation of org::kde::kirigami::PageRow. 0164 * 0165 * @see ColumnViewAttached 0166 * @since org.kde.kirigami 2.7 0167 */ 0168 class ColumnView : public QQuickItem 0169 { 0170 Q_OBJECT 0171 0172 /** 0173 * @brief This property holds the ColumnView's column resizing strategy. 0174 */ 0175 Q_PROPERTY(ColumnResizeMode columnResizeMode READ columnResizeMode WRITE setColumnResizeMode NOTIFY columnResizeModeChanged) 0176 0177 /** 0178 * @brief The width of all columns when ::columnResizeMode is set to ``ColumnResizeMode::FixedColumns``. 0179 */ 0180 Q_PROPERTY(qreal columnWidth READ columnWidth WRITE setColumnWidth NOTIFY columnWidthChanged) 0181 0182 /** 0183 * @brief This property holds the column count. 0184 */ 0185 Q_PROPERTY(int count READ count NOTIFY countChanged) 0186 0187 /** 0188 * @brief This property holds the index of currently focused item. 0189 * @note The current item will have keyboard focus. 0190 */ 0191 Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) 0192 0193 /** 0194 * @brief This property points to the currently focused item. 0195 * @note The focused item will have keyboard focus. 0196 */ 0197 Q_PROPERTY(QQuickItem *currentItem READ currentItem NOTIFY currentItemChanged) 0198 0199 /** 0200 * @brief This property points to the contentItem of the view, 0201 * which is the parent of the column items. 0202 */ 0203 Q_PROPERTY(QQuickItem *contentItem READ contentItem CONSTANT) 0204 0205 /** 0206 * @brief This property holds the view's horizontal scroll value in pixels. 0207 */ 0208 Q_PROPERTY(qreal contentX READ contentX WRITE setContentX NOTIFY contentXChanged) 0209 0210 /** 0211 * @brief This property holds the compound width of all columns in the view. 0212 */ 0213 Q_PROPERTY(qreal contentWidth READ contentWidth NOTIFY contentWidthChanged) 0214 0215 /** 0216 * @brief This property holds the view's top padding. 0217 */ 0218 Q_PROPERTY(qreal topPadding READ topPadding WRITE setTopPadding NOTIFY topPaddingChanged) 0219 0220 /** 0221 * @brief This property holds the view's bottom padding. 0222 */ 0223 Q_PROPERTY(qreal bottomPadding READ bottomPadding WRITE setBottomPadding NOTIFY bottomPaddingChanged) 0224 0225 /** 0226 * @brief This property holds the scrolling animation's duration. 0227 */ 0228 Q_PROPERTY(int scrollDuration READ scrollDuration WRITE setScrollDuration NOTIFY scrollDurationChanged) 0229 0230 /** 0231 * @brief This property sets whether columns should be visually separated by a line. 0232 */ 0233 Q_PROPERTY(bool separatorVisible READ separatorVisible WRITE setSeparatorVisible NOTIFY separatorVisibleChanged) 0234 0235 /** 0236 * @brief This property holds the list of all visible items that are currently at least partially visible. 0237 */ 0238 Q_PROPERTY(QList<QObject *> visibleItems READ visibleItems NOTIFY visibleItemsChanged) 0239 0240 /** 0241 * @brief This property points to the first currently visible item. 0242 */ 0243 Q_PROPERTY(QQuickItem *firstVisibleItem READ firstVisibleItem NOTIFY firstVisibleItemChanged) 0244 0245 /** 0246 * @brief This property points to the last currently visible item. 0247 */ 0248 Q_PROPERTY(QQuickItem *lastVisibleItem READ lastVisibleItem NOTIFY lastVisibleItemChanged) 0249 0250 // Properties to make it similar to Flickable 0251 /** 0252 * @brief This property specifies whether the user is currently dragging the view's contents with a touch gesture. 0253 */ 0254 Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged) 0255 0256 /** 0257 * @brief This property specifies whether the user is currently dragging 0258 * the view's contents with a touch gesture or if the view is animating. 0259 * 0260 */ 0261 Q_PROPERTY(bool moving READ moving NOTIFY movingChanged) 0262 0263 /** 0264 * @brief This property sets whether the view supports moving the contents by 0265 * dragging them with a touch gesture. 0266 */ 0267 Q_PROPERTY(bool interactive READ interactive WRITE setInteractive NOTIFY interactiveChanged) 0268 0269 /** 0270 * @brief This property sets whether the view supports moving the contents 0271 * by dragging them with a mouse. 0272 */ 0273 Q_PROPERTY(bool acceptsMouse READ acceptsMouse WRITE setAcceptsMouse NOTIFY acceptsMouseChanged) 0274 0275 // Default properties 0276 /** 0277 * @brief This property holds a list of every column visual item that the view currently contains. 0278 */ 0279 Q_PROPERTY(QQmlListProperty<QQuickItem> contentChildren READ contentChildren NOTIFY contentChildrenChanged FINAL) 0280 0281 /** 0282 * @brief This property holds a list of every column visual and non-visual item that the view currently contains. 0283 */ 0284 Q_PROPERTY(QQmlListProperty<QObject> contentData READ contentData FINAL) 0285 Q_CLASSINFO("DefaultProperty", "contentData") 0286 0287 public: 0288 enum ColumnResizeMode { 0289 /** 0290 * @brief Every column is fixed at the same width specified by columnWidth property. 0291 */ 0292 FixedColumns = 0, 0293 0294 /** 0295 * @brief Columns take their width from the implicitWidth property. 0296 */ 0297 DynamicColumns, 0298 0299 /** 0300 * @brief Only one column is shown, and as wide as the viewport allows it. 0301 */ 0302 SingleColumn, 0303 }; 0304 Q_ENUM(ColumnResizeMode) 0305 0306 ColumnView(QQuickItem *parent = nullptr); 0307 ~ColumnView() override; 0308 0309 // QML property accessors 0310 ColumnResizeMode columnResizeMode() const; 0311 void setColumnResizeMode(ColumnResizeMode mode); 0312 0313 qreal columnWidth() const; 0314 void setColumnWidth(qreal width); 0315 0316 int currentIndex() const; 0317 void setCurrentIndex(int index); 0318 0319 int scrollDuration() const; 0320 void setScrollDuration(int duration); 0321 0322 bool separatorVisible() const; 0323 void setSeparatorVisible(bool visible); 0324 0325 int count() const; 0326 0327 qreal topPadding() const; 0328 void setTopPadding(qreal padding); 0329 0330 qreal bottomPadding() const; 0331 void setBottomPadding(qreal padding); 0332 0333 QQuickItem *currentItem(); 0334 0335 // NOTE: It's a QList<QObject *> as QML can't correctly build an Array out of QList<QQuickItem*> 0336 QList<QObject *> visibleItems() const; 0337 QQuickItem *firstVisibleItem() const; 0338 QQuickItem *lastVisibleItem() const; 0339 0340 QQuickItem *contentItem() const; 0341 0342 QQmlListProperty<QQuickItem> contentChildren(); 0343 QQmlListProperty<QObject> contentData(); 0344 0345 bool dragging() const; 0346 bool moving() const; 0347 qreal contentWidth() const; 0348 0349 qreal contentX() const; 0350 void setContentX(qreal x) const; 0351 0352 bool interactive() const; 0353 void setInteractive(bool interactive); 0354 0355 bool acceptsMouse() const; 0356 void setAcceptsMouse(bool accepts); 0357 0358 // Api not intended for QML use 0359 // can't do overloads in QML 0360 QQuickItem *removeItem(QQuickItem *item); 0361 QQuickItem *removeItem(int item); 0362 0363 // QML attached property 0364 static ColumnViewAttached *qmlAttachedProperties(QObject *object); 0365 0366 public Q_SLOTS: 0367 /** 0368 * @brief This method pushes a new item to the end of the view. 0369 * @param item the new item which will be reparented and managed 0370 */ 0371 void addItem(QQuickItem *item); 0372 0373 /** 0374 * @brief This method inserts a new item in the view at a given position. 0375 * 0376 * The ::currentItem will not be changed, ::currentIndex will be adjusted 0377 * accordingly if needed to keep the same current item. 0378 * 0379 * @param pos the position we want the new item to be inserted in 0380 * @param item the new item which will be reparented and managed 0381 */ 0382 void insertItem(int pos, QQuickItem *item); 0383 0384 /** 0385 * @brief This method replaces an item in the view at a given position with a new item. 0386 * 0387 * The ::currentItem and ::currentIndex will not be changed. 0388 * 0389 * @param pos the position we want the new item to be placed in 0390 * @param item the new item which will be reparented and managed 0391 */ 0392 void replaceItem(int pos, QQuickItem *item); 0393 0394 /** 0395 * @brief This method swaps items at given positions. 0396 * 0397 * The ::currentIndex property may be changed in order to keep ::currentItem the same. 0398 * 0399 * @param from the old position 0400 * @param to the new position 0401 */ 0402 void moveItem(int from, int to); 0403 0404 /** 0405 * @brief This method removes an item from the view. 0406 * 0407 * Items will be reparented to their old parent. 0408 * If they have JavaScript ownership and they didn't have an old parent, they will be destroyed. 0409 * 0410 * The ::currentIndex property may be changed in order to keep the same ::currentItem. 0411 * 0412 * @param item it can either be a pointer of an item or an integer specifying the position to remove 0413 * @returns the item that has just been removed 0414 */ 0415 QQuickItem *removeItem(const QVariant &item); 0416 0417 /** 0418 * @brief This method removes every item after the specified @p item from 0419 * the column view. 0420 * 0421 * If no item is specified, only the last item will be removed. 0422 * 0423 * Items that are inserted in a column view are reparented to the column 0424 * view while keeping information about the original parent, if available. 0425 * 0426 * After calling this method, the items removed from the column view will 0427 * either be reparented back to their original parent if they had one, or be 0428 * deleted if they did not (this is normally the case if the item was 0429 * created from a JavaScript expression). 0430 * 0431 * @param item it can either be a pointer to an item or an integer 0432 * specifying the position to remove. 0433 * 0434 * @returns the item that has just been removed. 0435 */ 0436 QQuickItem *pop(QQuickItem *item); 0437 0438 /** 0439 * @brief This method removes every item in the view. 0440 * 0441 * Items will be reparented to their old parent. 0442 * If they have JavaScript ownership and they didn't have an old parent, they will be destroyed 0443 */ 0444 void clear(); 0445 0446 /** 0447 * @brief This method checks whether an item is present in the view. 0448 */ 0449 bool containsItem(QQuickItem *item); 0450 0451 /** 0452 * @brief This method returns the item in the view at a given position. 0453 * 0454 * If there is no item at the point specified, or the item is not visible null is returned. 0455 * 0456 * @param x The horizontal position of the item 0457 * @param y The vertical position of the item 0458 */ 0459 QQuickItem *itemAt(qreal x, qreal y); 0460 0461 protected: 0462 void classBegin() override; 0463 void componentComplete() override; 0464 void updatePolish() override; 0465 void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) override; 0466 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0467 void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override; 0468 #else 0469 void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; 0470 #endif 0471 bool childMouseEventFilter(QQuickItem *item, QEvent *event) override; 0472 void mousePressEvent(QMouseEvent *event) override; 0473 void mouseMoveEvent(QMouseEvent *event) override; 0474 void mouseReleaseEvent(QMouseEvent *event) override; 0475 void mouseUngrabEvent() override; 0476 0477 Q_SIGNALS: 0478 /** 0479 * @brief This signal is emitted when an item has been inserted into the view. 0480 * @param position where the page has been inserted 0481 * @param item a pointer to the new item 0482 */ 0483 void itemInserted(int position, QQuickItem *item); 0484 0485 /** 0486 * @brief This signal is emitted when an item has been removed from the view. 0487 * @param item a pointer to the item that has just been removed 0488 */ 0489 void itemRemoved(QQuickItem *item); 0490 0491 // Property notifiers 0492 void contentChildrenChanged(); 0493 void columnResizeModeChanged(); 0494 void columnWidthChanged(); 0495 void currentIndexChanged(); 0496 void currentItemChanged(); 0497 void visibleItemsChanged(); 0498 void countChanged(); 0499 void draggingChanged(); 0500 void movingChanged(); 0501 void contentXChanged(); 0502 void contentWidthChanged(); 0503 void interactiveChanged(); 0504 void acceptsMouseChanged(); 0505 void scrollDurationChanged(); 0506 void separatorVisibleChanged(); 0507 void firstVisibleItemChanged(); 0508 void lastVisibleItemChanged(); 0509 void topPaddingChanged(); 0510 void bottomPaddingChanged(); 0511 0512 private: 0513 static void contentChildren_append(QQmlListProperty<QQuickItem> *prop, QQuickItem *object); 0514 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0515 static int contentChildren_count(QQmlListProperty<QQuickItem> *prop); 0516 static QQuickItem *contentChildren_at(QQmlListProperty<QQuickItem> *prop, int index); 0517 #else 0518 static qsizetype contentChildren_count(QQmlListProperty<QQuickItem> *prop); 0519 static QQuickItem *contentChildren_at(QQmlListProperty<QQuickItem> *prop, qsizetype index); 0520 #endif 0521 static void contentChildren_clear(QQmlListProperty<QQuickItem> *prop); 0522 0523 static void contentData_append(QQmlListProperty<QObject> *prop, QObject *object); 0524 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0525 static int contentData_count(QQmlListProperty<QObject> *prop); 0526 static QObject *contentData_at(QQmlListProperty<QObject> *prop, int index); 0527 #else 0528 static qsizetype contentData_count(QQmlListProperty<QObject> *prop); 0529 static QObject *contentData_at(QQmlListProperty<QObject> *prop, qsizetype index); 0530 #endif 0531 static void contentData_clear(QQmlListProperty<QObject> *prop); 0532 0533 QList<QObject *> m_contentData; 0534 0535 ContentItem *m_contentItem; 0536 QPointer<QQuickItem> m_currentItem; 0537 0538 qreal m_oldMouseX = -1.0; 0539 qreal m_startMouseX = -1.0; 0540 qreal m_oldMouseY = -1.0; 0541 qreal m_startMouseY = -1.0; 0542 int m_currentIndex = -1; 0543 qreal m_topPadding = 0; 0544 qreal m_bottomPadding = 0; 0545 0546 bool m_mouseDown = false; 0547 bool m_interactive = true; 0548 bool m_dragging = false; 0549 bool m_moving = false; 0550 bool m_separatorVisible = true; 0551 bool m_complete = false; 0552 bool m_acceptsMouse = false; 0553 }; 0554 0555 QML_DECLARE_TYPEINFO(ColumnView, QML_HAS_ATTACHED_PROPERTIES)