From 362817d1834f2ada3ea4552a25fa39bbbb540f8c Mon Sep 17 00:00:00 2001 From: Peter Penz Date: Sat, 26 Nov 2011 01:05:58 +0100 Subject: Folders Panel fixes The following functionality from Dolphin 1.x has been ported to the new view-engine: - Allow expanding/collapsing of items - Automatically select the current item - Context menu for items Related improvements to the view-engine: - Make the expanding/collapsing interface already accessible in the base classes KItemModelBase and KItemListView. If no expanding/collapsing is supported at all by derived models (which is usually the default case) simply not reimplementing those 3 methods is sufficient and it does not introduce an additional complexity like in QAbstractItemModel/QModelIndex. - Automatically handle the expanding/collapsing in KItemListController. This also includes the key-handling, which is quite special for expandable items. - Don't let KItemListView automatically scroll to the current item if the current item got changed. The automatic scrolling should only be done if the current item has been changed by the user. Hence this functionality has been moved to the KItemListController which currently only triggers the automatic scrolling if the current item has been changed by the keyboard (we might extend the usecases later if required). --- src/kitemviews/kfileitemlistview.cpp | 5 +++ src/kitemviews/kfileitemlistview.h | 3 ++ src/kitemviews/kfileitemmodel.h | 7 ++-- src/kitemviews/kitemlistcontroller.cpp | 60 ++++++++++++++++++++++----------- src/kitemviews/kitemlistview.cpp | 61 +++++++++++++++++++--------------- src/kitemviews/kitemlistview.h | 16 +++++++++ src/kitemviews/kitemmodelbase.cpp | 19 +++++++++++ src/kitemviews/kitemmodelbase.h | 29 ++++++++++++++++ 8 files changed, 151 insertions(+), 49 deletions(-) (limited to 'src/kitemviews') diff --git a/src/kitemviews/kfileitemlistview.cpp b/src/kitemviews/kfileitemlistview.cpp index b0ffd3c20..d7dd5cf67 100644 --- a/src/kitemviews/kfileitemlistview.cpp +++ b/src/kitemviews/kfileitemlistview.cpp @@ -222,6 +222,11 @@ QHash KFileItemListView::visibleRolesSizes(const KItemRangeL return sizes; } +bool KFileItemListView::supportsItemExpanding() const +{ + return m_itemLayout == DetailsLayout; +} + QPixmap KFileItemListView::createDragPixmap(const QSet& indexes) const { if (!model()) { diff --git a/src/kitemviews/kfileitemlistview.h b/src/kitemviews/kfileitemlistview.h index d90d8ecf9..a41d091b7 100644 --- a/src/kitemviews/kfileitemlistview.h +++ b/src/kitemviews/kfileitemlistview.h @@ -63,6 +63,9 @@ public: /** @reimp */ virtual QHash visibleRolesSizes(const KItemRangeList& itemRanges) const; + /** @reimp */ + virtual bool supportsItemExpanding() const; + /** @reimp */ virtual QPixmap createDragPixmap(const QSet& indexes) const; diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h index 17524b82a..8cbcb1216 100644 --- a/src/kitemviews/kfileitemmodel.h +++ b/src/kitemviews/kfileitemmodel.h @@ -116,9 +116,10 @@ public: void setRoles(const QSet& roles); QSet roles() const; - bool setExpanded(int index, bool expanded); - bool isExpanded(int index) const; - bool isExpandable(int index) const; + virtual bool setExpanded(int index, bool expanded); + virtual bool isExpanded(int index) const; + virtual bool isExpandable(int index) const; + QSet expandedUrls() const; /** diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index b24e6df14..60bfef518 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -135,17 +135,31 @@ bool KItemListController::hideEvent(QHideEvent* event) bool KItemListController::keyPressEvent(QKeyEvent* event) { + int index = m_selectionManager->currentItem(); + int key = event->key(); + + // Handle the expanding/collapsing of items + if (m_view->supportsItemExpanding() && m_model->isExpandable(index)) { + if (key == Qt::Key_Right) { + if (m_model->setExpanded(index, true)) { + return true; + } + } else if (key == Qt::Key_Left) { + if (m_model->setExpanded(index, false)) { + return true; + } + } + } + const bool shiftPressed = event->modifiers() & Qt::ShiftModifier; const bool controlPressed = event->modifiers() & Qt::ControlModifier; const bool shiftOrControlPressed = shiftPressed || controlPressed; - int index = m_selectionManager->currentItem(); const int itemCount = m_model->count(); const int itemsPerRow = m_view->itemsPerOffset(); // For horizontal scroll orientation, transform // the arrow keys to simplify the event handling. - int key = event->key(); if (m_view->scrollOrientation() == Qt::Horizontal) { switch (key) { case Qt::Key_Up: key = Qt::Key_Left; break; @@ -156,6 +170,7 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) } } + switch (key) { case Qt::Key_Home: index = 0; @@ -234,6 +249,8 @@ bool KItemListController::keyPressEvent(QKeyEvent* event) if (!shiftPressed) { m_selectionManager->beginAnchoredSelection(index); } + + m_view->scrollToItem(index); } return true; } @@ -348,25 +365,27 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const return true; } - KItemListRubberBand* rubberBand = m_view->rubberBand(); - QPointF startPos = m_pressedMousePos; - if (m_view->scrollOrientation() == Qt::Vertical) { - startPos.ry() += m_view->scrollOffset(); - if (m_view->itemSize().width() < 0) { - // Use a special rubberband for views that have only one column and - // expand the rubberband to use the whole width of the view. - startPos.setX(0); + if (m_selectionBehavior == MultiSelection) { + QPointF startPos = m_pressedMousePos; + if (m_view->scrollOrientation() == Qt::Vertical) { + startPos.ry() += m_view->scrollOffset(); + if (m_view->itemSize().width() < 0) { + // Use a special rubberband for views that have only one column and + // expand the rubberband to use the whole width of the view. + startPos.setX(0); + } + } else { + startPos.rx() += m_view->scrollOffset(); } - } else { - startPos.rx() += m_view->scrollOffset(); - } - m_oldSelection = m_selectionManager->selectedItems(); - rubberBand->setStartPosition(startPos); - rubberBand->setEndPosition(startPos); - rubberBand->setActive(true); - connect(rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandChanged())); - m_view->setAutoScroll(true); + m_oldSelection = m_selectionManager->selectedItems(); + KItemListRubberBand* rubberBand = m_view->rubberBand(); + rubberBand->setStartPosition(startPos); + rubberBand->setEndPosition(startPos); + rubberBand->setActive(true); + connect(rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandChanged())); + m_view->setAutoScroll(true); + } return false; } @@ -461,6 +480,9 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, con if (event->button() & Qt::LeftButton) { bool emitItemActivated = true; if (m_view->isAboveExpansionToggle(index, pos)) { + const bool expanded = m_model->isExpanded(index); + m_model->setExpanded(index, !expanded); + emit itemExpansionToggleClicked(index); emitItemActivated = false; } else if (shiftOrControlPressed) { diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index 389069ce3..c4c1e3167 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -427,11 +427,45 @@ QHash KItemListView::visibleRolesSizes(const KItemRangeList& return QHash(); } +bool KItemListView::supportsItemExpanding() const +{ + return false; +} + QRectF KItemListView::itemRect(int index) const { return m_layouter->itemRect(index); } +void KItemListView::scrollToItem(int index) +{ + const QRectF viewGeometry = geometry(); + const QRectF currentRect = itemRect(index); + + if (!viewGeometry.contains(currentRect)) { + qreal newOffset = scrollOffset(); + if (currentRect.top() < viewGeometry.top()) { + Q_ASSERT(scrollOrientation() == Qt::Vertical); + newOffset += currentRect.top() - viewGeometry.top(); + } else if ((currentRect.bottom() > viewGeometry.bottom())) { + Q_ASSERT(scrollOrientation() == Qt::Vertical); + newOffset += currentRect.bottom() - viewGeometry.bottom(); + } else if (currentRect.left() < viewGeometry.left()) { + if (scrollOrientation() == Qt::Horizontal) { + newOffset += currentRect.left() - viewGeometry.left(); + } + } else if ((currentRect.right() > viewGeometry.right())) { + if (scrollOrientation() == Qt::Horizontal) { + newOffset += currentRect.right() - viewGeometry.right(); + } + } + + if (newOffset != scrollOffset()) { + emit scrollTo(newOffset); + } + } +} + int KItemListView::itemsPerOffset() const { return m_layouter->itemsPerOffset(); @@ -950,33 +984,6 @@ void KItemListView::slotCurrentChanged(int current, int previous) Q_ASSERT(!currentWidget->isCurrent()); currentWidget->setCurrent(true); } - - const QRectF viewGeometry = geometry(); - const QRectF currentRect = itemRect(current); - - if (!viewGeometry.contains(currentRect)) { - // Make sure that the new current item is fully visible in the view. - qreal newOffset = scrollOffset(); - if (currentRect.top() < viewGeometry.top()) { - Q_ASSERT(scrollOrientation() == Qt::Vertical); - newOffset += currentRect.top() - viewGeometry.top(); - } else if ((currentRect.bottom() > viewGeometry.bottom())) { - Q_ASSERT(scrollOrientation() == Qt::Vertical); - newOffset += currentRect.bottom() - viewGeometry.bottom(); - } else if (currentRect.left() < viewGeometry.left()) { - if (scrollOrientation() == Qt::Horizontal) { - newOffset += currentRect.left() - viewGeometry.left(); - } - } else if ((currentRect.right() > viewGeometry.right())) { - if (scrollOrientation() == Qt::Horizontal) { - newOffset += currentRect.right() - viewGeometry.right(); - } - } - - if (newOffset != scrollOffset()) { - emit scrollTo(newOffset); - } - } } void KItemListView::slotSelectionChanged(const QSet& current, const QSet& previous) diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index 481dd90f6..1da0cd7d2 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -168,12 +168,28 @@ public: */ virtual QHash visibleRolesSizes(const KItemRangeList& itemRanges) 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. + */ + virtual bool supportsItemExpanding() const; + /** * @return The rectangle of the item relative to the top/left of * the currently visible area (see KItemListView::offset()). */ QRectF itemRect(int index) const; + /** + * Scrolls to the item with the index \a index so that the item + * will be fully visible. + */ + void scrollToItem(int index); + /** * @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 diff --git a/src/kitemviews/kitemmodelbase.cpp b/src/kitemviews/kitemmodelbase.cpp index 3e6114027..e2b86d8a0 100644 --- a/src/kitemviews/kitemmodelbase.cpp +++ b/src/kitemviews/kitemmodelbase.cpp @@ -109,6 +109,25 @@ QList > KItemModelBase::groups() const return QList >(); } +bool KItemModelBase::setExpanded(int index, bool expanded) +{ + Q_UNUSED(index); + Q_UNUSED(expanded); + return false; +} + +bool KItemModelBase::isExpanded(int index) const +{ + Q_UNUSED(index); + return false; +} + +bool KItemModelBase::isExpandable(int index) const +{ + Q_UNUSED(index); + return false; +} + QMimeData* KItemModelBase::createMimeData(const QSet& indexes) const { Q_UNUSED(indexes); diff --git a/src/kitemviews/kitemmodelbase.h b/src/kitemviews/kitemmodelbase.h index edca15bd1..1dffaf8cf 100644 --- a/src/kitemviews/kitemmodelbase.h +++ b/src/kitemviews/kitemmodelbase.h @@ -53,6 +53,9 @@ typedef QList KItemRangeList; * One item consists of a variable number of role/value-pairs. * * A model can optionally provide sorting- and grouping-capabilities. + * + * Also optionally it is possible to provide a tree of items by implementing the methods + * setExpanded(), isExpanded() and isExpandable(). */ class LIBDOLPHINPRIVATE_EXPORT KItemModelBase : public QObject { @@ -116,6 +119,32 @@ public: */ virtual QList > groups() const; + /** + * Expands the item with the index \a index if \a expanded is true. + * If \a expanded is false the item will be collapsed. + * + * Per default no expanding of items is implemented. When implementing + * this method it is mandatory to overwrite KItemModelBase::isExpandable() + * and KItemListView::supportsExpandableItems() to return true. + * + * @return True if the operation has been successful. + */ + virtual bool setExpanded(int index, bool expanded); + + /** + * @return True if the item with the index \a index is expanded. + * Per default no expanding of items is implemented. When implementing + * this method it is mandatory to overwrite KItemModelBase::isExpandable() + * and KItemListView::supportsExpandableItems() to return true. + */ + virtual bool isExpanded(int index) const; + + /** + * @return True if expanding and collapsing of the item with the index \a index + * is supported. Per default false is returned. + */ + virtual bool isExpandable(int index) const; + /** * @return MIME-data for the items given by \a indexes. The default implementation * returns 0. The ownership of the returned instance is in the hand of the -- cgit v1.3