From: Peter Penz Date: Sat, 20 Aug 2011 20:52:45 +0000 (+0200) Subject: Select items when using the rubberband X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/commitdiff_plain/4aedb0767490989ea00251a39b8d76f1b51a4303?ds=inline Select items when using the rubberband --- diff --git a/src/kitemviews/kfileitemlistwidget.cpp b/src/kitemviews/kfileitemlistwidget.cpp index a8fe36c08..4fc3307ef 100644 --- a/src/kitemviews/kfileitemlistwidget.cpp +++ b/src/kitemviews/kfileitemlistwidget.cpp @@ -86,9 +86,7 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte { KItemListWidget::paint(painter, option, widget); - if (m_dirtyContent || m_dirtyLayout) { - const_cast(this)->updateCache(); - } + const_cast(this)->updateCache(); // Draw expansion toggle '>' or 'V' if (m_isDir && !m_expansionArea.isEmpty()) { @@ -135,6 +133,8 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte QRectF KFileItemListWidget::iconBoundingRect() const { + const_cast(this)->updateCache(); + QRectF bounds = m_hoverPixmapRect; const qreal margin = styleOption().margin; bounds.adjust(-margin, -margin, margin, margin); @@ -143,11 +143,13 @@ QRectF KFileItemListWidget::iconBoundingRect() const QRectF KFileItemListWidget::textBoundingRect() const { + const_cast(this)->updateCache(); return m_textBoundingRect; } QRectF KFileItemListWidget::expansionToggleRect() const { + const_cast(this)->updateCache(); return m_isDir ? m_expansionArea : QRectF(); } @@ -242,7 +244,7 @@ void KFileItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event) void KFileItemListWidget::updateCache() { - if (index() < 0) { + if ((!m_dirtyContent && !m_dirtyLayout) || index() < 0) { return; } diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index 7331131a9..31a1cfc2f 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -291,6 +291,7 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const rubberBand->setStartPosition(startPos); rubberBand->setEndPosition(startPos); rubberBand->setActive(true); + connect(rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandChanged())); } return false; @@ -322,7 +323,13 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, con return false; } - m_view->rubberBand()->setActive(false); + KItemListRubberBand* rubberBand = m_view->rubberBand(); + if (rubberBand->isActive()) { + disconnect(rubberBand, SIGNAL(endPositionChanged(QPointF,QPointF)), this, SLOT(slotRubberBandChanged())); + rubberBand->setActive(false); + m_pressedIndex = -1; + return false; + } const QPointF pos = transform.map(event->pos()); const int index = m_view->itemAt(pos); @@ -541,4 +548,68 @@ void KItemListController::slotViewOffsetChanged(qreal current, qreal previous) } } +void KItemListController::slotRubberBandChanged() +{ + if (!m_view || !m_model || m_model->count() <= 0) { + return; + } + + const KItemListRubberBand* rubberBand = m_view->rubberBand(); + const QPointF startPos = rubberBand->startPosition(); + const QPointF endPos = rubberBand->endPosition(); + QRectF rubberBandRect = QRectF(startPos, endPos).normalized(); + + const bool scrollVertical = (m_view->scrollOrientation() == Qt::Vertical); + if (scrollVertical) { + rubberBandRect.translate(0, -m_view->offset()); + } else { + rubberBandRect.translate(-m_view->offset(), 0); + } + + QSet selectedItems; + + // Select all visible items that intersect with the rubberband + foreach (const KItemListWidget* widget, m_view->visibleItemListWidgets()) { + const int index = widget->index(); + + const QRectF widgetRect = m_view->itemBoundingRect(index); + if (widgetRect.intersects(rubberBandRect)) { + const QRectF iconRect = widget->iconBoundingRect().translated(widgetRect.topLeft()); + const QRectF textRect = widget->textBoundingRect().translated(widgetRect.topLeft()); + if (iconRect.intersects(rubberBandRect) || textRect.intersects(rubberBandRect)) { + selectedItems.insert(index); + } + } + } + + // Select all invisible items that intersect with the rubberband. Instead of + // iterating all items only the area which might be touched by the rubberband + // will be checked. + const bool increaseIndex = scrollVertical ? + startPos.y() > endPos.y(): startPos.x() > endPos.x(); + + int index = increaseIndex ? m_view->lastVisibleIndex() + 1 : m_view->firstVisibleIndex() - 1; + bool selectionFinished = false; + do { + const QRectF widgetRect = m_view->itemBoundingRect(index); + if (widgetRect.intersects(rubberBandRect)) { + selectedItems.insert(index); + } + + if (increaseIndex) { + ++index; + selectionFinished = (index >= m_model->count()) || + ( scrollVertical && widgetRect.top() > rubberBandRect.bottom()) || + (!scrollVertical && widgetRect.left() > rubberBandRect.right()); + } else { + --index; + selectionFinished = (index < 0) || + ( scrollVertical && widgetRect.bottom() < rubberBandRect.top()) || + (!scrollVertical && widgetRect.right() < rubberBandRect.left()); + } + } while (!selectionFinished); + + m_selectionManager->setSelectedItems(selectedItems); +} + #include "kitemlistcontroller.moc" diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h index c4406a972..49442c643 100644 --- a/src/kitemviews/kitemlistcontroller.h +++ b/src/kitemviews/kitemlistcontroller.h @@ -28,7 +28,6 @@ #include class KItemModelBase; -class KItemListRubberBandManager; class KItemListSelectionManager; class KItemListView; class QGraphicsSceneHoverEvent; @@ -123,6 +122,12 @@ signals: private slots: void slotViewOffsetChanged(qreal current, qreal previous); + /** + * Is invoked when the rubberband boundaries have been changed and will select + * all items that are touched by the rubberband. + */ + void slotRubberBandChanged(); + private: SelectionBehavior m_selectionBehavior; KItemModelBase* m_model; diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index 1ff56babd..3f877d236 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -136,7 +136,19 @@ public: virtual QSizeF itemSizeHint(int index) const; virtual QHash visibleRoleSizes() const; + /** + * @return The bounding rectangle of the item relative to the top/left of + * the currently visible area (see KItemListView::offset()). + */ QRectF itemBoundingRect(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. + */ int itemsPerOffset() const; void beginTransaction();