#include <QStyleOptionRubberBand>
#include <QTimer>
+#include <algorithm>
+
#include "kitemlistviewaccessible.h"
namespace {
m_layouter->markAsDirty();
- int removedItemsCount = 0;
- for (int i = 0; i < itemRanges.count(); ++i) {
- removedItemsCount += itemRanges[i].count;
- }
-
m_sizeHintResolver->itemsRemoved(itemRanges);
for (int i = itemRanges.count() - 1; i >= 0; --i) {
const int firstRemovedIndex = index;
const int lastRemovedIndex = index + count - 1;
- const int lastIndex = m_model->count() - 1 + removedItemsCount;
- removedItemsCount -= count;
+
+ // Remeber which items have to be moved because they are behind the removed range.
+ QVector<int> itemsToMove;
// Remove all KItemListWidget instances that got deleted
- for (int i = firstRemovedIndex; i <= lastRemovedIndex; ++i) {
- KItemListWidget* widget = m_visibleItems.value(i);
- if (!widget) {
+ foreach (KItemListWidget* widget, m_visibleItems) {
+ const int i = widget->index();
+ if (i < firstRemovedIndex) {
+ continue;
+ } else if (i > lastRemovedIndex) {
+ itemsToMove.append(i);
continue;
}
}
// Update the indexes of all KItemListWidget instances that are located
- // after the deleted items
- for (int i = lastRemovedIndex + 1; i <= lastIndex; ++i) {
+ // after the deleted items. It is important to update them in ascending
+ // order to prevent overlaps when setting the new index.
+ std::sort(itemsToMove.begin(), itemsToMove.end());
+ foreach (int i, itemsToMove) {
KItemListWidget* widget = m_visibleItems.value(i);
- if (widget) {
- const int newIndex = i - count;
- if (hasMultipleRanges) {
- setWidgetIndex(widget, newIndex);
- } else {
- // Try to animate the moving of the item
- moveWidgetToIndex(widget, newIndex);
- }
+ Q_ASSERT(widget);
+ const int newIndex = i - count;
+ if (hasMultipleRanges) {
+ setWidgetIndex(widget, newIndex);
+ } else {
+ // Try to animate the moving of the item
+ moveWidgetToIndex(widget, newIndex);
}
}
void KItemListView::slotItemsMoved(const KItemRange& itemRange, const QList<int>& movedToIndexes)
{
- m_sizeHintResolver->itemsMoved(itemRange.index, itemRange.count);
+ m_sizeHintResolver->itemsMoved(itemRange, movedToIndexes);
m_layouter->markAsDirty();
if (m_controller) {
QAccessible::updateAccessibility(this, 0, QAccessible::TableModelChanged);
}
+void KItemListView::slotGroupsChanged()
+{
+ updateVisibleGroupHeaders();
+ doLayout(NoAnimation);
+ updateSiblingsInformation();
+}
+
void KItemListView::slotGroupedSortingChanged(bool current)
{
m_grouped = current;
if (m_grouped) {
updateGroupHeaderHeight();
} else {
- // Clear all visible headers
- QMutableHashIterator<KItemListWidget*, KItemListGroupHeader*> it (m_visibleGroups);
+ // Clear all visible headers. Note that the QHashIterator takes a copy of
+ // m_visibleGroups. Therefore, it remains valid even if items are removed
+ // from m_visibleGroups in recycleGroupHeaderForWidget().
+ QHashIterator<KItemListWidget*, KItemListGroupHeader*> it(m_visibleGroups);
while (it.hasNext()) {
it.next();
recycleGroupHeaderForWidget(it.key());
this, SLOT(slotItemsRemoved(KItemRangeList)));
disconnect(m_model, SIGNAL(itemsMoved(KItemRange,QList<int>)),
this, SLOT(slotItemsMoved(KItemRange,QList<int>)));
+ disconnect(m_model, SIGNAL(groupsChanged()),
+ this, SLOT(slotGroupsChanged()));
disconnect(m_model, SIGNAL(groupedSortingChanged(bool)),
this, SLOT(slotGroupedSortingChanged(bool)));
disconnect(m_model, SIGNAL(sortOrderChanged(Qt::SortOrder,Qt::SortOrder)),
this, SLOT(slotItemsRemoved(KItemRangeList)));
connect(m_model, SIGNAL(itemsMoved(KItemRange,QList<int>)),
this, SLOT(slotItemsMoved(KItemRange,QList<int>)));
+ connect(m_model, SIGNAL(groupsChanged()),
+ this, SLOT(slotGroupsChanged()));
connect(m_model, SIGNAL(groupedSortingChanged(bool)),
this, SLOT(slotGroupedSortingChanged(bool)));
connect(m_model, SIGNAL(sortOrderChanged(Qt::SortOrder,Qt::SortOrder)),
widget->resize(itemBounds.size());
if (animate && changedCount < 0) {
- // Items have been deleted, move the created item to the
- // imaginary old position. They will get animated to the new position
- // later.
- const QRectF itemRect = m_layouter->itemRect(i - changedCount);
- if (itemRect.isEmpty()) {
- const QPointF invisibleOldPos = (scrollOrientation() == Qt::Vertical)
- ? QPointF(0, size().height()) : QPointF(size().width(), 0);
- widget->setPos(invisibleOldPos);
- } else {
- widget->setPos(itemRect.topLeft());
+ // Items have been deleted.
+ if (i >= changedIndex) {
+ // The item is located behind the removed range. Move the
+ // created item to the imaginary old position outside the
+ // view. It will get animated to the new position later.
+ const int previousIndex = i - changedCount;
+ const QRectF itemRect = m_layouter->itemRect(previousIndex);
+ if (itemRect.isEmpty()) {
+ const QPointF invisibleOldPos = (scrollOrientation() == Qt::Vertical)
+ ? QPointF(0, size().height()) : QPointF(size().width(), 0);
+ widget->setPos(invisibleOldPos);
+ } else {
+ widget->setPos(itemRect.topLeft());
+ }
+ applyNewPos = false;
}
- applyNewPos = false;
}
if (supportsExpanding && changedCount == 0) {
const bool itemsRemoved = (changedCount < 0);
const bool itemsInserted = (changedCount > 0);
- if (itemsRemoved && (i >= changedIndex + changedCount + 1)) {
+ if (itemsRemoved && (i >= changedIndex)) {
// The item is located after the removed items. Animate the moving of the position.
applyNewPos = !moveWidget(widget, newPos);
} else if (itemsInserted && i >= changedIndex) {