From ff075380d7ec1472fcdff06b3f39ffdc02b7f112 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 17 Sep 2010 10:31:04 +1000 Subject: Fix worker agent to emit ListModel itemsChanged() correctly when set() and setProperty() are called Task-number: QTBUG-13666 --- src/declarative/util/qdeclarativelistmodelworkeragent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp index d9df169..4392bed 100644 --- a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp +++ b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp @@ -232,7 +232,7 @@ bool QDeclarativeListModelWorkerAgent::event(QEvent *e) emit m_orig->itemsMoved(change.index, change.to, change.count); break; case Change::Changed: - emit m_orig->itemsChanged(change.index, change.to, orig->m_roles.keys()); + emit m_orig->itemsChanged(change.index, change.count, orig->m_roles.keys()); break; } } -- cgit v0.12 From 7e6b2b2b95bc1db77544b898ec45ea4a2683e435 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 17 Sep 2010 13:46:44 +1000 Subject: Moving items in a PathView caused PathView.onPath to be set to false. Check that we no longer hold a reference to the item before setting onPath to false. Task-number: QTBUG-13689 Reviewed-by: Michael Brasser --- .../graphicsitems/qdeclarativepathview.cpp | 8 +++++--- .../qdeclarativepathview/data/datamodel.qml | 1 + .../tst_qdeclarativepathview.cpp | 23 ++++++++++++++-------- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp index dad547f..8f60281 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview.cpp +++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp @@ -141,11 +141,13 @@ void QDeclarativePathViewPrivate::releaseItem(QDeclarativeItem *item) { if (!item || !model) return; - if (QDeclarativePathViewAttached *att = attached(item)) - att->setOnPath(false); QDeclarativeItemPrivate *itemPrivate = static_cast(QGraphicsItemPrivate::get(item)); itemPrivate->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry); - model->release(item); + if (model->release(item) == 0) { + // item was not destroyed, and we no longer reference it. + if (QDeclarativePathViewAttached *att = attached(item)) + att->setOnPath(false); + } } QDeclarativePathViewAttached *QDeclarativePathViewPrivate::attached(QDeclarativeItem *item) diff --git a/tests/auto/declarative/qdeclarativepathview/data/datamodel.qml b/tests/auto/declarative/qdeclarativepathview/data/datamodel.qml index a5c3772..fb3c910 100644 --- a/tests/auto/declarative/qdeclarativepathview/data/datamodel.qml +++ b/tests/auto/declarative/qdeclarativepathview/data/datamodel.qml @@ -21,6 +21,7 @@ PathView { Rectangle { id: wrapper objectName: "wrapper" + property bool onPath: PathView.onPath width: 20; height: 20; color: name Text { objectName: "myText" diff --git a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp index 74d2f0a..cbfbfbd 100644 --- a/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp +++ b/tests/auto/declarative/qdeclarativepathview/tst_qdeclarativepathview.cpp @@ -152,27 +152,27 @@ public: QString number(int index) const { return list.at(index).second; } void addItem(const QString &name, const QString &number) { - emit beginInsertRows(QModelIndex(), list.count(), list.count()); + beginInsertRows(QModelIndex(), list.count(), list.count()); list.append(QPair(name, number)); - emit endInsertRows(); + endInsertRows(); } void insertItem(int index, const QString &name, const QString &number) { - emit beginInsertRows(QModelIndex(), index, index); + beginInsertRows(QModelIndex(), index, index); list.insert(index, QPair(name, number)); - emit endInsertRows(); + endInsertRows(); } void removeItem(int index) { - emit beginRemoveRows(QModelIndex(), index, index); + beginRemoveRows(QModelIndex(), index, index); list.removeAt(index); - emit endRemoveRows(); + endRemoveRows(); } void moveItem(int from, int to) { - emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to); + beginMoveRows(QModelIndex(), from, from, QModelIndex(), to); list.move(from, to); - emit endMoveRows(); + endMoveRows(); } void modifyItem(int idx, const QString &name, const QString &number) { @@ -411,6 +411,13 @@ void tst_QDeclarativePathView::dataModel() QVERIFY(text); QCOMPARE(text->text(), model.name(3)); + model.moveItem(3, 5); + QTRY_COMPARE(findItems(pathview, "wrapper").count(), 5); + QList items = findItems(pathview, "wrapper"); + foreach (QDeclarativeItem *item, items) { + QVERIFY(item->property("onPath").toBool()); + } + delete canvas; } -- cgit v0.12 From a4cadd1b1fd30a1989d56f6c06deb8fed4f79882 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Fri, 17 Sep 2010 14:53:40 +1000 Subject: PathView didn't accept mouse events, preventing it from working in a Flickable. Since it didn't accept the press it didn't get a grab, so its events were always filtered away by Flickable. Use the same implementation as Flickable, i.e. create private handler functions for mouse events and accept normal events in the mouse*Event() methods. Task-number: QTBUG-13687 Reviewed-by: Michael Brasser --- .../graphicsitems/qdeclarativepathview.cpp | 183 ++++++++++++--------- .../graphicsitems/qdeclarativepathview_p_p.h | 4 + 2 files changed, 112 insertions(+), 75 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp index 8f60281..d134929 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview.cpp +++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp @@ -1035,103 +1035,138 @@ QPointF QDeclarativePathViewPrivate::pointNear(const QPointF &point, qreal *near return nearPoint; } - void QDeclarativePathView::mousePressEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativePathView); - if (!d->interactive || !d->items.count()) + if (d->interactive) { + d->handleMousePressEvent(event); + event->accept(); + } else { + QDeclarativeItem::mousePressEvent(event); + } +} + +void QDeclarativePathViewPrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event) +{ + Q_Q(QDeclarativePathView); + if (!interactive || !items.count()) return; - QPointF scenePoint = mapToScene(event->pos()); + QPointF scenePoint = q->mapToScene(event->pos()); int idx = 0; - for (; idx < d->items.count(); ++idx) { - QRectF rect = d->items.at(idx)->boundingRect(); - rect = d->items.at(idx)->mapToScene(rect).boundingRect(); + for (; idx < items.count(); ++idx) { + QRectF rect = items.at(idx)->boundingRect(); + rect = items.at(idx)->mapToScene(rect).boundingRect(); if (rect.contains(scenePoint)) break; } - if (idx == d->items.count() && d->dragMargin == 0.) // didn't click on an item + if (idx == items.count() && dragMargin == 0.) // didn't click on an item return; - d->startPoint = d->pointNear(event->pos(), &d->startPc); - if (idx == d->items.count()) { - qreal distance = qAbs(event->pos().x() - d->startPoint.x()) + qAbs(event->pos().y() - d->startPoint.y()); - if (distance > d->dragMargin) + startPoint = pointNear(event->pos(), &startPc); + if (idx == items.count()) { + qreal distance = qAbs(event->pos().x() - startPoint.x()) + qAbs(event->pos().y() - startPoint.y()); + if (distance > dragMargin) return; } - if (d->tl.isActive() && d->flicking) - d->stealMouse = true; // If we've been flicked then steal the click. + if (tl.isActive() && flicking) + stealMouse = true; // If we've been flicked then steal the click. else - d->stealMouse = false; + stealMouse = false; - d->lastElapsed = 0; - d->lastDist = 0; - QDeclarativeItemPrivate::start(d->lastPosTime); - d->tl.clear(); + lastElapsed = 0; + lastDist = 0; + QDeclarativeItemPrivate::start(lastPosTime); + tl.clear(); } void QDeclarativePathView::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativePathView); - if (!d->interactive || !d->lastPosTime.isValid()) + if (d->interactive) { + d->handleMouseMoveEvent(event); + if (d->stealMouse) + setKeepMouseGrab(true); + event->accept(); + } else { + QDeclarativeItem::mouseMoveEvent(event); + } +} + +void QDeclarativePathViewPrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + Q_Q(QDeclarativePathView); + if (!interactive || !lastPosTime.isValid()) return; - if (!d->stealMouse) { - QPointF delta = event->pos() - d->startPoint; + if (!stealMouse) { + QPointF delta = event->pos() - startPoint; if (qAbs(delta.x()) > QApplication::startDragDistance() || qAbs(delta.y()) > QApplication::startDragDistance()) - d->stealMouse = true; + stealMouse = true; } - if (d->stealMouse) { - d->moveReason = QDeclarativePathViewPrivate::Mouse; + if (stealMouse) { + moveReason = QDeclarativePathViewPrivate::Mouse; qreal newPc; - d->pointNear(event->pos(), &newPc); - qreal diff = (newPc - d->startPc)*d->modelCount*d->mappedRange; + pointNear(event->pos(), &newPc); + qreal diff = (newPc - startPc)*modelCount*mappedRange; if (diff) { - setOffset(d->offset + diff); + setOffset(offset + diff); - if (diff > d->modelCount/2) - diff -= d->modelCount; - else if (diff < -d->modelCount/2) - diff += d->modelCount; + if (diff > modelCount/2) + diff -= modelCount; + else if (diff < -modelCount/2) + diff += modelCount; - d->lastElapsed = QDeclarativeItemPrivate::restart(d->lastPosTime); - d->lastDist = diff; - d->startPc = newPc; + lastElapsed = QDeclarativeItemPrivate::restart(lastPosTime); + lastDist = diff; + startPc = newPc; } - if (!d->moving) { - d->moving = true; - emit movingChanged(); - emit movementStarted(); + if (!moving) { + moving = true; + emit q->movingChanged(); + emit q->movementStarted(); } } } -void QDeclarativePathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *) +void QDeclarativePathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativePathView); - d->stealMouse = false; - setKeepMouseGrab(false); - if (!d->interactive || !d->lastPosTime.isValid()) + if (d->interactive) { + d->handleMouseReleaseEvent(event); + event->accept(); + ungrabMouse(); + } else { + QDeclarativeItem::mouseReleaseEvent(event); + } +} + +void QDeclarativePathViewPrivate::handleMouseReleaseEvent(QGraphicsSceneMouseEvent *) +{ + Q_Q(QDeclarativePathView); + stealMouse = false; + q->setKeepMouseGrab(false); + if (!interactive || !lastPosTime.isValid()) return; - qreal elapsed = qreal(d->lastElapsed + QDeclarativeItemPrivate::elapsed(d->lastPosTime)) / 1000.; - qreal velocity = elapsed > 0. ? d->lastDist / elapsed : 0; - if (d->model && d->modelCount && qAbs(velocity) > 1.) { - qreal count = d->pathItems == -1 ? d->modelCount : d->pathItems; + qreal elapsed = qreal(lastElapsed + QDeclarativeItemPrivate::elapsed(lastPosTime)) / 1000.; + qreal velocity = elapsed > 0. ? lastDist / elapsed : 0; + if (model && modelCount && qAbs(velocity) > 1.) { + qreal count = pathItems == -1 ? modelCount : pathItems; if (qAbs(velocity) > count * 2) // limit velocity velocity = (velocity > 0 ? count : -count) * 2; // Calculate the distance to be travelled qreal v2 = velocity*velocity; - qreal accel = d->deceleration/10; + qreal accel = deceleration/10; // + 0.25 to encourage moving at least one item in the flick direction - qreal dist = qMin(qreal(d->modelCount-1), qreal(v2 / (accel * 2.0) + 0.25)); - if (d->haveHighlightRange && d->highlightRangeMode == QDeclarativePathView::StrictlyEnforceRange) { + qreal dist = qMin(qreal(modelCount-1), qreal(v2 / (accel * 2.0) + 0.25)); + if (haveHighlightRange && highlightRangeMode == QDeclarativePathView::StrictlyEnforceRange) { // round to nearest item. if (velocity > 0.) - dist = qRound(dist + d->offset) - d->offset; + dist = qRound(dist + offset) - offset; else - dist = qRound(dist - d->offset) + d->offset; + dist = qRound(dist - offset) + offset; // Calculate accel required to stop on item boundary if (dist <= 0.) { dist = 0.; @@ -1140,23 +1175,22 @@ void QDeclarativePathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *) accel = v2 / (2.0f * qAbs(dist)); } } - d->offsetAdj = 0.0; - d->moveOffset.setValue(d->offset); - d->tl.accel(d->moveOffset, velocity, accel, dist); - d->tl.callback(QDeclarativeTimeLineCallback(&d->moveOffset, d->fixOffsetCallback, d)); - if (!d->flicking) { - d->flicking = true; - emit flickingChanged(); - emit flickStarted(); + offsetAdj = 0.0; + moveOffset.setValue(offset); + tl.accel(moveOffset, velocity, accel, dist); + tl.callback(QDeclarativeTimeLineCallback(&moveOffset, fixOffsetCallback, this)); + if (!flicking) { + flicking = true; + emit q->flickingChanged(); + emit q->flickStarted(); } } else { - d->fixOffset(); + fixOffset(); } - d->lastPosTime.invalidate(); - ungrabMouse(); - if (!d->tl.isActive()) - movementEnding(); + lastPosTime.invalidate(); + if (!tl.isActive()) + q->movementEnding(); } bool QDeclarativePathView::sendMouseEvent(QGraphicsSceneMouseEvent *event) @@ -1166,7 +1200,8 @@ bool QDeclarativePathView::sendMouseEvent(QGraphicsSceneMouseEvent *event) QRectF myRect = mapToScene(QRectF(0, 0, width(), height())).boundingRect(); QGraphicsScene *s = scene(); QDeclarativeItem *grabber = s ? qobject_cast(s->mouseGrabberItem()) : 0; - if ((d->stealMouse || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) { + bool stealThisEvent = d->stealMouse; + if ((stealThisEvent || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) { mouseEvent.setAccepted(false); for (int i = 0x1; i <= 0x10; i <<= 1) { if (event->buttons() & i) { @@ -1181,25 +1216,28 @@ bool QDeclarativePathView::sendMouseEvent(QGraphicsSceneMouseEvent *event) switch(mouseEvent.type()) { case QEvent::GraphicsSceneMouseMove: - mouseMoveEvent(&mouseEvent); + d->handleMouseMoveEvent(&mouseEvent); break; case QEvent::GraphicsSceneMousePress: - mousePressEvent(&mouseEvent); + d->handleMousePressEvent(&mouseEvent); + stealThisEvent = d->stealMouse; // Update stealThisEvent in case changed by function call above break; case QEvent::GraphicsSceneMouseRelease: - mouseReleaseEvent(&mouseEvent); + d->handleMouseReleaseEvent(&mouseEvent); break; default: break; } grabber = qobject_cast(s->mouseGrabberItem()); - if (grabber && d->stealMouse && !grabber->keepMouseGrab() && grabber != this) + if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this) grabMouse(); return d->stealMouse; } else if (d->lastPosTime.isValid()) { d->lastPosTime.invalidate(); } + if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) + d->stealMouse = false; return false; } @@ -1213,12 +1251,7 @@ bool QDeclarativePathView::sceneEventFilter(QGraphicsItem *i, QEvent *e) case QEvent::GraphicsSceneMousePress: case QEvent::GraphicsSceneMouseMove: case QEvent::GraphicsSceneMouseRelease: - { - bool ret = sendMouseEvent(static_cast(e)); - if (e->type() == QEvent::GraphicsSceneMouseRelease) - return ret; - break; - } + return sendMouseEvent(static_cast(e)); default: break; } diff --git a/src/declarative/graphicsitems/qdeclarativepathview_p_p.h b/src/declarative/graphicsitems/qdeclarativepathview_p_p.h index dfebe35..b217216 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativepathview_p_p.h @@ -123,6 +123,10 @@ public: return model && model->count() > 0 && model->isValid() && path; } + void handleMousePressEvent(QGraphicsSceneMouseEvent *event); + void handleMouseMoveEvent(QGraphicsSceneMouseEvent *event); + void handleMouseReleaseEvent(QGraphicsSceneMouseEvent *); + int calcCurrentIndex(); void updateCurrent(); static void fixOffsetCallback(void*); -- cgit v0.12 From 0c971a9801766a6d7646d1c1c413354f74db41e4 Mon Sep 17 00:00:00 2001 From: Joona Petrell Date: Fri, 17 Sep 2010 14:47:20 +1000 Subject: Fix QDeclarativeXmlQuery mutex locking and don't wait for new jobs if the query has already quit Task-number: QTBUG-13041 Reviewed-by: Aaron Kennedy --- src/declarative/util/qdeclarativexmllistmodel.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index 47b502d..f0ed80b 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -209,8 +209,9 @@ Q_SIGNALS: protected: void run() { + m_mutex.lock(); + while (!m_quit) { - m_mutex.lock(); if (!m_jobs.isEmpty()) m_currentJob = m_jobs.dequeue(); m_mutex.unlock(); @@ -230,12 +231,13 @@ protected: m_mutex.lock(); if (m_currentJob.queryId != -1 && m_abortQueryId != m_currentJob.queryId) emit queryCompleted(r); - if (m_jobs.isEmpty()) + if (m_jobs.isEmpty() && !m_quit) m_condition.wait(&m_mutex); m_currentJob.queryId = -1; m_abortQueryId = -1; - m_mutex.unlock(); } + + m_mutex.unlock(); } private: -- cgit v0.12 From ee9c9e412fd5467e82be446603e71bee620ff04b Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 17 Sep 2010 11:28:23 +1000 Subject: Doc changes --- src/declarative/util/qdeclarativelistmodel.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index cf2eada..f01d9b4 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -154,10 +154,10 @@ QDeclarativeListModelParser::ListInstruction *QDeclarativeListModelParser::ListM handler. You must call sync() or else the changes made to the list from the external thread will not be reflected in the list model in the main thread. - \section1 Limitations + \section1 Restrictions - If a list model is to be accessed from a WorkerScript, it \bold cannot - contain list data. So, the following model cannot be used from a WorkerScript + If a list model is to be accessed from a WorkerScript, it cannot + contain list-type data. So, the following model cannot be used from a WorkerScript because of the list contained in the "attributes" property: \code @@ -174,7 +174,7 @@ QDeclarativeListModelParser::ListInstruction *QDeclarativeListModelParser::ListM } \endcode - In addition, the WorkerScript cannot add any list data to the model. + In addition, the WorkerScript cannot add list-type data to the model. \sa {qmlmodels}{Data Models}, {declarative/threading/threadedlistmodel}{Threaded ListModel example}, QtDeclarative */ -- cgit v0.12 From 16013f8970471f161db9fcc728a8c263e5bb84a7 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 17 Sep 2010 14:16:08 +1000 Subject: Remove duplicated move() implementations --- src/declarative/util/qdeclarativelistmodel.cpp | 60 +++++++++++--------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index f01d9b4..401e400 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -58,6 +58,28 @@ Q_DECLARE_METATYPE(QListModelInterface *) QT_BEGIN_NAMESPACE +template +void qdeclarativelistmodel_move(int from, int to, int n, T *items) +{ + if (n == 1) { + items->move(from, to); + } else { + T replaced; + int i=0; + typename T::ConstIterator it=items->begin(); it += from+n; + for (; ibegin(); it += from; + for (; ibegin(); t += from; + for (; f != replaced.end(); ++f, ++t) + *t = *f; + } +} + QDeclarativeListModelParser::ListInstruction *QDeclarativeListModelParser::ListModelData::instructions() const { return (QDeclarativeListModelParser::ListInstruction *)((char *)this + sizeof(ListModelData)); @@ -947,23 +969,7 @@ void FlatListModel::setProperty(int index, const QString& property, const QVaria void FlatListModel::move(int from, int to, int n) { - if (n == 1) { - m_values.move(from, to); - } else { - QList > replaced; - int i=0; - QList >::ConstIterator it=m_values.begin(); it += from+n; - for (; i >::ConstIterator f=replaced.begin(); - QList >::Iterator t=m_values.begin(); t += from; - for (; f != replaced.end(); ++f, ++t) - *t = *f; - } + qdeclarativelistmodel_move > >(from, to, n, &m_values); } bool FlatListModel::addValue(const QScriptValue &value, QHash *row, QList *roles) @@ -1130,23 +1136,9 @@ bool NestedListModel::insert(int index, const QScriptValue& valuemap) void NestedListModel::move(int from, int to, int n) { - if (n==1) { - _root->values.move(from,to); - } else { - QList replaced; - int i=0; - QVariantList::const_iterator it=_root->values.begin(); it += from+n; - for (; ivalues.begin(); it += from; - for (; ivalues.begin(); t += from; - for (; f != replaced.end(); ++f, ++t) - *t = *f; - } + if (!_root) + return; + qdeclarativelistmodel_move(from, to, n, &_root->values); } bool NestedListModel::append(const QScriptValue& valuemap) -- cgit v0.12 From c298ed31f8dfa917e5428820aecd39234b4c9097 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 17 Sep 2010 14:55:52 +1000 Subject: Make it clear that private ListModel constructor is only for worker agent. Also set up the worker list copy in the ListModel implementation instead of the agent. --- src/declarative/util/qdeclarativelistmodel.cpp | 37 ++++++++++++++-------- src/declarative/util/qdeclarativelistmodel_p.h | 6 ++-- src/declarative/util/qdeclarativelistmodel_p_p.h | 2 ++ .../util/qdeclarativelistmodelworkeragent.cpp | 8 ++--- 4 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 401e400..0be9122 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -217,17 +217,21 @@ QDeclarativeListModelParser::ListInstruction *QDeclarativeListModelParser::ListM */ QDeclarativeListModel::QDeclarativeListModel(QObject *parent) -: QListModelInterface(parent), m_agent(0), m_nested(new NestedListModel(this)), m_flat(0), m_isWorkerCopy(false) +: QListModelInterface(parent), m_agent(0), m_nested(new NestedListModel(this)), m_flat(0) { } -QDeclarativeListModel::QDeclarativeListModel(bool workerCopy, QObject *parent) -: QListModelInterface(parent), m_agent(0), m_nested(0), m_flat(0), m_isWorkerCopy(workerCopy) +QDeclarativeListModel::QDeclarativeListModel(const QDeclarativeListModel *orig, QDeclarativeListModelWorkerAgent *parent) +: QListModelInterface(parent), m_agent(0), m_nested(0), m_flat(0) { - if (workerCopy) - m_flat = new FlatListModel(this); - else - m_nested = new NestedListModel(this); + m_flat = new FlatListModel(this); + m_flat->m_parentAgent = parent; + + if (orig->m_flat) { + m_flat->m_roles = orig->m_flat->m_roles; + m_flat->m_strings = orig->m_flat->m_strings; + m_flat->m_values = orig->m_flat->m_values; + } } QDeclarativeListModel::~QDeclarativeListModel() @@ -269,6 +273,11 @@ bool QDeclarativeListModel::flatten() return true; } +bool QDeclarativeListModel::inWorkerThread() const +{ + return m_flat && m_flat->m_parentAgent; +} + QDeclarativeListModelWorkerAgent *QDeclarativeListModel::agent() { if (m_agent) @@ -333,7 +342,7 @@ void QDeclarativeListModel::clear() else m_nested->clear(); - if (!m_isWorkerCopy) { + if (!inWorkerThread()) { emit itemsRemoved(0, cleared); emit countChanged(); } @@ -358,7 +367,7 @@ void QDeclarativeListModel::remove(int index) else m_nested->remove(index); - if (!m_isWorkerCopy) { + if (!inWorkerThread()) { emit itemsRemoved(index, 1); emit countChanged(); } @@ -392,7 +401,7 @@ void QDeclarativeListModel::insert(int index, const QScriptValue& valuemap) } bool ok = m_flat ? m_flat->insert(index, valuemap) : m_nested->insert(index, valuemap); - if (ok && !m_isWorkerCopy) { + if (ok && !inWorkerThread()) { emit itemsInserted(index, 1); emit countChanged(); } @@ -438,7 +447,7 @@ void QDeclarativeListModel::move(int from, int to, int n) else m_nested->move(from, to, n); - if (!m_isWorkerCopy) + if (!inWorkerThread()) emit itemsMoved(origfrom, origto, orign); } @@ -529,7 +538,7 @@ void QDeclarativeListModel::set(int index, const QScriptValue& valuemap) else m_nested->set(index, valuemap, &roles); - if (!m_isWorkerCopy) + if (!inWorkerThread()) emit itemsChanged(index, 1, roles); } } @@ -560,7 +569,7 @@ void QDeclarativeListModel::setProperty(int index, const QString& property, cons else m_nested->setProperty(index, property, value, &roles); - if (!m_isWorkerCopy) + if (!inWorkerThread()) emit itemsChanged(index, 1, roles); } @@ -848,7 +857,7 @@ bool QDeclarativeListModelParser::definesEmptyList(const QString &s) */ FlatListModel::FlatListModel(QDeclarativeListModel *base) - : m_scriptEngine(0), m_listModel(base) + : m_scriptEngine(0), m_listModel(base), m_parentAgent(0) { } diff --git a/src/declarative/util/qdeclarativelistmodel_p.h b/src/declarative/util/qdeclarativelistmodel_p.h index 6aff9c6..0a5e3ff 100644 --- a/src/declarative/util/qdeclarativelistmodel_p.h +++ b/src/declarative/util/qdeclarativelistmodel_p.h @@ -98,14 +98,16 @@ private: friend class QDeclarativeListModelWorkerAgent; friend struct ModelNode; + // Constructs a flat list model for a worker agent + QDeclarativeListModel(const QDeclarativeListModel *orig, QDeclarativeListModelWorkerAgent *parent); + QDeclarativeListModel(bool workerCopy, QObject *parent=0); bool flatten(); - bool modifyCheck(); + bool inWorkerThread() const; QDeclarativeListModelWorkerAgent *m_agent; NestedListModel *m_nested; FlatListModel *m_flat; - bool m_isWorkerCopy; }; // ### FIXME diff --git a/src/declarative/util/qdeclarativelistmodel_p_p.h b/src/declarative/util/qdeclarativelistmodel_p_p.h index 8231414..1e9513e 100644 --- a/src/declarative/util/qdeclarativelistmodel_p_p.h +++ b/src/declarative/util/qdeclarativelistmodel_p_p.h @@ -102,6 +102,8 @@ private: QHash m_strings; QList > m_values; QDeclarativeListModel *m_listModel; + + QDeclarativeListModelWorkerAgent *m_parentAgent; }; class NestedListModel diff --git a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp index 4392bed..658584e 100644 --- a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp +++ b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp @@ -83,11 +83,11 @@ void QDeclarativeListModelWorkerAgent::Data::changedChange(int index, int count) } QDeclarativeListModelWorkerAgent::QDeclarativeListModelWorkerAgent(QDeclarativeListModel *model) -: m_engine(0), m_ref(1), m_orig(model), m_copy(new QDeclarativeListModel(true, this)) + : m_engine(0), + m_ref(1), + m_orig(model), + m_copy(new QDeclarativeListModel(m_orig, this)) { - m_copy->m_flat->m_roles = m_orig->m_flat->m_roles; - m_copy->m_flat->m_strings = m_orig->m_flat->m_strings; - m_copy->m_flat->m_values = m_orig->m_flat->m_values; } QDeclarativeListModelWorkerAgent::~QDeclarativeListModelWorkerAgent() -- cgit v0.12 From c2bbef949126826f0330c69dff1a8c96919f69a5 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 17 Sep 2010 15:15:15 +1000 Subject: Changes to objects returned from get() should emit itemsChanged() so that the view is updated (currently the model data changes but the view does not). In flat-model mode, get() now returns a QScriptClass-type object so that changes to the returned object are received, and for nested-model mode, the fix adds a QDeclarativeOpenMetaObject subclass and ModelNode::listIndex so that itemsChanged() can be emitted when the node data changes. Task-number: QTBUG-12363 --- src/declarative/util/qdeclarativelistmodel.cpp | 293 ++++++++++++++++++-- src/declarative/util/qdeclarativelistmodel_p.h | 6 +- src/declarative/util/qdeclarativelistmodel_p_p.h | 121 +++++++- .../util/qdeclarativelistmodelworkeragent.cpp | 25 +- .../util/qdeclarativelistmodelworkeragent_p.h | 4 + .../tst_qdeclarativelistmodel.cpp | 307 +++++++++++++++++++-- 6 files changed, 698 insertions(+), 58 deletions(-) diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 0be9122..68e97b0 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -231,6 +231,10 @@ QDeclarativeListModel::QDeclarativeListModel(const QDeclarativeListModel *orig, m_flat->m_roles = orig->m_flat->m_roles; m_flat->m_strings = orig->m_flat->m_strings; m_flat->m_values = orig->m_flat->m_values; + + m_flat->m_nodeData.reserve(m_flat->m_values.count()); + for (int i=0; im_values.count(); i++) + m_flat->m_nodeData << 0; } } @@ -267,6 +271,10 @@ bool QDeclarativeListModel::flatten() flat->m_strings.insert(s, roles[i]); } + flat->m_nodeData.reserve(flat->m_values.count()); + for (int i=0; im_values.count(); i++) + flat->m_nodeData << 0; + m_flat = flat; delete m_nested; m_nested = 0; @@ -425,7 +433,7 @@ void QDeclarativeListModel::move(int from, int to, int n) { if (n==0 || from==to) return; - if (from+n > count() || to+n > count() || from < 0 || to < 0 || n < 0) { + if (!canMove(from, to, n)) { qmlInfo(this) << tr("move: out of range"); return; } @@ -476,11 +484,15 @@ void QDeclarativeListModel::append(const QScriptValue& valuemap) /*! \qmlmethod object ListModel::get(int index) - Returns the item at \a index in the list model. + Returns the item at \a index in the list model. This allows the item + data to be accessed or modified from JavaScript: \code - fruitModel.append({"cost": 5.95, "name":"Jackfruit"}) - fruitModel.get(0).cost + Component.onCompleted: { + fruitModel.append({"cost": 5.95, "name":"Jackfruit"}); + console.log(fruitModel.get(0).cost); + fruitModel.get(0).cost = 10.95; + } \endcode The \a index must be an element in the list. @@ -495,6 +507,9 @@ void QDeclarativeListModel::append(const QScriptValue& valuemap) fruitModel.get(0).attributes.get(1).value; // == "green" \endcode + \warning The returned object is not guaranteed to remain valid. It + should not be used in \l{Property Binding}{property bindings}. + \sa append() */ QScriptValue QDeclarativeListModel::get(int index) const @@ -736,7 +751,7 @@ void QDeclarativeListModelParser::setCustomData(QObject *obj, const QByteArray & { QDeclarativeListModel *rv = static_cast(obj); - ModelNode *root = new ModelNode; + ModelNode *root = new ModelNode(rv->m_nested); rv->m_nested->_root = root; QStack nodes; nodes << root; @@ -753,7 +768,7 @@ void QDeclarativeListModelParser::setCustomData(QObject *obj, const QByteArray & case ListInstruction::Push: { ModelNode *n = nodes.top(); - ModelNode *n2 = new ModelNode; + ModelNode *n2 = new ModelNode(rv->m_nested); n->values << qVariantFromValue(n2); nodes.push(n2); if (processingSet) @@ -792,7 +807,7 @@ void QDeclarativeListModelParser::setCustomData(QObject *obj, const QByteArray & case ListInstruction::Set: { ModelNode *n = nodes.top(); - ModelNode *n2 = new ModelNode; + ModelNode *n2 = new ModelNode(rv->m_nested); n->properties.insert(QString::fromUtf8(data + instr.dataIdx), n2); nodes.push(n2); processingSet = true; @@ -800,6 +815,13 @@ void QDeclarativeListModelParser::setCustomData(QObject *obj, const QByteArray & break; } } + + ModelNode *rootNode = rv->m_nested->_root; + for (int i=0; ivalues.count(); ++i) { + ModelNode *node = qvariant_cast(rootNode->values[i]); + node->listIndex = i; + node->updateListIndexes(); + } } bool QDeclarativeListModelParser::definesEmptyList(const QString &s) @@ -814,6 +836,7 @@ bool QDeclarativeListModelParser::definesEmptyList(const QString &s) return false; } + /*! \qmlclass ListElement QDeclarativeListElement \ingroup qml-working-with-data @@ -857,12 +880,13 @@ bool QDeclarativeListModelParser::definesEmptyList(const QString &s) */ FlatListModel::FlatListModel(QDeclarativeListModel *base) - : m_scriptEngine(0), m_listModel(base), m_parentAgent(0) + : m_scriptEngine(0), m_listModel(base), m_scriptClass(0), m_parentAgent(0) { } FlatListModel::~FlatListModel() { + qDeleteAll(m_nodeData); } QHash FlatListModel::data(int index, const QList &roles) const @@ -906,11 +930,15 @@ int FlatListModel::count() const void FlatListModel::clear() { m_values.clear(); + + qDeleteAll(m_nodeData); + m_nodeData.clear(); } void FlatListModel::remove(int index) { m_values.removeAt(index); + removedNode(index); } bool FlatListModel::append(const QScriptValue &value) @@ -927,6 +955,8 @@ bool FlatListModel::insert(int index, const QScriptValue &value) return false; m_values.insert(index, row); + insertedNode(index); + return true; } @@ -940,13 +970,17 @@ QScriptValue FlatListModel::get(int index) const if (index < 0 || index >= m_values.count()) return scriptEngine->undefinedValue(); - QScriptValue rv = scriptEngine->newObject(); + FlatListModel *that = const_cast(this); + if (!m_scriptClass) + that->m_scriptClass = new FlatListScriptClass(that, scriptEngine); - QHash row = m_values.at(index); - for (QHash::ConstIterator iter = row.begin(); iter != row.end(); ++iter) - rv.setProperty(m_roles.value(iter.key()), qScriptValueFromValue(scriptEngine, iter.value())); + FlatNodeData *data = m_nodeData.value(index); + if (!data) { + data = new FlatNodeData(index); + that->m_nodeData.replace(index, data); + } - return rv; + return QScriptDeclarativeClass::newObject(scriptEngine, m_scriptClass, new FlatNodeObjectData(data)); } void FlatListModel::set(int index, const QScriptValue &value, QList *roles) @@ -979,6 +1013,7 @@ void FlatListModel::setProperty(int index, const QString& property, const QVaria void FlatListModel::move(int from, int to, int n) { qdeclarativelistmodel_move > >(from, to, n, &m_values); + moveNodes(from, to, n); } bool FlatListModel::addValue(const QScriptValue &value, QHash *row, QList *roles) @@ -1008,6 +1043,139 @@ bool FlatListModel::addValue(const QScriptValue &value, QHash *ro return true; } +void FlatListModel::insertedNode(int index) +{ + if (index >= 0 && index <= m_values.count()) { + m_nodeData.insert(index, 0); + + for (int i=index + 1; iindex = i; + } + } +} + +void FlatListModel::removedNode(int index) +{ + if (index >= 0 && index < m_nodeData.count()) { + delete m_nodeData.takeAt(index); + + for (int i=index; iindex = i; + } + } +} + +void FlatListModel::moveNodes(int from, int to, int n) +{ + if (!m_listModel->canMove(from, to, n)) + return; + + qdeclarativelistmodel_move >(from, to, n, &m_nodeData); + + for (int i=from; iindex = i; + } +} + + + +FlatNodeData::~FlatNodeData() +{ + for (QSet::Iterator iter = objects.begin(); iter != objects.end(); ++iter) { + FlatNodeObjectData *data = *iter; + data->nodeData = 0; + } +} + +void FlatNodeData::addData(FlatNodeObjectData *data) +{ + objects.insert(data); +} + +void FlatNodeData::removeData(FlatNodeObjectData *data) +{ + objects.remove(data); +} + + +FlatListScriptClass::FlatListScriptClass(FlatListModel *model, QScriptEngine *seng) + : QScriptDeclarativeClass(seng), + m_model(model) +{ +} + +QScriptDeclarativeClass::Value FlatListScriptClass::property(Object *obj, const Identifier &name) +{ + FlatNodeObjectData *objData = static_cast(obj); + if (!objData->nodeData) // item at this index has been deleted + return QScriptDeclarativeClass::Value(engine(), engine()->undefinedValue()); + + int index = objData->nodeData->index; + QString propName = toString(name); + int role = m_model->m_strings.value(propName, -1); + + if (role >= 0 && index >=0 ) { + const QHash &row = m_model->m_values[index]; + QScriptValue sv = engine()->toScriptValue(row[role]); + return QScriptDeclarativeClass::Value(engine(), sv); + } + + return QScriptDeclarativeClass::Value(engine(), engine()->undefinedValue()); +} + +void FlatListScriptClass::setProperty(Object *obj, const Identifier &name, const QScriptValue &value) +{ + if (!value.isVariant() && !value.isRegExp() && !value.isDate() && value.isObject()) { + qmlInfo(m_model->m_listModel) << "Cannot add nested list values when modifying or after modification from a worker script"; + return; + } + + FlatNodeObjectData *objData = static_cast(obj); + if (!objData->nodeData) // item at this index has been deleted + return; + + int index = objData->nodeData->index; + QString propName = toString(name); + + int role = m_model->m_strings.value(propName, -1); + if (role >= 0 && index >= 0) { + QHash &row = m_model->m_values[index]; + row[role] = value.toVariant(); + + if (m_model->m_parentAgent) { + // This is the list in the worker thread, so tell the agent to + // emit itemsChanged() later + m_model->m_parentAgent->changedData(index, 1); + } else { + // This is the list in the main thread, so emit itemsChanged() + QList roles; + roles << role; + emit m_model->m_listModel->itemsChanged(index, 1, roles); + } + } +} + +QScriptClass::QueryFlags FlatListScriptClass::queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags) +{ + return (QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess); +} + +bool FlatListScriptClass::compare(Object *obj1, Object *obj2) +{ + FlatNodeObjectData *data1 = static_cast(obj1); + FlatNodeObjectData *data2 = static_cast(obj2); + + if (!data1->nodeData || !data2->nodeData) + return false; + + return data1->nodeData->index == data2->nodeData->index; +} + + + NestedListModel::NestedListModel(QDeclarativeListModel *base) : _root(0), m_ownsRoot(false), m_listModel(base), _rolesOk(false) { @@ -1133,11 +1301,12 @@ void NestedListModel::remove(int index) bool NestedListModel::insert(int index, const QScriptValue& valuemap) { if (!_root) { - _root = new ModelNode; + _root = new ModelNode(this); m_ownsRoot = true; } - ModelNode *mn = new ModelNode; + ModelNode *mn = new ModelNode(this); + mn->listIndex = index; mn->setObjectValue(valuemap); _root->values.insert(index,qVariantFromValue(mn)); return true; @@ -1153,12 +1322,11 @@ void NestedListModel::move(int from, int to, int n) bool NestedListModel::append(const QScriptValue& valuemap) { if (!_root) { - _root = new ModelNode; + _root = new ModelNode(this); m_ownsRoot = true; } - ModelNode *mn = new ModelNode; - mn->setObjectValue(valuemap); - _root->values << qVariantFromValue(mn); + + insert(count(), valuemap); return true; } @@ -1253,8 +1421,8 @@ QString NestedListModel::toString(int role) const } -ModelNode::ModelNode() -: modelCache(0), objectCache(0), isArray(false) +ModelNode::ModelNode(NestedListModel *model) +: modelCache(0), objectCache(0), isArray(false), m_model(model), listIndex(-1) { } @@ -1278,18 +1446,18 @@ void ModelNode::clear() properties.clear(); } -void ModelNode::setObjectValue(const QScriptValue& valuemap) { +void ModelNode::setObjectValue(const QScriptValue& valuemap, bool writeToCache) { QScriptValueIterator it(valuemap); while (it.hasNext()) { it.next(); - ModelNode *value = new ModelNode; + ModelNode *value = new ModelNode(m_model); QScriptValue v = it.value(); if (v.isArray()) { value->isArray = true; value->setListValue(v); } else { value->values << v.toVariant(); - if (objectCache) + if (writeToCache && objectCache) objectCache->setValue(it.name().toUtf8(), value->values.last()); } if (properties.contains(it.name())) @@ -1302,14 +1470,16 @@ void ModelNode::setListValue(const QScriptValue& valuelist) { values.clear(); int size = valuelist.property(QLatin1String("length")).toInt32(); for (int i=0; iisArray = true; value->setListValue(v); } else if (v.isObject()) { + value->listIndex = i; value->setObjectValue(v); } else { + value->listIndex = i; value->values << v.toVariant(); } values.append(qVariantFromValue(value)); @@ -1321,7 +1491,7 @@ void ModelNode::setProperty(const QString& prop, const QVariant& val) { if (it != properties.end()) { (*it)->values[0] = val; } else { - ModelNode *n = new ModelNode; + ModelNode *n = new ModelNode(m_model); n->values << val; properties.insert(prop,n); } @@ -1329,6 +1499,40 @@ void ModelNode::setProperty(const QString& prop, const QVariant& val) { objectCache->setValue(prop.toUtf8(), val); } +void ModelNode::updateListIndexes() +{ + for (QHash::ConstIterator iter = properties.begin(); iter != properties.end(); ++iter) { + ModelNode *node = iter.value(); + if (node->isArray) { + for (int i=0; ivalues.count(); ++i) { + ModelNode *subNode = qvariant_cast(node->values.at(i)); + if (subNode) + subNode->listIndex = i; + } + } + node->updateListIndexes(); + } +} + +/* + Need to call this to emit itemsChanged() for modifications outside of set() + and setProperty(), i.e. if an item returned from get() is modified +*/ +void ModelNode::changedProperty(const QString &name) const +{ + if (listIndex < 0) + return; + + m_model->checkRoles(); + QList roles; + int role = m_model->roleStrings.indexOf(name); + if (role < 0) + roles = m_model->roles(); + else + roles << role; + emit m_model->m_listModel->itemsChanged(listIndex, 1, roles); +} + void ModelNode::dump(ModelNode *node, int ind) { QByteArray indentBa(ind * 4, ' '); @@ -1350,16 +1554,47 @@ void ModelNode::dump(ModelNode *node, int ind) } } -ModelObject::ModelObject() -: _mo(new QDeclarativeOpenMetaObject(this)) +ModelObject::ModelObject(ModelNode *node, NestedListModel *model, QScriptEngine *seng) + : m_model(model), + m_node(node), + m_meta(new ModelNodeMetaObject(seng, this)) { } void ModelObject::setValue(const QByteArray &name, const QVariant &val) { - _mo->setValue(name, val); + m_meta->setValue(name, val); setProperty(name.constData(), val); } +void ModelObject::setNodeUpdatesEnabled(bool enable) +{ + m_meta->m_enabled = enable; +} + + +ModelNodeMetaObject::ModelNodeMetaObject(QScriptEngine *seng, ModelObject *object) + : QDeclarativeOpenMetaObject(object), + m_enabled(false), + m_seng(seng), + m_obj(object) +{ +} + +void ModelNodeMetaObject::propertyWritten(int index) +{ + if (!m_enabled) + return; + + QString propName = QString::fromUtf8(name(index)); + QVariant value = operator[](index); + + QScriptValue sv = m_seng->newObject(); + sv.setProperty(propName, m_seng->newVariant(value)); + m_obj->m_node->setObjectValue(sv, false); + + m_obj->m_node->changedProperty(propName); +} + QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativelistmodel_p.h b/src/declarative/util/qdeclarativelistmodel_p.h index 0a5e3ff..fe42ef6 100644 --- a/src/declarative/util/qdeclarativelistmodel_p.h +++ b/src/declarative/util/qdeclarativelistmodel_p.h @@ -63,6 +63,7 @@ class FlatListModel; class NestedListModel; class QDeclarativeListModelWorkerAgent; struct ModelNode; +class FlatListScriptClass; class Q_DECLARATIVE_EXPORT QDeclarativeListModel : public QListModelInterface { Q_OBJECT @@ -96,15 +97,18 @@ Q_SIGNALS: private: friend class QDeclarativeListModelParser; friend class QDeclarativeListModelWorkerAgent; + friend class FlatListModel; + friend class FlatListScriptClass; friend struct ModelNode; // Constructs a flat list model for a worker agent QDeclarativeListModel(const QDeclarativeListModel *orig, QDeclarativeListModelWorkerAgent *parent); - QDeclarativeListModel(bool workerCopy, QObject *parent=0); bool flatten(); bool inWorkerThread() const; + inline bool canMove(int from, int to, int n) const { return !(from+n > count() || to+n > count() || from < 0 || to < 0 || n < 0); } + QDeclarativeListModelWorkerAgent *m_agent; NestedListModel *m_nested; FlatListModel *m_flat; diff --git a/src/declarative/util/qdeclarativelistmodel_p_p.h b/src/declarative/util/qdeclarativelistmodel_p_p.h index 1e9513e..acf4f3e 100644 --- a/src/declarative/util/qdeclarativelistmodel_p_p.h +++ b/src/declarative/util/qdeclarativelistmodel_p_p.h @@ -54,9 +54,11 @@ // #include "private/qdeclarativelistmodel_p.h" - -#include "qdeclarative.h" #include "private/qdeclarativeengine_p.h" +#include "private/qdeclarativeopenmetaobject_p.h" +#include "qdeclarative.h" + +#include QT_BEGIN_HEADER @@ -68,6 +70,8 @@ class QDeclarativeOpenMetaObject; class QScriptEngine; class QDeclarativeListModelWorkerAgent; struct ModelNode; +class FlatListScriptClass; +class FlatNodeData; class FlatListModel { @@ -94,8 +98,13 @@ public: private: friend class QDeclarativeListModelWorkerAgent; friend class QDeclarativeListModel; + friend class FlatListScriptClass; + friend class FlatNodeData; bool addValue(const QScriptValue &value, QHash *row, QList *roles); + void insertedNode(int index); + void removedNode(int index); + void moveNodes(int from, int to, int n); QScriptEngine *m_scriptEngine; QHash m_roles; @@ -103,9 +112,68 @@ private: QList > m_values; QDeclarativeListModel *m_listModel; + FlatListScriptClass *m_scriptClass; + QList m_nodeData; QDeclarativeListModelWorkerAgent *m_parentAgent; }; + +/* + Created when get() is called on a FlatListModel. This allows changes to the + object returned by get() to be tracked, and passed onto the model. +*/ +class FlatListScriptClass : public QScriptDeclarativeClass +{ +public: + FlatListScriptClass(FlatListModel *model, QScriptEngine *seng); + + Value property(Object *, const Identifier &); + void setProperty(Object *, const Identifier &name, const QScriptValue &); + QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags); + bool compare(Object *, Object *); + +private: + FlatListModel *m_model; +}; + +/* + FlatNodeData and FlatNodeObjectData allow objects returned by get() to still + point to the correct list index if move(), insert() or remove() are called. +*/ +struct FlatNodeObjectData; +class FlatNodeData +{ +public: + FlatNodeData(int i) + : index(i) {} + + ~FlatNodeData(); + + void addData(FlatNodeObjectData *data); + void removeData(FlatNodeObjectData *data); + + int index; + +private: + QSet objects; +}; + +struct FlatNodeObjectData : public QScriptDeclarativeClass::Object +{ + FlatNodeObjectData(FlatNodeData *data) : nodeData(data) { + nodeData->addData(this); + } + + ~FlatNodeObjectData() { + if (nodeData) + nodeData->removeData(this); + } + + FlatNodeData *nodeData; +}; + + + class NestedListModel { public: @@ -136,25 +204,50 @@ public: QDeclarativeListModel *m_listModel; private: + friend struct ModelNode; mutable QStringList roleStrings; mutable bool _rolesOk; }; +class ModelNodeMetaObject; class ModelObject : public QObject { Q_OBJECT public: - ModelObject(); + ModelObject(ModelNode *node, NestedListModel *model, QScriptEngine *seng); void setValue(const QByteArray &name, const QVariant &val); + void setNodeUpdatesEnabled(bool enable); + + NestedListModel *m_model; + ModelNode *m_node; private: - QDeclarativeOpenMetaObject *_mo; + ModelNodeMetaObject *m_meta; }; +class ModelNodeMetaObject : public QDeclarativeOpenMetaObject +{ +public: + ModelNodeMetaObject(QScriptEngine *seng, ModelObject *object); + + bool m_enabled; + +protected: + void propertyWritten(int index); + +private: + QScriptEngine *m_seng; + ModelObject *m_obj; +}; + + +/* + A ModelNode is created for each item in a NestedListModel. +*/ struct ModelNode { - ModelNode(); + ModelNode(NestedListModel *model); ~ModelNode(); QList values; @@ -167,30 +260,44 @@ struct ModelNode modelCache = new QDeclarativeListModel; QDeclarativeEngine::setContextForObject(modelCache,QDeclarativeEngine::contextForObject(model->m_listModel)); modelCache->m_nested->_root = this; // ListModel defaults to nestable model + + for (int i=0; i(values.at(i)); + if (subNode) + subNode->m_model = modelCache->m_nested; + } } return modelCache; } ModelObject *object(const NestedListModel *model) { if (!objectCache) { - objectCache = new ModelObject(); + objectCache = new ModelObject(this, + const_cast(model), + QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(model->m_listModel))); QHash::iterator it; for (it = properties.begin(); it != properties.end(); ++it) { objectCache->setValue(it.key().toUtf8(), model->valueForNode(*it)); } + objectCache->setNodeUpdatesEnabled(true); } return objectCache; } - void setObjectValue(const QScriptValue& valuemap); + void setObjectValue(const QScriptValue& valuemap, bool writeToCache = true); void setListValue(const QScriptValue& valuelist); void setProperty(const QString& prop, const QVariant& val); + void changedProperty(const QString &name) const; + void updateListIndexes(); static void dump(ModelNode *node, int ind); QDeclarativeListModel *modelCache; ModelObject *objectCache; bool isArray; + + NestedListModel *m_model; + int listIndex; // only used for top-level nodes within a list }; diff --git a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp index 658584e..6804d4a 100644 --- a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp +++ b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp @@ -86,7 +86,7 @@ QDeclarativeListModelWorkerAgent::QDeclarativeListModelWorkerAgent(QDeclarativeL : m_engine(0), m_ref(1), m_orig(model), - m_copy(new QDeclarativeListModel(m_orig, this)) + m_copy(new QDeclarativeListModel(model, this)) { } @@ -194,6 +194,11 @@ void QDeclarativeListModelWorkerAgent::sync() mutex.unlock(); } +void QDeclarativeListModelWorkerAgent::changedData(int index, int count) +{ + data.changedChange(index, count); +} + bool QDeclarativeListModelWorkerAgent::event(QEvent *e) { if (e->type() == QEvent::User) { @@ -216,6 +221,24 @@ bool QDeclarativeListModelWorkerAgent::event(QEvent *e) orig->m_strings = copy->m_strings; orig->m_values = copy->m_values; + // update the orig->m_nodeData list + for (int ii = 0; ii < changes.count(); ++ii) { + const Change &change = changes.at(ii); + switch (change.type) { + case Change::Inserted: + orig->insertedNode(change.index); + break; + case Change::Removed: + orig->removedNode(change.index); + break; + case Change::Moved: + orig->moveNodes(change.index, change.to, change.count); + break; + case Change::Changed: + break; + } + } + syncDone.wakeAll(); locker.unlock(); diff --git a/src/declarative/util/qdeclarativelistmodelworkeragent_p.h b/src/declarative/util/qdeclarativelistmodelworkeragent_p.h index 01da374..10c3bca 100644 --- a/src/declarative/util/qdeclarativelistmodelworkeragent_p.h +++ b/src/declarative/util/qdeclarativelistmodelworkeragent_p.h @@ -67,6 +67,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeListModel; +class FlatListScriptClass; class QDeclarativeListModelWorkerAgent : public QObject { @@ -115,6 +116,7 @@ protected: private: friend class QDeclarativeWorkerScriptEnginePrivate; + friend class FlatListScriptClass; QScriptEngine *m_engine; struct Change { @@ -141,6 +143,8 @@ private: QDeclarativeListModel *list; }; + void changedData(int index, int count); + QAtomicInt m_ref; QDeclarativeListModel *m_orig; QDeclarativeListModel *m_copy; diff --git a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp index 10805b4..70ec416 100644 --- a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp +++ b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include "../../../shared/util.h" @@ -57,6 +58,8 @@ #define SRCDIR "." #endif +Q_DECLARE_METATYPE(QList) + class tst_qdeclarativelistmodel : public QObject { Q_OBJECT @@ -64,6 +67,7 @@ public: tst_qdeclarativelistmodel() {} private: + int roleFromName(const QDeclarativeListModel *model, const QString &roleName); QScriptValue nestedListValue(QScriptEngine *eng) const; QDeclarativeItem *createWorkerTest(QDeclarativeEngine *eng, QDeclarativeComponent *component, QDeclarativeListModel *model); void waitForWorker(QDeclarativeItem *item); @@ -78,6 +82,8 @@ private slots: void dynamic(); void dynamic_worker_data(); void dynamic_worker(); + void dynamic_worker_sync_data(); + void dynamic_worker_sync(); void convertNestedToFlat_fail(); void convertNestedToFlat_fail_data(); void convertNestedToFlat_ok(); @@ -86,7 +92,23 @@ private slots: void error_data(); void error(); void set(); + void get(); + void get_data(); + void get_worker(); + void get_worker_data(); + void get_nested(); + void get_nested_data(); }; +int tst_qdeclarativelistmodel::roleFromName(const QDeclarativeListModel *model, const QString &roleName) +{ + QList roles = model->roles(); + for (int i=0; itoString(roles[i]) == roleName) + return roles[i]; + } + Q_ASSERT(false); + return -1; +} QScriptValue tst_qdeclarativelistmodel::nestedListValue(QScriptEngine *eng) const { @@ -196,6 +218,10 @@ void tst_qdeclarativelistmodel::dynamic_data() QTest::newRow("get1") << "{get(0) === undefined}" << 1 << ""; QTest::newRow("get2") << "{get(-1) === undefined}" << 1 << ""; QTest::newRow("get3") << "{append({'foo':123});get(0) != undefined}" << 1 << ""; + QTest::newRow("get4") << "{append({'foo':123});get(0).foo}" << 123 << ""; + + QTest::newRow("get-modify1") << "{append({'foo':123,'bar':456});get(0).foo = 333;get(0).foo}" << 333 << ""; + QTest::newRow("get-modify2") << "{append({'z':1});append({'foo':123,'bar':456});get(1).bar = 999;get(1).bar}" << 999 << ""; QTest::newRow("append1") << "{append({'foo':123});count}" << 1 << ""; QTest::newRow("append2") << "{append({'foo':123,'bar':456});count}" << 1 << ""; @@ -310,8 +336,12 @@ void tst_qdeclarativelistmodel::dynamic_worker() QFETCH(int, result); QFETCH(QString, warning); + if (QByteArray(QTest::currentDataTag()).startsWith("nested")) + return; + // This is same as dynamic() except it applies the test to a ListModel called - // from a WorkerScript (i.e. testing the internal NestedListModel class) + // from a WorkerScript (i.e. testing the internal FlatListModel that is created + // by the WorkerListModelAgent) QDeclarativeListModel model; QDeclarativeEngine eng; @@ -330,27 +360,62 @@ void tst_qdeclarativelistmodel::dynamic_worker() if (!warning.isEmpty()) QTest::ignoreMessage(QtWarningMsg, warning.toLatin1()); - if (operations.count() == 1) { - // test count(), get() return the correct default values in the worker list model - QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker", - Q_ARG(QVariant, operations))); - waitForWorker(item); - QCOMPARE(QDeclarativeProperty(item, "result").read().toInt(), result); - } else { - // execute a set of commands on the worker list model, then check the - // changes are reflected in the list model in the main thread - if (QByteArray(QTest::currentDataTag()).startsWith("nested")) - QTest::ignoreMessage(QtWarningMsg, ": QML ListModel: Cannot add nested list values when modifying or after modification from a worker script"); - - QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker", - Q_ARG(QVariant, operations.mid(0, operations.length()-1)))); - waitForWorker(item); - - QDeclarativeExpression e(eng.rootContext(), &model, operations.last().toString()); - if (!QByteArray(QTest::currentDataTag()).startsWith("nested")) - QCOMPARE(e.evaluate().toInt(), result); + QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker", + Q_ARG(QVariant, operations))); + waitForWorker(item); + QCOMPARE(QDeclarativeProperty(item, "result").read().toInt(), result); + + delete item; + qApp->processEvents(); +} + + + +void tst_qdeclarativelistmodel::dynamic_worker_sync_data() +{ + dynamic_data(); +} + +void tst_qdeclarativelistmodel::dynamic_worker_sync() +{ + QFETCH(QString, script); + QFETCH(int, result); + QFETCH(QString, warning); + + // This is the same as dynamic_worker() except that it executes a set of list operations + // from the worker script, calls sync(), and tests the changes are reflected in the + // list in the main thread + + QDeclarativeListModel model; + QDeclarativeEngine eng; + QDeclarativeComponent component(&eng, QUrl::fromLocalFile(SRCDIR "/data/model.qml")); + QDeclarativeItem *item = createWorkerTest(&eng, &component, &model); + QVERIFY(item != 0); + + if (script[0] == QLatin1Char('{') && script[script.length()-1] == QLatin1Char('}')) + script = script.mid(1, script.length() - 2); + QVariantList operations; + foreach (const QString &s, script.split(';')) { + if (!s.isEmpty()) + operations << s; } + if (!warning.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, warning.toLatin1()); + + // execute a set of commands on the worker list model, then check the + // changes are reflected in the list model in the main thread + if (QByteArray(QTest::currentDataTag()).startsWith("nested")) + QTest::ignoreMessage(QtWarningMsg, ": QML ListModel: Cannot add nested list values when modifying or after modification from a worker script"); + + QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker", + Q_ARG(QVariant, operations.mid(0, operations.length()-1)))); + waitForWorker(item); + + QDeclarativeExpression e(eng.rootContext(), &model, operations.last().toString()); + if (!QByteArray(QTest::currentDataTag()).startsWith("nested")) + QCOMPARE(e.evaluate().toInt(), result); + delete item; qApp->processEvents(); } @@ -595,6 +660,9 @@ void tst_qdeclarativelistmodel::error() } } +/* + Test model changes from set() are available to the view +*/ void tst_qdeclarativelistmodel::set() { QDeclarativeEngine engine; @@ -618,6 +686,205 @@ void tst_qdeclarativelistmodel::set() QCOMPARE(model.data(0, model.roles()[0]), qVariantFromValue(false)); } +/* + Test model changes on values returned by get() are available to the view +*/ +void tst_qdeclarativelistmodel::get() +{ + QFETCH(QString, expression); + QFETCH(int, index); + QFETCH(QString, roleName); + QFETCH(QVariant, roleValue); + + QDeclarativeEngine eng; + QDeclarativeComponent component(&eng); + component.setData( + "import Qt 4.7\n" + "ListModel { \n" + "ListElement { roleA: 100 }\n" + "ListElement { roleA: 200; roleB: 400 } \n" + "ListElement { roleA: 200; roleB: 400 } \n" + "}", QUrl()); + QDeclarativeListModel *model = qobject_cast(component.create()); + int role = roleFromName(model, roleName); + + QSignalSpy spy(model, SIGNAL(itemsChanged(int, int, QList))); + QDeclarativeExpression expr(eng.rootContext(), model, expression); + expr.evaluate(); + QVERIFY(!expr.hasError()); + + QCOMPARE(model->data(index, role), roleValue); + QCOMPARE(spy.count(), 1); + + QList spyResult = spy.takeFirst(); + QCOMPARE(spyResult.at(0).toInt(), index); + QCOMPARE(spyResult.at(1).toInt(), 1); // only 1 item is modified at a time + QCOMPARE(spyResult.at(2).value >(), (QList() << role)); +} + +void tst_qdeclarativelistmodel::get_data() +{ + QTest::addColumn("expression"); + QTest::addColumn("index"); + QTest::addColumn("roleName"); + QTest::addColumn("roleValue"); + + QTest::newRow("simple value") << "get(0).roleA = 500" << 0 << "roleA" << QVariant(500); + QTest::newRow("simple value 2") << "get(1).roleB = 500" << 1 << "roleB" << QVariant(500); + + QVariantMap map; + map["zzz"] = 123; + QTest::newRow("object value") << "get(1).roleB = {'zzz':123}" << 1 << "roleB" << QVariant::fromValue(map); + + QVariantList list; + map.clear(); map["a"] = 50; map["b"] = 500; + list << map; + map.clear(); map["c"] = 1000; + list << map; + QTest::newRow("list of objects") << "get(2).roleB = [{'a': 50, 'b': 500}, {'c': 1000}]" << 2 << "roleB" << QVariant::fromValue(list); +} + +void tst_qdeclarativelistmodel::get_worker() +{ + QFETCH(QString, expression); + QFETCH(int, index); + QFETCH(QString, roleName); + QFETCH(QVariant, roleValue); + + QDeclarativeListModel model; + QDeclarativeEngine eng; + QDeclarativeComponent component(&eng, QUrl::fromLocalFile(SRCDIR "/data/model.qml")); + QDeclarativeItem *item = createWorkerTest(&eng, &component, &model); + QVERIFY(item != 0); + QScriptEngine *seng = QDeclarativeEnginePrivate::getScriptEngine(&eng); + + // Add some values like get() test + QScriptValue sv = seng->newObject(); + sv.setProperty(QLatin1String("roleA"), seng->newVariant(QVariant::fromValue(100))); + model.append(sv); + sv = seng->newObject(); + sv.setProperty(QLatin1String("roleA"), seng->newVariant(QVariant::fromValue(200))); + sv.setProperty(QLatin1String("roleB"), seng->newVariant(QVariant::fromValue(400))); + model.append(sv); + model.append(sv); + int role = roleFromName(&model, roleName); + + const char *warning = ": QML ListModel: Cannot add nested list values when modifying or after modification from a worker script"; + if (roleValue.type() == QVariant::List || roleValue.type() == QVariant::Map) + QTest::ignoreMessage(QtWarningMsg, warning); + QSignalSpy spy(&model, SIGNAL(itemsChanged(int, int, QList))); + + // in the worker thread, change the model data and call sync() + QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker", + Q_ARG(QVariant, QStringList(expression)))); + waitForWorker(item); + + // see if we receive the model changes in the main thread's model + if (roleValue.type() == QVariant::List || roleValue.type() == QVariant::Map) { + QVERIFY(model.data(index, role) != roleValue); + QCOMPARE(spy.count(), 0); + } else { + QCOMPARE(model.data(index, role), roleValue); + QCOMPARE(spy.count(), 1); + + QList spyResult = spy.takeFirst(); + QCOMPARE(spyResult.at(0).toInt(), index); + QCOMPARE(spyResult.at(1).toInt(), 1); // only 1 item is modified at a time + QVERIFY(spyResult.at(2).value >().contains(role)); + } +} + +void tst_qdeclarativelistmodel::get_worker_data() +{ + get_data(); +} + +/* + Test that the tests run in get() also work for nested list data +*/ +void tst_qdeclarativelistmodel::get_nested() +{ + QFETCH(QString, expression); + QFETCH(int, index); + QFETCH(QString, roleName); + QFETCH(QVariant, roleValue); + + QDeclarativeEngine eng; + QDeclarativeComponent component(&eng); + component.setData( + "import Qt 4.7\n" + "ListModel { \n" + "ListElement {\n" + "listRoleA: [\n" + "ListElement { roleA: 100 },\n" + "ListElement { roleA: 200; roleB: 400 },\n" + "ListElement { roleA: 200; roleB: 400 } \n" + "]\n" + "}\n" + "ListElement {\n" + "listRoleA: [\n" + "ListElement { roleA: 100 },\n" + "ListElement { roleA: 200; roleB: 400 },\n" + "ListElement { roleA: 200; roleB: 400 } \n" + "]\n" + "listRoleB: [\n" + "ListElement { roleA: 100 },\n" + "ListElement { roleA: 200; roleB: 400 },\n" + "ListElement { roleA: 200; roleB: 400 } \n" + "]\n" + "listRoleC: [\n" + "ListElement { roleA: 100 },\n" + "ListElement { roleA: 200; roleB: 400 },\n" + "ListElement { roleA: 200; roleB: 400 } \n" + "]\n" + "}\n" + "}", QUrl()); + QDeclarativeListModel *model = qobject_cast(component.create()); + QVERIFY(component.errorString().isEmpty()); + QDeclarativeListModel *childModel; + + // Test setting the inner list data for: + // get(0).listRoleA + // get(1).listRoleA + // get(1).listRoleB + // get(1).listRoleC + + QList > testData; + testData << qMakePair(0, QString("listRoleA")); + testData << qMakePair(1, QString("listRoleA")); + testData << qMakePair(1, QString("listRoleB")); + testData << qMakePair(1, QString("listRoleC")); + + for (int i=0; i(model->data(outerListIndex, outerListRole).value()); + QVERIFY(childModel); + + QString extendedExpression = QString("get(%1).%2.%3").arg(outerListIndex).arg(outerListRoleName).arg(expression); + QDeclarativeExpression expr(eng.rootContext(), model, extendedExpression); + + QSignalSpy spy(childModel, SIGNAL(itemsChanged(int, int, QList))); + expr.evaluate(); + QVERIFY(!expr.hasError()); + + int role = roleFromName(childModel, roleName); + QCOMPARE(childModel->data(index, role), roleValue); + QCOMPARE(spy.count(), 1); + + QList spyResult = spy.takeFirst(); + QCOMPARE(spyResult.at(0).toInt(), index); + QCOMPARE(spyResult.at(1).toInt(), 1); // only 1 item is modified at a time + QCOMPARE(spyResult.at(2).value >(), (QList() << role)); + } +} + +void tst_qdeclarativelistmodel::get_nested_data() +{ + get_data(); +} QTEST_MAIN(tst_qdeclarativelistmodel) -- cgit v0.12 From af29c555a29ebcdb1d962176912478212c9c7e65 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Fri, 17 Sep 2010 15:33:22 +1000 Subject: Improve error messages --- src/declarative/util/qdeclarativelistmodel.cpp | 6 +++--- .../qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 68e97b0..2d8b946 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -292,7 +292,7 @@ QDeclarativeListModelWorkerAgent *QDeclarativeListModel::agent() return m_agent; if (!flatten()) { - qmlInfo(this) << "List contains nested list values and cannot be used from a worker script"; + qmlInfo(this) << "List contains list-type data and cannot be used from a worker script"; return 0; } @@ -1023,7 +1023,7 @@ bool FlatListModel::addValue(const QScriptValue &value, QHash *ro it.next(); QScriptValue value = it.value(); if (!value.isVariant() && !value.isRegExp() && !value.isDate() && value.isObject()) { - qmlInfo(m_listModel) << "Cannot add nested list values when modifying or after modification from a worker script"; + qmlInfo(m_listModel) << "Cannot add list-type data when modifying or after modification from a worker script"; return false; } @@ -1129,7 +1129,7 @@ QScriptDeclarativeClass::Value FlatListScriptClass::property(Object *obj, const void FlatListScriptClass::setProperty(Object *obj, const Identifier &name, const QScriptValue &value) { if (!value.isVariant() && !value.isRegExp() && !value.isDate() && value.isObject()) { - qmlInfo(m_model->m_listModel) << "Cannot add nested list values when modifying or after modification from a worker script"; + qmlInfo(m_model->m_listModel) << "Cannot add list-type data when modifying or after modification from a worker script"; return; } diff --git a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp index 70ec416..f456778 100644 --- a/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp +++ b/tests/auto/declarative/qdeclarativelistmodel/tst_qdeclarativelistmodel.cpp @@ -406,7 +406,7 @@ void tst_qdeclarativelistmodel::dynamic_worker_sync() // execute a set of commands on the worker list model, then check the // changes are reflected in the list model in the main thread if (QByteArray(QTest::currentDataTag()).startsWith("nested")) - QTest::ignoreMessage(QtWarningMsg, ": QML ListModel: Cannot add nested list values when modifying or after modification from a worker script"); + QTest::ignoreMessage(QtWarningMsg, ": QML ListModel: Cannot add list-type data when modifying or after modification from a worker script"); QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker", Q_ARG(QVariant, operations.mid(0, operations.length()-1)))); @@ -439,7 +439,7 @@ void tst_qdeclarativelistmodel::convertNestedToFlat_fail() model.append(nestedListValue(&s_eng)); QCOMPARE(model.count(), 2); - QTest::ignoreMessage(QtWarningMsg, ": QML ListModel: List contains nested list values and cannot be used from a worker script"); + QTest::ignoreMessage(QtWarningMsg, ": QML ListModel: List contains list-type data and cannot be used from a worker script"); QVERIFY(QMetaObject::invokeMethod(item, "evalExpressionViaWorker", Q_ARG(QVariant, script))); waitForWorker(item); @@ -491,7 +491,7 @@ void tst_qdeclarativelistmodel::convertNestedToFlat_ok() QCOMPARE(model.count(), count+1); QScriptValue nested = nestedListValue(&s_eng); - const char *warning = ": QML ListModel: Cannot add nested list values when modifying or after modification from a worker script"; + const char *warning = ": QML ListModel: Cannot add list-type data when modifying or after modification from a worker script"; QTest::ignoreMessage(QtWarningMsg, warning); model.append(nested); @@ -769,7 +769,7 @@ void tst_qdeclarativelistmodel::get_worker() model.append(sv); int role = roleFromName(&model, roleName); - const char *warning = ": QML ListModel: Cannot add nested list values when modifying or after modification from a worker script"; + const char *warning = ": QML ListModel: Cannot add list-type data when modifying or after modification from a worker script"; if (roleValue.type() == QVariant::List || roleValue.type() == QVariant::Map) QTest::ignoreMessage(QtWarningMsg, warning); QSignalSpy spy(&model, SIGNAL(itemsChanged(int, int, QList))); -- cgit v0.12 From eef26bc8521da62db0dced6796eceb7c27f64160 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 17 Sep 2010 15:34:44 +1000 Subject: Autotest and small fix for QDeclarativeFontLoader. --- src/declarative/util/qdeclarativefontloader.cpp | 6 +-- .../qdeclarativefontloader/data/daniel.ttf | Bin 0 -> 51984 bytes .../tst_qdeclarativefontloader.cpp | 42 +++++++++++++++++++++ 3 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativefontloader/data/daniel.ttf diff --git a/src/declarative/util/qdeclarativefontloader.cpp b/src/declarative/util/qdeclarativefontloader.cpp index 91588b7..6879494 100644 --- a/src/declarative/util/qdeclarativefontloader.cpp +++ b/src/declarative/util/qdeclarativefontloader.cpp @@ -210,11 +210,7 @@ void QDeclarativeFontLoader::setSource(const QUrl &url) updateFontInfo(QString(), Error); } } else { - QDeclarativeFontObject *fo = d->fonts[d->url]; - d->name = QFontDatabase::applicationFontFamilies(fo->id).at(0); - emit nameChanged(); - d->status = QDeclarativeFontLoader::Ready; - emit statusChanged(); + updateFontInfo(QFontDatabase::applicationFontFamilies(d->fonts[d->url]->id).at(0), Ready); } } else #endif diff --git a/tests/auto/declarative/qdeclarativefontloader/data/daniel.ttf b/tests/auto/declarative/qdeclarativefontloader/data/daniel.ttf new file mode 100644 index 0000000..aae50d5 Binary files /dev/null and b/tests/auto/declarative/qdeclarativefontloader/data/daniel.ttf differ diff --git a/tests/auto/declarative/qdeclarativefontloader/tst_qdeclarativefontloader.cpp b/tests/auto/declarative/qdeclarativefontloader/tst_qdeclarativefontloader.cpp index ae23017..8765426 100644 --- a/tests/auto/declarative/qdeclarativefontloader/tst_qdeclarativefontloader.cpp +++ b/tests/auto/declarative/qdeclarativefontloader/tst_qdeclarativefontloader.cpp @@ -39,8 +39,10 @@ ** ****************************************************************************/ #include +#include #include #include +#include #include #include "../../../shared/util.h" #include "../shared/testhttpserver.h" @@ -67,6 +69,7 @@ private slots: void webFont(); void redirWebFont(); void failWebFont(); + void changeFont(); private slots: @@ -181,6 +184,45 @@ void tst_qdeclarativefontloader::failWebFont() QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Error); } +void tst_qdeclarativefontloader::changeFont() +{ + QString componentStr = "import Qt 4.7\nFontLoader { source: font }"; + QDeclarativeContext *ctxt = engine.rootContext(); + ctxt->setContextProperty("font", QUrl::fromLocalFile(SRCDIR "/data/tarzeau_ocr_a.ttf")); + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QDeclarativeFontLoader *fontObject = qobject_cast(component.create()); + + QVERIFY(fontObject != 0); + + QSignalSpy nameSpy(fontObject, SIGNAL(nameChanged())); + QSignalSpy statusSpy(fontObject, SIGNAL(statusChanged())); + + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready); + QCOMPARE(nameSpy.count(), 0); + QCOMPARE(statusSpy.count(), 0); + QTRY_COMPARE(fontObject->name(), QString("OCRA")); + + ctxt->setContextProperty("font", "http://localhost:14448/daniel.ttf"); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Loading); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready); + QCOMPARE(nameSpy.count(), 1); + QCOMPARE(statusSpy.count(), 2); + QTRY_COMPARE(fontObject->name(), QString("Daniel")); + + ctxt->setContextProperty("font", QUrl::fromLocalFile(SRCDIR "/data/tarzeau_ocr_a.ttf")); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready); + QCOMPARE(nameSpy.count(), 2); + QCOMPARE(statusSpy.count(), 2); + QTRY_COMPARE(fontObject->name(), QString("OCRA")); + + ctxt->setContextProperty("font", "http://localhost:14448/daniel.ttf"); + QTRY_VERIFY(fontObject->status() == QDeclarativeFontLoader::Ready); + QCOMPARE(nameSpy.count(), 3); + QCOMPARE(statusSpy.count(), 2); + QTRY_COMPARE(fontObject->name(), QString("Daniel")); +} + QTEST_MAIN(tst_qdeclarativefontloader) #include "tst_qdeclarativefontloader.moc" -- cgit v0.12 From 5372b313127302d94c748732052dd62d0e38a1cd Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Fri, 17 Sep 2010 16:34:50 +1000 Subject: Fix example after changes to font.letterSpacing. --- examples/declarative/text/fonts/hello.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/declarative/text/fonts/hello.qml b/examples/declarative/text/fonts/hello.qml index a396ff3..60bd919 100644 --- a/examples/declarative/text/fonts/hello.qml +++ b/examples/declarative/text/fonts/hello.qml @@ -56,10 +56,11 @@ Rectangle { color: "white" text: "Hello world!" font.pixelSize: 60 + smooth: true SequentialAnimation on font.letterSpacing { loops: Animation.Infinite; - NumberAnimation { from: 100; to: 300; easing.type: Easing.InQuad; duration: 3000 } + NumberAnimation { from: 0; to: 150; easing.type: Easing.InQuad; duration: 3000 } ScriptAction { script: { container.y = (screen.height / 4) + (Math.random() * screen.height / 2) -- cgit v0.12 From a9e5329168cd9113bf41293c05193d8b099494c6 Mon Sep 17 00:00:00 2001 From: Lasse Holmstedt Date: Fri, 17 Sep 2010 10:13:51 +0200 Subject: Make qml debugging work with command line arguments The environment variables do not work for Symbian devices, so without this change, QML debugging cannot be done on them. In addition, configure now contains an option to disable qml debugging entirely, due to it being a major security risk. Reviewed-by: kkoehne --- configure | 24 +++++++++++- configure.exe | Bin 1321472 -> 1402368 bytes src/corelib/kernel/qcoreapplication.cpp | 3 +- .../debugger/qdeclarativedebugservice.cpp | 41 +++++++++++++++------ src/gui/kernel/qapplication.cpp | 6 +++ src/gui/kernel/qapplication_p.h | 2 + .../qdeclarativedebug/tst_qdeclarativedebug.cpp | 16 +++++++- .../tst_qdeclarativedebugclient.cpp | 15 +++++++- .../tst_qdeclarativedebugservice.cpp | 16 +++++++- tools/configure/configureapp.cpp | 11 ++++++ 10 files changed, 114 insertions(+), 20 deletions(-) diff --git a/configure b/configure index 1ad0181..144bfbd 100755 --- a/configure +++ b/configure @@ -685,6 +685,7 @@ CFG_MULTIMEDIA=auto CFG_AUDIO_BACKEND=auto CFG_SVG=auto CFG_DECLARATIVE=auto +CFG_DECLARATIVE_DEBUG=yes CFG_WEBKIT=auto # (yes|no|auto) CFG_JAVASCRIPTCORE_JIT=auto @@ -1997,6 +1998,17 @@ while [ "$#" -gt 0 ]; do fi fi ;; + declarative-debug) + if [ "$VAL" = "yes" ]; then + CFG_DECLARATIVE_DEBUG="yes" + else + if [ "$VAL" = "no" ]; then + CFG_DECLARATIVE_DEBUG="no" + else + UNKNOWN_OPT=yes + fi + fi + ;; webkit) if [ "$VAL" = "yes" ] || [ "$VAL" = "auto" ]; then CFG_WEBKIT="yes" @@ -3524,7 +3536,8 @@ Usage: $relconf [-h] [-prefix ] [-prefix-install] [-bindir ] [-libdir [-no-media-backend] [-media-backend] [-no-audio-backend] [-audio-backend] [-no-openssl] [-openssl] [-openssl-linked] [-no-gtkstyle] [-gtkstyle] [-no-svg] [-svg] [-no-webkit] [-webkit] [-no-javascript-jit] [-javascript-jit] - [-no-script] [-script] [-no-scripttools] [-scripttools] [-no-declarative] [-declarative] + [-no-script] [-script] [-no-scripttools] [-scripttools] + [-no-declarative] [-declarative][-no-declarative-debug] [-declarative-debug] [additional platform specific options (see below)] @@ -3687,9 +3700,12 @@ fi -no-scripttools .... Do not build the QtScriptTools module. + -scripttools ....... Build the QtScriptTools module. - -no-declarative .....Do not build the declarative module. + -no-declarative ..... Do not build the declarative module. + -declarative ....... Build the declarative module. + -no-declarative-debug ..... Do not build the declarative debugging support. + + -declarative-debug ....... Build the declarative debugging support. + -platform target ... The operating system and compiler you are building on ($PLATFORM). @@ -7229,6 +7245,9 @@ fi if [ "$CFG_DECLARATIVE" = "yes" ]; then QT_CONFIG="$QT_CONFIG declarative" + if [ "$CFG_DECLARATIVE_DEBUG" = "no" ]; then + QCONFIG_FLAGS="$QCONFIG_FLAGS QDECLARATIVE_NO_DEBUG_PROTOCOL" + fi else QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_DECLARATIVE" fi @@ -8197,6 +8216,7 @@ if [ "$CFG_WEBKIT" = "yes" ]; then fi fi echo "Declarative module ..... $CFG_DECLARATIVE" +echo "Declarative debugging ...$CFG_DECLARATIVE_DEBUG" echo "Support for S60 ........ $CFG_S60" echo "Symbian DEF files ...... $CFG_SYMBIAN_DEFFILES" echo "STL support ............ $CFG_STL" diff --git a/configure.exe b/configure.exe index 18c9004..e2f4331 100755 Binary files a/configure.exe and b/configure.exe differ diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 512e193..d3f399b 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2091,7 +2091,8 @@ QStringList QCoreApplication::arguments() l1arg == "-stylesheet" || l1arg == "-widgetcount") ; - else if (l1arg.startsWith("-style=")) + else if (l1arg.startsWith("-style=") || + l1arg.startsWith("-qmljsdebugger=")) ; else if (l1arg == "-style" || l1arg == "-session" || diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp index 1bbfcf4..1f2bf4f 100644 --- a/src/declarative/debugger/qdeclarativedebugservice.cpp +++ b/src/declarative/debugger/qdeclarativedebugservice.cpp @@ -49,6 +49,8 @@ #include #include +#include +#include QT_BEGIN_NAMESPACE @@ -147,24 +149,41 @@ bool QDeclarativeDebugServer::hasDebuggingClient() const QDeclarativeDebugServer *QDeclarativeDebugServer::instance() { - static bool envTested = false; + static bool commandLineTested = false; static QDeclarativeDebugServer *server = 0; - if (!envTested) { - envTested = true; - QByteArray env = qgetenv("QML_DEBUG_SERVER_PORT"); - QByteArray block = qgetenv("QML_DEBUG_SERVER_BLOCK"); + if (!commandLineTested) { + commandLineTested = true; +#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL + QApplicationPrivate *appD = static_cast(QObjectPrivate::get(qApp)); + // ### remove port definition when protocol is changed + int port = 0; + bool block = false; bool ok = false; - int port = env.toInt(&ok); - if (ok && port > 1024) { - server = new QDeclarativeDebugServer(port); - server->listen(); - if (!block.isEmpty()) { - server->waitForConnection(); + // format: qmljsdebugger=port:3768[,block] + if (!appD->qmljsDebugArguments.isEmpty()) { + + if (appD->qmljsDebugArguments.indexOf(QLatin1String("port:")) == 0) { + int separatorIndex = appD->qmljsDebugArguments.indexOf(QLatin1Char(',')); + port = appD->qmljsDebugArguments.mid(5, separatorIndex - 5).toInt(&ok); + } + block = appD->qmljsDebugArguments.contains(QLatin1String("block")); + + if (ok) { + server = new QDeclarativeDebugServer(port); + server->listen(); + if (block) { + server->waitForConnection(); + } + } else { + qWarning(QString("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " + "Format is -qmljsdebugger=port:[,block]").arg( + appD->qmljsDebugArguments).toAscii().constData()); } } +#endif } return server; diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 2fd2f46..43d5772 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -494,6 +494,7 @@ bool QApplicationPrivate::fade_tooltip = false; bool QApplicationPrivate::animate_toolbox = false; bool QApplicationPrivate::widgetCount = false; bool QApplicationPrivate::load_testability = false; +QString QApplicationPrivate::qmljsDebugArguments; #ifdef QT_KEYPAD_NAVIGATION # ifdef Q_OS_SYMBIAN Qt::NavigationMode QApplicationPrivate::navigationMode = Qt::NavigationModeKeypadDirectional; @@ -565,6 +566,8 @@ void QApplicationPrivate::process_cmdline() QString s; if (arg == "-qdevel" || arg == "-qdebug") { // obsolete argument + } else if (arg.indexOf("-qmljsdebugger=", 0) != -1) { + qmljsDebugArguments = QString::fromLocal8Bit(arg.right(arg.length() - 15)); } else if (arg.indexOf("-style=", 0) != -1) { s = QString::fromLocal8Bit(arg.right(arg.length() - 7).toLower()); } else if (arg == "-style" && i < argc-1) { @@ -670,6 +673,9 @@ void QApplicationPrivate::process_cmdline() Qt::RightToLeft \o -graphicssystem, sets the backend to be used for on-screen widgets and QPixmaps. Available options are \c{raster} and \c{opengl}. + \o -qmljsdebugger=, activates the QML/JS debugger with a specified port. + The value must be of format port:1234[,block], where block is optional + and will make the application wait until a debugger connects to it. \endlist The X11 version of Qt supports some traditional X11 command line options: diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 8dc16e0..aa3a6d5 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -446,6 +446,8 @@ public: static bool animate_toolbox; static bool widgetCount; // Coupled with -widgetcount switch static bool load_testability; // Coupled with -testability switch + static QString qmljsDebugArguments; // a string containing arguments for js/qml debugging. + #ifdef Q_WS_MAC static bool native_modal_dialog_active; #endif diff --git a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp index 20ccccb..adba190 100644 --- a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp +++ b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp @@ -279,7 +279,7 @@ void tst_QDeclarativeDebug::initTestCase() qRegisterMetaType(); QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 3768..."); - qputenv("QML_DEBUG_SERVER_PORT", "3768"); + m_engine = new QDeclarativeEngine(this); QList qml; @@ -891,6 +891,18 @@ void tst_QDeclarativeDebug::tst_QDeclarativeDebugPropertyReference() compareProperties(r, ref); } -QTEST_MAIN(tst_QDeclarativeDebug) +int main(int argc, char *argv[]) +{ + int _argc = argc + 1; + char **_argv = new char*[_argc]; + for (int i = 0; i < argc; ++i) + _argv[i] = argv[i]; + _argv[_argc - 1] = "-qmljsdebugger=port:3768"; + + QApplication app(_argc, _argv); + tst_QDeclarativeDebug tc; + return QTest::qExec(&tc, _argc, _argv); + delete _argv; +} #include "tst_qdeclarativedebug.moc" diff --git a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp index a19c2c2..7db0e60 100644 --- a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp +++ b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp @@ -76,7 +76,6 @@ void tst_QDeclarativeDebugClient::initTestCase() { QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 3770..."); - qputenv("QML_DEBUG_SERVER_PORT", "3770"); new QDeclarativeEngine(this); m_conn = new QDeclarativeDebugConnection(this); @@ -151,7 +150,19 @@ void tst_QDeclarativeDebugClient::sendMessage() QCOMPARE(resp, msg); } -QTEST_MAIN(tst_QDeclarativeDebugClient) +int main(int argc, char *argv[]) +{ + int _argc = argc + 1; + char **_argv = new char*[_argc]; + for (int i = 0; i < argc; ++i) + _argv[i] = argv[i]; + _argv[_argc - 1] = "-qmljsdebugger=port:3770"; + + QApplication app(_argc, _argv); + tst_QDeclarativeDebugClient tc; + return QTest::qExec(&tc, _argc, _argv); + delete _argv; +} #include "tst_qdeclarativedebugclient.moc" diff --git a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp index 9ebbbaf..4683199 100644 --- a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp +++ b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp @@ -77,7 +77,6 @@ private slots: void tst_QDeclarativeDebugService::initTestCase() { QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugServer: Waiting for connection on port 3769..."); - qputenv("QML_DEBUG_SERVER_PORT", "3769"); new QDeclarativeEngine(this); m_conn = new QDeclarativeDebugConnection(this); @@ -184,6 +183,19 @@ void tst_QDeclarativeDebugService::objectToString() delete obj; } -QTEST_MAIN(tst_QDeclarativeDebugService) + +int main(int argc, char *argv[]) +{ + int _argc = argc + 1; + char **_argv = new char*[_argc]; + for (int i = 0; i < argc; ++i) + _argv[i] = argv[i]; + _argv[_argc - 1] = "-qmljsdebugger=port:3769"; + + QApplication app(_argc, _argv); + tst_QDeclarativeDebugService tc; + return QTest::qExec(&tc, _argc, _argv); + delete _argv; +} #include "tst_qdeclarativedebugservice.moc" diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 6e66742..a2c7fe9 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -279,6 +279,7 @@ Configure::Configure(int& argc, char** argv) dictionary[ "DIRECTSHOW" ] = "no"; dictionary[ "WEBKIT" ] = "auto"; dictionary[ "DECLARATIVE" ] = "auto"; + dictionary[ "DECLARATIVE_DEBUG" ]= "yes"; dictionary[ "PLUGIN_MANIFESTS" ] = "yes"; QString version; @@ -961,6 +962,10 @@ void Configure::parseCmdLine() dictionary[ "DECLARATIVE" ] = "no"; } else if (configCmdLine.at(i) == "-declarative") { dictionary[ "DECLARATIVE" ] = "yes"; + } else if (configCmdLine.at(i) == "-no-declarative-debug") { + dictionary[ "DECLARATIVE_DEBUG" ] = "no"; + } else if (configCmdLine.at(i) == "-declarative-debug") { + dictionary[ "DECLARATIVE_DEBUG" ] = "yes"; } else if (configCmdLine.at(i) == "-no-plugin-manifests") { dictionary[ "PLUGIN_MANIFESTS" ] = "no"; } else if (configCmdLine.at(i) == "-plugin-manifests") { @@ -1836,6 +1841,8 @@ bool Configure::displayHelp() desc("SCRIPTTOOLS", "yes", "-scripttools", "Build the QtScriptTools module."); desc("DECLARATIVE", "no", "-no-declarative", "Do not build the declarative module"); desc("DECLARATIVE", "yes", "-declarative", "Build the declarative module"); + desc("DECLARATIVE_DEBUG", "no", "-no-declarative-debug", "Do not build the declarative debugging support"); + desc("DECLARATIVE_DEBUG", "yes", "-declarative-debug", "Build the declarative debugging support"); desc( "-arch ", "Specify an architecture.\n" "Available values for :"); @@ -2273,6 +2280,8 @@ void Configure::autoDetection() dictionary["WEBKIT"] = checkAvailability("WEBKIT") ? "yes" : "no"; if (dictionary["DECLARATIVE"] == "auto") dictionary["DECLARATIVE"] = dictionary["SCRIPT"] == "yes" ? "yes" : "no"; + if (dictionary["DECLARATIVE_DEBUG"] == "auto") + dictionary["DECLARATIVE_DEBUG"] = dictionary["DECLARATIVE"] == "yes" ? "yes" : "no"; if (dictionary["AUDIO_BACKEND"] == "auto") dictionary["AUDIO_BACKEND"] = checkAvailability("AUDIO_BACKEND") ? "yes" : "no"; if (dictionary["WMSDK"] == "auto") @@ -3101,6 +3110,7 @@ void Configure::generateConfigfiles() if (dictionary["IPV6"] == "no") qconfigList += "QT_NO_IPV6"; if (dictionary["WEBKIT"] == "no") qconfigList += "QT_NO_WEBKIT"; if (dictionary["DECLARATIVE"] == "no") qconfigList += "QT_NO_DECLARATIVE"; + if (dictionary["DECLARATIVE_DEBUG"] == "no") qconfigList += "QDECLARATIVE_NO_DEBUG_PROTOCOL"; if (dictionary["PHONON"] == "no") qconfigList += "QT_NO_PHONON"; if (dictionary["MULTIMEDIA"] == "no") qconfigList += "QT_NO_MULTIMEDIA"; if (dictionary["XMLPATTERNS"] == "no") qconfigList += "QT_NO_XMLPATTERNS"; @@ -3398,6 +3408,7 @@ void Configure::displayConfig() cout << "QtMultimedia support........" << dictionary[ "MULTIMEDIA" ] << endl; cout << "WebKit support.............." << dictionary[ "WEBKIT" ] << endl; cout << "Declarative support........." << dictionary[ "DECLARATIVE" ] << endl; + cout << "Declarative debugging......." << dictionary[ "DECLARATIVE_DEBUG" ] << endl; cout << "QtScript support............" << dictionary[ "SCRIPT" ] << endl; cout << "QtScriptTools support......." << dictionary[ "SCRIPTTOOLS" ] << endl; cout << "Graphics System............." << dictionary[ "GRAPHICS_SYSTEM" ] << endl; -- cgit v0.12