aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den-exter@nokia.com>2011-06-27 10:58:18 +1000
committerAndrew den Exter <andrew.den-exter@nokia.com>2011-06-27 10:58:18 +1000
commit136c84811acda766182e55cd69a5a17b90b7c0c9 (patch)
tree500f5dfd9a85835d7b4cdc141284ef3ee9f26ed1
parent7f967bccc3e996ef5fd13271366a5e48dd03e19e (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.qml217
-rw-r--r--examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml17
-rw-r--r--src/declarative/items/qsglistview.cpp7
-rw-r--r--src/declarative/items/qsgvisualitemmodel.cpp116
-rw-r--r--src/declarative/items/qsgvisualitemmodel_p.h17
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;