diff options
Diffstat (limited to 'src')
22 files changed, 459 insertions, 378 deletions
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 948a084..5110ce8 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -262,11 +262,11 @@ void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation, bool isTopL void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation) { + unregisterRunningAnimation(animation); + if (!QAbstractAnimationPrivate::get(animation)->hasRegisteredTimer) return; - unregisterRunningAnimation(animation); - int idx = animations.indexOf(animation); if (idx != -1) { animations.removeAt(idx); @@ -347,34 +347,32 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) state = newState; QWeakPointer<QAbstractAnimation> guard(q); - q->updateState(oldState, newState); - if (!guard) - return; + //(un)registration of the animation must always happen before calls to + //virtual function (updateState) to ensure a correct state of the timer + bool isTopLevel = !group || group->state() == QAbstractAnimation::Stopped; + if (oldState == QAbstractAnimation::Running) { + if (newState == QAbstractAnimation::Paused && hasRegisteredTimer) + QUnifiedTimer::instance()->ensureTimerUpdate(); + //the animation, is not running any more + QUnifiedTimer::instance()->unregisterAnimation(q); + } else { + QUnifiedTimer::instance()->registerAnimation(q, isTopLevel); + } - //this is to be safe if updateState changes the state - if (state == oldState) + q->updateState(oldState, newState); + if (!guard || newState != state) //this is to be safe if updateState changes the state return; // Notify state change emit q->stateChanged(oldState, newState); - if (!guard) + if (!guard || newState != state) //this is to be safe if updateState changes the state return; switch (state) { case QAbstractAnimation::Paused: - if (hasRegisteredTimer) - // currentTime needs to be updated if pauseTimer is active - QUnifiedTimer::instance()->ensureTimerUpdate(); - if (!guard) - return; - //here we're sure that we were in running state before and that the - //animation is currently registered - QUnifiedTimer::instance()->unregisterAnimation(q); break; case QAbstractAnimation::Running: { - bool isTopLevel = !group || group->state() == QAbstractAnimation::Stopped; - QUnifiedTimer::instance()->registerAnimation(q, isTopLevel); // this ensures that the value is updated now that the animation is running if (oldState == QAbstractAnimation::Stopped) { @@ -389,15 +387,10 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) case QAbstractAnimation::Stopped: // Leave running state. int dura = q->duration(); - if (!guard) - return; if (deleteWhenStopped) q->deleteLater(); - if (oldState == QAbstractAnimation::Running) - QUnifiedTimer::instance()->unregisterAnimation(q); - if (dura == -1 || loopCount < 0 || (oldDirection == QAbstractAnimation::Forward && (oldCurrentTime * (oldCurrentLoop + 1)) == (dura * loopCount)) || (oldDirection == QAbstractAnimation::Backward && oldCurrentTime == 0)) { diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt index c85ef77..97cefd5 100644 --- a/src/declarative/QmlChanges.txt +++ b/src/declarative/QmlChanges.txt @@ -70,6 +70,8 @@ ListView: wrap -> keyNavigationWraps ListView: autoHighlight -> highlightFollowsCurrentItem GridView: wrap -> keyNavigationWraps GridView: autoHighlight -> highlightFollowsCurrentItem +Animation: targets -> matchTargets +Animation: properties -> matchProperties Additions: MouseRegion: add "acceptedButtons" property diff --git a/src/declarative/graphicsitems/qmlgraphicsanchors.cpp b/src/declarative/graphicsitems/qmlgraphicsanchors.cpp index 404daad..f6dc5fd 100644 --- a/src/declarative/graphicsitems/qmlgraphicsanchors.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsanchors.cpp @@ -152,13 +152,23 @@ void QmlGraphicsAnchorsPrivate::fillChanged() if (!fill || !isItemComplete()) return; - if (fill == item->parentItem()) { //child-parent - setItemPos(QPointF(leftMargin, topMargin)); - } else if (fill->parentItem() == item->parentItem()) { //siblings - setItemPos(QPointF(fill->x()+leftMargin, fill->y()+topMargin)); + if (updatingFill < 2) { + ++updatingFill; + + if (fill == item->parentItem()) { //child-parent + setItemPos(QPointF(leftMargin, topMargin)); + } else if (fill->parentItem() == item->parentItem()) { //siblings + setItemPos(QPointF(fill->x()+leftMargin, fill->y()+topMargin)); + } + setItemWidth(fill->width()-leftMargin-rightMargin); + setItemHeight(fill->height()-topMargin-bottomMargin); + + --updatingFill; + } else { + // ### Make this certain :) + qmlInfo(QmlGraphicsAnchors::tr("Possible anchor loop detected on fill."), item); } - setItemWidth(fill->width()-leftMargin-rightMargin); - setItemHeight(fill->height()-topMargin-bottomMargin); + } void QmlGraphicsAnchorsPrivate::centerInChanged() @@ -166,16 +176,25 @@ void QmlGraphicsAnchorsPrivate::centerInChanged() if (!centerIn || fill || !isItemComplete()) return; - if (centerIn == item->parentItem()) { - QPointF p((item->parentItem()->width() - item->width()) / 2., - (item->parentItem()->height() - item->height()) / 2.); - setItemPos(p); + if (updatingCenterIn < 2) { + ++updatingCenterIn; - } else if (centerIn->parentItem() == item->parentItem()) { + if (centerIn == item->parentItem()) { + QPointF p((item->parentItem()->width() - item->width()) / 2., + (item->parentItem()->height() - item->height()) / 2.); + setItemPos(p); - QPointF p(centerIn->x() + (centerIn->width() - item->width()) / 2., - centerIn->y() + (centerIn->height() - item->height()) / 2.); - setItemPos(p); + } else if (centerIn->parentItem() == item->parentItem()) { + + QPointF p(centerIn->x() + (centerIn->width() - item->width()) / 2., + centerIn->y() + (centerIn->height() - item->height()) / 2.); + setItemPos(p); + } + + --updatingCenterIn; + } else { + // ### Make this certain :) + qmlInfo(QmlGraphicsAnchors::tr("Possible anchor loop detected on centerIn."), item); } } diff --git a/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h b/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h index 5f8b2c1..d21d9c5 100644 --- a/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h +++ b/src/declarative/graphicsitems/qmlgraphicsanchors_p_p.h @@ -89,7 +89,7 @@ class QmlGraphicsAnchorsPrivate : public QObjectPrivate public: QmlGraphicsAnchorsPrivate() : updatingMe(false), updatingHorizontalAnchor(0), - updatingVerticalAnchor(0), item(0), usedAnchors(0), fill(0), + updatingVerticalAnchor(0), updatingFill(0), updatingCenterIn(0), item(0), usedAnchors(0), fill(0), centerIn(0), leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0), componentComplete(true) @@ -109,6 +109,8 @@ public: bool updatingMe; int updatingHorizontalAnchor; int updatingVerticalAnchor; + int updatingFill; + int updatingCenterIn; void setItemHeight(qreal); void setItemWidth(qreal); diff --git a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp index b030495..ea9c173 100644 --- a/src/declarative/graphicsitems/qmlgraphicsflickable.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsflickable.cpp @@ -1177,7 +1177,7 @@ void QmlGraphicsFlickable::setMaximumFlickVelocity(qreal v) } /*! - \qmlproperty real Flickable::maximumFlickVelocity + \qmlproperty real Flickable::flickDeceleration This property holds the rate at which a flick will decelerate. The default is 500. diff --git a/src/declarative/graphicsitems/qmlgraphicsgridview.cpp b/src/declarative/graphicsitems/qmlgraphicsgridview.cpp index 7427266..f39f5c7 100644 --- a/src/declarative/graphicsitems/qmlgraphicsgridview.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsgridview.cpp @@ -1154,7 +1154,7 @@ void QmlGraphicsGridView::keyPressEvent(QKeyEvent *event) } /*! - \qmlmethod GridView::moveCurrentIndexUp + \qmlmethod GridView::moveCurrentIndexUp() Move the currentIndex up one item in the view. The current index will wrap if keyNavigationWraps is true and it @@ -1177,7 +1177,7 @@ void QmlGraphicsGridView::moveCurrentIndexUp() } /*! - \qmlmethod GridView::moveCurrentIndexDown + \qmlmethod GridView::moveCurrentIndexDown() Move the currentIndex down one item in the view. The current index will wrap if keyNavigationWraps is true and it @@ -1200,7 +1200,7 @@ void QmlGraphicsGridView::moveCurrentIndexDown() } /*! - \qmlmethod GridView::moveCurrentIndexLeft + \qmlmethod GridView::moveCurrentIndexLeft() Move the currentIndex left one item in the view. The current index will wrap if keyNavigationWraps is true and it @@ -1223,7 +1223,7 @@ void QmlGraphicsGridView::moveCurrentIndexLeft() } /*! - \qmlmethod GridView::moveCurrentIndexRight + \qmlmethod GridView::moveCurrentIndexRight() Move the currentIndex right one item in the view. The current index will wrap if keyNavigationWraps is true and it diff --git a/src/declarative/graphicsitems/qmlgraphicsitem.cpp b/src/declarative/graphicsitems/qmlgraphicsitem.cpp index 77e6db8..572aa98 100644 --- a/src/declarative/graphicsitems/qmlgraphicsitem.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsitem.cpp @@ -389,6 +389,76 @@ void QmlGraphicsItemKeyFilter::componentComplete() if (m_next) m_next->componentComplete(); } + +/*! + \qmlclass KeyNavigation + \brief The KeyNavigation attached property supports key navigation by arrow keys. + + It is common in key-based UIs to use arrow keys to navigate + between focussed items. The KeyNavigation property provides a + convenient way of specifying which item will gain focus + when an arrow key is pressed. The following example provides + key navigation for a 2x2 grid of items. + + \code + Grid { + columns: 2 + width: 100; height: 100 + Rectangle { + id: item1 + focus: true + width: 50; height: 50 + color: focus ? "red" : "lightgray" + KeyNavigation.right: item2 + KeyNavigation.down: item3 + } + Rectangle { + id: item2 + width: 50; height: 50 + color: focus ? "red" : "lightgray" + KeyNavigation.left: item1 + KeyNavigation.down: item4 + } + Rectangle { + id: item3 + width: 50; height: 50 + color: focus ? "red" : "lightgray" + KeyNavigation.right: item4 + KeyNavigation.up: item1 + } + Rectangle { + id: item4 + width: 50; height: 50 + color: focus ? "red" : "lightgray" + KeyNavigation.left: item3 + KeyNavigation.up: item2 + } + } + \endcode + + KeyNavigation receives key events after the item it is attached to. + If the item accepts an arrow key event, the KeyNavigation + attached property will not receive an event for that key. + + If an item has been set for a direction and the KeyNavigation + attached property receives the corresponding + key press and release events, the events will be accepted by + KeyNaviagtion and will not propagate any further. + + \sa {Keys}{Keys attached property} +*/ + +/*! + \qmlproperty Item KeyNavigation::left + \qmlproperty Item KeyNavigation::right + \qmlproperty Item KeyNavigation::up + \qmlproperty Item KeyNavigation::down + + These properties hold the item to assign focus to + when Key_Left, Key_Right, Key_Up or Key_Down are + pressed. +*/ + class QmlGraphicsKeyNavigationAttachedPrivate : public QObjectPrivate { public: @@ -606,7 +676,7 @@ void QmlGraphicsKeyNavigationAttached::keyReleased(QKeyEvent *event) See \l {Qt::Key}{Qt.Key} for the list of keyboard codes. - \sa KeyEvent + \sa KeyEvent, {KeyNavigation}{KeyNavigation attached property} */ /*! @@ -1119,7 +1189,7 @@ void QmlGraphicsKeysAttached::keyPressed(QKeyEvent *event) // If we specifically handle a key then default to accepted ke.setAccepted(true); int idx = QmlGraphicsKeysAttached::staticMetaObject.indexOfSignal(keySignal); - metaObject()->method(idx).invoke(this, Q_ARG(QmlGraphicsKeysAttached, &ke)); + metaObject()->method(idx).invoke(this, Qt::DirectConnection, Q_ARG(QmlGraphicsKeyEvent*, &ke)); } } if (!ke.isAccepted()) @@ -1838,6 +1908,17 @@ void QmlGraphicsItem::setClip(bool c) */ /*! + \qmlproperty bool Item::visible + + Whether the item is visible. By default this is true. + + \note visible is not linked to actual visibility; if you item + goes off screen, or the opacity changes to 0, etc this will + not affect the visible property. +*/ + + +/*! This function is called to handle this item's changes in geometry from \a oldGeometry to \a newGeometry. If the two geometries are the same, it doesn't do anything. diff --git a/src/declarative/graphicsitems/qmlgraphicslistview.cpp b/src/declarative/graphicsitems/qmlgraphicslistview.cpp index 1f5d51d..53287a6 100644 --- a/src/declarative/graphicsitems/qmlgraphicslistview.cpp +++ b/src/declarative/graphicsitems/qmlgraphicslistview.cpp @@ -434,7 +434,6 @@ void QmlGraphicsListViewPrivate::clear() visibleIndex = 0; releaseItem(currentItem); currentItem = 0; - currentIndex = -1; createHighlight(); trackedItem = 0; } @@ -746,7 +745,7 @@ void QmlGraphicsListViewPrivate::updateCurrentSection() void QmlGraphicsListViewPrivate::updateCurrent(int modelIndex) { Q_Q(QmlGraphicsListView); - if (!isValid() || modelIndex < 0 || modelIndex >= model->count()) { + if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) { if (currentItem) { currentItem->attached->setIsCurrentItem(false); releaseItem(currentItem); @@ -1114,16 +1113,20 @@ void QmlGraphicsListView::setModel(const QVariant &model) dataModel->setModel(model); } if (d->model) { - if (d->currentIndex >= d->model->count() || d->currentIndex < 0) - setCurrentIndex(0); - else - d->updateCurrent(d->currentIndex); + if (isComponentComplete()) { + refill(); + if (d->currentIndex >= d->model->count() || d->currentIndex < 0) { + setCurrentIndex(0); + } else { + d->moveReason = QmlGraphicsListViewPrivate::SetIndex; + d->updateCurrent(d->currentIndex); + } + } connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int))); connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int))); connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int))); connect(d->model, SIGNAL(createdItem(int, QmlGraphicsItem*)), this, SLOT(createdItem(int,QmlGraphicsItem*))); connect(d->model, SIGNAL(destroyingItem(QmlGraphicsItem*)), this, SLOT(destroyingItem(QmlGraphicsItem*))); - refill(); emit countChanged(); } } @@ -1156,8 +1159,11 @@ void QmlGraphicsListView::setDelegate(QmlComponent *delegate) } if (QmlGraphicsVisualDataModel *dataModel = qobject_cast<QmlGraphicsVisualDataModel*>(d->model)) { dataModel->setDelegate(delegate); - d->updateCurrent(d->currentIndex); - refill(); + if (isComponentComplete()) { + refill(); + d->moveReason = QmlGraphicsListViewPrivate::SetIndex; + d->updateCurrent(d->currentIndex); + } } } @@ -1178,7 +1184,7 @@ int QmlGraphicsListView::currentIndex() const void QmlGraphicsListView::setCurrentIndex(int index) { Q_D(QmlGraphicsListView); - if (d->isValid() && index != d->currentIndex && index < d->model->count() && index >= 0) { + if (isComponentComplete() && d->isValid() && index != d->currentIndex && index < d->model->count() && index >= 0) { d->moveReason = QmlGraphicsListViewPrivate::SetIndex; cancelFlick(); d->updateCurrent(index); @@ -1254,7 +1260,7 @@ void QmlGraphicsListView::setHighlight(QmlComponent *highlight) is scrolled. This is because the view moves to maintain the highlight within the preferred highlight range (or visible viewport). - \sa highlight + \sa highlight, highlightMoveSpeed */ bool QmlGraphicsListView::highlightFollowsCurrentItem() const { @@ -1473,8 +1479,13 @@ QString QmlGraphicsListView::currentSection() const /*! \qmlproperty real ListView::highlightMoveSpeed + \qmlproperty real ListView::highlightResizeSpeed + These properties hold the move and resize animation speed of the highlight delegate. + + highlightFollowsCurrentItem must be true for these properties + to have effect. - This property holds the moving animation speed of the highlight delegate. + \sa highlightFollowsCurrentItem */ qreal QmlGraphicsListView::highlightMoveSpeed() const { @@ -1488,15 +1499,12 @@ void QmlGraphicsListView::setHighlightMoveSpeed(qreal speed) if (d->highlightMoveSpeed != speed) { d->highlightMoveSpeed = speed; + if (d->highlightPosAnimator) + d->highlightPosAnimator->setVelocity(d->highlightMoveSpeed); emit highlightMoveSpeedChanged(); } } -/*! - \qmlproperty real ListView::highlightResizeSpeed - - This property holds the resizing animation speed of the highlight delegate. -*/ qreal QmlGraphicsListView::highlightResizeSpeed() const { Q_D(const QmlGraphicsListView);\ @@ -1509,6 +1517,8 @@ void QmlGraphicsListView::setHighlightResizeSpeed(qreal speed) if (d->highlightResizeSpeed != speed) { d->highlightResizeSpeed = speed; + if (d->highlightSizeAnimator) + d->highlightSizeAnimator->setVelocity(d->highlightResizeSpeed); emit highlightResizeSpeedChanged(); } } @@ -1666,9 +1676,11 @@ void QmlGraphicsListView::componentComplete() { Q_D(QmlGraphicsListView); QmlGraphicsFlickable::componentComplete(); + refill(); if (d->currentIndex < 0) d->updateCurrent(0); - refill(); + else + d->updateCurrent(d->currentIndex); d->fixupPosition(); } @@ -1748,6 +1760,7 @@ void QmlGraphicsListView::itemsInserted(int modelIndex, int count) d->updateUnrequestedIndexes(); if (!d->visibleItems.count() || d->model->count() <= 1) { d->layout(); + d->updateSections(); d->updateCurrent(qMax(0, qMin(d->currentIndex, d->model->count()-1))); emit countChanged(); return; @@ -1827,6 +1840,7 @@ void QmlGraphicsListView::itemsInserted(int modelIndex, int count) added.at(j)->attached->emitAdd(); d->updateUnrequestedPositions(); d->updateViewport(); + d->updateSections(); emit countChanged(); } @@ -2009,6 +2023,7 @@ void QmlGraphicsListView::itemsMoved(int from, int to, int count) d->visibleItems.first()->setPosition(firstItemPos); d->layout(); + d->updateSections(); } void QmlGraphicsListView::createdItem(int index, QmlGraphicsItem *item) diff --git a/src/declarative/graphicsitems/qmlgraphicslistview_p.h b/src/declarative/graphicsitems/qmlgraphicslistview_p.h index 446d71a..3f46434 100644 --- a/src/declarative/graphicsitems/qmlgraphicslistview_p.h +++ b/src/declarative/graphicsitems/qmlgraphicslistview_p.h @@ -64,8 +64,11 @@ class Q_DECLARATIVE_EXPORT QmlGraphicsListView : public QmlGraphicsFlickable Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged) Q_PROPERTY(QmlGraphicsItem *currentItem READ currentItem NOTIFY currentIndexChanged) Q_PROPERTY(int count READ count NOTIFY countChanged) + Q_PROPERTY(QmlComponent *highlight READ highlight WRITE setHighlight) Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem) + Q_PROPERTY(qreal highlightMoveSpeed READ highlightMoveSpeed WRITE setHighlightMoveSpeed NOTIFY highlightMoveSpeedChanged) + Q_PROPERTY(qreal highlightResizeSpeed READ highlightResizeSpeed WRITE setHighlightResizeSpeed NOTIFY highlightResizeSpeedChanged) Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin) Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd) @@ -78,8 +81,6 @@ class Q_DECLARATIVE_EXPORT QmlGraphicsListView : public QmlGraphicsFlickable Q_PROPERTY(QString sectionExpression READ sectionExpression WRITE setSectionExpression NOTIFY sectionExpressionChanged) Q_PROPERTY(QString currentSection READ currentSection NOTIFY currentSectionChanged) - Q_PROPERTY(qreal highlightMoveSpeed READ highlightMoveSpeed WRITE setHighlightMoveSpeed NOTIFY highlightMoveSpeedChanged) - Q_PROPERTY(qreal highlightResizeSpeed READ highlightResizeSpeed WRITE setHighlightResizeSpeed NOTIFY highlightResizeSpeedChanged) Q_ENUMS(HighlightRangeMode) Q_ENUMS(Orientation) Q_CLASSINFO("DefaultProperty", "data") diff --git a/src/declarative/graphicsitems/qmlgraphicsmouseregion.cpp b/src/declarative/graphicsitems/qmlgraphicsmouseregion.cpp index 196cdf2..22c2c0a 100644 --- a/src/declarative/graphicsitems/qmlgraphicsmouseregion.cpp +++ b/src/declarative/graphicsitems/qmlgraphicsmouseregion.cpp @@ -146,19 +146,19 @@ void QmlGraphicsDrag::setYmax(qreal m) */ /*! - \qmlsignal MouseRegion::onEntered + \qmlsignal MouseRegion::onEntered() This handler is called when the mouse enters the mouse region. */ /*! - \qmlsignal MouseRegion::onExited + \qmlsignal MouseRegion::onExited() This handler is called when the mouse exists the mouse region. */ /*! - \qmlsignal MouseRegion::onPositionChanged(mouse) + \qmlsignal MouseRegion::onPositionChanged(MouseEvent mouse) This handler is called when the mouse position changes. diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 240f16c..8e92eb4 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -1714,7 +1714,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, prop->value, obj, ctxt.incr())); obj->addValueTypeProperty(prop); } else { - COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid property access")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid grouped property access")); } } else { @@ -1722,7 +1722,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, prop->value->metatype = QmlEnginePrivate::get(engine)->metaObjectForType(prop->type); if (!prop->value->metatype) - COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Cannot nest non-QObject property \"%1\"").arg(QString::fromUtf8(prop->name))); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid grouped property access")); obj->addGroupedProperty(prop); @@ -1749,8 +1749,11 @@ bool QmlCompiler::buildValueTypeProperty(QObject *type, prop->index = idx; prop->type = p.userType(); - if (prop->value || prop->values.count() != 1) - COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid property use")); + if (prop->value) + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Property assignment expected")); + + if (prop->values.count() != 1) + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Single property assignment expected")); Value *value = prop->values.at(0); @@ -1758,7 +1761,7 @@ bool QmlCompiler::buildValueTypeProperty(QObject *type, bool isPropertyValue = output->types.at(value->object->type).type->propertyValueSourceCast() != -1; bool isPropertyInterceptor = output->types.at(value->object->type).type->propertyValueInterceptorCast() != -1; if (!isPropertyValue && !isPropertyInterceptor) { - COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Invalid property use")); + COMPILE_EXCEPTION(prop, qApp->translate("QmlCompiler","Unexpected object assignment")); } else { COMPILE_CHECK(buildObject(value->object, ctxt)); diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index 7f9be0f..22d981f 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -74,7 +74,7 @@ class QmlExpressionPrivate; class QmlAbstractExpression; class QmlBinding_Id; -class QmlContextPrivate : public QObjectPrivate +class Q_DECLARATIVE_EXPORT QmlContextPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QmlContext) public: diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp index b6e794b..39d6730 100644 --- a/src/declarative/qml/qmldom.cpp +++ b/src/declarative/qml/qmldom.cpp @@ -52,8 +52,6 @@ QT_BEGIN_NAMESPACE -DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP) - QmlDomDocumentPrivate::QmlDomDocumentPrivate() : root(0) { @@ -191,11 +189,6 @@ bool QmlDomDocument::load(QmlEngine *engine, const QByteArray &data, const QUrl } if (td->data.tree()) { - if (compilerDump()) { - qWarning() << "-AST------------------------------------------------------------------------------"; - td->data.tree()->dump(); - qWarning() << "----------------------------------------------------------------------------------"; - } d->root = td->data.tree(); d->root->addref(); } diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index e46205d..177818f 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -908,7 +908,7 @@ QVariant QmlEnginePrivate::scriptValueToVariant(const QScriptValue &val) else if (dc == contextClass) return QVariant(); - QScriptClass *sc = val.scriptClass(); + QScriptDeclarativeClass *sc = QScriptDeclarativeClass::scriptClass(val); if (!sc) { return val.toVariant(); } else if (sc == valueTypeClass) { @@ -929,20 +929,7 @@ QVariant QmlScriptClass::toVariant(QmlEngine *engine, const QScriptValue &val) QmlEnginePrivate *ep = static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine)); - QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val); - if (dc == ep->objectClass) - return QVariant::fromValue(ep->objectClass->toQObject(val)); - else if (dc == ep->contextClass) - return QVariant(); - - QScriptClass *sc = val.scriptClass(); - if (!sc) { - return val.toVariant(); - } else if (sc == ep->valueTypeClass) { - return ep->valueTypeClass->toVariant(val); - } - - return QVariant(); + return ep->scriptValueToVariant(val); } // XXX this beyonds in QUrl::toLocalFile() diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index 7fd57f3..ee69b14 100644 --- a/src/declarative/qml/qmlparser.cpp +++ b/src/declarative/qml/qmlparser.cpp @@ -200,28 +200,6 @@ QmlParser::Object::DynamicSlot::DynamicSlot(const DynamicSlot &o) { } -void QmlParser::Object::dump(int indent) const -{ - QByteArray ba(indent * 4, ' '); - if (type != -1) { - qWarning() << ba.constData() << "Object:" << typeName; - } else { - qWarning() << ba.constData() << "Object: fetched"; - } - - for (QHash<QByteArray, Property *>::ConstIterator iter = properties.begin(); - iter != properties.end(); - ++iter) { - qWarning() << ba.constData() << " Property" << iter.key(); - (*iter)->dump(indent + 1); - } - - if (defaultProperty) { - qWarning() << ba.constData() << " Default property"; - defaultProperty->dump(indent + 1); - } -} - QmlParser::Property::Property() : parent(0), type(0), index(-1), value(0), isDefault(true), isDeferred(false) { @@ -256,15 +234,6 @@ bool QmlParser::Property::isEmpty() const return !value && values.isEmpty(); } -void QmlParser::Property::dump(int indent) const -{ - QByteArray ba(indent * 4, ' '); - for (int ii = 0; ii < values.count(); ++ii) - values.at(ii)->dump(indent); - if (value) - value->dump(indent); -} - QmlParser::Value::Value() : type(Unknown), object(0) { @@ -275,69 +244,6 @@ QmlParser::Value::~Value() if (object) object->release(); } -void QmlParser::Value::dump(int indent) const -{ - QByteArray type; - switch(this->type) { - default: - case Value::Unknown: - type = "Unknown"; - break; - case Value::Literal: - type = "Literal"; - break; - case Value::PropertyBinding: - type = "PropertyBinding"; - break; - case Value::ValueSource: - type = "ValueSource"; - break; - case Value::ValueInterceptor: - type = "ValueInterceptor"; - break; - case Value::CreatedObject: - type = "CreatedObject"; - break; - case Value::SignalObject: - type = "SignalObject"; - break; - case Value::SignalExpression: - type = "SignalExpression"; - break; - case Value::Id: - type = "Id"; - break; - } - - QByteArray primType; - switch(this->value.type()) { - default: - case Variant::Invalid: - primType = "Invalid"; - break; - case Variant::Boolean: - primType = "Boolean"; - break; - case Variant::Number: - primType = "Number"; - break; - case Variant::String: - primType = "String"; - break; - case Variant::Script: - primType = "Script"; - break; - } - - QByteArray ba(indent * 4, ' '); - if (object) { - qWarning() << ba.constData() << "Value (" << type << "):"; - object->dump(indent + 1); - } else { - qWarning() << ba.constData() << "Value (" << type << "):" << primType.constData() << primitive(); - } -} - QmlParser::Variant::Variant() : t(Invalid) {} diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index 5bffff2..4f080e5 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -216,8 +216,6 @@ namespace QmlParser QList<DynamicSignal> dynamicSignals; // The list of dynamic slots QList<DynamicSlot> dynamicSlots; - - void dump(int = 0) const; }; class Variant @@ -299,8 +297,6 @@ namespace QmlParser Object *object; LocationSpan location; - - void dump(int = 0) const; }; class Property : public QmlRefCount @@ -342,8 +338,6 @@ namespace QmlParser LocationSpan location; LocationRange listValueRange; QList<int> listCommaPositions; - - void dump(int = 0) const; }; } diff --git a/src/declarative/qml/qmlvaluetypescriptclass.cpp b/src/declarative/qml/qmlvaluetypescriptclass.cpp index 0c30992..e939e80 100644 --- a/src/declarative/qml/qmlvaluetypescriptclass.cpp +++ b/src/declarative/qml/qmlvaluetypescriptclass.cpp @@ -44,15 +44,14 @@ QT_BEGIN_NAMESPACE -struct QmlValueTypeReference { +struct QmlValueTypeReference : public QScriptDeclarativeClass::Object { QmlValueType *type; QGuard<QObject> object; int property; }; -Q_DECLARE_METATYPE(QmlValueTypeReference); QmlValueTypeScriptClass::QmlValueTypeScriptClass(QmlEngine *bindEngine) -: QScriptClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine) +: QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine) { } @@ -62,89 +61,83 @@ QmlValueTypeScriptClass::~QmlValueTypeScriptClass() QScriptValue QmlValueTypeScriptClass::newObject(QObject *object, int coreIndex, QmlValueType *type) { - QmlValueTypeReference ref = { type, object, coreIndex }; - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - return scriptEngine->newObject(this, scriptEngine->newVariant(qVariantFromValue(ref))); + QmlValueTypeReference *ref = new QmlValueTypeReference; + ref->type = type; + ref->object = object; + ref->property = coreIndex; + return QScriptDeclarativeClass::newObject(QmlEnginePrivate::getScriptEngine(engine), this, ref); } -QmlValueTypeScriptClass::QueryFlags -QmlValueTypeScriptClass::queryProperty(const QScriptValue &object, - const QScriptString &name, - QueryFlags flags, uint *id) +QScriptClass::QueryFlags +QmlValueTypeScriptClass::queryProperty(Object *obj, const Identifier &name, + QScriptClass::QueryFlags) { - Q_UNUSED(flags); - QmlValueTypeReference ref = - qvariant_cast<QmlValueTypeReference>(object.data().toVariant()); + QmlValueTypeReference *ref = static_cast<QmlValueTypeReference *>(obj); - if (!ref.object) + m_lastIndex = -1; + + if (!ref->object) return 0; - QByteArray propName = name.toString().toUtf8(); + QByteArray propName = toString(name).toUtf8(); - int idx = ref.type->metaObject()->indexOfProperty(propName.constData()); - if (idx == -1) + m_lastIndex = ref->type->metaObject()->indexOfProperty(propName.constData()); + if (m_lastIndex == -1) return 0; - *id = idx; - QMetaProperty prop = ref.object->metaObject()->property(idx); + QMetaProperty prop = ref->object->metaObject()->property(m_lastIndex); - QmlValueTypeScriptClass::QueryFlags rv = - QmlValueTypeScriptClass::HandlesReadAccess; + QScriptClass::QueryFlags rv = + QScriptClass::HandlesReadAccess; if (prop.isWritable()) - rv |= QmlValueTypeScriptClass::HandlesWriteAccess; + rv |= QScriptClass::HandlesWriteAccess; return rv; } -QScriptValue QmlValueTypeScriptClass::property(const QScriptValue &object, - const QScriptString &name, - uint id) +QScriptValue QmlValueTypeScriptClass::property(Object *obj, const Identifier &) { - Q_UNUSED(name); - QmlValueTypeReference ref = - qvariant_cast<QmlValueTypeReference>(object.data().toVariant()); - - if (!ref.object) - return QScriptValue(); + QmlValueTypeReference *ref = static_cast<QmlValueTypeReference *>(obj); - ref.type->read(ref.object, ref.property); - - QMetaProperty p = ref.type->metaObject()->property(id); - QVariant rv = p.read(ref.type); + QMetaProperty p = ref->type->metaObject()->property(m_lastIndex); + ref->type->read(ref->object, ref->property); + QVariant rv = p.read(ref->type); return static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine))->scriptValueFromVariant(rv); } -void QmlValueTypeScriptClass::setProperty(QScriptValue &object, - const QScriptString &name, - uint id, +void QmlValueTypeScriptClass::setProperty(Object *obj, const Identifier &, const QScriptValue &value) { - Q_UNUSED(name); - QmlValueTypeReference ref = - qvariant_cast<QmlValueTypeReference>(object.data().toVariant()); - - if (!ref.object) - return; + QmlValueTypeReference *ref = static_cast<QmlValueTypeReference *>(obj); QVariant v = QmlScriptClass::toVariant(engine, value); - ref.type->read(ref.object, ref.property); - QMetaProperty p = ref.type->metaObject()->property(id); - p.write(ref.type, v); - ref.type->write(ref.object, ref.property, 0); + ref->type->read(ref->object, ref->property); + QMetaProperty p = ref->type->metaObject()->property(m_lastIndex); + p.write(ref->type, v); + ref->type->write(ref->object, ref->property, 0); } -QVariant QmlValueTypeScriptClass::toVariant(const QScriptValue &val) +QVariant QmlValueTypeScriptClass::toVariant(Object *obj, bool *ok) { - QmlValueTypeReference ref = - qvariant_cast<QmlValueTypeReference>(val.data().toVariant()); + QmlValueTypeReference *ref = static_cast<QmlValueTypeReference *>(obj); - if (!ref.object) + if (ok) *ok = true; + + if (ref->object) { + ref->type->read(ref->object, ref->property); + return ref->type->value(); + } else { return QVariant(); + } +} + +QVariant QmlValueTypeScriptClass::toVariant(const QScriptValue &value) +{ + Q_ASSERT(scriptClass(value) == this); - QMetaProperty p = ref.object->metaObject()->property(ref.property); - return p.read(ref.object); + return toVariant(object(value), 0); } QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlvaluetypescriptclass_p.h b/src/declarative/qml/qmlvaluetypescriptclass_p.h index bd31ec1..19020b2 100644 --- a/src/declarative/qml/qmlvaluetypescriptclass_p.h +++ b/src/declarative/qml/qmlvaluetypescriptclass_p.h @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE class QmlEngine; class QmlValueType; -class QmlValueTypeScriptClass : public QScriptClass +class QmlValueTypeScriptClass : public QScriptDeclarativeClass { public: QmlValueTypeScriptClass(QmlEngine *); @@ -67,20 +67,16 @@ public: QScriptValue newObject(QObject *object, int coreIndex, QmlValueType *); - virtual QueryFlags queryProperty(const QScriptValue &object, - const QScriptString &name, - QueryFlags flags, uint *id); - virtual QScriptValue property(const QScriptValue &object, - const QScriptString &name, - uint id); - virtual void setProperty(QScriptValue &object, - const QScriptString &name, - uint id, - const QScriptValue &value); + virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, + QScriptClass::QueryFlags flags); + virtual QScriptValue property(Object *, const Identifier &); + virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); + virtual QVariant toVariant(Object *, bool *ok = 0); QVariant toVariant(const QScriptValue &); private: QmlEngine *engine; + int m_lastIndex; }; QT_END_NAMESPACE diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp index bd4c6f7..94cdadf 100644 --- a/src/declarative/util/qmlanimation.cpp +++ b/src/declarative/util/qmlanimation.cpp @@ -422,21 +422,6 @@ void QmlAbstractAnimation::setGroup(QmlAnimationGroup *g) setParent(g); } -/*! - \qmlproperty Object PropertyAction::target - This property holds an explicit target object to animate. - - The exact effect of the \c target property depends on how the animation - is being used. Refer to the \l animation documentation for details. -*/ - -/*! - \qmlproperty Object PropertyAnimation::target - This property holds an explicit target object to animate. - - The exact effect of the \c target property depends on how the animation - is being used. Refer to the \l animation documentation for details. -*/ QObject *QmlAbstractAnimation::target() const { Q_D(const QmlAbstractAnimation); @@ -459,21 +444,6 @@ void QmlAbstractAnimation::setTarget(QObject *o) emit targetChanged(d->target, d->propertyName); } -/*! - \qmlproperty string PropertyAction::property - This property holds an explicit property to animated. - - The exact effect of the \c property property depends on how the animation - is being used. Refer to the \l animation documentation for details. -*/ - -/*! - \qmlproperty string PropertyAnimation::property - This property holds an explicit property to animated. - - The exact effect of the \c property property depends on how the animation - is being used. Refer to the \l animation documentation for details. -*/ QString QmlAbstractAnimation::property() const { Q_D(const QmlAbstractAnimation); @@ -880,7 +850,7 @@ QML_DEFINE_TYPE(Qt,4,6,ScriptAction,QmlScriptAction) Set \c thewebview.url to the value set for the destination state: \code - PropertyAction { target: thewebview; property: "url" } + PropertyAction { matchTargets: thewebview; matchProperties: "url" } \endcode The PropertyAction is immediate - @@ -909,8 +879,33 @@ void QmlPropertyActionPrivate::init() } /*! - \qmlproperty string PropertyAction::properties - This property holds the properties to be immediately set, comma-separated. + \qmlproperty Object PropertyAction::target + This property holds an explicit target object to animate. + + The exact effect of the \c target property depends on how the animation + is being used. Refer to the \l animation documentation for details. +*/ + +/*! + \qmlproperty string PropertyAction::property + This property holds an explicit property to animated. + + The exact effect of the \c property property depends on how the animation + is being used. Refer to the \l animation documentation for details. +*/ + +/*! + \qmlproperty string PropertyAction::matchProperties + This property holds a comma-separated list of property names this action + will match against. These names are used in conjunction with matchTargets + to create a list of properties that the action will set, assuming those + properties have changed. + + This property is typically used for an action appearing as part of a Transition. + + By default, no property names will be matched. + + \sa matchTargets PropertyAnimation::matchProperties */ QString QmlPropertyAction::properties() const { @@ -928,9 +923,16 @@ void QmlPropertyAction::setProperties(const QString &p) } /*! - \qmlproperty list<Item> PropertyAction::targets - This property holds the items selected to be affected by this animation (all if not set). - \sa exclude + \qmlproperty list<Object> PropertyAction::matchTargets + This property holds a list of objects this action will match against. + These objects are used in conjunction with matchProperties to create a list of properties + that the action will set, assuming those properties have changed. + + This property is typically used for an action appearing as part of a Transition. + + By default, all changing targets will be matched. + + \sa exclude matchProperties PropertyAnimation::matchTargets */ QList<QObject *> *QmlPropertyAction::targets() { @@ -939,9 +941,9 @@ QList<QObject *> *QmlPropertyAction::targets() } /*! - \qmlproperty list<Item> PropertyAction::exclude - This property holds the items not to be affected by this animation. - \sa targets + \qmlproperty list<Object> PropertyAction::exclude + This property holds the objects not to be affected by this animation. + \sa matchTargets */ QList<QObject *> *QmlPropertyAction::exclude() { @@ -1014,19 +1016,26 @@ void QmlPropertyAction::transition(QmlStateActions &actions, QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(',')); for (int ii = 0; ii < props.count(); ++ii) props[ii] = props.at(ii).trimmed(); - if (!d->propertyName.isEmpty() && !props.contains(d->propertyName)) - props.append(d->propertyName); - - bool targetNeedsReset = false; - if (d->userProperty.isValid() && props.isEmpty() && !target()) { - props.append(d->userProperty.value.name()); - d->target = d->userProperty.value.object(); - targetNeedsReset = true; - } + + bool hasSelectors = !props.isEmpty() || !d->targets.isEmpty() || !d->exclude.isEmpty(); + bool hasTarget = !d->propertyName.isEmpty() || d->target; + + if (hasSelectors && hasTarget) { + qmlInfo(tr("matchTargets/matchProperties/exclude and target/property are mutually exclusive."), this); + return; + } QmlSetPropertyAnimationAction *data = new QmlSetPropertyAnimationAction; - QSet<QObject *> objs; + if (hasTarget && d->value.isValid()) { + Action myAction; + myAction.property = d->createProperty(target(), d->propertyName); + if (myAction.property.isValid()) { + myAction.toValue = d->value; + data->actions << myAction; + } + } + for (int ii = 0; ii < actions.count(); ++ii) { Action &action = actions[ii]; @@ -1038,9 +1047,7 @@ void QmlPropertyAction::transition(QmlStateActions &actions, if ((d->targets.isEmpty() || d->targets.contains(obj) || (!same && d->targets.contains(sObj))) && (!d->exclude.contains(obj)) && (same || (!d->exclude.contains(sObj))) && - (props.contains(propertyName) || (!same && props.contains(sPropertyName))) && - (!target() || target() == obj || (!same && target() == sObj))) { - objs.insert(obj); + (props.contains(propertyName) || (!same && props.contains(sPropertyName)))) { Action myAction = action; if (d->value.isValid()) @@ -1049,18 +1056,20 @@ void QmlPropertyAction::transition(QmlStateActions &actions, modified << action.property; data->actions << myAction; action.fromValue = myAction.toValue; - } - } + } else if (d->userProperty.isValid() && + !hasSelectors && !hasTarget) { + if ((d->userProperty.value.object() == obj || (!same && d->userProperty.value.object() == sObj)) && + (d->userProperty.value.name() == propertyName || (!same && d->userProperty.value.name() == sPropertyName))) { + //### same as above. merge + Action myAction = action; - if (d->value.isValid() && target() && !objs.contains(target())) { - QObject *obj = target(); - for (int jj = 0; jj < props.count(); ++jj) { - Action myAction; - myAction.property = d->createProperty(obj, props.at(jj)); - if (!myAction.property.isValid()) - continue; - myAction.toValue = d->value; - data->actions << myAction; + if (d->value.isValid()) + myAction.toValue = d->value; + + modified << action.property; + data->actions << myAction; + action.fromValue = myAction.toValue; + } } } @@ -1069,8 +1078,6 @@ void QmlPropertyAction::transition(QmlStateActions &actions, } else { delete data; } - if (targetNeedsReset) - d->target = 0; } QML_DEFINE_TYPE(Qt,4,6,PropertyAction,QmlPropertyAction) @@ -1222,7 +1229,7 @@ QML_DEFINE_TYPE(Qt,4,6,ParentAction,QmlParentAction) Animate a set of properties over 200ms, from their values in the start state to their values in the end state of the transition: \code - NumberAnimation { properties: "x,y,scale"; duration: 200 } + NumberAnimation { matchProperties: "x,y,scale"; duration: 200 } \endcode */ @@ -1500,6 +1507,8 @@ void QmlPropertyAnimationPrivate::convertVariant(QVariant &variant, int type) \code VariantAnimation { property: "size"; to: "20x20"; duration: 200 } \endcode + + \a qmlanimation.html */ QmlPropertyAnimation::QmlPropertyAnimation(QObject *parent) @@ -1785,11 +1794,53 @@ void QmlPropertyAnimation::setEasing(const QString &e) } /*! - \qmlproperty string PropertyAnimation::properties - This property holds the properties this animation should be applied to. + \qmlproperty Object PropertyAnimation::target + This property holds an explicit target object to animate. + + target is used in conjunction with property to determine + what property should be animated. + + \sa property matchTargets +*/ + +/*! + \qmlproperty string PropertyAnimation::property + This property holds an explicit property name to animate. + + property is used in conjunction with target to determine + what property should be animated. + + \sa target matchProperties +*/ + +/*! + \qmlproperty string PropertyAnimation::matchProperties + This property holds a comma-separated list of property names this animation + will match against. These names are used in conjunction with matchTargets + to create a list of properties that the animation will animate, assuming those + properties have changed. + + In the following example, the change in 'x' will be animated by the transition, while + the change in 'y' will not. + \qml + State { + PropertyChanges { + target: myItem + x: 15; y: 15 + } + } + Transition { + PropertyAnimation { + matchProperties: "x" + } + } + \endqml + + This property is typically used for an animation appearing as part of a Transition. + + By default, no property names will be matched. - This is a comma-separated list of properties that should use - this animation when they change. + \sa matchTargets PropertyAction::matchTargets */ QString QmlPropertyAnimation::properties() const { @@ -1808,9 +1859,37 @@ void QmlPropertyAnimation::setProperties(const QString &prop) } /*! - \qmlproperty list<Item> PropertyAnimation::targets - This property holds the items selected to be affected by this animation (all if not set). - \sa exclude + \qmlproperty list<Object> PropertyAnimation::matchTargets + This property holds a list of objects this animation will match against. + These objects are used in conjunction with matchProperties to create a list of properties + that the animation will animate, assuming those properties have changed. + + In the following example, the changes to \c myItem will be animated by the transition, while + the changes to \c myOtherItem will not. + \qml + State { + PropertyChanges { + target: myItem + x: 15; y: 15 + } + PropertyChanges { + target: myOtherItem + x: 30; y: 30 + } + } + Transition { + PropertyAnimation { + matchTargets: myItem + matchProperties: "x,y" + } + } + \endqml + + This property is typically used for an animation appearing as part of a Transition. + + By default, all changing targets will be matched. + + \sa exclude matchProperties */ QList<QObject *> *QmlPropertyAnimation::targets() { @@ -1819,9 +1898,9 @@ QList<QObject *> *QmlPropertyAnimation::targets() } /*! - \qmlproperty list<Item> PropertyAnimation::exclude + \qmlproperty list<Object> PropertyAnimation::exclude This property holds the items not to be affected by this animation. - \sa targets + \sa matchTargets */ QList<QObject *> *QmlPropertyAnimation::exclude() { @@ -1933,24 +2012,37 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, QStringList props = d->properties.isEmpty() ? QStringList() : d->properties.split(QLatin1Char(',')); for (int ii = 0; ii < props.count(); ++ii) props[ii] = props.at(ii).trimmed(); - if (!d->propertyName.isEmpty() && !props.contains(d->propertyName)) - props.append(d->propertyName); - bool useType = (props.isEmpty() && d->defaultToInterpolatorType) ? true : false; + bool hasSelectors = !props.isEmpty() || !d->targets.isEmpty() || !d->exclude.isEmpty(); + bool hasTarget = !d->propertyName.isEmpty() || d->target; - bool targetNeedsReset = false; - if (d->userProperty.isValid() && props.isEmpty() && !target()) { - props.append(d->userProperty.value.name()); - d->target = d->userProperty.value.object(); - targetNeedsReset = true; + if (hasSelectors && hasTarget) { + qmlInfo(tr("matchTargets/matchProperties/exclude and target/property are mutually exclusive."), this); + return; } + bool useType = (props.isEmpty() && d->propertyName.isEmpty() && d->defaultToInterpolatorType) ? true : false; + PropertyUpdater *data = new PropertyUpdater; data->interpolatorType = d->interpolatorType; data->interpolator = d->interpolator; data->reverse = direction == Backward ? true : false; - QSet<QObject *> objs; + //an explicit animation has been specified + if (hasTarget && d->toIsDefined) { + Action myAction; + myAction.property = d->createProperty(target(), d->propertyName); + if (myAction.property.isValid()) { + if (d->fromIsDefined) { + d->convertVariant(d->from, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()); + myAction.fromValue = d->from; + } + d->convertVariant(d->to, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()); + myAction.toValue = d->to; + data->actions << myAction; + } + } + for (int ii = 0; ii < actions.count(); ++ii) { Action &action = actions[ii]; @@ -1963,16 +2055,13 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, if ((d->targets.isEmpty() || d->targets.contains(obj) || (!same && d->targets.contains(sObj))) && (!d->exclude.contains(obj)) && (same || (!d->exclude.contains(sObj))) && (props.contains(propertyName) || (!same && props.contains(sPropertyName)) - || (useType && action.property.propertyType() == d->interpolatorType)) && - (!target() || target() == obj || (!same && target() == sObj))) { - objs.insert(obj); + || (useType && action.property.propertyType() == d->interpolatorType))) { Action myAction = action; - if (d->fromIsDefined) { + if (d->fromIsDefined) myAction.fromValue = d->from; - } else { + else myAction.fromValue = QVariant(); - } if (d->toIsDefined) myAction.toValue = d->to; @@ -1983,25 +2072,29 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, data->actions << myAction; action.fromValue = myAction.toValue; - } - } - - if (d->toIsDefined && target() && !objs.contains(target())) { - QObject *obj = target(); - for (int jj = 0; jj < props.count(); ++jj) { - Action myAction; - myAction.property = d->createProperty(obj, props.at(jj)); - if (!myAction.property.isValid()) - continue; - - if (d->fromIsDefined) { - d->convertVariant(d->from, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()); - myAction.fromValue = d->from; - } - d->convertVariant(d->to, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()); - myAction.toValue = d->to; - data->actions << myAction; - } + } else if (d->userProperty.isValid() && + !hasSelectors && !hasTarget) { + if ((d->userProperty.value.object() == obj || (!same && d->userProperty.value.object() == sObj)) && + (d->userProperty.value.name() == propertyName || (!same && d->userProperty.value.name() == sPropertyName))) { + //### same as above. merge + Action myAction = action; + + if (d->fromIsDefined) + myAction.fromValue = d->from; + else + myAction.fromValue = QVariant(); + if (d->toIsDefined) + myAction.toValue = d->to; + + d->convertVariant(myAction.fromValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()); + d->convertVariant(myAction.toValue, d->interpolatorType ? d->interpolatorType : myAction.property.propertyType()); + + modified << action.property; + + data->actions << myAction; + action.fromValue = myAction.toValue; + } + } } if (data->actions.count()) { @@ -2009,8 +2102,6 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, } else { delete data; } - if (targetNeedsReset) - d->target = 0; } QML_DEFINE_TYPE(Qt,4,6,PropertyAnimation,QmlPropertyAnimation) diff --git a/src/declarative/util/qmlanimation_p.h b/src/declarative/util/qmlanimation_p.h index 214bab9..3a9839e 100644 --- a/src/declarative/util/qmlanimation_p.h +++ b/src/declarative/util/qmlanimation_p.h @@ -191,8 +191,8 @@ class QmlPropertyAction : public QmlAbstractAnimation Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged) Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY targetChanged) - Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged) - Q_PROPERTY(QList<QObject *>* targets READ targets) + Q_PROPERTY(QString matchProperties READ properties WRITE setProperties NOTIFY propertiesChanged) + Q_PROPERTY(QList<QObject *>* matchTargets READ targets) Q_PROPERTY(QList<QObject *>* exclude READ exclude) Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged) @@ -260,8 +260,8 @@ class Q_AUTOTEST_EXPORT QmlPropertyAnimation : public QmlAbstractAnimation Q_PROPERTY(QString easing READ easing WRITE setEasing NOTIFY easingChanged) Q_PROPERTY(QObject *target READ target WRITE setTarget NOTIFY targetChanged) Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY targetChanged) - Q_PROPERTY(QString properties READ properties WRITE setProperties NOTIFY propertiesChanged) - Q_PROPERTY(QList<QObject *>* targets READ targets) + Q_PROPERTY(QString matchProperties READ properties WRITE setProperties NOTIFY propertiesChanged) + Q_PROPERTY(QList<QObject *>* matchTargets READ targets) Q_PROPERTY(QList<QObject *>* exclude READ exclude) public: diff --git a/src/declarative/util/qmltimer.cpp b/src/declarative/util/qmltimer.cpp index 0aa0747..8ee9059 100644 --- a/src/declarative/util/qmltimer.cpp +++ b/src/declarative/util/qmltimer.cpp @@ -176,6 +176,11 @@ void QmlTimer::setRepeating(bool repeating) /*! \qmlproperty bool Timer::triggeredOnStart + When the Timer is started the first trigger is normally after the specified + interval has elapsed. It is sometimes desireable to trigger immediately + when the timer is started, for example to establish an initial + state. + If \a triggeredOnStart is true, the timer will be triggered immediately when started, and subsequently at the specified interval. Note that for a Timer with \e repeat set to false, this will result in the timer being diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp index 9fd9ce9..fe7f5d7 100644 --- a/src/gui/styles/qwindowsxpstyle.cpp +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -2926,10 +2926,10 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } // Draw arrow p->save(); - p->setPen(option->palette.dark()); + p->setPen(option->palette.dark().color()); p->drawLine(menuarea.left(), menuarea.top() + 3, menuarea.left(), menuarea.bottom() - 3); - p->setPen(option->palette.light()); + p->setPen(option->palette.light().color()); p->drawLine(menuarea.left() - 1, menuarea.top() + 3, menuarea.left() - 1, menuarea.bottom() - 3); |