┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/kitemviews
diff options
context:
space:
mode:
authorPeter Penz <[email protected]>2011-08-08 23:41:18 +0200
committerPeter Penz <[email protected]>2011-08-09 16:22:36 +0200
commit3957884bf2e44619a4ed35ba0ffead519988885b (patch)
treed8a5bf1a015cc6001adb4afc5f0f1da721908a22 /src/kitemviews
parent4692eb7c96f57328479862c0d17d7945b4e87188 (diff)
Improvements for selections, smooth scrolling, tooltips and info-panel
Diffstat (limited to 'src/kitemviews')
-rw-r--r--src/kitemviews/kfileitemlistwidget.cpp47
-rw-r--r--src/kitemviews/kfileitemlistwidget.h2
-rw-r--r--src/kitemviews/kfileitemmodel.cpp9
-rw-r--r--src/kitemviews/kitemlistcontainer.cpp151
-rw-r--r--src/kitemviews/kitemlistcontainer.h6
-rw-r--r--src/kitemviews/kitemlistcontroller.cpp87
-rw-r--r--src/kitemviews/kitemlistcontroller.h13
-rw-r--r--src/kitemviews/kitemlistselectionmanager.cpp186
-rw-r--r--src/kitemviews/kitemlistselectionmanager.h28
-rw-r--r--src/kitemviews/kitemliststyleoption.cpp17
-rw-r--r--src/kitemviews/kitemliststyleoption.h11
-rw-r--r--src/kitemviews/kitemlistview.cpp178
-rw-r--r--src/kitemviews/kitemlistview.h16
-rw-r--r--src/kitemviews/kitemlistwidget.cpp117
-rw-r--r--src/kitemviews/kitemlistwidget.h15
-rw-r--r--src/kitemviews/kitemmodelbase.h39
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);