diff options
Diffstat (limited to 'src/declarative')
125 files changed, 2491 insertions, 1733 deletions
diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt index d5910e3..9c46467 100644 --- a/src/declarative/QmlChanges.txt +++ b/src/declarative/QmlChanges.txt @@ -1,4 +1,14 @@ ============================================================================= +The changes below are pre Qt 4.7.0 RC + +Flickable: overShoot is replaced by boundsBehavior enumeration. + +C++ API +------- +QDeclarativeExpression::value() has been renamed to +QDeclarativeExpression::evaluate() + +============================================================================= The changes below are pre Qt 4.7.0 beta TextEdit: wrap property is replaced by wrapMode enumeration. @@ -19,6 +29,8 @@ Animation: replace repeat with loops (loops: Animation.Infinite gives the old re AnchorChanges: use natural form to specify anchors (anchors.left instead of left) AnchorChanges: removed reset property. (reset: "left" should now be anchors.left: undefined) PathView: snapPosition replaced by preferredHighlightBegin, preferredHighlightEnd +createQmlObject: Moved to the Qt object, now use Qt.createQmlObject() +createComponent: Moved to the Qt object, now use Qt.createComponent() C++ API ------- @@ -55,22 +67,22 @@ automatically 'followed' anymore. If you want to follow an hypothetical rect1, you should do now: -Â Â Â Rectangle { -Â Â Â Â Â color: "green" -Â Â Â Â Â width: 60; height: 60; -Â Â Â Â Â x: rect1.x - 5; y: rect1.y - 5; -Â Â Â Â Â Behavior on x { SmoothedAnimation { velocity: 200 } } -Â Â Â Â Â Behavior on y { SmoothedAnimation { velocity: 200 } } -Â Â Â } + Rectangle { + color: "green" + width: 60; height: 60; + x: rect1.x - 5; y: rect1.y - 5; + Behavior on x { SmoothedAnimation { velocity: 200 } } + Behavior on y { SmoothedAnimation { velocity: 200 } } + } instead of the old automatic source changed tracking: -Â Â Â Rectangle { -Â Â Â Â Â color: "green" -Â Â Â Â Â width: 60; height: 60; -Â Â Â Â Â EaseFollow on x { source: rect1.x - 5; velocity: 200 } -Â Â Â Â Â EaseFollow on y { source: rect1.y - 5; velocity: 200 } -Â Â } + Rectangle { + color: "green" + width: 60; height: 60; + EaseFollow on x { source: rect1.x - 5; velocity: 200 } + EaseFollow on y { source: rect1.y - 5; velocity: 200 } + } This is a syntax and behavior change. diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp index 9d9d1d0..34e73fd 100644 --- a/src/declarative/debugger/qdeclarativedebugservice.cpp +++ b/src/declarative/debugger/qdeclarativedebugservice.cpp @@ -60,12 +60,12 @@ class QDeclarativeDebugServer : public QObject Q_DISABLE_COPY(QDeclarativeDebugServer) public: static QDeclarativeDebugServer *instance(); - void wait(); - void registerForStartNotification(QObject *object, const char *receiver); + void listen(); + bool hasDebuggingClient() const; private Q_SLOTS: void readyRead(); - void registeredObjectDestroyed(QObject *object); + void newConnection(); private: friend class QDeclarativeDebugService; @@ -78,14 +78,14 @@ class QDeclarativeDebugServerPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QDeclarativeDebugServer) public: QDeclarativeDebugServerPrivate(); - void wait(); int port; QTcpSocket *connection; QPacketProtocol *protocol; QHash<QString, QDeclarativeDebugService *> plugins; QStringList enabledPlugins; - QList<QPair<QObject*, QByteArray> > notifyClients; + QTcpServer *tcpServer; + bool gotHello; }; class QDeclarativeDebugServicePrivate : public QObjectPrivate @@ -99,56 +99,41 @@ public: }; QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() -: connection(0), protocol(0) +: connection(0), protocol(0), gotHello(false) { } -void QDeclarativeDebugServerPrivate::wait() +void QDeclarativeDebugServer::listen() { - Q_Q(QDeclarativeDebugServer); - QTcpServer server; - - if (!server.listen(QHostAddress::Any, port)) { - qWarning("QDeclarativeDebugServer: Unable to listen on port %d", port); - return; - } - - qWarning("QDeclarativeDebugServer: Waiting for connection on port %d...", port); - - for (int i=0; i<notifyClients.count(); i++) { - if (!QMetaObject::invokeMethod(notifyClients[i].first, notifyClients[i].second)) { - qWarning() << "QDeclarativeDebugServer: unable to call method" << notifyClients[i].second - << "on object" << notifyClients[i].first << "to notify of debug server start"; - } - } - notifyClients.clear(); + Q_D(QDeclarativeDebugServer); - if (!server.waitForNewConnection(-1)) { - qWarning("QDeclarativeDebugServer: Connection error"); - return; - } + d->tcpServer = new QTcpServer(this); + QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); + if (d->tcpServer->listen(QHostAddress::Any, d->port)) + qWarning("QDeclarativeDebugServer: Waiting for connection on port %d...", d->port); + else + qWarning("QDeclarativeDebugServer: Unable to listen on port %d", d->port); +} - connection = server.nextPendingConnection(); - connection->setParent(q); - protocol = new QPacketProtocol(connection, q); +void QDeclarativeDebugServer::newConnection() +{ + Q_D(QDeclarativeDebugServer); - // ### Wait for hello - while (!protocol->packetsAvailable()) { - connection->waitForReadyRead(); - } - QPacket hello = protocol->read(); - QString name; - hello >> name >> enabledPlugins; - if (name != QLatin1String("QDeclarativeDebugServer")) { - qWarning("QDeclarativeDebugServer: Invalid hello message"); - delete protocol; delete connection; connection = 0; protocol = 0; + if (d->connection) { + qWarning("QDeclarativeDebugServer error: another client is already connected"); return; } - QObject::connect(protocol, SIGNAL(readyRead()), q, SLOT(readyRead())); - q->readyRead(); + d->connection = d->tcpServer->nextPendingConnection(); + d->connection->setParent(this); + d->protocol = new QPacketProtocol(d->connection, this); + QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); +} - qWarning("QDeclarativeDebugServer: Connection established"); +bool QDeclarativeDebugServer::hasDebuggingClient() const +{ + Q_D(const QDeclarativeDebugServer); + return d->gotHello; } QDeclarativeDebugServer *QDeclarativeDebugServer::instance() @@ -163,36 +148,15 @@ QDeclarativeDebugServer *QDeclarativeDebugServer::instance() bool ok = false; int port = env.toInt(&ok); - if (ok && port > 1024) + if (ok && port > 1024) { server = new QDeclarativeDebugServer(port); + server->listen(); + } } return server; } -void QDeclarativeDebugServer::wait() -{ - Q_D(QDeclarativeDebugServer); - d->wait(); -} - -void QDeclarativeDebugServer::registerForStartNotification(QObject *object, const char *methodName) -{ - Q_D(QDeclarativeDebugServer); - connect(object, SIGNAL(destroyed(QObject*)), SLOT(registeredObjectDestroyed(QObject*))); - d->notifyClients.append(qMakePair(object, QByteArray(methodName))); -} - -void QDeclarativeDebugServer::registeredObjectDestroyed(QObject *object) -{ - Q_D(QDeclarativeDebugServer); - QMutableListIterator<QPair<QObject*, QByteArray> > i(d->notifyClients); - while (i.hasNext()) { - if (i.next().first == object) - i.remove(); - } -} - QDeclarativeDebugServer::QDeclarativeDebugServer(int port) : QObject(*(new QDeclarativeDebugServerPrivate)) { @@ -204,6 +168,23 @@ void QDeclarativeDebugServer::readyRead() { Q_D(QDeclarativeDebugServer); + if (!d->gotHello) { + QPacket hello = d->protocol->read(); + QString name; + hello >> name >> d->enabledPlugins; + if (name != QLatin1String("QDeclarativeDebugServer")) { + qWarning("QDeclarativeDebugServer: Invalid hello message"); + QObject::disconnect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); + d->protocol->deleteLater(); + d->protocol = 0; + d->connection->deleteLater(); + d->connection = 0; + return; + } + d->gotHello = true; + qWarning("QDeclarativeDebugServer: Connection established"); + } + QString debugServer(QLatin1String("QDeclarativeDebugServer")); while (d->protocol->packetsAvailable()) { @@ -375,6 +356,12 @@ bool QDeclarativeDebugService::isDebuggingEnabled() return QDeclarativeDebugServer::instance() != 0; } +bool QDeclarativeDebugService::hasDebuggingClient() +{ + return QDeclarativeDebugServer::instance() != 0 + && QDeclarativeDebugServer::instance()->hasDebuggingClient(); +} + QString QDeclarativeDebugService::objectToString(QObject *obj) { if(!obj) @@ -390,16 +377,6 @@ QString QDeclarativeDebugService::objectToString(QObject *obj) return rv; } -void QDeclarativeDebugService::waitForClients() -{ - QDeclarativeDebugServer::instance()->wait(); -} - -void QDeclarativeDebugService::notifyOnServerStart(QObject *object, const char *receiver) -{ - QDeclarativeDebugServer::instance()->registerForStartNotification(object, receiver); -} - void QDeclarativeDebugService::sendMessage(const QByteArray &message) { Q_D(QDeclarativeDebugService); diff --git a/src/declarative/debugger/qdeclarativedebugservice_p.h b/src/declarative/debugger/qdeclarativedebugservice_p.h index 498edf3..c461ddf 100644 --- a/src/declarative/debugger/qdeclarativedebugservice_p.h +++ b/src/declarative/debugger/qdeclarativedebugservice_p.h @@ -68,19 +68,16 @@ public: static int idForObject(QObject *); static QObject *objectForId(int); - static bool isDebuggingEnabled(); static QString objectToString(QObject *obj); - static void waitForClients(); - - static void notifyOnServerStart(QObject *object, const char *receiver); + static bool isDebuggingEnabled(); + static bool hasDebuggingClient(); protected: virtual void enabledChanged(bool); virtual void messageReceived(const QByteArray &); private: - void registerForStartNotification(QObject *object, const char *methodName); friend class QDeclarativeDebugServer; }; diff --git a/src/declarative/graphicsitems/graphicsitems.pri b/src/declarative/graphicsitems/graphicsitems.pri index ad7ccb5..d420595 100644 --- a/src/declarative/graphicsitems/graphicsitems.pri +++ b/src/declarative/graphicsitems/graphicsitems.pri @@ -5,7 +5,6 @@ HEADERS += \ $$PWD/qdeclarativeanchors_p.h \ $$PWD/qdeclarativeanchors_p_p.h \ $$PWD/qdeclarativeevents_p_p.h \ - $$PWD/qdeclarativeeffects_p.h \ $$PWD/qdeclarativeflickable_p.h \ $$PWD/qdeclarativeflickable_p_p.h \ $$PWD/qdeclarativeflipable_p.h \ @@ -50,7 +49,6 @@ HEADERS += \ $$PWD/qdeclarativelistview_p.h \ $$PWD/qdeclarativelayoutitem_p.h \ $$PWD/qdeclarativeitemchangelistener_p.h \ - $$PWD/qdeclarativeeffects.cpp \ $$PWD/qdeclarativegraphicswidget_p.h SOURCES += \ diff --git a/src/declarative/graphicsitems/qdeclarativeanchors.cpp b/src/declarative/graphicsitems/qdeclarativeanchors.cpp index 96d0867..f15316b 100644 --- a/src/declarative/graphicsitems/qdeclarativeanchors.cpp +++ b/src/declarative/graphicsitems/qdeclarativeanchors.cpp @@ -221,31 +221,31 @@ void QDeclarativeAnchorsPrivate::clearItem(QGraphicsObject *item) centerIn = 0; if (left.item == item) { left.item = 0; - usedAnchors &= ~QDeclarativeAnchors::HasLeftAnchor; + usedAnchors &= ~QDeclarativeAnchors::LeftAnchor; } if (right.item == item) { right.item = 0; - usedAnchors &= ~QDeclarativeAnchors::HasRightAnchor; + usedAnchors &= ~QDeclarativeAnchors::RightAnchor; } if (top.item == item) { top.item = 0; - usedAnchors &= ~QDeclarativeAnchors::HasTopAnchor; + usedAnchors &= ~QDeclarativeAnchors::TopAnchor; } if (bottom.item == item) { bottom.item = 0; - usedAnchors &= ~QDeclarativeAnchors::HasBottomAnchor; + usedAnchors &= ~QDeclarativeAnchors::BottomAnchor; } if (vCenter.item == item) { vCenter.item = 0; - usedAnchors &= ~QDeclarativeAnchors::HasVCenterAnchor; + usedAnchors &= ~QDeclarativeAnchors::VCenterAnchor; } if (hCenter.item == item) { hCenter.item = 0; - usedAnchors &= ~QDeclarativeAnchors::HasHCenterAnchor; + usedAnchors &= ~QDeclarativeAnchors::HCenterAnchor; } if (baseline.item == item) { baseline.item = 0; - usedAnchors &= ~QDeclarativeAnchors::HasBaselineAnchor; + usedAnchors &= ~QDeclarativeAnchors::BaselineAnchor; } } @@ -495,13 +495,13 @@ void QDeclarativeAnchorsPrivate::updateVerticalAnchors() if (updatingVerticalAnchor < 2) { ++updatingVerticalAnchor; QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item); - if (usedAnchors & QDeclarativeAnchors::HasTopAnchor) { + if (usedAnchors & QDeclarativeAnchors::TopAnchor) { //Handle stretching bool invalid = true; int height = 0; - if (usedAnchors & QDeclarativeAnchors::HasBottomAnchor) { + if (usedAnchors & QDeclarativeAnchors::BottomAnchor) { invalid = calcStretch(top, bottom, topMargin, -bottomMargin, QDeclarativeAnchorLine::Top, height); - } else if (usedAnchors & QDeclarativeAnchors::HasVCenterAnchor) { + } else if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) { invalid = calcStretch(top, vCenter, topMargin, vCenterOffset, QDeclarativeAnchorLine::Top, height); height *= 2; } @@ -514,9 +514,9 @@ void QDeclarativeAnchorsPrivate::updateVerticalAnchors() } else if (top.item->parentItem() == item->parentItem()) { setItemY(position(top.item, top.anchorLine) + topMargin); } - } else if (usedAnchors & QDeclarativeAnchors::HasBottomAnchor) { + } else if (usedAnchors & QDeclarativeAnchors::BottomAnchor) { //Handle stretching (top + bottom case is handled above) - if (usedAnchors & QDeclarativeAnchors::HasVCenterAnchor) { + if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) { int height = 0; bool invalid = calcStretch(vCenter, bottom, vCenterOffset, -bottomMargin, QDeclarativeAnchorLine::Top, height); @@ -530,7 +530,7 @@ void QDeclarativeAnchorsPrivate::updateVerticalAnchors() } else if (bottom.item->parentItem() == item->parentItem()) { setItemY(position(bottom.item, bottom.anchorLine) - itemPrivate->height() - bottomMargin); } - } else if (usedAnchors & QDeclarativeAnchors::HasVCenterAnchor) { + } else if (usedAnchors & QDeclarativeAnchors::VCenterAnchor) { //(stetching handled above) //Handle vCenter @@ -540,7 +540,7 @@ void QDeclarativeAnchorsPrivate::updateVerticalAnchors() } else if (vCenter.item->parentItem() == item->parentItem()) { setItemY(position(vCenter.item, vCenter.anchorLine) - itemPrivate->height()/2 + vCenterOffset); } - } else if (usedAnchors & QDeclarativeAnchors::HasBaselineAnchor) { + } else if (usedAnchors & QDeclarativeAnchors::BaselineAnchor) { //Handle baseline if (baseline.item == item->parentItem()) { if (itemPrivate->isDeclarativeItem) @@ -567,13 +567,13 @@ void QDeclarativeAnchorsPrivate::updateHorizontalAnchors() if (updatingHorizontalAnchor < 2) { ++updatingHorizontalAnchor; QGraphicsItemPrivate *itemPrivate = QGraphicsItemPrivate::get(item); - if (usedAnchors & QDeclarativeAnchors::HasLeftAnchor) { + if (usedAnchors & QDeclarativeAnchors::LeftAnchor) { //Handle stretching bool invalid = true; int width = 0; - if (usedAnchors & QDeclarativeAnchors::HasRightAnchor) { + if (usedAnchors & QDeclarativeAnchors::RightAnchor) { invalid = calcStretch(left, right, leftMargin, -rightMargin, QDeclarativeAnchorLine::Left, width); - } else if (usedAnchors & QDeclarativeAnchors::HasHCenterAnchor) { + } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { invalid = calcStretch(left, hCenter, leftMargin, hCenterOffset, QDeclarativeAnchorLine::Left, width); width *= 2; } @@ -586,9 +586,9 @@ void QDeclarativeAnchorsPrivate::updateHorizontalAnchors() } else if (left.item->parentItem() == item->parentItem()) { setItemX(position(left.item, left.anchorLine) + leftMargin); } - } else if (usedAnchors & QDeclarativeAnchors::HasRightAnchor) { + } else if (usedAnchors & QDeclarativeAnchors::RightAnchor) { //Handle stretching (left + right case is handled in updateLeftAnchor) - if (usedAnchors & QDeclarativeAnchors::HasHCenterAnchor) { + if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { int width = 0; bool invalid = calcStretch(hCenter, right, hCenterOffset, -rightMargin, QDeclarativeAnchorLine::Left, width); @@ -602,7 +602,7 @@ void QDeclarativeAnchorsPrivate::updateHorizontalAnchors() } else if (right.item->parentItem() == item->parentItem()) { setItemX(position(right.item, right.anchorLine) - itemPrivate->width() - rightMargin); } - } else if (usedAnchors & QDeclarativeAnchors::HasHCenterAnchor) { + } else if (usedAnchors & QDeclarativeAnchors::HCenterAnchor) { //Handle hCenter if (hCenter.item == item->parentItem()) { setItemX(adjustedPosition(hCenter.item, hCenter.anchorLine) - itemPrivate->width()/2 + hCenterOffset); @@ -630,10 +630,10 @@ void QDeclarativeAnchors::setTop(const QDeclarativeAnchorLine &edge) if (!d->checkVAnchorValid(edge) || d->top == edge) return; - d->usedAnchors |= HasTopAnchor; + d->usedAnchors |= TopAnchor; if (!d->checkVValid()) { - d->usedAnchors &= ~HasTopAnchor; + d->usedAnchors &= ~TopAnchor; return; } @@ -647,7 +647,7 @@ void QDeclarativeAnchors::setTop(const QDeclarativeAnchorLine &edge) void QDeclarativeAnchors::resetTop() { Q_D(QDeclarativeAnchors); - d->usedAnchors &= ~HasTopAnchor; + d->usedAnchors &= ~TopAnchor; d->remDepend(d->top.item); d->top = QDeclarativeAnchorLine(); emit topChanged(); @@ -666,10 +666,10 @@ void QDeclarativeAnchors::setBottom(const QDeclarativeAnchorLine &edge) if (!d->checkVAnchorValid(edge) || d->bottom == edge) return; - d->usedAnchors |= HasBottomAnchor; + d->usedAnchors |= BottomAnchor; if (!d->checkVValid()) { - d->usedAnchors &= ~HasBottomAnchor; + d->usedAnchors &= ~BottomAnchor; return; } @@ -683,7 +683,7 @@ void QDeclarativeAnchors::setBottom(const QDeclarativeAnchorLine &edge) void QDeclarativeAnchors::resetBottom() { Q_D(QDeclarativeAnchors); - d->usedAnchors &= ~HasBottomAnchor; + d->usedAnchors &= ~BottomAnchor; d->remDepend(d->bottom.item); d->bottom = QDeclarativeAnchorLine(); emit bottomChanged(); @@ -702,10 +702,10 @@ void QDeclarativeAnchors::setVerticalCenter(const QDeclarativeAnchorLine &edge) if (!d->checkVAnchorValid(edge) || d->vCenter == edge) return; - d->usedAnchors |= HasVCenterAnchor; + d->usedAnchors |= VCenterAnchor; if (!d->checkVValid()) { - d->usedAnchors &= ~HasVCenterAnchor; + d->usedAnchors &= ~VCenterAnchor; return; } @@ -719,7 +719,7 @@ void QDeclarativeAnchors::setVerticalCenter(const QDeclarativeAnchorLine &edge) void QDeclarativeAnchors::resetVerticalCenter() { Q_D(QDeclarativeAnchors); - d->usedAnchors &= ~HasVCenterAnchor; + d->usedAnchors &= ~VCenterAnchor; d->remDepend(d->vCenter.item); d->vCenter = QDeclarativeAnchorLine(); emit verticalCenterChanged(); @@ -738,10 +738,10 @@ void QDeclarativeAnchors::setBaseline(const QDeclarativeAnchorLine &edge) if (!d->checkVAnchorValid(edge) || d->baseline == edge) return; - d->usedAnchors |= HasBaselineAnchor; + d->usedAnchors |= BaselineAnchor; if (!d->checkVValid()) { - d->usedAnchors &= ~HasBaselineAnchor; + d->usedAnchors &= ~BaselineAnchor; return; } @@ -755,7 +755,7 @@ void QDeclarativeAnchors::setBaseline(const QDeclarativeAnchorLine &edge) void QDeclarativeAnchors::resetBaseline() { Q_D(QDeclarativeAnchors); - d->usedAnchors &= ~HasBaselineAnchor; + d->usedAnchors &= ~BaselineAnchor; d->remDepend(d->baseline.item); d->baseline = QDeclarativeAnchorLine(); emit baselineChanged(); @@ -774,10 +774,10 @@ void QDeclarativeAnchors::setLeft(const QDeclarativeAnchorLine &edge) if (!d->checkHAnchorValid(edge) || d->left == edge) return; - d->usedAnchors |= HasLeftAnchor; + d->usedAnchors |= LeftAnchor; if (!d->checkHValid()) { - d->usedAnchors &= ~HasLeftAnchor; + d->usedAnchors &= ~LeftAnchor; return; } @@ -791,7 +791,7 @@ void QDeclarativeAnchors::setLeft(const QDeclarativeAnchorLine &edge) void QDeclarativeAnchors::resetLeft() { Q_D(QDeclarativeAnchors); - d->usedAnchors &= ~HasLeftAnchor; + d->usedAnchors &= ~LeftAnchor; d->remDepend(d->left.item); d->left = QDeclarativeAnchorLine(); emit leftChanged(); @@ -810,10 +810,10 @@ void QDeclarativeAnchors::setRight(const QDeclarativeAnchorLine &edge) if (!d->checkHAnchorValid(edge) || d->right == edge) return; - d->usedAnchors |= HasRightAnchor; + d->usedAnchors |= RightAnchor; if (!d->checkHValid()) { - d->usedAnchors &= ~HasRightAnchor; + d->usedAnchors &= ~RightAnchor; return; } @@ -827,7 +827,7 @@ void QDeclarativeAnchors::setRight(const QDeclarativeAnchorLine &edge) void QDeclarativeAnchors::resetRight() { Q_D(QDeclarativeAnchors); - d->usedAnchors &= ~HasRightAnchor; + d->usedAnchors &= ~RightAnchor; d->remDepend(d->right.item); d->right = QDeclarativeAnchorLine(); emit rightChanged(); @@ -846,10 +846,10 @@ void QDeclarativeAnchors::setHorizontalCenter(const QDeclarativeAnchorLine &edge if (!d->checkHAnchorValid(edge) || d->hCenter == edge) return; - d->usedAnchors |= HasHCenterAnchor; + d->usedAnchors |= HCenterAnchor; if (!d->checkHValid()) { - d->usedAnchors &= ~HasHCenterAnchor; + d->usedAnchors &= ~HCenterAnchor; return; } @@ -863,7 +863,7 @@ void QDeclarativeAnchors::setHorizontalCenter(const QDeclarativeAnchorLine &edge void QDeclarativeAnchors::resetHorizontalCenter() { Q_D(QDeclarativeAnchors); - d->usedAnchors &= ~HasHCenterAnchor; + d->usedAnchors &= ~HCenterAnchor; d->remDepend(d->hCenter.item); d->hCenter = QDeclarativeAnchorLine(); emit horizontalCenterChanged(); @@ -1025,7 +1025,7 @@ void QDeclarativeAnchors::setBaselineOffset(qreal offset) emit baselineOffsetChanged(); } -QDeclarativeAnchors::UsedAnchors QDeclarativeAnchors::usedAnchors() const +QDeclarativeAnchors::Anchors QDeclarativeAnchors::usedAnchors() const { Q_D(const QDeclarativeAnchors); return d->usedAnchors; @@ -1033,9 +1033,9 @@ QDeclarativeAnchors::UsedAnchors QDeclarativeAnchors::usedAnchors() const bool QDeclarativeAnchorsPrivate::checkHValid() const { - if (usedAnchors & QDeclarativeAnchors::HasLeftAnchor && - usedAnchors & QDeclarativeAnchors::HasRightAnchor && - usedAnchors & QDeclarativeAnchors::HasHCenterAnchor) { + if (usedAnchors & QDeclarativeAnchors::LeftAnchor && + usedAnchors & QDeclarativeAnchors::RightAnchor && + usedAnchors & QDeclarativeAnchors::HCenterAnchor) { qmlInfo(item) << QDeclarativeAnchors::tr("Cannot specify left, right, and hcenter anchors."); return false; } @@ -1064,15 +1064,15 @@ bool QDeclarativeAnchorsPrivate::checkHAnchorValid(QDeclarativeAnchorLine anchor bool QDeclarativeAnchorsPrivate::checkVValid() const { - if (usedAnchors & QDeclarativeAnchors::HasTopAnchor && - usedAnchors & QDeclarativeAnchors::HasBottomAnchor && - usedAnchors & QDeclarativeAnchors::HasVCenterAnchor) { + if (usedAnchors & QDeclarativeAnchors::TopAnchor && + usedAnchors & QDeclarativeAnchors::BottomAnchor && + usedAnchors & QDeclarativeAnchors::VCenterAnchor) { qmlInfo(item) << QDeclarativeAnchors::tr("Cannot specify top, bottom, and vcenter anchors."); return false; - } else if (usedAnchors & QDeclarativeAnchors::HasBaselineAnchor && - (usedAnchors & QDeclarativeAnchors::HasTopAnchor || - usedAnchors & QDeclarativeAnchors::HasBottomAnchor || - usedAnchors & QDeclarativeAnchors::HasVCenterAnchor)) { + } else if (usedAnchors & QDeclarativeAnchors::BaselineAnchor && + (usedAnchors & QDeclarativeAnchors::TopAnchor || + usedAnchors & QDeclarativeAnchors::BottomAnchor || + usedAnchors & QDeclarativeAnchors::VCenterAnchor)) { qmlInfo(item) << QDeclarativeAnchors::tr("Baseline anchor cannot be used in conjunction with top, bottom, or vcenter anchors."); return false; } diff --git a/src/declarative/graphicsitems/qdeclarativeanchors_p.h b/src/declarative/graphicsitems/qdeclarativeanchors_p.h index f2e57cc..1bd7608 100644 --- a/src/declarative/graphicsitems/qdeclarativeanchors_p.h +++ b/src/declarative/graphicsitems/qdeclarativeanchors_p.h @@ -83,18 +83,18 @@ public: QDeclarativeAnchors(QGraphicsObject *item, QObject *parent=0); virtual ~QDeclarativeAnchors(); - enum UsedAnchor { - HasLeftAnchor = 0x01, - HasRightAnchor = 0x02, - HasTopAnchor = 0x04, - HasBottomAnchor = 0x08, - HasHCenterAnchor = 0x10, - HasVCenterAnchor = 0x20, - HasBaselineAnchor = 0x40, - Horizontal_Mask = HasLeftAnchor | HasRightAnchor | HasHCenterAnchor, - Vertical_Mask = HasTopAnchor | HasBottomAnchor | HasVCenterAnchor | HasBaselineAnchor + enum Anchor { + LeftAnchor = 0x01, + RightAnchor = 0x02, + TopAnchor = 0x04, + BottomAnchor = 0x08, + HCenterAnchor = 0x10, + VCenterAnchor = 0x20, + BaselineAnchor = 0x40, + Horizontal_Mask = LeftAnchor | RightAnchor | HCenterAnchor, + Vertical_Mask = TopAnchor | BottomAnchor | VCenterAnchor | BaselineAnchor }; - Q_DECLARE_FLAGS(UsedAnchors, UsedAnchor) + Q_DECLARE_FLAGS(Anchors, Anchor) QDeclarativeAnchorLine left() const; void setLeft(const QDeclarativeAnchorLine &edge); @@ -156,7 +156,7 @@ public: void setCenterIn(QGraphicsObject *); void resetCenterIn(); - UsedAnchors usedAnchors() const; + Anchors usedAnchors() const; void classBegin(); void componentComplete(); @@ -188,7 +188,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_widgetGeometryChanged()) Q_PRIVATE_SLOT(d_func(), void _q_widgetDestroyed(QObject *obj)) }; -Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeAnchors::UsedAnchors) +Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeAnchors::Anchors) QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h b/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h index f8489aa..05be6c5 100644 --- a/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeanchors_p_p.h @@ -139,7 +139,7 @@ public: void centerInChanged(); QGraphicsObject *item; - QDeclarativeAnchors::UsedAnchors usedAnchors; + QDeclarativeAnchors::Anchors usedAnchors; QGraphicsObject *fill; QGraphicsObject *centerIn; diff --git a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp index 6ab126d..c81c2d2 100644 --- a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp @@ -44,6 +44,7 @@ #ifndef QT_NO_MOVIE +#include <qdeclarativeinfo.h> #include <qdeclarativeengine.h> #include <QMovie> @@ -213,7 +214,7 @@ void QDeclarativeAnimatedImage::setSource(const QUrl &url) //### should be unified with movieRequestFinished d->_movie = new QMovie(lf); if (!d->_movie->isValid()){ - qWarning() << "Error Reading Animated Image File" << d->url; + qmlInfo(this) << "Error Reading Animated Image File " << d->url.toString(); delete d->_movie; d->_movie = 0; return; @@ -270,7 +271,7 @@ void QDeclarativeAnimatedImage::movieRequestFinished() d->_movie = new QMovie(d->reply); if (!d->_movie->isValid()){ - qWarning() << "Error Reading Animated Image File " << d->url; + qmlInfo(this) << "Error Reading Animated Image File " << d->url; delete d->_movie; d->_movie = 0; return; diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp index be9d8bd..06f8363 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp @@ -82,7 +82,7 @@ QDeclarativeBorderImage::~QDeclarativeBorderImage() QDeclarativePixmapCache::cancel(d->sciurl, this); } /*! - \qmlproperty enum BorderImage::status + \qmlproperty enumeration BorderImage::status This property holds the status of image loading. It can be one of: \list @@ -264,9 +264,9 @@ void QDeclarativeBorderImage::load() When the image is scaled: \list \i the corners (sections 1, 3, 7, and 9) are not scaled at all - \i the middle (section 5) is scaled according to BorderImage::horizontalTileMode and BorderImage::verticalTileMode - \i sections 2 and 8 are scaled according to BorderImage::horizontalTileMode - \i sections 4 and 6 are scaled according to BorderImage::verticalTileMode + \i sections 2 and 8 are scaled according to \l{BorderImage::horizontalTileMode}{horizontalTileMode} + \i sections 4 and 6 are scaled according to \l{BorderImage::verticalTileMode}{verticalTileMode} + \i the middle (section 5) is scaled according to both \l{BorderImage::horizontalTileMode}{horizontalTileMode} and \l{BorderImage::verticalTileMode}{verticalTileMode} \endlist Each border line (left, right, top, and bottom) specifies an offset from the respective side. For example, \c{border.bottom: 10} sets the bottom line 10 pixels up from the bottom of the image. @@ -282,8 +282,8 @@ QDeclarativeScaleGrid *QDeclarativeBorderImage::border() } /*! - \qmlproperty TileMode BorderImage::horizontalTileMode - \qmlproperty TileMode BorderImage::verticalTileMode + \qmlproperty enumeration BorderImage::horizontalTileMode + \qmlproperty enumeration BorderImage::verticalTileMode This property describes how to repeat or stretch the middle parts of the border image. diff --git a/src/declarative/graphicsitems/qdeclarativeeffects.cpp b/src/declarative/graphicsitems/qdeclarativeeffects.cpp deleted file mode 100644 index ea1f9cc..0000000 --- a/src/declarative/graphicsitems/qdeclarativeeffects.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtDeclarative module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qdeclarative.h> - -#include <QtGui/qgraphicseffect.h> - -/*! - \qmlclass Blur QGraphicsBlurEffect - \since 4.7 - \brief The Blur object provides a blur effect. - - A blur effect blurs the source item. This effect is useful for reducing details; - for example, when the a source loses focus and attention should be drawn to other - elements. Use blurRadius to control the level of detail and blurHint to control - the quality of the blur. - - By default, the blur radius is 5 pixels. - - \img graphicseffect-blur.png -*/ - -/*! - \qmlproperty real Blur::blurRadius - - This controls how blurry an item will appear. - - A smaller radius produces a sharper appearance, and a larger radius produces - a more blurred appearance. - - The default radius is 5 pixels. -*/ -/*! - \qmlproperty enumeration Blur::blurHint - - Use Qt.PerformanceHint to specify a faster blur or Qt.QualityHint hint - to specify a higher quality blur. - - If the blur radius is animated, it is recommended you use Qt.PerformanceHint. - - The default hint is Qt.PerformanceHint. -*/ - -/*! - \qmlclass Colorize QGraphicsColorizeEffect - \since 4.7 - \brief The Colorize object provides a colorize effect. - - A colorize effect renders the source item with a tint of its color. - - By default, the color is light blue. - - \img graphicseffect-colorize.png -*/ - -/*! - \qmlproperty color Colorize::color - The color of the effect. - - By default, the color is light blue. -*/ - -/*! - \qmlproperty real Colorize::strength - - To what extent the source item is "colored". A strength of 0.0 is equal to no effect, - while 1.0 means full colorization. By default, the strength is 1.0. -*/ - - -/*! - \qmlclass DropShadow QGraphicsDropShadowEffect - \since 4.7 - \brief The DropShadow object provides a drop shadow effect. - - A drop shadow effect renders the source item with a drop shadow. The color of - the drop shadow can be modified using the color property. The drop - shadow offset can be modified using the xOffset and yOffset properties and the blur - radius of the drop shadow can be changed with the blurRadius property. - - By default, the drop shadow is a semi-transparent dark gray shadow, - blurred with a radius of 1 at an offset of 8 pixels towards the lower right. - - \img graphicseffect-drop-shadow.png -*/ - -/*! - \qmlproperty real DropShadow::xOffset - \qmlproperty real DropShadow::yOffset - The shadow offset in pixels. - - By default, xOffset and yOffset are 8 pixels. -*/ - -/*! - \qmlproperty real DropShadow::blurRadius - The blur radius in pixels of the drop shadow. - - Using a smaller radius results in a sharper shadow, whereas using a bigger - radius results in a more blurred shadow. - - By default, the blur radius is 1 pixel. -*/ - -/*! - \qmlproperty color DropShadow::color - The color of the drop shadow. - - By default, the drop color is a semi-transparent dark gray. -*/ - - -/*! - \qmlclass Opacity QGraphicsOpacityEffect - \since 4.7 - \brief The Opacity object provides an opacity effect. - - An opacity effect renders the source with an opacity. This effect is useful - for making the source semi-transparent, similar to a fade-in/fade-out - sequence. The opacity can be modified using the opacity property. - - By default, the opacity is 0.7. - - \img graphicseffect-opacity.png -*/ - -/*! - \qmlproperty real Opacity::opacity - This property specifies how opaque an item should appear. - - The value should be in the range of 0.0 to 1.0, where 0.0 is - fully transparent and 1.0 is fully opaque. - - By default, the opacity is 0.7. -*/ - diff --git a/src/declarative/graphicsitems/qdeclarativeevents.cpp b/src/declarative/graphicsitems/qdeclarativeevents.cpp index a181071..4425c97 100644 --- a/src/declarative/graphicsitems/qdeclarativeevents.cpp +++ b/src/declarative/graphicsitems/qdeclarativeevents.cpp @@ -145,7 +145,7 @@ Item { */ /*! - \qmlproperty enum MouseEvent::button + \qmlproperty enumeration MouseEvent::button This property holds the button that caused the event. It can be one of: \list diff --git a/src/declarative/graphicsitems/qdeclarativeevents_p_p.h b/src/declarative/graphicsitems/qdeclarativeevents_p_p.h index 65ac8de..0e0329e 100644 --- a/src/declarative/graphicsitems/qdeclarativeevents_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeevents_p_p.h @@ -115,6 +115,10 @@ public: bool wasHeld() const { return _wasHeld; } bool isClick() const { return _isClick; } + // only for internal usage + void setX(int x) { _x = x; } + void setY(int y) { _y = y; } + bool isAccepted() { return _accepted; } void setAccepted(bool accepted) { _accepted = accepted; } diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 951b171..b462443 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -41,7 +41,7 @@ #include "private/qdeclarativeflickable_p.h" #include "private/qdeclarativeflickable_p_p.h" - +#include <qdeclarativeinfo.h> #include <QGraphicsSceneMouseEvent> #include <QPointer> #include <QTimer> @@ -125,12 +125,13 @@ QDeclarativeFlickablePrivate::QDeclarativeFlickablePrivate() : viewport(new QDeclarativeItem) , hData(this, &QDeclarativeFlickablePrivate::setRoundedViewportX) , vData(this, &QDeclarativeFlickablePrivate::setRoundedViewportY) - , overShoot(true), flicked(false), moving(false), stealMouse(false) + , flicked(false), moving(false), stealMouse(false) , pressed(false) , interactive(true), deceleration(500), maxVelocity(2000), reportedVelocitySmoothing(100) , delayedPressEvent(0), delayedPressTarget(0), pressDelay(0), fixupDuration(600) , vTime(0), visibleArea(0) , flickDirection(QDeclarativeFlickable::AutoFlickDirection) + , boundsBehavior(QDeclarativeFlickable::DragAndOvershootBounds) { } @@ -203,6 +204,7 @@ void QDeclarativeFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal { Q_Q(QDeclarativeFlickable); qreal maxDistance = -1; + bool overShoot = boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds; // -ve velocity means list is moving up if (velocity > 0) { if (data.move.value() < minExtent) @@ -248,18 +250,12 @@ void QDeclarativeFlickablePrivate::fixupX_callback(void *data) void QDeclarativeFlickablePrivate::fixupX() { Q_Q(QDeclarativeFlickable); - if (!q->xflick() || hData.move.timeLine()) - return; - fixup(hData, q->minXExtent(), q->maxXExtent()); } void QDeclarativeFlickablePrivate::fixupY() { Q_Q(QDeclarativeFlickable); - if (!q->yflick() || vData.move.timeLine()) - return; - fixup(vData, q->minYExtent(), q->maxYExtent()); } @@ -272,7 +268,7 @@ void QDeclarativeFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal if (fixupDuration) { qreal dist = minExtent - data.move; timeline.move(data.move, minExtent - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4); - timeline.move(data.move, minExtent, QEasingCurve(QEasingCurve::OutQuint), 3*fixupDuration/4); + timeline.move(data.move, minExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4); } else { data.move.setValue(minExtent); q->viewportMoved(); @@ -284,7 +280,7 @@ void QDeclarativeFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal if (fixupDuration) { qreal dist = maxExtent - data.move; timeline.move(data.move, maxExtent - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4); - timeline.move(data.move, maxExtent, QEasingCurve(QEasingCurve::OutQuint), 3*fixupDuration/4); + timeline.move(data.move, maxExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4); } else { data.move.setValue(maxExtent); q->viewportMoved(); @@ -652,7 +648,7 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent newY = minY + (newY - minY) / 2; if (newY < maxY && maxY - minY <= 0) newY = maxY + (newY - maxY) / 2; - if (!q->overShoot() && (newY > minY || newY < maxY)) { + if (boundsBehavior == QDeclarativeFlickable::StopAtBounds && (newY > minY || newY < maxY)) { if (newY > minY) newY = minY; else if (newY < maxY) @@ -661,7 +657,7 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent rejectY = true; } if (!rejectY && stealMouse) { - vData.move.setValue(newY); + vData.move.setValue(qRound(newY)); moved = true; } if (qAbs(dy) > QApplication::startDragDistance()) @@ -679,7 +675,7 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent newX = minX + (newX - minX) / 2; if (newX < maxX && maxX - minX <= 0) newX = maxX + (newX - maxX) / 2; - if (!q->overShoot() && (newX > minX || newX < maxX)) { + if (boundsBehavior == QDeclarativeFlickable::StopAtBounds && (newX > minX || newX < maxX)) { if (newX > minX) newX = minX; else if (newX < maxX) @@ -688,7 +684,7 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent rejectX = true; } if (!rejectX && stealMouse) { - hData.move.setValue(newX); + hData.move.setValue(qRound(newX)); moved = true; } @@ -1003,28 +999,58 @@ QDeclarativeListProperty<QGraphicsObject> QDeclarativeFlickable::flickableChildr return QGraphicsItemPrivate::get(d->viewport)->childrenList(); } +bool QDeclarativeFlickable::overShoot() const +{ + Q_D(const QDeclarativeFlickable); + return d->boundsBehavior == DragAndOvershootBounds; +} + +void QDeclarativeFlickable::setOverShoot(bool o) +{ + Q_D(QDeclarativeFlickable); + if ((o && d->boundsBehavior == DragAndOvershootBounds) + || (!o && d->boundsBehavior == StopAtBounds)) + return; + qmlInfo(this) << "overshoot is deprecated and will be removed imminently - use boundsBehavior."; + d->boundsBehavior = o ? DragAndOvershootBounds : StopAtBounds; + emit boundsBehaviorChanged(); + emit overShootChanged(); +} + /*! - \qmlproperty bool Flickable::overShoot - This property holds whether the surface may overshoot the + \qmlproperty enumeration Flickable::boundsBehavior + This property holds whether the surface may be dragged + beyond the Fickable's boundaries, or overshoot the Flickable's boundaries when flicked. - If overShoot is true the contents can be flicked beyond the boundary - of the Flickable before being moved back to the boundary. This provides - the feeling that the edges of the view are soft, rather than a hard - physical boundary. + This enables the feeling that the edges of the view are soft, + rather than a hard physical boundary. + + boundsBehavior can be one of: + + \list + \o \e StopAtBounds - the contents can not be dragged beyond the boundary + of the flickable, and flicks will not overshoot. + \o \e DragOverBounds - the contents can be dragged beyond the boundary + of the Flickable, but flicks will not overshoot. + \o \e DragAndOvershootBounds (default) - the contents can be dragged + beyond the boundary of the Flickable, and can overshoot the + boundary when flicked. + \endlist */ -bool QDeclarativeFlickable::overShoot() const +QDeclarativeFlickable::BoundsBehavior QDeclarativeFlickable::boundsBehavior() const { Q_D(const QDeclarativeFlickable); - return d->overShoot; + return d->boundsBehavior; } -void QDeclarativeFlickable::setOverShoot(bool o) +void QDeclarativeFlickable::setBoundsBehavior(BoundsBehavior b) { Q_D(QDeclarativeFlickable); - if (d->overShoot == o) + if (b == d->boundsBehavior) return; - d->overShoot = o; + d->boundsBehavior = b; + emit boundsBehaviorChanged(); emit overShootChanged(); } @@ -1059,8 +1085,12 @@ void QDeclarativeFlickable::setContentWidth(qreal w) else d->viewport->setWidth(w); // Make sure that we're entirely in view. - if (!d->pressed) + if (!d->pressed) { + int oldDuration = d->fixupDuration; + d->fixupDuration = 0; d->fixupX(); + d->fixupDuration = oldDuration; + } emit contentWidthChanged(); d->updateBeginningEnd(); } @@ -1082,8 +1112,12 @@ void QDeclarativeFlickable::setContentHeight(qreal h) else d->viewport->setHeight(h); // Make sure that we're entirely in view. - if (!d->pressed) + if (!d->pressed) { + int oldDuration = d->fixupDuration; + d->fixupDuration = 0; d->fixupY(); + d->fixupDuration = oldDuration; + } emit contentHeightChanged(); d->updateBeginningEnd(); } diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p.h index 1fa2c74..f031a24 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p.h @@ -64,7 +64,8 @@ class Q_DECLARATIVE_EXPORT QDeclarativeFlickable : public QDeclarativeItem Q_PROPERTY(qreal horizontalVelocity READ horizontalVelocity NOTIFY horizontalVelocityChanged) Q_PROPERTY(qreal verticalVelocity READ verticalVelocity NOTIFY verticalVelocityChanged) - Q_PROPERTY(bool overShoot READ overShoot WRITE setOverShoot NOTIFY overShootChanged) + Q_PROPERTY(bool overShoot READ overShoot WRITE setOverShoot NOTIFY overShootChanged) // deprecated + Q_PROPERTY(BoundsBehavior boundsBehavior READ boundsBehavior WRITE setBoundsBehavior NOTIFY boundsBehaviorChanged) Q_PROPERTY(qreal maximumFlickVelocity READ maximumFlickVelocity WRITE setMaximumFlickVelocity NOTIFY maximumFlickVelocityChanged) Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged) Q_PROPERTY(bool moving READ isMoving NOTIFY movingChanged) @@ -86,6 +87,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeFlickable : public QDeclarativeItem Q_CLASSINFO("DefaultProperty", "flickableData") Q_ENUMS(FlickDirection) + Q_ENUMS(BoundsBehavior) public: QDeclarativeFlickable(QDeclarativeItem *parent=0); @@ -97,6 +99,10 @@ public: bool overShoot() const; void setOverShoot(bool); + enum BoundsBehavior { StopAtBounds, DragOverBounds, DragAndOvershootBounds }; + BoundsBehavior boundsBehavior() const; + void setBoundsBehavior(BoundsBehavior); + qreal contentWidth() const; void setContentWidth(qreal); @@ -156,6 +162,7 @@ Q_SIGNALS: void flickDirectionChanged(); void interactiveChanged(); void overShootChanged(); + void boundsBehaviorChanged(); void maximumFlickVelocityChanged(); void flickDecelerationChanged(); void pressDelayChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h index 1a04091..01cfb18 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p_p.h @@ -131,7 +131,6 @@ public: AxisData vData; QDeclarativeTimeLine timeline; - bool overShoot : 1; bool flicked : 1; bool moving : 1; bool stealMouse : 1; @@ -160,6 +159,7 @@ public: QDeclarativeTimeLine velocityTimeline; QDeclarativeFlickableVisibleArea *visibleArea; QDeclarativeFlickable::FlickDirection flickDirection; + QDeclarativeFlickable::BoundsBehavior boundsBehavior; void handleMousePressEvent(QGraphicsSceneMouseEvent *); void handleMouseMoveEvent(QGraphicsSceneMouseEvent *); diff --git a/src/declarative/graphicsitems/qdeclarativeflipable.cpp b/src/declarative/graphicsitems/qdeclarativeflipable.cpp index 98e34a9..57045f1 100644 --- a/src/declarative/graphicsitems/qdeclarativeflipable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflipable.cpp @@ -57,10 +57,14 @@ public: QDeclarativeFlipablePrivate() : current(QDeclarativeFlipable::Front), front(0), back(0) {} void updateSceneTransformFromParent(); + void setBackTransform(); QDeclarativeFlipable::Side current; QDeclarativeGuard<QGraphicsObject> front; QDeclarativeGuard<QGraphicsObject> back; + + bool wantBackXFlipped; + bool wantBackYFlipped; }; /*! @@ -148,6 +152,17 @@ void QDeclarativeFlipable::setBack(QGraphicsObject *back) d->back->setParentItem(this); if (Front == d->current) d->back->setOpacity(0.); + connect(back, SIGNAL(widthChanged()), + this, SLOT(retransformBack())); + connect(back, SIGNAL(heightChanged()), + this, SLOT(retransformBack())); +} + +void QDeclarativeFlipable::retransformBack() +{ + Q_D(QDeclarativeFlipable); + if (d->current == QDeclarativeFlipable::Back && d->back) + d->setBackTransform(); } /*! @@ -184,26 +199,20 @@ void QDeclarativeFlipablePrivate::updateSceneTransformFromParent() qreal cross = (p1.x() - p2.x()) * (p3.y() - p2.y()) - (p1.y() - p2.y()) * (p3.x() - p2.x()); + wantBackYFlipped = p1.x() >= p2.x(); + wantBackXFlipped = p2.y() >= p3.y(); + QDeclarativeFlipable::Side newSide; if (cross > 0) { - newSide = QDeclarativeFlipable::Back; + newSide = QDeclarativeFlipable::Back; } else { newSide = QDeclarativeFlipable::Front; } if (newSide != current) { current = newSide; - if (current == QDeclarativeFlipable::Back && back) { - QTransform mat; - QGraphicsItemPrivate *dBack = QGraphicsItemPrivate::get(back); - mat.translate(dBack->width()/2,dBack->height()/2); - if (dBack->width() && p1.x() >= p2.x()) - mat.rotate(180, Qt::YAxis); - if (dBack->height() && p2.y() >= p3.y()) - mat.rotate(180, Qt::XAxis); - mat.translate(-dBack->width()/2,-dBack->height()/2); - back->setTransform(mat); - } + if (current == QDeclarativeFlipable::Back && back) + setBackTransform(); if (front) front->setOpacity((current==QDeclarativeFlipable::Front)?1.:0.); if (back) @@ -212,4 +221,20 @@ void QDeclarativeFlipablePrivate::updateSceneTransformFromParent() } } +/* Depends on the width/height of the back item, and so needs reevaulating + if those change. +*/ +void QDeclarativeFlipablePrivate::setBackTransform() +{ + QTransform mat; + QGraphicsItemPrivate *dBack = QGraphicsItemPrivate::get(back); + mat.translate(dBack->width()/2,dBack->height()/2); + if (dBack->width() && wantBackYFlipped) + mat.rotate(180, Qt::YAxis); + if (dBack->height() && wantBackXFlipped) + mat.rotate(180, Qt::XAxis); + mat.translate(-dBack->width()/2,-dBack->height()/2); + back->setTransform(mat); +} + QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativeflipable_p.h b/src/declarative/graphicsitems/qdeclarativeflipable_p.h index 302f083..fd0119b 100644 --- a/src/declarative/graphicsitems/qdeclarativeflipable_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflipable_p.h @@ -81,6 +81,9 @@ public: Q_SIGNALS: void sideChanged(); +private Q_SLOTS: + void retransformBack(); + private: Q_DISABLE_COPY(QDeclarativeFlipable) Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeFlipable) diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 562ba2a..f8b773e 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -50,6 +50,7 @@ #include <qlistmodelinterface_p.h> #include <QKeyEvent> +#include <qmath.h> #include <math.h> QT_BEGIN_NAMESPACE @@ -346,6 +347,7 @@ public: void QDeclarativeGridViewPrivate::init() { Q_Q(QDeclarativeGridView); + QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped())); q->setFlag(QGraphicsItem::ItemIsFocusScope); q->setFlickDirection(QDeclarativeFlickable::VerticalFlick); addItemChangeListener(this, Geometry); @@ -746,24 +748,31 @@ void QDeclarativeGridViewPrivate::fixupPosition() void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent) { Q_Q(QDeclarativeGridView); - - if ((&data == &vData && !q->yflick()) - || (&data == &hData && !q->xflick()) - || data.move.timeLine()) + if ((flow == QDeclarativeGridView::TopToBottom && &data == &vData) + || (flow == QDeclarativeGridView::LeftToRight && &data == &hData)) return; int oldDuration = fixupDuration; fixupDuration = moveReason == Mouse ? fixupDuration : 0; if (haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange) { - if (currentItem && currentItem->rowPos() - position() != highlightRangeStart) { - qreal pos = currentItem->rowPos() - highlightRangeStart; + if (currentItem) { + updateHighlight(); + qreal pos = currentItem->rowPos(); + qreal viewPos = position(); + if (viewPos < pos + rowSize() - highlightRangeEnd) + viewPos = pos + rowSize() - highlightRangeEnd; + if (viewPos > pos - highlightRangeStart) + viewPos = pos - highlightRangeStart; + timeline.reset(data.move); - if (fixupDuration) { - timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); - } else { - data.move.setValue(-pos); - q->viewportMoved(); + if (viewPos != position()) { + if (fixupDuration) { + timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); + } else { + data.move.setValue(-viewPos); + q->viewportMoved(); + } } vTime = timeline.time(); } @@ -808,7 +817,7 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m maxDistance = qAbs(minExtent - data.move.value()); } } - if (snapMode != QDeclarativeGridView::SnapToRow && highlightRange != QDeclarativeGridView::StrictlyEnforceRange) + if (snapMode == QDeclarativeGridView::NoSnap && highlightRange != QDeclarativeGridView::StrictlyEnforceRange) data.flickTarget = minExtent; } else { if (data.move.value() > maxExtent) { @@ -819,9 +828,10 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m maxDistance = qAbs(maxExtent - data.move.value()); } } - if (snapMode != QDeclarativeGridView::SnapToRow && highlightRange != QDeclarativeGridView::StrictlyEnforceRange) + if (snapMode == QDeclarativeGridView::NoSnap && highlightRange != QDeclarativeGridView::StrictlyEnforceRange) data.flickTarget = maxExtent; } + bool overShoot = boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds; if (maxDistance > 0 || overShoot) { // This mode requires the grid to stop exactly on a row boundary. qreal v = velocity; @@ -840,7 +850,15 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m if (v > 0) dist = -dist; data.flickTarget = -snapPosAt(-(data.move.value() - highlightRangeStart) + dist) + highlightRangeStart; - dist = -data.flickTarget + data.move.value(); + qreal adjDist = -data.flickTarget + data.move.value(); + if (qAbs(adjDist) > qAbs(dist)) { + // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration + v2 = accel * 2.0f * qAbs(dist); + v = qSqrt(v2); + if (dist > 0) + v = -v; + } + dist = adjDist; accel = v2 / (2.0f * qAbs(dist)); } else { data.flickTarget = velocity > 0 ? minExtent : maxExtent; @@ -885,7 +903,7 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m In this case ListModel is a handy way for us to test our UI. In practice the model would be implemented in C++, or perhaps via a SQL data source. - Note that views do not enable \e clip automatically. If the view + \bold Note that views do not enable \e clip automatically. If the view is not clipped by another item or the screen, it will be necessary to set \e {clip: true} in order to have the out of view items clipped nicely. @@ -1507,12 +1525,12 @@ void QDeclarativeGridView::viewportMoved() if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) { // reposition highlight qreal pos = d->highlight->rowPos(); - qreal viewPos = qRound(d->position()); - if (pos > viewPos + d->highlightRangeEnd - 1 - d->rowSize()) - pos = viewPos + d->highlightRangeEnd - 1 - d->rowSize(); + qreal viewPos = d->position(); + if (pos > viewPos + d->highlightRangeEnd - d->rowSize()) + pos = viewPos + d->highlightRangeEnd - d->rowSize(); if (pos < viewPos + d->highlightRangeStart) pos = viewPos + d->highlightRangeStart; - d->highlight->setPosition(d->highlight->colPos(), pos); + d->highlight->setPosition(d->highlight->colPos(), qRound(pos)); // update current index int idx = d->snapIndex(); @@ -1535,8 +1553,10 @@ qreal QDeclarativeGridView::minYExtent() const if (d->flow == QDeclarativeGridView::TopToBottom) return QDeclarativeFlickable::minYExtent(); qreal extent = -d->startPosition(); - if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) + if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) { extent += d->highlightRangeStart; + extent = qMax(extent, -(d->rowPosAt(0) + d->rowSize() - d->highlightRangeEnd)); + } return extent; } @@ -1547,8 +1567,9 @@ qreal QDeclarativeGridView::maxYExtent() const return QDeclarativeFlickable::maxYExtent(); qreal extent; if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) { - extent = -(d->endPosition() - d->highlightRangeEnd); - extent = qMax(extent, -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart)); + extent = -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart); + if (d->highlightRangeEnd != d->highlightRangeStart) + extent = qMin(extent, -(d->endPosition() - d->highlightRangeEnd + 1)); } else { extent = -(d->endPosition() - height()); } @@ -1564,8 +1585,10 @@ qreal QDeclarativeGridView::minXExtent() const if (d->flow == QDeclarativeGridView::LeftToRight) return QDeclarativeFlickable::minXExtent(); qreal extent = -d->startPosition(); - if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) + if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) { extent += d->highlightRangeStart; + extent = qMax(extent, -(d->rowPosAt(0) + d->rowSize() - d->highlightRangeEnd)); + } return extent; } @@ -1576,8 +1599,9 @@ qreal QDeclarativeGridView::maxXExtent() const return QDeclarativeFlickable::maxXExtent(); qreal extent; if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) { - extent = -(d->endPosition() - d->highlightRangeEnd); - extent = qMax(extent, -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart)); + extent = -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart); + if (d->highlightRangeEnd != d->highlightRangeStart) + extent = qMin(extent, -(d->endPosition() - d->highlightRangeEnd + 1)); } else { extent = -(d->endPosition() - height()); } @@ -2247,6 +2271,13 @@ void QDeclarativeGridView::destroyingItem(QDeclarativeItem *item) d->unrequestedItems.remove(item); } +void QDeclarativeGridView::animStopped() +{ + Q_D(QDeclarativeGridView); + d->bufferMode = QDeclarativeGridViewPrivate::NoBuffer; + if (d->haveHighlightRange && d->highlightRange == QDeclarativeGridView::StrictlyEnforceRange) + d->updateHighlight(); +} void QDeclarativeGridView::refill() { diff --git a/src/declarative/graphicsitems/qdeclarativegridview_p.h b/src/declarative/graphicsitems/qdeclarativegridview_p.h index 5baa1dd..c06879e 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview_p.h +++ b/src/declarative/graphicsitems/qdeclarativegridview_p.h @@ -192,6 +192,7 @@ private Q_SLOTS: void destroyRemoved(); void createdItem(int index, QDeclarativeItem *item); void destroyingItem(QDeclarativeItem *item); + void animStopped(); private: void refill(); diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp index ca86637..247e348 100644 --- a/src/declarative/graphicsitems/qdeclarativeimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp @@ -221,7 +221,7 @@ qreal QDeclarativeImage::paintedHeight() const } /*! - \qmlproperty enum Image::status + \qmlproperty enumeration Image::status This property holds the status of image loading. It can be one of: \list @@ -236,9 +236,12 @@ qreal QDeclarativeImage::paintedHeight() const to react to the change in status you need to do it yourself, for example in one of the following ways: \list - \o Create a state, so that a state change occurs, e.g. State{name: 'loaded'; when: image.status = Image.Ready;} - \o Do something inside the onStatusChanged signal handler, e.g. Image{id: image; onStatusChanged: if(image.status == Image.Ready) console.log('Loaded');} - \o Bind to the status variable somewhere, e.g. Text{text: if(image.status!=Image.Ready){'Not Loaded';}else{'Loaded';}} + \o Create a state, so that a state change occurs, e.g. + \qml State { name: 'loaded'; when: image.status = Image.Ready } \endqml + \o Do something inside the onStatusChanged signal handler, e.g. + \qml Image { id: image; onStatusChanged: if (image.status == Image.Ready) console.log('Loaded') } \endqml + \o Bind to the status variable somewhere, e.g. + \qml Text { text: if (image.status != Image.Ready) { 'Not Loaded' } else { 'Loaded' } } \endqml \endlist \sa progress @@ -366,12 +369,27 @@ void QDeclarativeImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWi if (width() != d->pix.width() || height() != d->pix.height()) { if (d->fillMode >= Tile) { - if (d->fillMode == Tile) + if (d->fillMode == Tile) { p->drawTiledPixmap(QRectF(0,0,width(),height()), d->pix); - else if (d->fillMode == TileVertically) - p->drawTiledPixmap(QRectF(0,0,d->pix.width(),height()), d->pix); - else - p->drawTiledPixmap(QRectF(0,0,width(),d->pix.height()), d->pix); + } else { + qreal widthScale = width() / qreal(d->pix.width()); + qreal heightScale = height() / qreal(d->pix.height()); + + QTransform scale; + if (d->fillMode == TileVertically) { + scale.scale(widthScale, 1.0); + QTransform old = p->transform(); + p->setWorldTransform(scale * old); + p->drawTiledPixmap(QRectF(0,0,d->pix.width(),height()), d->pix); + p->setWorldTransform(old); + } else { + scale.scale(1.0, heightScale); + QTransform old = p->transform(); + p->setWorldTransform(scale * old); + p->drawTiledPixmap(QRectF(0,0,width(),d->pix.height()), d->pix); + p->setWorldTransform(old); + } + } } else { qreal widthScale = width() / qreal(d->pix.width()); qreal heightScale = height() / qreal(d->pix.height()); diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 86dbaf0..bc0c65e 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -61,7 +61,6 @@ #include <QtCore/qnumeric.h> #include <QtScript/qscriptengine.h> #include <QtGui/qgraphicstransform.h> -#include <QtGui/qgraphicseffect.h> #include <qlistmodelinterface_p.h> QT_BEGIN_NAMESPACE @@ -70,8 +69,6 @@ QT_BEGIN_NAMESPACE #define FLT_MAX 1E+37 #endif -#include "qdeclarativeeffects.cpp" - /*! \qmlclass Transform QGraphicsTransform \since 4.7 @@ -234,11 +231,6 @@ QT_BEGIN_NAMESPACE */ /*! - \group group_effects - \title Effects -*/ - -/*! \group group_layouts \title Layouts */ @@ -275,17 +267,6 @@ QDeclarativeContents::QDeclarativeContents() : m_x(0), m_y(0), m_width(0), m_hei { } -/*! - \qmlproperty real Item::childrenRect.x - \qmlproperty real Item::childrenRect.y - \qmlproperty real Item::childrenRect.width - \qmlproperty real Item::childrenRect.height - - The childrenRect properties allow an item access to the geometry of its - children. This property is useful if you have an item that needs to be - sized to fit its children. -*/ - QRectF QDeclarativeContents::rectF() const { return QRectF(m_x, m_y, m_width, m_height); @@ -1415,7 +1396,7 @@ QDeclarativeItem::~QDeclarativeItem() } /*! - \qmlproperty enum Item::transformOrigin + \qmlproperty enumeration Item::transformOrigin This property holds the origin point around which scale and rotation transform. Nine transform origins are available, as shown in the image below. @@ -1457,6 +1438,18 @@ QDeclarativeItem *QDeclarativeItem::parentItem() const } /*! + \qmlproperty real Item::childrenRect.x + \qmlproperty real Item::childrenRect.y + \qmlproperty real Item::childrenRect.width + \qmlproperty real Item::childrenRect.height + + The childrenRect properties allow an item access to the geometry of its + children. This property is useful if you have an item that needs to be + sized to fit its children. +*/ + + +/*! \qmlproperty list<Item> Item::children \qmlproperty list<Object> Item::resources @@ -1594,10 +1587,10 @@ void QDeclarativeItemPrivate::transform_clear(QDeclarativeListProperty<QGraphics } } -void QDeclarativeItemPrivate::parentProperty(QObject *o, void *rv, QDeclarativeNotifierEndpoint *e) +void QDeclarativeItemPrivate::parentProperty(QObject *o, void *rv, QDeclarativeNotifierEndpoint *e) { QDeclarativeItem *item = static_cast<QDeclarativeItem*>(o); - if (e) + if (e) e->connect(&item->d_func()->parentNotifier); *((QDeclarativeItem **)rv) = item->parentItem(); } @@ -1794,9 +1787,13 @@ void QDeclarativeItem::geometryChanged(const QRectF &newGeometry, if (transformOrigin() != QDeclarativeItem::TopLeft && (newGeometry.width() != oldGeometry.width() || newGeometry.height() != oldGeometry.height())) { - QPointF origin = d->computeTransformOrigin(); - if (transformOriginPoint() != origin) - setTransformOriginPoint(origin); + if (d->transformData) { + QPointF origin = d->computeTransformOrigin(); + if (transformOriginPoint() != origin) + setTransformOriginPoint(origin); + } else { + d->transformOriginDirty = true; + } } if (newGeometry.x() != oldGeometry.x()) @@ -2149,8 +2146,8 @@ void QDeclarativeItem::setBaselineOffset(qreal offset) Opacity is an \e inherited attribute. That is, the opacity is also applied individually to child items. In almost all cases this - is what you want. If you can spot the issue in the following - example, you might need to use an \l Opacity effect instead. + is what you want, but in some cases (like the following example) + it may produce undesired results. \table \row @@ -2238,7 +2235,7 @@ QScriptValue QDeclarativeItem::mapFromItem(const QScriptValue &item, qreal x, qr QScriptValue sv = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this))->newObject(); QDeclarativeItem *itemObj = qobject_cast<QDeclarativeItem*>(item.toQObject()); if (!itemObj && !item.isNull()) { - qWarning().nospace() << "mapFromItem() given argument " << item.toString() << " which is neither null nor an Item"; + qmlInfo(this) << "mapFromItem() given argument \"" << item.toString() << "\" which is neither null nor an Item"; return 0; } @@ -2264,7 +2261,7 @@ QScriptValue QDeclarativeItem::mapToItem(const QScriptValue &item, qreal x, qrea QScriptValue sv = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this))->newObject(); QDeclarativeItem *itemObj = qobject_cast<QDeclarativeItem*>(item.toQObject()); if (!itemObj && !item.isNull()) { - qWarning().nospace() << "mapToItem() given argument " << item.toString() << " which is neither null nor an Item"; + qmlInfo(this) << "mapToItem() given argument \"" << item.toString() << "\" which is neither null nor an Item"; return 0; } @@ -2275,6 +2272,23 @@ QScriptValue QDeclarativeItem::mapToItem(const QScriptValue &item, qreal x, qrea return sv; } +/*! + \qmlmethod Item::forceFocus() + + Force the focus on the item. + This method sets the focus on the item and makes sure that all the focus scopes higher in the object hierarchy are given focus. +*/ +void QDeclarativeItem::forceFocus() +{ + setFocus(true); + QGraphicsItem *parent = parentItem(); + while (parent) { + if (parent->flags() & QGraphicsItem::ItemIsFocusScope) + parent->setFocus(Qt::OtherFocusReason); + parent = parent->parentItem(); + } +} + void QDeclarativeItemPrivate::focusChanged(bool flag) { Q_Q(QDeclarativeItem); @@ -2656,11 +2670,23 @@ void QDeclarativeItem::setTransformOrigin(TransformOrigin origin) Q_D(QDeclarativeItem); if (origin != d->origin) { d->origin = origin; - QGraphicsItem::setTransformOriginPoint(d->computeTransformOrigin()); + if (d->transformData) + QGraphicsItem::setTransformOriginPoint(d->computeTransformOrigin()); + else + d->transformOriginDirty = true; emit transformOriginChanged(d->origin); } } +void QDeclarativeItemPrivate::transformChanged() +{ + Q_Q(QDeclarativeItem); + if (transformOriginDirty) { + q->QGraphicsItem::setTransformOriginPoint(computeTransformOrigin()); + transformOriginDirty = false; + } +} + /*! \property QDeclarativeItem::smooth \brief whether the item is smoothly transformed. diff --git a/src/declarative/graphicsitems/qdeclarativeitem.h b/src/declarative/graphicsitems/qdeclarativeitem.h index 51889f6..da5a36e 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.h +++ b/src/declarative/graphicsitems/qdeclarativeitem.h @@ -157,6 +157,7 @@ public: Q_INVOKABLE QScriptValue mapFromItem(const QScriptValue &item, qreal x, qreal y) const; Q_INVOKABLE QScriptValue mapToItem(const QScriptValue &item, qreal x, qreal y) const; + Q_INVOKABLE void forceFocus(); QDeclarativeAnchorLine left() const; QDeclarativeAnchorLine right() const; diff --git a/src/declarative/graphicsitems/qdeclarativeitem_p.h b/src/declarative/graphicsitems/qdeclarativeitem_p.h index cf138c3..3f5bf1a 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem_p.h +++ b/src/declarative/graphicsitems/qdeclarativeitem_p.h @@ -116,7 +116,7 @@ public: _stateGroup(0), origin(QDeclarativeItem::Center), widthValid(false), heightValid(false), _componentComplete(true), _keepMouse(false), - smooth(false), keyHandler(0), + smooth(false), transformOriginDirty(true), keyHandler(0), mWidth(0), mHeight(0), implicitWidth(0), implicitHeight(0) { QGraphicsItemPrivate::acceptedMouseButtons = 0; @@ -233,6 +233,7 @@ public: bool _componentComplete:1; bool _keepMouse:1; bool smooth:1; + bool transformOriginDirty : 1; QDeclarativeItemKeyFilter *keyHandler; @@ -269,6 +270,9 @@ public: } } + // Reimplemented from QGraphicsItemPrivate + virtual void transformChanged(); + virtual void focusChanged(bool); static int consistentTime; diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index 2d01eef..2945b6c 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -46,7 +46,6 @@ #include <QtGui/qgraphicseffect.h> #include "private/qdeclarativeevents_p_p.h" -#include "private/qdeclarativeeffects_p.h" #include "private/qdeclarativescalegrid_p_p.h" #include "private/qdeclarativeanimatedimage_p.h" #include "private/qdeclarativeborderimage_p.h" @@ -82,56 +81,59 @@ void QDeclarativeItemModule::defineModule() { -#ifndef QT_NO_MOVIE - qmlRegisterType<QDeclarativeAnimatedImage>("Qt",4,6,"AnimatedImage"); +#ifdef QT_NO_MOVIE + qmlRegisterTypeNotAvailable("Qt",4,7,"AnimatedImage", + qApp->translate("QDeclarativeAnimatedImage","Qt was built without support for QMovie")); +#else + qmlRegisterType<QDeclarativeAnimatedImage>("Qt",4,7,"AnimatedImage"); #endif - qmlRegisterType<QDeclarativeBorderImage>("Qt",4,6,"BorderImage"); - qmlRegisterType<QDeclarativeColumn>("Qt",4,6,"Column"); - qmlRegisterType<QDeclarativeDrag>("Qt",4,6,"Drag"); - qmlRegisterType<QDeclarativeFlickable>("Qt",4,6,"Flickable"); - qmlRegisterType<QDeclarativeFlipable>("Qt",4,6,"Flipable"); - qmlRegisterType<QDeclarativeFlow>("Qt",4,6,"Flow"); - qmlRegisterType<QDeclarativeFocusPanel>("Qt",4,6,"FocusPanel"); - qmlRegisterType<QDeclarativeFocusScope>("Qt",4,6,"FocusScope"); - qmlRegisterType<QDeclarativeGradient>("Qt",4,6,"Gradient"); - qmlRegisterType<QDeclarativeGradientStop>("Qt",4,6,"GradientStop"); - qmlRegisterType<QDeclarativeGrid>("Qt",4,6,"Grid"); - qmlRegisterType<QDeclarativeGridView>("Qt",4,6,"GridView"); - qmlRegisterType<QDeclarativeImage>("Qt",4,6,"Image"); - qmlRegisterType<QDeclarativeItem>("Qt",4,6,"Item"); - qmlRegisterType<QDeclarativeLayoutItem>("Qt",4,6,"LayoutItem"); - qmlRegisterType<QDeclarativeListView>("Qt",4,6,"ListView"); - qmlRegisterType<QDeclarativeLoader>("Qt",4,6,"Loader"); - qmlRegisterType<QDeclarativeMouseArea>("Qt",4,6,"MouseArea"); - qmlRegisterType<QDeclarativePath>("Qt",4,6,"Path"); - qmlRegisterType<QDeclarativePathAttribute>("Qt",4,6,"PathAttribute"); - qmlRegisterType<QDeclarativePathCubic>("Qt",4,6,"PathCubic"); - qmlRegisterType<QDeclarativePathLine>("Qt",4,6,"PathLine"); - qmlRegisterType<QDeclarativePathPercent>("Qt",4,6,"PathPercent"); - qmlRegisterType<QDeclarativePathQuad>("Qt",4,6,"PathQuad"); - qmlRegisterType<QDeclarativePathView>("Qt",4,6,"PathView"); - qmlRegisterType<QIntValidator>("Qt",4,6,"IntValidator"); + qmlRegisterType<QDeclarativeBorderImage>("Qt",4,7,"BorderImage"); + qmlRegisterType<QDeclarativeColumn>("Qt",4,7,"Column"); + qmlRegisterType<QDeclarativeDrag>("Qt",4,7,"Drag"); + qmlRegisterType<QDeclarativeFlickable>("Qt",4,7,"Flickable"); + qmlRegisterType<QDeclarativeFlipable>("Qt",4,7,"Flipable"); + qmlRegisterType<QDeclarativeFlow>("Qt",4,7,"Flow"); + qmlRegisterType<QDeclarativeFocusPanel>("Qt",4,7,"FocusPanel"); + qmlRegisterType<QDeclarativeFocusScope>("Qt",4,7,"FocusScope"); + qmlRegisterType<QDeclarativeGradient>("Qt",4,7,"Gradient"); + qmlRegisterType<QDeclarativeGradientStop>("Qt",4,7,"GradientStop"); + qmlRegisterType<QDeclarativeGrid>("Qt",4,7,"Grid"); + qmlRegisterType<QDeclarativeGridView>("Qt",4,7,"GridView"); + qmlRegisterType<QDeclarativeImage>("Qt",4,7,"Image"); + qmlRegisterType<QDeclarativeItem>("Qt",4,7,"Item"); + qmlRegisterType<QDeclarativeLayoutItem>("Qt",4,7,"LayoutItem"); + qmlRegisterType<QDeclarativeListView>("Qt",4,7,"ListView"); + qmlRegisterType<QDeclarativeLoader>("Qt",4,7,"Loader"); + qmlRegisterType<QDeclarativeMouseArea>("Qt",4,7,"MouseArea"); + qmlRegisterType<QDeclarativePath>("Qt",4,7,"Path"); + qmlRegisterType<QDeclarativePathAttribute>("Qt",4,7,"PathAttribute"); + qmlRegisterType<QDeclarativePathCubic>("Qt",4,7,"PathCubic"); + qmlRegisterType<QDeclarativePathLine>("Qt",4,7,"PathLine"); + qmlRegisterType<QDeclarativePathPercent>("Qt",4,7,"PathPercent"); + qmlRegisterType<QDeclarativePathQuad>("Qt",4,7,"PathQuad"); + qmlRegisterType<QDeclarativePathView>("Qt",4,7,"PathView"); + qmlRegisterType<QIntValidator>("Qt",4,7,"IntValidator"); qmlRegisterType<QDoubleValidator>("Qt",4,7,"DoubleValidator"); qmlRegisterType<QRegExpValidator>("Qt",4,7,"RegExpValidator"); - qmlRegisterType<QDeclarativeRectangle>("Qt",4,6,"Rectangle"); - qmlRegisterType<QDeclarativeRepeater>("Qt",4,6,"Repeater"); - qmlRegisterType<QGraphicsRotation>("Qt",4,6,"Rotation"); - qmlRegisterType<QDeclarativeRow>("Qt",4,6,"Row"); - qmlRegisterType<QDeclarativeTranslate>("Qt",4,6,"Translate"); - qmlRegisterType<QGraphicsScale>("Qt",4,6,"Scale"); - qmlRegisterType<QDeclarativeText>("Qt",4,6,"Text"); - qmlRegisterType<QDeclarativeTextEdit>("Qt",4,6,"TextEdit"); - qmlRegisterType<QDeclarativeTextInput>("Qt",4,6,"TextInput"); - qmlRegisterType<QDeclarativeViewSection>("Qt",4,6,"ViewSection"); - qmlRegisterType<QDeclarativeVisualDataModel>("Qt",4,6,"VisualDataModel"); - qmlRegisterType<QDeclarativeVisualItemModel>("Qt",4,6,"VisualItemModel"); + qmlRegisterType<QDeclarativeRectangle>("Qt",4,7,"Rectangle"); + qmlRegisterType<QDeclarativeRepeater>("Qt",4,7,"Repeater"); + qmlRegisterType<QGraphicsRotation>("Qt",4,7,"Rotation"); + qmlRegisterType<QDeclarativeRow>("Qt",4,7,"Row"); + qmlRegisterType<QDeclarativeTranslate>("Qt",4,7,"Translate"); + qmlRegisterType<QGraphicsScale>("Qt",4,7,"Scale"); + qmlRegisterType<QDeclarativeText>("Qt",4,7,"Text"); + qmlRegisterType<QDeclarativeTextEdit>("Qt",4,7,"TextEdit"); + qmlRegisterType<QDeclarativeTextInput>("Qt",4,7,"TextInput"); + qmlRegisterType<QDeclarativeViewSection>("Qt",4,7,"ViewSection"); + qmlRegisterType<QDeclarativeVisualDataModel>("Qt",4,7,"VisualDataModel"); + qmlRegisterType<QDeclarativeVisualItemModel>("Qt",4,7,"VisualItemModel"); qmlRegisterType<QDeclarativeAnchors>(); qmlRegisterType<QDeclarativeKeyEvent>(); qmlRegisterType<QDeclarativeMouseEvent>(); qmlRegisterType<QGraphicsObject>(); - qmlRegisterType<QGraphicsWidget>("Qt",4,6,"QGraphicsWidget"); - qmlRegisterExtendedType<QGraphicsWidget,QDeclarativeGraphicsWidget>("Qt",4,6,"QGraphicsWidget"); + qmlRegisterType<QGraphicsWidget>("Qt",4,7,"QGraphicsWidget"); + qmlRegisterExtendedType<QGraphicsWidget,QDeclarativeGraphicsWidget>("Qt",4,7,"QGraphicsWidget"); qmlRegisterType<QGraphicsTransform>(); qmlRegisterType<QDeclarativePathElement>(); qmlRegisterType<QDeclarativeCurve>(); @@ -141,17 +143,8 @@ void QDeclarativeItemModule::defineModule() qmlRegisterType<QAction>(); qmlRegisterType<QDeclarativePen>(); qmlRegisterType<QDeclarativeFlickableVisibleArea>(); -#ifndef QT_NO_GRAPHICSEFFECT qmlRegisterType<QGraphicsEffect>(); - qmlRegisterType<QGraphicsBlurEffect>("Qt",4,6,"Blur"); - qmlRegisterType<QGraphicsColorizeEffect>("Qt",4,6,"Colorize"); - qmlRegisterType<QGraphicsDropShadowEffect>("Qt",4,6,"DropShadow"); - qmlRegisterType<QGraphicsOpacityEffect>("Qt",4,6,"Opacity"); -#endif -#ifdef QT_WEBKIT_LIB - qmlRegisterType<QDeclarativeWebSettings>(); -#endif - qmlRegisterUncreatableType<QDeclarativeKeyNavigationAttached>("Qt",4,6,"KeyNavigation"); - qmlRegisterUncreatableType<QDeclarativeKeysAttached>("Qt",4,6,"Keys"); + qmlRegisterUncreatableType<QDeclarativeKeyNavigationAttached>("Qt",4,7,"KeyNavigation",QDeclarativeKeyNavigationAttached::tr("KeyNavigation is only available via attached properties")); + qmlRegisterUncreatableType<QDeclarativeKeysAttached>("Qt",4,7,"Keys",QDeclarativeKeysAttached::tr("Keys is only available via attached properties")); } diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index 307c0a7..60e8f6c 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -50,6 +50,7 @@ #include <qdeclarativeguard_p.h> #include <qlistmodelinterface_p.h> +#include <qmath.h> #include <QKeyEvent> QT_BEGIN_NAMESPACE @@ -270,6 +271,28 @@ public: return 0; } + qreal endPositionAt(int modelIndex) const { + if (FxListItem *item = visibleItem(modelIndex)) + return item->endPosition(); + if (!visibleItems.isEmpty()) { + if (modelIndex < visibleIndex) { + int count = visibleIndex - modelIndex; + return (*visibleItems.constBegin())->position() - (count - 1) * (averageSize + spacing) - spacing - 1; + } else { + int idx = visibleItems.count() - 1; + while (idx >= 0 && visibleItems.at(idx)->index == -1) + --idx; + if (idx < 0) + idx = visibleIndex; + else + idx = visibleItems.at(idx)->index; + int count = modelIndex - idx - 1; + return (*(--visibleItems.constEnd()))->endPosition() + count * (averageSize + spacing); + } + } + return 0; + } + QString sectionAt(int modelIndex) { if (FxListItem *item = visibleItem(modelIndex)) return item->attached->section(); @@ -395,13 +418,16 @@ public: } void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) { + Q_Q(QDeclarativeListView); QDeclarativeFlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry); - if (item != viewport) { + if (item != viewport && (!highlight || item != highlight->item)) { if ((orient == QDeclarativeListView::Vertical && newGeometry.height() != oldGeometry.height()) || (orient == QDeclarativeListView::Horizontal && newGeometry.width() != oldGeometry.width())) { scheduleLayout(); } } + if (trackedItem && trackedItem->item == item) + q->trackedPositionChanged(); } // for debugging only @@ -566,13 +592,8 @@ void QDeclarativeListViewPrivate::releaseItem(FxListItem *item) Q_Q(QDeclarativeListView); if (!item || !model) return; - if (trackedItem == item) { - const char *notifier1 = orient == QDeclarativeListView::Vertical ? SIGNAL(yChanged()) : SIGNAL(xChanged()); - const char *notifier2 = orient == QDeclarativeListView::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged()); - QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged())); - QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged())); + if (trackedItem == item) trackedItem = 0; - } QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item->item)); itemPrivate->removeItemChangeListener(this, QDeclarativeItemPrivate::Geometry); if (model->release(item->item) == 0) { @@ -769,21 +790,7 @@ void QDeclarativeListViewPrivate::updateTrackedItem() FxListItem *item = currentItem; if (highlight) item = highlight; - - const char *notifier1 = orient == QDeclarativeListView::Vertical ? SIGNAL(yChanged()) : SIGNAL(xChanged()); - const char *notifier2 = orient == QDeclarativeListView::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged()); - - if (trackedItem && item != trackedItem) { - QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged())); - QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged())); - trackedItem = 0; - } - - if (!trackedItem && item) { - trackedItem = item; - QObject::connect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged())); - QObject::connect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged())); - } + trackedItem = item; if (trackedItem) q->trackedPositionChanged(); } @@ -832,6 +839,8 @@ void QDeclarativeListViewPrivate::createHighlight() highlight->item->setWidth(currentItem->item->width()); } } + QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item)); + itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry); const QLatin1String posProp(orient == QDeclarativeListView::Vertical ? "y" : "x"); highlightPosAnimator = new QSmoothedAnimation(q); highlightPosAnimator->target = QDeclarativeProperty(highlight->item, posProp); @@ -1101,23 +1110,27 @@ void QDeclarativeListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal m || (orient == QDeclarativeListView::Vertical && &data == &hData)) return; - if ((&data == &vData && !q->yflick()) - || (&data == &hData && !q->xflick()) - || data.move.timeLine()) - return; - int oldDuration = fixupDuration; fixupDuration = moveReason == Mouse ? fixupDuration : 0; if (haveHighlightRange && highlightRange == QDeclarativeListView::StrictlyEnforceRange) { - if (currentItem && currentItem->position() - position() != highlightRangeStart) { - qreal pos = currentItem->position() - highlightRangeStart; + if (currentItem) { + updateHighlight(); + qreal pos = currentItem->position(); + qreal viewPos = position(); + if (viewPos < pos + currentItem->size() - highlightRangeEnd) + viewPos = pos + currentItem->size() - highlightRangeEnd; + if (viewPos > pos - highlightRangeStart) + viewPos = pos - highlightRangeStart; + timeline.reset(data.move); - if (fixupDuration) { - timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); - } else { - data.move.setValue(-pos); - q->viewportMoved(); + if (viewPos != position()) { + if (fixupDuration) { + timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2); + } else { + data.move.setValue(-viewPos); + q->viewportMoved(); + } } vTime = timeline.time(); } @@ -1177,6 +1190,7 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m if (snapMode == QDeclarativeListView::NoSnap && highlightRange != QDeclarativeListView::StrictlyEnforceRange) data.flickTarget = maxExtent; } + bool overShoot = boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds; if (maxDistance > 0 || overShoot) { // These modes require the list to stop exactly on an item boundary. // The initial flick will estimate the boundary to stop on. @@ -1211,7 +1225,15 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m data.flickTarget -= overshootDist; } } - dist = -data.flickTarget + data.move.value(); + qreal adjDist = -data.flickTarget + data.move.value(); + if (qAbs(adjDist) > qAbs(dist)) { + // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration + v2 = accel * 2.0f * qAbs(dist); + v = qSqrt(v2); + if (dist > 0) + v = -v; + } + dist = adjDist; accel = v2 / (2.0f * qAbs(dist)); } else if (overShoot) { data.flickTarget = data.move.value() - dist; @@ -1286,7 +1308,7 @@ void QDeclarativeListViewPrivate::flick(AxisData &data, qreal minExtent, qreal m In this case ListModel is a handy way for us to test our UI. In practice the model would be implemented in C++, or perhaps via a SQL data source. - Note that views do not enable \e clip automatically. If the view + \bold Note that views do not enable \e clip automatically. If the view is not clipped by another item or the screen, it will be necessary to set \e {clip: true} in order to have the out of view items clipped nicely. @@ -2062,12 +2084,12 @@ void QDeclarativeListView::viewportMoved() if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) { // reposition highlight qreal pos = d->highlight->position(); - qreal viewPos = qRound(d->position()); - if (pos > viewPos + d->highlightRangeEnd - 1 - d->highlight->size()) - pos = viewPos + d->highlightRangeEnd - 1 - d->highlight->size(); + qreal viewPos = d->position(); + if (pos > viewPos + d->highlightRangeEnd - d->highlight->size()) + pos = viewPos + d->highlightRangeEnd - d->highlight->size(); if (pos < viewPos + d->highlightRangeStart) pos = viewPos + d->highlightRangeStart; - d->highlight->setPosition(pos); + d->highlight->setPosition(qRound(pos)); // update current index int idx = d->snapIndex(); @@ -2124,8 +2146,10 @@ qreal QDeclarativeListView::minYExtent() const d->minExtent = -d->startPosition(); if (d->header && d->visibleItems.count()) d->minExtent += d->header->size(); - if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) + if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) { d->minExtent += d->highlightRangeStart; + d->minExtent = qMax(d->minExtent, -(d->endPositionAt(0) - d->highlightRangeEnd + 1)); + } d->minExtentDirty = false; } @@ -2139,10 +2163,12 @@ qreal QDeclarativeListView::maxYExtent() const return height(); if (d->maxExtentDirty) { if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) { - d->maxExtent = -(d->endPosition() - d->highlightRangeEnd); - d->maxExtent = qMax(d->maxExtent, -(d->positionAt(d->model->count()-1) - d->highlightRangeStart)); - } else + d->maxExtent = -(d->positionAt(d->model->count()-1) - d->highlightRangeStart); + if (d->highlightRangeEnd != d->highlightRangeStart) + d->maxExtent = qMin(d->maxExtent, -(d->endPosition() - d->highlightRangeEnd + 1)); + } else { d->maxExtent = -(d->endPosition() - height() + 1); + } if (d->footer) d->maxExtent -= d->footer->size(); qreal minY = minYExtent(); @@ -2162,8 +2188,10 @@ qreal QDeclarativeListView::minXExtent() const d->minExtent = -d->startPosition(); if (d->header) d->minExtent += d->header->size(); - if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) + if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) { d->minExtent += d->highlightRangeStart; + d->minExtent = qMax(d->minExtent, -(d->endPositionAt(0) - d->highlightRangeEnd + 1)); + } d->minExtentDirty = false; } @@ -2177,10 +2205,12 @@ qreal QDeclarativeListView::maxXExtent() const return width(); if (d->maxExtentDirty) { if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) { - d->maxExtent = -(d->endPosition() - d->highlightRangeEnd); - d->maxExtent = qMax(d->maxExtent, -(d->positionAt(d->model->count()-1) - d->highlightRangeStart)); - } else + d->maxExtent = -(d->positionAt(d->model->count()-1) - d->highlightRangeStart); + if (d->highlightRangeEnd != d->highlightRangeStart) + d->maxExtent = qMin(d->maxExtent, -(d->endPosition() - d->highlightRangeEnd + 1)); + } else { d->maxExtent = -(d->endPosition() - width() + 1); + } if (d->footer) d->maxExtent -= d->footer->size(); qreal minX = minXExtent(); @@ -2389,7 +2419,7 @@ void QDeclarativeListView::trackedPositionChanged() if (!d->trackedItem || !d->currentItem) return; if (!isFlicking() && !d->moving && d->moveReason == QDeclarativeListViewPrivate::SetIndex) { - const qreal trackedPos = d->trackedItem->position(); + const qreal trackedPos = qCeil(d->trackedItem->position()); const qreal viewPos = d->position(); if (d->haveHighlightRange) { if (d->highlightRange == StrictlyEnforceRange) { @@ -2823,6 +2853,8 @@ void QDeclarativeListView::animStopped() { Q_D(QDeclarativeListView); d->bufferMode = QDeclarativeListViewPrivate::NoBuffer; + if (d->haveHighlightRange && d->highlightRange == QDeclarativeListView::StrictlyEnforceRange) + d->updateHighlight(); } QDeclarativeListViewAttached *QDeclarativeListView::qmlAttachedProperties(QObject *obj) diff --git a/src/declarative/graphicsitems/qdeclarativeloader.cpp b/src/declarative/graphicsitems/qdeclarativeloader.cpp index 409c228..bdd2c87 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader.cpp +++ b/src/declarative/graphicsitems/qdeclarativeloader.cpp @@ -132,12 +132,15 @@ void QDeclarativeLoaderPrivate::initResize() \endcode If the Loader source is changed, any previous items instantiated - will be destroyed. Setting \c source to an empty string + will be destroyed. Setting \c source to an empty string, or setting + sourceComponent to \e undefined will destroy the currently instantiated items, freeing resources and leaving the Loader empty. For example: \code pageLoader.source = "" + or + pageLoader.sourceComponent = undefined \endcode unloads "Page1.qml" and frees resources consumed by it. @@ -271,13 +274,18 @@ void QDeclarativeLoader::setSourceComponent(QDeclarativeComponent *comp) } } +void QDeclarativeLoader::resetSourceComponent() +{ + setSourceComponent(0); +} + void QDeclarativeLoaderPrivate::_q_sourceLoaded() { Q_Q(QDeclarativeLoader); if (component) { if (!component->errors().isEmpty()) { - qWarning() << component->errors(); + QDeclarativeEnginePrivate::warning(qmlEngine(q), component->errors()); emit q->sourceChanged(); emit q->statusChanged(); emit q->progressChanged(); @@ -312,7 +320,7 @@ void QDeclarativeLoaderPrivate::_q_sourceLoaded() } } else { if (!component->errors().isEmpty()) - qWarning() << component->errors(); + QDeclarativeEnginePrivate::warning(qmlEngine(q), component->errors()); delete obj; delete ctxt; source = QUrl(); @@ -325,7 +333,7 @@ void QDeclarativeLoaderPrivate::_q_sourceLoaded() } /*! - \qmlproperty enum Loader::status + \qmlproperty enumeration Loader::status This property holds the status of QML loading. It can be one of: \list @@ -383,7 +391,7 @@ qreal QDeclarativeLoader::progress() const } /*! - \qmlproperty enum Loader::resizeMode + \qmlproperty enumeration Loader::resizeMode This property determines how the Loader or item are resized: \list diff --git a/src/declarative/graphicsitems/qdeclarativeloader_p.h b/src/declarative/graphicsitems/qdeclarativeloader_p.h index 65538a8..e9fd8e9 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader_p.h +++ b/src/declarative/graphicsitems/qdeclarativeloader_p.h @@ -58,7 +58,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeLoader : public QDeclarativeItem Q_ENUMS(ResizeMode) Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) - Q_PROPERTY(QDeclarativeComponent *sourceComponent READ sourceComponent WRITE setSourceComponent NOTIFY sourceChanged) + Q_PROPERTY(QDeclarativeComponent *sourceComponent READ sourceComponent WRITE setSourceComponent RESET resetSourceComponent NOTIFY sourceChanged) Q_PROPERTY(ResizeMode resizeMode READ resizeMode WRITE setResizeMode NOTIFY resizeModeChanged) Q_PROPERTY(QGraphicsObject *item READ item NOTIFY itemChanged) Q_PROPERTY(Status status READ status NOTIFY statusChanged) @@ -73,6 +73,7 @@ public: QDeclarativeComponent *sourceComponent() const; void setSourceComponent(QDeclarativeComponent *); + void resetSourceComponent(); enum Status { Null, Ready, Loading, Error }; Status status() const; diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp index a6cc75e..126d041 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp +++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp @@ -50,7 +50,8 @@ QT_BEGIN_NAMESPACE static const int PressAndHoldDelay = 800; QDeclarativeDrag::QDeclarativeDrag(QObject *parent) -: QObject(parent), _target(0), _axis(XandYAxis), _xmin(0), _xmax(0), _ymin(0), _ymax(0) +: QObject(parent), _target(0), _axis(XandYAxis), _xmin(0), _xmax(0), _ymin(0), _ymax(0), +_active(false) { } @@ -144,6 +145,19 @@ void QDeclarativeDrag::setYmax(qreal m) emit maximumYChanged(); } +bool QDeclarativeDrag::active() const +{ + return _active; +} + +void QDeclarativeDrag::setActive(bool drag) +{ + if (_active == drag) + return; + _active = drag; + emit activeChanged(); +} + QDeclarativeMouseAreaPrivate::~QDeclarativeMouseAreaPrivate() { delete drag; @@ -389,7 +403,8 @@ void QDeclarativeMouseArea::mousePressEvent(QGraphicsSceneMouseEvent *event) d->dragX = drag()->axis() & QDeclarativeDrag::XAxis; d->dragY = drag()->axis() & QDeclarativeDrag::YAxis; } - d->dragged = false; + if (d->drag) + d->drag->setActive(false); setHovered(true); d->startScene = event->scenePos(); // we should only start timer if pressAndHold is connected to. @@ -438,7 +453,7 @@ void QDeclarativeMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event) qreal dx = qAbs(curLocalPos.x() - startLocalPos.x()); qreal dy = qAbs(curLocalPos.y() - startLocalPos.y()); if ((d->dragX && !(dx < dragThreshold)) || (d->dragY && !(dy < dragThreshold))) - d->dragged = true; + d->drag->setActive(true); if (!keepMouseGrab()) { if ((!d->dragY && dy < dragThreshold && d->dragX && dx > dragThreshold) || (!d->dragX && dx < dragThreshold && d->dragY && dy > dragThreshold) @@ -447,7 +462,7 @@ void QDeclarativeMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event) } } - if (d->dragX && d->dragged) { + if (d->dragX && d->drag->active()) { qreal x = (curLocalPos.x() - startLocalPos.x()) + d->startX; if (x < drag()->xmin()) x = drag()->xmin(); @@ -455,7 +470,7 @@ void QDeclarativeMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event) x = drag()->xmax(); drag()->target()->setX(x); } - if (d->dragY && d->dragged) { + if (d->dragY && d->drag->active()) { qreal y = (curLocalPos.y() - startLocalPos.y()) + d->startY; if (y < drag()->ymin()) y = drag()->ymin(); @@ -466,6 +481,9 @@ void QDeclarativeMouseArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event) d->moved = true; } QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress); + emit mousePositionChanged(&me); + me.setX(d->lastPos.x()); + me.setY(d->lastPos.y()); emit positionChanged(&me); } @@ -478,6 +496,8 @@ void QDeclarativeMouseArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) } else { d->saveEvent(event); setPressed(false); + if (d->drag) + d->drag->setActive(false); // If we don't accept hover, we need to reset containsMouse. if (!acceptHoverEvents()) setHovered(false); @@ -518,6 +538,9 @@ void QDeclarativeMouseArea::hoverMoveEvent(QGraphicsSceneHoverEvent *event) } else { d->lastPos = event->pos(); QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, d->lastButtons, d->lastModifiers, false, d->longPress); + emit mousePositionChanged(&me); + me.setX(d->lastPos.x()); + me.setY(d->lastPos.y()); emit positionChanged(&me); } } @@ -541,8 +564,10 @@ bool QDeclarativeMouseArea::sceneEvent(QEvent *event) // state d->pressed = false; setKeepMouseGrab(false); + QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, false); + emit released(&me); emit pressedChanged(); - //emit hoveredChanged(); + setHovered(false); } } return rv; @@ -553,7 +578,8 @@ void QDeclarativeMouseArea::timerEvent(QTimerEvent *event) Q_D(QDeclarativeMouseArea); if (event->timerId() == d->pressAndHoldTimer.timerId()) { d->pressAndHoldTimer.stop(); - if (d->pressed && d->dragged == false && d->hovered == true) { + bool dragged = d->drag && d->drag->active(); + if (d->pressed && dragged == false && d->hovered == true) { d->longPress = true; QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress); emit pressAndHold(&me); @@ -561,6 +587,18 @@ void QDeclarativeMouseArea::timerEvent(QTimerEvent *event) } } +void QDeclarativeMouseArea::geometryChanged(const QRectF &newGeometry, + const QRectF &oldGeometry) +{ + Q_D(QDeclarativeMouseArea); + QDeclarativeItem::geometryChanged(newGeometry, oldGeometry); + + if (d->lastScenePos.isNull) + d->lastScenePos = mapToScene(d->lastPos); + else if (newGeometry.x() != oldGeometry.x() || newGeometry.y() != oldGeometry.y()) + d->lastPos = mapFromScene(d->lastScenePos); +} + /*! \qmlproperty bool MouseArea::hoverEnabled This property holds whether hover events are handled. @@ -641,16 +679,21 @@ void QDeclarativeMouseArea::setAcceptedButtons(Qt::MouseButtons buttons) bool QDeclarativeMouseArea::setPressed(bool p) { Q_D(QDeclarativeMouseArea); - bool isclick = d->pressed == true && p == false && d->dragged == false && d->hovered == true; + bool dragged = d->drag && d->drag->active(); + bool isclick = d->pressed == true && p == false && dragged == false && d->hovered == true; if (d->pressed != p) { d->pressed = p; QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress); if (d->pressed) { emit pressed(&me); - emit positionChanged(&me); + me.setX(d->lastPos.x()); + me.setY(d->lastPos.y()); + emit mousePositionChanged(&me); } else { emit released(&me); + me.setX(d->lastPos.x()); + me.setY(d->lastPos.y()); if (isclick && !d->longPress) emit clicked(&me); } @@ -671,6 +714,7 @@ QDeclarativeDrag *QDeclarativeMouseArea::drag() /*! \qmlproperty Item MouseArea::drag.target + \qmlproperty bool MouseArea::drag.active \qmlproperty Axis MouseArea::drag.axis \qmlproperty real MouseArea::drag.minimumX \qmlproperty real MouseArea::drag.maximumX @@ -681,6 +725,7 @@ QDeclarativeDrag *QDeclarativeMouseArea::drag() \list \i \c target specifies the item to drag. + \i \c active specifies if the target item is being currently dragged. \i \c axis specifies whether dragging can be done horizontally (XAxis), vertically (YAxis), or both (XandYAxis) \i the minimum and maximum properties limit how far the target can be dragged along the corresponding axes. \endlist diff --git a/src/declarative/graphicsitems/qdeclarativemousearea_p.h b/src/declarative/graphicsitems/qdeclarativemousearea_p.h index 58faac1..4f7df62 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea_p.h +++ b/src/declarative/graphicsitems/qdeclarativemousearea_p.h @@ -61,6 +61,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeDrag : public QObject Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax NOTIFY maximumXChanged) Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin NOTIFY minimumYChanged) Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged) + Q_PROPERTY(bool active READ active NOTIFY activeChanged) //### consider drag and drop public: @@ -84,6 +85,9 @@ public: qreal ymax() const; void setYmax(qreal); + bool active() const; + void setActive(bool); + Q_SIGNALS: void targetChanged(); void axisChanged(); @@ -91,6 +95,7 @@ Q_SIGNALS: void maximumXChanged(); void minimumYChanged(); void maximumYChanged(); + void activeChanged(); private: QGraphicsObject *_target; @@ -99,6 +104,7 @@ private: qreal _xmax; qreal _ymin; qreal _ymax; + bool _active; Q_DISABLE_COPY(QDeclarativeDrag) }; @@ -108,8 +114,8 @@ class Q_DECLARATIVE_EXPORT QDeclarativeMouseArea : public QDeclarativeItem { Q_OBJECT - Q_PROPERTY(qreal mouseX READ mouseX NOTIFY positionChanged) - Q_PROPERTY(qreal mouseY READ mouseY NOTIFY positionChanged) + Q_PROPERTY(qreal mouseX READ mouseX NOTIFY mousePositionChanged) + Q_PROPERTY(qreal mouseY READ mouseY NOTIFY mousePositionChanged) Q_PROPERTY(bool containsMouse READ hovered NOTIFY hoveredChanged) Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) @@ -144,6 +150,7 @@ Q_SIGNALS: void enabledChanged(); void acceptedButtonsChanged(); void positionChanged(QDeclarativeMouseEvent *mouse); + void mousePositionChanged(QDeclarativeMouseEvent *mouse); void pressed(QDeclarativeMouseEvent *mouse); void pressAndHold(QDeclarativeMouseEvent *mouse); @@ -167,6 +174,9 @@ protected: bool sceneEvent(QEvent *); void timerEvent(QTimerEvent *event); + virtual void geometryChanged(const QRectF &newGeometry, + const QRectF &oldGeometry); + private: void handlePress(); void handleRelease(); diff --git a/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h b/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h index 9068c7c..4e909ff 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativemousearea_p_p.h @@ -67,7 +67,8 @@ class QDeclarativeMouseAreaPrivate : public QDeclarativeItemPrivate public: QDeclarativeMouseAreaPrivate() - : absorb(true), hovered(false), pressed(false), longPress(false), drag(0) + : absorb(true), hovered(false), pressed(false), longPress(false), + moved(false), drag(0) { } @@ -81,6 +82,7 @@ public: void saveEvent(QGraphicsSceneMouseEvent *event) { lastPos = event->pos(); + lastScenePos = event->scenePos(); lastButton = event->button(); lastButtons = event->buttons(); lastModifiers = event->modifiers(); @@ -99,12 +101,12 @@ public: bool moved : 1; bool dragX : 1; bool dragY : 1; - bool dragged : 1; QDeclarativeDrag *drag; QPointF startScene; qreal startX; qreal startY; QPointF lastPos; + QDeclarativeNullableValue<QPointF> lastScenePos; Qt::MouseButton lastButton; Qt::MouseButtons lastButtons; Qt::KeyboardModifiers lastModifiers; diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp index 4aaa28d..d0a3cd1 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview.cpp +++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp @@ -314,7 +314,7 @@ void QDeclarativePathViewPrivate::regenerate() \image pathview.gif - Note that views do not enable \e clip automatically. If the view + \bold Note that views do not enable \e clip automatically. If the view is not clipped by another item or the screen, it will be necessary to set \e {clip: true} in order to have the out of view items clipped nicely. diff --git a/src/declarative/graphicsitems/qdeclarativepositioners_p.h b/src/declarative/graphicsitems/qdeclarativepositioners_p.h index 24b65fa..b5fc979 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners_p.h +++ b/src/declarative/graphicsitems/qdeclarativepositioners_p.h @@ -136,7 +136,7 @@ private: class Q_DECLARATIVE_EXPORT QDeclarativeGrid : public QDeclarativeBasePositioner { Q_OBJECT - Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowChanged) + Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged) Q_PROPERTY(int columns READ columns WRITE setColumns NOTIFY columnsChanged) Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged) diff --git a/src/declarative/graphicsitems/qdeclarativerectangle.cpp b/src/declarative/graphicsitems/qdeclarativerectangle.cpp index 54c8ab2..0328f91 100644 --- a/src/declarative/graphicsitems/qdeclarativerectangle.cpp +++ b/src/declarative/graphicsitems/qdeclarativerectangle.cpp @@ -172,6 +172,8 @@ void QDeclarativeGradient::doUpdate() \image declarative-rect.png */ +int QDeclarativeRectanglePrivate::doUpdateSlotIdx = -1; + /*! \internal \class QDeclarativeRectangle @@ -252,11 +254,16 @@ void QDeclarativeRectangle::setGradient(QDeclarativeGradient *gradient) Q_D(QDeclarativeRectangle); if (d->gradient == gradient) return; + static int updatedSignalIdx = -1; + if (updatedSignalIdx < 0) + updatedSignalIdx = QDeclarativeGradient::staticMetaObject.indexOfSignal("updated()"); + if (d->doUpdateSlotIdx < 0) + d->doUpdateSlotIdx = QDeclarativeRectangle::staticMetaObject.indexOfSlot("doUpdate()"); if (d->gradient) - disconnect(d->gradient, SIGNAL(updated()), this, SLOT(doUpdate())); + QMetaObject::disconnect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx); d->gradient = gradient; if (d->gradient) - connect(d->gradient, SIGNAL(updated()), this, SLOT(doUpdate())); + QMetaObject::connect(d->gradient, updatedSignalIdx, this, d->doUpdateSlotIdx); update(); } diff --git a/src/declarative/graphicsitems/qdeclarativerectangle_p_p.h b/src/declarative/graphicsitems/qdeclarativerectangle_p_p.h index 84418bc..001b018 100644 --- a/src/declarative/graphicsitems/qdeclarativerectangle_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativerectangle_p_p.h @@ -81,12 +81,18 @@ public: qreal radius; qreal paintmargin; QPixmap rectImage; + static int doUpdateSlotIdx; QDeclarativePen *getPen() { if (!pen) { Q_Q(QDeclarativeRectangle); pen = new QDeclarativePen; - QObject::connect(pen, SIGNAL(penChanged()), q, SLOT(doUpdate())); + static int penChangedSignalIdx = -1; + if (penChangedSignalIdx < 0) + penChangedSignalIdx = QDeclarativePen::staticMetaObject.indexOfSignal("penChanged()"); + if (doUpdateSlotIdx < 0) + doUpdateSlotIdx = QDeclarativeRectangle::staticMetaObject.indexOfSlot("doUpdate()"); + QMetaObject::connect(pen, penChangedSignalIdx, q, doUpdateSlotIdx); } return pen; } diff --git a/src/declarative/graphicsitems/qdeclarativescalegrid.cpp b/src/declarative/graphicsitems/qdeclarativescalegrid.cpp index e68f645..fe89190 100644 --- a/src/declarative/graphicsitems/qdeclarativescalegrid.cpp +++ b/src/declarative/graphicsitems/qdeclarativescalegrid.cpp @@ -175,7 +175,7 @@ QDeclarativeBorderImage::TileMode QDeclarativeGridScaledImage::stringToRule(cons if (s == QLatin1String("Round")) return QDeclarativeBorderImage::Round; - qWarning() << "Unknown tile rule specified. Using Stretch"; + qWarning("QDeclarativeGridScaledImage: Invalid tile rule specified. Using Stretch."); return QDeclarativeBorderImage::Stretch; } diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index a95c930..0b59503 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -525,18 +525,6 @@ void QDeclarativeText::setWrapMode(WrapMode mode) emit wrapModeChanged(); } -bool QDeclarativeText::wrap() const -{ - Q_D(const QDeclarativeText); - return d->wrapMode != NoWrap; -} - -void QDeclarativeText::setWrap(bool w) -{ - qmlInfo(this) << "\"wrap\" property is deprecated and will soon be removed. Use wrapMode"; - setWrapMode(w ? WordWrap : NoWrap); -} - /*! \qmlproperty enumeration Text::textFormat diff --git a/src/declarative/graphicsitems/qdeclarativetext_p.h b/src/declarative/graphicsitems/qdeclarativetext_p.h index 4fd5e3a..00ce126 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p.h @@ -69,7 +69,6 @@ class Q_DECLARATIVE_EXPORT QDeclarativeText : public QDeclarativeItem Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged) Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged) Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged) - Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapModeChanged) Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged) Q_PROPERTY(TextElideMode elide READ elideMode WRITE setElideMode NOTIFY elideModeChanged) //### elideMode? @@ -123,8 +122,6 @@ public: VAlignment vAlign() const; void setVAlign(VAlignment align); - bool wrap() const; - void setWrap(bool w); WrapMode wrapMode() const; void setWrapMode(WrapMode w); diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 1fec484..25eaef6 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -495,19 +495,6 @@ void QDeclarativeTextEdit::setWrapMode(WrapMode mode) emit wrapModeChanged(); } -bool QDeclarativeTextEdit::wrap() const -{ - Q_D(const QDeclarativeTextEdit); - return d->wrapMode != QDeclarativeTextEdit::NoWrap; -} - -void QDeclarativeTextEdit::setWrap(bool w) -{ - - qmlInfo(this) << "\"wrap\" property is deprecated and will soon be removed. Use wrapMode"; - setWrapMode(w ? WordWrap : NoWrap); -} - /*! \qmlproperty bool TextEdit::cursorVisible If true the text edit shows a cursor. @@ -614,7 +601,7 @@ void QDeclarativeTextEdit::loadCursorDelegate() d->cursor->setHeight(QFontMetrics(d->font).height()); moveCursorDelegate(); }else{ - qWarning() << QLatin1String("Error loading cursor delegate for TextEdit:") + objectName(); + qmlInfo(this) << "Error loading cursor delegate."; } } @@ -1076,8 +1063,6 @@ void QDeclarativeTextEditPrivate::updateSelection() q->selectionEndChanged(); startChange = (lastSelectionStart != control->textCursor().selectionStart()); endChange = (lastSelectionEnd != control->textCursor().selectionEnd()); - if(startChange || endChange) - qWarning() << "QDeclarativeTextEditPrivate::updateSelection() has failed you."; } void QDeclarativeTextEdit::updateSelectionMarkers() diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index 605b620..474de09 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -73,7 +73,6 @@ class Q_DECLARATIVE_EXPORT QDeclarativeTextEdit : public QDeclarativePaintedItem Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged) Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged) - Q_PROPERTY(bool wrap READ wrap WRITE setWrap NOTIFY wrapChanged) //### deprecated Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged) Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged) Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly NOTIFY readOnlyChanged) @@ -139,8 +138,6 @@ public: VAlignment vAlign() const; void setVAlign(VAlignment align); - bool wrap() const; - void setWrap(bool w); WrapMode wrapMode() const; void setWrapMode(WrapMode w); diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index e00d333..2161e23 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -779,9 +779,8 @@ void QDeclarativeTextInputPrivate::startCreatingCursor() }else if(cursorComponent->isLoading()){ q->connect(cursorComponent, SIGNAL(statusChanged(int)), q, SLOT(createCursor())); - }else{//isError - qmlInfo(q) << QDeclarativeTextInput::tr("Could not load cursor delegate"); - qWarning() << cursorComponent->errors(); + }else {//isError + qmlInfo(q, cursorComponent->errors()) << QDeclarativeTextInput::tr("Could not load cursor delegate"); } } @@ -789,8 +788,7 @@ void QDeclarativeTextInput::createCursor() { Q_D(QDeclarativeTextInput); if(d->cursorComponent->isError()){ - qmlInfo(this) << tr("Could not load cursor delegate"); - qWarning() << d->cursorComponent->errors(); + qmlInfo(this, d->cursorComponent->errors()) << tr("Could not load cursor delegate"); return; } @@ -801,8 +799,7 @@ void QDeclarativeTextInput::createCursor() delete d->cursorItem; d->cursorItem = qobject_cast<QDeclarativeItem*>(d->cursorComponent->create()); if(!d->cursorItem){ - qmlInfo(this) << tr("Could not instantiate cursor delegate"); - //The failed instantiation should print its own error messages + qmlInfo(this, d->cursorComponent->errors()) << tr("Could not instantiate cursor delegate"); return; } diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp index 751284d..e2d8bc7 100644 --- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp +++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp @@ -198,7 +198,7 @@ QVariant QDeclarativeVisualItemModel::evaluate(int index, const QString &express QDeclarativeContext *ctxt = new QDeclarativeContext(ccontext); ctxt->setContextObject(d->children.at(index)); QDeclarativeExpression e(ctxt, expression, objectContext); - QVariant value = e.value(); + QVariant value = e.evaluate(); delete ctxt; return value; } @@ -262,6 +262,7 @@ public: } if (m_roles.count() == 1) m_roleNames.insert("modelData", m_roles.at(0)); + m_roleNames.insert("hasModelChildren", 0); } else if (m_listAccessor) { m_roleNames.insert("modelData", 0); if (m_listAccessor->type() == QDeclarativeListAccessor::Instance) { @@ -473,11 +474,16 @@ QVariant QDeclarativeVisualDataModelDataMetaObject::initialValue(int propId) } } else if (model->m_abstractItemModel) { model->ensureRoles(); - QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName); - if (it != model->m_roleNames.end()) { - roleToProp.insert(*it, propId); + if (propName == "hasModelChildren") { QModelIndex index = model->m_abstractItemModel->index(data->m_index, 0, model->m_root); - return model->m_abstractItemModel->data(index, *it); + return model->m_abstractItemModel->hasChildren(index); + } else { + QHash<QByteArray,int>::const_iterator it = model->m_roleNames.find(propName); + if (it != model->m_roleNames.end()) { + roleToProp.insert(*it, propId); + QModelIndex index = model->m_abstractItemModel->index(data->m_index, 0, model->m_root); + return model->m_abstractItemModel->data(index, *it); + } } } Q_ASSERT(!"Can never be reached"); @@ -784,34 +790,13 @@ void QDeclarativeVisualDataModel::setDelegate(QDeclarativeComponent *delegate) \qmlproperty QModelIndex VisualDataModel::rootIndex QAbstractItemModel provides a heirachical tree of data, whereas - QML only operates on list data. rootIndex allows the children of + QML only operates on list data. \c rootIndex allows the children of any node in a QAbstractItemModel to be provided by this model. This property only affects models of type QAbstractItemModel. \code // main.cpp - Q_DECLARE_METATYPE(QModelIndex) - - class MyModel : public QDirModel - { - Q_OBJECT - public: - MyModel(QDeclarativeContext *ctxt) : QDirModel(), context(ctxt) { - QHash<int,QByteArray> roles = roleNames(); - roles.insert(FilePathRole, "path"); - setRoleNames(roles); - context->setContextProperty("myModel", this); - context->setContextProperty("myRoot", QVariant::fromValue(index(0,0,QModelIndex()))); - } - - Q_INVOKABLE void setRoot(const QString &path) { - QModelIndex root = index(path); - context->setContextProperty("myRoot", QVariant::fromValue(root)); - } - - QDeclarativeContext *context; - }; int main(int argc, char ** argv) { @@ -819,7 +804,8 @@ void QDeclarativeVisualDataModel::setDelegate(QDeclarativeComponent *delegate) QDeclarativeView view; - MyModel model(view.rootContext()); + QDirModel model; + view.rootContext()->setContextProperty("myModel", &model); view.setSource(QUrl("qrc:view.qml")); view.show(); @@ -835,18 +821,18 @@ void QDeclarativeVisualDataModel::setDelegate(QDeclarativeComponent *delegate) import Qt 4.7 ListView { + id: view width: 200 height: 200 model: VisualDataModel { model: myModel - rootIndex: myRoot delegate: Component { Rectangle { - height: 25; width: 100 - Text { text: path } + height: 25; width: 200 + Text { text: filePath } MouseArea { anchors.fill: parent; - onClicked: myModel.setRoot(path) + onClicked: if (hasModelChildren) view.model.rootIndex = view.model.modelIndex(index) } } } @@ -854,19 +840,21 @@ void QDeclarativeVisualDataModel::setDelegate(QDeclarativeComponent *delegate) } \endcode + \sa modelIndex(), parentModelIndex() */ -QModelIndex QDeclarativeVisualDataModel::rootIndex() const +QVariant QDeclarativeVisualDataModel::rootIndex() const { Q_D(const QDeclarativeVisualDataModel); - return d->m_root; + return QVariant::fromValue(d->m_root); } -void QDeclarativeVisualDataModel::setRootIndex(const QModelIndex &root) +void QDeclarativeVisualDataModel::setRootIndex(const QVariant &root) { Q_D(QDeclarativeVisualDataModel); - if (d->m_root != root) { + QModelIndex modelIndex = qvariant_cast<QModelIndex>(root); + if (d->m_root != modelIndex) { int oldCount = d->modelCount(); - d->m_root = root; + d->m_root = modelIndex; int newCount = d->modelCount(); if (d->m_delegate && oldCount) emit itemsRemoved(0, oldCount); @@ -878,6 +866,47 @@ void QDeclarativeVisualDataModel::setRootIndex(const QModelIndex &root) } } + +/*! + \qmlmethod QModelIndex VisualDataModel::modelIndex(int index) + + QAbstractItemModel provides a heirachical tree of data, whereas + QML only operates on list data. This function assists in using + tree models in QML. + + Returns a QModelIndex for the specified index. + This value can be assigned to rootIndex. + + \sa rootIndex +*/ +QVariant QDeclarativeVisualDataModel::modelIndex(int idx) const +{ + Q_D(const QDeclarativeVisualDataModel); + if (d->m_abstractItemModel) + return QVariant::fromValue(d->m_abstractItemModel->index(idx, 0, d->m_root)); + return QVariant::fromValue(QModelIndex()); +} + +/*! + \qmlmethod QModelIndex VisualDataModel::parentModelIndex() + + QAbstractItemModel provides a heirachical tree of data, whereas + QML only operates on list data. This function assists in using + tree models in QML. + + Returns a QModelIndex for the parent of the current rootIndex. + This value can be assigned to rootIndex. + + \sa rootIndex +*/ +QVariant QDeclarativeVisualDataModel::parentModelIndex() const +{ + Q_D(const QDeclarativeVisualDataModel); + if (d->m_abstractItemModel) + return QVariant::fromValue(d->m_abstractItemModel->parent(d->m_root)); + return QVariant::fromValue(QModelIndex()); +} + QString QDeclarativeVisualDataModel::part() const { Q_D(const QDeclarativeVisualDataModel); @@ -1011,7 +1040,7 @@ QDeclarativeItem *QDeclarativeVisualDataModel::item(int index, const QByteArray } else { delete data; delete ctxt; - qWarning() << d->m_delegate->errors(); + qmlInfo(this, d->m_delegate->errors()) << "Error creating delgate"; } } QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(nobj); @@ -1109,7 +1138,7 @@ QVariant QDeclarativeVisualDataModel::evaluate(int index, const QString &express QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(nobj); if (item) { QDeclarativeExpression e(qmlContext(item), expression, objectContext); - value = e.value(); + value = e.evaluate(); } } else { QDeclarativeContext *ccontext = d->m_context; @@ -1118,7 +1147,7 @@ QVariant QDeclarativeVisualDataModel::evaluate(int index, const QString &express QDeclarativeVisualDataModelData *data = new QDeclarativeVisualDataModelData(index, this); ctxt->setContextObject(data); QDeclarativeExpression e(ctxt, expression, objectContext); - value = e.value(); + value = e.evaluate(); delete data; delete ctxt; } diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h b/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h index d34bcaf..0a9173f 100644 --- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h +++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel_p.h @@ -150,7 +150,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeVisualDataModel : public QDeclarativeVisu Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate) Q_PROPERTY(QString part READ part WRITE setPart) Q_PROPERTY(QObject *parts READ parts CONSTANT) - Q_PROPERTY(QModelIndex rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged) + Q_PROPERTY(QVariant rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged) Q_CLASSINFO("DefaultProperty", "delegate") public: QDeclarativeVisualDataModel(); @@ -163,8 +163,11 @@ public: QDeclarativeComponent *delegate() const; void setDelegate(QDeclarativeComponent *); - QModelIndex rootIndex() const; - void setRootIndex(const QModelIndex &root); + QVariant rootIndex() const; + void setRootIndex(const QVariant &root); + + Q_INVOKABLE QVariant modelIndex(int idx) const; + Q_INVOKABLE QVariant parentModelIndex() const; QString part() const; void setPart(const QString &); diff --git a/src/declarative/qml/parser/qdeclarativejs.g b/src/declarative/qml/parser/qdeclarativejs.g index ba9338e..1b66ba0 100644 --- a/src/declarative/qml/parser/qdeclarativejs.g +++ b/src/declarative/qml/parser/qdeclarativejs.g @@ -1376,7 +1376,7 @@ case $rule_number: { } break; ./ -PropertyName: T_IDENTIFIER %prec REDUCE_HERE ; +PropertyName: T_IDENTIFIER %prec SHIFT_THERE ; /. case $rule_number: { AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); diff --git a/src/declarative/qml/parser/qdeclarativejsgrammar.cpp b/src/declarative/qml/parser/qdeclarativejsgrammar.cpp index 52e979a..b87d8f4 100644 --- a/src/declarative/qml/parser/qdeclarativejsgrammar.cpp +++ b/src/declarative/qml/parser/qdeclarativejsgrammar.cpp @@ -40,7 +40,7 @@ ****************************************************************************/ // This file was generated by qlalr - DO NOT EDIT! -#include "private/qdeclarativejsgrammar_p.h" +#include "qdeclarativejsgrammar_p.h" QT_BEGIN_NAMESPACE @@ -346,9 +346,9 @@ const short QDeclarativeJSGrammar::action_index [] = { const short QDeclarativeJSGrammar::action_info [] = { 399, 352, 345, -101, 343, 457, 440, 403, 257, -112, - -125, -131, -123, -98, -120, 348, -128, 389, 453, 391, + -125, -131, -123, 346, -120, 348, -128, 389, 453, 391, 416, 401, 408, 563, -101, -123, 416, -120, 539, -131, - -98, -112, -125, 348, 257, 99, 71, 645, 621, 101, + 346, -112, -125, 348, 257, 99, 71, 645, 621, 101, -128, 440, 141, 621, 164, 431, 539, 430, 453, 573, 457, 444, 440, 424, 71, 424, 101, 446, 559, 420, 424, 448, 539, 440, 570, 539, 466, 527, 312, 346, diff --git a/src/declarative/qml/parser/qdeclarativejslexer.cpp b/src/declarative/qml/parser/qdeclarativejslexer.cpp index 3a0e897..975ad4c 100644 --- a/src/declarative/qml/parser/qdeclarativejslexer.cpp +++ b/src/declarative/qml/parser/qdeclarativejslexer.cpp @@ -484,6 +484,8 @@ int Lexer::lex() stackToken = -1; } + bool identifierWithEscapedUnicode = false; + while (!done) { switch (state) { case Start: @@ -523,7 +525,26 @@ int Lexer::lex() state = InString; multiLineString = false; stringType = current; + } else if (current == '\\' && next1 == 'u') { + identifierWithEscapedUnicode = true; + recordStartPos(); + + shift(2); // skip the unicode escape prefix `\u' + + if (isHexDigit(current) && isHexDigit(next1) && + isHexDigit(next2) && isHexDigit(next3)) { + record16(convertUnicode(current, next1, next2, next3)); + shift(3); + state = InIdentifier; + } else { + setDone(Bad); + err = IllegalUnicodeEscapeSequence; + errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal unicode escape sequence"); + break; + } + } else if (isIdentLetter(current)) { + identifierWithEscapedUnicode = false; recordStartPos(); record16(current); state = InIdentifier; @@ -683,6 +704,21 @@ int Lexer::lex() if (isIdentLetter(current) || isDecimalDigit(current)) { record16(current); break; + } else if (current == '\\' && next1 == 'u') { + identifierWithEscapedUnicode = true; + shift(2); // skip the unicode escape prefix `\u' + + if (isHexDigit(current) && isHexDigit(next1) && + isHexDigit(next2) && isHexDigit(next3)) { + record16(convertUnicode(current, next1, next2, next3)); + shift(3); + break; + } else { + setDone(Bad); + err = IllegalUnicodeEscapeSequence; + errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal unicode escape sequence"); + break; + } } setDone(Identifier); break; @@ -825,7 +861,11 @@ int Lexer::lex() delimited = true; return token; case Identifier: - if ((token = findReservedWord(buffer16, pos16)) < 0) { + token = -1; + if (! identifierWithEscapedUnicode) + token = findReservedWord(buffer16, pos16); + + if (token < 0) { /* TODO: close leak on parse error. same holds true for String */ if (driver) qsyylval.ustr = driver->intern(buffer16, pos16); @@ -1104,47 +1144,97 @@ void Lexer::recordStartPos() bool Lexer::scanRegExp(RegExpBodyPrefix prefix) { pos16 = 0; - bool lastWasEscape = false; + pattern = 0; if (prefix == EqualPrefix) record16(QLatin1Char('=')); - while (1) { - if (isLineTerminator() || current == 0) { + while (true) { + switch (current) { + + case 0: // eof + case '\n': case '\r': // line terminator errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression literal"); return false; - } - else if (current != '/' || lastWasEscape == true) - { - record16(current); - lastWasEscape = !lastWasEscape && (current == '\\'); - } - else { - if (driver) + + case '/': + shift(1); + + if (driver) // create the pattern pattern = driver->intern(buffer16, pos16); - else - pattern = 0; + + // scan the flags pos16 = 0; + flags = 0; + while (isIdentLetter(current)) { + int flag = Ecma::RegExp::flagFromChar(current); + if (flag == 0) { + errmsg = QCoreApplication::translate("QDeclarativeParser", "Invalid regular expression flag '%0'") + .arg(QChar(current)); + return false; + } + flags |= flag; + record16(current); + shift(1); + } + return true; + + case '\\': + // regular expression backslash sequence + record16(current); + shift(1); + + if (! current || isLineTerminator()) { + errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression backslash sequence"); + return false; + } + + record16(current); shift(1); break; - } - shift(1); - } - flags = 0; - while (isIdentLetter(current)) { - int flag = Ecma::RegExp::flagFromChar(current); - if (flag == 0) { - errmsg = QCoreApplication::translate("QDeclarativeParser", "Invalid regular expression flag '%0'") - .arg(QChar(current)); - return false; - } - flags |= flag; - record16(current); - shift(1); - } + case '[': + // regular expression class + record16(current); + shift(1); + + while (current && ! isLineTerminator()) { + if (current == ']') + break; + else if (current == '\\') { + // regular expression backslash sequence + record16(current); + shift(1); + + if (! current || isLineTerminator()) { + errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression backslash sequence"); + return false; + } + + record16(current); + shift(1); + } else { + record16(current); + shift(1); + } + } + + if (current != ']') { + errmsg = QCoreApplication::translate("QDeclarativeParser", "Unterminated regular expression class"); + return false; + } + + record16(current); + shift(1); // skip ] + break; + + default: + record16(current); + shift(1); + } // switch + } // while - return true; + return false; } void Lexer::syncProhibitAutomaticSemicolon() diff --git a/src/declarative/qml/qdeclarative.h b/src/declarative/qml/qdeclarative.h index 6e36d4f..d75f0a8 100644 --- a/src/declarative/qml/qdeclarative.h +++ b/src/declarative/qml/qdeclarative.h @@ -100,6 +100,7 @@ int qmlRegisterType() qRegisterMetaType<T *>(pointerName.constData()), qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), 0, 0, + QString(), 0, 0, 0, 0, &T::staticMetaObject, @@ -118,8 +119,10 @@ int qmlRegisterType() return QDeclarativePrivate::registerType(type); } +int qmlRegisterTypeNotAvailable(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& message); + template<typename T> -int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) +int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& reason) { QByteArray name(T::staticMetaObject.className()); @@ -132,6 +135,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin qRegisterMetaType<T *>(pointerName.constData()), qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), 0, 0, + reason, uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, @@ -164,6 +168,7 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c qRegisterMetaType<T *>(pointerName.constData()), qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), sizeof(T), QDeclarativePrivate::createInto<T>, + QString(), uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, @@ -196,6 +201,7 @@ int qmlRegisterExtendedType() qRegisterMetaType<T *>(pointerName.constData()), qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), 0, 0, + QString(), 0, 0, 0, 0, &T::staticMetaObject, @@ -236,6 +242,7 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, qRegisterMetaType<T *>(pointerName.constData()), qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), sizeof(T), QDeclarativePrivate::createInto<T>, + QString(), uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, @@ -276,9 +283,9 @@ int qmlRegisterInterface(const char *typeName) template<typename T> int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, - const char *qmlName, const char *typeName, QDeclarativeCustomParser *parser) + const char *qmlName, QDeclarativeCustomParser *parser) { - QByteArray name(typeName); + QByteArray name(T::staticMetaObject.className()); QByteArray pointerName(name + '*'); QByteArray listName("QDeclarativeListProperty<" + name + ">"); @@ -289,6 +296,7 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, qRegisterMetaType<T *>(pointerName.constData()), qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), sizeof(T), QDeclarativePrivate::createInto<T>, + QString(), uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index 25492ac..d44e7fb 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -156,6 +156,9 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) QScriptValue scriptValue = d->scriptValue(0, &isUndefined); if (data->property.propertyTypeCategory() == QDeclarativeProperty::List) { value = ep->scriptValueToVariant(scriptValue, qMetaTypeId<QList<QObject *> >()); + } else if (scriptValue.isNull() && + data->property.propertyTypeCategory() == QDeclarativeProperty::Object) { + value = QVariant::fromValue((QObject *)0); } else { value = ep->scriptValueToVariant(scriptValue, data->property.propertyType()); if (value.userType() == QMetaType::QObjectStar && !qvariant_cast<QObject*>(value)) { @@ -168,6 +171,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) } } + if (data->error.isValid()) { } else if (isUndefined && data->property.isResettable()) { @@ -210,8 +214,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) } if (data->error.isValid()) { - if (!data->addError(ep)) - qWarning().nospace() << qPrintable(this->error().toString()); + if (!data->addError(ep)) ep->warning(this->error()); } else { data->removeError(); } @@ -358,8 +361,10 @@ void QDeclarativeAbstractBinding::removeFromObject() void QDeclarativeAbstractBinding::clear() { - if (m_mePtr) + if (m_mePtr) { *m_mePtr = 0; + m_mePtr = 0; + } } QString QDeclarativeAbstractBinding::expression() const diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp index 8c7a977..89f1256 100644 --- a/src/declarative/qml/qdeclarativeboundsignal.cpp +++ b/src/declarative/qml/qdeclarativeboundsignal.cpp @@ -95,10 +95,8 @@ QDeclarativeAbstractBoundSignal::~QDeclarativeAbstractBoundSignal() QDeclarativeBoundSignal::QDeclarativeBoundSignal(QObject *scope, const QMetaMethod &signal, QObject *parent) -: m_expression(0), m_signal(signal), m_paramsValid(false), m_params(0) +: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0) { - // A cached evaluation of the QDeclarativeExpression::value() slot index. - // // This is thread safe. Although it may be updated by two threads, they // will both set it to the same value - so the worst thing that can happen // is that they both do the work to figure it out. Boo hoo. @@ -111,10 +109,8 @@ QDeclarativeBoundSignal::QDeclarativeBoundSignal(QObject *scope, const QMetaMeth QDeclarativeBoundSignal::QDeclarativeBoundSignal(QDeclarativeContext *ctxt, const QString &val, QObject *scope, const QMetaMethod &signal, QObject *parent) -: m_expression(0), m_signal(signal), m_paramsValid(false), m_params(0) +: m_expression(0), m_signal(signal), m_paramsValid(false), m_isEvaluating(false), m_params(0) { - // A cached evaluation of the QDeclarativeExpression::value() slot index. - // // This is thread safe. Although it may be updated by two threads, they // will both set it to the same value - so the worst thing that can happen // is that they both do the work to figure it out. Boo hoo. @@ -169,6 +165,7 @@ QDeclarativeBoundSignal *QDeclarativeBoundSignal::cast(QObject *o) int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) { if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) { + m_isEvaluating = true; if (!m_paramsValid) { if (!m_signal.parameterTypes().isEmpty()) m_params = new QDeclarativeBoundSignalParameters(m_signal, this); @@ -179,9 +176,10 @@ int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) if (m_expression && m_expression->engine()) { QDeclarativeExpressionPrivate::get(m_expression)->value(m_params); if (m_expression && m_expression->hasError()) - qWarning().nospace() << qPrintable(m_expression->error().toString()); + QDeclarativeEnginePrivate::warning(m_expression->engine(), m_expression->error()); } if (m_params) m_params->clearValues(); + m_isEvaluating = false; return -1; } else { return QObject::qt_metacall(c, id, a); diff --git a/src/declarative/qml/qdeclarativeboundsignal_p.h b/src/declarative/qml/qdeclarativeboundsignal_p.h index bba4eec..06900d7 100644 --- a/src/declarative/qml/qdeclarativeboundsignal_p.h +++ b/src/declarative/qml/qdeclarativeboundsignal_p.h @@ -83,6 +83,8 @@ public: QDeclarativeExpression *expression() const; QDeclarativeExpression *setExpression(QDeclarativeExpression *); + bool isEvaluating() const { return m_isEvaluating; } + static QDeclarativeBoundSignal *cast(QObject *); protected: @@ -91,7 +93,8 @@ protected: private: QDeclarativeExpression *m_expression; QMetaMethod m_signal; - bool m_paramsValid; + bool m_paramsValid : 1; + bool m_isEvaluating : 1; QDeclarativeBoundSignalParameters *m_params; }; diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp index 6fdf706..6596aba 100644 --- a/src/declarative/qml/qdeclarativecompiledbindings.cpp +++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp @@ -888,13 +888,6 @@ void QDeclarativeCompiledBindingsPrivate::findgeneric(Register *output, return; } - for (int ii = 0; ii < context->scripts.count(); ++ii) { - QScriptValue function = QScriptDeclarativeClass::function(context->scripts.at(ii), name); - if (function.isValid()) { - qFatal("Binding optimizer resolved name to QScript method"); - } - } - if (QObject *root = context->contextObject) { if (findproperty(root, output, enginePriv, subIdx, name, isTerminal)) @@ -938,7 +931,7 @@ static void throwException(int id, QDeclarativeDelayedError *error, error->error.setColumn(-1); } if (!context->engine || !error->addError(QDeclarativeEnginePrivate::get(context->engine))) - qWarning() << error->error; + QDeclarativeEnginePrivate::warning(context->engine, error->error); } static void dumpInstruction(const Instr *instr) diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 065009a..1727687 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -571,8 +571,12 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, QDeclarativeScriptParser::TypeReference *parserRef = unit->data.referencedTypes().at(ii); if (tref.type) { ref.type = tref.type; - if (!ref.type->isCreatable()) - COMPILE_EXCEPTION(parserRef->refObjects.first(), tr( "Element is not creatable.")); + if (!ref.type->isCreatable()) { + QString err = ref.type->noCreationReason(); + if (err.isEmpty()) + err = tr( "Element is not creatable."); + COMPILE_EXCEPTION(parserRef->refObjects.first(), err); + } } else if (tref.unit) { ref.component = tref.unit->toComponent(engine); @@ -733,10 +737,6 @@ bool QDeclarativeCompiler::buildObject(Object *obj, const BindingContext &ctxt) return true; } - // Build any script blocks for this type - for (int ii = 0; ii < obj->scriptBlockObjects.count(); ++ii) - COMPILE_CHECK(buildScript(obj, obj->scriptBlockObjects.at(ii))); - // Object instantiations reset the binding context BindingContext objCtxt(obj); @@ -868,12 +868,14 @@ bool QDeclarativeCompiler::buildObject(Object *obj, const BindingContext &ctxt) defaultProperty->release(); // Compile custom parser parts - if (isCustomParser && !customProps.isEmpty()) { + if (isCustomParser/* && !customProps.isEmpty()*/) { QDeclarativeCustomParser *cp = output->types.at(obj->type).type->customParser(); cp->clearErrors(); cp->compiler = this; + cp->object = obj; obj->custom = cp->compile(customProps); cp->compiler = 0; + cp->object = 0; foreach (QDeclarativeError err, cp->errors()) { err.setUrl(output->url); exceptions << err; @@ -961,17 +963,6 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) output->bytecode << id; } - // Set any script blocks - for (int ii = 0; ii < obj->scripts.count(); ++ii) { - QDeclarativeInstruction script; - script.type = QDeclarativeInstruction::StoreScript; - script.line = 0; // ### - int idx = output->scripts.count(); - output->scripts << obj->scripts.at(ii); - script.storeScript.value = idx; - output->bytecode << script; - } - // Begin the class if (obj->parserStatusCast != -1) { QDeclarativeInstruction begin; @@ -1177,9 +1168,6 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj, (obj->properties.count() == 1 && obj->properties.begin().key() != "id")) COMPILE_EXCEPTION(*obj->properties.begin(), tr("Component elements may not contain properties other than id")); - if (!obj->scriptBlockObjects.isEmpty()) - COMPILE_EXCEPTION(obj->scriptBlockObjects.first(), tr("Component elements may not contain script blocks")); - if (obj->properties.count()) idProp = *obj->properties.begin(); @@ -1203,6 +1191,13 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj, (obj->defaultProperty->values.count() == 1 && !obj->defaultProperty->values.first()->object))) COMPILE_EXCEPTION(obj, tr("Invalid component body specification")); + if (!obj->dynamicProperties.isEmpty()) + COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new properties.")); + if (!obj->dynamicSignals.isEmpty()) + COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new signals.")); + if (!obj->dynamicSlots.isEmpty()) + COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new functions.")); + Object *root = 0; if (obj->defaultProperty && obj->defaultProperty->values.count()) root = obj->defaultProperty->values.first()->object; @@ -1216,94 +1211,6 @@ bool QDeclarativeCompiler::buildComponent(QDeclarativeParser::Object *obj, return true; } -bool QDeclarativeCompiler::buildScript(QDeclarativeParser::Object *obj, QDeclarativeParser::Object *script) -{ - qWarning().nospace() << qPrintable(output->url.toString()) << ":" << obj->location.start.line << ":" << obj->location.start.column << ": Script blocks have been deprecated. Support will be removed entirely shortly."; - - Object::ScriptBlock scriptBlock; - - if (script->properties.count() == 1 && - script->properties.begin().key() == QByteArray("source")) { - - Property *source = *script->properties.begin(); - if (script->defaultProperty) - COMPILE_EXCEPTION(source, tr("Invalid Script block. Specify either the source property or inline script")); - - if (source->value || source->values.count() != 1 || - source->values.at(0)->object || !source->values.at(0)->value.isStringList()) - COMPILE_EXCEPTION(source, tr("Invalid Script source value")); - - QStringList sources = source->values.at(0)->value.asStringList(); - - for (int jj = 0; jj < sources.count(); ++jj) { - QString sourceUrl = output->url.resolved(QUrl(sources.at(jj))).toString(); - QString scriptCode; - int lineNumber = 1; - - for (int ii = 0; ii < unit->resources.count(); ++ii) { - if (unit->resources.at(ii)->url == sourceUrl) { - scriptCode = QString::fromUtf8(unit->resources.at(ii)->data); - break; - } - } - - if (!scriptCode.isEmpty()) { - scriptBlock.codes.append(scriptCode); - scriptBlock.files.append(sourceUrl); - scriptBlock.lineNumbers.append(lineNumber); - scriptBlock.pragmas.append(Object::ScriptBlock::None); - } - } - - } else if (!script->properties.isEmpty()) { - COMPILE_EXCEPTION(*script->properties.begin(), tr("Properties cannot be set on Script block")); - } else if (script->defaultProperty) { - - QString scriptCode; - int lineNumber = 1; - QString sourceUrl = output->url.toString(); - - QDeclarativeParser::Location currentLocation; - - for (int ii = 0; ii < script->defaultProperty->values.count(); ++ii) { - Value *v = script->defaultProperty->values.at(ii); - if (lineNumber == 1) - lineNumber = v->location.start.line; - if (v->object || !v->value.isString()) - COMPILE_EXCEPTION(v, tr("Invalid Script block")); - - if (ii == 0) { - currentLocation = v->location.start; - scriptCode.append(QString(currentLocation.column, QLatin1Char(' '))); - } - - while (currentLocation.line < v->location.start.line) { - scriptCode.append(QLatin1Char('\n')); - currentLocation.line++; - currentLocation.column = 0; - } - - scriptCode.append(QString(v->location.start.column - currentLocation.column, QLatin1Char(' '))); - - scriptCode += v->value.asString(); - currentLocation = v->location.end; - currentLocation.column++; - } - - if (!scriptCode.isEmpty()) { - scriptBlock.codes.append(scriptCode); - scriptBlock.files.append(sourceUrl); - scriptBlock.lineNumbers.append(lineNumber); - scriptBlock.pragmas.append(Object::ScriptBlock::None); - } - } - - if (!scriptBlock.codes.isEmpty()) - obj->scripts << scriptBlock; - - return true; -} - bool QDeclarativeCompiler::buildComponentFromRoot(QDeclarativeParser::Object *obj, const BindingContext &ctxt) { @@ -1351,7 +1258,7 @@ bool QDeclarativeCompiler::buildSubObject(Object *obj, const BindingContext &ctx int QDeclarativeCompiler::componentTypeRef() { - QDeclarativeType *t = QDeclarativeMetaType::qmlType("Qt/Component",4,6); + QDeclarativeType *t = QDeclarativeMetaType::qmlType("Qt/Component",4,7); for (int ii = output->types.count() - 1; ii >= 0; --ii) { if (output->types.at(ii).type == t) return ii; @@ -2902,25 +2809,6 @@ bool QDeclarativeCompiler::canCoerce(int to, QDeclarativeParser::Object *from) return false; } -/*! - Returns true if from can be assigned to a (QObject) property of type - to. -*/ -bool QDeclarativeCompiler::canCoerce(int to, int from) -{ - const QMetaObject *toMo = - QDeclarativeEnginePrivate::get(engine)->rawMetaObjectForType(to); - const QMetaObject *fromMo = - QDeclarativeEnginePrivate::get(engine)->rawMetaObjectForType(from); - - while (fromMo) { - if (QDeclarativePropertyPrivate::equal(fromMo, toMo)) - return true; - fromMo = fromMo->superClass(); - } - return false; -} - QDeclarativeType *QDeclarativeCompiler::toQmlType(QDeclarativeParser::Object *from) { // ### Optimize diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index 867db2c..fefab7a 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -186,7 +186,6 @@ private: bool buildObject(QDeclarativeParser::Object *obj, const BindingContext &); - bool buildScript(QDeclarativeParser::Object *obj, QDeclarativeParser::Object *script); bool buildComponent(QDeclarativeParser::Object *obj, const BindingContext &); bool buildSubObject(QDeclarativeParser::Object *obj, const BindingContext &); bool buildSignal(QDeclarativeParser::Property *prop, QDeclarativeParser::Object *obj, @@ -275,7 +274,6 @@ private: static QDeclarativeType *toQmlType(QDeclarativeParser::Object *from); bool canCoerce(int to, QDeclarativeParser::Object *from); - bool canCoerce(int to, int from); QStringList deferredProperties(QDeclarativeParser::Object *); diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index f41d867..c697367 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -67,14 +67,14 @@ int statusId = qRegisterMetaType<QDeclarativeComponent::Status>("QDeclarativeCom /*! \class QDeclarativeComponent - \since 4.7 + \since 4.7 \brief The QDeclarativeComponent class encapsulates a QML component description. \mainclass */ /*! \qmlclass Component QDeclarativeComponent - \since 4.7 + \since 4.7 \brief The Component element encapsulates a QML component description. Components are reusable, encapsulated Qml element with a well-defined interface. @@ -86,26 +86,26 @@ int statusId = qRegisterMetaType<QDeclarativeComponent::Status>("QDeclarativeCom file containing it. \qml -Item { - Component { - id: redSquare - Rectangle { - color: "red" - width: 10 - height: 10 + Item { + Component { + id: redSquare + Rectangle { + color: "red" + width: 10 + height: 10 + } } + Loader { sourceComponent: redSquare } + Loader { sourceComponent: redSquare; x: 20 } } - Loader { sourceComponent: redSquare } - Loader { sourceComponent: redSquare; x: 20 } -} \endqml +*/ - \section1 Attached Properties - - \e onCompleted +/*! + \qmlattachedsignal Component::onCompleted() Emitted after component "startup" has completed. This can be used to - execute script code at startup, once the full QML environment has been + execute script code at startup, once the full QML environment has been established. The \c {Component::onCompleted} attached property can be applied to @@ -120,8 +120,10 @@ Item { } } \endqml +*/ - \e onDestruction +/*! + \qmlattachedsignal Component::onDestruction() Emitted as the component begins destruction. This can be used to undo work done in the onCompleted signal, or other imperative code in your @@ -129,7 +131,7 @@ Item { The \c {Component::onDestruction} attached property can be applied to any element. However, it applies to the destruction of the component as - a whole, and not the destruction of the specific object. The order of + a whole, and not the destruction of the specific object. The order of running the \c onDestruction scripts is undefined. \qml @@ -532,10 +534,8 @@ QScriptValue QDeclarativeComponent::createObject() { Q_D(QDeclarativeComponent); QDeclarativeContext* ctxt = creationContext(); - if(!ctxt){ - qWarning() << QLatin1String("createObject can only be used in QML"); + if(!ctxt) return QScriptValue(); - } QObject* ret = create(ctxt); if (!ret) return QScriptValue(); @@ -615,17 +615,17 @@ QDeclarativeComponentPrivate::beginCreate(QDeclarativeContextData *context, cons { Q_Q(QDeclarativeComponent); if (!context) { - qWarning("QDeclarativeComponent::beginCreate(): Cannot create a component in a null context"); + qWarning("QDeclarativeComponent: Cannot create a component in a null context"); return 0; } if (!context->isValid()) { - qWarning("QDeclarativeComponent::beginCreate(): Cannot create a component in an invalid context"); + qWarning("QDeclarativeComponent: Cannot create a component in an invalid context"); return 0; } if (context->engine != engine) { - qWarning("QDeclarativeComponent::beginCreate(): Must create component in context from the same QDeclarativeEngine"); + qWarning("QDeclarativeComponent: Must create component in context from the same QDeclarativeEngine"); return 0; } @@ -768,7 +768,7 @@ void QDeclarativeComponentPrivate::complete(QDeclarativeEnginePrivate *enginePri enginePriv->inProgressCreations--; if (0 == enginePriv->inProgressCreations) { while (enginePriv->erroredBindings) { - qWarning().nospace() << qPrintable(enginePriv->erroredBindings->error.toString()); + enginePriv->warning(enginePriv->erroredBindings->error); enginePriv->erroredBindings->removeError(); } } diff --git a/src/declarative/qml/qdeclarativecomponent.h b/src/declarative/qml/qdeclarativecomponent.h index 6ee5070..f3cfe3c 100644 --- a/src/declarative/qml/qdeclarativecomponent.h +++ b/src/declarative/qml/qdeclarativecomponent.h @@ -99,8 +99,6 @@ public: virtual QObject *beginCreate(QDeclarativeContext *); virtual void completeCreate(); - Q_INVOKABLE QScriptValue createObject(); - void loadUrl(const QUrl &url); void setData(const QByteArray &, const QUrl &baseUrl); @@ -114,10 +112,12 @@ Q_SIGNALS: protected: QDeclarativeComponent(QDeclarativeComponentPrivate &dd, QObject* parent); + Q_INVOKABLE QScriptValue createObject(); private: QDeclarativeComponent(QDeclarativeEngine *, QDeclarativeCompiledData *, int, int, QObject *parent); + Q_DISABLE_COPY(QDeclarativeComponent) friend class QDeclarativeVME; friend class QDeclarativeCompositeTypeData; }; diff --git a/src/declarative/qml/qdeclarativecompositetypemanager.cpp b/src/declarative/qml/qdeclarativecompositetypemanager.cpp index 133b71f..adeb7a5 100644 --- a/src/declarative/qml/qdeclarativecompositetypemanager.cpp +++ b/src/declarative/qml/qdeclarativecompositetypemanager.cpp @@ -341,7 +341,6 @@ static QString toLocalFileOrQrc(const QUrl& url) if (url.scheme() == QLatin1String("qrc")) { if (url.authority().isEmpty()) return QLatin1Char(':') + url.path(); - qWarning() << "Invalid url:" << url.toString() << "authority" << url.authority() << "not known."; return QString(); } return url.toLocalFile(); diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp index 6657fea..ae4223e 100644 --- a/src/declarative/qml/qdeclarativecontext.cpp +++ b/src/declarative/qml/qdeclarativecontext.cpp @@ -114,7 +114,7 @@ QDeclarativeContextPrivate::QDeclarativeContextPrivate() \endcode All properties added explicitly by QDeclarativeContext::setContextProperty() take - precedence over context object's properties. + precedence over the context object's properties. Contexts form a hierarchy. The root of this heirarchy is the QDeclarativeEngine's \l {QDeclarativeEngine::rootContext()}{root context}. A component instance can @@ -140,6 +140,11 @@ QDeclarativeContextPrivate::QDeclarativeContextPrivate() While QML objects instantiated in a context are not strictly owned by that context, their bindings are. If a context is destroyed, the property bindings of outstanding QML objects will stop evaluating. + + \note Setting the context object or adding new context properties after an object + has been created in that context is an expensive operation (essentially forcing all bindings + to reevaluate). Thus whenever possible you should complete "setup" of the context + before using it to create any objects. */ /*! \internal */ @@ -203,6 +208,12 @@ QDeclarativeContext::~QDeclarativeContext() d->data->destroy(); } +/*! + Returns whether the context is valid. + + To be valid, a context must have a engine, and it's contextObject(), if any, + must not have been deleted. +*/ bool QDeclarativeContext::isValid() const { Q_D(const QDeclarativeContext); @@ -655,7 +666,7 @@ void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object if (scriptEngine->hasUncaughtException()) { QDeclarativeError error; QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error); - qWarning().nospace() << qPrintable(error.toString()); + enginePriv->warning(error); } scriptEngine->popContext(); @@ -681,7 +692,7 @@ void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object if (scriptEngine->hasUncaughtException()) { QDeclarativeError error; QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error); - qWarning().nospace() << qPrintable(error.toString()); + enginePriv->warning(error); } scriptEngine->popContext(); @@ -691,39 +702,6 @@ void QDeclarativeContextData::addImportedScript(const QDeclarativeParser::Object } } -void QDeclarativeContextData::addScript(const QDeclarativeParser::Object::ScriptBlock &script, - QObject *scopeObject) -{ - if (!engine) - return; - - QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); - QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine); - - QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine); - - scriptContext->pushScope(enginePriv->contextClass->newContext(this, scopeObject)); - scriptContext->pushScope(enginePriv->globalClass->globalObject()); - - QScriptValue scope = scriptEngine->newObject(); - scriptContext->setActivationObject(scope); - scriptContext->pushScope(scope); - - for (int ii = 0; ii < script.codes.count(); ++ii) { - scriptEngine->evaluate(script.codes.at(ii), script.files.at(ii), script.lineNumbers.at(ii)); - - if (scriptEngine->hasUncaughtException()) { - QDeclarativeError error; - QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error); - qWarning().nospace() << qPrintable(error.toString()); - } - } - - scriptEngine->popContext(); - - scripts.append(scope); -} - void QDeclarativeContextData::setIdProperty(int idx, QObject *obj) { idValues[idx] = obj; diff --git a/src/declarative/qml/qdeclarativecontext.h b/src/declarative/qml/qdeclarativecontext.h index 94c9f4a..548869c 100644 --- a/src/declarative/qml/qdeclarativecontext.h +++ b/src/declarative/qml/qdeclarativecontext.h @@ -103,6 +103,7 @@ private: friend class QDeclarativeContextData; QDeclarativeContext(QDeclarativeContextData *); QDeclarativeContext(QDeclarativeEngine *, bool); + Q_DISABLE_COPY(QDeclarativeContext) }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h index 77a6d94..c7fb099 100644 --- a/src/declarative/qml/qdeclarativecontext_p.h +++ b/src/declarative/qml/qdeclarativecontext_p.h @@ -145,10 +145,8 @@ public: QObject *contextObject; // Any script blocks that exist on this context - QList<QScriptValue> scripts; QList<QScriptValue> importedScripts; void addImportedScript(const QDeclarativeParser::Object::ScriptBlock &script); - void addScript(const QDeclarativeParser::Object::ScriptBlock &script, QObject *scopeObject); // Context base url QUrl url; diff --git a/src/declarative/qml/qdeclarativecontextscriptclass.cpp b/src/declarative/qml/qdeclarativecontextscriptclass.cpp index 461fab5..1336a1a 100644 --- a/src/declarative/qml/qdeclarativecontextscriptclass.cpp +++ b/src/declarative/qml/qdeclarativecontextscriptclass.cpp @@ -189,14 +189,6 @@ QDeclarativeContextScriptClass::queryProperty(QDeclarativeContextData *bindConte } } - for (int ii = 0; ii < bindContext->scripts.count(); ++ii) { - lastFunction = QScriptDeclarativeClass::function(bindContext->scripts.at(ii), name); - if (lastFunction.isValid()) { - lastContext = bindContext; - return QScriptClass::HandlesReadAccess; - } - } - if (scopeObject) { QScriptClass::QueryFlags rv = ep->objectClass->queryProperty(scopeObject, name, flags, bindContext, diff --git a/src/declarative/qml/qdeclarativecustomparser.cpp b/src/declarative/qml/qdeclarativecustomparser.cpp index 1a97315..472a883 100644 --- a/src/declarative/qml/qdeclarativecustomparser.cpp +++ b/src/declarative/qml/qdeclarativecustomparser.cpp @@ -89,6 +89,8 @@ using namespace QDeclarativeParser; by \a data, which is a block of data previously returned by a call to compile(). + Errors should be reported using qmlInfo(object). + The \a object will be an instance of the TypeClass specified by QML_REGISTER_CUSTOM_TYPE. */ @@ -235,6 +237,24 @@ void QDeclarativeCustomParser::clearErrors() } /*! + Reports an error with the given \a description. + + This can only be used during the compile() step. For errors during setCustomData(), use qmlInfo(). + + An error is generated referring to the position of the element in the source file. +*/ +void QDeclarativeCustomParser::error(const QString& description) +{ + Q_ASSERT(object); + QDeclarativeError error; + QString exceptionDescription; + error.setLine(object->location.start.line); + error.setColumn(object->location.start.column); + error.setDescription(description); + exceptions << error; +} + +/*! Reports an error in parsing \a prop, with the given \a description. An error is generated referring to the position of \a node in the source file. diff --git a/src/declarative/qml/qdeclarativecustomparser_p.h b/src/declarative/qml/qdeclarativecustomparser_p.h index da0358a..0e397c5 100644 --- a/src/declarative/qml/qdeclarativecustomparser_p.h +++ b/src/declarative/qml/qdeclarativecustomparser_p.h @@ -113,7 +113,7 @@ private: class Q_DECLARATIVE_EXPORT QDeclarativeCustomParser { public: - QDeclarativeCustomParser() : compiler(0) {} + QDeclarativeCustomParser() : compiler(0), object(0) {} virtual ~QDeclarativeCustomParser() {} void clearErrors(); @@ -124,6 +124,7 @@ public: QList<QDeclarativeError> errors() const { return exceptions; } protected: + void error(const QString& description); void error(const QDeclarativeCustomParserProperty&, const QString& description); void error(const QDeclarativeCustomParserNode&, const QString& description); @@ -132,6 +133,7 @@ protected: private: QList<QDeclarativeError> exceptions; QDeclarativeCompiler *compiler; + QDeclarativeParser::Object *object; friend class QDeclarativeCompiler; }; diff --git a/src/declarative/qml/qdeclarativedata_p.h b/src/declarative/qml/qdeclarativedata_p.h index 2ddd7e5..4a56536 100644 --- a/src/declarative/qml/qdeclarativedata_p.h +++ b/src/declarative/qml/qdeclarativedata_p.h @@ -75,7 +75,7 @@ public: : ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false), context(0), outerContext(0), bindings(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0), bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), - attachedProperties(0), scriptValue(0), propertyCache(0), guards(0) { + attachedProperties(0), scriptValue(0), objectDataRefCount(0), propertyCache(0), guards(0) { init(); } @@ -128,6 +128,7 @@ public: // ### Can we make this QScriptValuePrivate so we incur no additional allocation // cost? QScriptValue *scriptValue; + quint32 objectDataRefCount; QDeclarativePropertyCache *propertyCache; QDeclarativeGuard<QObject> *guards; diff --git a/src/declarative/qml/qdeclarativedirparser.cpp b/src/declarative/qml/qdeclarativedirparser.cpp index 1e3b37b..3e05853 100644 --- a/src/declarative/qml/qdeclarativedirparser.cpp +++ b/src/declarative/qml/qdeclarativedirparser.cpp @@ -170,10 +170,9 @@ bool QDeclarativeDirParser::parse() const int dotIndex = version.indexOf(QLatin1Char('.')); if (dotIndex == -1) { - qWarning() << "expected '.'"; // ### use reportError + reportError(lineNumber, -1, QLatin1String("expected '.'")); } else if (version.indexOf(QLatin1Char('.'), dotIndex + 1) != -1) { - qWarning() << "unexpected '.'"; // ### use reportError - + reportError(lineNumber, -1, QLatin1String("unexpected '.'")); } else { bool validVersionNumber = false; const int majorVersion = version.left(dotIndex).toInt(&validVersionNumber); @@ -189,8 +188,8 @@ bool QDeclarativeDirParser::parse() } } } else { - // ### use reportError - qWarning() << "a component declaration requires 3 arguments, but" << (sectionCount + 1) << "were provided"; + reportError(lineNumber, -1, + QString::fromUtf8("a component declaration requires 3 arguments, but %1 were provided").arg(sectionCount + 1)); } } diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 96145fb..8eae120 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -144,19 +144,19 @@ static bool qt_QmlQtModule_registered = false; void QDeclarativeEnginePrivate::defineModule() { - qmlRegisterType<QDeclarativeComponent>("Qt",4,6,"Component"); - qmlRegisterType<QObject>("Qt",4,6,"QtObject"); - qmlRegisterType<QDeclarativeWorkerScript>("Qt",4,6,"WorkerScript"); + qmlRegisterType<QDeclarativeComponent>("Qt",4,7,"Component"); + qmlRegisterType<QObject>("Qt",4,7,"QtObject"); + qmlRegisterType<QDeclarativeWorkerScript>("Qt",4,7,"WorkerScript"); qmlRegisterType<QDeclarativeBinding>(); } QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e) -: captureProperties(false), rootContext(0), currentExpression(0), isDebugging(false), - contextClass(0), sharedContext(0), sharedScope(0), objectClass(0), valueTypeClass(0), - globalClass(0), cleanup(0), erroredBindings(0), inProgressCreations(0), - scriptEngine(this), workerScriptEngine(0), componentAttached(0), inBeginCreate(false), - networkAccessManager(0), networkAccessManagerFactory(0), +: captureProperties(false), rootContext(0), currentExpression(0), isDebugging(false), + outputWarningsToStdErr(true), contextClass(0), sharedContext(0), sharedScope(0), + objectClass(0), valueTypeClass(0), globalClass(0), cleanup(0), erroredBindings(0), + inProgressCreations(0), scriptEngine(this), workerScriptEngine(0), componentAttached(0), + inBeginCreate(false), networkAccessManager(0), networkAccessManagerFactory(0), typeManager(e), uniqueId(1) { if (!qt_QmlQtModule_registered) { @@ -216,8 +216,6 @@ QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *pr offlineStoragePath = QDesktopServices::storageLocation(QDesktopServices::DataLocation).replace(QLatin1Char('/'), QDir::separator()) + QDir::separator() + QLatin1String("QML") + QDir::separator() + QLatin1String("OfflineStorage"); -#else - qWarning("offlineStoragePath is not set by default with QT_NO_DESKTOPSERVICES"); #endif qt_add_qmlxmlhttprequest(this); @@ -256,19 +254,19 @@ QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *pr qtObject.setProperty(QLatin1String("quit"), newFunction(QDeclarativeEnginePrivate::quit, 0)); qtObject.setProperty(QLatin1String("resolvedUrl"),newFunction(QDeclarativeScriptEngine::resolvedUrl, 1)); + if (mainthread) { + qtObject.setProperty(QLatin1String("createQmlObject"), + newFunction(QDeclarativeEnginePrivate::createQmlObject, 1)); + qtObject.setProperty(QLatin1String("createComponent"), + newFunction(QDeclarativeEnginePrivate::createComponent, 1)); + } + //firebug/webkit compat QScriptValue consoleObject = newObject(); consoleObject.setProperty(QLatin1String("log"),newFunction(QDeclarativeEnginePrivate::consoleLog, 1)); consoleObject.setProperty(QLatin1String("debug"),newFunction(QDeclarativeEnginePrivate::consoleLog, 1)); globalObject().setProperty(QLatin1String("console"), consoleObject); - if (mainthread) { - globalObject().setProperty(QLatin1String("createQmlObject"), - newFunction(QDeclarativeEnginePrivate::createQmlObject, 1)); - globalObject().setProperty(QLatin1String("createComponent"), - newFunction(QDeclarativeEnginePrivate::createComponent, 1)); - } - // translation functions need to be installed // before the global script class is constructed (QTBUG-6437) installTranslatorFunctions(); @@ -355,7 +353,7 @@ void QDeclarativePrivate::qdeclarativeelement_destructor(QObject *o) QObjectPrivate *p = QObjectPrivate::get(o); Q_ASSERT(p->declarativeData); QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData); - if (d->ownContext) + if (d->ownContext) d->context->destroy(); } @@ -390,15 +388,13 @@ void QDeclarativeEnginePrivate::init() qmlEngineDebugServer(); isDebugging = true; QDeclarativeEngineDebugServer::addEngine(q); - - qmlEngineDebugServer()->waitForClients(); } } QDeclarativeWorkerScriptEngine *QDeclarativeEnginePrivate::getWorkerScriptEngine() { Q_Q(QDeclarativeEngine); - if (!workerScriptEngine) + if (!workerScriptEngine) workerScriptEngine = new QDeclarativeWorkerScriptEngine(q); return workerScriptEngine; } @@ -423,7 +419,7 @@ QDeclarativeWorkerScriptEngine *QDeclarativeEnginePrivate::getWorkerScriptEngine QDeclarativeComponent component(&engine); component.setData("import Qt 4.7\nText { text: \"Hello world!\" }", QUrl()); QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create()); - + //add item to view, etc ... \endcode @@ -655,6 +651,34 @@ void QDeclarativeEngine::setBaseUrl(const QUrl &url) } /*! + Returns true if warning messages will be output to stderr in addition + to being emitted by the warnings() signal, otherwise false. + + The default value is true. +*/ +bool QDeclarativeEngine::outputWarningsToStandardError() const +{ + Q_D(const QDeclarativeEngine); + return d->outputWarningsToStdErr; +} + +/*! + Set whether warning messages will be output to stderr to \a enabled. + + If \a enabled is true, any warning messages generated by QML will be + output to stderr and emitted by the warnings() signal. If \a enabled + is false, on the warnings() signal will be emitted. This allows + applications to handle warning output themselves. + + The default value is true. +*/ +void QDeclarativeEngine::setOutputWarningsToStandardError(bool enabled) +{ + Q_D(QDeclarativeEngine); + d->outputWarningsToStdErr = enabled; +} + +/*! Returns the QDeclarativeContext for the \a object, or 0 if no context has been set. @@ -743,6 +767,9 @@ void QDeclarativeEngine::setContextForObject(QObject *object, QDeclarativeContex */ void QDeclarativeEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership) { + if (!object) + return; + QDeclarativeData *ddata = QDeclarativeData::get(object, true); if (!ddata) return; @@ -756,8 +783,11 @@ void QDeclarativeEngine::setObjectOwnership(QObject *object, ObjectOwnership own */ QDeclarativeEngine::ObjectOwnership QDeclarativeEngine::objectOwnership(QObject *object) { + if (!object) + return CppOwnership; + QDeclarativeData *ddata = QDeclarativeData::get(object, false); - if (!ddata) + if (!ddata) return CppOwnership; else return ddata->indestructible?CppOwnership:JavaScriptOwnership; @@ -780,8 +810,7 @@ void qmlExecuteDeferred(QObject *object) QDeclarativeComponentPrivate::complete(ep, &state); if (!state.errors.isEmpty()) - qWarning() << state.errors; - + ep->warning(state.errors); } } @@ -821,7 +850,7 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool cre return rv; } -QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object, +QObject *qmlAttachedPropertiesObject(int *idCache, const QObject *object, const QMetaObject *attachedMetaObject, bool create) { if (*idCache == -1) @@ -840,7 +869,7 @@ void QDeclarativeData::destroyed(QObject *object) if (attachedProperties) delete attachedProperties; - if (nextContextObject) + if (nextContextObject) nextContextObject->prevContextObject = prevContextObject; if (prevContextObject) *prevContextObject = nextContextObject; @@ -887,7 +916,7 @@ void QDeclarativeData::parentChanged(QObject *, QObject *parent) bool QDeclarativeData::hasBindingBit(int bit) const { - if (bindingBitsSize > bit) + if (bindingBitsSize > bit) return bindingBits[bit / 32] & (1 << (bit % 32)); else return false; @@ -895,7 +924,7 @@ bool QDeclarativeData::hasBindingBit(int bit) const void QDeclarativeData::clearBindingBit(int bit) { - if (bindingBitsSize > bit) + if (bindingBitsSize > bit) bindingBits[bit / 32] &= ~(1 << (bit % 32)); } @@ -908,10 +937,10 @@ void QDeclarativeData::setBindingBit(QObject *obj, int bit) int arraySize = (props + 31) / 32; int oldArraySize = bindingBitsSize / 32; - bindingBits = (quint32 *)realloc(bindingBits, + bindingBits = (quint32 *)realloc(bindingBits, arraySize * sizeof(quint32)); - memset(bindingBits + oldArraySize, + memset(bindingBits + oldArraySize, 0x00, sizeof(quint32) * (arraySize - oldArraySize)); @@ -957,7 +986,7 @@ QScriptValue QDeclarativeEnginePrivate::createComponent(QScriptContext *ctxt, QS Q_ASSERT(context); if(ctxt->argumentCount() != 1) { - return engine->nullValue(); + return ctxt->throwError("Qt.createComponent(): Invalid arguments"); }else{ QString arg = ctxt->argument(0).toString(); if (arg.isEmpty()) @@ -977,7 +1006,7 @@ QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QS QDeclarativeEngine* activeEngine = activeEnginePriv->q_func(); if(ctxt->argumentCount() < 2 || ctxt->argumentCount() > 3) - return engine->nullValue(); + return ctxt->throwError("Qt.createQmlObject(): Invalid arguments"); QDeclarativeContextData* context = activeEnginePriv->getContext(ctxt); Q_ASSERT(context); @@ -996,36 +1025,53 @@ QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QS url = context->resolvedUrl(url); QObject *parentArg = activeEnginePriv->objectClass->toQObject(ctxt->argument(1)); - if(!parentArg) - return engine->nullValue(); + if(!parentArg) + return ctxt->throwError("Qt.createQmlObject(): Missing parent object"); QDeclarativeComponent component(activeEngine); component.setData(qml.toUtf8(), url); if(component.isError()) { QList<QDeclarativeError> errors = component.errors(); - qWarning().nospace() << "QDeclarativeEngine::createQmlObject():"; - foreach (const QDeclarativeError &error, errors) - qWarning().nospace() << " " << error; - - return engine->nullValue(); + QString errstr = QLatin1String("Qt.createQmlObject() failed to create object: "); + QScriptValue arr = ctxt->engine()->newArray(errors.length()); + int i = 0; + foreach (const QDeclarativeError &error, errors){ + errstr += QLatin1String(" ") + error.toString() + QLatin1String("\n"); + QScriptValue qmlErrObject = ctxt->engine()->newObject(); + qmlErrObject.setProperty("lineNumber", QScriptValue(error.line())); + qmlErrObject.setProperty("columnNumber", QScriptValue(error.column())); + qmlErrObject.setProperty("fileName", QScriptValue(error.url().toString())); + qmlErrObject.setProperty("message", QScriptValue(error.description())); + arr.setProperty(i++, qmlErrObject); + } + QScriptValue err = ctxt->throwError(errstr); + err.setProperty("qmlErrors",arr); + return err; } - if (!component.isReady()) { - qWarning().nospace() << "QDeclarativeEngine::createQmlObject(): Component is not ready"; - - return engine->nullValue(); - } + if (!component.isReady()) + return ctxt->throwError("Qt.createQmlObject(): Component is not ready"); QObject *obj = component.create(context->asQDeclarativeContext()); if(component.isError()) { QList<QDeclarativeError> errors = component.errors(); - qWarning().nospace() << "QDeclarativeEngine::createQmlObject():"; - foreach (const QDeclarativeError &error, errors) - qWarning().nospace() << " " << error; - - return engine->nullValue(); + QString errstr = QLatin1String("Qt.createQmlObject() failed to create object: "); + QScriptValue arr = ctxt->engine()->newArray(errors.length()); + int i = 0; + foreach (const QDeclarativeError &error, errors){ + errstr += QLatin1String(" ") + error.toString() + QLatin1String("\n"); + QScriptValue qmlErrObject = ctxt->engine()->newObject(); + qmlErrObject.setProperty("lineNumber", QScriptValue(error.line())); + qmlErrObject.setProperty("columnNumber", QScriptValue(error.column())); + qmlErrObject.setProperty("fileName", QScriptValue(error.url().toString())); + qmlErrObject.setProperty("message", QScriptValue(error.description())); + arr.setProperty(i++, qmlErrObject); + } + QScriptValue err = ctxt->throwError(errstr); + err.setProperty("qmlErrors",arr); + return err; } Q_ASSERT(obj); @@ -1051,7 +1097,7 @@ QScriptValue QDeclarativeEnginePrivate::isQtObject(QScriptContext *ctxt, QScript QScriptValue QDeclarativeEnginePrivate::vector(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 3) - return engine->nullValue(); + return ctxt->throwError("Qt.vector(): Invalid arguments"); qsreal x = ctxt->argument(0).toNumber(); qsreal y = ctxt->argument(1).toNumber(); qsreal z = ctxt->argument(2).toNumber(); @@ -1062,7 +1108,7 @@ QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptE { int argCount = ctxt->argumentCount(); if(argCount == 0 || argCount > 2) - return engine->nullValue(); + return ctxt->throwError("Qt.formatDate(): Invalid arguments"); QDate date = ctxt->argument(0).toDateTime().date(); Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; @@ -1072,8 +1118,9 @@ QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptE return engine->newVariant(qVariantFromValue(date.toString(format))); } else if (ctxt->argument(1).isNumber()) { enumFormat = Qt::DateFormat(ctxt->argument(1).toUInt32()); - } else - return engine->nullValue(); + } else { + return ctxt->throwError("Qt.formatDate(): Invalid date format"); + } } return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); } @@ -1082,7 +1129,7 @@ QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptE { int argCount = ctxt->argumentCount(); if(argCount == 0 || argCount > 2) - return engine->nullValue(); + return ctxt->throwError("Qt.formatTime(): Invalid arguments"); QTime date = ctxt->argument(0).toDateTime().time(); Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; @@ -1092,8 +1139,9 @@ QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptE return engine->newVariant(qVariantFromValue(date.toString(format))); } else if (ctxt->argument(1).isNumber()) { enumFormat = Qt::DateFormat(ctxt->argument(1).toUInt32()); - } else - return engine->nullValue(); + } else { + return ctxt->throwError("Qt.formatTime(): Invalid time format"); + } } return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); } @@ -1102,7 +1150,7 @@ QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScr { int argCount = ctxt->argumentCount(); if(argCount == 0 || argCount > 2) - return engine->nullValue(); + return ctxt->throwError("Qt.formatDateTime(): Invalid arguments"); QDateTime date = ctxt->argument(0).toDateTime(); Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; @@ -1112,8 +1160,9 @@ QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScr return engine->newVariant(qVariantFromValue(date.toString(format))); } else if (ctxt->argument(1).isNumber()) { enumFormat = Qt::DateFormat(ctxt->argument(1).toUInt32()); - } else - return engine->nullValue(); + } else { + return ctxt->throwError("Qt.formatDateTime(): Invalid datetime formate"); + } } return engine->newVariant(qVariantFromValue(date.toString(enumFormat))); } @@ -1122,14 +1171,20 @@ QScriptValue QDeclarativeEnginePrivate::rgba(QScriptContext *ctxt, QScriptEngine { int argCount = ctxt->argumentCount(); if(argCount < 3 || argCount > 4) - return engine->nullValue(); + return ctxt->throwError("Qt.rgba(): Invalid arguments"); qsreal r = ctxt->argument(0).toNumber(); qsreal g = ctxt->argument(1).toNumber(); qsreal b = ctxt->argument(2).toNumber(); qsreal a = (argCount == 4) ? ctxt->argument(3).toNumber() : 1; - if (r < 0 || r > 1 || g < 0 || g > 1 || b < 0 || b > 1 || a < 0 || a > 1) - return engine->nullValue(); + if (r < 0.0) r=0.0; + if (r > 1.0) r=1.0; + if (g < 0.0) g=0.0; + if (g > 1.0) g=1.0; + if (b < 0.0) b=0.0; + if (b > 1.0) b=1.0; + if (a < 0.0) a=0.0; + if (a > 1.0) a=1.0; return qScriptValueFromValue(engine, qVariantFromValue(QColor::fromRgbF(r, g, b, a))); } @@ -1138,14 +1193,20 @@ QScriptValue QDeclarativeEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine { int argCount = ctxt->argumentCount(); if(argCount < 3 || argCount > 4) - return engine->nullValue(); + return ctxt->throwError("Qt.hsla(): Invalid arguments"); qsreal h = ctxt->argument(0).toNumber(); qsreal s = ctxt->argument(1).toNumber(); qsreal l = ctxt->argument(2).toNumber(); qsreal a = (argCount == 4) ? ctxt->argument(3).toNumber() : 1; - if (h < 0 || h > 1 || s < 0 || s > 1 || l < 0 || l > 1 || a < 0 || a > 1) - return engine->nullValue(); + if (h < 0.0) h=0.0; + if (h > 1.0) h=1.0; + if (s < 0.0) s=0.0; + if (s > 1.0) s=1.0; + if (l < 0.0) l=0.0; + if (l > 1.0) l=1.0; + if (a < 0.0) a=0.0; + if (a > 1.0) a=1.0; return qScriptValueFromValue(engine, qVariantFromValue(QColor::fromHslF(h, s, l, a))); } @@ -1153,7 +1214,7 @@ QScriptValue QDeclarativeEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 4) - return engine->nullValue(); + return ctxt->throwError("Qt.rect(): Invalid arguments"); qsreal x = ctxt->argument(0).toNumber(); qsreal y = ctxt->argument(1).toNumber(); @@ -1169,7 +1230,7 @@ QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine QScriptValue QDeclarativeEnginePrivate::point(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 2) - return engine->nullValue(); + return ctxt->throwError("Qt.point(): Invalid arguments"); qsreal x = ctxt->argument(0).toNumber(); qsreal y = ctxt->argument(1).toNumber(); return qScriptValueFromValue(engine, qVariantFromValue(QPointF(x, y))); @@ -1178,7 +1239,7 @@ QScriptValue QDeclarativeEnginePrivate::point(QScriptContext *ctxt, QScriptEngin QScriptValue QDeclarativeEnginePrivate::size(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 2) - return engine->nullValue(); + return ctxt->throwError("Qt.size(): Invalid arguments"); qsreal w = ctxt->argument(0).toNumber(); qsreal h = ctxt->argument(1).toNumber(); return qScriptValueFromValue(engine, qVariantFromValue(QSizeF(w, h))); @@ -1187,7 +1248,7 @@ QScriptValue QDeclarativeEnginePrivate::size(QScriptContext *ctxt, QScriptEngine QScriptValue QDeclarativeEnginePrivate::lighter(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 1) - return engine->nullValue(); + return ctxt->throwError("Qt.lighter(): Invalid arguments"); QVariant v = ctxt->argument(0).toVariant(); QColor color; if (v.userType() == QVariant::Color) @@ -1206,7 +1267,7 @@ QScriptValue QDeclarativeEnginePrivate::lighter(QScriptContext *ctxt, QScriptEng QScriptValue QDeclarativeEnginePrivate::darker(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 1) - return engine->nullValue(); + return ctxt->throwError("Qt.darker(): Invalid arguments"); QVariant v = ctxt->argument(0).toVariant(); QColor color; if (v.userType() == QVariant::Color) @@ -1225,21 +1286,20 @@ QScriptValue QDeclarativeEnginePrivate::darker(QScriptContext *ctxt, QScriptEngi QScriptValue QDeclarativeEnginePrivate::desktopOpenUrl(QScriptContext *ctxt, QScriptEngine *e) { if(ctxt->argumentCount() < 1) - return e->newVariant(QVariant(false)); + return QScriptValue(e, false); bool ret = false; #ifndef QT_NO_DESKTOPSERVICES ret = QDesktopServices::openUrl(QUrl(ctxt->argument(0).toString())); #endif - return e->newVariant(QVariant(ret)); + return QScriptValue(e, ret); } QScriptValue QDeclarativeEnginePrivate::md5(QScriptContext *ctxt, QScriptEngine *) { - QByteArray data; - - if (ctxt->argumentCount() >= 1) - data = ctxt->argument(0).toString().toUtf8(); + if (ctxt->argumentCount() != 1) + return ctxt->throwError("Qt.md5(): Invalid arguments"); + QByteArray data = ctxt->argument(0).toString().toUtf8(); QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5); return QScriptValue(QLatin1String(result.toHex())); @@ -1247,20 +1307,20 @@ QScriptValue QDeclarativeEnginePrivate::md5(QScriptContext *ctxt, QScriptEngine QScriptValue QDeclarativeEnginePrivate::btoa(QScriptContext *ctxt, QScriptEngine *) { - QByteArray data; + if (ctxt->argumentCount() != 1) + return ctxt->throwError("Qt.btoa(): Invalid arguments"); - if (ctxt->argumentCount() >= 1) - data = ctxt->argument(0).toString().toUtf8(); + QByteArray data = ctxt->argument(0).toString().toUtf8(); return QScriptValue(QLatin1String(data.toBase64())); } QScriptValue QDeclarativeEnginePrivate::atob(QScriptContext *ctxt, QScriptEngine *) { - QByteArray data; + if (ctxt->argumentCount() != 1) + return ctxt->throwError("Qt.atob(): Invalid arguments"); - if (ctxt->argumentCount() >= 1) - data = ctxt->argument(0).toString().toUtf8(); + QByteArray data = ctxt->argument(0).toString().toUtf8(); return QScriptValue(QLatin1String(QByteArray::fromBase64(data))); } @@ -1284,23 +1344,82 @@ QScriptValue QDeclarativeEnginePrivate::consoleLog(QScriptContext *ctxt, QScript return e->newVariant(QVariant(true)); } -void QDeclarativeEnginePrivate::sendQuit () +void QDeclarativeEnginePrivate::sendQuit() { Q_Q(QDeclarativeEngine); emit q->quit(); } +static void dumpwarning(const QDeclarativeError &error) +{ + qWarning().nospace() << qPrintable(error.toString()); +} + +static void dumpwarning(const QList<QDeclarativeError> &errors) +{ + for (int ii = 0; ii < errors.count(); ++ii) + dumpwarning(errors.at(ii)); +} + +void QDeclarativeEnginePrivate::warning(const QDeclarativeError &error) +{ + Q_Q(QDeclarativeEngine); + q->warnings(QList<QDeclarativeError>() << error); + if (outputWarningsToStdErr) + dumpwarning(error); +} + +void QDeclarativeEnginePrivate::warning(const QList<QDeclarativeError> &errors) +{ + Q_Q(QDeclarativeEngine); + q->warnings(errors); + if (outputWarningsToStdErr) + dumpwarning(errors); +} + +void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QDeclarativeError &error) +{ + if (engine) + QDeclarativeEnginePrivate::get(engine)->warning(error); + else + dumpwarning(error); +} + +void QDeclarativeEnginePrivate::warning(QDeclarativeEngine *engine, const QList<QDeclarativeError> &error) +{ + if (engine) + QDeclarativeEnginePrivate::get(engine)->warning(error); + else + dumpwarning(error); +} + +void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QDeclarativeError &error) +{ + if (engine) + engine->warning(error); + else + dumpwarning(error); +} + +void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const QList<QDeclarativeError> &error) +{ + if (engine) + engine->warning(error); + else + dumpwarning(error); +} + QScriptValue QDeclarativeEnginePrivate::quit(QScriptContext * /*ctxt*/, QScriptEngine *e) { QDeclarativeEnginePrivate *qe = get (e); - qe->sendQuit (); + qe->sendQuit(); return QScriptValue(); } QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine) { if(ctxt->argumentCount() != 2) - return engine->nullValue(); + return ctxt->throwError("Qt.tint(): Invalid arguments"); //get color QVariant v = ctxt->argument(0).toVariant(); QColor color; @@ -1350,7 +1469,7 @@ QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val) { if (val.userType() == qMetaTypeId<QDeclarativeListReference>()) { - QDeclarativeListReferencePrivate *p = + QDeclarativeListReferencePrivate *p = QDeclarativeListReferencePrivate::get((QDeclarativeListReference*)val.constData()); if (p->object) { return listClass->newList(p->property, p->propertyType); @@ -1383,7 +1502,7 @@ QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val); if (dc == objectClass) return QVariant::fromValue(objectClass->toQObject(val)); - else if (dc == valueTypeClass) + else if (dc == valueTypeClass) return valueTypeClass->toVariant(val); else if (dc == contextClass) return QVariant(); @@ -1410,7 +1529,6 @@ static QString toLocalFileOrQrc(const QUrl& url) if (url.scheme() == QLatin1String("qrc")) { if (url.authority().isEmpty()) return QLatin1Char(':') + url.path(); - qWarning() << "Invalid url:" << url.toString() << "authority" << url.authority() << "not known."; return QString(); } return url.toLocalFile(); @@ -1595,7 +1713,7 @@ public: if (importType == QDeclarativeScriptParser::Import::Library) { url.replace(QLatin1Char('.'), QLatin1Char('/')); bool found = false; - QString dir; + QString dir; foreach (const QString &p, @@ -1620,7 +1738,7 @@ public: found = QDeclarativeMetaType::isModule(uri.toUtf8(), vmaj, vmin); if (!found) { if (errorString) { - bool anyversion = QDeclarativeMetaType::isModule(uri.toUtf8(), 0, 0); + bool anyversion = QDeclarativeMetaType::isModule(uri.toUtf8(), -1, -1); if (anyversion) *errorString = QDeclarativeEngine::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin); else @@ -1773,8 +1891,8 @@ static QDeclarativeTypeNameCache *cacheForNamespace(QDeclarativeEngine *engine, int minor = set.minversions.at(ii); foreach (QDeclarativeType *type, types) { - if (type->qmlTypeName().startsWith(base) && - type->qmlTypeName().lastIndexOf('/') == (base.length() - 1) && + if (type->qmlTypeName().startsWith(base) && + type->qmlTypeName().lastIndexOf('/') == (base.length() - 1) && type->availableInVersion(major,minor)) { QString name = QString::fromUtf8(type->qmlTypeName().mid(base.length())); @@ -1943,7 +2061,8 @@ QStringList QDeclarativeEngine::pluginPathList() const /*! Sets the list of directories where the engine searches for - native plugins for imported modules (referenced in the \c qmldir file). + native plugins for imported modules (referenced in the \c qmldir file) + to \a paths. By default, the list contains only \c ., i.e. the engine searches in the directory of the \c qmldir file itself. @@ -1961,6 +2080,8 @@ void QDeclarativeEngine::setPluginPathList(const QStringList &paths) Imports the plugin named \a filePath with the \a uri provided. Returns true if the plugin was successfully imported; otherwise returns false. + On failure and if non-null, *\a errorString will be set to a message describing the failure. + The plugin has to be a Qt plugin which implements the QDeclarativeExtensionPlugin interface. */ bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &uri, QString *errorString) diff --git a/src/declarative/qml/qdeclarativeengine.h b/src/declarative/qml/qdeclarativeengine.h index 7b058ea..01487f5 100644 --- a/src/declarative/qml/qdeclarativeengine.h +++ b/src/declarative/qml/qdeclarativeengine.h @@ -46,6 +46,7 @@ #include <QtCore/qobject.h> #include <QtCore/qmap.h> #include <QtScript/qscriptvalue.h> +#include <QtDeclarative/qdeclarativeerror.h> QT_BEGIN_HEADER @@ -102,6 +103,9 @@ public: QUrl baseUrl() const; void setBaseUrl(const QUrl &); + bool outputWarningsToStandardError() const; + void setOutputWarningsToStandardError(bool); + static QDeclarativeContext *contextForObject(const QObject *); static void setContextForObject(QObject *, QDeclarativeContext *); @@ -110,9 +114,11 @@ public: static ObjectOwnership objectOwnership(QObject *); Q_SIGNALS: - void quit (); + void quit(); + void warnings(const QList<QDeclarativeError> &warnings); private: + Q_DISABLE_COPY(QDeclarativeEngine) Q_DECLARE_PRIVATE(QDeclarativeEngine) }; diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h index b3bba43..f6b9bcb 100644 --- a/src/declarative/qml/qdeclarativeengine_p.h +++ b/src/declarative/qml/qdeclarativeengine_p.h @@ -162,6 +162,8 @@ public: QDeclarativeExpression *currentExpression; bool isDebugging; + bool outputWarningsToStdErr; + struct ImportedNamespace; QDeclarativeContextScriptClass *contextClass; QDeclarativeContextData *sharedContext; @@ -311,7 +313,13 @@ public: QScriptValue scriptValueFromVariant(const QVariant &); QVariant scriptValueToVariant(const QScriptValue &, int hint = QVariant::Invalid); - void sendQuit (); + void sendQuit(); + void warning(const QDeclarativeError &); + void warning(const QList<QDeclarativeError> &); + static void warning(QDeclarativeEngine *, const QDeclarativeError &); + static void warning(QDeclarativeEngine *, const QList<QDeclarativeError> &); + static void warning(QDeclarativeEnginePrivate *, const QDeclarativeError &); + static void warning(QDeclarativeEnginePrivate *, const QList<QDeclarativeError> &); static QScriptValue qmlScriptObject(QObject*, QDeclarativeEngine*); diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp index 578733c..69e42f8 100644 --- a/src/declarative/qml/qdeclarativeenginedebug.cpp +++ b/src/declarative/qml/qdeclarativeenginedebug.cpp @@ -308,8 +308,6 @@ void QDeclarativeEngineDebugServer::messageReceived(const QByteArray &message) QByteArray type; ds >> type; - //qDebug() << "QDeclarativeEngineDebugServer::messageReceived()" << type; - if (type == "LIST_ENGINES") { int queryId; ds >> queryId; @@ -418,7 +416,7 @@ void QDeclarativeEngineDebugServer::messageReceived(const QByteArray &message) if (object && context) { QDeclarativeExpression exprObj(context, expr, object); bool undefined = false; - QVariant value = exprObj.value(&undefined); + QVariant value = exprObj.evaluate(&undefined); if (undefined) result = QLatin1String("<undefined>"); else diff --git a/src/declarative/qml/qdeclarativeerror.cpp b/src/declarative/qml/qdeclarativeerror.cpp index 7e8aac0..8717f56 100644 --- a/src/declarative/qml/qdeclarativeerror.cpp +++ b/src/declarative/qml/qdeclarativeerror.cpp @@ -49,8 +49,27 @@ QT_BEGIN_NAMESPACE /*! \class QDeclarativeError - \since 4.7 - \brief The QDeclarativeError class encapsulates a QML error + \since 4.7 + \brief The QDeclarativeError class encapsulates a QML error. + + QDeclarativeError includes a textual description of the error, as well + as location information (the file, line, and column). The toString() + method creates a single-line, human-readable string containing all of + this information, for example: + \code + file:///home/user/test.qml:7:8: Invalid property assignment: double expected + \endcode + + You can use qDebug() or qWarning() to output errors to the console. This method + will attempt to open the file indicated by the error + and include additional contextual information. + \code + file:///home/user/test.qml:7:8: Invalid property assignment: double expected + y: "hello" + ^ + \endcode + + \sa QDeclarativeView::errors(), QDeclarativeComponent::errors() */ class QDeclarativeErrorPrivate { @@ -69,7 +88,7 @@ QDeclarativeErrorPrivate::QDeclarativeErrorPrivate() } /*! - Create an empty error object. + Creates an empty error object. */ QDeclarativeError::QDeclarativeError() : d(0) @@ -77,7 +96,7 @@ QDeclarativeError::QDeclarativeError() } /*! - Create a copy of \a other. + Creates a copy of \a other. */ QDeclarativeError::QDeclarativeError(const QDeclarativeError &other) : d(0) @@ -86,7 +105,7 @@ QDeclarativeError::QDeclarativeError(const QDeclarativeError &other) } /*! - Assign \a other to this error object. + Assigns \a other to this error object. */ QDeclarativeError &QDeclarativeError::operator=(const QDeclarativeError &other) { @@ -112,7 +131,7 @@ QDeclarativeError::~QDeclarativeError() } /*! - Return true if this error is valid, otherwise false. + Returns true if this error is valid, otherwise false. */ bool QDeclarativeError::isValid() const { @@ -120,7 +139,7 @@ bool QDeclarativeError::isValid() const } /*! - Return the url for the file that caused this error. + Returns the url for the file that caused this error. */ QUrl QDeclarativeError::url() const { @@ -129,7 +148,7 @@ QUrl QDeclarativeError::url() const } /*! - Set the \a url for the file that caused this error. + Sets the \a url for the file that caused this error. */ void QDeclarativeError::setUrl(const QUrl &url) { @@ -138,7 +157,7 @@ void QDeclarativeError::setUrl(const QUrl &url) } /*! - Return the error description. + Returns the error description. */ QString QDeclarativeError::description() const { @@ -147,7 +166,7 @@ QString QDeclarativeError::description() const } /*! - Set the error \a description. + Sets the error \a description. */ void QDeclarativeError::setDescription(const QString &description) { @@ -156,7 +175,7 @@ void QDeclarativeError::setDescription(const QString &description) } /*! - Return the error line number. + Returns the error line number. */ int QDeclarativeError::line() const { @@ -165,7 +184,7 @@ int QDeclarativeError::line() const } /*! - Set the error \a line number. + Sets the error \a line number. */ void QDeclarativeError::setLine(int line) { @@ -174,7 +193,7 @@ void QDeclarativeError::setLine(int line) } /*! - Return the error column number. + Returns the error column number. */ int QDeclarativeError::column() const { @@ -183,7 +202,7 @@ int QDeclarativeError::column() const } /*! - Set the error \a column number. + Sets the error \a column number. */ void QDeclarativeError::setColumn(int column) { @@ -192,14 +211,20 @@ void QDeclarativeError::setColumn(int column) } /*! - Return the error as a human readable string. + Returns the error as a human readable string. */ QString QDeclarativeError::toString() const { QString rv; - rv = url().toString() + QLatin1Char(':') + QString::number(line()); - if(column() != -1) - rv += QLatin1Char(':') + QString::number(column()); + if (url().isEmpty()) { + rv = QLatin1String("<Unknown File>"); + } else if (line() != -1) { + rv = url().toString() + QLatin1Char(':') + QString::number(line()); + if(column() != -1) + rv += QLatin1Char(':') + QString::number(column()); + } else { + rv = url().toString(); + } rv += QLatin1String(": ") + description(); @@ -210,7 +235,7 @@ QString QDeclarativeError::toString() const \relates QDeclarativeError \fn QDebug operator<<(QDebug debug, const QDeclarativeError &error) - Output a human readable version of \a error to \a debug. + Outputs a human readable version of \a error to \a debug. */ QDebug operator<<(QDebug debug, const QDeclarativeError &error) diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp index 05240a2..f561a7e 100644 --- a/src/declarative/qml/qdeclarativeexpression.cpp +++ b/src/declarative/qml/qdeclarativeexpression.cpp @@ -479,18 +479,18 @@ QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isU } /*! - Returns the value of the expression, or an invalid QVariant if the - expression is invalid or has an error. + Evaulates the expression, returning the result of the evaluation, + or an invalid QVariant if the expression is invalid or has an error. - \a isUndefined is set to true if the expression resulted in an + \a valueIsUndefined is set to true if the expression resulted in an undefined value. \sa hasError(), error() */ -QVariant QDeclarativeExpression::value(bool *isUndefined) +QVariant QDeclarativeExpression::evaluate(bool *valueIsUndefined) { Q_D(QDeclarativeExpression); - return d->value(0, isUndefined); + return d->value(0, valueIsUndefined); } /*! @@ -569,7 +569,7 @@ QObject *QDeclarativeExpression::scopeObject() const } /*! - Returns true if the last call to value() resulted in an error, + Returns true if the last call to evaluate() resulted in an error, otherwise false. \sa error(), clearError() @@ -593,7 +593,7 @@ void QDeclarativeExpression::clearError() } /*! - Return any error from the last call to value(). If there was no error, + Return any error from the last call to evaluate(). If there was no error, this returns an invalid QDeclarativeError instance. \sa hasError(), clearError() @@ -606,10 +606,9 @@ QDeclarativeError QDeclarativeExpression::error() const } /*! \internal */ -void QDeclarativeExpression::__q_notify() +void QDeclarativeExpressionPrivate::_q_notify() { - Q_D(QDeclarativeExpression); - d->emitValueChanged(); + emitValueChanged(); } void QDeclarativeExpressionPrivate::clearGuards() @@ -625,7 +624,7 @@ void QDeclarativeExpressionPrivate::updateGuards(const QPODVector<QDeclarativeEn static int notifyIdx = -1; if (notifyIdx == -1) - notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("__q_notify()"); + notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()"); if (properties.count() != data->guardListLength) { QDeclarativeNotifierEndpoint *newGuardList = @@ -695,14 +694,13 @@ void QDeclarativeExpressionPrivate::updateGuards(const QPODVector<QDeclarativeEn if (!outputWarningHeader) { outputWarningHeader = true; qWarning() << "QDeclarativeExpression: Expression" << q->expression() - << "depends on non-NOTIFYable properties:"; + << "depends on non-NOTIFYable properties:"; } const QMetaObject *metaObj = property.object->metaObject(); QMetaProperty metaProp = metaObj->property(property.coreIndex); - qWarning().nospace() << " " << metaObj->className() - << "::" << metaProp.name(); + qWarning().nospace() << " " << metaObj->className() << "::" << metaProp.name(); } } } @@ -712,7 +710,7 @@ void QDeclarativeExpressionPrivate::updateGuards(const QPODVector<QDeclarativeEn Emitted each time the expression value changes from the last time it was evaluated. The expression must have been evaluated at least once (by - calling QDeclarativeExpression::value()) before this signal will be emitted. + calling QDeclarativeExpression::evaluate()) before this signal will be emitted. */ void QDeclarativeExpressionPrivate::emitValueChanged() @@ -772,3 +770,4 @@ bool QDeclarativeAbstractExpression::isValid() const QT_END_NAMESPACE +#include <moc_qdeclarativeexpression.cpp> diff --git a/src/declarative/qml/qdeclarativeexpression.h b/src/declarative/qml/qdeclarativeexpression.h index 35d6949..6c72e4d 100644 --- a/src/declarative/qml/qdeclarativeexpression.h +++ b/src/declarative/qml/qdeclarativeexpression.h @@ -86,7 +86,7 @@ public: void clearError(); QDeclarativeError error() const; - QVariant value(bool *isUndefined = 0); + QVariant evaluate(bool *valueIsUndefined = 0); Q_SIGNALS: void valueChanged(); @@ -97,13 +97,12 @@ protected: QDeclarativeExpression(QDeclarativeContextData *, void *, QDeclarativeRefCount *rc, QObject *me, const QString &, int, QDeclarativeExpressionPrivate &dd); -private Q_SLOTS: - void __q_notify(); - private: QDeclarativeExpression(QDeclarativeContextData *, const QString &, QObject *); + Q_DISABLE_COPY(QDeclarativeExpression) Q_DECLARE_PRIVATE(QDeclarativeExpression) + Q_PRIVATE_SLOT(d_func(), void _q_notify()) friend class QDeclarativeDebugger; friend class QDeclarativeContext; friend class QDeclarativeVME; diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h index d39aa2c..4ff3162 100644 --- a/src/declarative/qml/qdeclarativeexpression_p.h +++ b/src/declarative/qml/qdeclarativeexpression_p.h @@ -164,6 +164,7 @@ public: return expr->q_func(); } + void _q_notify(); virtual void emitValueChanged(); static void exceptionToError(QScriptEngine *, QDeclarativeError &); diff --git a/src/declarative/qml/qdeclarativeextensionplugin.cpp b/src/declarative/qml/qdeclarativeextensionplugin.cpp index 762c642d..863bfc4 100644 --- a/src/declarative/qml/qdeclarativeextensionplugin.cpp +++ b/src/declarative/qml/qdeclarativeextensionplugin.cpp @@ -59,6 +59,11 @@ QT_BEGIN_NAMESPACE function, and exporting the class using the Q_EXPORT_PLUGIN2() macro. + QML extension plugins can be used to provide either application-specific or + library-like plugins. Library plugins should limit themselves to registering types, + as any manipulation of the engine's root context may cause conflicts + or other issues in the library user's code. + See \l {Extending QML in C++} for details how to write a QML extension plugin. See \l {How to Create Qt Plugins} for general Qt plugin documentation. @@ -85,7 +90,7 @@ QDeclarativeExtensionPlugin::QDeclarativeExtensionPlugin(QObject *parent) } /*! - Destructor. + Destroys the plugin. */ QDeclarativeExtensionPlugin::~QDeclarativeExtensionPlugin() { @@ -94,7 +99,9 @@ QDeclarativeExtensionPlugin::~QDeclarativeExtensionPlugin() /*! \fn void QDeclarativeExtensionPlugin::initializeEngine(QDeclarativeEngine *engine, const char *uri) - Initializes the extension from the \a uri using the \a engine. + Initializes the extension from the \a uri using the \a engine. Here an application + plugin might, for example, expose some data or objects to QML, + as context properties on the engine's root context. */ void QDeclarativeExtensionPlugin::initializeEngine(QDeclarativeEngine *engine, const char *uri) diff --git a/src/declarative/qml/qdeclarativeextensionplugin.h b/src/declarative/qml/qdeclarativeextensionplugin.h index 8095ec7..8a9378a 100644 --- a/src/declarative/qml/qdeclarativeextensionplugin.h +++ b/src/declarative/qml/qdeclarativeextensionplugin.h @@ -64,6 +64,9 @@ public: virtual void registerTypes(const char *uri) = 0; virtual void initializeEngine(QDeclarativeEngine *engine, const char *uri); + +private: + Q_DISABLE_COPY(QDeclarativeExtensionPlugin) }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeimageprovider.cpp b/src/declarative/qml/qdeclarativeimageprovider.cpp index b992b9f..4be3472 100644 --- a/src/declarative/qml/qdeclarativeimageprovider.cpp +++ b/src/declarative/qml/qdeclarativeimageprovider.cpp @@ -45,31 +45,39 @@ QT_BEGIN_NAMESPACE /*! \class QDeclarativeImageProvider - \brief The QDeclarativeImageProvider class provides an interface for threaded image requests. + \since 4.7 + \brief The QDeclarativeImageProvider class provides an interface for threaded image requests in QML. - Note: the request() method may be called by multiple threads, so ensure the + QDeclarativeImageProvider can be used by a QDeclarativeEngine to provide images to QML asynchronously. + The image request will be run in a low priority thread, allowing potentially costly image + loading to be done in the background, without affecting the performance of the UI. + + See the QDeclarativeEngine::addImageProvider() documentation for an + example of how a custom QDeclarativeImageProvider can be constructed and used. + + \note the request() method may be called by multiple threads, so ensure the implementation of this method is reentrant. \sa QDeclarativeEngine::addImageProvider() */ /*! - The destructor is virtual. + Destroys the image provider. */ QDeclarativeImageProvider::~QDeclarativeImageProvider() { } /*! - \fn QImage QDeclarativeImageProvider::request(const QString &id, QSize *size, const QSize& requested_size) + \fn QImage QDeclarativeImageProvider::request(const QString &id, QSize *size, const QSize& requestedSize) Implement this method to return the image with \a id. - If \a requested_size is a valid size, resize the image to that size before returning. + If \a requestedSize is a valid size, the image returned should be of that size. - In any case, \a size must be set to the (original) size of the image. + In all cases, \a size must be set to the original size of the image. - Note: this method may be called by multiple threads, so ensure the + \note this method may be called by multiple threads, so ensure the implementation of this method is reentrant. */ diff --git a/src/declarative/qml/qdeclarativeimageprovider.h b/src/declarative/qml/qdeclarativeimageprovider.h index 50b73fe..cc9c9af 100644 --- a/src/declarative/qml/qdeclarativeimageprovider.h +++ b/src/declarative/qml/qdeclarativeimageprovider.h @@ -54,7 +54,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeImageProvider { public: virtual ~QDeclarativeImageProvider(); - virtual QImage request(const QString &id, QSize *size, const QSize& requested_size) = 0; + virtual QImage request(const QString &id, QSize *size, const QSize& requestedSize) = 0; }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeinfo.cpp b/src/declarative/qml/qdeclarativeinfo.cpp index 0a4352f..ffed14e 100644 --- a/src/declarative/qml/qdeclarativeinfo.cpp +++ b/src/declarative/qml/qdeclarativeinfo.cpp @@ -45,6 +45,7 @@ #include "qdeclarativecontext.h" #include "private/qdeclarativecontext_p.h" #include "private/qdeclarativemetatype_p.h" +#include "private/qdeclarativeengine_p.h" #include <QCoreApplication> @@ -77,51 +78,98 @@ QT_BEGIN_NAMESPACE \endcode */ -QDeclarativeInfo::QDeclarativeInfo(const QObject *object) -: QDebug(QtWarningMsg) +struct QDeclarativeInfoPrivate { - QString pos = QLatin1String("QML"); - if (object) { - pos += QLatin1Char(' '); - - QString typeName; - QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject()); - if (type) { - typeName = QLatin1String(type->qmlTypeName()); - int lastSlash = typeName.lastIndexOf(QLatin1Char('/')); - if (lastSlash != -1) - typeName = typeName.mid(lastSlash+1); - } else { - typeName = QString::fromUtf8(object->metaObject()->className()); - int marker = typeName.indexOf(QLatin1String("_QMLTYPE_")); - if (marker != -1) - typeName = typeName.left(marker); - } + QDeclarativeInfoPrivate() : ref (1), object(0) {} - pos += typeName; - } - QDeclarativeData *ddata = object?QDeclarativeData::get(object):0; - pos += QLatin1String(" ("); - if (ddata) { - if (ddata->outerContext && !ddata->outerContext->url.isEmpty()) { - pos += ddata->outerContext->url.toString(); - pos += QLatin1Char(':'); - pos += QString::number(ddata->lineNumber); - pos += QLatin1Char(':'); - pos += QString::number(ddata->columnNumber); - } else { - pos += QCoreApplication::translate("QDeclarativeInfo","unknown location"); - } - } else { - pos += QCoreApplication::translate("QDeclarativeInfo","unknown location"); - } - pos += QLatin1Char(')'); - *this << pos; + int ref; + const QObject *object; + QString buffer; + QList<QDeclarativeError> errors; +}; + +QDeclarativeInfo::QDeclarativeInfo(QDeclarativeInfoPrivate *p) +: QDebug(&p->buffer), d(p) +{ nospace(); } +QDeclarativeInfo::QDeclarativeInfo(const QDeclarativeInfo &other) +: QDebug(other), d(other.d) +{ + d->ref++; +} + QDeclarativeInfo::~QDeclarativeInfo() { + if (0 == --d->ref) { + QList<QDeclarativeError> errors = d->errors; + + QDeclarativeEngine *engine = 0; + + if (!d->buffer.isEmpty()) { + QDeclarativeError error; + + QObject *object = const_cast<QObject *>(d->object); + + if (object) { + engine = qmlEngine(d->object); + QString typeName; + QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject()); + if (type) { + typeName = QLatin1String(type->qmlTypeName()); + int lastSlash = typeName.lastIndexOf(QLatin1Char('/')); + if (lastSlash != -1) + typeName = typeName.mid(lastSlash+1); + } else { + typeName = QString::fromUtf8(object->metaObject()->className()); + int marker = typeName.indexOf(QLatin1String("_QMLTYPE_")); + if (marker != -1) + typeName = typeName.left(marker); + } + + d->buffer.prepend(QLatin1String("QML ") + typeName + QLatin1String(": ")); + + QDeclarativeData *ddata = QDeclarativeData::get(object, false); + if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) { + error.setUrl(ddata->outerContext->url); + error.setLine(ddata->lineNumber); + error.setColumn(ddata->columnNumber); + } + } + + error.setDescription(d->buffer); + + errors.prepend(error); + } + + QDeclarativeEnginePrivate::warning(engine, errors); + + delete d; + } +} + +QDeclarativeInfo qmlInfo(const QObject *me) +{ + QDeclarativeInfoPrivate *d = new QDeclarativeInfoPrivate; + d->object = me; + return QDeclarativeInfo(d); +} + +QDeclarativeInfo qmlInfo(const QObject *me, const QDeclarativeError &error) +{ + QDeclarativeInfoPrivate *d = new QDeclarativeInfoPrivate; + d->object = me; + d->errors << error; + return QDeclarativeInfo(d); +} + +QDeclarativeInfo qmlInfo(const QObject *me, const QList<QDeclarativeError> &errors) +{ + QDeclarativeInfoPrivate *d = new QDeclarativeInfoPrivate; + d->object = me; + d->errors = errors; + return QDeclarativeInfo(d); } diff --git a/src/declarative/qml/qdeclarativeinfo.h b/src/declarative/qml/qdeclarativeinfo.h index 8f69f73..2ac28f4 100644 --- a/src/declarative/qml/qdeclarativeinfo.h +++ b/src/declarative/qml/qdeclarativeinfo.h @@ -43,6 +43,8 @@ #define QDECLARATIVEINFO_H #include <QtCore/qdebug.h> +#include <QtCore/qurl.h> +#include <QtDeclarative/qdeclarativeerror.h> QT_BEGIN_HEADER @@ -50,10 +52,11 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) +class QDeclarativeInfoPrivate; class Q_DECLARATIVE_EXPORT QDeclarativeInfo : public QDebug { public: - QDeclarativeInfo(const QObject *); + QDeclarativeInfo(const QDeclarativeInfo &); ~QDeclarativeInfo(); inline QDeclarativeInfo &operator<<(QChar t) { QDebug::operator<<(t); return *this; } @@ -78,12 +81,20 @@ public: inline QDeclarativeInfo &operator<<(const void * t) { QDebug::operator<<(t); return *this; } inline QDeclarativeInfo &operator<<(QTextStreamFunction f) { QDebug::operator<<(f); return *this; } inline QDeclarativeInfo &operator<<(QTextStreamManipulator m) { QDebug::operator<<(m); return *this; } + inline QDeclarativeInfo &operator<<(const QUrl &t) { static_cast<QDebug &>(*this) << t; return *this; } + +private: + friend Q_DECLARATIVE_EXPORT QDeclarativeInfo qmlInfo(const QObject *me); + friend Q_DECLARATIVE_EXPORT QDeclarativeInfo qmlInfo(const QObject *me, const QDeclarativeError &error); + friend Q_DECLARATIVE_EXPORT QDeclarativeInfo qmlInfo(const QObject *me, const QList<QDeclarativeError> &errors); + + QDeclarativeInfo(QDeclarativeInfoPrivate *); + QDeclarativeInfoPrivate *d; }; -Q_DECLARATIVE_EXPORT inline QDeclarativeInfo qmlInfo(const QObject *me) -{ - return QDeclarativeInfo(me); -} +Q_DECLARATIVE_EXPORT QDeclarativeInfo qmlInfo(const QObject *me); +Q_DECLARATIVE_EXPORT QDeclarativeInfo qmlInfo(const QObject *me, const QDeclarativeError &error); +Q_DECLARATIVE_EXPORT QDeclarativeInfo qmlInfo(const QObject *me, const QList<QDeclarativeError> &errors); QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp index d88d06a..99f1cc8 100644 --- a/src/declarative/qml/qdeclarativeinstruction.cpp +++ b/src/declarative/qml/qdeclarativeinstruction.cpp @@ -149,9 +149,6 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx) case QDeclarativeInstruction::StoreSignal: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_SIGNAL\t\t" << instr->storeSignal.signalIndex << "\t" << instr->storeSignal.value << "\t\t" << primitives.at(instr->storeSignal.value); break; - case QDeclarativeInstruction::StoreScript: - qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_SCRIPT\t\t" << instr->storeScript.value; - break; case QDeclarativeInstruction::StoreImportedScript: qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_IMPORTED_SCRIPT\t" << instr->storeScript.value; break; diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h index e8287c0..c09b157 100644 --- a/src/declarative/qml/qdeclarativeinstruction_p.h +++ b/src/declarative/qml/qdeclarativeinstruction_p.h @@ -121,7 +121,6 @@ public: StoreInterface, /* storeObject */ StoreSignal, /* storeSignal */ - StoreScript, /* storeScript */ StoreImportedScript, /* storeScript */ StoreScriptString, /* storeScriptString */ diff --git a/src/declarative/qml/qdeclarativelist.cpp b/src/declarative/qml/qdeclarativelist.cpp index 45b8cd7..31ef4c2 100644 --- a/src/declarative/qml/qdeclarativelist.cpp +++ b/src/declarative/qml/qdeclarativelist.cpp @@ -87,9 +87,10 @@ void QDeclarativeListReferencePrivate::release() /*! \class QDeclarativeListReference +\since 4.7 \brief The QDeclarativeListReference class allows the manipulation of QDeclarativeListProperty properties. -QDeclarativeListReference allows programs to read from, and assign values to a QML list property in a +QDeclarativeListReference allows C++ programs to read from, and assign values to a QML list property in a simple and type safe way. A QDeclarativeListReference can be created by passing an object and property name or through a QDeclarativeProperty instance. These two are equivalant: @@ -304,6 +305,7 @@ int QDeclarativeListReference::count() const /*! \class QDeclarativeListProperty +\since 4.7 \brief The QDeclarativeListProperty class allows applications to explose list-like properties to QML. @@ -313,10 +315,10 @@ The use of a list property from QML looks like this: \code FruitBasket { fruit: [ - Apple {}, - Orange{}, - Banana {} - ] + Apple {}, + Orange{}, + Banana{} + ] } \endcode @@ -336,6 +338,9 @@ Q_PROPERTY(QDeclarativeListProperty<Fruit> fruit READ fruit); QML list properties are typesafe - in this case \c {Fruit} is a QObject type that \c {Apple}, \c {Orange} and \c {Banana} all derive from. + +\note QDeclarativeListProperty can only be used for lists of QObject-derived object pointers. + */ /*! diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp index 7b71608..d9ea8dc 100644 --- a/src/declarative/qml/qdeclarativemetatype.cpp +++ b/src/declarative/qml/qdeclarativemetatype.cpp @@ -99,8 +99,12 @@ struct QDeclarativeMetaTypeData StringConverters stringConverters; struct ModuleInfo { - ModuleInfo(int maj, int min) : vmajor(maj), vminor(min) {} - int vmajor, vminor; + ModuleInfo(int major, int minor) + : vmajor_min(major), vminor_min(minor), vmajor_max(major), vminor_max(minor) {} + ModuleInfo(int major_min, int minor_min, int major_max, int minor_max) + : vmajor_min(major_min), vminor_min(minor_min), vmajor_max(major_max), vminor_max(minor_max) {} + int vmajor_min, vminor_min; + int vmajor_max, vminor_max; }; typedef QHash<QByteArray, ModuleInfo> ModuleInfoHash; ModuleInfoHash modules; @@ -134,6 +138,7 @@ public: int m_allocationSize; void (*m_newFunc)(void *); + QString m_noCreationReason; const QMetaObject *m_baseMetaObject; QDeclarativeAttachedPropertiesFunc m_attachedPropertiesFunc; @@ -186,6 +191,7 @@ QDeclarativeType::QDeclarativeType(int index, const QDeclarativePrivate::Registe d->m_listId = type.listId; d->m_allocationSize = type.objectSize; d->m_newFunc = type.create; + d->m_noCreationReason = type.noCreationReason; d->m_baseMetaObject = type.metaObject; d->m_attachedPropertiesFunc = type.attachedPropertiesFunction; d->m_attachedPropertiesType = type.attachedPropertiesMetaObject; @@ -221,6 +227,76 @@ bool QDeclarativeType::availableInVersion(int vmajor, int vminor) const return vmajor > d->m_version_maj || (vmajor == d->m_version_maj && vminor >= d->m_version_min); } +static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo, + const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd) +{ + // Clone Q_CLASSINFO + for (int ii = mo->classInfoOffset(); ii < mo->classInfoCount(); ++ii) { + QMetaClassInfo info = mo->classInfo(ii); + + int otherIndex = ignoreEnd->indexOfClassInfo(info.name()); + if (otherIndex >= ignoreStart->classInfoOffset() + ignoreStart->classInfoCount()) { + // Skip + } else { + builder.addClassInfo(info.name(), info.value()); + } + } + + // Clone Q_PROPERTY + for (int ii = mo->propertyOffset(); ii < mo->propertyCount(); ++ii) { + QMetaProperty property = mo->property(ii); + + int otherIndex = ignoreEnd->indexOfProperty(property.name()); + if (otherIndex >= ignoreStart->classInfoOffset() + ignoreStart->classInfoCount()) { + builder.addProperty(QByteArray("__qml_ignore__") + property.name(), QByteArray("void")); + // Skip + } else { + builder.addProperty(property); + } + } + + // Clone Q_METHODS + for (int ii = mo->methodOffset(); ii < mo->methodCount(); ++ii) { + QMetaMethod method = mo->method(ii); + + // More complex - need to search name + QByteArray name = method.signature(); + int parenIdx = name.indexOf('('); + if (parenIdx != -1) name = name.left(parenIdx); + + + bool found = false; + + for (int ii = ignoreStart->methodOffset() + ignoreStart->methodCount(); + !found && ii < ignoreEnd->methodOffset() + ignoreEnd->methodCount(); + ++ii) { + + QMetaMethod other = ignoreEnd->method(ii); + QByteArray othername = other.signature(); + int parenIdx = othername.indexOf('('); + if (parenIdx != -1) othername = othername.left(parenIdx); + + found = name == othername; + } + + QMetaMethodBuilder m = builder.addMethod(method); + if (found) // SKIP + m.setAccess(QMetaMethod::Private); + } + + // Clone Q_ENUMS + for (int ii = mo->enumeratorOffset(); ii < mo->enumeratorCount(); ++ii) { + QMetaEnum enumerator = mo->enumerator(ii); + + int otherIndex = ignoreEnd->indexOfEnumerator(enumerator.name()); + if (otherIndex >= ignoreStart->enumeratorOffset() + ignoreStart->enumeratorCount()) { + // Skip + } else { + builder.addEnumerator(enumerator); + } + } +} + void QDeclarativeTypePrivate::init() const { if (m_isSetup) return; @@ -245,8 +321,9 @@ void QDeclarativeTypePrivate::init() const QDeclarativeType *t = metaTypeData()->metaObjectToType.value(mo); if (t) { if (t->d->m_extFunc) { - QMetaObject *mmo = new QMetaObject; - *mmo = *t->d->m_extMetaObject; + QMetaObjectBuilder builder; + clone(builder, t->d->m_extMetaObject, t->d->m_baseMetaObject, m_baseMetaObject); + QMetaObject *mmo = builder.toMetaObject(); mmo->d.superdata = m_baseMetaObject; if (!m_metaObjects.isEmpty()) m_metaObjects.last().metaObject->d.superdata = mmo; @@ -318,6 +395,11 @@ QDeclarativeType::CreateFunc QDeclarativeType::createFunction() const return d->m_newFunc; } +QString QDeclarativeType::noCreationReason() const +{ + return d->m_noCreationReason; +} + int QDeclarativeType::createSize() const { return d->m_allocationSize; @@ -403,10 +485,8 @@ int QDeclarativeType::index() const int QDeclarativePrivate::registerType(const QDeclarativePrivate::RegisterInterface &interface) { - if (interface.version > 0) { - qWarning("Cannot mix incompatible QML versions."); - return -1; - } + if (interface.version > 0) + qFatal("qmlRegisterType(): Cannot mix incompatible QML versions."); QWriteLocker lock(metaTypeDataLock()); QDeclarativeMetaTypeData *data = metaTypeData(); @@ -437,7 +517,7 @@ int QDeclarativePrivate::registerType(const QDeclarativePrivate::RegisterType &t if (type.elementName) { for (int ii = 0; type.elementName[ii]; ++ii) { if (!isalnum(type.elementName[ii])) { - qWarning("QDeclarativeMetaType: Invalid QML element name %s", type.elementName); + qWarning("qmlRegisterType(): Invalid QML element name \"%s\"", type.elementName); return -1; } } @@ -468,9 +548,15 @@ int QDeclarativePrivate::registerType(const QDeclarativePrivate::RegisterType &t if (type.uri) { QByteArray mod(type.uri); QDeclarativeMetaTypeData::ModuleInfoHash::Iterator it = data->modules.find(mod); - if (it == data->modules.end() - || ((*it).vmajor < type.versionMajor || ((*it).vmajor == type.versionMajor && (*it).vminor < type.versionMinor))) { + if (it == data->modules.end()) { + // New module data->modules.insert(mod, QDeclarativeMetaTypeData::ModuleInfo(type.versionMajor,type.versionMinor)); + } else if ((*it).vmajor_max < type.versionMajor || ((*it).vmajor_max == type.versionMajor && (*it).vminor_max < type.versionMinor)) { + // Newer module + data->modules.insert(mod, QDeclarativeMetaTypeData::ModuleInfo((*it).vmajor_min, (*it).vminor_min, type.versionMajor, type.versionMinor)); + } else if ((*it).vmajor_min > type.versionMajor || ((*it).vmajor_min == type.versionMajor && (*it).vminor_min > type.versionMinor)) { + // Older module + data->modules.insert(mod, QDeclarativeMetaTypeData::ModuleInfo(type.versionMajor, type.versionMinor, (*it).vmajor_min, (*it).vminor_min)); } } @@ -478,15 +564,23 @@ int QDeclarativePrivate::registerType(const QDeclarativePrivate::RegisterType &t } /* - Have any types been registered for \a module with at least versionMajor.versionMinor. + Have any types been registered for \a module with at least versionMajor.versionMinor, and types + for \a module with at most versionMajor.versionMinor. + + So if only 4.7 and 4.9 have been registered, 4.7,4.8, and 4.9 are valid, but not 4.6 nor 4.10. + + Passing -1 for both \a versionMajor \a versionMinor will return true if any version is installed. */ bool QDeclarativeMetaType::isModule(const QByteArray &module, int versionMajor, int versionMinor) { QDeclarativeMetaTypeData *data = metaTypeData(); QDeclarativeMetaTypeData::ModuleInfoHash::Iterator it = data->modules.find(module); return it != data->modules.end() - && ((*it).vmajor > versionMajor || - ((*it).vmajor == versionMajor && (*it).vminor >= versionMinor)); + && ((versionMajor<0 && versionMinor<0) || + (((*it).vmajor_max > versionMajor || + ((*it).vmajor_max == versionMajor && (*it).vminor_max >= versionMinor)) + && ((*it).vmajor_min < versionMajor || + ((*it).vmajor_min == versionMajor && (*it).vminor_min <= versionMinor)))); } QObject *QDeclarativeMetaType::toQObject(const QVariant &v, bool *ok) diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h index 70b7c90..bf6a700 100644 --- a/src/declarative/qml/qdeclarativemetatype_p.h +++ b/src/declarative/qml/qdeclarativemetatype_p.h @@ -123,6 +123,7 @@ public: bool isCreatable() const; bool isExtendedType() const; + QString noCreationReason() const; bool isInterface() const; int typeId() const; diff --git a/src/declarative/qml/qdeclarativenetworkaccessmanagerfactory.cpp b/src/declarative/qml/qdeclarativenetworkaccessmanagerfactory.cpp index 9dd7d39..b116129 100644 --- a/src/declarative/qml/qdeclarativenetworkaccessmanagerfactory.cpp +++ b/src/declarative/qml/qdeclarativenetworkaccessmanagerfactory.cpp @@ -45,8 +45,8 @@ QT_BEGIN_NAMESPACE /*! \class QDeclarativeNetworkAccessManagerFactory - \since 4.7 - \brief The QDeclarativeNetworkAccessManagerFactory class provides a factory for QNetworkAccessManager + \since 4.7 + \brief The QDeclarativeNetworkAccessManagerFactory class provides a factory for QNetworkAccessManager for use by a Qt Declarative engine. QNetworkAccessManager is used for all network access by QML. By implementing a factory it is possible to create custom @@ -56,12 +56,17 @@ QT_BEGIN_NAMESPACE To implement a factory, subclass QDeclarativeNetworkAccessManagerFactory and implement the create() method. + To use a factory, assign it to the relevant QDeclarativeEngine using + QDeclarativeEngine::setNetworkAccessManagerFactory(). + If the created QNetworkAccessManager becomes invalid, due to a change in proxy settings, for example, call the invalidate() method. This will cause all QNetworkAccessManagers to be recreated. Note: the create() method may be called by multiple threads, so ensure the implementation of this method is reentrant. + + \sa QDeclarativeEngine::setNetworkAccessManagerFactory() */ /*! @@ -77,6 +82,8 @@ QDeclarativeNetworkAccessManagerFactory::~QDeclarativeNetworkAccessManagerFactor Implement this method to create a QNetworkAccessManager with \a parent. This allows proxies, caching and cookie support to be setup appropriately. + This method should return a new QNetworkAccessManager each time it is called. + Note: this method may be called by multiple threads, so ensure the implementation of this method is reentrant. */ diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index 5773fe6..bb5c8b7 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -59,12 +59,17 @@ Q_DECLARE_METATYPE(QScriptValue); QT_BEGIN_NAMESPACE struct ObjectData : public QScriptDeclarativeClass::Object { - ObjectData(QObject *o, int t) : object(o), type(t) {} + ObjectData(QObject *o, int t) : object(o), type(t) { + if (o) { + QDeclarativeData *ddata = QDeclarativeData::get(object, true); + if (ddata) ddata->objectDataRefCount++; + } + } virtual ~ObjectData() { if (object && !object->parent()) { QDeclarativeData *ddata = QDeclarativeData::get(object, false); - if (ddata && !ddata->indestructible) + if (ddata && !ddata->indestructible && 0 == --ddata->objectDataRefCount) object->deleteLater(); } } @@ -348,7 +353,13 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj, if (delBinding) delBinding->destroy(); - if (value.isUndefined() && lastData->flags & QDeclarativePropertyCache::Data::IsResettable) { + if (value.isNull() && lastData->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) { + QObject *o = 0; + int status = -1; + int flags = 0; + void *argv[] = { &o, 0, &status, &flags }; + QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, argv); + } else if (value.isUndefined() && lastData->flags & QDeclarativePropertyCache::Data::IsResettable) { void *a[] = { 0 }; QMetaObject::metacall(obj, QMetaObject::ResetProperty, lastData->coreIndex, a); } else if (value.isUndefined() && lastData->propType == qMetaTypeId<QVariant>()) { @@ -458,12 +469,21 @@ QStringList QDeclarativeObjectScriptClass::propertyNames(Object *object) cache = ddata->propertyCache; if (!cache) { cache = enginePrivate->cache(obj); - if (cache && ddata) { cache->addref(); ddata->propertyCache = cache; } + if (cache) { + if (ddata) { cache->addref(); ddata->propertyCache = cache; } + } else { + // Not cachable - fall back to QMetaObject (eg. dynamic meta object) + // XXX QDeclarativeOpenMetaObject has a cache, so this is suboptimal. + // XXX This is a workaround for QTBUG-9420. + const QMetaObject *mo = obj->metaObject(); + QStringList r; + int pc = mo->propertyCount(); + int po = mo->propertyOffset(); + for (int i=po; i<pc; ++i) + r += QString::fromUtf8(mo->property(i).name()); + return r; + } } - - if (!cache) - return QStringList(); - return cache->propertyNames(); } diff --git a/src/declarative/qml/qdeclarativeparser.cpp b/src/declarative/qml/qdeclarativeparser.cpp index d1f209a..b38bd76 100644 --- a/src/declarative/qml/qdeclarativeparser.cpp +++ b/src/declarative/qml/qdeclarativeparser.cpp @@ -89,8 +89,6 @@ QDeclarativeParser::Object::~Object() prop.first->release(); foreach(const DynamicProperty &prop, dynamicProperties) if (prop.defaultValue) prop.defaultValue->release(); - foreach(Object *obj, scriptBlockObjects) - obj->release(); } void Object::setBindingBit(int b) diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h index 00fc65b..0870cfb 100644 --- a/src/declarative/qml/qdeclarativeparser_p.h +++ b/src/declarative/qml/qdeclarativeparser_p.h @@ -160,8 +160,6 @@ namespace QDeclarativeParser Property *defaultProperty; QHash<QByteArray, Property *> properties; - QList<Object *> scriptBlockObjects; - // Output of the compilation phase (these properties continue to exist // in either the defaultProperty or properties members too) void addValueProperty(Property *); @@ -190,7 +188,9 @@ namespace QDeclarativeParser QList<int> lineNumbers; QList<Pragmas> pragmas; }; +#if 0 QList<ScriptBlock> scripts; +#endif // The bytes to cast instances by to get to the QDeclarativeParserStatus // interface. -1 indicates the type doesn't support this interface. diff --git a/src/declarative/qml/qdeclarativeparserstatus.cpp b/src/declarative/qml/qdeclarativeparserstatus.cpp index ec6260e..978bfb4 100644 --- a/src/declarative/qml/qdeclarativeparserstatus.cpp +++ b/src/declarative/qml/qdeclarativeparserstatus.cpp @@ -45,8 +45,36 @@ QT_BEGIN_NAMESPACE /*! \class QDeclarativeParserStatus - \since 4.7 - \brief The QDeclarativeParserStatus class provides updates on the parser state. + \since 4.7 + \brief The QDeclarativeParserStatus class provides updates on the QML parser state. + + QDeclarativeParserStatus provides a mechanism for classes instantiated by + a QDeclarativeEngine to receive notification at key points in their creation. + + This class is often used for optimization purposes, as it allows you to defer an + expensive operation until after all the properties have been set on an + object. For example, QML's \l {Text} element uses the parser status + to defer text layout until all of its properties have been set (we + don't want to layout when the \c text is assigned, and then relayout + when the \c font is assigned, and relayout again when the \c width is assigned, + and so on). + + To use QDeclarativeParserStatus, you must inherit both a QObject-derived class + and QDeclarativeParserStatus, and use the Q_INTERFACES() macro. + + \code + class MyObject : public QObject, public QDeclarativeParserStatus + { + Q_OBJECT + Q_INTERFACES(QDeclarativeParserStatus) + + public: + MyObject(QObject *parent = 0); + ... + void classBegin(); + void componentComplete(); + } + \endcode */ /*! \internal */ diff --git a/src/declarative/qml/qdeclarativeprivate.h b/src/declarative/qml/qdeclarativeprivate.h index 6e240d8..e657dd5 100644 --- a/src/declarative/qml/qdeclarativeprivate.h +++ b/src/declarative/qml/qdeclarativeprivate.h @@ -184,6 +184,7 @@ namespace QDeclarativePrivate int listId; int objectSize; void (*create)(void *); + QString noCreationReason; const char *uri; int versionMajor; diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index afd0d84..3881d0a 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -64,6 +64,7 @@ QT_BEGIN_NAMESPACE /*! \class QDeclarativeProperty +\since 4.7 \brief The QDeclarativeProperty class abstracts accessing properties on objects created from QML. As QML uses Qt's meta-type system all of the existing QMetaObject classes can be used to introspect diff --git a/src/declarative/qml/qdeclarativepropertyvaluesource.cpp b/src/declarative/qml/qdeclarativepropertyvaluesource.cpp index b106d4f..a0ed78f 100644 --- a/src/declarative/qml/qdeclarativepropertyvaluesource.cpp +++ b/src/declarative/qml/qdeclarativepropertyvaluesource.cpp @@ -47,8 +47,10 @@ QT_BEGIN_NAMESPACE /*! \class QDeclarativePropertyValueSource - \brief The QDeclarativePropertyValueSource class is inherited by property value sources such as animations and bindings. - \internal + \brief The QDeclarativePropertyValueSource class is an interface for property value sources such as animations and bindings. + + See \l{Property Value Sources} for information on writing custom property + value sources. */ /*! diff --git a/src/declarative/qml/qdeclarativeproxymetaobject.cpp b/src/declarative/qml/qdeclarativeproxymetaobject.cpp index fe0dce7..c2dce0a 100644 --- a/src/declarative/qml/qdeclarativeproxymetaobject.cpp +++ b/src/declarative/qml/qdeclarativeproxymetaobject.cpp @@ -41,17 +41,11 @@ #include "private/qdeclarativeproxymetaobject_p.h" -#include <QDebug> - QT_BEGIN_NAMESPACE QDeclarativeProxyMetaObject::QDeclarativeProxyMetaObject(QObject *obj, QList<ProxyData> *mList) : metaObjects(mList), proxies(0), parent(0), object(obj) { -#ifdef QDECLARATIVEPROXYMETAOBJECT_DEBUG - qWarning() << "QDeclarativeProxyMetaObject" << obj->metaObject()->className(); -#endif - *static_cast<QMetaObject *>(this) = *metaObjects->first().metaObject; QObjectPrivate *op = QObjectPrivate::get(obj); @@ -59,14 +53,6 @@ QDeclarativeProxyMetaObject::QDeclarativeProxyMetaObject(QObject *obj, QList<Pro parent = static_cast<QAbstractDynamicMetaObject*>(op->metaObject); op->metaObject = this; - -#ifdef QDECLARATIVEPROXYMETAOBJECT_DEBUG - const QMetaObject *mo = obj->metaObject(); - while(mo) { - qWarning() << " " << mo->className(); - mo = mo->superClass(); - } -#endif } QDeclarativeProxyMetaObject::~QDeclarativeProxyMetaObject() diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp index ac49332..e7c8a12 100644 --- a/src/declarative/qml/qdeclarativescriptparser.cpp +++ b/src/declarative/qml/qdeclarativescriptparser.cpp @@ -296,27 +296,12 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName, if (lastTypeDot >= 0) resolvableObjectType.replace(QLatin1Char('.'),QLatin1Char('/')); - bool isScript = resolvableObjectType == QLatin1String("Script"); - - if (isScript) { - if (_stateStack.isEmpty() || _stateStack.top().property) { - QDeclarativeError error; - error.setDescription(QCoreApplication::translate("QDeclarativeParser","Invalid use of Script block")); - error.setLine(typeLocation.startLine); - error.setColumn(typeLocation.startColumn); - _parser->_errors << error; - return 0; - } - } - Object *obj = new Object; - if (!isScript) { - QDeclarativeScriptParser::TypeReference *typeRef = _parser->findOrCreateType(resolvableObjectType); - obj->type = typeRef->id; + QDeclarativeScriptParser::TypeReference *typeRef = _parser->findOrCreateType(resolvableObjectType); + obj->type = typeRef->id; - typeRef->refObjects.append(obj); - } + typeRef->refObjects.append(obj); // XXX this doesn't do anything (_scope never builds up) _scope.append(resolvableObjectType); @@ -325,11 +310,7 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName, obj->location = location; - if (isScript) { - - _stateStack.top().object->scriptBlockObjects.append(obj); - - } else if (propertyCount) { + if (propertyCount) { Property *prop = currentProperty(); Value *v = new Value; @@ -535,7 +516,6 @@ bool ProcessAST::visit(AST::UiPublicMember *node) // { "time", Object::DynamicProperty::Time, "QTime" }, // { "date", Object::DynamicProperty::Date, "QDate" }, { "date", Object::DynamicProperty::DateTime, "QDateTime" }, - { "var", Object::DynamicProperty::Variant, "QVariant" }, { "variant", Object::DynamicProperty::Variant, "QVariant" } }; const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) / @@ -647,11 +627,6 @@ bool ProcessAST::visit(AST::UiPublicMember *node) property.location = location(node->firstSourceLocation(), node->lastSourceLocation()); - if (memberType == QLatin1String("var")) - qWarning().nospace() << qPrintable(_parser->_scriptFile) << ":" << property.location.start.line << ":" - << property.location.start.column << ": var type has been replaced by variant. " - << "Support will be removed entirely shortly."; - if (node->expression) { // default value property.defaultValue = new Property; property.defaultValue->parent = _stateStack.top().object; @@ -827,62 +802,29 @@ bool ProcessAST::visit(AST::UiSourceElement *node) { QDeclarativeParser::Object *obj = currentObject(); - bool isScript = (obj && obj->typeName == "Script"); - - if (!isScript) { - - if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) { + if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) { - Object::DynamicSlot slot; - slot.location = location(funDecl->firstSourceLocation(), funDecl->lastSourceLocation()); + Object::DynamicSlot slot; + slot.location = location(funDecl->firstSourceLocation(), funDecl->lastSourceLocation()); - AST::FormalParameterList *f = funDecl->formals; - while (f) { - slot.parameterNames << f->name->asString().toUtf8(); - f = f->finish(); - } - - QString body = textAt(funDecl->lbraceToken, funDecl->rbraceToken); - slot.name = funDecl->name->asString().toUtf8(); - slot.body = body; - obj->dynamicSlots << slot; - - } else { - QDeclarativeError error; - error.setDescription(QCoreApplication::translate("QDeclarativeParser","JavaScript declaration outside Script element")); - error.setLine(node->firstSourceLocation().startLine); - error.setColumn(node->firstSourceLocation().startColumn); - _parser->_errors << error; + AST::FormalParameterList *f = funDecl->formals; + while (f) { + slot.parameterNames << f->name->asString().toUtf8(); + f = f->finish(); } - return false; - - } else { - QString source; - int line = 0; - if (AST::FunctionDeclaration *funDecl = AST::cast<AST::FunctionDeclaration *>(node->sourceElement)) { - line = funDecl->functionToken.startLine; - source = asString(funDecl); - } else if (AST::VariableStatement *varStmt = AST::cast<AST::VariableStatement *>(node->sourceElement)) { - // ignore variable declarations - line = varStmt->declarationKindToken.startLine; + QString body = textAt(funDecl->lbraceToken, funDecl->rbraceToken); + slot.name = funDecl->name->asString().toUtf8(); + slot.body = body; + obj->dynamicSlots << slot; - QDeclarativeError error; - error.setDescription(QCoreApplication::translate("QDeclarativeParser", "Variable declarations not allow in inline Script blocks")); - error.setLine(node->firstSourceLocation().startLine); - error.setColumn(node->firstSourceLocation().startColumn); - _parser->_errors << error; - return false; - } - - Value *value = new Value; - value->location = location(node->firstSourceLocation(), - node->lastSourceLocation()); - value->value = QDeclarativeParser::Variant(source); - - obj->getDefaultProperty()->addValue(value); + } else { + QDeclarativeError error; + error.setDescription(QCoreApplication::translate("QDeclarativeParser","JavaScript declaration outside Script element")); + error.setLine(node->firstSourceLocation().startLine); + error.setColumn(node->firstSourceLocation().startColumn); + _parser->_errors << error; } - return false; } diff --git a/src/declarative/qml/qdeclarativescriptstring.cpp b/src/declarative/qml/qdeclarativescriptstring.cpp index 5b9afe9..8f717d1 100644 --- a/src/declarative/qml/qdeclarativescriptstring.cpp +++ b/src/declarative/qml/qdeclarativescriptstring.cpp @@ -55,24 +55,35 @@ public: /*! \class QDeclarativeScriptString - \since 4.7 +\since 4.7 \brief The QDeclarativeScriptString class encapsulates a script and its context. -The QDeclarativeScriptString is used by properties that want to accept a script "assignment" from QML. +QDeclarativeScriptString is used to create QObject properties that accept a script "assignment" from QML. -Normally, the following code would result in a binding being established for the \c script -property. If the property had a type of QDeclarativeScriptString, the script - \e {console.log(1921)} - itself -would be passed to the property and it could choose how to handle it. +Normally, the following QML would result in a binding being established for the \c script +property; i.e. \c script would be assigned the value obtained from running \c {myObj.value = Math.max(myValue, 100)} -\code +\qml MyType { - script: console.log(1921) + script: myObj.value = Math.max(myValue, 100) } +\endqml + +If instead the property had a type of QDeclarativeScriptString, +the script itself -- \e {myObj.value = Math.max(myValue, 100)} -- would be passed to the \c script property +and the class could choose how to handle it. Typically, the class will evaluate +the script at some later time using a QDeclarativeExpression. + +\code +QDeclarativeExpression expr(scriptString.context(), scriptString.script(), scriptStr.scopeObject()); +expr.value(); \endcode + +\sa QDeclarativeExpression */ /*! -Construct an empty instance. +Constructs an empty instance. */ QDeclarativeScriptString::QDeclarativeScriptString() : d(new QDeclarativeScriptStringPrivate) @@ -80,7 +91,7 @@ QDeclarativeScriptString::QDeclarativeScriptString() } /*! -Copy \a other. +Copies \a other. */ QDeclarativeScriptString::QDeclarativeScriptString(const QDeclarativeScriptString &other) : d(other.d) @@ -95,7 +106,7 @@ QDeclarativeScriptString::~QDeclarativeScriptString() } /*! -Assign \a other to this. +Assigns \a other to this. */ QDeclarativeScriptString &QDeclarativeScriptString::operator=(const QDeclarativeScriptString &other) { @@ -104,7 +115,7 @@ QDeclarativeScriptString &QDeclarativeScriptString::operator=(const QDeclarative } /*! -Return the context for the script. +Returns the context for the script. */ QDeclarativeContext *QDeclarativeScriptString::context() const { diff --git a/src/declarative/qml/qdeclarativetypenotavailable.cpp b/src/declarative/qml/qdeclarativetypenotavailable.cpp new file mode 100644 index 0000000..7a84732 --- /dev/null +++ b/src/declarative/qml/qdeclarativetypenotavailable.cpp @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativetypenotavailable_p.h" + +int qmlRegisterTypeNotAvailable(const char *uri, int versionMajor, int versionMinor, const char *qmlName, const QString& message) +{ + return qmlRegisterUncreatableType<QDeclarativeTypeNotAvailable>(uri,versionMajor,versionMinor,qmlName,message); +} + +QDeclarativeTypeNotAvailable::QDeclarativeTypeNotAvailable() { } diff --git a/src/declarative/graphicsitems/qdeclarativeeffects_p.h b/src/declarative/qml/qdeclarativetypenotavailable_p.h index 0de5854..9c1c256 100644 --- a/src/declarative/graphicsitems/qdeclarativeeffects_p.h +++ b/src/declarative/qml/qdeclarativetypenotavailable_p.h @@ -39,29 +39,27 @@ ** ****************************************************************************/ -#ifndef QDECLARATIVEEFFECTS_P_H -#define QDECLARATIVEEFFECTS_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// +#ifndef QDECLARATIVETYPENOTAVAILABLE_H +#define QDECLARATIVETYPENOTAVAILABLE_H #include <qdeclarative.h> -#include <QtGui/qgraphicseffect.h> -#ifndef QT_NO_GRAPHICSEFFECT -QML_DECLARE_TYPE(QGraphicsEffect) -QML_DECLARE_TYPE(QGraphicsBlurEffect) -QML_DECLARE_TYPE(QGraphicsColorizeEffect) -QML_DECLARE_TYPE(QGraphicsDropShadowEffect) -QML_DECLARE_TYPE(QGraphicsOpacityEffect) -#endif +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeTypeNotAvailable : public QObject { + Q_OBJECT +public: + QDeclarativeTypeNotAvailable(); +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeTypeNotAvailable) + +QT_END_HEADER -#endif // QDECLARATIVEEFFECTS_P_H +#endif // QDECLARATIVETYPENOTAVAILABLE_H diff --git a/src/declarative/qml/qdeclarativevaluetype.cpp b/src/declarative/qml/qdeclarativevaluetype.cpp index 352a6c0..c6fe161 100644 --- a/src/declarative/qml/qdeclarativevaluetype.cpp +++ b/src/declarative/qml/qdeclarativevaluetype.cpp @@ -55,13 +55,15 @@ int qmlRegisterValueTypeEnums(const char *qmlName) QByteArray pointerName(name + '*'); QDeclarativePrivate::RegisterType type = { - 0, + 0, qRegisterMetaType<T *>(pointerName.constData()), 0, 0, 0, - "Qt", 4, 6, qmlName, &T::staticMetaObject, + QString(), - 0, 0, + "Qt", 4, 7, qmlName, &T::staticMetaObject, + + 0, 0, 0, 0, 0, @@ -712,7 +714,7 @@ int QDeclarativeFontValueType::pixelSize() const void QDeclarativeFontValueType::setPixelSize(int size) { - if (size >=0) { + if (size >0) { if (pointSizeSet) qWarning() << "Both point size and pixel size set. Using pixel size."; font.setPixelSize(size); diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index fdcbeee..57bf726 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -623,13 +623,6 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, } break; - case QDeclarativeInstruction::StoreScript: - { - QObject *target = stack.top(); - ctxt->addScript(scripts.at(instr.storeScript.value), target); - } - break; - case QDeclarativeInstruction::StoreImportedScript: { ctxt->addImportedScript(scripts.at(instr.storeScript.value)); diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp index c4d47b3..45f04a0 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject.cpp +++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp @@ -86,7 +86,6 @@ public: inline void setValue(const QDate &); inline void setValue(const QDateTime &); inline void setValue(const QScriptValue &); - private: int type; void *data[4]; // Large enough to hold all types @@ -112,6 +111,9 @@ void QDeclarativeVMEVariant::cleanup() type == QMetaType::Bool || type == QMetaType::Double) { type = QVariant::Invalid; + } else if (type == QMetaType::QObjectStar) { + ((QDeclarativeGuard<QObject>*)dataPtr())->~QDeclarativeGuard<QObject>(); + type = QVariant::Invalid; } else if (type == QMetaType::QString) { ((QString *)dataPtr())->~QString(); type = QVariant::Invalid; @@ -160,7 +162,7 @@ QObject *QDeclarativeVMEVariant::asQObject() if (type != QMetaType::QObjectStar) setValue((QObject *)0); - return *(QObject **)(dataPtr()); + return *(QDeclarativeGuard<QObject> *)(dataPtr()); } const QVariant &QDeclarativeVMEVariant::asQVariant() @@ -256,8 +258,9 @@ void QDeclarativeVMEVariant::setValue(QObject *v) if (type != QMetaType::QObjectStar) { cleanup(); type = QMetaType::QObjectStar; + new (dataPtr()) QDeclarativeGuard<QObject>(); } - *(QObject **)(dataPtr()) = v; + *(QDeclarativeGuard<QObject>*)(dataPtr()) = v; } void QDeclarativeVMEVariant::setValue(const QVariant &v) @@ -465,8 +468,7 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) if (c == QMetaObject::ReadProperty) { *reinterpret_cast<QVariant *>(a[0]) = readVarPropertyAsVariant(id); } else if (c == QMetaObject::WriteProperty) { - needActivate = (data[id].asQVariant() != *reinterpret_cast<QVariant *>(a[0])); - data[id].setValue(*reinterpret_cast<QVariant *>(a[0])); + writeVarProperty(id, *reinterpret_cast<QVariant *>(a[0])); } } else { @@ -682,6 +684,8 @@ QScriptValue QDeclarativeVMEMetaObject::readVarProperty(int id) { if (data[id].dataType() == qMetaTypeId<QScriptValue>()) return data[id].asQScriptValue(); + else if (data[id].dataType() == QMetaType::QObjectStar) + return QDeclarativeEnginePrivate::get(ctxt->engine)->objectClass->newQObject(data[id].asQObject()); else return QDeclarativeEnginePrivate::get(ctxt->engine)->scriptValueFromVariant(data[id].asQVariant()); } @@ -690,7 +694,9 @@ QVariant QDeclarativeVMEMetaObject::readVarPropertyAsVariant(int id) { if (data[id].dataType() == qMetaTypeId<QScriptValue>()) return QDeclarativeEnginePrivate::get(ctxt->engine)->scriptValueToVariant(data[id].asQScriptValue()); - else + else if (data[id].dataType() == QMetaType::QObjectStar) + return QVariant::fromValue(data[id].asQObject()); + else return data[id].asQVariant(); } @@ -700,6 +706,15 @@ void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QScriptValue &val activate(object, methodOffset + id, 0); } +void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QVariant &value) +{ + if (value.userType() == QMetaType::QObjectStar) + data[id].setValue(qvariant_cast<QObject *>(value)); + else + data[id].setValue(value); + activate(object, methodOffset + id, 0); +} + void QDeclarativeVMEMetaObject::listChanged(int id) { activate(object, methodOffset + id, 0); diff --git a/src/declarative/qml/qdeclarativevmemetaobject_p.h b/src/declarative/qml/qdeclarativevmemetaobject_p.h index 76390c9..4fc3269 100644 --- a/src/declarative/qml/qdeclarativevmemetaobject_p.h +++ b/src/declarative/qml/qdeclarativevmemetaobject_p.h @@ -148,6 +148,7 @@ private: QScriptValue readVarProperty(int); QVariant readVarPropertyAsVariant(int); void writeVarProperty(int, const QScriptValue &); + void writeVarProperty(int, const QVariant &); QAbstractDynamicMetaObject *parent; diff --git a/src/declarative/qml/qdeclarativewatcher.cpp b/src/declarative/qml/qdeclarativewatcher.cpp index 9ea84b8..842b3c4 100644 --- a/src/declarative/qml/qdeclarativewatcher.cpp +++ b/src/declarative/qml/qdeclarativewatcher.cpp @@ -110,7 +110,7 @@ void QDeclarativeWatchProxy::notifyValueChanged() { QVariant v; if (m_expr) - v = m_expr->value(); + v = m_expr->evaluate(); else v = m_property.read(m_object); diff --git a/src/declarative/qml/qdeclarativexmlhttprequest.cpp b/src/declarative/qml/qdeclarativexmlhttprequest.cpp index be2a1a7..b7e1832 100644 --- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp +++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp @@ -1305,7 +1305,7 @@ void QDeclarativeXMLHttpRequest::printError(const QScriptValue& sv) { QDeclarativeError error; QDeclarativeExpressionPrivate::exceptionToError(sv.engine(), error); - qWarning().nospace() << qPrintable(error.toString()); + QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate::get(sv.engine()), error); } void QDeclarativeXMLHttpRequest::destroyNetwork() diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index c48662c..3848593 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -40,6 +40,7 @@ SOURCES += \ $$PWD/qdeclarativepropertycache.cpp \ $$PWD/qdeclarativenotifier.cpp \ $$PWD/qdeclarativeintegercache.cpp \ + $$PWD/qdeclarativetypenotavailable.cpp \ $$PWD/qdeclarativetypenamecache.cpp \ $$PWD/qdeclarativescriptstring.cpp \ $$PWD/qdeclarativeobjectscriptclass.cpp \ @@ -112,6 +113,7 @@ HEADERS += \ $$PWD/qdeclarativepropertycache_p.h \ $$PWD/qdeclarativenotifier_p.h \ $$PWD/qdeclarativeintegercache_p.h \ + $$PWD/qdeclarativetypenotavailable_p.h \ $$PWD/qdeclarativetypenamecache_p.h \ $$PWD/qdeclarativescriptstring.h \ $$PWD/qdeclarativeobjectscriptclass_p.h \ diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index f38f66c..4059522 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -185,7 +185,7 @@ void QDeclarativeAbstractAnimation::setRunning(bool r) return; if (d->group || d->disableUserControl) { - qWarning("QDeclarativeAbstractAnimation: setRunning() cannot be used on non-root animation nodes"); + qmlInfo(this) << "setRunning() cannot be used on non-root animation nodes."; return; } @@ -245,7 +245,7 @@ void QDeclarativeAbstractAnimation::setPaused(bool p) return; if (d->group || d->disableUserControl) { - qWarning("QDeclarativeAbstractAnimation: setPaused() cannot be used on non-root animation nodes"); + qmlInfo(this) << "setPaused() cannot be used on non-root animation nodes."; return; } @@ -780,9 +780,9 @@ void QDeclarativeScriptActionPrivate::execute() QDeclarativeData *ddata = QDeclarativeData::get(q); if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) expr.setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber); - expr.value(); - if (expr.hasError()) - qWarning() << expr.error(); + expr.evaluate(); + if (expr.hasError()) + qmlInfo(q) << expr.error(); } } @@ -1318,7 +1318,7 @@ void QDeclarativeRotationAnimation::setTo(qreal t) } /*! - \qmlproperty enum RotationAnimation::direction + \qmlproperty enumeration RotationAnimation::direction The direction in which to rotate. Possible values are Numerical, Clockwise, Counterclockwise, or Shortest. @@ -1676,7 +1676,7 @@ void QDeclarativePropertyAnimationPrivate::init() /*! \qmlproperty int PropertyAnimation::duration - This property holds the duration of the transition, in milliseconds. + This property holds the duration of the animation, in milliseconds. The default value is 250. */ @@ -1743,14 +1743,15 @@ void QDeclarativePropertyAnimation::setTo(const QVariant &t) } /*! - \qmlproperty enum PropertyAnimation::easing.type + \qmlproperty enumeration PropertyAnimation::easing.type \qmlproperty real PropertyAnimation::easing.amplitude \qmlproperty real PropertyAnimation::easing.overshoot \qmlproperty real PropertyAnimation::easing.period \brief the easing curve used for the animation. To specify an easing curve you need to specify at least the type. For some curves you can also specify - amplitude, period and/or overshoot (more details provided after the table). + amplitude, period and/or overshoot (more details provided after the table). The default easing curve is + Linear. \qml PropertyAnimation { properties: "y"; easing.type: "InOutElastic"; easing.amplitude: 2.0; easing.period: 1.5 } @@ -2691,6 +2692,67 @@ QDeclarativeListProperty<QDeclarativeItem> QDeclarativeAnchorAnimation::targets( return QDeclarativeListProperty<QDeclarativeItem>(this, d->targets); } +/*! + \qmlproperty int AnchorAnimation::duration + This property holds the duration of the animation, in milliseconds. + + The default value is 250. +*/ +int QDeclarativeAnchorAnimation::duration() const +{ + Q_D(const QDeclarativeAnchorAnimation); + return d->va->duration(); +} + +void QDeclarativeAnchorAnimation::setDuration(int duration) +{ + if (duration < 0) { + qmlInfo(this) << tr("Cannot set a duration of < 0"); + return; + } + + Q_D(QDeclarativeAnchorAnimation); + if (d->va->duration() == duration) + return; + d->va->setDuration(duration); + emit durationChanged(duration); +} + +/*! + \qmlproperty enumeration AnchorAnimation::easing.type + \qmlproperty real AnchorAnimation::easing.amplitude + \qmlproperty real AnchorAnimation::easing.overshoot + \qmlproperty real AnchorAnimation::easing.period + \brief the easing curve used for the animation. + + To specify an easing curve you need to specify at least the type. For some curves you can also specify + amplitude, period and/or overshoot. The default easing curve is + Linear. + + \qml + AnchorAnimation { easing.type: "InOutQuad" } + \endqml + + See the \l{PropertyAnimation::easing.type} documentation for information + about the different types of easing curves. +*/ + +QEasingCurve QDeclarativeAnchorAnimation::easing() const +{ + Q_D(const QDeclarativeAnchorAnimation); + return d->va->easingCurve(); +} + +void QDeclarativeAnchorAnimation::setEasing(const QEasingCurve &e) +{ + Q_D(QDeclarativeAnchorAnimation); + if (d->va->easingCurve() == e) + return; + + d->va->setEasingCurve(e); + emit easingChanged(e); +} + void QDeclarativeAnchorAnimation::transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, TransitionDirection direction) diff --git a/src/declarative/util/qdeclarativeanimation_p.h b/src/declarative/util/qdeclarativeanimation_p.h index c839c2c..40c893c 100644 --- a/src/declarative/util/qdeclarativeanimation_p.h +++ b/src/declarative/util/qdeclarativeanimation_p.h @@ -475,6 +475,8 @@ class QDeclarativeAnchorAnimation : public QDeclarativeAbstractAnimation Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeAnchorAnimation) Q_PROPERTY(QDeclarativeListProperty<QDeclarativeItem> targets READ targets) + Q_PROPERTY(int duration READ duration WRITE setDuration NOTIFY durationChanged) + Q_PROPERTY(QEasingCurve easing READ easing WRITE setEasing NOTIFY easingChanged) public: QDeclarativeAnchorAnimation(QObject *parent=0); @@ -482,6 +484,16 @@ public: QDeclarativeListProperty<QDeclarativeItem> targets(); + int duration() const; + void setDuration(int); + + QEasingCurve easing() const; + void setEasing(const QEasingCurve &); + +Q_SIGNALS: + void durationChanged(int); + void easingChanged(const QEasingCurve&); + protected: virtual void transition(QDeclarativeStateActions &actions, QDeclarativeProperties &modified, diff --git a/src/declarative/util/qdeclarativeconnections.cpp b/src/declarative/util/qdeclarativeconnections.cpp index c392c74..20d878b 100644 --- a/src/declarative/util/qdeclarativeconnections.cpp +++ b/src/declarative/util/qdeclarativeconnections.cpp @@ -152,8 +152,14 @@ void QDeclarativeConnections::setTarget(QObject *obj) Q_D(QDeclarativeConnections); if (d->target == obj) return; - foreach (QDeclarativeBoundSignal *s, d->boundsignals) - delete s; + foreach (QDeclarativeBoundSignal *s, d->boundsignals) { + // It is possible that target is being changed due to one of our signal + // handlers -> use deleteLater(). + if (s->isEvaluating()) + s->deleteLater(); + else + delete s; + } d->boundsignals.clear(); d->target = obj; connectSignals(); diff --git a/src/declarative/util/qdeclarativefontloader.cpp b/src/declarative/util/qdeclarativefontloader.cpp index b577b81..4115193 100644 --- a/src/declarative/util/qdeclarativefontloader.cpp +++ b/src/declarative/util/qdeclarativefontloader.cpp @@ -53,6 +53,7 @@ #include <QFontDatabase> #include <private/qobject_p.h> +#include <qdeclarativeinfo.h> QT_BEGIN_NAMESPACE @@ -136,7 +137,7 @@ void QDeclarativeFontLoader::setSource(const QUrl &url) d->status = QDeclarativeFontLoader::Ready; } else { d->status = QDeclarativeFontLoader::Error; - qWarning() << "Cannot load font:" << url; + qmlInfo(this) << "Cannot load font: \"" << url.toString() << "\""; } emit statusChanged(); } else @@ -181,7 +182,7 @@ void QDeclarativeFontLoader::setName(const QString &name) } /*! - \qmlproperty enum FontLoader::status + \qmlproperty enumeration FontLoader::status This property holds the status of font loading. It can be one of: \list @@ -231,7 +232,7 @@ void QDeclarativeFontLoader::replyFinished() d->addFontToDatabase(ba); } else { d->status = Error; - qWarning() << "Cannot load font:" << d->reply->url(); + qmlInfo(this) << "Cannot load font: \"" << d->reply->url().toString() << "\""; emit statusChanged(); } d->reply->deleteLater(); @@ -250,7 +251,7 @@ void QDeclarativeFontLoaderPrivate::addFontToDatabase(const QByteArray &ba) status = QDeclarativeFontLoader::Ready; } else { status = QDeclarativeFontLoader::Error; - qWarning() << "Cannot load font:" << url; + qmlInfo(q) << "Cannot load font: \"" << url.toString() << "\""; } emit q->statusChanged(); } diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 0c2c2a4..3810256 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -1187,10 +1187,9 @@ QScriptValue NestedListModel::get(int index) const if (!node) return 0; QDeclarativeEngine *eng = qmlEngine(m_listModel); - if (!eng) { - qWarning("Cannot call QDeclarativeListModel::get() without a QDeclarativeEngine"); + if (!eng) return 0; - } + return QDeclarativeEnginePrivate::qmlScriptObject(node->object(this), eng); } diff --git a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp index d91b107..534c923 100644 --- a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp +++ b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp @@ -202,10 +202,9 @@ bool QDeclarativeListModelWorkerAgent::event(QEvent *e) FlatListModel *orig = m_orig->m_flat; FlatListModel *copy = s->list->m_flat; - if (!orig || !copy) { - qWarning("QML ListModel worker: sync() failed"); + if (!orig || !copy) return QObject::event(e); - } + orig->m_roles = copy->m_roles; orig->m_strings = copy->m_strings; orig->m_values = copy->m_values; diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp index 81b83c3..ab50bb1 100644 --- a/src/declarative/util/qdeclarativepropertychanges.cpp +++ b/src/declarative/util/qdeclarativepropertychanges.cpp @@ -159,12 +159,12 @@ public: QDeclarativeExpression *rewindExpression; QDeclarativeGuard<QDeclarativeExpression> ownedExpression; - virtual void execute() { + virtual void execute(Reason) { ownedExpression = QDeclarativePropertyPrivate::setSignalExpression(property, expression); } virtual bool isReversable() { return true; } - virtual void reverse() { + virtual void reverse(Reason) { ownedExpression = QDeclarativePropertyPrivate::setSignalExpression(property, reverseExpression); } @@ -434,7 +434,7 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions() a.specifiedProperty = QString::fromUtf8(property); if (d->isExplicit) { - a.toValue = d->expressions.at(ii).second->value(); + a.toValue = d->expressions.at(ii).second->evaluate(); } else { QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->expressions.at(ii).second->expression(), object(), qmlContext(this)); diff --git a/src/declarative/util/qdeclarativepropertymap.cpp b/src/declarative/util/qdeclarativepropertymap.cpp index 0e477b1..919727f 100644 --- a/src/declarative/util/qdeclarativepropertymap.cpp +++ b/src/declarative/util/qdeclarativepropertymap.cpp @@ -98,7 +98,7 @@ void QDeclarativePropertyMapMetaObject::propertyCreated(int, QMetaPropertyBuilde /*! \class QDeclarativePropertyMap \since 4.7 - \brief The QDeclarativePropertyMap class allows you to set key-value pairs that can be used in bindings. + \brief The QDeclarativePropertyMap class allows you to set key-value pairs that can be used in QML bindings. QDeclarativePropertyMap provides a convenient way to expose domain data to the UI layer. The following example shows how you might declare data in C++ and then @@ -112,7 +112,7 @@ void QDeclarativePropertyMapMetaObject::propertyCreated(int, QMetaPropertyBuilde ownerData.insert("phone", QVariant(QString("555-5555"))); //expose it to the UI layer - QDeclarativeContext *ctxt = view->bindContext(); + QDeclarativeContext *ctxt = view->rootContext(); ctxt->setProperty("owner", &data); \endcode @@ -265,7 +265,7 @@ QVariant &QDeclarativePropertyMap::operator[](const QString &key) Same as value(). */ -const QVariant QDeclarativePropertyMap::operator[](const QString &key) const +QVariant QDeclarativePropertyMap::operator[](const QString &key) const { return value(key); } diff --git a/src/declarative/util/qdeclarativepropertymap.h b/src/declarative/util/qdeclarativepropertymap.h index e0b7ce3..1b6594b 100644 --- a/src/declarative/util/qdeclarativepropertymap.h +++ b/src/declarative/util/qdeclarativepropertymap.h @@ -73,7 +73,7 @@ public: bool contains(const QString &key) const; QVariant &operator[](const QString &key); - const QVariant operator[](const QString &key) const; + QVariant operator[](const QString &key) const; Q_SIGNALS: void valueChanged(const QString &key, const QVariant &value); diff --git a/src/declarative/util/qdeclarativesmoothedanimation.cpp b/src/declarative/util/qdeclarativesmoothedanimation.cpp index 48a7583..19a00ee 100644 --- a/src/declarative/util/qdeclarativesmoothedanimation.cpp +++ b/src/declarative/util/qdeclarativesmoothedanimation.cpp @@ -438,7 +438,7 @@ qreal QDeclarativeSmoothedAnimation::velocity() const } /*! - \qmlproperty qreal SmoothedAnimation::velocity + \qmlproperty real SmoothedAnimation::velocity This property holds the average velocity allowed when tracking the 'to' value. @@ -457,7 +457,7 @@ void QDeclarativeSmoothedAnimation::setVelocity(qreal v) } /*! - \qmlproperty qreal SmoothedAnimation::maximumEasingTime + \qmlproperty int SmoothedAnimation::maximumEasingTime This property specifies the maximum time, in msecs, an "eases" during the follow should take. Setting this property causes the velocity to "level out" after at a time. Setting diff --git a/src/declarative/util/qdeclarativesmoothedfollow.cpp b/src/declarative/util/qdeclarativesmoothedfollow.cpp index 9f155fc..3ed9257 100644 --- a/src/declarative/util/qdeclarativesmoothedfollow.cpp +++ b/src/declarative/util/qdeclarativesmoothedfollow.cpp @@ -195,7 +195,7 @@ qreal QDeclarativeSmoothedFollow::velocity() const } /*! - \qmlproperty qreal SmoothedFollow::velocity + \qmlproperty real SmoothedFollow::velocity This property holds the average velocity allowed when tracking the 'to' value. @@ -214,7 +214,7 @@ void QDeclarativeSmoothedFollow::setVelocity(qreal v) } /*! - \qmlproperty qreal SmoothedFollow::maximumEasingTime + \qmlproperty int SmoothedFollow::maximumEasingTime This property specifies the maximum time, in msecs, an "eases" during the follow should take. Setting this property causes the velocity to "level out" after at a time. Setting diff --git a/src/declarative/util/qdeclarativespringfollow.cpp b/src/declarative/util/qdeclarativespringfollow.cpp index 7921735..70077f3 100644 --- a/src/declarative/util/qdeclarativespringfollow.cpp +++ b/src/declarative/util/qdeclarativespringfollow.cpp @@ -267,7 +267,7 @@ qreal QDeclarativeSpringFollow::to() const } /*! - \qmlproperty qreal SpringFollow::to + \qmlproperty real SpringFollow::to This property holds the target value which will be tracked. Bind to a property in order to track its changes. @@ -284,7 +284,7 @@ void QDeclarativeSpringFollow::setTo(qreal value) } /*! - \qmlproperty qreal SpringFollow::velocity + \qmlproperty real SpringFollow::velocity This property holds the maximum velocity allowed when tracking the source. */ @@ -303,7 +303,7 @@ void QDeclarativeSpringFollow::setVelocity(qreal velocity) } /*! - \qmlproperty qreal SpringFollow::spring + \qmlproperty real SpringFollow::spring This property holds the spring constant The spring constant describes how strongly the target is pulled towards the @@ -326,7 +326,7 @@ void QDeclarativeSpringFollow::setSpring(qreal spring) } /*! - \qmlproperty qreal SpringFollow::damping + \qmlproperty real SpringFollow::damping This property holds the spring damping constant The damping constant describes how quickly a sprung follower comes to rest. @@ -349,7 +349,7 @@ void QDeclarativeSpringFollow::setDamping(qreal damping) /*! - \qmlproperty qreal SpringFollow::epsilon + \qmlproperty real SpringFollow::epsilon This property holds the spring epsilon The epsilon is the rate and amount of change in the value which is close enough @@ -371,7 +371,7 @@ void QDeclarativeSpringFollow::setEpsilon(qreal epsilon) } /*! - \qmlproperty qreal SpringFollow::modulus + \qmlproperty real SpringFollow::modulus This property holds the modulus value. Setting a \a modulus forces the target value to "wrap around" at the modulus. @@ -394,7 +394,7 @@ void QDeclarativeSpringFollow::setModulus(qreal modulus) } /*! - \qmlproperty qreal SpringFollow::mass + \qmlproperty real SpringFollow::mass This property holds the "mass" of the property being moved. mass is 1.0 by default. Setting a different mass changes the dynamics of @@ -452,7 +452,7 @@ bool QDeclarativeSpringFollow::inSync() const } /*! - \qmlproperty qreal SpringFollow::value + \qmlproperty real SpringFollow::value The current value. */ qreal QDeclarativeSpringFollow::value() const diff --git a/src/declarative/util/qdeclarativestate.cpp b/src/declarative/util/qdeclarativestate.cpp index d27fc51..861cbc8 100644 --- a/src/declarative/util/qdeclarativestate.cpp +++ b/src/declarative/util/qdeclarativestate.cpp @@ -95,7 +95,7 @@ QString QDeclarativeActionEvent::typeName() const return QString(); } -void QDeclarativeActionEvent::execute() +void QDeclarativeActionEvent::execute(Reason) { } @@ -104,7 +104,7 @@ bool QDeclarativeActionEvent::isReversable() return false; } -void QDeclarativeActionEvent::reverse() +void QDeclarativeActionEvent::reverse(Reason) { } diff --git a/src/declarative/util/qdeclarativestate_p.h b/src/declarative/util/qdeclarativestate_p.h index 472897e..0ba67b0 100644 --- a/src/declarative/util/qdeclarativestate_p.h +++ b/src/declarative/util/qdeclarativestate_p.h @@ -90,9 +90,11 @@ public: virtual ~QDeclarativeActionEvent(); virtual QString typeName() const; - virtual void execute(); + enum Reason { ActualChange, FastForward }; + + virtual void execute(Reason reason = ActualChange); virtual bool isReversable(); - virtual void reverse(); + virtual void reverse(Reason reason = ActualChange); virtual void saveOriginals() {} virtual void copyOriginals(QDeclarativeActionEvent *) {} diff --git a/src/declarative/util/qdeclarativestategroup.cpp b/src/declarative/util/qdeclarativestategroup.cpp index 79bc677..5b51495 100644 --- a/src/declarative/util/qdeclarativestategroup.cpp +++ b/src/declarative/util/qdeclarativestategroup.cpp @@ -50,6 +50,7 @@ #include <QtCore/qdebug.h> #include <private/qobject_p.h> +#include <qdeclarativeinfo.h> QT_BEGIN_NAMESPACE @@ -287,7 +288,7 @@ bool QDeclarativeStateGroupPrivate::updateAutoState() QDeclarativeState *state = states.at(ii); if (state->isWhenKnown()) { if (!state->name().isEmpty()) { - if (state->when() && state->when()->value().toBool()) { + if (state->when() && state->when()->evaluate().toBool()) { if (stateChangeDebug()) qWarning() << "Setting auto state due to:" << state->when()->expression(); @@ -381,7 +382,7 @@ void QDeclarativeStateGroupPrivate::setCurrentStateInternal(const QString &state } if (applyingState) { - qWarning() << "Can't apply a state change as part of a state definition."; + qmlInfo(q) << "Can't apply a state change as part of a state definition."; return; } diff --git a/src/declarative/util/qdeclarativestateoperations.cpp b/src/declarative/util/qdeclarativestateoperations.cpp index 3854b10..9049b83 100644 --- a/src/declarative/util/qdeclarativestateoperations.cpp +++ b/src/declarative/util/qdeclarativestateoperations.cpp @@ -50,6 +50,8 @@ #include <qdeclarativeguard_p.h> #include <qdeclarativenullablevalue_p_p.h> #include "private/qdeclarativecontext_p.h" +#include "private/qdeclarativeproperty_p.h" +#include "private/qdeclarativebinding_p.h" #include <QtCore/qdebug.h> #include <QtGui/qgraphicsitem.h> @@ -86,7 +88,6 @@ public: void QDeclarativeParentChangePrivate::doChange(QDeclarativeItem *targetParent, QDeclarativeItem *stackBefore) { if (targetParent && target && target->parentItem()) { - //### for backwards direction, can we just restore original x, y, scale, rotation Q_Q(QDeclarativeParentChange); bool ok; const QTransform &transform = target->parentItem()->itemTransform(targetParent, &ok); @@ -123,6 +124,10 @@ void QDeclarativeParentChangePrivate::doChange(QDeclarativeItem *targetParent, Q const QPointF &point = transform.map(QPointF(target->x(),target->y())); qreal x = point.x(); qreal y = point.y(); + + // setParentItem will update the transformOriginPoint if needed + target->setParentItem(targetParent); + if (ok && target->transformOrigin() != QDeclarativeItem::TopLeft) { qreal tempxt = target->transformOriginPoint().x(); qreal tempyt = target->transformOriginPoint().y(); @@ -136,7 +141,6 @@ void QDeclarativeParentChangePrivate::doChange(QDeclarativeItem *targetParent, Q y += offset.y(); } - target->setParentItem(targetParent); if (ok) { //qDebug() << x << y << rotation << scale; target->setX(x); @@ -415,7 +419,7 @@ void QDeclarativeParentChange::copyOriginals(QDeclarativeActionEvent *other) saveCurrentValues(); } -void QDeclarativeParentChange::execute() +void QDeclarativeParentChange::execute(Reason) { Q_D(QDeclarativeParentChange); d->doChange(d->parent); @@ -426,7 +430,7 @@ bool QDeclarativeParentChange::isReversable() return true; } -void QDeclarativeParentChange::reverse() +void QDeclarativeParentChange::reverse(Reason) { Q_D(QDeclarativeParentChange); d->doChange(d->origParent, d->origStackBefore); @@ -566,7 +570,7 @@ void QDeclarativeStateChangeScript::setName(const QString &n) d->name = n; } -void QDeclarativeStateChangeScript::execute() +void QDeclarativeStateChangeScript::execute(Reason) { Q_D(QDeclarativeStateChangeScript); const QString &script = d->script.script(); @@ -575,9 +579,9 @@ void QDeclarativeStateChangeScript::execute() QDeclarativeData *ddata = QDeclarativeData::get(this); if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) expr.setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber); - expr.value(); + expr.evaluate(); if (expr.hasError()) - qWarning() << expr.error(); + qmlInfo(this, expr.error()); } } @@ -601,15 +605,22 @@ QString QDeclarativeStateChangeScript::typeName() const In the following example we change the top and bottom anchors of an item: \qml - AnchorChanges { - target: content; top: window.top; bottom: window.bottom + State { + name: "reanchored" + AnchorChanges { + target: content; + anchors.top: window.top; + anchors.bottom: window.bottom + } } \endqml AnchorChanges can be animated using AnchorAnimation. \qml //animate our anchor changes - AnchorAnimation {} + Transition { + AnchorAnimation {} + } \endqml For more information on anchors see \l {anchor-layout}{Anchor Layouts}. @@ -620,26 +631,25 @@ class QDeclarativeAnchorSetPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QDeclarativeAnchorSet) public: QDeclarativeAnchorSetPrivate() - : usedAnchors(0), fill(0), + : usedAnchors(0), resetAnchors(0), fill(0), centerIn(0)/*, leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0), margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0)*/ { } - QDeclarativeAnchors::UsedAnchors usedAnchors; - //### change to QDeclarativeAnchors::UsedAnchors resetAnchors - QStringList resetList; + QDeclarativeAnchors::Anchors usedAnchors; + QDeclarativeAnchors::Anchors resetAnchors; QDeclarativeItem *fill; QDeclarativeItem *centerIn; - QDeclarativeAnchorLine left; - QDeclarativeAnchorLine right; - QDeclarativeAnchorLine top; - QDeclarativeAnchorLine bottom; - QDeclarativeAnchorLine vCenter; - QDeclarativeAnchorLine hCenter; - QDeclarativeAnchorLine baseline; + QDeclarativeScriptString leftScript; + QDeclarativeScriptString rightScript; + QDeclarativeScriptString topScript; + QDeclarativeScriptString bottomScript; + QDeclarativeScriptString hCenterScript; + QDeclarativeScriptString vCenterScript; + QDeclarativeScriptString baselineScript; /*qreal leftMargin; qreal rightMargin; @@ -660,151 +670,165 @@ QDeclarativeAnchorSet::~QDeclarativeAnchorSet() { } -QDeclarativeAnchorLine QDeclarativeAnchorSet::top() const +QDeclarativeScriptString QDeclarativeAnchorSet::top() const { Q_D(const QDeclarativeAnchorSet); - return d->top; + return d->topScript; } -void QDeclarativeAnchorSet::setTop(const QDeclarativeAnchorLine &edge) +void QDeclarativeAnchorSet::setTop(const QDeclarativeScriptString &edge) { Q_D(QDeclarativeAnchorSet); - d->usedAnchors |= QDeclarativeAnchors::HasTopAnchor; - d->top = edge; + d->usedAnchors |= QDeclarativeAnchors::TopAnchor; + d->topScript = edge; + if (edge.script() == QLatin1String("undefined")) + resetTop(); } void QDeclarativeAnchorSet::resetTop() { Q_D(QDeclarativeAnchorSet); - d->usedAnchors &= ~QDeclarativeAnchors::HasTopAnchor; - d->top = QDeclarativeAnchorLine(); - d->resetList << QLatin1String("top"); + d->usedAnchors &= ~QDeclarativeAnchors::TopAnchor; + d->topScript = QDeclarativeScriptString(); + d->resetAnchors |= QDeclarativeAnchors::TopAnchor; } -QDeclarativeAnchorLine QDeclarativeAnchorSet::bottom() const +QDeclarativeScriptString QDeclarativeAnchorSet::bottom() const { Q_D(const QDeclarativeAnchorSet); - return d->bottom; + return d->bottomScript; } -void QDeclarativeAnchorSet::setBottom(const QDeclarativeAnchorLine &edge) +void QDeclarativeAnchorSet::setBottom(const QDeclarativeScriptString &edge) { Q_D(QDeclarativeAnchorSet); - d->usedAnchors |= QDeclarativeAnchors::HasBottomAnchor; - d->bottom = edge; + d->usedAnchors |= QDeclarativeAnchors::BottomAnchor; + d->bottomScript = edge; + if (edge.script() == QLatin1String("undefined")) + resetBottom(); } void QDeclarativeAnchorSet::resetBottom() { Q_D(QDeclarativeAnchorSet); - d->usedAnchors &= ~QDeclarativeAnchors::HasBottomAnchor; - d->bottom = QDeclarativeAnchorLine(); - d->resetList << QLatin1String("bottom"); + d->usedAnchors &= ~QDeclarativeAnchors::BottomAnchor; + d->bottomScript = QDeclarativeScriptString(); + d->resetAnchors |= QDeclarativeAnchors::BottomAnchor; } -QDeclarativeAnchorLine QDeclarativeAnchorSet::verticalCenter() const +QDeclarativeScriptString QDeclarativeAnchorSet::verticalCenter() const { Q_D(const QDeclarativeAnchorSet); - return d->vCenter; + return d->vCenterScript; } -void QDeclarativeAnchorSet::setVerticalCenter(const QDeclarativeAnchorLine &edge) +void QDeclarativeAnchorSet::setVerticalCenter(const QDeclarativeScriptString &edge) { Q_D(QDeclarativeAnchorSet); - d->usedAnchors |= QDeclarativeAnchors::HasVCenterAnchor; - d->vCenter = edge; + d->usedAnchors |= QDeclarativeAnchors::VCenterAnchor; + d->vCenterScript = edge; + if (edge.script() == QLatin1String("undefined")) + resetVerticalCenter(); } void QDeclarativeAnchorSet::resetVerticalCenter() { Q_D(QDeclarativeAnchorSet); - d->usedAnchors &= ~QDeclarativeAnchors::HasVCenterAnchor; - d->vCenter = QDeclarativeAnchorLine(); - d->resetList << QLatin1String("verticalCenter"); + d->usedAnchors &= ~QDeclarativeAnchors::VCenterAnchor; + d->vCenterScript = QDeclarativeScriptString(); + d->resetAnchors |= QDeclarativeAnchors::VCenterAnchor; } -QDeclarativeAnchorLine QDeclarativeAnchorSet::baseline() const +QDeclarativeScriptString QDeclarativeAnchorSet::baseline() const { Q_D(const QDeclarativeAnchorSet); - return d->baseline; + return d->baselineScript; } -void QDeclarativeAnchorSet::setBaseline(const QDeclarativeAnchorLine &edge) +void QDeclarativeAnchorSet::setBaseline(const QDeclarativeScriptString &edge) { Q_D(QDeclarativeAnchorSet); - d->usedAnchors |= QDeclarativeAnchors::HasBaselineAnchor; - d->baseline = edge; + d->usedAnchors |= QDeclarativeAnchors::BaselineAnchor; + d->baselineScript = edge; + if (edge.script() == QLatin1String("undefined")) + resetBaseline(); } void QDeclarativeAnchorSet::resetBaseline() { Q_D(QDeclarativeAnchorSet); - d->usedAnchors &= ~QDeclarativeAnchors::HasBaselineAnchor; - d->baseline = QDeclarativeAnchorLine(); - d->resetList << QLatin1String("baseline"); + d->usedAnchors &= ~QDeclarativeAnchors::BaselineAnchor; + d->baselineScript = QDeclarativeScriptString(); + d->resetAnchors |= QDeclarativeAnchors::BaselineAnchor; } -QDeclarativeAnchorLine QDeclarativeAnchorSet::left() const +QDeclarativeScriptString QDeclarativeAnchorSet::left() const { Q_D(const QDeclarativeAnchorSet); - return d->left; + return d->leftScript; } -void QDeclarativeAnchorSet::setLeft(const QDeclarativeAnchorLine &edge) +void QDeclarativeAnchorSet::setLeft(const QDeclarativeScriptString &edge) { Q_D(QDeclarativeAnchorSet); - d->usedAnchors |= QDeclarativeAnchors::HasLeftAnchor; - d->left = edge; + d->usedAnchors |= QDeclarativeAnchors::LeftAnchor; + d->leftScript = edge; + if (edge.script() == QLatin1String("undefined")) + resetLeft(); } void QDeclarativeAnchorSet::resetLeft() { Q_D(QDeclarativeAnchorSet); - d->usedAnchors &= ~QDeclarativeAnchors::HasLeftAnchor; - d->left = QDeclarativeAnchorLine(); - d->resetList << QLatin1String("left"); + d->usedAnchors &= ~QDeclarativeAnchors::LeftAnchor; + d->leftScript = QDeclarativeScriptString(); + d->resetAnchors |= QDeclarativeAnchors::LeftAnchor; } -QDeclarativeAnchorLine QDeclarativeAnchorSet::right() const +QDeclarativeScriptString QDeclarativeAnchorSet::right() const { Q_D(const QDeclarativeAnchorSet); - return d->right; + return d->rightScript; } -void QDeclarativeAnchorSet::setRight(const QDeclarativeAnchorLine &edge) +void QDeclarativeAnchorSet::setRight(const QDeclarativeScriptString &edge) { Q_D(QDeclarativeAnchorSet); - d->usedAnchors |= QDeclarativeAnchors::HasRightAnchor; - d->right = edge; + d->usedAnchors |= QDeclarativeAnchors::RightAnchor; + d->rightScript = edge; + if (edge.script() == QLatin1String("undefined")) + resetRight(); } void QDeclarativeAnchorSet::resetRight() { Q_D(QDeclarativeAnchorSet); - d->usedAnchors &= ~QDeclarativeAnchors::HasRightAnchor; - d->right = QDeclarativeAnchorLine(); - d->resetList << QLatin1String("right"); + d->usedAnchors &= ~QDeclarativeAnchors::RightAnchor; + d->rightScript = QDeclarativeScriptString(); + d->resetAnchors |= QDeclarativeAnchors::RightAnchor; } -QDeclarativeAnchorLine QDeclarativeAnchorSet::horizontalCenter() const +QDeclarativeScriptString QDeclarativeAnchorSet::horizontalCenter() const { Q_D(const QDeclarativeAnchorSet); - return d->hCenter; + return d->hCenterScript; } -void QDeclarativeAnchorSet::setHorizontalCenter(const QDeclarativeAnchorLine &edge) +void QDeclarativeAnchorSet::setHorizontalCenter(const QDeclarativeScriptString &edge) { Q_D(QDeclarativeAnchorSet); - d->usedAnchors |= QDeclarativeAnchors::HasHCenterAnchor; - d->hCenter = edge; + d->usedAnchors |= QDeclarativeAnchors::HCenterAnchor; + d->hCenterScript = edge; + if (edge.script() == QLatin1String("undefined")) + resetHorizontalCenter(); } void QDeclarativeAnchorSet::resetHorizontalCenter() { Q_D(QDeclarativeAnchorSet); - d->usedAnchors &= ~QDeclarativeAnchors::HasHCenterAnchor; - d->hCenter = QDeclarativeAnchorLine(); - d->resetList << QLatin1String("horizontalCenter"); + d->usedAnchors &= ~QDeclarativeAnchors::HCenterAnchor; + d->hCenterScript = QDeclarativeScriptString(); + d->resetAnchors |= QDeclarativeAnchors::HCenterAnchor; } QDeclarativeItem *QDeclarativeAnchorSet::fill() const @@ -846,19 +870,35 @@ class QDeclarativeAnchorChangesPrivate : public QObjectPrivate { public: QDeclarativeAnchorChangesPrivate() - : target(0), anchorSet(new QDeclarativeAnchorSet) {} + : target(0), anchorSet(new QDeclarativeAnchorSet), + leftBinding(0), rightBinding(0), hCenterBinding(0), + topBinding(0), bottomBinding(0), vCenterBinding(0), baselineBinding(0), + origLeftBinding(0), origRightBinding(0), origHCenterBinding(0), + origTopBinding(0), origBottomBinding(0), origVCenterBinding(0), + origBaselineBinding(0) + { + + } ~QDeclarativeAnchorChangesPrivate() { delete anchorSet; } QDeclarativeItem *target; QDeclarativeAnchorSet *anchorSet; - QDeclarativeAnchorLine origLeft; - QDeclarativeAnchorLine origRight; - QDeclarativeAnchorLine origHCenter; - QDeclarativeAnchorLine origTop; - QDeclarativeAnchorLine origBottom; - QDeclarativeAnchorLine origVCenter; - QDeclarativeAnchorLine origBaseline; + QDeclarativeBinding *leftBinding; + QDeclarativeBinding *rightBinding; + QDeclarativeBinding *hCenterBinding; + QDeclarativeBinding *topBinding; + QDeclarativeBinding *bottomBinding; + QDeclarativeBinding *vCenterBinding; + QDeclarativeBinding *baselineBinding; + + QDeclarativeAbstractBinding *origLeftBinding; + QDeclarativeAbstractBinding *origRightBinding; + QDeclarativeAbstractBinding *origHCenterBinding; + QDeclarativeAbstractBinding *origTopBinding; + QDeclarativeAbstractBinding *origBottomBinding; + QDeclarativeAbstractBinding *origVCenterBinding; + QDeclarativeAbstractBinding *origBaselineBinding; QDeclarativeAnchorLine rewindLeft; QDeclarativeAnchorLine rewindRight; @@ -890,6 +930,16 @@ public: bool applyOrigBottom; bool applyOrigVCenter; bool applyOrigBaseline; + + QList<QDeclarativeAbstractBinding*> oldBindings; + + QDeclarativeProperty leftProp; + QDeclarativeProperty rightProp; + QDeclarativeProperty hCenterProp; + QDeclarativeProperty topProp; + QDeclarativeProperty bottomProp; + QDeclarativeProperty vCenterProp; + QDeclarativeProperty baselineProp; }; /*! @@ -908,6 +958,47 @@ QDeclarativeAnchorChanges::~QDeclarativeAnchorChanges() QDeclarativeAnchorChanges::ActionList QDeclarativeAnchorChanges::actions() { + Q_D(QDeclarativeAnchorChanges); + d->leftBinding = d->rightBinding = d->hCenterBinding = d->topBinding + = d->bottomBinding = d->vCenterBinding = d->baselineBinding = 0; + + d->leftProp = QDeclarativeProperty(d->target, QLatin1String("anchors.left")); + d->rightProp = QDeclarativeProperty(d->target, QLatin1String("anchors.right")); + d->hCenterProp = QDeclarativeProperty(d->target, QLatin1String("anchors.horizontalCenter")); + d->topProp = QDeclarativeProperty(d->target, QLatin1String("anchors.top")); + d->bottomProp = QDeclarativeProperty(d->target, QLatin1String("anchors.bottom")); + d->vCenterProp = QDeclarativeProperty(d->target, QLatin1String("anchors.verticalCenter")); + d->baselineProp = QDeclarativeProperty(d->target, QLatin1String("anchors.baseline")); + + if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::LeftAnchor) { + d->leftBinding = new QDeclarativeBinding(d->anchorSet->d_func()->leftScript.script(), d->target, qmlContext(this)); + d->leftBinding->setTarget(d->leftProp); + } + if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::RightAnchor) { + d->rightBinding = new QDeclarativeBinding(d->anchorSet->d_func()->rightScript.script(), d->target, qmlContext(this)); + d->rightBinding->setTarget(d->rightProp); + } + if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::HCenterAnchor) { + d->hCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->hCenterScript.script(), d->target, qmlContext(this)); + d->hCenterBinding->setTarget(d->hCenterProp); + } + if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::TopAnchor) { + d->topBinding = new QDeclarativeBinding(d->anchorSet->d_func()->topScript.script(), d->target, qmlContext(this)); + d->topBinding->setTarget(d->topProp); + } + if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::BottomAnchor) { + d->bottomBinding = new QDeclarativeBinding(d->anchorSet->d_func()->bottomScript.script(), d->target, qmlContext(this)); + d->bottomBinding->setTarget(d->bottomProp); + } + if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::VCenterAnchor) { + d->vCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->vCenterScript.script(), d->target, qmlContext(this)); + d->vCenterBinding->setTarget(d->vCenterProp); + } + if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::BaselineAnchor) { + d->baselineBinding = new QDeclarativeBinding(d->anchorSet->d_func()->baselineScript.script(), d->target, qmlContext(this)); + d->baselineBinding->setTarget(d->baselineProp); + } + QDeclarativeAction a; a.event = this; return ActionList() << a; @@ -952,59 +1043,104 @@ void QDeclarativeAnchorChanges::setObject(QDeclarativeItem *target) \endqml */ -void QDeclarativeAnchorChanges::execute() +void QDeclarativeAnchorChanges::execute(Reason reason) { Q_D(QDeclarativeAnchorChanges); if (!d->target) return; //incorporate any needed "reverts" - if (d->applyOrigLeft) - d->target->anchors()->setLeft(d->origLeft); - if (d->applyOrigRight) - d->target->anchors()->setRight(d->origRight); - if (d->applyOrigHCenter) - d->target->anchors()->setHorizontalCenter(d->origHCenter); - if (d->applyOrigTop) - d->target->anchors()->setTop(d->origTop); - if (d->applyOrigBottom) - d->target->anchors()->setBottom(d->origBottom); - if (d->applyOrigVCenter) - d->target->anchors()->setVerticalCenter(d->origVCenter); - if (d->applyOrigBaseline) - d->target->anchors()->setBaseline(d->origBaseline); - - //reset any anchors that have been specified - if (d->anchorSet->d_func()->resetList .contains(QLatin1String("left"))) + if (d->applyOrigLeft) { + if (!d->origLeftBinding) + d->target->anchors()->resetLeft(); + QDeclarativePropertyPrivate::setBinding(d->leftProp, d->origLeftBinding); + } + if (d->applyOrigRight) { + if (!d->origRightBinding) + d->target->anchors()->resetRight(); + QDeclarativePropertyPrivate::setBinding(d->rightProp, d->origRightBinding); + } + if (d->applyOrigHCenter) { + if (!d->origHCenterBinding) + d->target->anchors()->resetHorizontalCenter(); + QDeclarativePropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding); + } + if (d->applyOrigTop) { + if (!d->origTopBinding) + d->target->anchors()->resetTop(); + QDeclarativePropertyPrivate::setBinding(d->topProp, d->origTopBinding); + } + if (d->applyOrigBottom) { + if (!d->origBottomBinding) + d->target->anchors()->resetBottom(); + QDeclarativePropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding); + } + if (d->applyOrigVCenter) { + if (!d->origVCenterBinding) + d->target->anchors()->resetVerticalCenter(); + QDeclarativePropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding); + } + if (d->applyOrigBaseline) { + if (!d->origBaselineBinding) + d->target->anchors()->resetBaseline(); + QDeclarativePropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding); + } + + //destroy old bindings + if (reason == ActualChange) { + for (int i = 0; i < d->oldBindings.size(); ++i) { + QDeclarativeAbstractBinding *binding = d->oldBindings.at(i); + if (binding) + binding->destroy(); + } + d->oldBindings.clear(); + } + + //reset any anchors that have been specified as "undefined" + if (d->anchorSet->d_func()->resetAnchors & QDeclarativeAnchors::LeftAnchor) { d->target->anchors()->resetLeft(); - if (d->anchorSet->d_func()->resetList .contains(QLatin1String("right"))) + QDeclarativePropertyPrivate::setBinding(d->leftProp, 0); + } + if (d->anchorSet->d_func()->resetAnchors & QDeclarativeAnchors::RightAnchor) { d->target->anchors()->resetRight(); - if (d->anchorSet->d_func()->resetList .contains(QLatin1String("horizontalCenter"))) + QDeclarativePropertyPrivate::setBinding(d->rightProp, 0); + } + if (d->anchorSet->d_func()->resetAnchors & QDeclarativeAnchors::HCenterAnchor) { d->target->anchors()->resetHorizontalCenter(); - if (d->anchorSet->d_func()->resetList .contains(QLatin1String("top"))) + QDeclarativePropertyPrivate::setBinding(d->hCenterProp, 0); + } + if (d->anchorSet->d_func()->resetAnchors & QDeclarativeAnchors::TopAnchor) { d->target->anchors()->resetTop(); - if (d->anchorSet->d_func()->resetList .contains(QLatin1String("bottom"))) + QDeclarativePropertyPrivate::setBinding(d->topProp, 0); + } + if (d->anchorSet->d_func()->resetAnchors & QDeclarativeAnchors::BottomAnchor) { d->target->anchors()->resetBottom(); - if (d->anchorSet->d_func()->resetList .contains(QLatin1String("verticalCenter"))) + QDeclarativePropertyPrivate::setBinding(d->bottomProp, 0); + } + if (d->anchorSet->d_func()->resetAnchors & QDeclarativeAnchors::VCenterAnchor) { d->target->anchors()->resetVerticalCenter(); - if (d->anchorSet->d_func()->resetList .contains(QLatin1String("baseline"))) + QDeclarativePropertyPrivate::setBinding(d->vCenterProp, 0); + } + if (d->anchorSet->d_func()->resetAnchors & QDeclarativeAnchors::BaselineAnchor) { d->target->anchors()->resetBaseline(); + QDeclarativePropertyPrivate::setBinding(d->baselineProp, 0); + } //set any anchors that have been specified - if (d->anchorSet->d_func()->left.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setLeft(d->anchorSet->d_func()->left); - if (d->anchorSet->d_func()->right.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setRight(d->anchorSet->d_func()->right); - if (d->anchorSet->d_func()->hCenter.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setHorizontalCenter(d->anchorSet->d_func()->hCenter); - if (d->anchorSet->d_func()->top.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setTop(d->anchorSet->d_func()->top); - if (d->anchorSet->d_func()->bottom.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setBottom(d->anchorSet->d_func()->bottom); - if (d->anchorSet->d_func()->vCenter.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setVerticalCenter(d->anchorSet->d_func()->vCenter); - if (d->anchorSet->d_func()->baseline.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setBaseline(d->anchorSet->d_func()->baseline); + if (d->leftBinding) + QDeclarativePropertyPrivate::setBinding(d->leftBinding->property(), d->leftBinding); + if (d->rightBinding) + QDeclarativePropertyPrivate::setBinding(d->rightBinding->property(), d->rightBinding); + if (d->hCenterBinding) + QDeclarativePropertyPrivate::setBinding(d->hCenterBinding->property(), d->hCenterBinding); + if (d->topBinding) + QDeclarativePropertyPrivate::setBinding(d->topBinding->property(), d->topBinding); + if (d->bottomBinding) + QDeclarativePropertyPrivate::setBinding(d->bottomBinding->property(), d->bottomBinding); + if (d->vCenterBinding) + QDeclarativePropertyPrivate::setBinding(d->vCenterBinding->property(), d->vCenterBinding); + if (d->baselineBinding) + QDeclarativePropertyPrivate::setBinding(d->baselineBinding->property(), d->baselineBinding); } bool QDeclarativeAnchorChanges::isReversable() @@ -1012,43 +1148,78 @@ bool QDeclarativeAnchorChanges::isReversable() return true; } -void QDeclarativeAnchorChanges::reverse() +void QDeclarativeAnchorChanges::reverse(Reason reason) { Q_D(QDeclarativeAnchorChanges); if (!d->target) return; //reset any anchors set by the state - if (d->anchorSet->d_func()->left.anchorLine != QDeclarativeAnchorLine::Invalid) + if (d->leftBinding) { d->target->anchors()->resetLeft(); - if (d->anchorSet->d_func()->right.anchorLine != QDeclarativeAnchorLine::Invalid) + QDeclarativePropertyPrivate::setBinding(d->leftBinding->property(), 0); + if (reason == ActualChange) { + d->leftBinding->destroy(); d->leftBinding = 0; + } + } + if (d->rightBinding) { d->target->anchors()->resetRight(); - if (d->anchorSet->d_func()->hCenter.anchorLine != QDeclarativeAnchorLine::Invalid) + QDeclarativePropertyPrivate::setBinding(d->rightBinding->property(), 0); + if (reason == ActualChange) { + d->rightBinding->destroy(); d->rightBinding = 0; + } + } + if (d->hCenterBinding) { d->target->anchors()->resetHorizontalCenter(); - if (d->anchorSet->d_func()->top.anchorLine != QDeclarativeAnchorLine::Invalid) + QDeclarativePropertyPrivate::setBinding(d->hCenterBinding->property(), 0); + if (reason == ActualChange) { + d->hCenterBinding->destroy(); d->hCenterBinding = 0; + } + } + if (d->topBinding) { d->target->anchors()->resetTop(); - if (d->anchorSet->d_func()->bottom.anchorLine != QDeclarativeAnchorLine::Invalid) + QDeclarativePropertyPrivate::setBinding(d->topBinding->property(), 0); + if (reason == ActualChange) { + d->topBinding->destroy(); d->topBinding = 0; + } + } + if (d->bottomBinding) { d->target->anchors()->resetBottom(); - if (d->anchorSet->d_func()->vCenter.anchorLine != QDeclarativeAnchorLine::Invalid) + QDeclarativePropertyPrivate::setBinding(d->bottomBinding->property(), 0); + if (reason == ActualChange) { + d->bottomBinding->destroy(); d->bottomBinding = 0; + } + } + if (d->vCenterBinding) { d->target->anchors()->resetVerticalCenter(); - if (d->anchorSet->d_func()->baseline.anchorLine != QDeclarativeAnchorLine::Invalid) + QDeclarativePropertyPrivate::setBinding(d->vCenterBinding->property(), 0); + if (reason == ActualChange) { + d->vCenterBinding->destroy(); d->vCenterBinding = 0; + } + } + if (d->baselineBinding) { d->target->anchors()->resetBaseline(); + QDeclarativePropertyPrivate::setBinding(d->baselineBinding->property(), 0); + if (reason == ActualChange) { + d->baselineBinding->destroy(); d->baselineBinding = 0; + } + } //restore previous anchors - if (d->origLeft.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setLeft(d->origLeft); - if (d->origRight.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setRight(d->origRight); - if (d->origHCenter.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setHorizontalCenter(d->origHCenter); - if (d->origTop.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setTop(d->origTop); - if (d->origBottom.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setBottom(d->origBottom); - if (d->origVCenter.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setVerticalCenter(d->origVCenter); - if (d->origBaseline.anchorLine != QDeclarativeAnchorLine::Invalid) - d->target->anchors()->setBaseline(d->origBaseline); + if (d->origLeftBinding) + QDeclarativePropertyPrivate::setBinding(d->leftProp, d->origLeftBinding); + if (d->origRightBinding) + QDeclarativePropertyPrivate::setBinding(d->rightProp, d->origRightBinding); + if (d->origHCenterBinding) + QDeclarativePropertyPrivate::setBinding(d->hCenterProp, d->origHCenterBinding); + if (d->origTopBinding) + QDeclarativePropertyPrivate::setBinding(d->topProp, d->origTopBinding); + if (d->origBottomBinding) + QDeclarativePropertyPrivate::setBinding(d->bottomProp, d->origBottomBinding); + if (d->origVCenterBinding) + QDeclarativePropertyPrivate::setBinding(d->vCenterProp, d->origVCenterBinding); + if (d->origBaselineBinding) + QDeclarativePropertyPrivate::setBinding(d->baselineProp, d->origBaselineBinding); } QString QDeclarativeAnchorChanges::typeName() const @@ -1099,13 +1270,13 @@ void QDeclarativeAnchorChanges::saveOriginals() if (!d->target) return; - d->origLeft = d->target->anchors()->left(); - d->origRight = d->target->anchors()->right(); - d->origHCenter = d->target->anchors()->horizontalCenter(); - d->origTop = d->target->anchors()->top(); - d->origBottom = d->target->anchors()->bottom(); - d->origVCenter = d->target->anchors()->verticalCenter(); - d->origBaseline = d->target->anchors()->baseline(); + d->origLeftBinding = QDeclarativePropertyPrivate::binding(d->leftProp); + d->origRightBinding = QDeclarativePropertyPrivate::binding(d->rightProp); + d->origHCenterBinding = QDeclarativePropertyPrivate::binding(d->hCenterProp); + d->origTopBinding = QDeclarativePropertyPrivate::binding(d->topProp); + d->origBottomBinding = QDeclarativePropertyPrivate::binding(d->bottomProp); + d->origVCenterBinding = QDeclarativePropertyPrivate::binding(d->vCenterProp); + d->origBaselineBinding = QDeclarativePropertyPrivate::binding(d->baselineProp); d->applyOrigLeft = d->applyOrigRight = d->applyOrigHCenter = d->applyOrigTop = d->applyOrigBottom = d->applyOrigVCenter = d->applyOrigBaseline = false; @@ -1119,35 +1290,29 @@ void QDeclarativeAnchorChanges::copyOriginals(QDeclarativeActionEvent *other) QDeclarativeAnchorChanges *ac = static_cast<QDeclarativeAnchorChanges*>(other); QDeclarativeAnchorChangesPrivate *acp = ac->d_func(); - //probably also need to revert some things - d->applyOrigLeft = (acp->anchorSet->d_func()->left.anchorLine != QDeclarativeAnchorLine::Invalid || - acp->anchorSet->d_func()->resetList.contains(QLatin1String("left"))); - - d->applyOrigRight = (acp->anchorSet->d_func()->right.anchorLine != QDeclarativeAnchorLine::Invalid || - acp->anchorSet->d_func()->resetList.contains(QLatin1String("right"))); - - d->applyOrigHCenter = (acp->anchorSet->d_func()->hCenter.anchorLine != QDeclarativeAnchorLine::Invalid || - acp->anchorSet->d_func()->resetList.contains(QLatin1String("horizontalCenter"))); - - d->applyOrigTop = (acp->anchorSet->d_func()->top.anchorLine != QDeclarativeAnchorLine::Invalid || - acp->anchorSet->d_func()->resetList.contains(QLatin1String("top"))); - - d->applyOrigBottom = (acp->anchorSet->d_func()->bottom.anchorLine != QDeclarativeAnchorLine::Invalid || - acp->anchorSet->d_func()->resetList.contains(QLatin1String("bottom"))); + QDeclarativeAnchors::Anchors combined = acp->anchorSet->d_func()->usedAnchors | + acp->anchorSet->d_func()->resetAnchors; - d->applyOrigVCenter = (acp->anchorSet->d_func()->vCenter.anchorLine != QDeclarativeAnchorLine::Invalid || - acp->anchorSet->d_func()->resetList.contains(QLatin1String("verticalCenter"))); - - d->applyOrigBaseline = (acp->anchorSet->d_func()->baseline.anchorLine != QDeclarativeAnchorLine::Invalid || - acp->anchorSet->d_func()->resetList.contains(QLatin1String("baseline"))); - - d->origLeft = ac->d_func()->origLeft; - d->origRight = ac->d_func()->origRight; - d->origHCenter = ac->d_func()->origHCenter; - d->origTop = ac->d_func()->origTop; - d->origBottom = ac->d_func()->origBottom; - d->origVCenter = ac->d_func()->origVCenter; - d->origBaseline = ac->d_func()->origBaseline; + //probably also need to revert some things + d->applyOrigLeft = (combined & QDeclarativeAnchors::LeftAnchor); + d->applyOrigRight = (combined & QDeclarativeAnchors::RightAnchor); + d->applyOrigHCenter = (combined & QDeclarativeAnchors::HCenterAnchor); + d->applyOrigTop = (combined & QDeclarativeAnchors::TopAnchor); + d->applyOrigBottom = (combined & QDeclarativeAnchors::BottomAnchor); + d->applyOrigVCenter = (combined & QDeclarativeAnchors::VCenterAnchor); + d->applyOrigBaseline = (combined & QDeclarativeAnchors::BaselineAnchor); + + d->origLeftBinding = acp->origLeftBinding; + d->origRightBinding = acp->origRightBinding; + d->origHCenterBinding = acp->origHCenterBinding; + d->origTopBinding = acp->origTopBinding; + d->origBottomBinding = acp->origBottomBinding; + d->origVCenterBinding = acp->origVCenterBinding; + d->origBaselineBinding = acp->origBaselineBinding; + + d->oldBindings.clear(); + d->oldBindings << acp->leftBinding << acp->rightBinding << acp->hCenterBinding + << acp->topBinding << acp->bottomBinding << acp->baselineBinding; saveCurrentValues(); } @@ -1164,52 +1329,38 @@ void QDeclarativeAnchorChanges::clearBindings() d->fromHeight = d->target->height(); //reset any anchors with corresponding reverts - if (d->applyOrigLeft) - d->target->anchors()->resetLeft(); - if (d->applyOrigRight) - d->target->anchors()->resetRight(); - if (d->applyOrigHCenter) - d->target->anchors()->resetHorizontalCenter(); - if (d->applyOrigTop) - d->target->anchors()->resetTop(); - if (d->applyOrigBottom) - d->target->anchors()->resetBottom(); - if (d->applyOrigVCenter) - d->target->anchors()->resetVerticalCenter(); - if (d->applyOrigBaseline) - d->target->anchors()->resetBaseline(); - - //reset any anchors that have been specified - if (d->anchorSet->d_func()->resetList .contains(QLatin1String("left"))) - d->target->anchors()->resetLeft(); - if (d->anchorSet->d_func()->resetList .contains(QLatin1String("right"))) - d->target->anchors()->resetRight(); - if (d->anchorSet->d_func()->resetList .contains(QLatin1String("horizontalCenter"))) - d->target->anchors()->resetHorizontalCenter(); - if (d->anchorSet->d_func()->resetList .contains(QLatin1String("top"))) - d->target->anchors()->resetTop(); - if (d->anchorSet->d_func()->resetList .contains(QLatin1String("bottom"))) - d->target->anchors()->resetBottom(); - if (d->anchorSet->d_func()->resetList .contains(QLatin1String("verticalCenter"))) - d->target->anchors()->resetVerticalCenter(); - if (d->anchorSet->d_func()->resetList .contains(QLatin1String("baseline"))) - d->target->anchors()->resetBaseline(); - + //reset any anchors that have been specified as "undefined" //reset any anchors that we'll be setting in the state - if (d->anchorSet->d_func()->left.anchorLine != QDeclarativeAnchorLine::Invalid) + QDeclarativeAnchors::Anchors combined = d->anchorSet->d_func()->resetAnchors | + d->anchorSet->d_func()->usedAnchors; + if (d->applyOrigLeft || (combined & QDeclarativeAnchors::LeftAnchor)) { d->target->anchors()->resetLeft(); - if (d->anchorSet->d_func()->right.anchorLine != QDeclarativeAnchorLine::Invalid) + QDeclarativePropertyPrivate::setBinding(d->leftProp, 0); + } + if (d->applyOrigRight || (combined & QDeclarativeAnchors::RightAnchor)) { d->target->anchors()->resetRight(); - if (d->anchorSet->d_func()->hCenter.anchorLine != QDeclarativeAnchorLine::Invalid) + QDeclarativePropertyPrivate::setBinding(d->rightProp, 0); + } + if (d->applyOrigHCenter || (combined & QDeclarativeAnchors::HCenterAnchor)) { d->target->anchors()->resetHorizontalCenter(); - if (d->anchorSet->d_func()->top.anchorLine != QDeclarativeAnchorLine::Invalid) + QDeclarativePropertyPrivate::setBinding(d->hCenterProp, 0); + } + if (d->applyOrigTop || (combined & QDeclarativeAnchors::TopAnchor)) { d->target->anchors()->resetTop(); - if (d->anchorSet->d_func()->bottom.anchorLine != QDeclarativeAnchorLine::Invalid) + QDeclarativePropertyPrivate::setBinding(d->topProp, 0); + } + if (d->applyOrigBottom || (combined & QDeclarativeAnchors::BottomAnchor)) { d->target->anchors()->resetBottom(); - if (d->anchorSet->d_func()->vCenter.anchorLine != QDeclarativeAnchorLine::Invalid) + QDeclarativePropertyPrivate::setBinding(d->bottomProp, 0); + } + if (d->applyOrigVCenter || (combined & QDeclarativeAnchors::VCenterAnchor)) { d->target->anchors()->resetVerticalCenter(); - if (d->anchorSet->d_func()->baseline.anchorLine != QDeclarativeAnchorLine::Invalid) + QDeclarativePropertyPrivate::setBinding(d->vCenterProp, 0); + } + if (d->applyOrigBaseline || (combined & QDeclarativeAnchors::BaselineAnchor)) { d->target->anchors()->resetBaseline(); + QDeclarativePropertyPrivate::setBinding(d->baselineProp, 0); + } } bool QDeclarativeAnchorChanges::override(QDeclarativeActionEvent*other) diff --git a/src/declarative/util/qdeclarativestateoperations_p.h b/src/declarative/util/qdeclarativestateoperations_p.h index d49ec63..e22c1e2 100644 --- a/src/declarative/util/qdeclarativestateoperations_p.h +++ b/src/declarative/util/qdeclarativestateoperations_p.h @@ -108,9 +108,9 @@ public: virtual void saveOriginals(); virtual void copyOriginals(QDeclarativeActionEvent*); - virtual void execute(); + virtual void execute(Reason reason = ActualChange); virtual bool isReversable(); - virtual void reverse(); + virtual void reverse(Reason reason = ActualChange); virtual QString typeName() const; virtual bool override(QDeclarativeActionEvent*other); virtual void rewind(); @@ -140,7 +140,7 @@ public: QString name() const; void setName(const QString &); - virtual void execute(); + virtual void execute(Reason reason = ActualChange); }; class QDeclarativeAnchorChanges; @@ -149,13 +149,13 @@ class Q_AUTOTEST_EXPORT QDeclarativeAnchorSet : public QObject { Q_OBJECT - Q_PROPERTY(QDeclarativeAnchorLine left READ left WRITE setLeft RESET resetLeft) - Q_PROPERTY(QDeclarativeAnchorLine right READ right WRITE setRight RESET resetRight) - Q_PROPERTY(QDeclarativeAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter) - Q_PROPERTY(QDeclarativeAnchorLine top READ top WRITE setTop RESET resetTop) - Q_PROPERTY(QDeclarativeAnchorLine bottom READ bottom WRITE setBottom RESET resetBottom) - Q_PROPERTY(QDeclarativeAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter) - Q_PROPERTY(QDeclarativeAnchorLine baseline READ baseline WRITE setBaseline RESET resetBaseline) + Q_PROPERTY(QDeclarativeScriptString left READ left WRITE setLeft RESET resetLeft) + Q_PROPERTY(QDeclarativeScriptString right READ right WRITE setRight RESET resetRight) + Q_PROPERTY(QDeclarativeScriptString horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter) + Q_PROPERTY(QDeclarativeScriptString top READ top WRITE setTop RESET resetTop) + Q_PROPERTY(QDeclarativeScriptString bottom READ bottom WRITE setBottom RESET resetBottom) + Q_PROPERTY(QDeclarativeScriptString verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter) + Q_PROPERTY(QDeclarativeScriptString baseline READ baseline WRITE setBaseline RESET resetBaseline) //Q_PROPERTY(QDeclarativeItem *fill READ fill WRITE setFill RESET resetFill) //Q_PROPERTY(QDeclarativeItem *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn) @@ -172,32 +172,32 @@ public: QDeclarativeAnchorSet(QObject *parent=0); virtual ~QDeclarativeAnchorSet(); - QDeclarativeAnchorLine left() const; - void setLeft(const QDeclarativeAnchorLine &edge); + QDeclarativeScriptString left() const; + void setLeft(const QDeclarativeScriptString &edge); void resetLeft(); - QDeclarativeAnchorLine right() const; - void setRight(const QDeclarativeAnchorLine &edge); + QDeclarativeScriptString right() const; + void setRight(const QDeclarativeScriptString &edge); void resetRight(); - QDeclarativeAnchorLine horizontalCenter() const; - void setHorizontalCenter(const QDeclarativeAnchorLine &edge); + QDeclarativeScriptString horizontalCenter() const; + void setHorizontalCenter(const QDeclarativeScriptString &edge); void resetHorizontalCenter(); - QDeclarativeAnchorLine top() const; - void setTop(const QDeclarativeAnchorLine &edge); + QDeclarativeScriptString top() const; + void setTop(const QDeclarativeScriptString &edge); void resetTop(); - QDeclarativeAnchorLine bottom() const; - void setBottom(const QDeclarativeAnchorLine &edge); + QDeclarativeScriptString bottom() const; + void setBottom(const QDeclarativeScriptString &edge); void resetBottom(); - QDeclarativeAnchorLine verticalCenter() const; - void setVerticalCenter(const QDeclarativeAnchorLine &edge); + QDeclarativeScriptString verticalCenter() const; + void setVerticalCenter(const QDeclarativeScriptString &edge); void resetVerticalCenter(); - QDeclarativeAnchorLine baseline() const; - void setBaseline(const QDeclarativeAnchorLine &edge); + QDeclarativeScriptString baseline() const; + void setBaseline(const QDeclarativeScriptString &edge); void resetBaseline(); QDeclarativeItem *fill() const; @@ -232,7 +232,7 @@ public: qreal baselineOffset() const; void setBaselineOffset(qreal);*/ - QDeclarativeAnchors::UsedAnchors usedAnchors() const; + QDeclarativeAnchors::Anchors usedAnchors() const; /*Q_SIGNALS: void leftMarginChanged(); @@ -270,9 +270,9 @@ public: QDeclarativeItem *object() const; void setObject(QDeclarativeItem *); - virtual void execute(); + virtual void execute(Reason reason = ActualChange); virtual bool isReversable(); - virtual void reverse(); + virtual void reverse(Reason reason = ActualChange); virtual QString typeName() const; virtual bool override(QDeclarativeActionEvent*other); virtual bool changesBindings(); diff --git a/src/declarative/util/qdeclarativetimer_p.h b/src/declarative/util/qdeclarativetimer_p.h index d1e6630..08c3d4e 100644 --- a/src/declarative/util/qdeclarativetimer_p.h +++ b/src/declarative/util/qdeclarativetimer_p.h @@ -63,6 +63,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeTimer : public QObject, public QDeclarati Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged) Q_PROPERTY(bool repeat READ isRepeating WRITE setRepeating NOTIFY repeatChanged) Q_PROPERTY(bool triggeredOnStart READ triggeredOnStart WRITE setTriggeredOnStart NOTIFY triggeredOnStartChanged) + Q_PROPERTY(QObject *parent READ parent CONSTANT) public: QDeclarativeTimer(QObject *parent=0); diff --git a/src/declarative/util/qdeclarativetransitionmanager.cpp b/src/declarative/util/qdeclarativetransitionmanager.cpp index bc40377..368d484 100644 --- a/src/declarative/util/qdeclarativetransitionmanager.cpp +++ b/src/declarative/util/qdeclarativetransitionmanager.cpp @@ -42,6 +42,7 @@ #include "private/qdeclarativetransitionmanager_p_p.h" #include "private/qdeclarativestate_p_p.h" +#include "private/qdeclarativestate_p.h" #include <qdeclarativebinding_p.h> #include <qdeclarativeglobal_p.h> @@ -150,9 +151,9 @@ void QDeclarativeTransitionManager::transition(const QList<QDeclarativeAction> & QDeclarativePropertyPrivate::write(action.property, action.toValue, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding); } else if (action.event->isReversable()) { if (action.reverseEvent) - action.event->reverse(); + action.event->reverse(QDeclarativeActionEvent::FastForward); else - action.event->execute(); + action.event->execute(QDeclarativeActionEvent::FastForward); } } diff --git a/src/declarative/util/qdeclarativeutilmodule.cpp b/src/declarative/util/qdeclarativeutilmodule.cpp index b9f1abb..eb59fb1 100644 --- a/src/declarative/util/qdeclarativeutilmodule.cpp +++ b/src/declarative/util/qdeclarativeutilmodule.cpp @@ -68,56 +68,60 @@ #include "private/qdeclarativetransitionmanager_p_p.h" #include "private/qdeclarativetransition_p.h" #include "qdeclarativeview.h" +#include "qdeclarativeinfo.h" +#include "private/qdeclarativetypenotavailable_p.h" #ifndef QT_NO_XMLPATTERNS #include "private/qdeclarativexmllistmodel_p.h" #endif void QDeclarativeUtilModule::defineModule() { - qmlRegisterType<QDeclarativeAnchorAnimation>("Qt",4,6,"AnchorAnimation"); - qmlRegisterType<QDeclarativeAnchorChanges>("Qt",4,6,"AnchorChanges"); - qmlRegisterType<QDeclarativeBehavior>("Qt",4,6,"Behavior"); - qmlRegisterType<QDeclarativeBind>("Qt",4,6,"Binding"); - qmlRegisterType<QDeclarativeColorAnimation>("Qt",4,6,"ColorAnimation"); - qmlRegisterType<QDeclarativeConnections>("Qt",4,6,"Connections"); - qmlRegisterType<QDeclarativeSmoothedAnimation>("Qt",4,6,"SmoothedAnimation"); - qmlRegisterType<QDeclarativeSmoothedFollow>("Qt",4,6,"SmoothedFollow"); - qmlRegisterType<QDeclarativeFontLoader>("Qt",4,6,"FontLoader"); - qmlRegisterType<QDeclarativeListElement>("Qt",4,6,"ListElement"); - qmlRegisterType<QDeclarativeNumberAnimation>("Qt",4,6,"NumberAnimation"); - qmlRegisterType<QDeclarativePackage>("Qt",4,6,"Package"); - qmlRegisterType<QDeclarativeParallelAnimation>("Qt",4,6,"ParallelAnimation"); - qmlRegisterType<QDeclarativeParentAnimation>("Qt",4,6,"ParentAnimation"); - qmlRegisterType<QDeclarativeParentChange>("Qt",4,6,"ParentChange"); - qmlRegisterType<QDeclarativePauseAnimation>("Qt",4,6,"PauseAnimation"); - qmlRegisterType<QDeclarativePropertyAction>("Qt",4,6,"PropertyAction"); - qmlRegisterType<QDeclarativePropertyAnimation>("Qt",4,6,"PropertyAnimation"); - qmlRegisterType<QDeclarativeRotationAnimation>("Qt",4,6,"RotationAnimation"); - qmlRegisterType<QDeclarativeScriptAction>("Qt",4,6,"ScriptAction"); - qmlRegisterType<QDeclarativeSequentialAnimation>("Qt",4,6,"SequentialAnimation"); - qmlRegisterType<QDeclarativeSpringFollow>("Qt",4,6,"SpringFollow"); - qmlRegisterType<QDeclarativeStateChangeScript>("Qt",4,6,"StateChangeScript"); - qmlRegisterType<QDeclarativeStateGroup>("Qt",4,6,"StateGroup"); - qmlRegisterType<QDeclarativeState>("Qt",4,6,"State"); - qmlRegisterType<QDeclarativeSystemPalette>("Qt",4,6,"SystemPalette"); - qmlRegisterType<QDeclarativeTimer>("Qt",4,6,"Timer"); - qmlRegisterType<QDeclarativeTransition>("Qt",4,6,"Transition"); - qmlRegisterType<QDeclarativeVector3dAnimation>("Qt",4,6,"Vector3dAnimation"); -#ifndef QT_NO_XMLPATTERNS - qmlRegisterType<QDeclarativeXmlListModel>("Qt",4,6,"XmlListModel"); - qmlRegisterType<QDeclarativeXmlListModelRole>("Qt",4,6,"XmlRole"); + qmlRegisterType<QDeclarativeAnchorAnimation>("Qt",4,7,"AnchorAnimation"); + qmlRegisterType<QDeclarativeAnchorChanges>("Qt",4,7,"AnchorChanges"); + qmlRegisterType<QDeclarativeBehavior>("Qt",4,7,"Behavior"); + qmlRegisterType<QDeclarativeBind>("Qt",4,7,"Binding"); + qmlRegisterType<QDeclarativeColorAnimation>("Qt",4,7,"ColorAnimation"); + qmlRegisterType<QDeclarativeConnections>("Qt",4,7,"Connections"); + qmlRegisterType<QDeclarativeSmoothedAnimation>("Qt",4,7,"SmoothedAnimation"); + qmlRegisterType<QDeclarativeSmoothedFollow>("Qt",4,7,"SmoothedFollow"); + qmlRegisterType<QDeclarativeFontLoader>("Qt",4,7,"FontLoader"); + qmlRegisterType<QDeclarativeListElement>("Qt",4,7,"ListElement"); + qmlRegisterType<QDeclarativeNumberAnimation>("Qt",4,7,"NumberAnimation"); + qmlRegisterType<QDeclarativePackage>("Qt",4,7,"Package"); + qmlRegisterType<QDeclarativeParallelAnimation>("Qt",4,7,"ParallelAnimation"); + qmlRegisterType<QDeclarativeParentAnimation>("Qt",4,7,"ParentAnimation"); + qmlRegisterType<QDeclarativeParentChange>("Qt",4,7,"ParentChange"); + qmlRegisterType<QDeclarativePauseAnimation>("Qt",4,7,"PauseAnimation"); + qmlRegisterType<QDeclarativePropertyAction>("Qt",4,7,"PropertyAction"); + qmlRegisterType<QDeclarativePropertyAnimation>("Qt",4,7,"PropertyAnimation"); + qmlRegisterType<QDeclarativeRotationAnimation>("Qt",4,7,"RotationAnimation"); + qmlRegisterType<QDeclarativeScriptAction>("Qt",4,7,"ScriptAction"); + qmlRegisterType<QDeclarativeSequentialAnimation>("Qt",4,7,"SequentialAnimation"); + qmlRegisterType<QDeclarativeSpringFollow>("Qt",4,7,"SpringFollow"); + qmlRegisterType<QDeclarativeStateChangeScript>("Qt",4,7,"StateChangeScript"); + qmlRegisterType<QDeclarativeStateGroup>("Qt",4,7,"StateGroup"); + qmlRegisterType<QDeclarativeState>("Qt",4,7,"State"); + qmlRegisterType<QDeclarativeSystemPalette>("Qt",4,7,"SystemPalette"); + qmlRegisterType<QDeclarativeTimer>("Qt",4,7,"Timer"); + qmlRegisterType<QDeclarativeTransition>("Qt",4,7,"Transition"); + qmlRegisterType<QDeclarativeVector3dAnimation>("Qt",4,7,"Vector3dAnimation"); +#ifdef QT_NO_XMLPATTERNS + qmlRegisterTypeNotAvailable("Qt",4,7,"XmlListModel", + qApp->translate("QDeclarativeXmlListModel","Qt was built without support for xmlpatterns")); + qmlRegisterTypeNotAvailable("Qt",4,7,"XmlRole", + qApp->translate("QDeclarativeXmlListModel","Qt was built without support for xmlpatterns")); +#else + qmlRegisterType<QDeclarativeXmlListModel>("Qt",4,7,"XmlListModel"); + qmlRegisterType<QDeclarativeXmlListModelRole>("Qt",4,7,"XmlRole"); #endif qmlRegisterType<QDeclarativeAnchors>(); qmlRegisterType<QDeclarativeStateOperation>(); qmlRegisterType<QDeclarativeAnchorSet>(); - qmlRegisterUncreatableType<QDeclarativeAbstractAnimation>("Qt",4,6,"Animation"); + qmlRegisterUncreatableType<QDeclarativeAbstractAnimation>("Qt",4,7,"Animation",QDeclarativeAbstractAnimation::tr("Animation is an abstract class")); - qmlRegisterCustomType<QDeclarativeListModel>("Qt", 4,6, "ListModel", "QDeclarativeListModel", - new QDeclarativeListModelParser); - qmlRegisterCustomType<QDeclarativePropertyChanges>("Qt", 4, 6, "PropertyChanges", "QDeclarativePropertyChanges", - new QDeclarativePropertyChangesParser); - qmlRegisterCustomType<QDeclarativeConnections>("Qt", 4, 6, "Connections", "QDeclarativeConnections", - new QDeclarativeConnectionsParser); + qmlRegisterCustomType<QDeclarativeListModel>("Qt", 4,7, "ListModel", new QDeclarativeListModelParser); + qmlRegisterCustomType<QDeclarativePropertyChanges>("Qt", 4, 6, "PropertyChanges", new QDeclarativePropertyChangesParser); + qmlRegisterCustomType<QDeclarativeConnections>("Qt", 4, 6, "Connections", new QDeclarativeConnectionsParser); } diff --git a/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp index c0425ef..62d913c 100644 --- a/src/declarative/util/qdeclarativeview.cpp +++ b/src/declarative/util/qdeclarativeview.cpp @@ -59,10 +59,14 @@ #include <qfontdatabase.h> #include <qicon.h> #include <qurl.h> -#include <qboxlayout.h> +#include <qlayout.h> +#include <qwidget.h> +#include <qgraphicswidget.h> #include <qbasictimer.h> #include <QtCore/qabstractanimation.h> #include <private/qgraphicsview_p.h> +#include <private/qdeclarativeitem_p.h> +#include <private/qdeclarativeitemchangelistener_p.h> QT_BEGIN_NAMESPACE @@ -124,19 +128,23 @@ void FrameBreakAnimation::updateCurrentTime(int msecs) server->frameBreak(); } -class QDeclarativeViewPrivate +class QDeclarativeViewPrivate : public QDeclarativeItemChangeListener { public: QDeclarativeViewPrivate(QDeclarativeView *view) - : q(view), root(0), component(0), resizeMode(QDeclarativeView::SizeViewToRootObject) {} + : q(view), root(0), declarativeItemRoot(0), graphicsWidgetRoot(0), component(0), resizeMode(QDeclarativeView::SizeViewToRootObject) {} ~QDeclarativeViewPrivate() { delete root; } - void execute(); + void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry); + void initResize(); + void updateSize(); + inline QSize rootObjectSize(); QDeclarativeView *q; QDeclarativeGuard<QGraphicsObject> root; - QDeclarativeGuard<QDeclarativeItem> qmlRoot; + QDeclarativeGuard<QDeclarativeItem> declarativeItemRoot; + QDeclarativeGuard<QGraphicsWidget> graphicsWidgetRoot; QUrl source; @@ -144,7 +152,6 @@ public: QDeclarativeComponent *component; QBasicTimer resizetimer; - mutable QSize initialSize; QDeclarativeView::ResizeMode resizeMode; QTime frameTimer; @@ -155,18 +162,32 @@ public: void QDeclarativeViewPrivate::execute() { - delete root; - delete component; - initialSize = QSize(); - component = new QDeclarativeComponent(&engine, source, q); - - if (!component->isLoading()) { - q->continueExecute(); - } else { - QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), q, SLOT(continueExecute())); + if (root) { + delete root; + root = 0; + } + if (component) { + delete component; + component = 0; + } + if (!source.isEmpty()) { + component = new QDeclarativeComponent(&engine, source, q); + if (!component->isLoading()) { + q->continueExecute(); + } else { + QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), q, SLOT(continueExecute())); + } } } +void QDeclarativeViewPrivate::itemGeometryChanged(QDeclarativeItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry) +{ + if (resizeItem == root && resizeMode == QDeclarativeView::SizeViewToRootObject) { + // wait for both width and height to be changed + resizetimer.start(0,q); + } + QDeclarativeItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry); +} /*! \class QDeclarativeView @@ -332,21 +353,20 @@ QDeclarativeContext* QDeclarativeView::rootContext() /*! \enum QDeclarativeView::Status - Specifies the loading status of the QDeclarativeView. \value Null This QDeclarativeView has no source set. \value Ready This QDeclarativeView has loaded and created the QML component. \value Loading This QDeclarativeView is loading network data. - \value Error An error has occured. Calling errorDescription() to retrieve a description. + \value Error An error has occured. Call errorDescription() to retrieve a description. */ /*! \enum QDeclarativeView::ResizeMode This enum specifies how to resize the view. - \value SizeViewToRootObject - \value SizeRootObjectToView + \value SizeViewToRootObject The view resizes with the root item in the QML. + \value SizeRootObjectToView The view will automatically resize the root item to the size of the view. */ /*! @@ -373,7 +393,6 @@ QList<QDeclarativeError> QDeclarativeView::errors() const return QList<QDeclarativeError>(); } - /*! \property QDeclarativeView::resizeMode \brief whether the view should resize the canvas contents @@ -394,16 +413,92 @@ void QDeclarativeView::setResizeMode(ResizeMode mode) if (d->resizeMode == mode) return; + if (d->declarativeItemRoot) { + if (d->resizeMode == SizeViewToRootObject) { + QDeclarativeItemPrivate *p = + static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(d->declarativeItemRoot)); + p->removeItemChangeListener(d, QDeclarativeItemPrivate::Geometry); + } + } else if (d->graphicsWidgetRoot) { + if (d->resizeMode == QDeclarativeView::SizeViewToRootObject) { + d->graphicsWidgetRoot->removeEventFilter(this); + } + } + d->resizeMode = mode; - if (d->qmlRoot) { - if (d->resizeMode == SizeRootObjectToView) { - d->qmlRoot->setWidth(width()); - d->qmlRoot->setHeight(height()); - } else { - d->qmlRoot->setWidth(d->initialSize.width()); - d->qmlRoot->setHeight(d->initialSize.height()); + if (d->root) { + d->initResize(); + } +} + +void QDeclarativeViewPrivate::initResize() +{ + if (declarativeItemRoot) { + if (resizeMode == QDeclarativeView::SizeViewToRootObject) { + QDeclarativeItemPrivate *p = + static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(declarativeItemRoot)); + p->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry); + } + } else if (graphicsWidgetRoot) { + if (resizeMode == QDeclarativeView::SizeViewToRootObject) { + graphicsWidgetRoot->installEventFilter(q); + } + } + updateSize(); +} + +void QDeclarativeViewPrivate::updateSize() +{ + if (!root) + return; + if (declarativeItemRoot) { + if (resizeMode == QDeclarativeView::SizeViewToRootObject) { + QSize newSize = QSize(declarativeItemRoot->width(), declarativeItemRoot->height()); + if (newSize.isValid() && newSize != q->size()) { + q->resize(newSize); + } + } else if (resizeMode == QDeclarativeView::SizeRootObjectToView) { + if (!qFuzzyCompare(q->width(), declarativeItemRoot->width())) + declarativeItemRoot->setWidth(q->width()); + if (!qFuzzyCompare(q->height(), declarativeItemRoot->height())) + declarativeItemRoot->setHeight(q->height()); } + } else if (graphicsWidgetRoot) { + if (resizeMode == QDeclarativeView::SizeViewToRootObject) { + QSize newSize = QSize(graphicsWidgetRoot->size().width(), graphicsWidgetRoot->size().height()); + if (newSize.isValid() && newSize != q->size()) { + q->resize(newSize); + } + } else if (resizeMode == QDeclarativeView::SizeRootObjectToView) { + QSizeF newSize = QSize(q->size().width(), q->size().height()); + if (newSize.isValid() && newSize != graphicsWidgetRoot->size()) { + graphicsWidgetRoot->resize(newSize); + } + } + } + q->updateGeometry(); +} + +QSize QDeclarativeViewPrivate::rootObjectSize() +{ + QSize rootObjectSize(0,0); + int widthCandidate = -1; + int heightCandidate = -1; + if (declarativeItemRoot) { + widthCandidate = declarativeItemRoot->width(); + heightCandidate = declarativeItemRoot->height(); + } else if (root) { + QSizeF size = root->boundingRect().size(); + widthCandidate = size.width(); + heightCandidate = size.height(); + } + if (widthCandidate > 0) { + rootObjectSize.setWidth(widthCandidate); } + if (heightCandidate > 0) { + rootObjectSize.setHeight(heightCandidate); + } + return rootObjectSize; } QDeclarativeView::ResizeMode QDeclarativeView::resizeMode() const @@ -449,55 +544,46 @@ void QDeclarativeView::continueExecute() */ void QDeclarativeView::setRootObject(QObject *obj) { - if (QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(obj)) { - d->scene.addItem(item); - - d->root = item; - d->qmlRoot = item; - connect(item, SIGNAL(widthChanged()), this, SLOT(sizeChanged())); - connect(item, SIGNAL(heightChanged()), this, SLOT(sizeChanged())); - if (d->initialSize.height() <= 0 && d->qmlRoot->width() > 0) - d->initialSize.setWidth(d->qmlRoot->width()); - if (d->initialSize.height() <= 0 && d->qmlRoot->height() > 0) - d->initialSize.setHeight(d->qmlRoot->height()); - resize(d->initialSize); - - if (d->resizeMode == SizeRootObjectToView) { - d->qmlRoot->setWidth(width()); - d->qmlRoot->setHeight(height()); + if (d->root == obj) + return; + if (QDeclarativeItem *declarativeItem = qobject_cast<QDeclarativeItem *>(obj)) { + d->scene.addItem(declarativeItem); + d->root = declarativeItem; + d->declarativeItemRoot = declarativeItem; + } else if (QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(obj)) { + d->scene.addItem(graphicsObject); + d->root = graphicsObject; + if (graphicsObject->isWidget()) { + d->graphicsWidgetRoot = static_cast<QGraphicsWidget*>(graphicsObject); } else { - QSize sz(d->qmlRoot->width(),d->qmlRoot->height()); - emit sceneResized(sz); - resize(sz); + qWarning() << "QDeclarativeView::resizeMode is not honored for components of type QGraphicsObject"; } - updateGeometry(); - } else if (QGraphicsObject *item = qobject_cast<QGraphicsObject *>(obj)) { - d->scene.addItem(item); - qWarning() << "QDeclarativeView::resizeMode is not honored for components of type QGraphicsObject"; - } else if (QWidget *wid = qobject_cast<QWidget *>(obj)) { - window()->setAttribute(Qt::WA_OpaquePaintEvent, false); - window()->setAttribute(Qt::WA_NoSystemBackground, false); - if (!layout()) { - setLayout(new QVBoxLayout); - layout()->setContentsMargins(0, 0, 0, 0); - } else if (layout()->count()) { - // Hide the QGraphicsView in GV mode. - QLayoutItem *item = layout()->itemAt(0); - if (item->widget()) - item->widget()->hide(); + } else if (obj) { + qWarning() << "QDeclarativeView only supports loading of root objects that derive from QGraphicsObject"; + if (QWidget* widget = qobject_cast<QWidget *>(obj)) { + window()->setAttribute(Qt::WA_OpaquePaintEvent, false); + window()->setAttribute(Qt::WA_NoSystemBackground, false); + if (layout() && layout()->count()) { + // Hide the QGraphicsView in GV mode. + QLayoutItem *item = layout()->itemAt(0); + if (item->widget()) + item->widget()->hide(); + } + widget->setParent(this); + if (isVisible()) { + widget->setVisible(true); + } + resize(widget->size()); } - layout()->addWidget(wid); - emit sceneResized(wid->size()); } -} -/*! - \internal - */ -void QDeclarativeView::sizeChanged() -{ - // delay, so we catch both width and height changing. - d->resizetimer.start(0,this); + if (d->root) { + QSize initialSize = d->rootObjectSize(); + if (initialSize != size()) { + resize(initialSize); + } + d->initResize(); + } } /*! @@ -508,30 +594,37 @@ void QDeclarativeView::sizeChanged() void QDeclarativeView::timerEvent(QTimerEvent* e) { if (!e || e->timerId() == d->resizetimer.timerId()) { - if (d->qmlRoot) { - QSize sz(d->qmlRoot->width(),d->qmlRoot->height()); - emit sceneResized(sz); - //if (!d->resizable) - //resize(sz); - } + d->updateSize(); d->resizetimer.stop(); - updateGeometry(); } } +/*! \reimp */ +bool QDeclarativeView::eventFilter(QObject *watched, QEvent *e) +{ + if (watched == d->root && d->resizeMode == SizeViewToRootObject) { + if (d->graphicsWidgetRoot) { + if (e->type() == QEvent::GraphicsSceneResize) { + d->updateSize(); + } + } + } + return QGraphicsView::eventFilter(watched, e); +} + /*! \internal - The size hint is the size of the root item. + Preferred size follows the root object in + resize mode SizeViewToRootObject and + the view in resize mode SizeRootObjectToView. */ QSize QDeclarativeView::sizeHint() const { - if (d->qmlRoot) { - if (d->initialSize.width() <= 0) - d->initialSize.setWidth(d->qmlRoot->width()); - if (d->initialSize.height() <= 0) - d->initialSize.setHeight(d->qmlRoot->height()); + if (d->resizeMode == SizeRootObjectToView) { + return size(); + } else { // d->resizeMode == SizeViewToRootObject + return d->rootObjectSize(); } - return d->initialSize; } /*! @@ -549,17 +642,17 @@ QGraphicsObject *QDeclarativeView::rootObject() const */ void QDeclarativeView::resizeEvent(QResizeEvent *e) { - if (d->resizeMode == SizeRootObjectToView && d->qmlRoot) { - d->qmlRoot->setWidth(width()); - d->qmlRoot->setHeight(height()); + if (d->resizeMode == SizeRootObjectToView) { + d->updateSize(); } - if (d->qmlRoot) { - setSceneRect(QRectF(0, 0, d->qmlRoot->width(), d->qmlRoot->height())); + if (d->declarativeItemRoot) { + setSceneRect(QRectF(0, 0, d->declarativeItemRoot->width(), d->declarativeItemRoot->height())); } else if (d->root) { setSceneRect(d->root->boundingRect()); } else { setSceneRect(rect()); } + emit sceneResized(e->size()); QGraphicsView::resizeEvent(e); } diff --git a/src/declarative/util/qdeclarativeview.h b/src/declarative/util/qdeclarativeview.h index 107f3f9..3513c04 100644 --- a/src/declarative/util/qdeclarativeview.h +++ b/src/declarative/util/qdeclarativeview.h @@ -97,16 +97,18 @@ Q_SIGNALS: private Q_SLOTS: void continueExecute(); - void sizeChanged(); protected: virtual void resizeEvent(QResizeEvent *); virtual void paintEvent(QPaintEvent *event); virtual void timerEvent(QTimerEvent*); virtual void setRootObject(QObject *obj); + virtual bool eventFilter(QObject *watched, QEvent *e); +private: friend class QDeclarativeViewPrivate; QDeclarativeViewPrivate *d; + Q_DISABLE_COPY(QDeclarativeView) }; QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index c9f7fee..bdebadf 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -671,7 +671,7 @@ void QDeclarativeXmlListModel::setNamespaceDeclarations(const QString &declarati } /*! - \qmlproperty enum XmlListModel::status + \qmlproperty enumeration XmlListModel::status Specifies the model loading status, which can be one of the following: \list |