From 0fc0e12b85f588644f0829494681ddefae77860f Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Mon, 18 Jan 2010 15:00:21 +1000 Subject: Doc. --- src/declarative/graphicsitems/qmlgraphicstext.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/declarative/graphicsitems/qmlgraphicstext.cpp b/src/declarative/graphicsitems/qmlgraphicstext.cpp index 84f925d..bfb928a 100644 --- a/src/declarative/graphicsitems/qmlgraphicstext.cpp +++ b/src/declarative/graphicsitems/qmlgraphicstext.cpp @@ -368,7 +368,7 @@ void QmlGraphicsText::setWrap(bool w) will automatically determine whether the text should be treated as rich text. This determination is made using Qt::mightBeRichText(). - StyledText is an optimized format able supporting some basic text + StyledText is an optimized format supporting some basic text styling markup, in the style of html 3.2: \code @@ -379,6 +379,8 @@ void QmlGraphicsText::setWrap(bool w) > < & \endcode + \c StyledText parser is strict, requiring tags to be correctly nested. + \table \row \o -- cgit v0.12 From ac90f1e7a4f06749f93b2b593fbf1b993d8af4c5 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 19 Jan 2010 10:30:53 +1000 Subject: Try again to make it compile on Symbian. --- .../graphicsitems/qmlgraphicspathview.cpp | 34 +++++++++++++++------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/declarative/graphicsitems/qmlgraphicspathview.cpp b/src/declarative/graphicsitems/qmlgraphicspathview.cpp index 2fc0dfb..112eda2 100644 --- a/src/declarative/graphicsitems/qmlgraphicspathview.cpp +++ b/src/declarative/graphicsitems/qmlgraphicspathview.cpp @@ -56,6 +56,18 @@ QT_BEGIN_NAMESPACE QML_DEFINE_TYPE(Qt,4,6,PathView,QmlGraphicsPathView) + +inline qreal qmlMod(qreal x, qreal y) +{ +#ifdef QT_USE_MATH_H_FLOATS + if(sizeof(qreal) == sizeof(float)) + return fmodf(float(x), float(y)); + else +#endif + return fmod(x, y); +} + + class QmlGraphicsPathViewAttached : public QObject { Q_OBJECT @@ -250,7 +262,7 @@ void QmlGraphicsPathViewPrivate::setOffset(qreal o) { Q_Q(QmlGraphicsPathView); if (_offset != o) { - _offset = fmod(o, qreal(100.0)); + _offset = qmlMod(o, qreal(100.0)); if (_offset < 0) _offset = 100.0 + _offset; q->refill(); @@ -450,8 +462,8 @@ void QmlGraphicsPathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *) velocity = 100; else if (velocity < -100) velocity = -100; - qreal inc = fmod(d->_offset - d->snapPos, qreal(100.0 / d->model->count())); - qreal dist = qAbs(velocity/2 - fmod(velocity/2, qreal(100.0 / d->model->count()) - inc)); + qreal inc = qmlMod(d->_offset - d->snapPos, qreal(100.0 / d->model->count())); + qreal dist = qAbs(velocity/2 - qmlMod(velocity/2, qreal(100.0 / d->model->count()) - inc)); d->moveOffset.setValue(d->_offset); d->tl.accel(d->moveOffset, velocity, 10, dist); d->tl.execute(d->fixupOffsetEvent); @@ -542,7 +554,7 @@ void QmlGraphicsPathView::componentComplete() itemIndex += d->pathOffset; itemIndex %= d->items.count(); - qreal targetOffset = fmod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0)); + qreal targetOffset = qmlMod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0)); if (targetOffset < 0) targetOffset = 100.0 + targetOffset; @@ -609,7 +621,7 @@ void QmlGraphicsPathView::refill() for (int i=0; iitems.count(); i++){ qreal percent = i * (100. / d->items.count()); percent = percent + d->_offset; - percent = fmod(percent, qreal(100.0)); + percent = qmlMod(percent, qreal(100.0)); positions << qAbs(percent/100.0); } @@ -696,7 +708,7 @@ void QmlGraphicsPathView::itemsInserted(int modelIndex, int count) int itemIndex = (d->currentIndex - d->firstIndex + d->model->count())%d->model->count(); itemIndex += d->pathOffset; itemIndex %= d->items.count(); - qreal targetOffset = fmod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0)); + qreal targetOffset = qmlMod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0)); if (targetOffset < 0) targetOffset = 100.0 + targetOffset; @@ -733,7 +745,7 @@ void QmlGraphicsPathView::itemsRemoved(int modelIndex, int count) int itemIndex = (d->currentIndex - d->firstIndex + d->model->count())%d->model->count(); itemIndex += d->pathOffset; itemIndex %= d->items.count(); - qreal targetOffset = fmod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0)); + qreal targetOffset = qmlMod(100 + (d->snapPos*100) - 100.0 * itemIndex / d->items.count(), qreal(100.0)); if (targetOffset < 0) targetOffset = 100.0 + targetOffset; @@ -766,12 +778,12 @@ int QmlGraphicsPathViewPrivate::calcCurrentIndex() { int current = -1; if (model && items.count()) { - _offset = fmod(_offset, qreal(100.0)); + _offset = qmlMod(_offset, qreal(100.0)); if (_offset < 0) _offset += 100.0; if (pathItems == -1) { - qreal delta = fmod(_offset - snapPos, qreal(100.0)); + qreal delta = qmlMod(_offset - snapPos, qreal(100.0)); if (delta < 0) delta = 100.0 + delta; int ii = model->count() - qRound(delta * model->count() / 100); @@ -784,7 +796,7 @@ int QmlGraphicsPathViewPrivate::calcCurrentIndex() for (int i=0; i Date: Tue, 19 Jan 2010 10:34:47 +1000 Subject: Allow the QML based file browser to be used in place of native. --- tools/qmlviewer/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/qmlviewer/main.cpp b/tools/qmlviewer/main.cpp index 8a5efa3..d170521 100644 --- a/tools/qmlviewer/main.cpp +++ b/tools/qmlviewer/main.cpp @@ -222,6 +222,8 @@ int main(int argc, char ** argv) translationFile = argv[++i]; } else if (arg == "-opengl") { useGL = true; + } else if (arg == "-qmlbrowser") { + useNativeFileBrowser = false; } else if (arg == "-L") { if (lastArg) usage(); libraries << QString(argv[++i]); -- cgit v0.12 From 123420ab170376cbd4e2e2c7676f383daa36bb95 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 19 Jan 2010 10:38:32 +1000 Subject: Doc. --- tools/qmlviewer/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/qmlviewer/main.cpp b/tools/qmlviewer/main.cpp index d170521..0a4537d 100644 --- a/tools/qmlviewer/main.cpp +++ b/tools/qmlviewer/main.cpp @@ -83,6 +83,7 @@ void usage() qWarning(" -skin ...................... run with a skin window frame"); qWarning(" \"list\" for a list of built-ins"); qWarning(" -resizeview .............................. resize the view, not the skin"); + qWarning(" -qmlbrowser .............................. use a QML-based file browser"); qWarning(" -recordfile ..................... set video recording file"); qWarning(" - ImageMagick 'convert' for GIF)"); qWarning(" - png file for raw frames"); -- cgit v0.12 From bc6940f53891856a3a6c3d8f1c25a8eaada90b33 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 19 Jan 2010 12:42:03 +1000 Subject: Fix to correctly return property values that are javascript arrays. --- src/declarative/util/qmllistmodel.cpp | 45 ++++++++++++---------- .../declarative/qmllistmodel/tst_qmllistmodel.cpp | 5 +++ 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index de6ee2e..cd4a120 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -265,6 +265,7 @@ struct ModelNode QmlListModel *modelCache; ModelObject *objectCache; + bool isArray; }; QT_END_NAMESPACE @@ -280,6 +281,7 @@ void ModelNode::setObjectValue(const QScriptValue& valuemap) { ModelNode *value = new ModelNode; QScriptValue v = it.value(); if (v.isArray()) { + value->isArray = true; value->setListValue(v); } else { value->values << v.toVariant(); @@ -296,6 +298,7 @@ void ModelNode::setListValue(const QScriptValue& valuelist) { ModelNode *value = new ModelNode; QScriptValue v = it.value(); if (v.isArray()) { + value->isArray = true; value->setListValue(v); } else if (v.isObject()) { value->setObjectValue(v); @@ -367,27 +370,29 @@ QVariant QmlListModel::valueForNode(ModelNode *node) const { QObject *rv = 0; - if (!node->properties.isEmpty()) { - // Object - rv = node->object(this); - } else if (node->values.count() == 0) { - // Invalid - return QVariant(); - } else if (node->values.count() == 1) { - // Value - QVariant &var = node->values[0]; - ModelNode *valueNode = qvariant_cast(var); - if (valueNode) { - if (!valueNode->properties.isEmpty()) - rv = valueNode->object(this); - else - rv = valueNode->model(this); - } else { - return var; - } - } else if (node->values.count() > 1) { + if (node->isArray) { // List rv = node->model(this); + } else { + if (!node->properties.isEmpty()) { + // Object + rv = node->object(this); + } else if (node->values.count() == 0) { + // Invalid + return QVariant(); + } else if (node->values.count() == 1) { + // Value + QVariant &var = node->values[0]; + ModelNode *valueNode = qvariant_cast(var); + if (valueNode) { + if (!valueNode->properties.isEmpty()) + rv = valueNode->object(this); + else + rv = valueNode->model(this); + } else { + return var; + } + } } if (rv) @@ -933,7 +938,7 @@ static void dump(ModelNode *node, int ind) } ModelNode::ModelNode() -: modelCache(0), objectCache(0) +: modelCache(0), objectCache(0), isArray(false) { } diff --git a/tests/auto/declarative/qmllistmodel/tst_qmllistmodel.cpp b/tests/auto/declarative/qmllistmodel/tst_qmllistmodel.cpp index 0986d20..b43b699 100644 --- a/tests/auto/declarative/qmllistmodel/tst_qmllistmodel.cpp +++ b/tests/auto/declarative/qmllistmodel/tst_qmllistmodel.cpp @@ -150,7 +150,12 @@ void tst_QmlListModel::dynamic_data() QTest::newRow("listprop1a") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]});count}" << 1 << ""; QTest::newRow("listprop1b") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]});get(0).bars.get(1).a}" << 2 << ""; + QTest::newRow("listprop1c") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]});get(0).bars.count}" << 3 << ""; QTest::newRow("listprop2a") << "{append({'foo':123,'bars':[{'a':1},{'a':2},{'a':3}]});get(0).bars.append({'a':4});get(0).bars.get(3).a}" << 4 << ""; + + QTest::newRow("list-0-items") << "{append({'foo':[]});get(0).foo.count}" << 0 << ""; + QTest::newRow("list-1-item") << "{append({'foo':[1]});get(0).foo.count}" << 1 << ""; + QTest::newRow("list-multi-items") << "{append({'foo':[1,2,3]});get(0).foo.count}" << 3 << ""; } void tst_QmlListModel::dynamic() -- cgit v0.12 From cdf57ac7a20fb29c1835ccff1dd668aeeba8d71f Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 19 Jan 2010 14:54:24 +1000 Subject: Basic WorkerListModel implementation --- src/declarative/qml/qmlworkerscript.cpp | 487 +++++++++++++++++++++++++++++++- src/declarative/qml/qmlworkerscript_p.h | 41 +++ 2 files changed, 527 insertions(+), 1 deletion(-) diff --git a/src/declarative/qml/qmlworkerscript.cpp b/src/declarative/qml/qmlworkerscript.cpp index a0d6ef0..8ebf841 100644 --- a/src/declarative/qml/qmlworkerscript.cpp +++ b/src/declarative/qml/qmlworkerscript.cpp @@ -51,6 +51,9 @@ #include #include #include +#include + +QT_BEGIN_NAMESPACE class WorkerDataEvent : public QEvent { @@ -144,6 +147,76 @@ private: void processLoad(int, const QUrl &); }; +// Currently this will leak as no-one releases it in the worker thread +class QmlWorkerListModelAgent : public QObject +{ + Q_OBJECT + Q_PROPERTY(int count READ count); + +public: + QmlWorkerListModelAgent(QmlWorkerListModel *); + ~QmlWorkerListModelAgent(); + + void addref(); + void release(); + + int count() const; + + Q_INVOKABLE void clear(); + Q_INVOKABLE void remove(int index); + Q_INVOKABLE void append(const QScriptValue &); + Q_INVOKABLE void insert(int index, const QScriptValue&); + Q_INVOKABLE QScriptValue get(int index) const; + Q_INVOKABLE void set(int index, const QScriptValue &); + Q_INVOKABLE void sync(); + + struct VariantRef + { + VariantRef() : a(0) {} + VariantRef(const VariantRef &r) : a(r.a) { if (a) a->addref(); } + VariantRef(QmlWorkerListModelAgent *_a) : a(_a) { if (a) a->addref(); } + ~VariantRef() { if (a) a->release(); } + + QmlWorkerListModelAgent *a; + }; +protected: + virtual bool event(QEvent *); + +private: + friend class QmlWorkerScriptEnginePrivate; + friend class QmlWorkerListModel; + QScriptEngine *m_engine; + + struct Change { + enum { Inserted, Removed, Moved, Changed } type; + int index; // Inserted/Removed/Moved/Changed + int count; // Inserted/Removed/Moved/Changed + int to; // Moved + }; + + struct Data { + QHash roles; + QHash strings; + QList > values; + QList changes; + + void clearChange(); + void insertChange(int index, int count); + void removeChange(int index, int count); + void changedChange(int index, int count); + }; + Data data; + + struct Sync : public QEvent { + Sync() : QEvent(QEvent::User) {} + Data data; + }; + + QAtomicInt m_ref; + QmlWorkerListModel *m_model; +}; +Q_DECLARE_METATYPE(QmlWorkerListModelAgent::VariantRef); + QmlWorkerScriptEnginePrivate::QmlWorkerScriptEnginePrivate() : workerEngine(0), m_nextId(0) { @@ -285,6 +358,15 @@ QVariant QmlWorkerScriptEnginePrivate::scriptValueToVariant(const QScriptValue & } return QVariant(list); + } else if (value.isQObject()) { + QmlWorkerListModel *lm = qobject_cast(value.toQObject()); + if (lm) { + QmlWorkerListModelAgent::VariantRef v(lm->agent()); + return qVariantFromValue(v); + } else { + // No other QObject's are allowed to be sent + return QVariant(); + } } else if (value.isObject()) { QVariantHash hash; @@ -310,6 +392,15 @@ QScriptValue QmlWorkerScriptEnginePrivate::variantToScriptValue(const QVariant & return QScriptValue(value.toString()); } else if (value.userType() == QMetaType::QReal) { return QScriptValue(value.toReal()); + } else if (value.userType() == qMetaTypeId()) { + QmlWorkerListModelAgent::VariantRef vr = qvariant_cast(value); + if (vr.a->m_engine == 0) + vr.a->m_engine = engine; + else if (vr.a->m_engine != engine) + return engine->nullValue(); + QScriptValue o = engine->newQObject(vr.a); + o.setData(engine->newVariant(value)); // Keeps the agent ref so that it is cleaned up on gc + return o; } else if (value.userType() == QMetaType::QVariantList) { QVariantList list = qvariant_cast(value); QScriptValue rv = engine->newArray(list.count()); @@ -513,5 +604,399 @@ bool QmlWorkerScript::event(QEvent *event) } } - QML_DEFINE_TYPE(Qt, 4, 6, WorkerScript, QmlWorkerScript); + +void QmlWorkerListModelAgent::Data::clearChange() +{ + changes.clear(); +} + +void QmlWorkerListModelAgent::Data::insertChange(int index, int count) +{ + Change c = { Change::Inserted, index, count, 0 }; + changes << c; +} + +void QmlWorkerListModelAgent::Data::removeChange(int index, int count) +{ + Change c = { Change::Removed, index, count, 0 }; + changes << c; +} + +void QmlWorkerListModelAgent::Data::changedChange(int index, int count) +{ + Change c = { Change::Changed, index, count, 0 }; + changes << c; +} + +QmlWorkerListModelAgent::QmlWorkerListModelAgent(QmlWorkerListModel *m) +: m_engine(0), m_model(m) +{ + data.roles = m_model->m_roles; + data.strings = m_model->m_strings; + data.values = m_model->m_values; +} + +QmlWorkerListModelAgent::~QmlWorkerListModelAgent() +{ +} + +void QmlWorkerListModelAgent::addref() +{ + m_ref.ref(); +} + +void QmlWorkerListModelAgent::release() +{ + if (!m_ref.deref()) + delete this; +} + +int QmlWorkerListModelAgent::count() const +{ + return data.values.count(); +} + +void QmlWorkerListModelAgent::clear() +{ + data.clearChange(); + data.insertChange(0, data.values.count()); + data.values.clear(); +} + +void QmlWorkerListModelAgent::remove(int index) +{ + if (data.values.count() <= index) + return; + + data.values.removeAt(index); + data.removeChange(index, 1); +} + +void QmlWorkerListModelAgent::append(const QScriptValue &value) +{ + QHash row; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash::Iterator iter = data.strings.find(name); + if (iter == data.strings.end()) { + int role = data.roles.count(); + data.roles.insert(role, name); + iter = data.strings.insert(name, role); + } + row.insert(*iter, v); + } + + data.values.append(row); + data.insertChange(data.values.count() - 1, 1); +} + +void QmlWorkerListModelAgent::insert(int index, const QScriptValue &value) +{ + if (index > data.values.count()) + return; + + QHash row; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash::Iterator iter = data.strings.find(name); + if (iter == data.strings.end()) { + int role = data.roles.count(); + data.roles.insert(role, name); + iter = data.strings.insert(name, role); + } + row.insert(*iter, v); + } + + data.values.insert(index, row); + data.insertChange(index, 1); +} + +void QmlWorkerListModelAgent::set(int index, const QScriptValue &value) +{ + if (data.values.count() <= index) + return; + + QHash row; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash::Iterator iter = data.strings.find(name); + if (iter == data.strings.end()) { + int role = data.roles.count(); + data.roles.insert(role, name); + iter = data.strings.insert(name, role); + } + row.insert(*iter, v); + } + + if (data.values.at(index) != row) { + data.values[index] = row; + data.changedChange(index, 1); + } +} + +QScriptValue QmlWorkerListModelAgent::get(int index) const +{ + if (data.values.count() <= index) + return m_engine->undefinedValue(); + + QScriptValue rv = m_engine->newObject(); + + QHash row = data.values.at(index); + for (QHash::ConstIterator iter = row.begin(); iter != row.end(); ++iter) + rv.setProperty(data.roles.value(iter.key()), qScriptValueFromValue(m_engine, iter.value())); + + return rv; +} + +void QmlWorkerListModelAgent::sync() +{ + Sync *s = new Sync; + s->data = data; + data.changes.clear(); + QCoreApplication::postEvent(this, s); +} + +bool QmlWorkerListModelAgent::event(QEvent *e) +{ + if (e->type() == QEvent::User) { + Sync *s = static_cast(e); + + const QList &changes = s->data.changes; + + if (m_model) { + m_model->m_roles = s->data.roles; + m_model->m_strings = s->data.strings; + m_model->m_values = s->data.values; + + for (int ii = 0; ii < changes.count(); ++ii) { + const Change &change = changes.at(ii); + switch (change.type) { + case Change::Inserted: + emit m_model->itemsInserted(change.index, change.count); + break; + case Change::Removed: + emit m_model->itemsRemoved(change.index, change.count); + break; + case Change::Moved: + emit m_model->itemsMoved(change.index, change.to, change.count); + break; + case Change::Changed: + emit m_model->itemsMoved(change.index, change.to, change.count); + break; + } + } + } + } + + return QObject::event(e); +} + +QmlWorkerListModel::QmlWorkerListModel(QObject *parent) +: QListModelInterface(parent), m_agent(0) +{ +} + +QmlWorkerListModel::~QmlWorkerListModel() +{ + if (m_agent) { + m_agent->m_model = 0; + m_agent->release(); + } +} + +void QmlWorkerListModel::clear() +{ + if (m_agent) { + qmlInfo(this) << "List can only be modified from a WorkerScript"; + return; + } + + int count = m_values.count(); + m_values.clear(); + if (count) + emit itemsRemoved(0, count); +} + +void QmlWorkerListModel::remove(int index) +{ + if (m_agent) { + qmlInfo(this) << "List can only be modified from a WorkerScript"; + return; + } + + if (m_values.count() <= index) + return; + + m_values.removeAt(index); + emit itemsRemoved(index, 1); +} + +void QmlWorkerListModel::append(const QScriptValue &value) +{ + if (m_agent) { + qmlInfo(this) << "List can only be modified from a WorkerScript"; + return; + } + + QHash data; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash::Iterator iter = m_strings.find(name); + if (iter == m_strings.end()) { + int role = m_roles.count(); + m_roles.insert(role, name); + iter = m_strings.insert(name, role); + } + data.insert(*iter, v); + } + + m_values.append(data); + + emit itemsInserted(m_values.count() - 1, 1); +} + +void QmlWorkerListModel::insert(int index, const QScriptValue &value) +{ + if (m_agent) { + qmlInfo(this) << "List can only be modified from a WorkerScript"; + return; + } + + if (index > m_values.count()) + return; + + QHash data; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash::Iterator iter = m_strings.find(name); + if (iter == m_strings.end()) { + int role = m_roles.count(); + m_roles.insert(role, name); + iter = m_strings.insert(name, role); + } + data.insert(*iter, v); + } + + m_values.insert(index, data); + emit itemsInserted(index, 1); +} + +QScriptValue QmlWorkerListModel::get(int index) const +{ + QmlEngine *engine = qmlEngine(this); + if (!engine || m_values.count() <= index) + return QScriptValue(); + + QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); + QScriptValue rv = scriptEngine->newObject(); + + QHash data = m_values.at(index); + for (QHash::ConstIterator iter = data.begin(); iter != data.end(); ++iter) + rv.setProperty(m_roles.value(iter.key()), qScriptValueFromValue(scriptEngine, iter.value())); + + return rv; +} + +void QmlWorkerListModel::set(int index, const QScriptValue &value) +{ + if (m_agent) { + qmlInfo(this) << "List can only be modified from a WorkerScript"; + return; + } + + if (m_values.count() <= index) + return; + + QHash data; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash::Iterator iter = m_strings.find(name); + if (iter == m_strings.end()) { + int role = m_roles.count(); + m_roles.insert(role, name); + iter = m_strings.insert(name, role); + } + data.insert(*iter, v); + } + + if (m_values.at(index) != data) { + m_values[index] = data; + emit itemsChanged(index, 1, m_roles.keys()); + } +} + +QmlWorkerListModelAgent *QmlWorkerListModel::agent() +{ + if (!m_agent) + m_agent = new QmlWorkerListModelAgent(this); + + return m_agent; +} + +QList QmlWorkerListModel::roles() const +{ + return m_roles.keys(); +} + +QString QmlWorkerListModel::toString(int role) const +{ + return m_roles.value(role); +} + +int QmlWorkerListModel::count() const +{ + return m_values.count(); +} + +QHash QmlWorkerListModel::data(int index, const QList &) const +{ + if (m_values.count() <= index) + return QHash(); + else + return m_values.at(index); +} + +QVariant QmlWorkerListModel::data(int index, int role) const +{ + if (m_values.count() <= index) + return QVariant(); + else + return m_values.at(index).value(role); +} + +QML_DEFINE_TYPE(Qt,4,6,WorkerListModel,QmlWorkerListModel) + +#include "qmlworkerscript.moc" + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlworkerscript_p.h b/src/declarative/qml/qmlworkerscript_p.h index 1ec7af3..fdc726e 100644 --- a/src/declarative/qml/qmlworkerscript_p.h +++ b/src/declarative/qml/qmlworkerscript_p.h @@ -55,11 +55,14 @@ #include "qml.h" #include "qmlparserstatus.h" +#include #include #include #include +QT_BEGIN_NAMESPACE + class QmlWorkerScript; class QmlWorkerScriptEnginePrivate; class QmlWorkerScriptEngine : public QThread @@ -110,6 +113,44 @@ private: int m_scriptId; QUrl m_source; }; + +class QmlWorkerListModelAgent; +class QmlWorkerListModel : public QListModelInterface +{ + Q_OBJECT + +public: + QmlWorkerListModel(QObject * = 0); + virtual ~QmlWorkerListModel(); + + Q_INVOKABLE void clear(); + Q_INVOKABLE void remove(int index); + Q_INVOKABLE void append(const QScriptValue &); + Q_INVOKABLE void insert(int index, const QScriptValue&); + Q_INVOKABLE QScriptValue get(int index) const; + Q_INVOKABLE void set(int index, const QScriptValue &); + + QmlWorkerListModelAgent *agent(); + + virtual QList roles() const; + virtual QString toString(int role) const; + virtual int count() const; + virtual QHash data(int index, const QList &roles = (QList())) const; + virtual QVariant data(int index, int role) const; + +private: + friend class QmlWorkerListModelAgent; + + QHash m_roles; + QHash m_strings; + QList > m_values; + + QmlWorkerListModelAgent *m_agent; +}; + +QT_END_NAMESPACE + QML_DECLARE_TYPE(QmlWorkerScript); +QML_DECLARE_TYPE(QmlWorkerListModel); #endif // QMLWORKERSCRIPT_P_H -- cgit v0.12 From 8eb1bf3ea506ec1f9636cab684695b91d846a3cd Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 19 Jan 2010 16:17:05 +1000 Subject: WorkerListModel fixes --- src/declarative/qml/qmlworkerscript.cpp | 26 ++++++++++++++++++++++---- src/declarative/qml/qmlworkerscript_p.h | 4 ++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/declarative/qml/qmlworkerscript.cpp b/src/declarative/qml/qmlworkerscript.cpp index 8ebf841..75c5179 100644 --- a/src/declarative/qml/qmlworkerscript.cpp +++ b/src/declarative/qml/qmlworkerscript.cpp @@ -177,6 +177,12 @@ public: VariantRef(QmlWorkerListModelAgent *_a) : a(_a) { if (a) a->addref(); } ~VariantRef() { if (a) a->release(); } + VariantRef &operator=(const VariantRef &o) { + if (o.a) o.a->addref(); + if (a) a->release(); a = o.a; + return *this; + } + QmlWorkerListModelAgent *a; }; protected: @@ -630,7 +636,7 @@ void QmlWorkerListModelAgent::Data::changedChange(int index, int count) } QmlWorkerListModelAgent::QmlWorkerListModelAgent(QmlWorkerListModel *m) -: m_engine(0), m_model(m) +: m_engine(0), m_ref(1), m_model(m) { data.roles = m_model->m_roles; data.strings = m_model->m_strings; @@ -648,7 +654,9 @@ void QmlWorkerListModelAgent::addref() void QmlWorkerListModelAgent::release() { - if (!m_ref.deref()) + bool del = !m_ref.deref(); + + if (del) delete this; } @@ -660,7 +668,7 @@ int QmlWorkerListModelAgent::count() const void QmlWorkerListModelAgent::clear() { data.clearChange(); - data.insertChange(0, data.values.count()); + data.removeChange(0, data.values.count()); data.values.clear(); } @@ -780,6 +788,8 @@ bool QmlWorkerListModelAgent::event(QEvent *e) const QList &changes = s->data.changes; if (m_model) { + bool cc = m_model->m_values.count() != s->data.values.count(); + m_model->m_roles = s->data.roles; m_model->m_strings = s->data.strings; m_model->m_values = s->data.values; @@ -801,6 +811,9 @@ bool QmlWorkerListModelAgent::event(QEvent *e) break; } } + + if (cc) + emit m_model->countChanged(); } } @@ -829,8 +842,10 @@ void QmlWorkerListModel::clear() int count = m_values.count(); m_values.clear(); - if (count) + if (count) { emit itemsRemoved(0, count); + emit countChanged(); + } } void QmlWorkerListModel::remove(int index) @@ -845,6 +860,7 @@ void QmlWorkerListModel::remove(int index) m_values.removeAt(index); emit itemsRemoved(index, 1); + emit countChanged(); } void QmlWorkerListModel::append(const QScriptValue &value) @@ -874,6 +890,7 @@ void QmlWorkerListModel::append(const QScriptValue &value) m_values.append(data); emit itemsInserted(m_values.count() - 1, 1); + emit countChanged(); } void QmlWorkerListModel::insert(int index, const QScriptValue &value) @@ -905,6 +922,7 @@ void QmlWorkerListModel::insert(int index, const QScriptValue &value) m_values.insert(index, data); emit itemsInserted(index, 1); + emit countChanged(); } QScriptValue QmlWorkerListModel::get(int index) const diff --git a/src/declarative/qml/qmlworkerscript_p.h b/src/declarative/qml/qmlworkerscript_p.h index fdc726e..1c70f2d 100644 --- a/src/declarative/qml/qmlworkerscript_p.h +++ b/src/declarative/qml/qmlworkerscript_p.h @@ -118,6 +118,7 @@ class QmlWorkerListModelAgent; class QmlWorkerListModel : public QListModelInterface { Q_OBJECT + Q_PROPERTY(int count READ count NOTIFY countChanged); public: QmlWorkerListModel(QObject * = 0); @@ -138,6 +139,9 @@ public: virtual QHash data(int index, const QList &roles = (QList())) const; virtual QVariant data(int index, int role) const; +Q_SIGNALS: + void countChanged(); + private: friend class QmlWorkerListModelAgent; -- cgit v0.12