File indexing completed on 2024-04-28 05:45:09
0001 /* 0002 * SPDX-FileCopyrightText: 2011 Peter Penz <peter.penz19@gmail.com> 0003 * 0004 * Based on the Itemviews NG project from Trolltech Labs 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #ifndef KITEMLISTVIEW_H 0010 #define KITEMLISTVIEW_H 0011 0012 #include <optional> 0013 0014 #include "dolphin_export.h" 0015 #include "kitemviews/kitemliststyleoption.h" 0016 #include "kitemviews/kitemlistwidget.h" 0017 #include "kitemviews/kitemmodelbase.h" 0018 #include "kitemviews/kstandarditemlistgroupheader.h" 0019 #include "kitemviews/private/kitemlistviewanimation.h" 0020 0021 #include <QGraphicsWidget> 0022 #include <QSet> 0023 0024 class KItemListContainer; 0025 class KItemListContainerAccessible; 0026 class KItemListController; 0027 class KItemListGroupHeaderCreatorBase; 0028 class KItemListHeader; 0029 class KItemListHeaderWidget; 0030 class KItemListSizeHintResolver; 0031 class KItemListRubberBand; 0032 class KItemListViewAnimation; 0033 class KItemListViewLayouter; 0034 class KItemListWidget; 0035 class KItemListWidgetInformant; 0036 class KItemListWidgetCreatorBase; 0037 class QTimer; 0038 class QPropertyAnimation; 0039 class QVariantAnimation; 0040 0041 /** 0042 * @brief Represents the view of an item-list. 0043 * 0044 * The view is responsible for showing the items of the model within 0045 * a GraphicsItem. Each visible item is represented by a KItemListWidget. 0046 * 0047 * The created view must be applied to the KItemListController with 0048 * KItemListController::setView() or with the constructor of 0049 * KItemListController. 0050 * 0051 * @see KItemListWidget 0052 * @see KItemModelBase 0053 */ 0054 class DOLPHIN_EXPORT KItemListView : public QGraphicsWidget 0055 { 0056 Q_OBJECT 0057 0058 Q_PROPERTY(qreal scrollOffset READ scrollOffset WRITE setScrollOffset NOTIFY scrollOffsetChanged) 0059 Q_PROPERTY(qreal itemOffset READ itemOffset WRITE setItemOffset NOTIFY itemOffsetChanged) 0060 0061 public: 0062 /** The position in the view to which an item should be scrolled to. */ 0063 enum ViewItemPosition { Beginning, Middle, End, Nearest }; 0064 0065 explicit KItemListView(QGraphicsWidget *parent = nullptr); 0066 ~KItemListView() override; 0067 0068 /** 0069 * Offset of the scrollbar that represents the scroll-orientation 0070 * (see setScrollOrientation()). 0071 */ 0072 void setScrollOffset(qreal offset); 0073 qreal scrollOffset() const; 0074 0075 qreal maximumScrollOffset() const; 0076 0077 /** 0078 * Offset related to an item, that does not fit into the available 0079 * size of the listview. If the scroll-orientation is vertical 0080 * the item-offset describes the offset of the horizontal axe, if 0081 * the scroll-orientation is horizontal the item-offset describes 0082 * the offset of the vertical axe. 0083 */ 0084 void setItemOffset(qreal scrollOffset); 0085 qreal itemOffset() const; 0086 0087 qreal maximumItemOffset() const; 0088 0089 int maximumVisibleItems() const; 0090 0091 void setVisibleRoles(const QList<QByteArray> &roles); 0092 QList<QByteArray> visibleRoles() const; 0093 0094 /** 0095 * If set to true an automatic scrolling is done as soon as the 0096 * mouse is moved near the borders of the view. Per default 0097 * the automatic scrolling is turned off. 0098 */ 0099 void setAutoScroll(bool enabled); 0100 bool autoScroll() const; 0101 0102 /** 0103 * If set to true selection-toggles will be shown when hovering 0104 * an item. Per default the selection-toggles are disabled. 0105 */ 0106 void setEnabledSelectionToggles(bool enabled); 0107 bool enabledSelectionToggles() const; 0108 0109 /** 0110 * @return Controller of the item-list. The controller gets 0111 * initialized by KItemListController::setView() and will 0112 * result in calling KItemListController::onControllerChanged(). 0113 */ 0114 KItemListController *controller() const; 0115 0116 /** 0117 * @return Model of the item-list. The model gets 0118 * initialized by KItemListController::setModel() and will 0119 * result in calling KItemListController::onModelChanged(). 0120 */ 0121 KItemModelBase *model() const; 0122 0123 /** 0124 * Sets the creator that creates a widget showing the 0125 * content of one model-item. Usually it is sufficient 0126 * to implement a custom widget X derived from KItemListWidget and 0127 * set the creator by: 0128 * <code> 0129 * itemListView->setWidgetCreator(new KItemListWidgetCreator<X>()); 0130 * </code> 0131 * The ownership of the widget creator is transferred to 0132 * the item-list view. 0133 **/ 0134 void setWidgetCreator(KItemListWidgetCreatorBase *widgetCreator); 0135 KItemListWidgetCreatorBase *widgetCreator() const; 0136 0137 /** 0138 * Sets the creator that creates a group header. Usually it is sufficient 0139 * to implement a custom header widget X derived from KItemListGroupHeader and 0140 * set the creator by: 0141 * <code> 0142 * itemListView->setGroupHeaderCreator(new KItemListGroupHeaderCreator<X>()); 0143 * </code> 0144 * The ownership of the gropup header creator is transferred to 0145 * the item-list view. 0146 **/ 0147 void setGroupHeaderCreator(KItemListGroupHeaderCreatorBase *groupHeaderCreator); 0148 KItemListGroupHeaderCreatorBase *groupHeaderCreator() const; 0149 0150 #ifndef QT_NO_ACCESSIBILITY 0151 /** 0152 * Uses \a parent to create an accessible object for \a parent. That accessible object will 0153 * then be used as the accessible parent of the accessible object for this KItemListView. 0154 * Make sure \a parent is the container which contains this specific KItemListView. 0155 * This method must be called once before the accessible interface is queried for this class. 0156 */ 0157 void setAccessibleParentsObject(KItemListContainer *accessibleParentsObject); 0158 /** The parent of the QAccessibilityInterface of this class. */ 0159 KItemListContainerAccessible *accessibleParent(); 0160 #endif 0161 0162 /** 0163 * @return The basic size of all items. The size of an item may be larger than 0164 * the basic size (see KItemListView::itemRect()). 0165 */ 0166 QSizeF itemSize() const; 0167 0168 const KItemListStyleOption &styleOption() const; 0169 0170 void setGeometry(const QRectF &rect) override; 0171 0172 /** 0173 * @return The page step which should be used by the vertical scroll bar. 0174 * This is the height of the view except for the header widget. 0175 */ 0176 qreal verticalPageStep() const; 0177 0178 /** 0179 * @return Index of the item that is below the point \a pos. 0180 * The position is relative to the upper right of 0181 * the visible area. Only (at least partly) visible 0182 * items are considered. std::nullopt is returned if 0183 * no item is below the position. 0184 */ 0185 std::optional<int> itemAt(const QPointF &pos) const; 0186 bool isAboveSelectionToggle(int index, const QPointF &pos) const; 0187 bool isAboveExpansionToggle(int index, const QPointF &pos) const; 0188 bool isAboveText(int index, const QPointF &pos) const; 0189 0190 /** 0191 * @return Index of the first item that is at least partly visible. 0192 * -1 is returned if the model contains no items. 0193 */ 0194 int firstVisibleIndex() const; 0195 0196 /** 0197 * @return Index of the last item that is at least partly visible. 0198 * -1 is returned if the model contains no items. 0199 */ 0200 int lastVisibleIndex() const; 0201 0202 /** 0203 * Calculates the required size for all items in the model. 0204 * It might be larger than KItemListView::itemSize(). 0205 * In this case the layout grid will be stretched to assure an 0206 * unclipped item. 0207 * 0208 * @note the logical height (width) is actually the 0209 * width (height) if the scroll orientation is Qt::Vertical! 0210 */ 0211 void calculateItemSizeHints(QVector<std::pair<qreal, bool>> &logicalHeightHints, qreal &logicalWidthHint) const; 0212 0213 /** 0214 * If set to true, items having child-items can be expanded to show the child-items as 0215 * part of the view. Per default the expanding of items is disabled. If expanding of 0216 * items is enabled, the methods KItemModelBase::setExpanded(), KItemModelBase::isExpanded(), 0217 * KItemModelBase::isExpandable() and KItemModelBase::expandedParentsCount() 0218 * must be reimplemented. The view-implementation 0219 * has to take care itself how to visually represent the expanded items provided 0220 * by the model. 0221 */ 0222 void setSupportsItemExpanding(bool supportsExpanding); 0223 bool supportsItemExpanding() const; 0224 0225 void setHighlightEntireRow(bool highlightEntireRow); 0226 bool highlightEntireRow() const; 0227 0228 void setAlternateBackgrounds(bool alternate); 0229 bool alternateBackgrounds() const; 0230 0231 /** 0232 * @return The rectangle of the item relative to the top/left of 0233 * the currently visible area (see KItemListView::offset()). 0234 */ 0235 QRectF itemRect(int index) const; 0236 0237 /** 0238 * @return The context rectangle of the item relative to the top/left of 0239 * the currently visible area (see KItemListView::offset()). The 0240 * context rectangle is defined by the united rectangle of 0241 * the icon rectangle and the text rectangle (see KItemListWidget::iconRect() 0242 * and KItemListWidget::textRect()) and is useful as reference for e.g. aligning 0243 * a tooltip or a context-menu for an item. Note that a context rectangle will 0244 * only be returned for (at least partly) visible items. An empty rectangle will 0245 * be returned for fully invisible items. 0246 */ 0247 QRectF itemContextRect(int index) const; 0248 0249 /** 0250 * @return Whether or not the name of the file has been elided. At present this will 0251 * only ever be true when in icons view. 0252 */ 0253 bool isElided(int index) const; 0254 0255 /** 0256 * Scrolls to the item with the index \a index so that the item 0257 * will be fully visible. The item is positioned within the view 0258 * as specified by \a viewItemPosition. 0259 */ 0260 void scrollToItem(int index, ViewItemPosition viewItemPosition = ViewItemPosition::Nearest); 0261 0262 /** 0263 * If several properties of KItemListView are changed synchronously, it is 0264 * recommended to encapsulate the calls between beginTransaction() and endTransaction(). 0265 * This prevents unnecessary and expensive layout-calculations. 0266 */ 0267 void beginTransaction(); 0268 0269 /** 0270 * Counterpart to beginTransaction(). The layout changes will only be animated if 0271 * all property changes between beginTransaction() and endTransaction() support 0272 * animations. 0273 */ 0274 void endTransaction(); 0275 0276 bool isTransactionActive() const; 0277 0278 /** 0279 * Turns on the header if \p visible is true. Per default the 0280 * header is not visible. Usually the header is turned on when 0281 * showing a classic "table-view" to describe the shown columns. 0282 */ 0283 void setHeaderVisible(bool visible); 0284 bool isHeaderVisible() const; 0285 0286 /** 0287 * @return Header of the list. The header is also available if it is not shown 0288 * (see KItemListView::setHeaderShown()). 0289 */ 0290 KItemListHeader *header() const; 0291 0292 /** 0293 * @return Pixmap that is used for a drag operation based on the 0294 * items given by \a indexes. 0295 */ 0296 virtual QPixmap createDragPixmap(const KItemSet &indexes) const; 0297 0298 /** 0299 * Lets the user edit the role \a role for item with the index \a index. 0300 */ 0301 void editRole(int index, const QByteArray &role); 0302 0303 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override; 0304 0305 Q_SIGNALS: 0306 void scrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous); 0307 void scrollOffsetChanged(qreal current, qreal previous); 0308 void maximumScrollOffsetChanged(qreal current, qreal previous); 0309 void itemOffsetChanged(qreal current, qreal previous); 0310 void maximumItemOffsetChanged(qreal current, qreal previous); 0311 void scrollTo(qreal newOffset); 0312 0313 /** 0314 * Is emitted if the user has changed the sort order by clicking on a 0315 * header item (see KItemListView::setHeaderShown()). The sort order 0316 * of the model has already been adjusted to 0317 * the current sort order. Note that no signal will be emitted if the 0318 * sort order of the model has been changed without user interaction. 0319 */ 0320 void sortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous); 0321 0322 /** 0323 * Is emitted if the user has changed the sort role by clicking on a 0324 * header item (see KItemListView::setHeaderShown()). The sort role 0325 * of the model has already been adjusted to 0326 * the current sort role. Note that no signal will be emitted if the 0327 * sort role of the model has been changed without user interaction. 0328 */ 0329 void sortRoleChanged(const QByteArray ¤t, const QByteArray &previous); 0330 0331 /** 0332 * Is emitted if the user has changed the visible roles by moving a header 0333 * item (see KItemListView::setHeaderShown()). Note that no signal will be 0334 * emitted if the roles have been changed without user interaction by 0335 * KItemListView::setVisibleRoles(). 0336 */ 0337 void visibleRolesChanged(const QList<QByteArray> ¤t, const QList<QByteArray> &previous); 0338 0339 void roleEditingCanceled(int index, const QByteArray &role, const QVariant &value); 0340 void roleEditingFinished(int index, const QByteArray &role, const QVariant &value); 0341 0342 /** 0343 * Emitted once scrolling has finished, or immediately if no scrolling was necessary 0344 * to get item in view in scrollToItem. 0345 */ 0346 void scrollingStopped(); 0347 0348 void columnHovered(int roleIndex); 0349 void columnUnHovered(int roleIndex); 0350 0351 protected: 0352 QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; 0353 void setItemSize(const QSizeF &size); 0354 void setStyleOption(const KItemListStyleOption &option); 0355 0356 /** 0357 * If the scroll-orientation is vertical, the items are ordered 0358 * from top to bottom (= default setting). If the scroll-orientation 0359 * is horizontal, the items are ordered from left to right. 0360 */ 0361 void setScrollOrientation(Qt::Orientation orientation); 0362 Qt::Orientation scrollOrientation() const; 0363 0364 /** 0365 * Factory method for creating a default widget-creator. The method will be used 0366 * in case if setWidgetCreator() has not been set by the application. 0367 * @return New instance of the widget-creator that should be used per 0368 * default. 0369 */ 0370 virtual KItemListWidgetCreatorBase *defaultWidgetCreator() const; 0371 0372 /** 0373 * Factory method for creating a default group-header-creator. The method will be used 0374 * in case if setGroupHeaderCreator() has not been set by the application. 0375 * @return New instance of the group-header-creator that should be used per 0376 * default. 0377 */ 0378 virtual KItemListGroupHeaderCreatorBase *defaultGroupHeaderCreator() const; 0379 0380 /** 0381 * Is called when creating a new KItemListWidget instance and allows derived 0382 * classes to do a custom initialization. 0383 */ 0384 virtual void initializeItemListWidget(KItemListWidget *item); 0385 0386 /** 0387 * @return True if at least one of the changed roles \p changedRoles might result 0388 * in the need to update the item-size hint (see KItemListView::itemSizeHint()). 0389 * Per default true is returned which means on each role-change of existing items 0390 * the item-size hints are recalculated. For performance reasons it is recommended 0391 * to return false in case if a role-change will not result in a changed 0392 * item-size hint. 0393 */ 0394 virtual bool itemSizeHintUpdateRequired(const QSet<QByteArray> &changedRoles) const; 0395 0396 virtual void onControllerChanged(KItemListController *current, KItemListController *previous); 0397 virtual void onModelChanged(KItemModelBase *current, KItemModelBase *previous); 0398 0399 virtual void onScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous); 0400 virtual void onItemSizeChanged(const QSizeF ¤t, const QSizeF &previous); 0401 virtual void onScrollOffsetChanged(qreal current, qreal previous); 0402 virtual void onVisibleRolesChanged(const QList<QByteArray> ¤t, const QList<QByteArray> &previous); 0403 virtual void onStyleOptionChanged(const KItemListStyleOption ¤t, const KItemListStyleOption &previous); 0404 virtual void onHighlightEntireRowChanged(bool highlightEntireRow); 0405 virtual void onSupportsItemExpandingChanged(bool supportsExpanding); 0406 0407 virtual void onTransactionBegin(); 0408 virtual void onTransactionEnd(); 0409 0410 bool event(QEvent *event) override; 0411 void mousePressEvent(QGraphicsSceneMouseEvent *event) override; 0412 void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; 0413 void dragEnterEvent(QGraphicsSceneDragDropEvent *event) override; 0414 void dragMoveEvent(QGraphicsSceneDragDropEvent *event) override; 0415 void dragLeaveEvent(QGraphicsSceneDragDropEvent *event) override; 0416 void dropEvent(QGraphicsSceneDragDropEvent *event) override; 0417 0418 QList<KItemListWidget *> visibleItemListWidgets() const; 0419 0420 virtual void updateFont(); 0421 virtual void updatePalette(); 0422 0423 protected Q_SLOTS: 0424 virtual void slotItemsInserted(const KItemRangeList &itemRanges); 0425 virtual void slotItemsRemoved(const KItemRangeList &itemRanges); 0426 virtual void slotItemsMoved(const KItemRange &itemRange, const QList<int> &movedToIndexes); 0427 virtual void slotItemsChanged(const KItemRangeList &itemRanges, const QSet<QByteArray> &roles); 0428 virtual void slotGroupsChanged(); 0429 0430 virtual void slotGroupedSortingChanged(bool current); 0431 virtual void slotSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous); 0432 virtual void slotSortRoleChanged(const QByteArray ¤t, const QByteArray &previous); 0433 virtual void slotCurrentChanged(int current, int previous); 0434 virtual void slotSelectionChanged(const KItemSet ¤t, const KItemSet &previous); 0435 0436 private Q_SLOTS: 0437 void slotAnimationFinished(QGraphicsWidget *widget, KItemListViewAnimation::AnimationType type); 0438 0439 void slotRubberBandPosChanged(); 0440 void slotRubberBandActivationChanged(bool active); 0441 0442 /** 0443 * Is invoked if the column-width of one role in the header has 0444 * been changed by the user. The automatic resizing of columns 0445 * will be turned off as soon as this method has been called at 0446 * least once. 0447 */ 0448 void slotHeaderColumnWidthChanged(const QByteArray &role, qreal currentWidth, qreal previousWidth); 0449 0450 void slotSidePaddingChanged(qreal width); 0451 0452 /** 0453 * Is invoked if a column has been moved by the user. Applies 0454 * the moved role to the view. 0455 */ 0456 void slotHeaderColumnMoved(const QByteArray &role, int currentIndex, int previousIndex); 0457 0458 /** 0459 * Triggers the autoscrolling if autoScroll() is enabled by checking the 0460 * current mouse position. If the mouse position is within the autoscroll 0461 * margins a timer will be started that periodically triggers the autoscrolling. 0462 */ 0463 void triggerAutoScrolling(); 0464 0465 /** 0466 * Is invoked if the geometry of the parent-widget from a group-header has been 0467 * changed. The x-position and width of the group-header gets adjusted to assure 0468 * that it always spans the whole width even during temporary transitions of the 0469 * parent widget. 0470 */ 0471 void slotGeometryOfGroupHeaderParentChanged(); 0472 0473 void slotRoleEditingCanceled(int index, const QByteArray &role, const QVariant &value); 0474 void slotRoleEditingFinished(int index, const QByteArray &role, const QVariant &value); 0475 0476 private: 0477 enum LayoutAnimationHint { NoAnimation, Animation }; 0478 0479 enum SizeType { LayouterSize, ItemSize }; 0480 0481 void setController(KItemListController *controller); 0482 void setModel(KItemModelBase *model); 0483 0484 KItemListRubberBand *rubberBand() const; 0485 0486 void doLayout(LayoutAnimationHint hint, int changedIndex = 0, int changedCount = 0); 0487 0488 /** 0489 * Helper method for doLayout: Returns a list of items that can be reused for the visible 0490 * area. Invisible group headers get recycled. The reusable items are items that are 0491 * invisible. If the animation hint is 'Animation' then items that are currently animated 0492 * won't be reused. Reusing items is faster in comparison to deleting invisible 0493 * items and creating a new instance for visible items. 0494 */ 0495 QList<int> recycleInvisibleItems(int firstVisibleIndex, int lastVisibleIndex, LayoutAnimationHint hint); 0496 0497 /** 0498 * Helper method for doLayout: Starts a moving-animation for the widget to the given 0499 * new position. The moving-animation is only started if the new position is within 0500 * the same row or column, otherwise the create-animation is used instead. 0501 * @return True if the moving-animation has been applied. 0502 */ 0503 bool moveWidget(KItemListWidget *widget, const QPointF &newPos); 0504 0505 void emitOffsetChanges(); 0506 0507 KItemListWidget *createWidget(int index); 0508 void recycleWidget(KItemListWidget *widget); 0509 0510 /** 0511 * Changes the index of the widget to \a index and assures a consistent 0512 * update for m_visibleItems and m_visibleCells. The cell-information 0513 * for the new index will not be updated and be initialized as empty cell. 0514 */ 0515 void setWidgetIndex(KItemListWidget *widget, int index); 0516 0517 /** 0518 * Changes the index of the widget to \a index. In opposite to 0519 * setWidgetIndex() the cell-information for the widget gets updated. 0520 * This update gives doLayout() the chance to animate the moving 0521 * of the item visually (see moveWidget()). 0522 */ 0523 void moveWidgetToIndex(KItemListWidget *widget, int index); 0524 0525 /** 0526 * Helper method for prepareLayoutForIncreasedItemCount(). 0527 */ 0528 void setLayouterSize(const QSizeF &size, SizeType sizeType); 0529 0530 /** 0531 * Helper method for createWidget() and setWidgetIndex() to update the properties 0532 * of the itemlist widget. 0533 */ 0534 void updateWidgetProperties(KItemListWidget *widget, int index); 0535 0536 /** 0537 * Helper method for updateWidgetPropertes() to create or update 0538 * the itemlist group-header. 0539 */ 0540 void updateGroupHeaderForWidget(KItemListWidget *widget); 0541 0542 /** 0543 * Updates the position and size of the group-header that belongs 0544 * to the itemlist widget \a widget. The given widget must represent 0545 * the first item of a group. 0546 */ 0547 void updateGroupHeaderLayout(KItemListWidget *widget); 0548 0549 /** 0550 * Recycles the group-header for the widget. 0551 */ 0552 void recycleGroupHeaderForWidget(KItemListWidget *widget); 0553 0554 /** 0555 * Helper method for slotGroupedSortingChanged(), slotSortOrderChanged() 0556 * and slotSortRoleChanged(): Iterates through all visible items and updates 0557 * the group-header widgets. 0558 */ 0559 void updateVisibleGroupHeaders(); 0560 0561 /** 0562 * @return Index for the item in the list returned by KItemModelBase::groups() 0563 * that represents the group where the item with the index \a index 0564 * belongs to. -1 is returned if no groups are available. 0565 */ 0566 int groupIndexForItem(int index) const; 0567 0568 /** 0569 * Updates the alternate background for all visible items. 0570 * @see updateAlternateBackgroundForWidget() 0571 */ 0572 void updateAlternateBackgrounds(); 0573 0574 /** 0575 * Updates the alternateBackground-property of the widget dependent 0576 * on the state of useAlternateBackgrounds() and the grouping state. 0577 */ 0578 void updateAlternateBackgroundForWidget(KItemListWidget *widget); 0579 0580 /** 0581 * @return True if alternate backgrounds should be used for the items. 0582 * This is the case if an empty item-size is given and if there 0583 * is more than one visible role. 0584 */ 0585 bool useAlternateBackgrounds() const; 0586 0587 /** 0588 * @param itemRanges Items that must be checked for getting the widths of columns. 0589 * @return The preferred width of the column of each visible role. The width will 0590 * be respected if the width of the item size is <= 0 (see 0591 * KItemListView::setItemSize()). Per default an empty hash 0592 * is returned. 0593 */ 0594 QHash<QByteArray, qreal> preferredColumnWidths(const KItemRangeList &itemRanges) const; 0595 0596 /** 0597 * Applies the column-widths from m_headerWidget to the layout 0598 * of the view. 0599 */ 0600 void applyColumnWidthsFromHeader(); 0601 0602 /** 0603 * Applies the column-widths from m_headerWidget to \a widget. 0604 */ 0605 void updateWidgetColumnWidths(KItemListWidget *widget); 0606 0607 /** 0608 * Updates the preferred column-widths of m_groupHeaderWidget by 0609 * invoking KItemListView::columnWidths(). 0610 */ 0611 void updatePreferredColumnWidths(const KItemRangeList &itemRanges); 0612 0613 /** 0614 * Convenience method for 0615 * updatePreferredColumnWidths(KItemRangeList() << KItemRange(0, m_model->count()). 0616 */ 0617 void updatePreferredColumnWidths(); 0618 0619 /** 0620 * Resizes the column-widths of m_headerWidget based on the preferred widths 0621 * and the available view-size. 0622 */ 0623 void applyAutomaticColumnWidths(); 0624 0625 /** 0626 * @return Sum of the widths of all columns. 0627 */ 0628 qreal columnWidthsSum() const; 0629 0630 /** 0631 * @return Boundaries of the header. An empty rectangle is returned 0632 * if no header is shown. 0633 */ 0634 QRectF headerBoundaries() const; 0635 0636 /** 0637 * @return True if the number of columns or rows will be changed when applying 0638 * the new grid- and item-size. Used to determine whether an animation 0639 * should be done when applying the new layout. 0640 */ 0641 bool changesItemGridLayout(const QSizeF &newGridSize, const QSizeF &newItemSize, const QSizeF &newItemMargin) const; 0642 0643 /** 0644 * @param changedItemCount Number of inserted or removed items. 0645 * @return True if the inserting or removing of items should be animated. 0646 * No animation should be done if the number of items is too large 0647 * to provide a pleasant animation. 0648 */ 0649 bool animateChangedItemCount(int changedItemCount) const; 0650 0651 /** 0652 * @return True if a scrollbar for the given scroll-orientation is required 0653 * when using a size of \p size for the view. Calling the method is rather 0654 * expansive as a temporary relayout needs to be done. 0655 */ 0656 bool scrollBarRequired(const QSizeF &size) const; 0657 0658 /** 0659 * Shows a drop-indicator between items dependent on the given 0660 * cursor position. The cursor position is relative to the upper left 0661 * edge of the view. 0662 * @return Index of the item where the dropping is done. An index of -1 0663 * indicates that the item has been dropped after the last item. 0664 */ 0665 int showDropIndicator(const QPointF &pos); 0666 void hideDropIndicator(); 0667 0668 /** 0669 * Applies the height of the group header to the layouter. The height 0670 * depends on the used scroll orientation. 0671 */ 0672 void updateGroupHeaderHeight(); 0673 0674 /** 0675 * Updates the siblings-information for all visible items that are inside 0676 * the range of \p firstIndex and \p lastIndex. If firstIndex or lastIndex 0677 * is smaller than 0, the siblings-information for all visible items gets 0678 * updated. 0679 * @see KItemListWidget::setSiblingsInformation() 0680 */ 0681 void updateSiblingsInformation(int firstIndex = -1, int lastIndex = -1); 0682 0683 /** 0684 * Helper method for updateExpansionIndicators(). 0685 * @return True if the item with the index \a index has a sibling successor 0686 * (= the item is not the last item of the current hierarchy). 0687 */ 0688 bool hasSiblingSuccessor(int index) const; 0689 0690 /** 0691 * Helper method for slotRoleEditingCanceled() and slotRoleEditingFinished(). 0692 * Disconnects the two Signals "roleEditingCanceled" and 0693 * "roleEditingFinished" 0694 */ 0695 void disconnectRoleEditingSignals(int index); 0696 0697 /** 0698 * Helper function for triggerAutoScrolling(). 0699 * @param pos Logical position of the mouse relative to the range. 0700 * @param range Range of the visible area. 0701 * @param oldInc Previous increment. Is used to assure that the increment 0702 * increases only gradually. 0703 * @return Scroll increment that should be added to the offset(). 0704 * As soon as \a pos is inside the autoscroll-margin a 0705 * value != 0 will be returned. 0706 */ 0707 static int calculateAutoScrollingIncrement(int pos, int range, int oldInc); 0708 0709 /** 0710 * Helper functions for changesItemCount(). 0711 * @return The number of items that fit into the available size by 0712 * respecting the size of the item and the margin between the items. 0713 */ 0714 static int itemsPerSize(qreal size, qreal itemSize, qreal itemMargin); 0715 0716 private: 0717 bool m_enabledSelectionToggles; 0718 bool m_grouped; 0719 bool m_highlightEntireRow; 0720 bool m_alternateBackgrounds; 0721 bool m_supportsItemExpanding; 0722 bool m_editingRole; 0723 int m_activeTransactions; // Counter for beginTransaction()/endTransaction() 0724 LayoutAnimationHint m_endTransactionAnimationHint; 0725 0726 QSizeF m_itemSize; 0727 KItemListController *m_controller; 0728 KItemModelBase *m_model; 0729 QList<QByteArray> m_visibleRoles; 0730 mutable KItemListWidgetCreatorBase *m_widgetCreator; 0731 mutable KItemListGroupHeaderCreatorBase *m_groupHeaderCreator; 0732 #ifndef QT_NO_ACCESSIBILITY 0733 /** The object that will be the parent of this classes QAccessibleInterface. */ 0734 KItemListContainerAccessible *m_accessibleParent = nullptr; 0735 #endif 0736 KItemListStyleOption m_styleOption; 0737 0738 QHash<int, KItemListWidget *> m_visibleItems; 0739 QHash<KItemListWidget *, KItemListGroupHeader *> m_visibleGroups; 0740 0741 struct Cell { 0742 Cell() 0743 : column(-1) 0744 , row(-1) 0745 { 0746 } 0747 Cell(int c, int r) 0748 : column(c) 0749 , row(r) 0750 { 0751 } 0752 int column; 0753 int row; 0754 }; 0755 QHash<int, Cell> m_visibleCells; 0756 0757 int m_scrollBarExtent; 0758 KItemListViewLayouter *m_layouter; 0759 KItemListViewAnimation *m_animation; 0760 0761 qreal m_oldScrollOffset; 0762 qreal m_oldMaximumScrollOffset; 0763 qreal m_oldItemOffset; 0764 qreal m_oldMaximumItemOffset; 0765 0766 bool m_skipAutoScrollForRubberBand; 0767 KItemListRubberBand *m_rubberBand; 0768 KItemListRubberBand *m_tapAndHoldIndicator; 0769 0770 QPointF m_mousePos; 0771 int m_autoScrollIncrement; 0772 QTimer *m_autoScrollTimer; 0773 0774 KItemListHeader *m_header; 0775 KItemListHeaderWidget *m_headerWidget; 0776 0777 QPropertyAnimation *m_indicatorAnimation; 0778 0779 // When dragging items into the view where the sort-role of the model 0780 // is empty, a visual indicator should be shown during dragging where 0781 // the dropping will happen. This indicator is specified by an index 0782 // of the item. -1 means that no indicator will be shown at all. 0783 // The m_dropIndicator is set by the KItemListController 0784 // by KItemListView::showDropIndicator() and KItemListView::hideDropIndicator(). 0785 QRectF m_dropIndicator; 0786 0787 QList<QVariantAnimation *> m_rubberBandAnimations; 0788 0789 KItemListSizeHintResolver *m_sizeHintResolver; 0790 0791 friend class KItemListContainer; // Accesses scrollBarRequired() 0792 friend class KItemListHeader; // Accesses m_headerWidget 0793 friend class KItemListController; 0794 friend class KItemListControllerTest; 0795 friend class KItemListViewAccessible; 0796 friend class KItemListAccessibleCell; 0797 }; 0798 0799 /** 0800 * Allows to do a fast logical creation and deletion of QGraphicsWidgets 0801 * by recycling existing QGraphicsWidgets instances. Is used by 0802 * KItemListWidgetCreatorBase and KItemListGroupHeaderCreatorBase. 0803 * @internal 0804 */ 0805 class DOLPHIN_EXPORT KItemListCreatorBase 0806 { 0807 public: 0808 virtual ~KItemListCreatorBase(); 0809 0810 protected: 0811 void addCreatedWidget(QGraphicsWidget *widget); 0812 void pushRecycleableWidget(QGraphicsWidget *widget); 0813 QGraphicsWidget *popRecycleableWidget(); 0814 0815 private: 0816 QSet<QGraphicsWidget *> m_createdWidgets; 0817 QList<QGraphicsWidget *> m_recycleableWidgets; 0818 }; 0819 0820 /** 0821 * @brief Base class for creating KItemListWidgets. 0822 * 0823 * It is recommended that applications simply use the KItemListWidgetCreator-template class. 0824 * For a custom implementation the methods create(), itemSizeHint() and preferredColumnWith() 0825 * must be reimplemented. The intention of the widget creator is to prevent repetitive and 0826 * expensive instantiations and deletions of KItemListWidgets by recycling existing widget 0827 * instances. 0828 */ 0829 class DOLPHIN_EXPORT KItemListWidgetCreatorBase : public KItemListCreatorBase 0830 { 0831 public: 0832 ~KItemListWidgetCreatorBase() override; 0833 0834 virtual KItemListWidget *create(KItemListView *view) = 0; 0835 0836 virtual void recycle(KItemListWidget *widget); 0837 0838 virtual void calculateItemSizeHints(QVector<std::pair<qreal, bool>> &logicalHeightHints, qreal &logicalWidthHint, const KItemListView *view) const = 0; 0839 0840 virtual qreal preferredRoleColumnWidth(const QByteArray &role, int index, const KItemListView *view) const = 0; 0841 }; 0842 0843 /** 0844 * @brief Template class for creating KItemListWidgets. 0845 */ 0846 template<class T> 0847 class KItemListWidgetCreator : public KItemListWidgetCreatorBase 0848 { 0849 public: 0850 KItemListWidgetCreator(); 0851 ~KItemListWidgetCreator() override; 0852 0853 KItemListWidget *create(KItemListView *view) override; 0854 0855 void calculateItemSizeHints(QVector<std::pair<qreal, bool>> &logicalHeightHints, qreal &logicalWidthHint, const KItemListView *view) const override; 0856 0857 qreal preferredRoleColumnWidth(const QByteArray &role, int index, const KItemListView *view) const override; 0858 0859 private: 0860 KItemListWidgetInformant *m_informant; 0861 }; 0862 0863 template<class T> 0864 KItemListWidgetCreator<T>::KItemListWidgetCreator() 0865 : m_informant(T::createInformant()) 0866 { 0867 } 0868 0869 template<class T> 0870 KItemListWidgetCreator<T>::~KItemListWidgetCreator() 0871 { 0872 delete m_informant; 0873 } 0874 0875 template<class T> 0876 KItemListWidget *KItemListWidgetCreator<T>::create(KItemListView *view) 0877 { 0878 KItemListWidget *widget = static_cast<KItemListWidget *>(popRecycleableWidget()); 0879 if (!widget) { 0880 widget = new T(m_informant, view); 0881 addCreatedWidget(widget); 0882 } 0883 widget->setParentItem(view); 0884 return widget; 0885 } 0886 0887 template<class T> 0888 void KItemListWidgetCreator<T>::calculateItemSizeHints(QVector<std::pair<qreal, bool>> &logicalHeightHints, 0889 qreal &logicalWidthHint, 0890 const KItemListView *view) const 0891 { 0892 return m_informant->calculateItemSizeHints(logicalHeightHints, logicalWidthHint, view); 0893 } 0894 0895 template<class T> 0896 qreal KItemListWidgetCreator<T>::preferredRoleColumnWidth(const QByteArray &role, int index, const KItemListView *view) const 0897 { 0898 return m_informant->preferredRoleColumnWidth(role, index, view); 0899 } 0900 0901 /** 0902 * @brief Base class for creating KItemListGroupHeaders. 0903 * 0904 * It is recommended that applications simply use the KItemListGroupHeaderCreator-template class. 0905 * For a custom implementation the methods create() and recycle() must be reimplemented. 0906 * The intention of the group-header creator is to prevent repetitive and expensive instantiations and 0907 * deletions of KItemListGroupHeaders by recycling existing header instances. 0908 */ 0909 class DOLPHIN_EXPORT KItemListGroupHeaderCreatorBase : public KItemListCreatorBase 0910 { 0911 public: 0912 ~KItemListGroupHeaderCreatorBase() override; 0913 virtual KItemListGroupHeader *create(KItemListView *view) = 0; 0914 virtual void recycle(KItemListGroupHeader *header); 0915 }; 0916 0917 template<class T> 0918 class KItemListGroupHeaderCreator : public KItemListGroupHeaderCreatorBase 0919 { 0920 public: 0921 ~KItemListGroupHeaderCreator() override; 0922 KItemListGroupHeader *create(KItemListView *view) override; 0923 }; 0924 0925 template<class T> 0926 KItemListGroupHeaderCreator<T>::~KItemListGroupHeaderCreator() 0927 { 0928 } 0929 0930 template<class T> 0931 KItemListGroupHeader *KItemListGroupHeaderCreator<T>::create(KItemListView *view) 0932 { 0933 KItemListGroupHeader *widget = static_cast<KItemListGroupHeader *>(popRecycleableWidget()); 0934 if (!widget) { 0935 widget = new T(view); 0936 addCreatedWidget(widget); 0937 } 0938 return widget; 0939 } 0940 0941 #endif