diff options
author | Alan Alpert <alan.alpert@nokia.com> | 2010-01-19 07:54:46 (GMT) |
---|---|---|
committer | Alan Alpert <alan.alpert@nokia.com> | 2010-01-19 07:54:46 (GMT) |
commit | 630114a8c65e492b7b9008e056895302865ba528 (patch) | |
tree | 50bb56cd3d5cd45626bb2d9a40c7cf21f14a4a20 | |
parent | 98a8be614d410a153cd9c314465f4c49d4ad096d (diff) | |
parent | 8eb1bf3ea506ec1f9636cab684695b91d846a3cd (diff) | |
download | Qt-630114a8c65e492b7b9008e056895302865ba528.zip Qt-630114a8c65e492b7b9008e056895302865ba528.tar.gz Qt-630114a8c65e492b7b9008e056895302865ba528.tar.bz2 |
Merge branch 'kinetic-declarativeui' of scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
-rw-r--r-- | src/declarative/graphicsitems/qmlgraphicspathview.cpp | 34 | ||||
-rw-r--r-- | src/declarative/graphicsitems/qmlgraphicstext.cpp | 4 | ||||
-rw-r--r-- | src/declarative/qml/qmlworkerscript.cpp | 505 | ||||
-rw-r--r-- | src/declarative/qml/qmlworkerscript_p.h | 45 | ||||
-rw-r--r-- | src/declarative/util/qmllistmodel.cpp | 45 | ||||
-rw-r--r-- | tests/auto/declarative/qmllistmodel/tst_qmllistmodel.cpp | 5 | ||||
-rw-r--r-- | tools/qmlviewer/main.cpp | 3 |
7 files changed, 608 insertions, 33 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; i<d->items.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<items.count(); i++){ qreal percent = i * (100. / items.count()); percent = percent + _offset; - percent = fmod(percent, qreal(100.0)); + percent = qmlMod(percent, qreal(100.0)); qreal diff = qAbs(snapPos - (percent/100.0)); if (diff < bestDiff){ bestDiff = diff; @@ -843,7 +855,7 @@ void QmlGraphicsPathViewPrivate::snapToCurrent() itemIndex += pathOffset; itemIndex %= items.count(); - qreal targetOffset = fmod(100 + (snapPos*100) - 100.0 * itemIndex / items.count(), qreal(100.0)); + qreal targetOffset = qmlMod(100 + (snapPos*100) - 100.0 * itemIndex / items.count(), qreal(100.0)); if (targetOffset < 0) targetOffset = 100.0 + targetOffset; 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 diff --git a/src/declarative/qml/qmlworkerscript.cpp b/src/declarative/qml/qmlworkerscript.cpp index a0d6ef0..75c5179 100644 --- a/src/declarative/qml/qmlworkerscript.cpp +++ b/src/declarative/qml/qmlworkerscript.cpp @@ -51,6 +51,9 @@ #include <QtCore/qwaitcondition.h> #include <QtScript/qscriptvalueiterator.h> #include <QtCore/qfile.h> +#include <QtDeclarative/qmlinfo.h> + +QT_BEGIN_NAMESPACE class WorkerDataEvent : public QEvent { @@ -144,6 +147,82 @@ 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(); } + + VariantRef &operator=(const VariantRef &o) { + if (o.a) o.a->addref(); + if (a) a->release(); a = o.a; + return *this; + } + + 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<int, QString> roles; + QHash<QString, int> strings; + QList<QHash<int, QVariant> > values; + QList<Change> 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 +364,15 @@ QVariant QmlWorkerScriptEnginePrivate::scriptValueToVariant(const QScriptValue & } return QVariant(list); + } else if (value.isQObject()) { + QmlWorkerListModel *lm = qobject_cast<QmlWorkerListModel *>(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 +398,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>()) { + QmlWorkerListModelAgent::VariantRef vr = qvariant_cast<QmlWorkerListModelAgent::VariantRef>(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<QVariantList>(value); QScriptValue rv = engine->newArray(list.count()); @@ -513,5 +610,411 @@ 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_ref(1), 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() +{ + bool del = !m_ref.deref(); + + if (del) + delete this; +} + +int QmlWorkerListModelAgent::count() const +{ + return data.values.count(); +} + +void QmlWorkerListModelAgent::clear() +{ + data.clearChange(); + data.removeChange(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<int, QVariant> row; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash<QString, int>::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<int, QVariant> row; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash<QString, int>::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<int, QVariant> row; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash<QString, int>::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<int, QVariant> row = data.values.at(index); + for (QHash<int, QVariant>::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<Sync *>(e); + + const QList<Change> &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; + + 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; + } + } + + if (cc) + emit m_model->countChanged(); + } + } + + 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); + emit countChanged(); + } +} + +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); + emit countChanged(); +} + +void QmlWorkerListModel::append(const QScriptValue &value) +{ + if (m_agent) { + qmlInfo(this) << "List can only be modified from a WorkerScript"; + return; + } + + QHash<int, QVariant> data; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash<QString, int>::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); + emit countChanged(); +} + +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<int, QVariant> data; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash<QString, int>::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); + emit countChanged(); +} + +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<int, QVariant> data = m_values.at(index); + for (QHash<int, QVariant>::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<int, QVariant> data; + + QScriptValueIterator it(value); + while (it.hasNext()) { + it.next(); + QString name = it.name(); + QVariant v = it.value().toVariant(); + + QHash<QString, int>::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<int> 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<int,QVariant> QmlWorkerListModel::data(int index, const QList<int> &) const +{ + if (m_values.count() <= index) + return QHash<int, QVariant>(); + 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..1c70f2d 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 <private/qlistmodelinterface_p.h> #include <QtCore/qthread.h> #include <QtScript/qscriptvalue.h> #include <QtCore/qurl.h> +QT_BEGIN_NAMESPACE + class QmlWorkerScript; class QmlWorkerScriptEnginePrivate; class QmlWorkerScriptEngine : public QThread @@ -110,6 +113,48 @@ private: int m_scriptId; QUrl m_source; }; + +class QmlWorkerListModelAgent; +class QmlWorkerListModel : public QListModelInterface +{ + Q_OBJECT + Q_PROPERTY(int count READ count NOTIFY countChanged); + +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<int> roles() const; + virtual QString toString(int role) const; + virtual int count() const; + virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const; + virtual QVariant data(int index, int role) const; + +Q_SIGNALS: + void countChanged(); + +private: + friend class QmlWorkerListModelAgent; + + QHash<int, QString> m_roles; + QHash<QString, int> m_strings; + QList<QHash<int, QVariant> > m_values; + + QmlWorkerListModelAgent *m_agent; +}; + +QT_END_NAMESPACE + QML_DECLARE_TYPE(QmlWorkerScript); +QML_DECLARE_TYPE(QmlWorkerListModel); #endif // QMLWORKERSCRIPT_P_H 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<ModelNode *>(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<ModelNode *>(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() diff --git a/tools/qmlviewer/main.cpp b/tools/qmlviewer/main.cpp index f11c7c9..b7a3f1a 100644 --- a/tools/qmlviewer/main.cpp +++ b/tools/qmlviewer/main.cpp @@ -83,6 +83,7 @@ void usage() qWarning(" -skin <qvfbskindir> ...................... 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 <output> ..................... set video recording file"); qWarning(" - ImageMagick 'convert' for GIF)"); qWarning(" - png file for raw frames"); @@ -222,6 +223,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]); |