diff options
author | Andrew den Exter <andrew.den-exter@nokia.com> | 2011-06-27 10:58:18 +1000 |
---|---|---|
committer | Andrew den Exter <andrew.den-exter@nokia.com> | 2011-06-27 10:58:18 +1000 |
commit | 136c84811acda766182e55cd69a5a17b90b7c0c9 (patch) | |
tree | 500f5dfd9a85835d7b4cdc141284ef3ee9f26ed1 | |
parent | 7f967bccc3e996ef5fd13271366a5e48dd03e19e (diff) |
Add a take function to VisualModel.
Allows a delegate item to be removed from a view and positioned
independently of the view.
-rw-r--r-- | examples/declarative/modelviews/visualdatamodel/Bubble.qml | 217 | ||||
-rw-r--r-- | examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml | 17 | ||||
-rw-r--r-- | src/declarative/items/qsglistview.cpp | 7 | ||||
-rw-r--r-- | src/declarative/items/qsgvisualitemmodel.cpp | 116 | ||||
-rw-r--r-- | src/declarative/items/qsgvisualitemmodel_p.h | 17 |
5 files changed, 225 insertions, 149 deletions
diff --git a/examples/declarative/modelviews/visualdatamodel/Bubble.qml b/examples/declarative/modelviews/visualdatamodel/Bubble.qml index 5f36a9a979..870533ff85 100644 --- a/examples/declarative/modelviews/visualdatamodel/Bubble.qml +++ b/examples/declarative/modelviews/visualdatamodel/Bubble.qml @@ -1,156 +1,143 @@ import QtQuick 2.0 -Item { - id: bubble +Rectangle { + id: content - width: 480 - height: content.height + property int contentHeight: height - senderText.implicitHeight + 2 - property int contentHeight: content.height - senderText.implicitHeight + 2 + x: 1; + width: 477 + height: Math.max(messageText.implicitHeight, 48) + senderText.implicitHeight + 6 - Rectangle { - id: content + border.width: 1 + border.color: "#404040" + color: outbound ? "#202020" : "#313131" - x: 1; - width: 477 - height: Math.max(messageText.implicitHeight, 48) + senderText.implicitHeight + 6 + state: delegateState - border.width: 1 - border.color: "#404040" - color: outbound ? "#202020" : "#313131" + Item { + id: avatarItem - state: delegateState + width: 48; height: 48 - Item { - id: avatarItem - - width: 48; height: 48 - - anchors { - left: outbound ? undefined : parent.left; right: outbound ? parent.right: undefined - top: parent.top - leftMargin: 3; topMargin: 3; rightMargin: 2 - } + anchors { + left: outbound ? undefined : parent.left; right: outbound ? parent.right: undefined + top: parent.top + leftMargin: 3; topMargin: 3; rightMargin: 2 + } - Image { - id: avatarImage - height: 48 - anchors.centerIn: parent - sourceSize.width: 48 + Image { + id: avatarImage + height: 48 + anchors.centerIn: parent + sourceSize.width: 48 - source: avatar != "" ? avatar : "images/face-smile.png" - } + source: avatar != "" ? avatar : "images/face-smile.png" + } - Component { - id: sendComponent + Component { + id: sendComponent - Rectangle { - id: sendButton - anchors { fill: parent; rightMargin: 1; bottomMargin: 1 } + Rectangle { + id: sendButton + anchors { fill: parent; rightMargin: 1; bottomMargin: 1 } - color: "#202020" + color: "#202020" - opacity: sendArea.pressed ? 0.5 : 1.0 + opacity: sendArea.pressed ? 0.5 : 1.0 - Behavior on opacity { NumberAnimation { duration: 150 } } + Behavior on opacity { NumberAnimation { duration: 150 } } - Rectangle { - anchors.fill: parent - radius: 4 - color: "#080808" - } + Rectangle { + anchors.fill: parent + radius: 4 + color: "#080808" + } - Text { - id: sendText - anchors.fill: parent - text: "Send" + Text { + id: sendText + anchors.fill: parent + text: "Send" - color: "#FFFFFF" - font.pixelSize: 16 - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - } + color: "#FFFFFF" + font.pixelSize: 16 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } - MouseArea { - id: sendArea + MouseArea { + id: sendArea - anchors.fill: parent + anchors.fill: parent - onClicked: root.send(editorLoader.item.text) - } + onClicked: root.send(editorLoader.item.text) } } + } - Loader { - id: sendLoader - anchors.fill: parent - } + Loader { + id: sendLoader + anchors.fill: parent } + } - Text { - id: messageText + Text { + id: messageText - anchors { - left: outbound ? parent.left : avatarItem.right; top: parent.top - right: outbound ? avatarItem.left : parent.right; margins: 2 - } - color: "#FFFFFF" - font.pixelSize: 18 - wrapMode: Text.WordWrap - text: message + anchors { + left: outbound ? parent.left : avatarItem.right; top: parent.top + right: outbound ? avatarItem.left : parent.right; margins: 2 } + color: "#FFFFFF" + font.pixelSize: 18 + wrapMode: Text.WordWrap + text: message + } - Component { - id: editorComponent + Component { + id: editorComponent - TextEdit { - color: "#FFFFFF" - font.pixelSize: 18 - wrapMode: Text.WordWrap - focus: true + TextEdit { + color: "#FFFFFF" + font.pixelSize: 18 + wrapMode: Text.WordWrap + focus: true - Keys.onReturnPressed: root.send(text) - Keys.onEnterPressed: root.send(text) - } + Keys.onReturnPressed: root.send(text) + Keys.onEnterPressed: root.send(text) } + } - Loader { - id: editorLoader - anchors.fill: messageText - } + Loader { + id: editorLoader + anchors.fill: messageText + } - Text { - id: senderText - anchors { left: parent.left; bottom: parent.bottom; margins: 2 } - color: "#DDDDDD" - font.pixelSize: 12 - text: sender - } + Text { + id: senderText + anchors { left: parent.left; bottom: parent.bottom; margins: 2 } + color: "#DDDDDD" + font.pixelSize: 12 + text: sender + } - Text { - id: timeText - anchors { right: parent.right; bottom: parent.bottom; margins: 2 } - color: "#DDDDDD" - font.pixelSize: 12 - text: time - } + Text { + id: timeText + anchors { right: parent.right; bottom: parent.bottom; margins: 2 } + color: "#DDDDDD" + font.pixelSize: 12 + text: time + } - states: State { - name: "composing" + states: State { + name: "composing" - ParentChange { target: content; parent: composer; x: 0; y: 0 } - PropertyChanges { target: bubble; height: 0 } - PropertyChanges { target: editorLoader; sourceComponent: editorComponent } - PropertyChanges { target: sendLoader; sourceComponent: sendComponent } - } + PropertyChanges { target: editorLoader; sourceComponent: editorComponent } + PropertyChanges { target: sendLoader; sourceComponent: sendComponent } + } - transitions: Transition { - from: "composing" - NumberAnimation { target: bubble; property: "height"; duration: 3000 } - ParentAnimation { - via: root - NumberAnimation { properties: "y"; duration: 3000; easing.type: Easing.InOutQuad } - } - } + transitions: Transition { + from: "composing" + NumberAnimation { target: sendLoader.item; property: "opacity"; to: 0.0; duration: 3000 } } } diff --git a/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml b/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml index 5198e11d8b..ece72198f2 100644 --- a/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml +++ b/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml @@ -10,8 +10,6 @@ Rectangle { property int messageCounter: 0 function send(message) { - - messageView.positionViewAtEnd() messageModel.set(messageModel.count - 1, { "sender": root.sender, "message": message, @@ -20,7 +18,9 @@ Rectangle { "time": Qt.formatTime(Date.now()), "delegateState": "" }) + visualModel.insert(visualModel.count, messageBubble) newMessage() + messageView.positionViewAtEnd() } function newMessage() { @@ -32,7 +32,9 @@ Rectangle { "time": "", "delegateState": "composing" }) - messageBubble = visualModel.item(visualModel.count - 1) + var bubble = visualModel.take(visualModel.count - 1, composer) + messageBubble = bubble + messageBubble.y = 0 // Override the position set by the view. } Component.onCompleted: newMessage() @@ -60,6 +62,13 @@ Rectangle { model: ListModel { id: messageModel } delegate: Bubble {} } + + add: Transition { + ParentAnimation { + via: root + NumberAnimation { properties: "y"; duration: 3000; easing.type: Easing.InOutQuad } + } + } } Timer { @@ -86,7 +95,7 @@ Rectangle { Item { id: composer - height: messageBubble != undefined ? messageBubble.contentHeight : 0 + height: messageBubble != undefined ? messageBubble.contentHeight : 48 anchors { left: parent.left; right: parent.right; bottom: parent.bottom } } } diff --git a/src/declarative/items/qsglistview.cpp b/src/declarative/items/qsglistview.cpp index 4cd4625923..abd1a59eed 100644 --- a/src/declarative/items/qsglistview.cpp +++ b/src/declarative/items/qsglistview.cpp @@ -751,9 +751,8 @@ FxListItemSG *QSGListViewPrivate::createItem(int modelIndex) listItem->item->setZ(1); listItem->item->setParentItem(q->contentItem()); model->completeItem(); - } else { - if (!item->parentItem()) - listItem->item->setParentItem(q->contentItem()); + } else if (!addTransitionComponent || !item->parentItem()) { + listItem->item->setParentItem(q->contentItem()); } QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item); itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry); @@ -2967,8 +2966,6 @@ void QSGListView::itemsInserted(int modelIndex, int count) transition->addItem(item, item->positionIfMovedTo(pos, true), contentItem()); d->indexesInTransition.insert(item->index); } else { - if (item->item->parentItem() != contentItem()) - item->item->setParentItem(contentItem()); item->setPosition(pos); } added.append(item); diff --git a/src/declarative/items/qsgvisualitemmodel.cpp b/src/declarative/items/qsgvisualitemmodel.cpp index 66d1a34876..e2f7fd84c1 100644 --- a/src/declarative/items/qsgvisualitemmodel.cpp +++ b/src/declarative/items/qsgvisualitemmodel.cpp @@ -205,15 +205,25 @@ public: } void invalidateIndexes(int start, int end = INT_MAX) { - foreach (const Item &item, children) { - QSGVisualModelAttached *attached = QSGVisualModelAttached::properties(item.item); - if (attached->m_index >= start && attached->m_index < end) - attached->setIndex(-1); + for (QSGVisualModelAttached::List::iterator it = attachedItems.begin(); it != attachedItems.end(); ++it) { + if (it->m_index >= start && it->m_index < end) + it->setIndex(-1); } - for (QHash<QSGItem *, QSGVisualData *>::iterator it = itemModels.begin(); it != itemModels.end(); ++it) { - QSGVisualModelAttached *attached = QSGVisualModelAttached::properties(it.key()); - if (attached->m_index >= start && attached->m_index < end) - attached->setIndex(-1); + } + + void removeIndexes(int start, int count) { + for (QSGVisualModelAttached::List::iterator it = attachedItems.begin(); it != attachedItems.end();) { + if (it->m_index >= start) { + it->setIndex(-1); + if (it->m_index < start + count) { + it->setModel(0); + it = it.erase(); + } else { + ++it; + } + } else { + ++it; + } } } @@ -229,9 +239,10 @@ public: }; QList<Item> children; - QHash<QSGItem *, QSGVisualData *> itemModels; QHash<QSGItem *, int> removedItems; + QSGVisualModelAttached::List attachedItems; QDeclarativeChangeSet transactionChanges; + QDeclarativeGuard<QDeclarativeContext> context; QSGVisualData *pendingModel; QSGVisualModelParts *parts; @@ -353,8 +364,9 @@ QSGItem *QSGVisualModel::item(int index, const QByteArray &viewId, bool complete QSGItem *item = model->item(range.index + offset, viewId, complete); QSGVisualModelAttached *attached = QSGVisualModelAttached::properties(item); attached->setModel(this); + attached->setData(model); attached->setIndex(index); - d->itemModels.insert(item, model); + d->attachedItems.insert(attached); if (model->completePending()) d->pendingModel = model; return item; @@ -370,14 +382,22 @@ QSGItem *QSGVisualModel::item(int index) return item(index, QByteArray()); } +QSGItem *QSGVisualModel::take(int index, QSGItem *parent) +{ + Q_D(QSGVisualModel); + QSGItem *i = item(index); + remove(index, 1); + i->setParentItem(parent); + + return i; +} + QSGVisualModel::ReleaseFlags QSGVisualModel::release(QSGItem *item) { Q_D(QSGVisualModel); - if (QSGVisualData *model = d->itemModels.value(item)) { - ReleaseFlags flags = model->release(item); - if (flags) - d->itemModels.remove(item); - return flags; + QSGVisualModelAttached *attached = QSGVisualModelAttached::properties(item); + if (QSGVisualData *model = attached->m_data) { + return model->release(item); } else { int idx = d->indexOf(item); if (idx >= 0) { @@ -425,7 +445,8 @@ QString QSGVisualModel::stringValue(int index, const QString &name) int QSGVisualModel::indexOf(QSGItem *item, QObject *context) const { Q_D(const QSGVisualModel); - if (QSGVisualData *model = d->itemModels.value(item)) { + QSGVisualModelAttached *attached = QSGVisualModelAttached::properties(item); + if (QSGVisualData *model = attached->m_data) { int modelIndex = model->indexOf(item, context); return modelIndex != -1 ? d->absoluteIndexOf(model, modelIndex) : modelIndex; } else { @@ -460,7 +481,21 @@ void QSGVisualModel::append(QSGItem *item) { Q_D(QSGVisualModel); int index = d->count(); - if (d->appendData(item)) { + QSGVisualModelAttached *attached = QSGVisualModelAttached::properties(item); + bool inserted = false; + if (attached->m_data) { + QSGVisualData *model = attached->m_data; + int modelIndex = model->indexOf(item, 0); + if (modelIndex != -1) { + d->appendList(model, modelIndex, 1, false); + d->connectModel(model); + inserted = true; + } + } else if (d->appendData(item)) { + d->attachedItems.insert(attached); + inserted = true; + } + if (inserted) { QSGVisualModelAttached *attached = QSGVisualModelAttached::properties(item); attached->setModel(this); attached->setIndex(count() - 1); @@ -508,8 +543,21 @@ void QSGVisualModel::append(QSGVisualModel *sourceModel, int sourceIndex, int co void QSGVisualModel::insert(int index, QSGItem *item) { Q_D(QSGVisualModel); - if (d->insertData(index, item)) { - QSGVisualModelAttached *attached = QSGVisualModelAttached::properties(item); + QSGVisualModelAttached *attached = QSGVisualModelAttached::properties(item); + bool inserted = false; + if (attached->m_data) { + QSGVisualData *model = attached->m_data; + int modelIndex = model->indexOf(item, 0); + if (modelIndex != -1) { + d->insertList(index, model, modelIndex, 1, false); + d->connectModel(model); + inserted = true; + } + } else if (d->insertData(index, item)) { + d->attachedItems.insert(attached); + inserted = true; + } + if (inserted) { attached->setModel(this); attached->setIndex(index); d->invalidateIndexes(index); @@ -562,7 +610,7 @@ void QSGVisualModel::remove(int index, int count) if (!d->transaction) d->childrenChanged = false; d->removeAt(index, count); - d->invalidateIndexes(index); + d->removeIndexes(index, count); if (d->transaction) { d->transactionChanges.insertRemove(index, index + count); } else { @@ -1670,6 +1718,34 @@ QVariant QSGVisualDataModel::parentModelIndex() const return d->data->parentModelIndex(); } +QSGVisualPartModel::QSGVisualPartModel(QSGVisualModel *model, const QByteArray &part, QObject *parent) + : QObject(parent), m_model(model), m_part(part) +{ +} + +QSGVisualModel *QSGVisualPartModel::model() const +{ + return m_model; +} + +QByteArray QSGVisualPartModel::part() const +{ + return m_part; +} + +QSGItem *QSGVisualPartModel::item(int index) +{ + return m_model->item(index, m_part); +} + +QSGItem *QSGVisualPartModel::take(int index, QSGItem *parent) +{ + QSGItem *item = m_model->item(index, m_part); + m_model->remove(index, 1); + item->setParentItem(parent); + return item; +} + QT_END_NAMESPACE #include <qsgvisualitemmodel.moc> diff --git a/src/declarative/items/qsgvisualitemmodel_p.h b/src/declarative/items/qsgvisualitemmodel_p.h index 966246b52b..4267f01fe1 100644 --- a/src/declarative/items/qsgvisualitemmodel_p.h +++ b/src/declarative/items/qsgvisualitemmodel_p.h @@ -50,6 +50,7 @@ #include <QtScript/qscriptvalue.h> #include <private/qdeclarativeguard_p.h> +#include <private/qintrusivelist_p.h> QT_BEGIN_HEADER @@ -106,6 +107,7 @@ public: static QSGVisualModelAttached *qmlAttachedProperties(QObject *obj); Q_INVOKABLE QSGItem *item(int index); + Q_INVOKABLE QSGItem *take(int index, QSGItem *parent = 0); public Q_SLOTS: void append(QSGItem *item); @@ -234,6 +236,7 @@ public: } void setModel(QSGVisualModel *model) { m_model = model; } + void setData(QSGVisualData *data) { m_data = data; } static QSGVisualModelAttached *properties(QObject *obj) { QSGVisualModelAttached *rv = attachedProperties.value(obj); @@ -250,6 +253,10 @@ Q_SIGNALS: public: int m_index; QDeclarativeGuard<QSGVisualModel> m_model; + QDeclarativeGuard<QSGVisualData> m_data; + QIntrusiveListNode m_node; + + typedef QIntrusiveList<QSGVisualModelAttached, &QSGVisualModelAttached::m_node> List; static QHash<QObject*, QSGVisualModelAttached*> attachedProperties; }; @@ -304,13 +311,13 @@ class Q_DECLARATIVE_EXPORT QSGVisualPartModel : public QObject { Q_OBJECT public: - QSGVisualPartModel(QSGVisualModel *model, const QByteArray &part, QObject *parent = 0) - : QObject(parent), m_model(model), m_part(part) {} + QSGVisualPartModel(QSGVisualModel *model, const QByteArray &part, QObject *parent = 0); - QSGVisualModel *model() const { return m_model; } - QByteArray part() const { return m_part; } + QSGVisualModel *model() const; + QByteArray part() const; - Q_INVOKABLE QSGItem *item(int index) { return m_model->item(index, m_part); } + Q_INVOKABLE QSGItem *item(int index); + Q_INVOKABLE QSGItem *take(int index, QSGItem *parent = 0); private: QSGVisualModel *m_model; |