aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den-exter@nokia.com>2011-06-29 16:45:21 +1000
committerAndrew den Exter <andrew.den-exter@nokia.com>2011-06-29 16:45:21 +1000
commitb961cb8f0d7d69c0343dd18a442be240fa178bf7 (patch)
treebaddd8a9034e190f871687fccc6e5ac0e98c06f9
parent8cf428d4ebd4c8c246806243730aad3a4f325300 (diff)
Add model data accessor and merge function to VisualModel.
This provides a way to find an override a tempory item when the real thing appears in the model data.
-rw-r--r--examples/declarative/modelviews/visualdatamodel/Bubble.qml36
-rw-r--r--examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml40
-rw-r--r--src/declarative/items/qsgvisualitemmodel.cpp45
-rw-r--r--src/declarative/items/qsgvisualitemmodel_p.h2
4 files changed, 110 insertions, 13 deletions
diff --git a/examples/declarative/modelviews/visualdatamodel/Bubble.qml b/examples/declarative/modelviews/visualdatamodel/Bubble.qml
index de2c80763f..da41af8a47 100644
--- a/examples/declarative/modelviews/visualdatamodel/Bubble.qml
+++ b/examples/declarative/modelviews/visualdatamodel/Bubble.qml
@@ -5,6 +5,11 @@ Rectangle {
property int contentHeight: height - senderText.implicitHeight - 2
+ function send() {
+ state = "sending"
+ root.sending()
+ }
+
x: 1;
width: 477
height: Math.max(messageText.implicitHeight, 48) + senderText.implicitHeight + 6
@@ -15,6 +20,12 @@ Rectangle {
state: delegateState
+ Timer {
+ id: sendTimer
+ interval: 1000
+ onTriggered: root.sent(messageId, sender, message, avatar)
+ }
+
Item {
id: avatarItem
@@ -70,7 +81,7 @@ Rectangle {
anchors.fill: parent
- onClicked: root.send(editorLoader.item.text)
+ onClicked: content.send()
}
}
}
@@ -103,8 +114,10 @@ Rectangle {
wrapMode: Text.WordWrap
focus: true
- Keys.onReturnPressed: root.send(text)
- Keys.onEnterPressed: root.send(text)
+ text: message
+
+ Keys.onReturnPressed: content.send()
+ Keys.onEnterPressed: content.send()
}
}
@@ -129,12 +142,19 @@ Rectangle {
text: time
}
- states: State {
- name: "composing"
+ states: [
+ State {
+ name: "composing"
+ PropertyChanges { target: editorLoader; sourceComponent: editorComponent }
+ PropertyChanges { target: sendLoader; sourceComponent: sendComponent }
+ },
+ State {
+ name: "sending"
+ PropertyChanges { target: editorLoader; sourceComponent: editorComponent }
+ PropertyChanges { target: sendTimer; running: true }
+ }
- PropertyChanges { target: editorLoader; sourceComponent: editorComponent }
- PropertyChanges { target: sendLoader; sourceComponent: sendComponent }
- }
+ ]
transitions: Transition {
from: "composing"
diff --git a/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml b/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml
index 4a3e511db2..0374ac9da6 100644
--- a/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml
+++ b/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml
@@ -9,14 +9,26 @@ Rectangle {
property string sender: "Me"
property int messageCounter: 0
- function send(message) {
+ function sending() {
visualModel.insert(visualModel.count, messageBubble)
newMessage()
messageView.positionViewAtEnd()
}
+ function sent(messageId, sender, message, avatar) {
+ messageModel.append({
+ "messageId": messageId,
+ "sender": sender,
+ "message": message,
+ "avatar": avatar,
+ "outbound": true,
+ "time": Qt.formatTime(Date.now()),
+ "delegateState": ""
+ })
+ }
+
function newMessage() {
- visualModel.appendData({})
+ visualModel.appendData({ "messageId": ++messageCounter })
var bubble = visualModel.take(visualModel.count - 1, composer)
messageBubble = bubble
messageBubble.y = 0 // Override the position set by the view.
@@ -45,6 +57,7 @@ Rectangle {
id: visualModel
roles: [
+ VisualRole { name: "messageId"; },
VisualRole { name: "sender"; defaultValue: root.sender },
VisualRole { name: "message"; defaultValue: "" },
VisualRole { name: "avatar"; defaultValue: "" },
@@ -55,6 +68,28 @@ Rectangle {
model: ListModel { id: messageModel }
delegate: Bubble {}
+
+ onUpdated: {
+ var delta = 0
+ for (var i = 0; i < inserts.length; ++i) {
+ for (var j = inserts[i].start - delta; j < inserts[i].end - delta; ++j) {
+ var message = visualModel.get(j)
+ if (!message.outbound)
+ continue;
+ for (var k = inserts[i].start - 1 - delta; k >= 0; ++k) {
+ var existing = visualModel.get(k);
+ if (!existing.outbound)
+ continue;
+ if (message.messageId == existing.messageId) {
+ visualModel.merge(j, k)
+ ++delta
+ --j
+ break;
+ }
+ }
+ }
+ }
+ }
}
// add: Transition {
@@ -73,6 +108,7 @@ Rectangle {
var message = script.get(scriptIndex);
messageModel.append({
+ "messageId": -1,
"sender": message.sender,
"message": message.message,
"avatar": message.avatar,
diff --git a/src/declarative/items/qsgvisualitemmodel.cpp b/src/declarative/items/qsgvisualitemmodel.cpp
index c2328e70e8..3a3b1596f8 100644
--- a/src/declarative/items/qsgvisualitemmodel.cpp
+++ b/src/declarative/items/qsgvisualitemmodel.cpp
@@ -73,11 +73,13 @@ QHash<QObject*, QSGVisualModelAttached*> QSGVisualModelAttached::attachedPropert
class VDMDelegateDataType : public QDeclarativeOpenMetaObjectType
{
public:
- VDMDelegateDataType(const QMetaObject *base, QDeclarativeEngine *engine) : QDeclarativeOpenMetaObjectType(base, engine) {}
+ VDMDelegateDataType(const QMetaObject *base, QDeclarativeEngine *engine) : QDeclarativeOpenMetaObjectType(base, engine), m_caching(false) {}
void propertyCreated(int, QMetaPropertyBuilder &prop) {
- prop.setWritable(false);
+ prop.setWritable(m_caching);
}
+
+ bool m_caching;
};
class QSGVisualModelPartsMetaObject : public QDeclarativeOpenMetaObject
@@ -400,6 +402,7 @@ public:
ensureRoles();
QHash<QByteArray, int> roleNames = m_roleNames;
QSGVisualModelPrivate *parent = QSGVisualModelPrivate::get(static_cast<QSGVisualModel *>(q_ptr->parent()));
+ m_delegateDataType->m_caching = true;
for (QList<QSGVisualModelRole *>::iterator it = parent->roles.begin(); it != parent->roles.end(); ++it) {
QByteArray name = (*it)->name().toUtf8();
int propId = m_delegateDataType->createProperty(name) - m_delegateDataType->propertyOffset();
@@ -409,7 +412,7 @@ public:
roleNames.erase(it);
}
}
-
+ m_delegateDataType->m_caching = false;
if (m_roleNames.count()) {
QHash<QByteArray, int>::const_iterator it = roleNames.begin();
@@ -514,6 +517,7 @@ QSGVisualModelData *QSGVisualModelPrivate::createScriptData(QDeclarativeComponen
delegateDataType = new VDMDelegateDataType(
&QSGVisualModelData::staticMetaObject,
context ? context->engine() : qmlEngine(q));
+ delegateDataType->m_caching = true;
for (QList<QSGVisualModelRole *>::iterator it = roles.begin(); it != roles.end(); ++it)
delegateDataType->createProperty((*it)->name().toUtf8());
}
@@ -655,6 +659,23 @@ QSGItem *QSGVisualModel::take(int index, QSGItem *parent)
return i;
}
+QScriptValue QSGVisualModel::get(int index)
+{
+ Q_D(QSGVisualModel);
+ QDeclarativeEngine *dengine = d->context ? d->context->engine() : qmlEngine(this);
+ QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(dengine);
+ int offset = 0;
+ int internalIndex = 0;
+ QDeclarativeCompositeRange range = d->at(index, &offset, &internalIndex);
+ if (range.internal()) {
+ return engine->newQObject(d->children[internalIndex].data);
+ } else {
+ return engine->newQObject(
+ new QSGVisualModelData(range.index + offset, static_cast<QSGVisualData *>(range.list)),
+ QScriptEngine::ScriptOwnership);
+ }
+}
+
QSGVisualModel::ReleaseFlags QSGVisualModel::release(QObject *object)
{
Q_D(QSGVisualModel);
@@ -989,6 +1010,24 @@ void QSGVisualModel::move(int from, int to, int count)
}
}
+void QSGVisualModel::merge(int from, int to)
+{
+ Q_D(QSGVisualModel);
+ if (from == to)
+ return;
+ if (!d->transaction)
+ d->childrenChanged = false;
+ if (!d->merge(from, to)) {
+ 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();
+ }
+}
+
void QSGVisualModel::_q_itemsInserted(QSGVisualData *model, int index, int count)
{
Q_D(QSGVisualModel);
diff --git a/src/declarative/items/qsgvisualitemmodel_p.h b/src/declarative/items/qsgvisualitemmodel_p.h
index d4a7084fa3..cc8a93c8d9 100644
--- a/src/declarative/items/qsgvisualitemmodel_p.h
+++ b/src/declarative/items/qsgvisualitemmodel_p.h
@@ -109,6 +109,7 @@ public:
static QSGVisualModelAttached *qmlAttachedProperties(QObject *obj);
+ Q_INVOKABLE QScriptValue get(int index);
Q_INVOKABLE QSGItem *item(int index, bool complete = true);
Q_INVOKABLE QSGItem *item(int index, const QByteArray &viewId, bool complete = true);
Q_INVOKABLE QSGItem *take(int index, QSGItem *parent = 0);
@@ -124,6 +125,7 @@ public Q_SLOTS:
void insert(int index, QDeclarativeComponent *delegate, const QScriptValue &data);
void remove(int index, int count);
void move(int from, int to, int count);
+ void merge(int from, int to);
Q_SIGNALS:
void childrenChanged();