From ad96554aa5eae45d256120dbaf840da0bcee2fba Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 11 Sep 2009 08:32:18 +1000 Subject: Implement itemsMoved() in ListView. No animation possible currently. --- src/declarative/fx/qfxlistview.cpp | 78 +++++++++++++++++++++---------- src/declarative/fx/qfxvisualitemmodel.cpp | 19 +++++++- src/declarative/util/qmllistmodel.cpp | 2 +- 3 files changed, 73 insertions(+), 26 deletions(-) diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index 49de016..a07b3c0 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -377,7 +377,6 @@ public: QmlComponent *highlightComponent; FxListItem *highlight; FxListItem *trackedItem; - QFxItem *activeItem; //XXX fix enum MovementReason { Other, Key, Mouse }; MovementReason moveReason; int buffer; @@ -1431,9 +1430,7 @@ void QFxListView::itemResized() Q_D(QFxListView); QFxItem *item = qobject_cast(sender()); if (item) { - d->activeItem = item; // Ick - don't delete the sender d->layout(); - d->activeItem = 0; d->fixupPosition(); } } @@ -1642,33 +1639,66 @@ void QFxListView::destroyRemoved() void QFxListView::itemsMoved(int from, int to, int count) { - qWarning() << "ListView does not support moving in models"; - Q_D(QFxListView); - int fromCount = count; - int toCount = count; - bool fromVisible = d->mapRangeFromModel(from, fromCount); - bool toVisible = d->mapRangeFromModel(to, toCount); - - if (!fromVisible && !toVisible) { - // The items are outside the visible range. - if (d->visibleItems.count()) - d->visibleIndex = -1; - for (int i = 0; i < d->visibleItems.count(); ++i) { - FxListItem *listItem = d->visibleItems.at(i); - if (listItem->index != -1) { - listItem->index = d->model->indexOf(listItem->item, this); - if (d->visibleIndex < 0) - d->visibleIndex = listItem->index; + QHash moved; + int moveBy = 0; + + QList::Iterator it = d->visibleItems.begin(); + while (it != d->visibleItems.end()) { + FxListItem *item = *it; + if (item->index >= from && item->index < from + count) { + // take the items that are moving + item->index += (to-from); + moved.insert(item->index, item); + moveBy += item->size(); + it = d->visibleItems.erase(it); + } else { + if (item->index > from && item->index != -1) { + // move everything after the moved items. + item->index -= count; + item->setPosition(item->position()-moveBy); } + ++it; } - if (d->currentItem) { - d->currentItem->index = d->model->indexOf(d->currentItem->item, this); - d->currentIndex = d->currentItem->index; + } + + int remaining = count; + int endIndex = d->visibleIndex; + it = d->visibleItems.begin(); + while (it != d->visibleItems.end()) { + FxListItem *item = *it; + if (remaining && item->index >= to && item->index < to + count) { + // place items in the target position, reusing any existing items + FxListItem *movedItem = moved.take(item->index); + if (!movedItem) + movedItem = d->createItem(item->index); + it = d->visibleItems.insert(it, movedItem); + ++it; + --remaining; + } else { + if (item->index != -1) { + if (item->index >= to) { + // update everything after the moved items. + item->index += count; + } + endIndex = item->index; + } + ++it; } - return; } + // If we have moved items to the end of the visible items + // then add any existing moved items that we have + while (FxListItem *item = moved.take(endIndex+1)) { + d->visibleItems.append(item); + ++endIndex; + } + + // Whatever moved items remain are no longer visible items. + while (moved.count()) + d->releaseItem(moved.take(moved.begin().key())); + + d->layout(); } void QFxListView::createdItem(int index, QFxItem *item) diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp index cac8b8d..30879a2 100644 --- a/src/declarative/fx/qfxvisualitemmodel.cpp +++ b/src/declarative/fx/qfxvisualitemmodel.cpp @@ -695,7 +695,8 @@ QFxVisualDataModel::ReleaseFlags QFxVisualDataModel::release(QFxItem *item) if (inPackage) emit destroyingPackage(qobject_cast(obj)); stat |= Destroyed; - delete obj; + obj->setParent(0); + obj->deleteLater(); } else if (!inPackage) { stat |= Referenced; } @@ -916,6 +917,22 @@ void QFxVisualDataModel::_q_itemsMoved(int from, int to, int count) ++iter; } } + for (QHash::Iterator iter = d->m_cache.begin(); + iter != d->m_cache.end(); ) { + + if (iter.key() >= qMin(from,to) && iter.key() < qMax(from+count,to+count)) { + QFxVisualDataModelPrivate::ObjectRef objRef = *iter; + int index = iter.key() + from - to; + iter = d->m_cache.erase(iter); + + items.insert(index, objRef); + + QFxVisualDataModelData *data = d->data(objRef.obj); + data->setIndex(index); + } else { + ++iter; + } + } d->m_cache.unite(items); emit itemsMoved(from, to, count); diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index 19499a1..345bc3b 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -497,7 +497,7 @@ void QmlListModel::insert(int index, const QScriptValue& valuemap) */ void QmlListModel::move(int from, int to, int n) { - if (from+n > count() || to+n > count() || n==0 || from==to) + if (from+n > count() || to+n > count() || n==0 || from==to || from < 0 || to < 0) return; if (from > to) { // Only move forwards - flip if backwards moving -- cgit v0.12 From 804c9ef64085fafe6f12b92e5dd40e595ed3460f Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 11 Sep 2009 10:08:06 +1000 Subject: Handle itemsMoved() in GridView. --- src/declarative/fx/qfxgridview.cpp | 63 ++++++++++++++++++++++++++++++++++++++ src/declarative/fx/qfxgridview.h | 1 + 2 files changed, 64 insertions(+) diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp index dfb04ad..f49375a 100644 --- a/src/declarative/fx/qfxgridview.cpp +++ b/src/declarative/fx/qfxgridview.cpp @@ -723,6 +723,7 @@ void QFxGridView::setModel(const QVariant &model) if (d->model) { disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int))); disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int))); + disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int))); disconnect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*))); disconnect(d->model, SIGNAL(destroyingItem(QFxItem*)), this, SLOT(destroyingItem(QFxItem*))); } @@ -751,6 +752,7 @@ void QFxGridView::setModel(const QVariant &model) d->updateCurrent(d->currentIndex); connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int))); connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int))); + connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int))); connect(d->model, SIGNAL(createdItem(int, QFxItem*)), this, SLOT(createdItem(int,QFxItem*))); connect(d->model, SIGNAL(destroyingItem(QFxItem*)), this, SLOT(destroyingItem(QFxItem*))); refill(); @@ -1356,6 +1358,67 @@ void QFxGridView::destroyRemoved() d->layout(); } +void QFxGridView::itemsMoved(int from, int to, int count) +{ + Q_D(QFxGridView); + QHash moved; + + QList::Iterator it = d->visibleItems.begin(); + while (it != d->visibleItems.end()) { + FxGridItem *item = *it; + if (item->index >= from && item->index < from + count) { + // take the items that are moving + item->index += (to-from); + moved.insert(item->index, item); + it = d->visibleItems.erase(it); + } else { + if (item->index > from && item->index != -1) { + // move everything after the moved items. + item->index -= count; + } + ++it; + } + } + + int remaining = count; + int endIndex = d->visibleIndex; + it = d->visibleItems.begin(); + while (it != d->visibleItems.end()) { + FxGridItem *item = *it; + if (remaining && item->index >= to && item->index < to + count) { + // place items in the target position, reusing any existing items + FxGridItem *movedItem = moved.take(item->index); + if (!movedItem) + movedItem = d->createItem(item->index); + it = d->visibleItems.insert(it, movedItem); + ++it; + --remaining; + } else { + if (item->index != -1) { + if (item->index >= to) { + // update everything after the moved items. + item->index += count; + } + endIndex = item->index; + } + ++it; + } + } + + // If we have moved items to the end of the visible items + // then add any existing moved items that we have + while (FxGridItem *item = moved.take(endIndex+1)) { + d->visibleItems.append(item); + ++endIndex; + } + + // Whatever moved items remain are no longer visible items. + while (moved.count()) + d->releaseItem(moved.take(moved.begin().key())); + + d->layout(); +} + void QFxGridView::createdItem(int index, QFxItem *item) { Q_D(QFxGridView); diff --git a/src/declarative/fx/qfxgridview.h b/src/declarative/fx/qfxgridview.h index 954f9fe..734039c 100644 --- a/src/declarative/fx/qfxgridview.h +++ b/src/declarative/fx/qfxgridview.h @@ -130,6 +130,7 @@ private Q_SLOTS: void trackedPositionChanged(); void itemsInserted(int index, int count); void itemsRemoved(int index, int count); + void itemsMoved(int from, int to, int count); void destroyRemoved(); void createdItem(int index, QFxItem *item); void destroyingItem(QFxItem *item); -- cgit v0.12