From f017b9fbcdb31ad5b175024bc0469cc2cac3a8a8 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 30 Jun 2011 14:21:22 +1000 Subject: Fix issues in merge operation. Provide a way for internal items to be merged if possible, and correctly remove the from item from the composite list. --- .../modelviews/visualdatamodel/visualdatamodel.qml | 2 +- src/declarative/items/qsgvisualitemmodel.cpp | 42 ++++++++++-- .../util/qdeclarativelistcompositor.cpp | 78 +++++++++++++++++----- .../util/qdeclarativelistcompositor_p.h | 5 +- 4 files changed, 102 insertions(+), 25 deletions(-) diff --git a/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml b/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml index 0374ac9da6..38f1e12604 100644 --- a/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml +++ b/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml @@ -76,7 +76,7 @@ Rectangle { var message = visualModel.get(j) if (!message.outbound) continue; - for (var k = inserts[i].start - 1 - delta; k >= 0; ++k) { + for (var k = inserts[i].start - 1 - delta; k >= 0; --k) { var existing = visualModel.get(k); if (!existing.outbound) continue; diff --git a/src/declarative/items/qsgvisualitemmodel.cpp b/src/declarative/items/qsgvisualitemmodel.cpp index feecbe5b92..2447814565 100644 --- a/src/declarative/items/qsgvisualitemmodel.cpp +++ b/src/declarative/items/qsgvisualitemmodel.cpp @@ -347,6 +347,9 @@ protected: *t = *f; } } + + bool mergeInternalData(int from, int to); + bool mergeInternalData(int internalIndex, void *list, int index); }; class QSGVisualDataParts; @@ -497,6 +500,7 @@ public: } QSGVisualData *model() const { return m_model; } + void setModel(QSGVisualData *model, int index); QDeclarativeComponent *delegate() const { return m_delegate; } void ensureProperties(); @@ -532,6 +536,23 @@ QSGVisualModelData *QSGVisualModelPrivate::createScriptData(QDeclarativeComponen return data; } + +bool QSGVisualModelPrivate::mergeInternalData(int internalIndex, void *list, int index) +{ + if (children[internalIndex].data) + children[internalIndex].data->setModel(static_cast(list), index); + return true; +} + +bool QSGVisualModelPrivate::mergeInternalData(int from, int to) +{ + Q_UNUSED(to); + if (children[to].data && children[from].data) + children[to].data->setModel(children[from].data->model(), children[from].data->index()); + removeInternalData(from, 1); + return true; +} + QSGVisualModel::QSGVisualModel(QObject *parent) : QObject(*(new QSGVisualModelPrivate), parent) { @@ -1019,14 +1040,17 @@ void QSGVisualModel::merge(int from, int to) return; if (!d->transaction) d->childrenChanged = false; - if (!d->merge(from, to)) { + int internalIndex = d->merge(from, to); + if (internalIndex == -1) { qmlInfo(this) << "Items cannot be merged" << from << to; - } else if (d->transaction) { - d->transactionChanges.insertRemove(from, 1); } else { - emit itemsRemoved(from, 1); - if (d->childrenChanged) - emit childrenChanged(); + if (d->transaction) { + d->transactionChanges.insertRemove(from, from + 1); + } else { + emit itemsRemoved(from, 1); + if (d->childrenChanged) + emit childrenChanged(); + } } } @@ -1280,6 +1304,12 @@ void QSGVisualModelData::setIndex(int index) emit indexChanged(); } +void QSGVisualModelData::setModel(QSGVisualData *model, int index) +{ + m_model = model; + m_index = index; + emit indexChanged(); +} //--------------------------------------------------------------------------- diff --git a/src/declarative/util/qdeclarativelistcompositor.cpp b/src/declarative/util/qdeclarativelistcompositor.cpp index b081549e59..6fba99fb99 100644 --- a/src/declarative/util/qdeclarativelistcompositor.cpp +++ b/src/declarative/util/qdeclarativelistcompositor.cpp @@ -521,7 +521,7 @@ void QDeclarativeListCompositor::move(int from, int to, int count) Q_ASSERT(qt_verifyIntegrity(ranges, absoluteCount, internalCount)); } -bool QDeclarativeListCompositor::merge(int from, int to) +int QDeclarativeListCompositor::merge(int from, int to) { int internalIndex = 0; int internalFrom = 0; @@ -544,8 +544,10 @@ bool QDeclarativeListCompositor::merge(int from, int to) internalFrom = internalIndex; if (range->internal()) internalFrom += relativeFrom; - relativeTo -= from - relativeFrom; - internalIndex -= 1; + if (from > to) + relativeTo -= to - relativeFrom; + else + relativeTo -= from - relativeFrom; break; } if (range->internal()) @@ -575,16 +577,44 @@ bool QDeclarativeListCompositor::merge(int from, int to) if (fromRange == ranges.end() || toRange == ranges.end() - || fromRange->list - || !toRange->list - || toRange->internal()) { - return false; + || (!fromRange->internal() && !toRange->internal()) + || (fromRange->list && toRange->list)) { + return -1; + } else if (fromRange->internal() && toRange->internal()) { + if (!mergeInternalData(internalFrom, internalTo)) + return -1; + } else if (fromRange->internal()) { + if (!mergeInternalData(internalTo, toRange->list, toRange->index + relativeTo)) + return -1; + } else if (toRange->internal()) { + if (!mergeInternalData(internalTo, fromRange->list, fromRange->index + relativeFrom)) + return -1; } - fromRange->count -= 1; + void *toList = fromRange->list; + int toIndex = fromRange->index + relativeFrom; - if (fromRange->count == 0) - ranges.erase(fromRange); + fromRange->count -= 1; + int removeFrom = fromRange->index + relativeFrom; + if (relativeFrom > 0) { + int splitOffset = relativeFrom; + if (fromRange->list) + splitOffset += 1; + if (splitOffset < fromRange->count) { + fromRange = insert(fromRange, QDeclarativeCompositeRange( + fromRange->list, fromRange->index, relativeFrom, fromRange->flags & ~Append)); + fromRange->index += splitOffset; + fromRange->count -= splitOffset; + } else { + fromRange->index += relativeFrom; + } + } else if (fromRange->list) { + fromRange->index += 1; + } + if (fromRange->prepend()) { + fromRange = insert(fromRange, QDeclarativeCompositeRange( + fromRange->list, removeFrom, 1, Null | Prepend)); + } if (relativeTo > 0) { toRange = ++ranges.insert(toRange, QDeclarativeCompositeRange( @@ -595,19 +625,25 @@ bool QDeclarativeListCompositor::merge(int from, int to) if (toRange->count == 1 && !toRange->append()) { toRange->flags |= Internal; + if (!toRange->list) { + toRange->list = toList; + toRange->index = toIndex; + } } else { - toRange = ++ranges.insert(toRange, QDeclarativeCompositeRange( - toRange->list, toRange->index, 1, (toRange->flags | Internal) & ~Append)); + if (toRange->list) { + toRange = ++ranges.insert(toRange, QDeclarativeCompositeRange( + toRange->list, toRange->index, 1, (toRange->flags | Internal) & ~Append)); + } else { + toRange = ++ranges.insert(toRange, QDeclarativeCompositeRange( + toList, toIndex, 1, Internal)); + } toRange->index += 1; toRange->count -= 1; } - if (internalFrom != internalTo) - moveInternalData(internalFrom, internalTo, 1); - absoluteCount -= 1; - return true; + return internalTo; } void QDeclarativeListCompositor::clear() @@ -985,6 +1021,16 @@ void QDeclarativeListCompositor::listItemsChanged(void *list, int start, int end } } +bool QDeclarativeListCompositor::mergeInternalData(int, int) +{ + return false; +} + +bool QDeclarativeListCompositor::mergeInternalData(int, void *, int) +{ + return false; +} + void QDeclarativeListCompositor::compress() { } diff --git a/src/declarative/util/qdeclarativelistcompositor_p.h b/src/declarative/util/qdeclarativelistcompositor_p.h index 2d2123ad8c..e3220f1466 100644 --- a/src/declarative/util/qdeclarativelistcompositor_p.h +++ b/src/declarative/util/qdeclarativelistcompositor_p.h @@ -106,7 +106,7 @@ public: void removeAt(int index, int count); void removeList(void *list, QVector *changes); void move(int from, int to, int count); - bool merge(int from, int to); + int merge(int from, int to); void clear(); void clearData(int internalIndex, int count); @@ -128,7 +128,8 @@ protected: virtual void replaceInternalData(int index, const void *data) = 0; virtual void removeInternalData(int index, int count) = 0; virtual void moveInternalData(int from, int to, int count) = 0; - + virtual bool mergeInternalData(int from, int to); + virtual bool mergeInternalData(int internalIndex, void *list, int range); private: int absoluteCount; -- cgit v1.2.3