X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/5369ee6819a26d9d3f106521c525c03f81a943ce..8e3addb7e73122a4c89ef347b03f714ff75a253a:/src/kitemviews/kitemlistview.h diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index 50d8908e5..1a4ff0df1 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -1,49 +1,42 @@ -/*************************************************************************** - * Copyright (C) 2011 by Peter Penz * - * * - * Based on the Itemviews NG project from Trolltech Labs: * - * http://qt.gitorious.org/qt-labs/itemviews-ng * - * * - * 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 * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - ***************************************************************************/ +/* + * SPDX-FileCopyrightText: 2011 Peter Penz + * + * Based on the Itemviews NG project from Trolltech Labs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ #ifndef KITEMLISTVIEW_H #define KITEMLISTVIEW_H -#include +#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 KItemListContainer; +class KItemListContainerAccessible; 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; +class QPropertyAnimation; +class QVariantAnimation; /** * @brief Represents the view of an item-list. @@ -52,44 +45,50 @@ 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 - Q_PROPERTY(qreal scrollOffset READ scrollOffset WRITE setScrollOffset) - Q_PROPERTY(qreal itemOffset READ itemOffset WRITE setItemOffset) + Q_PROPERTY(qreal scrollOffset READ scrollOffset WRITE setScrollOffset NOTIFY scrollOffsetChanged) + Q_PROPERTY(qreal itemOffset READ itemOffset WRITE setItemOffset NOTIFY itemOffsetChanged) public: - KItemListView(QGraphicsWidget* parent = 0); - virtual ~KItemListView(); - - void setScrollOrientation(Qt::Orientation orientation); - Qt::Orientation scrollOrientation() const; + /** The position in the view to which an item should be scrolled to. */ + enum ViewItemPosition { Beginning, Middle, End, Nearest }; - void setItemSize(const QSizeF& size); - QSizeF itemSize() const; + explicit KItemListView(QGraphicsWidget *parent = nullptr); + ~KItemListView() override; - // 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; - void setVisibleRoles(const QList& roles); + int maximumVisibleItems() const; + + void setVisibleRoles(const QList &roles); QList visibleRoles() const; /** @@ -112,14 +111,14 @@ public: * initialized by KItemListController::setView() and will * result in calling KItemListController::onControllerChanged(). */ - KItemListController* controller() const; + KItemListController *controller() const; /** * @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; + KItemModelBase *model() const; /** * Sets the creator that creates a widget showing the @@ -129,54 +128,110 @@ 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 setWidgetCreator(KItemListWidgetCreatorBase* widgetCreator); - KItemListWidgetCreatorBase* widgetCreator() const; + void setGroupHeaderCreator(KItemListGroupHeaderCreatorBase *groupHeaderCreator); + KItemListGroupHeaderCreatorBase *groupHeaderCreator() const; + +#ifndef QT_NO_ACCESSIBILITY + /** + * Uses \a parent to create an accessible object for \a parent. That accessible object will + * then be used as the accessible parent of the accessible object for this KItemListView. + * Make sure \a parent is the container which contains this specific KItemListView. + * This method must be called once before the accessible interface is queried for this class. + */ + void setAccessibleParentsObject(KItemListContainer *accessibleParentsObject); + /** The parent of the QAccessibilityInterface of this class. */ + KItemListContainerAccessible *accessibleParent(); +#endif - void setGroupHeaderCreator(KItemListGroupHeaderCreatorBase* groupHeaderCreator); - KItemListGroupHeaderCreatorBase* groupHeaderCreator() const; + /** + * @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; - void setStyleOption(const KItemListStyleOption& option); - const KItemListStyleOption& styleOption() const; + const KItemListStyleOption &styleOption() const; - /** @reimp */ - virtual void setGeometry(const QRectF& rect); + void setGeometry(const QRectF &rect) override; - int itemAt(const QPointF& pos) const; - bool isAboveSelectionToggle(int index, const QPointF& pos) const; - bool isAboveExpansionToggle(int index, const QPointF& pos) const; + /** + * @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 The line step which should be used for the scroll by mouse wheel. + */ + virtual qreal scrollSingleStep() 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. std::nullopt is returned if + * no item is below the position. + */ + std::optional 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; - 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(). + * @return Index of the last item that is at least partly visible. + * -1 is returned if the model contains no items. */ - virtual QSizeF itemSizeHint(int index) const; + int lastVisibleIndex() 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. + * 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 QHash visibleRolesSizes(const KItemRangeList& itemRanges) const; + void calculateItemSizeHints(QVector> &logicalHeightHints, qreal &logicalWidthHint) const; /** - * @return True if the view supports the expanding of items. Per default false - * is returned. If expanding of items is supported, the methods - * KItemModelBase::setExpanded(), KItemModelBase::isExpanded() and - * KItemModelBase::isExpandable() must be reimplemented. The view-implementation - * has to take care itself how to visually represent the expanded items provided - * by the model. + * 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 bool supportsItemExpanding() const; + void setSupportsItemExpanding(bool supportsExpanding); + bool supportsItemExpanding() const; + + void setHighlightEntireRow(bool highlightEntireRow); + bool highlightEntireRow() const; + + void setAlternateBackgrounds(bool alternate); + bool alternateBackgrounds() const; /** * @return The rectangle of the item relative to the top/left of @@ -187,7 +242,7 @@ public: /** * @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 by the united rectangle of + * 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 @@ -196,11 +251,18 @@ public: */ QRectF itemContextRect(int index) const; + /** + * @return Whether or not the name of the file has been elided. At present this will + * only ever be true when in icons view. + */ + bool isElided(int index) const; + /** * Scrolls to the item with the index \a index so that the item - * will be fully visible. + * will be fully visible. The item is positioned within the view + * as specified by \a viewItemPosition. */ - void scrollToItem(int index); + void scrollToItem(int index, ViewItemPosition viewItemPosition = ViewItemPosition::Nearest); /** * If several properties of KItemListView are changed synchronously, it is @@ -219,25 +281,39 @@ public: 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 setHeaderShown(bool show); - bool isHeaderShown() const; + 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()). + */ + 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: + /** + * Set the bottom offset for moving the view so that the small overlayed statusbar + * won't cover any items by accident. + */ + void setStatusBarOffset(int offset); + +Q_SIGNALS: void scrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous); void scrollOffsetChanged(qreal current, qreal previous); void maximumScrollOffsetChanged(qreal current, qreal previous); @@ -261,10 +337,62 @@ signals: * 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); + void sortRoleChanged(const QByteArray ¤t, 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 ¤t, const QList &previous); + + void roleEditingCanceled(int index, const QByteArray &role, const QVariant &value); + void roleEditingFinished(int index, const QByteArray &role, const QVariant &value); + + /** + * Emitted once scrolling has finished, or immediately if no scrolling was necessary + * to get item in view in scrollToItem. + */ + void scrollingStopped(); + + void columnHovered(int roleIndex); + void columnUnHovered(int roleIndex); protected: - virtual void initializeItemListWidget(KItemListWidget* item); + 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); /** * @return True if at least one of the changed roles \p changedRoles might result @@ -274,60 +402,69 @@ protected: * to return false in case if a role-change will not result in a changed * item-size hint. */ - virtual bool itemSizeHintUpdateRequired(const QSet& changedRoles) const; + virtual bool itemSizeHintUpdateRequired(const QSet &changedRoles) const; - virtual void onControllerChanged(KItemListController* current, KItemListController* previous); - virtual void onModelChanged(KItemModelBase* current, KItemModelBase* previous); + virtual void onControllerChanged(KItemListController *current, KItemListController *previous); + virtual void onModelChanged(KItemModelBase *current, KItemModelBase *previous); virtual void onScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous); - virtual void onItemSizeChanged(const QSizeF& current, const QSizeF& previous); + virtual void onItemSizeChanged(const QSizeF ¤t, const QSizeF &previous); 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 onVisibleRolesChanged(const QList ¤t, const QList &previous); + virtual void onStyleOptionChanged(const KItemListStyleOption ¤t, const KItemListStyleOption &previous); + virtual void onHighlightEntireRowChanged(bool highlightEntireRow); + 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; - QList visibleItemListWidgets() const; + virtual void updateFont(); + virtual void updatePalette(); -protected slots: - virtual void slotItemsInserted(const KItemRangeList& itemRanges); - virtual void slotItemsRemoved(const KItemRangeList& itemRanges); - virtual void slotItemsMoved(const KItemRange& itemRange, const QList& movedToIndexes); - virtual void slotItemsChanged(const KItemRangeList& itemRanges, - const QSet& roles); +protected Q_SLOTS: + virtual void slotItemsInserted(const KItemRangeList &itemRanges); + virtual void slotItemsRemoved(const KItemRangeList &itemRanges); + 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 slotSortRoleChanged(const QByteArray ¤t, const QByteArray &previous); virtual void slotCurrentChanged(int current, int previous); - virtual void slotSelectionChanged(const QSet& current, const QSet& previous); + virtual void slotSelectionChanged(const KItemSet ¤t, const KItemSet &previous); -private slots: - void slotAnimationFinished(QGraphicsWidget* widget, - KItemListViewAnimation::AnimationType type); - void slotLayoutTimerFinished(); +private Q_SLOTS: + void slotAnimationFinished(QGraphicsWidget *widget, KItemListViewAnimation::AnimationType type); void slotRubberBandPosChanged(); 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 slotVisibleRoleWidthChanged(const QByteArray& role, - qreal currentWidth, - qreal previousWidth); + void slotHeaderColumnWidthChanged(const QByteArray &role, qreal currentWidth, qreal previousWidth); + + void slotSidePaddingChanged(qreal width); + + /** + * Is invoked if a column has been moved by the user. Applies + * the moved role to the view. + */ + void slotHeaderColumnMoved(const QByteArray &role, int currentIndex, int previousIndex); /** * Triggers the autoscrolling if autoScroll() is enabled by checking the @@ -336,23 +473,26 @@ 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 - { - NoAnimation, - Animation - }; + enum LayoutAnimationHint { NoAnimation, Animation }; - enum SizeType - { - LayouterSize, - ItemSize - }; + enum SizeType { LayouterSize, ItemSize }; - void setController(KItemListController* controller); - void setModel(KItemModelBase* model); + void setController(KItemListController *controller); + void setModel(KItemModelBase *model); - KItemListRubberBand* rubberBand() const; + KItemListRubberBand *rubberBand() const; void doLayout(LayoutAnimationHint hint, int changedIndex = 0, int changedCount = 0); @@ -363,9 +503,7 @@ private: * 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); + QList recycleInvisibleItems(int firstVisibleIndex, int lastVisibleIndex, LayoutAnimationHint hint); /** * Helper method for doLayout: Starts a moving-animation for the widget to the given @@ -373,42 +511,56 @@ private: * 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 QRectF& itemBounds); + bool moveWidget(KItemListWidget *widget, const QPointF &newPos); void emitOffsetChanges(); - KItemListWidget* createWidget(int index); - void recycleWidget(KItemListWidget* widget); - void setWidgetIndex(KItemListWidget* widget, int index); + 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); + + /** + * 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 moveWidgetToIndex(KItemListWidget *widget, int index); /** * Helper method for prepareLayoutForIncreasedItemCount(). */ - void setLayouterSize(const QSizeF& size, SizeType sizeType); + void setLayouterSize(const QSizeF &size, SizeType sizeType); /** * Helper method for createWidget() and setWidgetIndex() to update the properties * of the itemlist widget. */ - void updateWidgetProperties(KItemListWidget* widget, int index); + 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); + void updateGroupHeaderForWidget(KItemListWidget *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); + void updateGroupHeaderLayout(KItemListWidget *widget); /** - * Recycles the group-header from the widget. + * Recycles the group-header for the widget. */ - void recycleGroupHeaderForWidget(KItemListWidget* widget); + void recycleGroupHeaderForWidget(KItemListWidget *widget); /** * Helper method for slotGroupedSortingChanged(), slotSortOrderChanged() @@ -418,53 +570,87 @@ private: void updateVisibleGroupHeaders(); /** - * @return The widths of each visible role that is shown in the KItemListHeader. + * @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. + */ + void updateAlternateBackgroundForWidget(KItemListWidget *widget); + + /** + * @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. + */ + bool useAlternateBackgrounds() const; + + /** + * @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. + */ + QHash preferredColumnWidths(const KItemRangeList &itemRanges) const; + + /** + * Applies the column-widths from m_headerWidget to the layout + * of the view. */ - QHash headerRolesWidths() const; + void applyColumnWidthsFromHeader(); /** - * 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. + * Applies the column-widths from m_headerWidget to \a widget. */ - void updateVisibleRolesSizes(const KItemRangeList& itemRanges); + void updateWidgetColumnWidths(KItemListWidget *widget); /** - * Convenience method for updateVisibleRoleSizes(KItemRangeList() << KItemRange(0, m_model->count()). + * Updates the preferred column-widths of m_groupHeaderWidget by + * invoking KItemListView::columnWidths(). */ - void updateVisibleRolesSizes(); + void updatePreferredColumnWidths(const KItemRangeList &itemRanges); /** - * 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). + * Convenience method for + * updatePreferredColumnWidths(KItemRangeList() << KItemRange(0, m_model->count()). */ - void updateStretchedVisibleRolesSizes(); + void updatePreferredColumnWidths(); /** - * @return Sum of the widths of all visible roles. + * Resizes the column-widths of m_headerWidget based on the preferred widths + * and the available view-size. */ - qreal visibleRolesSizesWidthSum() const; + void applyAutomaticColumnWidths(); /** - * @return Sum of the heights of all visible roles. + * @return Sum of the widths of all columns. */ - qreal visibleRolesSizesHeightSum() const; + qreal columnWidthsSum() const; /** * @return Boundaries of the header. An empty rectangle is returned * if no header is shown. */ 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; - + 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. @@ -478,7 +664,17 @@ private: * 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; + 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 @@ -486,6 +682,29 @@ private: */ 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. @@ -498,49 +717,98 @@ 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_highlightEntireRow; + bool m_alternateBackgrounds; + 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; + 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; +#ifndef QT_NO_ACCESSIBILITY + /** The object that will be the parent of this classes QAccessibleInterface. */ + KItemListContainerAccessible *m_accessibleParent = nullptr; +#endif KItemListStyleOption m_styleOption; - QHash m_visibleItems; - QHash m_visibleGroups; + 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; - KItemListViewAnimation* m_animation; + KItemListViewLayouter *m_layouter; + KItemListViewAnimation *m_animation; - QTimer* m_layoutTimer; // Triggers an asynchronous doLayout() call. qreal m_oldScrollOffset; qreal m_oldMaximumScrollOffset; qreal m_oldItemOffset; qreal m_oldMaximumItemOffset; bool m_skipAutoScrollForRubberBand; - KItemListRubberBand* m_rubberBand; + KItemListRubberBand *m_rubberBand; + KItemListRubberBand *m_tapAndHoldIndicator; QPointF m_mousePos; int m_autoScrollIncrement; - QTimer* m_autoScrollTimer; + QTimer *m_autoScrollTimer; - KItemListHeader* m_header; - bool m_useHeaderWidths; + KItemListHeader *m_header; + KItemListHeaderWidget *m_headerWidget; + + QPropertyAnimation *m_indicatorAnimation; + + int m_statusBarOffset; + + // 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; + + QList m_rubberBandAnimations; + + KItemListSizeHintResolver *m_sizeHintResolver; friend class KItemListContainer; // Accesses scrollBarRequired() + friend class KItemListHeader; // Accesses m_headerWidget friend class KItemListController; friend class KItemListControllerTest; + friend class KItemListViewAccessible; + friend class KItemListDelegateAccessible; + + friend class DolphinMainWindowTest; }; /** @@ -549,94 +817,135 @@ private: * KItemListWidgetCreatorBase and KItemListGroupHeaderCreatorBase. * @internal */ -class LIBDOLPHINPRIVATE_EXPORT KItemListCreatorBase +class DOLPHIN_EXPORT KItemListCreatorBase { public: virtual ~KItemListCreatorBase(); protected: - void addCreatedWidget(QGraphicsWidget* widget); - void pushRecycleableWidget(QGraphicsWidget* widget); - QGraphicsWidget* popRecycleableWidget(); + void addCreatedWidget(QGraphicsWidget *widget); + void pushRecycleableWidget(QGraphicsWidget *widget); + QGraphicsWidget *popRecycleableWidget(); private: - QSet m_createdWidgets; - QList m_recycleableWidgets; + QSet m_createdWidgets; + QList m_recycleableWidgets; }; /** * @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(); - virtual KItemListWidget* create(KItemListView* view) = 0; - virtual void recycle(KItemListWidget* widget); + ~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; }; -template +/** + * @brief Template class for creating KItemListWidgets. + */ +template 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 +template +KItemListWidgetCreator::KItemListWidgetCreator() + : m_informant(T::createInformant()) +{ +} + +template KItemListWidgetCreator::~KItemListWidgetCreator() { + delete m_informant; } -template -KItemListWidget* KItemListWidgetCreator::create(KItemListView* view) +template +KItemListWidget *KItemListWidgetCreator::create(KItemListView *view) { - KItemListWidget* widget = static_cast(popRecycleableWidget()); + KItemListWidget *widget = static_cast(popRecycleableWidget()); if (!widget) { - widget = new T(view); + widget = new T(m_informant, view); addCreatedWidget(widget); } + widget->setParentItem(view); 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. * * It is recommended that applications simply use the KItemListGroupHeaderCreator-template class. - * For a custom implementation the methods create() and recyle() must be reimplemented. + * For a custom implementation the methods create() and recycle() must be reimplemented. * 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(); - virtual KItemListGroupHeader* create(KItemListView* view) = 0; - virtual void recycle(KItemListGroupHeader* header); + ~KItemListGroupHeaderCreatorBase() override; + virtual KItemListGroupHeader *create(KItemListView *view) = 0; + virtual void recycle(KItemListGroupHeader *header); }; -template +template class KItemListGroupHeaderCreator : public KItemListGroupHeaderCreatorBase { public: - virtual ~KItemListGroupHeaderCreator(); - virtual KItemListGroupHeader* create(KItemListView* view); + ~KItemListGroupHeaderCreator() override; + KItemListGroupHeader *create(KItemListView *view) override; }; -template +template KItemListGroupHeaderCreator::~KItemListGroupHeaderCreator() { } -template -KItemListGroupHeader* KItemListGroupHeaderCreator::create(KItemListView* view) +template +KItemListGroupHeader *KItemListGroupHeaderCreator::create(KItemListView *view) { - KItemListGroupHeader* widget = static_cast(popRecycleableWidget()); + KItemListGroupHeader *widget = static_cast(popRecycleableWidget()); if (!widget) { widget = new T(view); addCreatedWidget(widget);