X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/07b0bf462698cc36db886c555124269a4ad7741f..76a46fd9094b17eb99e8a42cca8562fdc0b3814c:/src/kitemviews/kitemlistview.h diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index 985b7c278..2a3b7ada2 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -1,8 +1,7 @@ /*************************************************************************** * Copyright (C) 2011 by Peter Penz * * * - * Based on the Itemviews NG project from Trolltech Labs: * - * http://qt.gitorious.org/qt-labs/itemviews-ng * + * Based on the Itemviews NG project from Trolltech Labs * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -23,26 +22,27 @@ #ifndef KITEMLISTVIEW_H #define KITEMLISTVIEW_H -#include +#include "dolphin_export.h" +#include "kitemviews/kitemliststyleoption.h" +#include "kitemviews/kitemlistwidget.h" +#include "kitemviews/kitemmodelbase.h" +#include "kitemviews/kstandarditemlistgroupheader.h" +#include "kitemviews/private/kitemlistviewanimation.h" -#include -#include -#include -#include -#include #include #include class KItemListController; class KItemListGroupHeaderCreatorBase; class KItemListHeader; +class KItemListHeaderWidget; class KItemListSizeHintResolver; class KItemListRubberBand; class KItemListViewAnimation; class KItemListViewLayouter; class KItemListWidget; +class KItemListWidgetInformant; class KItemListWidgetCreatorBase; -class KItemListViewCreatorBase; class QTimer; /** @@ -52,16 +52,13 @@ class QTimer; * a GraphicsItem. Each visible item is represented by a KItemListWidget. * * The created view must be applied to the KItemListController with - * KItemListController::setView(). For showing a custom model it is not - * mandatory to derive from KItemListView, all that is necessary is - * to set a widget-creator that is capable to create KItemListWidgets - * showing the model items. A widget-creator can be set with - * KItemListView::setWidgetCreator(). + * KItemListController::setView() or with the constructor of + * KItemListController. * * @see KItemListWidget * @see KItemModelBase */ -class LIBDOLPHINPRIVATE_EXPORT KItemListView : public QGraphicsWidget +class DOLPHIN_EXPORT KItemListView : public QGraphicsWidget { Q_OBJECT @@ -69,26 +66,32 @@ class LIBDOLPHINPRIVATE_EXPORT KItemListView : public QGraphicsWidget Q_PROPERTY(qreal itemOffset READ itemOffset WRITE setItemOffset) public: - KItemListView(QGraphicsWidget* parent = 0); - virtual ~KItemListView(); + explicit KItemListView(QGraphicsWidget* parent = nullptr); + ~KItemListView() override; - void setScrollOrientation(Qt::Orientation orientation); - Qt::Orientation scrollOrientation() const; - - void setItemSize(const QSizeF& size); - QSizeF itemSize() const; - - // TODO: add note that offset is not checked against maximumOffset, only against 0. + /** + * Offset of the scrollbar that represents the scroll-orientation + * (see setScrollOrientation()). + */ void setScrollOffset(qreal offset); qreal scrollOffset() const; qreal maximumScrollOffset() const; + /** + * Offset related to an item, that does not fit into the available + * size of the listview. If the scroll-orientation is vertical + * the item-offset describes the offset of the horizontal axe, if + * the scroll-orientation is horizontal the item-offset describes + * the offset of the vertical axe. + */ void setItemOffset(qreal scrollOffset); qreal itemOffset() const; qreal maximumItemOffset() const; + int maximumVisibleItems() const; + void setVisibleRoles(const QList& roles); QList visibleRoles() const; @@ -100,6 +103,13 @@ public: void setAutoScroll(bool enabled); bool autoScroll() const; + /** + * If set to true selection-toggles will be shown when hovering + * an item. Per default the selection-toggles are disabled. + */ + void setEnabledSelectionToggles(bool enabled); + bool enabledSelectionToggles() const; + /** * @return Controller of the item-list. The controller gets * initialized by KItemListController::setView() and will @@ -109,7 +119,7 @@ public: /** * @return Model of the item-list. The model gets - * initialized by KItemListController::setView() and will + * initialized by KItemListController::setModel() and will * result in calling KItemListController::onModelChanged(). */ KItemModelBase* model() const; @@ -122,82 +132,154 @@ public: * * itemListView->setWidgetCreator(new KItemListWidgetCreator()); * - * Note that the ownership of the widget creator is not transferred to - * the item-list view: One instance of a widget creator might get shared - * by several item-list view instances. + * The ownership of the widget creator is transferred to + * the item-list view. **/ void setWidgetCreator(KItemListWidgetCreatorBase* widgetCreator); KItemListWidgetCreatorBase* widgetCreator() const; + /** + * Sets the creator that creates a group header. Usually it is sufficient + * to implement a custom header widget X derived from KItemListGroupHeader and + * set the creator by: + * + * itemListView->setGroupHeaderCreator(new KItemListGroupHeaderCreator()); + * + * The ownership of the gropup header creator is transferred to + * the item-list view. + **/ void setGroupHeaderCreator(KItemListGroupHeaderCreatorBase* groupHeaderCreator); KItemListGroupHeaderCreatorBase* groupHeaderCreator() const; - void setStyleOption(const KItemListStyleOption& option); + /** + * @return The basic size of all items. The size of an item may be larger than + * the basic size (see KItemListView::itemRect()). + */ + QSizeF itemSize() const; + const KItemListStyleOption& styleOption() const; - /** @reimp */ - virtual void setGeometry(const QRectF& rect); + void setGeometry(const QRectF& rect) override; + /** + * @return The page step which should be used by the vertical scroll bar. + * This is the height of the view except for the header widget. + */ + qreal verticalPageStep() const; + + /** + * @return Index of the item that is below the point \a pos. + * The position is relative to the upper right of + * the visible area. Only (at least partly) visible + * items are considered. -1 is returned if no item is + * below the position. + */ int itemAt(const QPointF& pos) const; bool isAboveSelectionToggle(int index, const QPointF& pos) const; bool isAboveExpansionToggle(int index, const QPointF& pos) const; + bool isAboveText(int index, const QPointF& pos) const; + /** + * @return Index of the first item that is at least partly visible. + * -1 is returned if the model contains no items. + */ int firstVisibleIndex() const; + + /** + * @return Index of the last item that is at least partly visible. + * -1 is returned if the model contains no items. + */ int lastVisibleIndex() const; /** - * @return Required size for the item with the index \p index. - * Per default KItemListView::itemSize() is returned. - * When reimplementing this method it is recommended to - * also reimplement KItemListView::itemSizeHintUpdateRequired(). + * Calculates the required size for all items in the model. + * It might be larger than KItemListView::itemSize(). + * In this case the layout grid will be stretched to assure an + * unclipped item. + * + * @note the logical height (width) is actually the + * width (height) if the scroll orientation is Qt::Vertical! */ - virtual QSizeF itemSizeHint(int index) const; + void calculateItemSizeHints(QVector& logicalHeightHints, qreal& logicalWidthHint) const; /** - * @param itemRanges Items that must be checked for getting the visible roles sizes. - * @return The size of each visible role in case if KItemListView::itemSize() - * is empty. This allows to have dynamic but equal role sizes between - * all items. Per default an empty hash is returned. + * If set to true, items having child-items can be expanded to show the child-items as + * part of the view. Per default the expanding of items is disabled. If expanding of + * items is enabled, the methods KItemModelBase::setExpanded(), KItemModelBase::isExpanded(), + * KItemModelBase::isExpandable() and KItemModelBase::expandedParentsCount() + * must be reimplemented. The view-implementation + * has to take care itself how to visually represent the expanded items provided + * by the model. */ - virtual QHash visibleRolesSizes(const KItemRangeList& itemRanges) const; + void setSupportsItemExpanding(bool supportsExpanding); + bool supportsItemExpanding() const; /** - * @return The bounding rectangle of the item relative to the top/left of + * @return The rectangle of the item relative to the top/left of * the currently visible area (see KItemListView::offset()). */ - QRectF itemBoundingRect(int index) const; + QRectF itemRect(int index) const; + + /** + * @return The context rectangle of the item relative to the top/left of + * the currently visible area (see KItemListView::offset()). The + * context rectangle is defined by the united rectangle of + * the icon rectangle and the text rectangle (see KItemListWidget::iconRect() + * and KItemListWidget::textRect()) and is useful as reference for e.g. aligning + * a tooltip or a context-menu for an item. Note that a context rectangle will + * only be returned for (at least partly) visible items. An empty rectangle will + * be returned for fully invisible items. + */ + QRectF itemContextRect(int index) const; /** - * @return The number of items that can be shown in parallel for one offset. - * Assuming the scrolldirection is vertical then a value of 4 means - * that 4 columns for items are available. Assuming the scrolldirection - * is horizontal then a value of 4 means that 4 lines for items are - * available. + * Scrolls to the item with the index \a index so that the item + * will be fully visible. */ - int itemsPerOffset() const; + void scrollToItem(int index); + /** + * If several properties of KItemListView are changed synchronously, it is + * recommended to encapsulate the calls between beginTransaction() and endTransaction(). + * This prevents unnecessary and expensive layout-calculations. + */ void beginTransaction(); + + /** + * Counterpart to beginTransaction(). The layout changes will only be animated if + * all property changes between beginTransaction() and endTransaction() support + * animations. + */ void endTransaction(); + bool isTransactionActive() const; /** - * Turns on the header if \p show is true. Per default the - * header is not shown. + * Turns on the header if \p visible is true. Per default the + * header is not visible. Usually the header is turned on when + * showing a classic "table-view" to describe the shown columns. + */ + void setHeaderVisible(bool visible); + bool isHeaderVisible() const; + + /** + * @return Header of the list. The header is also available if it is not shown + * (see KItemListView::setHeaderShown()). */ - void setHeaderShown(bool show); - bool isHeaderShown() const; + KItemListHeader* header() const; /** * @return Pixmap that is used for a drag operation based on the - * items given by \a indexes. The default implementation returns - * a null-pixmap. + * items given by \a indexes. */ - virtual QPixmap createDragPixmap(const QSet& indexes) const; + virtual QPixmap createDragPixmap(const KItemSet& indexes) const; /** - * @reimp + * Lets the user edit the role \a role for item with the index \a index. */ - virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0); + void editRole(int index, const QByteArray& role); + + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = nullptr) override; signals: void scrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous); @@ -207,7 +289,68 @@ signals: void maximumItemOffsetChanged(qreal current, qreal previous); void scrollTo(qreal newOffset); + /** + * Is emitted if the user has changed the sort order by clicking on a + * header item (see KItemListView::setHeaderShown()). The sort order + * of the model has already been adjusted to + * the current sort order. Note that no signal will be emitted if the + * sort order of the model has been changed without user interaction. + */ + void sortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous); + + /** + * Is emitted if the user has changed the sort role by clicking on a + * header item (see KItemListView::setHeaderShown()). The sort role + * of the model has already been adjusted to + * the current sort role. Note that no signal will be emitted if the + * sort role of the model has been changed without user interaction. + */ + void sortRoleChanged(const QByteArray& current, const QByteArray& previous); + + /** + * Is emitted if the user has changed the visible roles by moving a header + * item (see KItemListView::setHeaderShown()). Note that no signal will be + * emitted if the roles have been changed without user interaction by + * KItemListView::setVisibleRoles(). + */ + void visibleRolesChanged(const QList& current, const QList& previous); + + void roleEditingCanceled(int index, const QByteArray& role, const QVariant& value); + void roleEditingFinished(int index, const QByteArray& role, const QVariant& value); + protected: + QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; + void setItemSize(const QSizeF& size); + void setStyleOption(const KItemListStyleOption& option); + + /** + * If the scroll-orientation is vertical, the items are ordered + * from top to bottom (= default setting). If the scroll-orientation + * is horizontal, the items are ordered from left to right. + */ + void setScrollOrientation(Qt::Orientation orientation); + Qt::Orientation scrollOrientation() const; + + /** + * Factory method for creating a default widget-creator. The method will be used + * in case if setWidgetCreator() has not been set by the application. + * @return New instance of the widget-creator that should be used per + * default. + */ + virtual KItemListWidgetCreatorBase* defaultWidgetCreator() const; + + /** + * Factory method for creating a default group-header-creator. The method will be used + * in case if setGroupHeaderCreator() has not been set by the application. + * @return New instance of the group-header-creator that should be used per + * default. + */ + virtual KItemListGroupHeaderCreatorBase* defaultGroupHeaderCreator() const; + + /** + * Is called when creating a new KItemListWidget instance and allows derived + * classes to do a custom initialization. + */ virtual void initializeItemListWidget(KItemListWidget* item); /** @@ -228,22 +371,23 @@ protected: virtual void onScrollOffsetChanged(qreal current, qreal previous); virtual void onVisibleRolesChanged(const QList& current, const QList& previous); virtual void onStyleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous); + virtual void onSupportsItemExpandingChanged(bool supportsExpanding); virtual void onTransactionBegin(); virtual void onTransactionEnd(); - virtual bool event(QEvent* event); - virtual void mousePressEvent(QGraphicsSceneMouseEvent* event); - virtual void mouseMoveEvent(QGraphicsSceneMouseEvent* event); - virtual void dragEnterEvent(QGraphicsSceneDragDropEvent* event); - virtual void dragMoveEvent(QGraphicsSceneDragDropEvent* event); - virtual void dragLeaveEvent(QGraphicsSceneDragDropEvent* event); - virtual void dropEvent(QGraphicsSceneDragDropEvent* event); + bool event(QEvent* event) override; + void mousePressEvent(QGraphicsSceneMouseEvent* event) override; + void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override; + void dragEnterEvent(QGraphicsSceneDragDropEvent* event) override; + void dragMoveEvent(QGraphicsSceneDragDropEvent* event) override; + void dragLeaveEvent(QGraphicsSceneDragDropEvent* event) override; + void dropEvent(QGraphicsSceneDragDropEvent* event) override; QList visibleItemListWidgets() const; - /** @reimp */ - virtual void resizeEvent(QGraphicsSceneResizeEvent* event); + virtual void updateFont(); + virtual void updatePalette(); protected slots: virtual void slotItemsInserted(const KItemRangeList& itemRanges); @@ -251,11 +395,15 @@ protected slots: virtual void slotItemsMoved(const KItemRange& itemRange, const QList& movedToIndexes); virtual void slotItemsChanged(const KItemRangeList& itemRanges, const QSet& roles); + virtual void slotGroupsChanged(); + + virtual void slotGroupedSortingChanged(bool current); + virtual void slotSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous); + virtual void slotSortRoleChanged(const QByteArray& current, const QByteArray& previous); + virtual void slotCurrentChanged(int current, int previous); + virtual void slotSelectionChanged(const KItemSet& current, const KItemSet& previous); private slots: - void slotGroupedSortingChanged(bool current); - void slotCurrentChanged(int current, int previous); - void slotSelectionChanged(const QSet& current, const QSet& previous); void slotAnimationFinished(QGraphicsWidget* widget, KItemListViewAnimation::AnimationType type); void slotLayoutTimerFinished(); @@ -264,14 +412,22 @@ private slots: void slotRubberBandActivationChanged(bool active); /** - * Is invoked if the visible role-width of one role in the header has - * been changed by the user. It is remembered that the user has modified - * the role-width, so that it won't be changed anymore automatically to - * calculate an optimized width. + * Is invoked if the column-width of one role in the header has + * been changed by the user. The automatic resizing of columns + * will be turned off as soon as this method has been called at + * least once. + */ + void slotHeaderColumnWidthChanged(const QByteArray& role, + qreal currentWidth, + qreal previousWidth); + + /** + * Is invoked if a column has been moved by the user. Applies + * the moved role to the view. */ - void slotVisibleRoleWidthChanged(const QByteArray& role, - qreal currentWidth, - qreal previousWidth); + void slotHeaderColumnMoved(const QByteArray& role, + int currentIndex, + int previousIndex); /** * Triggers the autoscrolling if autoScroll() is enabled by checking the @@ -280,6 +436,17 @@ private slots: */ void triggerAutoScrolling(); + /** + * Is invoked if the geometry of the parent-widget from a group-header has been + * changed. The x-position and width of the group-header gets adjusted to assure + * that it always spans the whole width even during temporary transitions of the + * parent widget. + */ + void slotGeometryOfGroupHeaderParentChanged(); + + void slotRoleEditingCanceled(int index, const QByteArray& role, const QVariant& value); + void slotRoleEditingFinished(int index, const QByteArray& role, const QVariant& value); + private: enum LayoutAnimationHint { @@ -298,25 +465,46 @@ private: KItemListRubberBand* rubberBand() const; - void updateLayout(); - void doLayout(LayoutAnimationHint hint, int changedIndex, int changedCount); - void doGroupHeadersLayout(LayoutAnimationHint hint, int changedIndex, int changedCount); + void doLayout(LayoutAnimationHint hint, int changedIndex = 0, int changedCount = 0); + + /** + * Helper method for doLayout: Returns a list of items that can be reused for the visible + * area. Invisible group headers get recycled. The reusable items are items that are + * invisible. If the animation hint is 'Animation' then items that are currently animated + * won't be reused. Reusing items is faster in comparison to deleting invisible + * items and creating a new instance for visible items. + */ + QList recycleInvisibleItems(int firstVisibleIndex, + int lastVisibleIndex, + LayoutAnimationHint hint); + + /** + * Helper method for doLayout: Starts a moving-animation for the widget to the given + * new position. The moving-animation is only started if the new position is within + * the same row or column, otherwise the create-animation is used instead. + * @return True if the moving-animation has been applied. + */ + bool moveWidget(KItemListWidget* widget, const QPointF& newPos); + void emitOffsetChanges(); KItemListWidget* createWidget(int index); void recycleWidget(KItemListWidget* widget); + + /** + * Changes the index of the widget to \a index and assures a consistent + * update for m_visibleItems and m_visibleCells. The cell-information + * for the new index will not be updated and be initialized as empty cell. + */ void setWidgetIndex(KItemListWidget* widget, int index); /** - * Helper method for setGeometry() and setItemSize(): Calling both methods might result - * in a changed number of visible items. To assure that currently invisible items can - * get animated from the old position to the new position prepareLayoutForIncreasedItemCount() - * takes care to create all item widgets that are visible with the old or the new size. - * @param size Size of the layouter or the item dependent on \p sizeType. - * @param sizeType LayouterSize: KItemListLayouter::setSize() is used. - * ItemSize: KItemListLayouter::setItemSize() is used. + * Changes the index of the widget to \a index. In opposite to + * setWidgetIndex() the cell-information for the widget gets updated. + * This update gives doLayout() the chance to animate the moving + * of the item visually (see moveWidget()). */ - void prepareLayoutForIncreasedItemCount(const QSizeF& size, SizeType sizeType); + void moveWidgetToIndex(KItemListWidget* widget, int index); /** * Helper method for prepareLayoutForIncreasedItemCount(). @@ -330,50 +518,98 @@ private: void updateWidgetProperties(KItemListWidget* widget, int index); /** - * Helper method for createWidget() and setWidgetIndex() to create or update + * Helper method for updateWidgetPropertes() to create or update * the itemlist group-header. */ void updateGroupHeaderForWidget(KItemListWidget* widget); /** - * Recycles the group-header from the widget. + * Updates the position and size of the group-header that belongs + * to the itemlist widget \a widget. The given widget must represent + * the first item of a group. + */ + void updateGroupHeaderLayout(KItemListWidget* widget); + + /** + * Recycles the group-header for the widget. */ void recycleGroupHeaderForWidget(KItemListWidget* widget); /** - * @return The widths of each visible role that is shown in the KItemListHeader. + * Helper method for slotGroupedSortingChanged(), slotSortOrderChanged() + * and slotSortRoleChanged(): Iterates through all visible items and updates + * the group-header widgets. + */ + void updateVisibleGroupHeaders(); + + /** + * @return Index for the item in the list returned by KItemModelBase::groups() + * that represents the group where the item with the index \a index + * belongs to. -1 is returned if no groups are available. + */ + int groupIndexForItem(int index) const; + + /** + * Updates the alternate background for all visible items. + * @see updateAlternateBackgroundForWidget() + */ + void updateAlternateBackgrounds(); + + /** + * Updates the alternateBackground-property of the widget dependent + * on the state of useAlternateBackgrounds() and the grouping state. */ - QHash headerRolesWidths() const; + void updateAlternateBackgroundForWidget(KItemListWidget* widget); /** - * Updates m_visibleRolesSizes by calling KItemListView::visibleRolesSizes(). - * Nothing will be done if m_itemRect is not empty or custom header-widths - * are used (see m_useHeaderWidths). Also m_strechedVisibleRolesSizes will be adjusted - * to respect the available view-size. + * @return True if alternate backgrounds should be used for the items. + * This is the case if an empty item-size is given and if there + * is more than one visible role. */ - void updateVisibleRolesSizes(const KItemRangeList& itemRanges); + bool useAlternateBackgrounds() const; /** - * Convenience method for updateVisibleRoleSizes(KItemRangeList() << KItemRange(0, m_model->count()). + * @param itemRanges Items that must be checked for getting the widths of columns. + * @return The preferred width of the column of each visible role. The width will + * be respected if the width of the item size is <= 0 (see + * KItemListView::setItemSize()). Per default an empty hash + * is returned. */ - void updateVisibleRolesSizes(); + QHash preferredColumnWidths(const KItemRangeList& itemRanges) const; /** - * Updates m_stretchedVisibleRolesSizes based on m_visibleRolesSizes and the available - * view-size. Nothing will be done if m_itemRect is not empty or custom header-widths - * are used (see m_useHeaderWidths). + * Applies the column-widths from m_headerWidget to the layout + * of the view. */ - void updateStretchedVisibleRolesSizes(); + void applyColumnWidthsFromHeader(); /** - * @return Sum of the widths of all visible roles. + * Applies the column-widths from m_headerWidget to \a widget. */ - qreal visibleRolesSizesWidthSum() const; + void updateWidgetColumnWidths(KItemListWidget* widget); /** - * @return Sum of the heights of all visible roles. + * Updates the preferred column-widths of m_groupHeaderWidget by + * invoking KItemListView::columnWidths(). */ - qreal visibleRolesSizesHeightSum() const; + void updatePreferredColumnWidths(const KItemRangeList& itemRanges); + + /** + * Convenience method for + * updatePreferredColumnWidths(KItemRangeList() << KItemRange(0, m_model->count()). + */ + void updatePreferredColumnWidths(); + + /** + * Resizes the column-widths of m_headerWidget based on the preferred widths + * and the vailable view-size. + */ + void applyAutomaticColumnWidths(); + + /** + * @return Sum of the widths of all columns. + */ + qreal columnWidthsSum() const; /** * @return Boundaries of the header. An empty rectangle is returned @@ -381,6 +617,69 @@ private: */ QRectF headerBoundaries() const; + /** + * @return True if the number of columns or rows will be changed when applying + * the new grid- and item-size. Used to determine whether an animation + * should be done when applying the new layout. + */ + bool changesItemGridLayout(const QSizeF& newGridSize, + const QSizeF& newItemSize, + const QSizeF& newItemMargin) const; + + /** + * @param changedItemCount Number of inserted or removed items. + * @return True if the inserting or removing of items should be animated. + * No animation should be done if the number of items is too large + * to provide a pleasant animation. + */ + bool animateChangedItemCount(int changedItemCount) const; + + /** + * @return True if a scrollbar for the given scroll-orientation is required + * when using a size of \p size for the view. Calling the method is rather + * expansive as a temporary relayout needs to be done. + */ + bool scrollBarRequired(const QSizeF& size) const; + + /** + * Shows a drop-indicator between items dependent on the given + * cursor position. The cursor position is relative to the upper left + * edge of the view. + * @return Index of the item where the dropping is done. An index of -1 + * indicates that the item has been dropped after the last item. + */ + int showDropIndicator(const QPointF& pos); + void hideDropIndicator(); + + /** + * Applies the height of the group header to the layouter. The height + * depends on the used scroll orientation. + */ + void updateGroupHeaderHeight(); + + /** + * Updates the siblings-information for all visible items that are inside + * the range of \p firstIndex and \p lastIndex. If firstIndex or lastIndex + * is smaller than 0, the siblings-information for all visible items gets + * updated. + * @see KItemListWidget::setSiblingsInformation() + */ + void updateSiblingsInformation(int firstIndex = -1, int lastIndex = -1); + + /** + * Helper method for updateExpansionIndicators(). + * @return True if the item with the index \a index has a sibling successor + * (= the item is not the last item of the current hierarchy). + */ + bool hasSiblingSuccessor(int index) const; + + /** + * Helper method for slotRoleEditingCanceled() and slotRoleEditingFinished(). + * Disconnects the two Signals "roleEditingCanceled" and + * "roleEditingFinished" + */ + void disconnectRoleEditingSignals(int index); + /** * Helper function for triggerAutoScrolling(). * @param pos Logical position of the mouse relative to the range. @@ -393,23 +692,41 @@ private: */ static int calculateAutoScrollingIncrement(int pos, int range, int oldInc); + /** + * Helper functions for changesItemCount(). + * @return The number of items that fit into the available size by + * respecting the size of the item and the margin between the items. + */ + static int itemsPerSize(qreal size, qreal itemSize, qreal itemMargin); + private: + bool m_enabledSelectionToggles; bool m_grouped; + bool m_supportsItemExpanding; + bool m_editingRole; int m_activeTransactions; // Counter for beginTransaction()/endTransaction() + LayoutAnimationHint m_endTransactionAnimationHint; QSizeF m_itemSize; KItemListController* m_controller; KItemModelBase* m_model; QList m_visibleRoles; - QHash m_visibleRolesSizes; - QHash m_stretchedVisibleRolesSizes; - KItemListWidgetCreatorBase* m_widgetCreator; - KItemListGroupHeaderCreatorBase* m_groupHeaderCreator; + mutable KItemListWidgetCreatorBase* m_widgetCreator; + mutable KItemListGroupHeaderCreatorBase* m_groupHeaderCreator; KItemListStyleOption m_styleOption; QHash m_visibleItems; QHash m_visibleGroups; + struct Cell + { + Cell() : column(-1), row(-1) {} + Cell(int c, int r) : column(c), row(r) {} + int column; + int row; + }; + QHash m_visibleCells; + int m_scrollBarExtent; KItemListSizeHintResolver* m_sizeHintResolver; KItemListViewLayouter* m_layouter; @@ -429,9 +746,22 @@ private: QTimer* m_autoScrollTimer; KItemListHeader* m_header; - bool m_useHeaderWidths; - + KItemListHeaderWidget* m_headerWidget; + + // When dragging items into the view where the sort-role of the model + // is empty, a visual indicator should be shown during dragging where + // the dropping will happen. This indicator is specified by an index + // of the item. -1 means that no indicator will be shown at all. + // The m_dropIndicator is set by the KItemListController + // by KItemListView::showDropIndicator() and KItemListView::hideDropIndicator(). + QRectF m_dropIndicator; + + friend class KItemListContainer; // Accesses scrollBarRequired() + friend class KItemListHeader; // Accesses m_headerWidget friend class KItemListController; + friend class KItemListControllerTest; + friend class KItemListViewAccessible; + friend class KItemListAccessibleCell; }; /** @@ -440,7 +770,7 @@ private: * KItemListWidgetCreatorBase and KItemListGroupHeaderCreatorBase. * @internal */ -class LIBDOLPHINPRIVATE_EXPORT KItemListCreatorBase +class DOLPHIN_EXPORT KItemListCreatorBase { public: virtual ~KItemListCreatorBase(); @@ -459,29 +789,58 @@ private: * @brief Base class for creating KItemListWidgets. * * It is recommended that applications simply use the KItemListWidgetCreator-template class. - * For a custom implementation the methods create() and recyle() must be reimplemented. - * The intention of the widget creator is to prevent repetitive and expensive instantiations and - * deletions of KItemListWidgets by recycling existing widget instances. + * For a custom implementation the methods create(), itemSizeHint() and preferredColumnWith() + * must be reimplemented. The intention of the widget creator is to prevent repetitive and + * expensive instantiations and deletions of KItemListWidgets by recycling existing widget + * instances. */ -class LIBDOLPHINPRIVATE_EXPORT KItemListWidgetCreatorBase : public KItemListCreatorBase +class DOLPHIN_EXPORT KItemListWidgetCreatorBase : public KItemListCreatorBase { public: - virtual ~KItemListWidgetCreatorBase(); + ~KItemListWidgetCreatorBase() override; + virtual KItemListWidget* create(KItemListView* view) = 0; + virtual void recycle(KItemListWidget* widget); + + virtual void calculateItemSizeHints(QVector& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const = 0; + + virtual qreal preferredRoleColumnWidth(const QByteArray& role, + int index, + const KItemListView* view) const = 0; }; +/** + * @brief Template class for creating KItemListWidgets. + */ template -class LIBDOLPHINPRIVATE_EXPORT KItemListWidgetCreator : public KItemListWidgetCreatorBase +class KItemListWidgetCreator : public KItemListWidgetCreatorBase { public: - virtual ~KItemListWidgetCreator(); - virtual KItemListWidget* create(KItemListView* view); + KItemListWidgetCreator(); + ~KItemListWidgetCreator() override; + + KItemListWidget* create(KItemListView* view) override; + + void calculateItemSizeHints(QVector& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const override; + + qreal preferredRoleColumnWidth(const QByteArray& role, + int index, + const KItemListView* view) const override; +private: + KItemListWidgetInformant* m_informant; }; +template +KItemListWidgetCreator::KItemListWidgetCreator() : + m_informant(T::createInformant()) +{ +} + template KItemListWidgetCreator::~KItemListWidgetCreator() { + delete m_informant; } template @@ -489,12 +848,26 @@ KItemListWidget* KItemListWidgetCreator::create(KItemListView* view) { KItemListWidget* widget = static_cast(popRecycleableWidget()); if (!widget) { - widget = new T(view); + widget = new T(m_informant, view); addCreatedWidget(widget); } return widget; } +template +void KItemListWidgetCreator::calculateItemSizeHints(QVector& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const +{ + return m_informant->calculateItemSizeHints(logicalHeightHints, logicalWidthHint, view); +} + +template +qreal KItemListWidgetCreator::preferredRoleColumnWidth(const QByteArray& role, + int index, + const KItemListView* view) const +{ + return m_informant->preferredRoleColumnWidth(role, index, view); +} + /** * @brief Base class for creating KItemListGroupHeaders. * @@ -503,20 +876,20 @@ KItemListWidget* KItemListWidgetCreator::create(KItemListView* view) * The intention of the group-header creator is to prevent repetitive and expensive instantiations and * deletions of KItemListGroupHeaders by recycling existing header instances. */ -class LIBDOLPHINPRIVATE_EXPORT KItemListGroupHeaderCreatorBase : public KItemListCreatorBase +class DOLPHIN_EXPORT KItemListGroupHeaderCreatorBase : public KItemListCreatorBase { public: - virtual ~KItemListGroupHeaderCreatorBase(); + ~KItemListGroupHeaderCreatorBase() override; virtual KItemListGroupHeader* create(KItemListView* view) = 0; virtual void recycle(KItemListGroupHeader* header); }; template -class LIBDOLPHINPRIVATE_EXPORT KItemListGroupHeaderCreator : public KItemListGroupHeaderCreatorBase +class KItemListGroupHeaderCreator : public KItemListGroupHeaderCreatorBase { public: - virtual ~KItemListGroupHeaderCreator(); - virtual KItemListGroupHeader* create(KItemListView* view); + ~KItemListGroupHeaderCreator() override; + KItemListGroupHeader* create(KItemListView* view) override; }; template