diff options
| author | Peter Penz <[email protected]> | 2011-08-08 23:41:18 +0200 |
|---|---|---|
| committer | Peter Penz <[email protected]> | 2011-08-09 16:22:36 +0200 |
| commit | 3957884bf2e44619a4ed35ba0ffead519988885b (patch) | |
| tree | d8a5bf1a015cc6001adb4afc5f0f1da721908a22 /src/kitemviews | |
| parent | 4692eb7c96f57328479862c0d17d7945b4e87188 (diff) | |
Improvements for selections, smooth scrolling, tooltips and info-panel
Diffstat (limited to 'src/kitemviews')
| -rw-r--r-- | src/kitemviews/kfileitemlistwidget.cpp | 47 | ||||
| -rw-r--r-- | src/kitemviews/kfileitemlistwidget.h | 2 | ||||
| -rw-r--r-- | src/kitemviews/kfileitemmodel.cpp | 9 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistcontainer.cpp | 151 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistcontainer.h | 6 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistcontroller.cpp | 87 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistcontroller.h | 13 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistselectionmanager.cpp | 186 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistselectionmanager.h | 28 | ||||
| -rw-r--r-- | src/kitemviews/kitemliststyleoption.cpp | 17 | ||||
| -rw-r--r-- | src/kitemviews/kitemliststyleoption.h | 11 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistview.cpp | 178 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistview.h | 16 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistwidget.cpp | 117 | ||||
| -rw-r--r-- | src/kitemviews/kitemlistwidget.h | 15 | ||||
| -rw-r--r-- | src/kitemviews/kitemmodelbase.h | 39 |
16 files changed, 726 insertions, 196 deletions
diff --git a/src/kitemviews/kfileitemlistwidget.cpp b/src/kitemviews/kfileitemlistwidget.cpp index 91c0cb597..a5251439f 100644 --- a/src/kitemviews/kfileitemlistwidget.cpp +++ b/src/kitemviews/kfileitemlistwidget.cpp @@ -33,6 +33,7 @@ #include <QFontMetricsF> #include <QGraphicsSceneResizeEvent> #include <QPainter> +#include <QStyleOption> #include <QTextLayout> #include <QTextLine> @@ -91,6 +92,7 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte const_cast<KFileItemListWidget*>(this)->updateCache(); } + // Draw expansion toggle '>' or 'V' if (m_isDir && !m_expansionArea.isEmpty()) { QStyleOption arrowOption; arrowOption.rect = m_expansionArea.toRect(); @@ -99,10 +101,8 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte style()->drawPrimitive(arrow, &arrowOption, painter); } - const bool isHovered = (hoverOpacity() > 0.0); - const KItemListStyleOption& itemListStyleOption = styleOption(); - if (isHovered) { + if (isHovered()) { // Blend the unhovered and hovered pixmap if the hovering // animation is ongoing if (hoverOpacity() < 1.0) { @@ -127,11 +127,11 @@ void KFileItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsIte drawPixmap(painter, m_pixmap); } - QFont font(itemListStyleOption.font); - if (itemListStyleOption.state & QStyle::State_HasFocus) { - font.setUnderline(true); + if (isCurrent()) { + drawFocusIndicator(painter); } - painter->setFont(font); + + painter->setFont(itemListStyleOption.font); painter->setPen(itemListStyleOption.palette.text().color()); painter->drawStaticText(m_textPos[Name], m_text[Name]); @@ -244,6 +244,12 @@ void KFileItemListWidget::styleOptionChanged(const KItemListStyleOption& current m_dirtyLayout = true; } +void KFileItemListWidget::hoveredChanged(bool hovered) +{ + Q_UNUSED(hovered); + m_dirtyLayout = true; +} + void KFileItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event) { KItemListWidget::resizeEvent(event); @@ -374,7 +380,7 @@ void KFileItemListWidget::updatePixmapCache() m_hoverPixmapRect.moveTopLeft(QPointF(x, y)); // Prepare the pixmap that is used when the item gets hovered - if (option.state & QStyle::State_MouseOver) { + if (isHovered()) { m_hoverPixmap = m_pixmap; KIconEffect* effect = KIconLoader::global()->iconEffect(); // In the KIconLoader terminology, active = hover. @@ -681,6 +687,31 @@ void KFileItemListWidget::drawPixmap(QPainter* painter, const QPixmap& pixmap) } } +void KFileItemListWidget::drawFocusIndicator(QPainter* painter) +{ + // Ideally style()->drawPrimitive(QStyle::PE_FrameFocusRect...) + // should be used, but Oxygen only draws indicators within classes + // derived from QAbstractItemView or Q3ListView. As a workaround + // the indicator is drawn manually. Code copied from oxygenstyle.cpp + // Copyright ( C ) 2009-2010 Hugo Pereira Da Costa <[email protected]> + // TODO: Clarify with Oxygen maintainers how to proceed with this. + + const KItemListStyleOption& option = styleOption(); + const QPalette palette = option.palette; + const QRect rect = m_textsBoundingRect.toRect().adjusted(0, 0, 0, -1); + + QLinearGradient gradient(rect.bottomLeft(), rect.bottomRight()); + gradient.setColorAt(0.0, Qt::transparent); + gradient.setColorAt(1.0, Qt::transparent); + gradient.setColorAt(0.2, palette.color(QPalette::Text)); + gradient.setColorAt(0.8, palette.color(QPalette::Text)); + + painter->setRenderHint(QPainter::Antialiasing, false); + painter->setPen(QPen(gradient, 1)); + painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + painter->setRenderHint(QPainter::Antialiasing, true); +} + QPixmap KFileItemListWidget::pixmapForIcon(const QString& name, int size) { const KIcon icon(name); diff --git a/src/kitemviews/kfileitemlistwidget.h b/src/kitemviews/kfileitemlistwidget.h index 3ce953106..1d1b6fd86 100644 --- a/src/kitemviews/kfileitemlistwidget.h +++ b/src/kitemviews/kfileitemlistwidget.h @@ -57,6 +57,7 @@ protected: virtual void visibleRolesChanged(const QHash<QByteArray, int>& current, const QHash<QByteArray, int>& previous); virtual void visibleRolesSizesChanged(const QHash<QByteArray, QSizeF>& current, const QHash<QByteArray, QSizeF>& previous); virtual void styleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous); + virtual void hoveredChanged(bool hovered); virtual void resizeEvent(QGraphicsSceneResizeEvent* event); private: @@ -85,6 +86,7 @@ private: QString roleText(TextId textId, const QVariant& roleValue) const; void drawPixmap(QPainter* painter, const QPixmap& pixmap); + void drawFocusIndicator(QPainter* painter); static QPixmap pixmapForIcon(const QString& name, int size); static TextId roleTextId(const QByteArray& role); diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index b191abab6..ddc56209b 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -403,8 +403,9 @@ void KFileItemModel::insertItems(const KFileItemList& items) KItemRangeList itemRanges; int targetIndex = 0; int sourceIndex = 0; - int insertedAtIndex = -1; - int insertedCount = 0; + int insertedAtIndex = -1; // Index for the current item-range + int insertedCount = 0; // Count for the current item-range + int previouslyInsertedCount = 0; // Sum of previously inserted items for all ranges while (sourceIndex < sortedItems.count()) { // Find target index from m_items to insert the current item // in a sorted order @@ -418,7 +419,8 @@ void KFileItemModel::insertItems(const KFileItemList& items) if (targetIndex - previousTargetIndex > 0 && insertedAtIndex >= 0) { itemRanges << KItemRange(insertedAtIndex, insertedCount); - insertedAtIndex = targetIndex; + previouslyInsertedCount += insertedCount; + insertedAtIndex = targetIndex - previouslyInsertedCount; insertedCount = 0; } @@ -431,6 +433,7 @@ void KFileItemModel::insertItems(const KFileItemList& items) if (insertedAtIndex < 0) { insertedAtIndex = targetIndex; + Q_ASSERT(previouslyInsertedCount == 0); } ++targetIndex; ++sourceIndex; diff --git a/src/kitemviews/kitemlistcontainer.cpp b/src/kitemviews/kitemlistcontainer.cpp index 09fb505d6..e247df0c7 100644 --- a/src/kitemviews/kitemlistcontainer.cpp +++ b/src/kitemviews/kitemlistcontainer.cpp @@ -28,6 +28,7 @@ #include <QGraphicsScene> #include <QGraphicsView> +#include <QPropertyAnimation> #include <QScrollBar> #include <QStyle> @@ -56,7 +57,9 @@ public: KItemListContainer::KItemListContainer(KItemListController* controller, QWidget* parent) : QAbstractScrollArea(parent), - m_controller(controller) + m_controller(controller), + m_sliderMovedByUser(false), + m_viewOffsetAnimation(0) { Q_ASSERT(controller); controller->setParent(this); @@ -99,8 +102,86 @@ void KItemListContainer::scrollContentsBy(int dx, int dy) } const qreal currentOffset = view->offset(); - const qreal offsetDiff = (view->scrollOrientation() == Qt::Vertical) ? dy : dx; - view->setOffset(currentOffset - offsetDiff); + qreal offsetDiff = (view->scrollOrientation() == Qt::Vertical) ? dy : dx; + + const bool animRunning = (m_viewOffsetAnimation->state() == QAbstractAnimation::Running); + if (animRunning) { + // Stopping a running animation means skipping the range from the current offset + // until the target offset. To prevent skipping of the range the difference + // is added to the new target offset. + m_viewOffsetAnimation->stop(); + const qreal targetOffset = m_viewOffsetAnimation->endValue().toReal(); + offsetDiff += (currentOffset - targetOffset); + } + + const qreal newOffset = currentOffset - offsetDiff; + + if (m_sliderMovedByUser || animRunning) { + m_viewOffsetAnimation->stop(); + m_viewOffsetAnimation->setStartValue(currentOffset); + m_viewOffsetAnimation->setEndValue(newOffset); + m_viewOffsetAnimation->setEasingCurve(animRunning ? QEasingCurve::OutQuad : QEasingCurve::InOutQuad); + m_viewOffsetAnimation->start(); + } else { + view->setOffset(newOffset); + } +} + +bool KItemListContainer::eventFilter(QObject* obj, QEvent* event) +{ + Q_ASSERT(obj == horizontalScrollBar() || obj == verticalScrollBar()); + + // Check whether the scrollbar has been adjusted by a mouse-event + // triggered by the user and remember this in m_sliderMovedByUser. + // The smooth scrolling will only get active if m_sliderMovedByUser + // is true (see scrollContentsBy()). + const bool scrollVertical = (m_controller->view()->scrollOrientation() == Qt::Vertical); + const bool checkEvent = ( scrollVertical && obj == verticalScrollBar()) || + (!scrollVertical && obj == horizontalScrollBar()); + if (checkEvent) { + switch (event->type()) { + case QEvent::MouseButtonPress: + m_sliderMovedByUser = true; + break; + + case QEvent::MouseButtonRelease: + m_sliderMovedByUser = false; + break; + + case QEvent::Wheel: + wheelEvent(static_cast<QWheelEvent*>(event)); + break; + + default: + break; + } + } + + return QAbstractScrollArea::eventFilter(obj, event); +} + +void KItemListContainer::wheelEvent(QWheelEvent* event) +{ + KItemListView* view = m_controller->view(); + if (!view || event->orientation() != view->scrollOrientation()) { + return; + } + + const int numDegrees = event->delta() / 8; + const int numSteps = numDegrees / 15; + + const bool previous = m_sliderMovedByUser; + m_sliderMovedByUser = true; + if (view->scrollOrientation() == Qt::Vertical) { + const int value = verticalScrollBar()->value(); + verticalScrollBar()->setValue(value - numSteps * view->size().height()); + } else { + const int value = horizontalScrollBar()->value(); + horizontalScrollBar()->setValue(value - numSteps * view->size().width()); + } + m_sliderMovedByUser = previous; + + event->accept(); } void KItemListContainer::slotModelChanged(KItemModelBase* current, KItemModelBase* previous) @@ -116,37 +197,57 @@ void KItemListContainer::slotViewChanged(KItemListView* current, KItemListView* scene->removeItem(previous); disconnect(previous, SIGNAL(offsetChanged(int,int)), this, SLOT(updateScrollBars())); disconnect(previous, SIGNAL(maximumOffsetChanged(int,int)), this, SLOT(updateScrollBars())); + m_viewOffsetAnimation->setTargetObject(0); } if (current) { scene->addItem(current); - connect(previous, SIGNAL(offsetChanged(int,int)), this, SLOT(updateScrollBars())); + connect(current, SIGNAL(offsetChanged(int,int)), this, SLOT(updateScrollBars())); connect(current, SIGNAL(maximumOffsetChanged(int,int)), this, SLOT(updateScrollBars())); + m_viewOffsetAnimation->setTargetObject(current); } } void KItemListContainer::updateScrollBars() { - const QSizeF size = m_controller->view()->size(); + const KItemListView* view = m_controller->view(); + if (!view) { + return; + } - if (m_controller->view()->scrollOrientation() == Qt::Vertical) { - QScrollBar* scrollBar = verticalScrollBar(); - const int value = m_controller->view()->offset(); - const int maximum = qMax(0, int(m_controller->view()->maximumOffset() - size.height())); - scrollBar->setPageStep(size.height()); - scrollBar->setMinimum(0); - scrollBar->setMaximum(maximum); - scrollBar->setValue(value); - horizontalScrollBar()->setMaximum(0); + QScrollBar* scrollBar = 0; + int singleStep = 0; + int pageStep = 0; + if (view->scrollOrientation() == Qt::Vertical) { + scrollBar = verticalScrollBar(); + singleStep = view->itemSize().height(); + pageStep = view->size().height(); } else { - QScrollBar* scrollBar = horizontalScrollBar(); - const int value = m_controller->view()->offset(); - const int maximum = qMax(0, int(m_controller->view()->maximumOffset() - size.width())); - scrollBar->setPageStep(size.width()); - scrollBar->setMinimum(0); - scrollBar->setMaximum(maximum); - scrollBar->setValue(value); - verticalScrollBar()->setMaximum(0); + scrollBar = horizontalScrollBar(); + singleStep = view->itemSize().width(); + pageStep = view->size().width(); + } + + const int value = view->offset(); + const int maximum = qMax(0, int(view->maximumOffset() - pageStep)); + if (m_viewOffsetAnimation->state() == QAbstractAnimation::Running) { + if (maximum == scrollBar->maximum()) { + // The value has been changed by the animation, no update + // of the scrollbars is required as their target state will be + // reached with the end of the animation. + return; + } + + // The maximum has been changed which indicates that the content + // of the view has been changed. Stop the animation in any case and + // update the scrollbars immediately. + m_viewOffsetAnimation->stop(); } + + scrollBar->setSingleStep(singleStep); + scrollBar->setPageStep(pageStep); + scrollBar->setMinimum(0); + scrollBar->setMaximum(maximum); + scrollBar->setValue(value); } void KItemListContainer::updateGeometries() @@ -186,6 +287,12 @@ void KItemListContainer::initialize() QGraphicsView* graphicsView = new KItemListContainerViewport(new QGraphicsScene(this), this); setViewport(graphicsView); + + m_viewOffsetAnimation = new QPropertyAnimation(this, "offset"); + m_viewOffsetAnimation->setDuration(500); + + horizontalScrollBar()->installEventFilter(this); + verticalScrollBar()->installEventFilter(this); } #include "kitemlistcontainer.moc" diff --git a/src/kitemviews/kitemlistcontainer.h b/src/kitemviews/kitemlistcontainer.h index 83044c4f8..4994eb249 100644 --- a/src/kitemviews/kitemlistcontainer.h +++ b/src/kitemviews/kitemlistcontainer.h @@ -30,6 +30,7 @@ class KItemListController; class KItemListView; class KItemModelBase; +class QPropertyAnimation; /** * @brief Provides a QWidget based scrolling view for a KItemListController. @@ -51,6 +52,8 @@ protected: virtual void showEvent(QShowEvent* event); virtual void resizeEvent(QResizeEvent* event); virtual void scrollContentsBy(int dx, int dy); + virtual bool eventFilter(QObject* obj, QEvent* event); + virtual void wheelEvent(QWheelEvent* event); private slots: void slotModelChanged(KItemModelBase* current, KItemModelBase* previous); @@ -63,6 +66,9 @@ private: private: KItemListController* m_controller; + + bool m_sliderMovedByUser; + QPropertyAnimation* m_viewOffsetAnimation; }; #endif diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index 2d72a96de..dcd62ad52 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -82,14 +82,9 @@ void KItemListController::setView(KItemListView* view) KItemListView* oldView = m_view; m_view = view; - if (oldView) { - disconnect(m_selectionManager, SIGNAL(currentChanged(int,int)), oldView, SLOT(currentChanged(int,int))); - } - if (m_view) { m_view->setController(this); m_view->setModel(m_model); - connect(m_selectionManager, SIGNAL(currentChanged(int,int)), m_view, SLOT(currentChanged(int,int))); } emit viewChanged(m_view, oldView); @@ -139,14 +134,20 @@ bool KItemListController::mousePressEvent(QGraphicsSceneMouseEvent* event, const const QPointF pos = transform.map(event->pos()); m_pressedIndex = m_view->itemAt(pos); - m_selectionManager->setCurrentItem(m_pressedIndex); - - // The anchor for the current selection is updated except for Shift+LeftButton events - // (the current selection is continued with the previous anchor in that case). - if (!(event->buttons() & Qt::LeftButton && event->modifiers() & Qt::ShiftModifier)) { + const bool shiftOrControlPressed = event->modifiers() & Qt::ShiftModifier || + event->modifiers() & Qt::ControlModifier; + if (!shiftOrControlPressed) { + m_selectionManager->clearSelection(); m_selectionManager->setAnchorItem(m_pressedIndex); } + if (m_pressedIndex >= 0) { + m_selectionManager->setCurrentItem(m_pressedIndex); + if (!m_view->isAboveExpansionToggle(m_pressedIndex, pos)) { + m_selectionManager->setSelected(m_pressedIndex); + } + } + return false; } @@ -162,15 +163,18 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, con if (m_view) { const QPointF pos = transform.map(event->pos()); const int index = m_view->itemAt(pos); + const bool shiftOrControlPressed = event->modifiers() & Qt::ShiftModifier || event->modifiers() & Qt::ControlModifier; + if (index >= 0 && index == m_pressedIndex) { + // The release event is done above the same item as the press event bool emitItemClicked = true; if (event->button() & Qt::LeftButton) { if (m_view->isAboveExpansionToggle(index, pos)) { emit itemExpansionToggleClicked(index); emitItemClicked = false; } - else if (event->modifiers() & Qt::ShiftModifier || event->modifiers() & Qt::ControlModifier) { - // The mouse click should only update the selection, not trigger the item. + else if (shiftOrControlPressed) { + // The mouse click should only update the selection, not trigger the item emitItemClicked = false; } } @@ -178,6 +182,8 @@ bool KItemListController::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, con if (emitItemClicked) { emit itemClicked(index, event->button()); } + } else if (!shiftOrControlPressed) { + m_selectionManager->clearSelection(); } } @@ -229,8 +235,49 @@ bool KItemListController::hoverEnterEvent(QGraphicsSceneHoverEvent* event, const bool KItemListController::hoverMoveEvent(QGraphicsSceneHoverEvent* event, const QTransform& transform) { - Q_UNUSED(event); + // The implementation assumes that only one item can get hovered no matter + // whether they overlap or not. + Q_UNUSED(transform); + if (!m_model || !m_view) { + return false; + } + + // Search the previously hovered item that might get unhovered + KItemListWidget* unhoveredWidget = 0; + foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) { + if (widget->isHovered()) { + unhoveredWidget = widget; + break; + } + } + + // Search the currently hovered item + KItemListWidget* hoveredWidget = 0; + foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) { + const QPointF mappedPos = widget->mapFromItem(m_view, event->pos()); + + const bool hovered = widget->contains(mappedPos) && + !widget->expansionToggleRect().contains(mappedPos) && + !widget->selectionToggleRect().contains(mappedPos); + if (hovered) { + hoveredWidget = widget; + break; + } + } + + if (unhoveredWidget != hoveredWidget) { + if (unhoveredWidget) { + unhoveredWidget->setHovered(false); + emit itemUnhovered(unhoveredWidget->index()); + } + + if (hoveredWidget) { + hoveredWidget->setHovered(true); + emit itemHovered(hoveredWidget->index()); + } + } + return false; } @@ -238,6 +285,17 @@ bool KItemListController::hoverLeaveEvent(QGraphicsSceneHoverEvent* event, const { Q_UNUSED(event); Q_UNUSED(transform); + + if (!m_model || !m_view) { + return false; + } + + foreach (KItemListWidget* widget, m_view->visibleItemListWidgets()) { + if (widget->isHovered()) { + widget->setHovered(false); + emit itemUnhovered(widget->index()); + } + } return false; } @@ -262,9 +320,6 @@ bool KItemListController::processEvent(QEvent* event, const QTransform& transfor } switch (event->type()) { -// case QEvent::FocusIn: -// case QEvent::FocusOut: -// return focusEvent(static_cast<QFocusEvent*>(event)); case QEvent::KeyPress: return keyPressEvent(static_cast<QKeyEvent*>(event)); case QEvent::InputMethod: diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h index 86f2b4ea6..092a7bc62 100644 --- a/src/kitemviews/kitemlistcontroller.h +++ b/src/kitemviews/kitemlistcontroller.h @@ -101,6 +101,19 @@ public: signals: void itemClicked(int index, Qt::MouseButton button); + + /** + * Is emitted if the item with the index \p index gets hovered. + */ + void itemHovered(int index); + + /** + * Is emitted if the item with the index \p index gets unhovered. + * It is assured that the signal itemHovered() for this index + * has been emitted before. + */ + void itemUnhovered(int index); + void itemExpansionToggleClicked(int index); void modelChanged(KItemModelBase* current, KItemModelBase* previous); diff --git a/src/kitemviews/kitemlistselectionmanager.cpp b/src/kitemviews/kitemlistselectionmanager.cpp index 6fe9ed818..ee8ba929e 100644 --- a/src/kitemviews/kitemlistselectionmanager.cpp +++ b/src/kitemviews/kitemlistselectionmanager.cpp @@ -23,11 +23,13 @@ #include "kitemlistselectionmanager.h" #include "kitemmodelbase.h" +#include <KDebug> KItemListSelectionManager::KItemListSelectionManager(QObject* parent) : QObject(parent), m_currentItem(-1), m_anchorItem(-1), + m_selectedItems(), m_model(0) { } @@ -39,7 +41,7 @@ KItemListSelectionManager::~KItemListSelectionManager() void KItemListSelectionManager::setCurrentItem(int current) { const int previous = m_currentItem; - if (m_model && current < m_model->count()) { + if (m_model && current >= 0 && current < m_model->count()) { m_currentItem = current; } else { m_currentItem = -1; @@ -55,6 +57,88 @@ int KItemListSelectionManager::currentItem() const return m_currentItem; } +void KItemListSelectionManager::setSelectedItems(const QSet<int>& items) +{ + if (m_selectedItems != items) { + const QSet<int> previous = m_selectedItems; + m_selectedItems = items; + emit selectionChanged(m_selectedItems, previous); + } +} + +QSet<int> KItemListSelectionManager::selectedItems() const +{ + return m_selectedItems; +} + +bool KItemListSelectionManager::hasSelection() const +{ + return !m_selectedItems.isEmpty(); +} + +void KItemListSelectionManager::setSelected(int index, int count, SelectionMode mode) +{ + if (index < 0 || count < 1 || !m_model || index >= m_model->count()) { + return; + } + + const QSet<int> previous = m_selectedItems; + + count = qMin(count, m_model->count() - index); + + const int endIndex = index + count -1; + switch (mode) { + case Select: + for (int i = index; i <= endIndex; ++i) { + m_selectedItems.insert(i); + } + break; + + case Deselect: + for (int i = index; i <= endIndex; ++i) { + m_selectedItems.remove(i); + } + break; + + case Toggle: + for (int i = index; i <= endIndex; ++i) { + if (m_selectedItems.contains(i)) { + m_selectedItems.remove(i); + } else { + m_selectedItems.insert(i); + } + } + break; + + default: + Q_ASSERT(false); + break; + } + + if (m_selectedItems != previous) { + emit selectionChanged(m_selectedItems, previous); + } +} + +void KItemListSelectionManager::clearSelection() +{ + if (!m_selectedItems.isEmpty()) { + const QSet<int> previous = m_selectedItems; + m_selectedItems.clear(); + emit selectionChanged(m_selectedItems, previous); + } +} + +void KItemListSelectionManager::beginAnchoredSelection(int anchor, SelectionMode mode) +{ + Q_UNUSED(anchor); + Q_UNUSED(mode); +} + +void KItemListSelectionManager::endAnchoredSelection() +{ +} + void KItemListSelectionManager::setAnchorItem(int anchor) { const int previous = m_anchorItem; @@ -82,6 +166,106 @@ KItemModelBase* KItemListSelectionManager::model() const void KItemListSelectionManager::setModel(KItemModelBase* model) { m_model = model; + if (model && model->count() > 0) { + m_currentItem = 0; + } +} + +void KItemListSelectionManager::itemsInserted(const KItemRangeList& itemRanges) +{ + // Update the current item + if (m_currentItem < 0) { + setCurrentItem(0); + } else { + int inc = 0; + foreach (const KItemRange& itemRange, itemRanges) { + if (m_currentItem < itemRange.index) { + break; + } + inc += itemRange.count; + } + setCurrentItem(m_currentItem + inc); + } + + // Update the selections + if (!m_selectedItems.isEmpty()) { + const QSet<int> previous = m_selectedItems; + + QSet<int> current; + current.reserve(m_selectedItems.count()); + QSetIterator<int> it(m_selectedItems); + while (it.hasNext()) { + const int index = it.next(); + int inc = 0; + foreach (const KItemRange& itemRange, itemRanges) { + if (index < itemRange.index) { + break; + } + inc += itemRange.count; + } + current.insert(index + inc); + } + + if (current != previous) { + m_selectedItems = current; + emit selectionChanged(current, previous); + } + } +} + +void KItemListSelectionManager::itemsRemoved(const KItemRangeList& itemRanges) +{ + // Update the current item + if (m_currentItem >= 0) { + int currentItem = m_currentItem; + foreach (const KItemRange& itemRange, itemRanges) { + if (currentItem < itemRange.index) { + break; + } + if (currentItem >= itemRange.index + itemRange.count) { + currentItem -= itemRange.count; + } else if (currentItem >= m_model->count()) { + currentItem = m_model->count() - 1; + } + } + setCurrentItem(currentItem); + } + + // Update the selections + if (!m_selectedItems.isEmpty()) { + const QSet<int> previous = m_selectedItems; + + QSet<int> current; + current.reserve(m_selectedItems.count()); + QSetIterator<int> it(m_selectedItems); + while (it.hasNext()) { + int index = it.next(); + int dec = 0; + foreach (const KItemRange& itemRange, itemRanges) { + if (index < itemRange.index) { + break; + } + + if (index < itemRange.index + itemRange.count) { + // The selection is part of the removed range + // and will get deleted + index = -1; + break; + } + + dec += itemRange.count; + } + index -= dec; + if (index >= 0) { + current.insert(index); + } + } + + if (current != previous) { + m_selectedItems = current; + emit selectionChanged(current, previous); + } + } } #include "kitemlistselectionmanager.moc" diff --git a/src/kitemviews/kitemlistselectionmanager.h b/src/kitemviews/kitemlistselectionmanager.h index 5c8e84614..5b329b40e 100644 --- a/src/kitemviews/kitemlistselectionmanager.h +++ b/src/kitemviews/kitemlistselectionmanager.h @@ -25,10 +25,16 @@ #include <libdolphin_export.h> +#include <kitemviews/kitemmodelbase.h> + #include <QObject> +#include <QSet> class KItemModelBase; +/** + * @brief Allows to select and deselect items of a KItemListView. + */ class LIBDOLPHINPRIVATE_EXPORT KItemListSelectionManager : public QObject { Q_OBJECT @@ -39,13 +45,22 @@ public: Deselect, Toggle }; - + KItemListSelectionManager(QObject* parent = 0); virtual ~KItemListSelectionManager(); void setCurrentItem(int current); int currentItem() const; + void setSelectedItems(const QSet<int>& items); + QSet<int> selectedItems() const; + bool hasSelection() const; + + void setSelected(int index, int count = 1, SelectionMode mode = Select); + void clearSelection(); + + void beginAnchoredSelection(int anchor, SelectionMode mode = Select); + void endAnchoredSelection(); void setAnchorItem(int anchor); int anchorItem() const; @@ -53,17 +68,24 @@ public: signals: void currentChanged(int current, int previous); + void selectionChanged(const QSet<int>& current, const QSet<int>& previous); void anchorChanged(int anchor, int previous); -protected: +private: void setModel(KItemModelBase* model); + void itemsInserted(const KItemRangeList& itemRanges); + void itemsRemoved(const KItemRangeList& itemRanges); private: int m_currentItem; int m_anchorItem; + QSet<int> m_selectedItems; + KItemModelBase* m_model; - friend class KItemListController; + friend class KItemListController; // Calls setModel() + friend class KItemListView; // Calls itemsInserted() and itemsRemoved() + friend class KItemListSelectionManagerTest; }; #endif diff --git a/src/kitemviews/kitemliststyleoption.cpp b/src/kitemviews/kitemliststyleoption.cpp index 261dfc07b..f26b220bc 100644 --- a/src/kitemviews/kitemliststyleoption.cpp +++ b/src/kitemviews/kitemliststyleoption.cpp @@ -20,16 +20,23 @@ #include "kitemliststyleoption.h" KItemListStyleOption::KItemListStyleOption() : - QStyleOption(QStyleOption::Version, QStyleOption::SO_CustomBase + 1) + rect(), + font(), + fontMetrics(QFont()), + palette(), + margin(0), + iconSize(0) { } KItemListStyleOption::KItemListStyleOption(const KItemListStyleOption& other) : - QStyleOption(other) + rect(other.rect), + font(other.font), + fontMetrics(other.fontMetrics), + palette(other.palette), + margin(other.margin), + iconSize(other.iconSize) { - margin = other.margin; - iconSize = other.iconSize; - font = other.font; } KItemListStyleOption::~KItemListStyleOption() diff --git a/src/kitemviews/kitemliststyleoption.h b/src/kitemviews/kitemliststyleoption.h index d181204d7..bafb81d3a 100644 --- a/src/kitemviews/kitemliststyleoption.h +++ b/src/kitemviews/kitemliststyleoption.h @@ -23,18 +23,23 @@ #include <libdolphin_export.h> #include <QFont> -#include <QStyleOption> +#include <QFontMetrics> +#include <QPalette> +#include <QRect> -class LIBDOLPHINPRIVATE_EXPORT KItemListStyleOption : public QStyleOption +class LIBDOLPHINPRIVATE_EXPORT KItemListStyleOption { public: KItemListStyleOption(); KItemListStyleOption(const KItemListStyleOption& other); virtual ~KItemListStyleOption(); + QRect rect; + QFont font; + QFontMetrics fontMetrics; + QPalette palette; int margin; int iconSize; - QFont font; }; #endif diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp index b89f4d0f5..9c054e119 100644 --- a/src/kitemviews/kitemlistview.cpp +++ b/src/kitemviews/kitemlistview.cpp @@ -256,10 +256,6 @@ void KItemListView::setGeometry(const QRectF& rect) int KItemListView::itemAt(const QPointF& pos) const { - if (!m_model) { - return -1; - } - QHashIterator<int, KItemListWidget*> it(m_visibleItems); while (it.hasNext()) { it.next(); @@ -315,6 +311,11 @@ QHash<QByteArray, QSizeF> KItemListView::visibleRoleSizes() const return QHash<QByteArray, QSizeF>(); } +QRectF KItemListView::itemBoundingRect(int index) const +{ + return m_layouter->itemBoundingRect(index); +} + void KItemListView::beginTransaction() { ++m_activeTransactions; @@ -412,56 +413,6 @@ void KItemListView::mousePressEvent(QGraphicsSceneMouseEvent* event) event->accept(); } -void KItemListView::hoverMoveEvent(QGraphicsSceneHoverEvent* event) -{ - if (!m_model) { - return; - } - - QHashIterator<int, KItemListWidget*> it(m_visibleItems); - while (it.hasNext()) { - it.next(); - - KItemListWidget* widget = it.value(); - KItemListStyleOption styleOption = widget->styleOption(); - const QPointF mappedPos = widget->mapFromItem(this, event->pos()); - - const bool hovered = widget->contains(mappedPos) && - !widget->expansionToggleRect().contains(mappedPos) && - !widget->selectionToggleRect().contains(mappedPos); - if (hovered) { - if (!(styleOption.state & QStyle::State_MouseOver)) { - styleOption.state |= QStyle::State_MouseOver; - widget->setStyleOption(styleOption); - } - } else if (styleOption.state & QStyle::State_MouseOver) { - styleOption.state &= ~QStyle::State_MouseOver; - widget->setStyleOption(styleOption); - } - } -} - -void KItemListView::hoverLeaveEvent(QGraphicsSceneHoverEvent* event) -{ - Q_UNUSED(event); - - if (!m_model) { - return; - } - - QHashIterator<int, KItemListWidget*> it(m_visibleItems); - while (it.hasNext()) { - it.next(); - - KItemListWidget* widget = it.value(); - KItemListStyleOption styleOption = widget->styleOption(); - if (styleOption.state & QStyle::State_MouseOver) { - styleOption.state &= ~QStyle::State_MouseOver; - widget->setStyleOption(styleOption); - } - } -} - QList<KItemListWidget*> KItemListView::visibleItemListWidgets() const { return m_visibleItems.values(); @@ -476,13 +427,18 @@ void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges) beginTransaction(); } + int previouslyInsertedCount = 0; foreach (const KItemRange& range, itemRanges) { - const int index = range.index; + // range.index is related to the model before anything has been inserted. + // As in each loop the current item-range gets inserted the index must + // be increased by the already previoulsy inserted items. + const int index = range.index + previouslyInsertedCount; const int count = range.count; if (index < 0 || count <= 0) { kWarning() << "Invalid item range (index:" << index << ", count:" << count << ")"; continue; } + previouslyInsertedCount += count; m_sizeHintResolver->itemsInserted(index, count); @@ -524,16 +480,10 @@ void KItemListView::slotItemsInserted(const KItemRangeList& itemRanges) doLayout(Animation, index, count); update(); } + } - if (m_controller) { - KItemListSelectionManager* selectionManager = m_controller->selectionManager(); - const int current = selectionManager->currentItem(); - if (current < 0) { - selectionManager->setCurrentItem(0); - } else if (current >= index) { - selectionManager->setCurrentItem(current + count); - } - } + if (m_controller) { + m_controller->selectionManager()->itemsInserted(itemRanges); } if (hasMultipleRanges) { @@ -611,14 +561,10 @@ void KItemListView::slotItemsRemoved(const KItemRangeList& itemRanges) doLayout(Animation, index, -count); update(); } + } - /*KItemListSelectionManager* selectionManager = m_controller->selectionManager(); - const int current = selectionManager->currentItem(); - if (count() <= 0) { - selectionManager->setCurrentItem(-1); - } else if (current >= index) { - selectionManager->setCurrentItem(current + count); - }*/ + if (m_controller) { + m_controller->selectionManager()->itemsRemoved(itemRanges); } if (hasMultipleRanges) { @@ -645,24 +591,33 @@ void KItemListView::slotItemsChanged(const KItemRangeList& itemRanges, } } -void KItemListView::currentChanged(int current, int previous) +void KItemListView::slotCurrentChanged(int current, int previous) +{ + Q_UNUSED(previous); + + KItemListWidget* previousWidget = m_visibleItems.value(previous, 0); + if (previousWidget) { + Q_ASSERT(previousWidget->isCurrent()); + previousWidget->setCurrent(false); + } + + KItemListWidget* currentWidget = m_visibleItems.value(current, 0); + if (currentWidget) { + Q_ASSERT(!currentWidget->isCurrent()); + currentWidget->setCurrent(true); + } +} + +void KItemListView::slotSelectionChanged(const QSet<int>& current, const QSet<int>& previous) { Q_UNUSED(previous); QHashIterator<int, KItemListWidget*> it(m_visibleItems); while (it.hasNext()) { it.next(); - + const int index = it.key(); KItemListWidget* widget = it.value(); - KItemListStyleOption styleOption = widget->styleOption(); - if (it.key() == current) { - styleOption.state |= QStyle::State_HasFocus; - widget->setStyleOption(styleOption); - } - else if (styleOption.state & QStyle::State_HasFocus) { - styleOption.state &= ~QStyle::State_HasFocus; - widget->setStyleOption(styleOption); - } + widget->setSelected(current.contains(index)); } } @@ -717,7 +672,20 @@ void KItemListView::setController(KItemListController* controller) { if (m_controller != controller) { KItemListController* previous = m_controller; + if (previous) { + KItemListSelectionManager* selectionManager = previous->selectionManager(); + disconnect(selectionManager, SIGNAL(currentChanged(int,int)), this, SLOT(slotCurrentChanged(int,int))); + disconnect(selectionManager, SIGNAL(selectionChanged(QSet<int>,QSet<int>)), this, SLOT(slotSelectionChanged(QSet<int>,QSet<int>))); + } + m_controller = controller; + + if (controller) { + KItemListSelectionManager* selectionManager = controller->selectionManager(); + connect(selectionManager, SIGNAL(currentChanged(int,int)), this, SLOT(slotCurrentChanged(int,int))); + connect(selectionManager, SIGNAL(selectionChanged(QSet<int>,QSet<int>)), this, SLOT(slotSelectionChanged(QSet<int>,QSet<int>))); + } + onControllerChanged(controller, previous); } } @@ -918,17 +886,7 @@ void KItemListView::emitOffsetChanges() KItemListWidget* KItemListView::createWidget(int index) { KItemListWidget* widget = m_widgetCreator->create(this); - widget->setVisibleRoles(m_visibleRoles); - widget->setVisibleRolesSizes(m_visibleRolesSizes); - - KItemListStyleOption option = m_styleOption; - if (index == m_controller->selectionManager()->currentItem()) { - option.state |= QStyle::State_HasFocus; - } - widget->setStyleOption(option); - - widget->setIndex(index); - widget->setData(m_model->data(index)); + updateWidgetProperties(widget, index); m_visibleItems.insert(index, widget); if (m_grouped) { @@ -982,17 +940,7 @@ void KItemListView::setWidgetIndex(KItemListWidget* widget, int index) const int oldIndex = widget->index(); m_visibleItems.remove(oldIndex); - widget->setVisibleRoles(m_visibleRoles); - widget->setVisibleRolesSizes(m_visibleRolesSizes); - - KItemListStyleOption option = m_styleOption; - if (index == m_controller->selectionManager()->currentItem()) { - option.state |= QStyle::State_HasFocus; - } - widget->setStyleOption(option); - - widget->setIndex(index); - widget->setData(m_model->data(index)); + updateWidgetProperties(widget, index); m_visibleItems.insert(index, widget); initializeItemListWidget(widget); @@ -1099,6 +1047,28 @@ void KItemListView::applyDynamicItemSize() } } +void KItemListView::updateWidgetProperties(KItemListWidget* widget, int index) +{ + widget->setVisibleRoles(m_visibleRoles); + widget->setVisibleRolesSizes(m_visibleRolesSizes); + widget->setStyleOption(m_styleOption); + + const KItemListSelectionManager* selectionManager = m_controller->selectionManager(); + widget->setCurrent(index == selectionManager->currentItem()); + + if (selectionManager->hasSelection()) { + const QSet<int> selectedItems = selectionManager->selectedItems(); + widget->setSelected(selectedItems.contains(index)); + } else { + widget->setSelected(false); + } + + widget->setHovered(false); + + widget->setIndex(index); + widget->setData(m_model->data(index)); +} + KItemListCreatorBase::~KItemListCreatorBase() { qDeleteAll(m_recycleableWidgets); diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h index 81ad52ac3..23181db6e 100644 --- a/src/kitemviews/kitemlistview.h +++ b/src/kitemviews/kitemlistview.h @@ -30,6 +30,7 @@ #include <kitemviews/kitemlistwidget.h> #include <kitemviews/kitemmodelbase.h> #include <QGraphicsWidget> +#include <QSet> class KItemListController; class KItemListWidgetCreatorBase; @@ -62,6 +63,8 @@ class LIBDOLPHINPRIVATE_EXPORT KItemListView : public QGraphicsWidget { Q_OBJECT + Q_PROPERTY(qreal offset READ offset WRITE setOffset) + public: KItemListView(QGraphicsWidget* parent = 0); virtual ~KItemListView(); @@ -132,6 +135,8 @@ public: virtual QSizeF itemSizeHint(int index) const; virtual QHash<QByteArray, QSizeF> visibleRoleSizes() const; + QRectF itemBoundingRect(int index) const; + void beginTransaction(); void endTransaction(); bool isTransactionActive() const; @@ -157,8 +162,6 @@ protected: virtual bool event(QEvent* event); virtual void mousePressEvent(QGraphicsSceneMouseEvent* event); - virtual void hoverMoveEvent(QGraphicsSceneHoverEvent* event); - virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event); QList<KItemListWidget*> visibleItemListWidgets() const; @@ -169,7 +172,8 @@ protected slots: const QSet<QByteArray>& roles); private slots: - void currentChanged(int current, int previous); + void slotCurrentChanged(int current, int previous); + void slotSelectionChanged(const QSet<int>& current, const QSet<int>& previous); void slotAnimationFinished(QGraphicsWidget* widget, KItemListViewAnimation::AnimationType type); void slotLayoutTimerFinished(); @@ -229,6 +233,12 @@ private: */ void applyDynamicItemSize(); + /** + * Helper method for createWidget() and setWidgetIndex() to update the properties + * of the itemlist widget. + */ + void updateWidgetProperties(KItemListWidget* widget, int index); + private: bool m_grouped; int m_activeTransactions; // Counter for beginTransaction()/endTransaction() diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp index 3f08d9f7a..ef4c1f797 100644 --- a/src/kitemviews/kitemlistwidget.cpp +++ b/src/kitemviews/kitemlistwidget.cpp @@ -30,10 +30,14 @@ #include <QPainter> #include <QPropertyAnimation> #include <QStyle> +#include <QStyleOption> KItemListWidget::KItemListWidget(QGraphicsItem* parent) : QGraphicsWidget(parent, 0), m_index(-1), + m_selected(false), + m_current(false), + m_hovered(false), m_data(), m_visibleRoles(), m_visibleRolesSizes(), @@ -90,11 +94,21 @@ QHash<QByteArray, QVariant> KItemListWidget::data() const void KItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { Q_UNUSED(option); + + const QRect hoverBounds = hoverBoundingRect().toRect(); + if (m_selected) { + QStyleOptionViewItemV4 viewItemOption; + viewItemOption.initFrom(widget); + viewItemOption.rect = hoverBounds; + viewItemOption.state = QStyle::State_Enabled | QStyle::State_Selected | QStyle::State_Item; + viewItemOption.viewItemPosition = QStyleOptionViewItemV4::OnlyOne; + widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, painter, widget); + } + if (m_hoverOpacity <= 0.0) { return; } - const QRect hoverBounds = hoverBoundingRect().toRect(); if (!m_hoverCache) { m_hoverCache = new QPixmap(hoverBounds.size()); m_hoverCache->fill(Qt::transparent); @@ -104,7 +118,7 @@ void KItemListWidget::paint(QPainter* painter, const QStyleOptionGraphicsItem* o QStyleOptionViewItemV4 viewItemOption; viewItemOption.initFrom(widget); viewItemOption.rect = QRect(0, 0, hoverBounds.width(), hoverBounds.height()); - viewItemOption.state = QStyle::State_Enabled | QStyle::State_MouseOver; + viewItemOption.state = QStyle::State_Enabled | QStyle::State_MouseOver | QStyle::State_Item; viewItemOption.viewItemPosition = QStyleOptionViewItemV4::OnlyOne; widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &viewItemOption, &pixmapPainter, widget); @@ -143,41 +157,75 @@ QHash<QByteArray, QSizeF> KItemListWidget::visibleRolesSizes() const void KItemListWidget::setStyleOption(const KItemListStyleOption& option) { const KItemListStyleOption previous = m_styleOption; - if (m_index >= 0) { - clearCache(); + clearCache(); + m_styleOption = option; - const bool wasHovered = (previous.state & QStyle::State_MouseOver); - m_styleOption = option; - const bool isHovered = (m_styleOption.state & QStyle::State_MouseOver); + styleOptionChanged(option, previous); +} - if (wasHovered != isHovered) { - // The hovering state has been changed. Assure that a fade-animation - // is done to the new state. - if (!m_hoverAnimation) { - m_hoverAnimation = new QPropertyAnimation(this, "hoverOpacity", this); - m_hoverAnimation->setDuration(200); - } - m_hoverAnimation->stop(); +const KItemListStyleOption& KItemListWidget::styleOption() const +{ + return m_styleOption; +} - if (!wasHovered && isHovered) { - m_hoverAnimation->setEndValue(1.0); - } else { - Q_ASSERT(wasHovered && !isHovered); - m_hoverAnimation->setEndValue(0.0); - } +void KItemListWidget::setSelected(bool selected) +{ + if (m_selected != selected) { + m_selected = selected; + selectedChanged(selected); + update(); + } +} - m_hoverAnimation->start(); - } +bool KItemListWidget::isSelected() const +{ + return m_selected; +} + +void KItemListWidget::setCurrent(bool current) +{ + if (m_current != current) { + m_current = current; + currentChanged(current); + update(); + } +} + +bool KItemListWidget::isCurrent() const +{ + return m_current; +} + +void KItemListWidget::setHovered(bool hovered) +{ + if (hovered == m_hovered) { + return; + } + + m_hovered = hovered; + + if (!m_hoverAnimation) { + m_hoverAnimation = new QPropertyAnimation(this, "hoverOpacity", this); + m_hoverAnimation->setDuration(200); + } + m_hoverAnimation->stop(); + + if (hovered) { + m_hoverAnimation->setEndValue(1.0); } else { - m_styleOption = option; + m_hoverAnimation->setEndValue(0.0); } - styleOptionChanged(option, previous); + m_hoverAnimation->start(); + + hoveredChanged(hovered); + + update(); } -const KItemListStyleOption& KItemListWidget::styleOption() const +bool KItemListWidget::isHovered() const { - return m_styleOption; + return m_hovered; } bool KItemListWidget::contains(const QPointF& point) const @@ -234,6 +282,21 @@ void KItemListWidget::styleOptionChanged(const KItemListStyleOption& current, update(); } +void KItemListWidget::currentChanged(bool current) +{ + Q_UNUSED(current); +} + +void KItemListWidget::selectedChanged(bool selected) +{ + Q_UNUSED(selected); +} + +void KItemListWidget::hoveredChanged(bool hovered) +{ + Q_UNUSED(hovered); +} + void KItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event) { QGraphicsWidget::resizeEvent(event); diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h index eb2ebf455..d655042b8 100644 --- a/src/kitemviews/kitemlistwidget.h +++ b/src/kitemviews/kitemlistwidget.h @@ -72,6 +72,15 @@ public: void setStyleOption(const KItemListStyleOption& option); const KItemListStyleOption& styleOption() const; + void setSelected(bool selected); + bool isSelected() const; + + void setCurrent(bool current); + bool isCurrent() const; + + void setHovered(bool hovered); + bool isHovered() const; + /** * @return True if \a point is inside KItemListWidget::hoverBoundingRect(), * KItemListWidget::selectionToggleRect() or KItemListWidget::expansionToggleRect(). @@ -104,6 +113,9 @@ protected: virtual void visibleRolesChanged(const QHash<QByteArray, int>& current, const QHash<QByteArray, int>& previous); virtual void visibleRolesSizesChanged(const QHash<QByteArray, QSizeF>& current, const QHash<QByteArray, QSizeF>& previous); virtual void styleOptionChanged(const KItemListStyleOption& current, const KItemListStyleOption& previous); + virtual void currentChanged(bool current); + virtual void selectedChanged(bool selected); + virtual void hoveredChanged(bool hovered); virtual void resizeEvent(QGraphicsSceneResizeEvent* event); /** @@ -120,6 +132,9 @@ private: Q_PROPERTY(qreal hoverOpacity READ hoverOpacity WRITE setHoverOpacity) int m_index; + bool m_selected; + bool m_current; + bool m_hovered; QHash<QByteArray, QVariant> m_data; QHash<QByteArray, int> m_visibleRoles; QHash<QByteArray, QSizeF> m_visibleRolesSizes; diff --git a/src/kitemviews/kitemmodelbase.h b/src/kitemviews/kitemmodelbase.h index 4eb96c8fd..44135d2f4 100644 --- a/src/kitemviews/kitemmodelbase.h +++ b/src/kitemviews/kitemmodelbase.h @@ -106,9 +106,46 @@ public: virtual QString roleDescription(const QByteArray& role) const; signals: + /** + * Is emitted if one or more items have been inserted. Each item-range consists + * of: + * - an index where items have been inserted + * - the number of inserted items. + * The index of each item-range represents the index of the model + * before the items have been inserted. + * + * For the item-ranges it is assured that: + * - They don't overlap + * - The index of item-range n is smaller than the index of item-range n + 1. + */ void itemsInserted(const KItemRangeList& itemRanges); + + /** + * Is emitted if one or more items have been removed. Each item-range consists + * of: + * - an index where items have been inserted + * - the number of inserted items. + * The index of each item-range represents the index of the model + * before the items have been removed. + * + * For the item-ranges it is assured that: + * - They don't overlap + * - The index of item-range n is smaller than the index of item-range n + 1. + */ void itemsRemoved(const KItemRangeList& itemRanges); - void itemsMoved(const KItemRangeList& itemRanges); + + /** + * Is emitted if one ore more items get moved. + * @param itemRanges Item-ranges that get moved to a new position. + * @param movedToIndexes New position of the ranges. + * It is assured that the itemRanges list has the same size as the movedToIndexes list. + * + * For the item-ranges it is assured that: + * - They don't overlap + * - The index of item-range n is smaller than the index of item-range n + 1. + */ + void itemsMoved(const KItemRangeList& itemRanges, const QList<int> movedToIndexes); + void itemsChanged(const KItemRangeList& itemRanges, const QSet<QByteArray>& roles); void groupRoleChanged(const QByteArray& current, const QByteArray& previous); |
