diff options
author | Martin Jones <martin.jones@nokia.com> | 2009-10-12 06:56:50 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2009-10-12 06:56:50 (GMT) |
commit | 7421702dd3202c21f3871171792476f0d2d50abe (patch) | |
tree | 5a45e20fd74e23cf0a4ad2aa1a80bd073fa51413 /src | |
parent | 9094a6588de3a7264ec4647a24b94253a7609823 (diff) | |
parent | 949e21cdafeec0c0e4ac632ebbf21767479f04e5 (diff) | |
download | Qt-7421702dd3202c21f3871171792476f0d2d50abe.zip Qt-7421702dd3202c21f3871171792476f0d2d50abe.tar.gz Qt-7421702dd3202c21f3871171792476f0d2d50abe.tar.bz2 |
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
Conflicts:
src/declarative/qml/qmlcompiler.cpp
Diffstat (limited to 'src')
71 files changed, 831 insertions, 587 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index f98c449..10eb955 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -2237,7 +2237,10 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const // -1 (unchanged): normal qt_metacall, result stored in argv[0] // changed: result stored directly in value, return the value of status int status = -1; - void *argv[] = { 0, &v, &status }; + // the flags variable is used by the declarative module to implement + // interception of property writes. + int flags = 0; + void *argv[] = { 0, &v, &status, &flags }; if (t == QVariant::LastType) argv[0] = &v; else diff --git a/src/declarative/debugger/qmldebug.cpp b/src/declarative/debugger/qmldebug.cpp index a515c1d..1ef7503 100644 --- a/src/declarative/debugger/qmldebug.cpp +++ b/src/declarative/debugger/qmldebug.cpp @@ -276,7 +276,7 @@ QmlDebugPropertyWatch *QmlEngineDebug::addWatch(const QmlDebugPropertyReference QByteArray message; QDataStream ds(&message, QIODevice::WriteOnly); - ds << QByteArray("WATCH_PROPERTY") << queryId << property.objectDebugId() << property.name().toLatin1(); + ds << QByteArray("WATCH_PROPERTY") << queryId << property.objectDebugId() << property.name().toUtf8(); d->client->sendMessage(message); } else { watch->m_state = QmlDebugWatch::Dead; diff --git a/src/declarative/debugger/qmldebugservice.cpp b/src/declarative/debugger/qmldebugservice.cpp index b83a4b1..6913def 100644 --- a/src/declarative/debugger/qmldebugservice.cpp +++ b/src/declarative/debugger/qmldebugservice.cpp @@ -353,7 +353,7 @@ QString QmlDebugService::objectToString(QObject *obj) if(objectName.isEmpty()) objectName = QLatin1String("<unnamed>"); - QString rv = QLatin1String(obj->metaObject()->className()) + + QString rv = QString::fromUtf8(obj->metaObject()->className()) + QLatin1String(": ") + objectName; return rv; diff --git a/src/declarative/extra/qbindablemap.cpp b/src/declarative/extra/qbindablemap.cpp index c8c8ced..5254e2a 100644 --- a/src/declarative/extra/qbindablemap.cpp +++ b/src/declarative/extra/qbindablemap.cpp @@ -58,7 +58,7 @@ public: protected: virtual void propertyWrite(int index) { - map->emitChanged(QLatin1String(name(index))); + map->emitChanged(QString::fromUtf8(name(index))); } private: @@ -130,7 +130,7 @@ QBindableMap::~QBindableMap() void QBindableMap::clearValue(const QString &key) { //m_keys.remove(); //### - m_mo->setValue(key.toLatin1(), QVariant()); + m_mo->setValue(key.toUtf8(), QVariant()); //emit changed(key); } @@ -142,7 +142,7 @@ void QBindableMap::clearValue(const QString &key) */ QVariant QBindableMap::value(const QString &key) const { - return m_mo->value(key.toLatin1()); + return m_mo->value(key.toUtf8()); } /*! @@ -154,7 +154,7 @@ void QBindableMap::setValue(const QString &key, QVariant value) { if (!m_keys.contains(key)) m_keys.append(key); - m_mo->setValue(key.toLatin1(), value); + m_mo->setValue(key.toUtf8(), value); //emit changed(key); } diff --git a/src/declarative/extra/qfxparticles.cpp b/src/declarative/extra/qfxparticles.cpp index b4a04a9..36fdd79 100644 --- a/src/declarative/extra/qfxparticles.cpp +++ b/src/declarative/extra/qfxparticles.cpp @@ -111,6 +111,7 @@ QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,ParticleMotion,QFxParticleMotion \class QFxParticleMotion \ingroup group_effects \brief The QFxParticleMotion class is the base class for particle motion. + \internal This class causes the particles to remain static. */ diff --git a/src/declarative/extra/qmlbehavior.cpp b/src/declarative/extra/qmlbehavior.cpp index 7784ef5..e30bd39 100644 --- a/src/declarative/extra/qmlbehavior.cpp +++ b/src/declarative/extra/qmlbehavior.cpp @@ -44,180 +44,77 @@ #include "qmltransition.h" #include "qmlbehavior.h" #include <QtDeclarative/qmlcontext.h> +#include <QtDeclarative/qmlinfo.h> #include <QtCore/qparallelanimationgroup.h> QT_BEGIN_NAMESPACE QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,Behavior,QmlBehavior) -class QmlBehaviorData : public QObject -{ -Q_OBJECT -public: - QmlBehaviorData(QObject *parent) - : QObject(parent) {} - - Q_PROPERTY(QVariant endValue READ endValue NOTIFY valuesChanged) - Q_PROPERTY(QVariant startValue READ startValue NOTIFY valuesChanged) - QVariant endValue() const { return e; } - QVariant startValue() const { return s; } - - QVariant e; - QVariant s; - -Q_SIGNALS: - void valuesChanged(); - -private: - friend class QmlBehavior; -}; - class QmlBehaviorPrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QmlBehavior) public: - QmlBehaviorPrivate() : operations(this) {} + QmlBehaviorPrivate() : animation(0) {} + QmlMetaProperty property; QVariant currentValue; - - QVariant fromValue; - QVariant toValue; - class AnimationList : public QmlConcreteList<QmlAbstractAnimation *> - { - public: - AnimationList(QmlBehaviorPrivate *parent) : _parent(parent) {} - virtual void append(QmlAbstractAnimation *a) - { - QmlConcreteList<QmlAbstractAnimation *>::append(a); - _parent->group->addAnimation(a->qtAnimation()); - if (_parent->property.isValid()) { - a->setTarget(_parent->property); - } - } - virtual void clear() { QmlConcreteList<QmlAbstractAnimation *>::clear(); } //### - private: - QmlBehaviorPrivate *_parent; - }; - AnimationList operations; - QParallelAnimationGroup *group; + QmlAbstractAnimation *animation; }; -/*! - \qmlclass Behavior QmlBehavior - \brief The Behavior element allows you to specify a default animation for a property change. - - In example below, the rect will use a bounce easing curve over 200 millisecond for any changes to its y property: - \code - Rectangle { - width: 20; height: 20 - color: "#00ff00" - y: 200 //initial value - y: Behavior { - NumberAnimation { - easing: "easeOutBounce(amplitude:100)" - duration: 200 - } - } - } - \endcode -*/ - QmlBehavior::QmlBehavior(QObject *parent) -: QObject(*(new QmlBehaviorPrivate), parent) -{ - Q_D(QmlBehavior); - d->group = new QParallelAnimationGroup; - QFx_setParent_noEvent(d->group, this); -} - -/*! - \qmlproperty QVariant Behavior::from - This property holds a selector specifying a starting value for the behavior. - - If you only want the behavior to apply when the change starts at a - specific value you can specify fromValue. This selector is used in conjunction - with the to selector. -*/ - -QVariant QmlBehavior::fromValue() const + : QObject(*(new QmlBehaviorPrivate), parent) { - Q_D(const QmlBehavior); - return d->fromValue; } -void QmlBehavior::setFromValue(const QVariant &v) +QmlAbstractAnimation *QmlBehavior::animation() { Q_D(QmlBehavior); - d->fromValue = v; + return d->animation; } -/*! - \qmlproperty QVariant Behavior::to - This property holds a selector specifying a ending value for the behavior. - - If you only want the behavior to apply when the change ends at a - specific value you can specify toValue. This selector is used in conjunction - with the from selector. -*/ - -QVariant QmlBehavior::toValue() const -{ - Q_D(const QmlBehavior); - return d->toValue; -} - -void QmlBehavior::setToValue(const QVariant &v) +void QmlBehavior::setAnimation(QmlAbstractAnimation *animation) { Q_D(QmlBehavior); - d->toValue = v; -} + if (d->animation) { + qmlInfo(this) << "Can't change the animation assigned to a Behavior."; + return; + } -QmlList<QmlAbstractAnimation *>* QmlBehavior::operations() -{ - Q_D(QmlBehavior); - return &d->operations; + d->animation = animation; + if (d->animation) + d->animation->setTarget(d->property); } QmlBehavior::~QmlBehavior() { - //### do we need any other cleanup here? } -bool QmlBehavior::_ignore = false; -void QmlBehavior::propertyValueChanged() +void QmlBehavior::write(const QVariant &value) { Q_D(QmlBehavior); - if (_ignore) + if (!d->animation) { + d->property.write(value, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); return; + } - QVariant newValue = d->property.read(); - - if ((!fromValue().isValid() || fromValue() == d->currentValue) && - (!toValue().isValid() || toValue() == newValue)) { - - //### does this clean up everything needed? - d->group->stop(); - - QmlStateOperation::ActionList actions; - Action action; - action.property = d->property; - action.fromValue = d->currentValue; - action.toValue = newValue; - actions << action; + d->currentValue = d->property.read(); - _ignore = true; - d->property.write(d->currentValue); + d->animation->qtAnimation()->stop(); - QList<QmlMetaProperty> after; - for (int ii = 0; ii < d->operations.count(); ++ii) { - d->operations.at(ii)->transition(actions, after, QmlAbstractAnimation::Forward); - } - d->group->start(); - if (!after.contains(d->property)) - d->property.write(newValue); - _ignore = false; - } + QmlStateOperation::ActionList actions; + Action action; + action.property = d->property; + action.fromValue = d->currentValue; + action.toValue = value; + actions << action; - d->currentValue = newValue; + QList<QmlMetaProperty> after; + if (d->animation) + d->animation->transition(actions, after, QmlAbstractAnimation::Forward); + d->animation->qtAnimation()->start(); + if (!after.contains(d->property)) + d->property.write(value, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } void QmlBehavior::setTarget(const QmlMetaProperty &property) @@ -225,12 +122,8 @@ void QmlBehavior::setTarget(const QmlMetaProperty &property) Q_D(QmlBehavior); d->property = property; d->currentValue = property.read(); - d->property.connectNotifier(this, SLOT(propertyValueChanged())); - for (int ii = 0; ii < d->operations.count(); ++ii) { - d->operations.at(ii)->setTarget(property); - } + if (d->animation) + d->animation->setTarget(property); } QT_END_NAMESPACE - -#include "qmlbehavior.moc" diff --git a/src/declarative/extra/qmlbehavior.h b/src/declarative/extra/qmlbehavior.h index a4a0679..994d85c 100644 --- a/src/declarative/extra/qmlbehavior.h +++ b/src/declarative/extra/qmlbehavior.h @@ -43,6 +43,7 @@ #define QMLBEHAVIOR_H #include <QtDeclarative/qmlpropertyvaluesource.h> +#include <QtDeclarative/qmlpropertyvalueinterceptor.h> #include <QtDeclarative/qml.h> #include <QtDeclarative/qmlstate.h> @@ -54,32 +55,23 @@ QT_MODULE(Declarative) class QmlAbstractAnimation; class QmlBehaviorPrivate; -class Q_DECLARATIVE_EXPORT QmlBehavior : public QObject, public QmlPropertyValueSource +class Q_DECLARATIVE_EXPORT QmlBehavior : public QObject, public QmlPropertyValueInterceptor { Q_OBJECT Q_DECLARE_PRIVATE(QmlBehavior) - Q_PROPERTY(QVariant from READ fromValue WRITE setFromValue) - Q_PROPERTY(QVariant to READ toValue WRITE setToValue) - Q_CLASSINFO("DefaultProperty", "operations") - Q_PROPERTY(QmlList<QmlAbstractAnimation *>* operations READ operations) + Q_CLASSINFO("DefaultProperty", "animation") + Q_PROPERTY(QmlAbstractAnimation *animation READ animation WRITE setAnimation) public: QmlBehavior(QObject *parent=0); ~QmlBehavior(); - QVariant fromValue() const; - void setFromValue(const QVariant &); - QVariant toValue() const; - void setToValue(const QVariant &); virtual void setTarget(const QmlMetaProperty &); + virtual void write(const QVariant &value); - QmlList<QmlAbstractAnimation *>* operations(); - - static bool _ignore; - -private Q_SLOTS: - void propertyValueChanged(); + QmlAbstractAnimation *animation(); + void setAnimation(QmlAbstractAnimation *); }; QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxborderimage.cpp b/src/declarative/fx/qfxborderimage.cpp index 6616912..8f98a11 100644 --- a/src/declarative/fx/qfxborderimage.cpp +++ b/src/declarative/fx/qfxborderimage.cpp @@ -273,7 +273,7 @@ void QFxBorderImage::setHorizontalTileMode(TileMode t) Q_D(QFxBorderImage); if (t != d->horizontalTileMode) { d->horizontalTileMode = t; - emit tileModeChanged(); + emit horizontalTileModeChanged(); update(); } } @@ -289,7 +289,7 @@ void QFxBorderImage::setVerticalTileMode(TileMode t) Q_D(QFxBorderImage); if (t != d->verticalTileMode) { d->verticalTileMode = t; - emit tileModeChanged(); + emit verticalTileModeChanged(); update(); } } diff --git a/src/declarative/fx/qfxborderimage.h b/src/declarative/fx/qfxborderimage.h index eae9bd1..5bc1067 100644 --- a/src/declarative/fx/qfxborderimage.h +++ b/src/declarative/fx/qfxborderimage.h @@ -59,8 +59,8 @@ class Q_DECLARATIVE_EXPORT QFxBorderImage : public QFxImageBase Q_ENUMS(TileMode) Q_PROPERTY(QFxScaleGrid *border READ border CONSTANT) - Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY tileModeChanged) - Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY tileModeChanged) + Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged) + Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged) public: QFxBorderImage(QFxItem *parent=0); @@ -80,7 +80,8 @@ public: void setSource(const QUrl &url); Q_SIGNALS: - void tileModeChanged(); + void horizontalTileModeChanged(); + void verticalTileModeChanged(); protected: QFxBorderImage(QFxBorderImagePrivate &dd, QFxItem *parent); diff --git a/src/declarative/fx/qfxgridview.cpp b/src/declarative/fx/qfxgridview.cpp index 2d25d56..6abe88e 100644 --- a/src/declarative/fx/qfxgridview.cpp +++ b/src/declarative/fx/qfxgridview.cpp @@ -991,7 +991,7 @@ void QFxGridView::setCellWidth(int cellWidth) if (cellWidth != d->cellWidth && cellWidth > 0) { d->cellWidth = qMax(1, cellWidth); d->updateGrid(); - emit cellSizeChanged(); + emit cellWidthChanged(); d->layout(); } } @@ -1008,7 +1008,7 @@ void QFxGridView::setCellHeight(int cellHeight) if (cellHeight != d->cellHeight && cellHeight > 0) { d->cellHeight = qMax(1, cellHeight); d->updateGrid(); - emit cellSizeChanged(); + emit cellHeightChanged(); d->layout(); } } diff --git a/src/declarative/fx/qfxgridview.h b/src/declarative/fx/qfxgridview.h index 08a7565..7f30f03 100644 --- a/src/declarative/fx/qfxgridview.h +++ b/src/declarative/fx/qfxgridview.h @@ -67,8 +67,8 @@ class Q_DECLARATIVE_EXPORT QFxGridView : public QFxFlickable Q_PROPERTY(Flow flow READ flow WRITE setFlow) Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled) Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer) - Q_PROPERTY(int cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellSizeChanged) - Q_PROPERTY(int cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellSizeChanged) + Q_PROPERTY(int cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellWidthChanged) + Q_PROPERTY(int cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellHeightChanged) Q_CLASSINFO("DefaultProperty", "data") public: @@ -121,7 +121,8 @@ public Q_SLOTS: Q_SIGNALS: void countChanged(); void currentIndexChanged(); - void cellSizeChanged(); + void cellWidthChanged(); + void cellHeightChanged(); protected: virtual void viewportMoved(); diff --git a/src/declarative/fx/qfxitem.cpp b/src/declarative/fx/qfxitem.cpp index d6534a1..a155d5a 100644 --- a/src/declarative/fx/qfxitem.cpp +++ b/src/declarative/fx/qfxitem.cpp @@ -1257,12 +1257,6 @@ QFxKeysAttached *QFxKeysAttached::qmlAttachedProperties(QObject *obj) */ /*! - \fn void QFxItem::activeFocusChanged() - - This signal is emitted when this item gains active focus. -*/ - -/*! \fn void QFxItem::baselineOffsetChanged() This signal is emitted when the baseline offset of the item @@ -2260,16 +2254,6 @@ void QFxItem::setKeepMouseGrab(bool keep) } /*! - This function emits the \e activeFocusChanged signal. - \a flag is not used. - */ -void QFxItem::activeFocusChanged(bool flag) -{ - Q_UNUSED(flag); - emit activeFocusChanged(); -} - -/*! This function emits the \e focusChanged signal. Subclasses overriding this function should call up diff --git a/src/declarative/fx/qfxitem.h b/src/declarative/fx/qfxitem.h index bde0c9e..b2aefe2 100644 --- a/src/declarative/fx/qfxitem.h +++ b/src/declarative/fx/qfxitem.h @@ -166,7 +166,6 @@ Q_SIGNALS: void stateChanged(const QString &); void focusChanged(); void wantsFocusChanged(); - void activeFocusChanged(); void parentChanged(); protected: @@ -183,7 +182,6 @@ protected: virtual void classBegin(); virtual void componentComplete(); virtual void focusChanged(bool); - virtual void activeFocusChanged(bool); virtual void keyPressEvent(QKeyEvent *event); virtual void keyReleaseEvent(QKeyEvent *event); virtual void inputMethodEvent(QInputMethodEvent *); diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index 5afd881..604d16b 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -1169,6 +1169,7 @@ void QFxListView::setOrientation(Qt::Orientation orientation) setViewportHeight(-1); d->clear(); refill(); + emit orientationChanged(); d->updateCurrent(d->currentIndex); } } diff --git a/src/declarative/fx/qfxlistview.h b/src/declarative/fx/qfxlistview.h index 3cff422..5a83604 100644 --- a/src/declarative/fx/qfxlistview.h +++ b/src/declarative/fx/qfxlistview.h @@ -72,7 +72,7 @@ class Q_DECLARATIVE_EXPORT QFxListView : public QFxFlickable Q_PROPERTY(bool strictlyEnforceHighlightRange READ strictlyEnforceHighlightRange WRITE setStrictlyEnforceHighlightRange) Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) - Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation) + Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged) Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled) Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer) Q_PROPERTY(QString sectionExpression READ sectionExpression WRITE setSectionExpression NOTIFY sectionExpressionChanged) @@ -106,7 +106,7 @@ public: bool strictlyEnforceHighlightRange() const; void setStrictlyEnforceHighlightRange(bool strict); - + qreal preferredHighlightBegin() const; void setPreferredHighlightBegin(qreal); @@ -144,6 +144,7 @@ public Q_SLOTS: Q_SIGNALS: void countChanged(); void spacingChanged(); + void orientationChanged(); void currentIndexChanged(); void currentSectionChanged(); void sectionExpressionChanged(); diff --git a/src/declarative/fx/qfxpathview.cpp b/src/declarative/fx/qfxpathview.cpp index b127f39..c580e98 100644 --- a/src/declarative/fx/qfxpathview.cpp +++ b/src/declarative/fx/qfxpathview.cpp @@ -607,7 +607,7 @@ void QFxPathViewPrivate::updateItem(QFxItem *item, qreal percent) { if (QObject *obj = QFxPathView::qmlAttachedProperties(item)) { foreach(const QString &attr, path->attributes()) - static_cast<QFxPathViewAttached *>(obj)->setValue(attr.toLatin1(), path->attributeAt(attr, percent)); + static_cast<QFxPathViewAttached *>(obj)->setValue(attr.toUtf8(), path->attributeAt(attr, percent)); } QPointF pf = path->pointAt(percent); item->setX(pf.x() - item->width()*item->scale()/2); diff --git a/src/declarative/fx/qfxpositioners.cpp b/src/declarative/fx/qfxpositioners.cpp index e4500aa..f8e7213 100644 --- a/src/declarative/fx/qfxpositioners.cpp +++ b/src/declarative/fx/qfxpositioners.cpp @@ -97,6 +97,7 @@ void QFxBasePositioner::setSpacing(int s) return; d->_spacing = s; prePositioning(); + emit spacingChanged(); } QmlTransition *QFxBasePositioner::move() const diff --git a/src/declarative/fx/qfxpositioners.h b/src/declarative/fx/qfxpositioners.h index 89a61d7..d62da08 100644 --- a/src/declarative/fx/qfxpositioners.h +++ b/src/declarative/fx/qfxpositioners.h @@ -59,7 +59,7 @@ class Q_DECLARATIVE_EXPORT QFxBasePositioner : public QFxItem { Q_OBJECT - Q_PROPERTY(int spacing READ spacing WRITE setSpacing) + Q_PROPERTY(int spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) Q_PROPERTY(QmlTransition *move READ move WRITE setMove) Q_PROPERTY(QmlTransition *add READ add WRITE setAdd) Q_PROPERTY(QmlTransition *remove READ remove WRITE setRemove) @@ -93,6 +93,7 @@ protected: Q_SIGNALS: void layoutItemChanged(); + void spacingChanged(); protected Q_SLOTS: virtual void doPositioning()=0; diff --git a/src/declarative/fx/qfxtextedit.cpp b/src/declarative/fx/qfxtextedit.cpp index 07444bb..ccb8f7e 100644 --- a/src/declarative/fx/qfxtextedit.cpp +++ b/src/declarative/fx/qfxtextedit.cpp @@ -822,7 +822,7 @@ void QFxTextEdit::keyReleaseEvent(QKeyEvent *event) \overload Handles changing of the focus property. Focus is applied to the control even if the edit does not have active focus. This is because things - like KeyProxy can give the behavior of focus even when activeFocus isn't + like KeyProxy can give the behavior of focus even when hasFocus() isn't true. */ void QFxTextEdit::focusChanged(bool hasFocus) diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp index 943f909..3a9e5d4 100644 --- a/src/declarative/fx/qfxvisualitemmodel.cpp +++ b/src/declarative/fx/qfxvisualitemmodel.cpp @@ -264,7 +264,7 @@ public: for (QHash<int,QByteArray>::const_iterator it = m_abstractItemModel->roleNames().begin(); it != m_abstractItemModel->roleNames().end(); ++it) { m_roles.append(it.key()); - m_roleNames.insert(QLatin1String(*it), it.key()); + m_roleNames.insert(QString::fromUtf8(*it), it.key()); } if (m_roles.count() == 1) m_roleNames.insert(QLatin1String("modelData"), m_roles.at(0)); @@ -416,11 +416,11 @@ int QFxVisualDataModelDataMetaObject::createProperty(const char *name, const cha if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) { model->ensureRoles(); - if (model->m_roleNames.contains(QLatin1String(name))) + if (model->m_roleNames.contains(QString::fromUtf8(name))) return QmlOpenMetaObject::createProperty(name, type); } else { model->ensureRoles(); - const QLatin1String sname(name); + QString sname = QString::fromUtf8(name); if (model->m_roleNames.contains(sname)) return QmlOpenMetaObject::createProperty(name, type); } @@ -438,7 +438,7 @@ QFxVisualDataModelDataMetaObject::propertyCreated(int, QMetaPropertyBuilder &pro Q_ASSERT(data->m_model); QFxVisualDataModelPrivate *model = QFxVisualDataModelPrivate::get(data->m_model); - QString name = QLatin1String(prop.name()); + QString name = QString::fromUtf8(prop.name()); if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) { if (name == QLatin1String("modelData")) { if (model->m_listAccessor->type() == QmlListAccessor::Instance) { @@ -532,7 +532,7 @@ QFxVisualDataModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &pr QFxVisualDataModel *m = new QFxVisualDataModel; m->setParent(object()); - m->setPart(QLatin1String(prop.name())); + m->setPart(QString::fromUtf8(prop.name())); m->setModel(QVariant::fromValue(static_cast<QFxVisualDataModelParts *>(object())->model)); QVariant var = QVariant::fromValue((QObject *)m); @@ -706,7 +706,7 @@ QFxItem *QFxVisualDataModel::item(int index, bool complete) { Q_D(QFxVisualDataModel); if (d->m_visualItemModel) - return d->m_visualItemModel->item(index, d->m_part.toLatin1(), complete); + return d->m_visualItemModel->item(index, d->m_part.toUtf8(), complete); return item(index, QByteArray(), complete); } @@ -790,7 +790,7 @@ QFxItem *QFxVisualDataModel::item(int index, const QByteArray &viewId, bool comp if (!item) { QmlPackage *package = qobject_cast<QmlPackage *>(nobj); if (package) { - QObject *o = package->part(QLatin1String(viewId)); + QObject *o = package->part(QString::fromUtf8(viewId)); item = qobject_cast<QFxItem *>(o); if (item) d->m_packaged.insertMulti(item, package); diff --git a/src/declarative/fx/qfxwebview.cpp b/src/declarative/fx/qfxwebview.cpp index a06e294..f7030ca 100644 --- a/src/declarative/fx/qfxwebview.cpp +++ b/src/declarative/fx/qfxwebview.cpp @@ -1325,9 +1325,8 @@ public Q_SLOTS: void qmlLoaded() { if (component->isError()) { - // XXX Could instead give these errors to the WebView to handle. - foreach (QmlError err, component->errors()) - qWarning(err.toString().toLatin1()); + // ### Could instead give these errors to the WebView to handle. + qWarning() << component->errors(); return; } item = qobject_cast<QFxItem*>(component->create(qmlContext(webview))); @@ -1335,7 +1334,7 @@ public Q_SLOTS: QString jsObjName; for (int i=0; i<propertyNames.count(); ++i) { if (propertyNames[i] != QLatin1String("type") && propertyNames[i] != QLatin1String("data")) { - item->setProperty(propertyNames[i].toLatin1(),propertyValues[i]); + item->setProperty(propertyNames[i].toUtf8(),propertyValues[i]); if (propertyNames[i] == QLatin1String("objectname")) jsObjName = propertyValues[i]; } diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index a2e2050..2e62a3b 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -10,6 +10,7 @@ SOURCES += qml/qmlparser.cpp \ qml/qmlcontext.cpp \ qml/qmlcustomparser.cpp \ qml/qmlpropertyvaluesource.cpp \ + qml/qmlpropertyvalueinterceptor.cpp \ qml/qmlproxymetaobject.cpp \ qml/qmlvme.cpp \ qml/qmlcompiler.cpp \ @@ -59,6 +60,7 @@ HEADERS += qml/qmlparser_p.h \ qml/qmlcustomparser_p.h \ qml/qmlcustomparser_p_p.h \ qml/qmlpropertyvaluesource.h \ + qml/qmlpropertyvalueinterceptor.h \ qml/qmlboundsignal_p.h \ qml/qmlparserstatus.h \ qml/qmlproxymetaobject_p.h \ diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index f3f9289..a0d749f 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -52,6 +52,8 @@ QT_BEGIN_NAMESPACE +DEFINE_BOOL_CONFIG_OPTION(qmlBasicScriptDump, QML_BASICSCRIPT_DUMP); + using namespace QmlJS; struct ScriptInstruction { @@ -367,7 +369,7 @@ bool QmlBasicScript::compile(const Expression &expression) { if (!expression.expression.asAST()) return false; - QByteArray expr = expression.expression.asScript().toLatin1(); + QByteArray expr = expression.expression.asScript().toUtf8(); const char *src = expr.constData(); QmlBasicScriptCompiler bsc; @@ -400,6 +402,8 @@ bool QmlBasicScript::compile(const Expression &expression) ::memcpy((char *)d->data(), bsc.data.constData(), bsc.data.count()); } + if (d && qmlBasicScriptDump()) + dump(); return d != 0; } @@ -649,7 +653,7 @@ QVariant QmlBasicScript::run(QmlContext *context, QObject *me) case ScriptInstruction::FetchRootConstant: { - QObject *obj = contextPrivate->defaultObjects.at(0); + QObject *obj = contextPrivate->defaultObjects.last(); stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type)); if (obj && instr.constant.notify != 0) diff --git a/src/declarative/qml/qmlbinding.cpp b/src/declarative/qml/qmlbinding.cpp index 3a34f46..2435c40 100644 --- a/src/declarative/qml/qmlbinding.cpp +++ b/src/declarative/qml/qmlbinding.cpp @@ -67,8 +67,8 @@ QmlBindingPrivate::QmlBindingPrivate() { } -QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, QObject *parent) -: QmlExpression(ctxt, data, rc, obj, *new QmlBindingPrivate) +QmlBinding::QmlBinding(void *data, QmlRefCount *rc, QObject *obj, QmlContext *ctxt, const QUrl &url, int lineNumber, QObject *parent) +: QmlExpression(ctxt, data, rc, obj, url, lineNumber, *new QmlBindingPrivate) { setParent(parent); } @@ -97,7 +97,7 @@ QmlMetaProperty QmlBinding::property() const return d->bindingData()->property; } -void QmlBinding::update() +void QmlBinding::update(QmlMetaProperty::WriteFlags flags) { Q_D(QmlBinding); @@ -119,17 +119,17 @@ void QmlBinding::update() int idx = data->property.coreIndex(); Q_ASSERT(idx != -1); - void *a[1]; + QmlBinding *t = this; - a[0] = (void *)&t; - QMetaObject::metacall(data->property.object(), + int status = -1; + void *a[] = { &t, 0, &status, &flags }; + QMetaObject::metacall(data->property.object(), QMetaObject::WriteProperty, idx, a); } else { - QVariant value = this->value(); - data->property.write(value, QmlMetaProperty::Binding); + data->property.write(value, flags); } data->updating = false; @@ -146,17 +146,17 @@ void QmlBinding::valueChanged() update(); } -void QmlBinding::setEnabled(bool e) +void QmlBinding::setEnabled(bool e, QmlMetaProperty::WriteFlags flags) { Q_D(QmlBinding); d->bindingData()->enabled = e; setTrackChange(e); - QmlAbstractBinding::setEnabled(e); + QmlAbstractBinding::setEnabled(e, flags); if (e) { addToObject(d->bindingData()->property.object()); - update(); + update(flags); } else { removeFromObject(); } @@ -231,7 +231,7 @@ QString QmlAbstractBinding::expression() const return QLatin1String("<Unknown>"); } -void QmlAbstractBinding::setEnabled(bool e) +void QmlAbstractBinding::setEnabled(bool e, QmlMetaProperty::WriteFlags) { if (e) m_mePtr = 0; } diff --git a/src/declarative/qml/qmlbinding.h b/src/declarative/qml/qmlbinding.h index e3a297c..6a3e92a 100644 --- a/src/declarative/qml/qmlbinding.h +++ b/src/declarative/qml/qmlbinding.h @@ -47,6 +47,7 @@ #include <QtDeclarative/qml.h> #include <QtDeclarative/qmlpropertyvaluesource.h> #include <QtDeclarative/qmlexpression.h> +#include <QtCore/QMetaProperty> QT_BEGIN_HEADER @@ -62,10 +63,12 @@ public: virtual QString expression() const; - virtual void setEnabled(bool) = 0; + void setEnabled(bool e) { setEnabled(e, QmlMetaProperty::DontRemoveBinding); } + virtual void setEnabled(bool, QmlMetaProperty::WriteFlags) = 0; virtual int propertyIndex() = 0; - virtual void update() = 0; + void update() { update(QmlMetaProperty::DontRemoveBinding); } + virtual void update(QmlMetaProperty::WriteFlags) = 0; void addToObject(QObject *); void removeFromObject(); @@ -90,7 +93,8 @@ class Q_DECLARATIVE_EXPORT QmlBinding : public QmlExpression, Q_OBJECT public: QmlBinding(const QString &, QObject *, QmlContext *, QObject *parent=0); - QmlBinding(void *, QmlRefCount *, QObject *, QmlContext *, QObject *parent); + QmlBinding(void *, QmlRefCount *, QObject *, QmlContext *, const QUrl &, int, + QObject *parent); ~QmlBinding(); void setTarget(const QmlMetaProperty &); @@ -99,12 +103,13 @@ public: bool enabled() const; // Inherited from QmlAbstractBinding - virtual void setEnabled(bool); + virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags); virtual int propertyIndex(); + virtual void update(QmlMetaProperty::WriteFlags flags); virtual QString expression() const; public Q_SLOTS: - void update(); + void update() { update(QmlMetaProperty::DontRemoveBinding); } protected: virtual void valueChanged(); diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp index e4ca358..6dc221e 100644 --- a/src/declarative/qml/qmlbindingoptimizations.cpp +++ b/src/declarative/qml/qmlbindingoptimizations.cpp @@ -69,16 +69,16 @@ QmlBinding_Id::~QmlBinding_Id() removeFromContext(); } -void QmlBinding_Id::setEnabled(bool e) +void QmlBinding_Id::setEnabled(bool e, QmlMetaProperty::WriteFlags flags) { if (e) { addToObject(m_object); - update(); + update(flags); } else { removeFromObject(); } - QmlAbstractBinding::setEnabled(e); + QmlAbstractBinding::setEnabled(e, flags); } int QmlBinding_Id::propertyIndex() @@ -86,7 +86,7 @@ int QmlBinding_Id::propertyIndex() return m_propertyIdx; } -void QmlBinding_Id::update() +void QmlBinding_Id::update(QmlMetaProperty::WriteFlags flags) { QmlContextPrivate *ctxtPriv = static_cast<QmlContextPrivate *>(QObjectPrivate::get(context())); @@ -102,7 +102,8 @@ void QmlBinding_Id::update() } QObject *o = ctxtPriv->idValues[m_id].data(); - void *a[] = { &o, 0 }; + int status = -1; + void *a[] = { &o, 0, &status, &flags }; QMetaObject::metacall(m_object, QMetaObject::WriteProperty, m_propertyIdx, a); } @@ -123,7 +124,9 @@ void QmlBinding_Id::reset() removeFromContext(); QObject *o = 0; - void *a[] = { &o, 0 }; + int status = -1; + QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding; + void *a[] = { &o, 0, &status, &flags }; QMetaObject::metacall(m_object, QMetaObject::WriteProperty, m_propertyIdx, a); } @@ -150,17 +153,17 @@ QmlBinding_ObjProperty::QmlBinding_ObjProperty(QObject *object, int propertyIdx, { } -void QmlBinding_ObjProperty::setEnabled(bool e) +void QmlBinding_ObjProperty::setEnabled(bool e, QmlMetaProperty::WriteFlags flags) { m_enabled = e; if (e) { addToObject(m_object); - update(); + update(flags); } else { removeFromObject(); } - QmlAbstractBinding::setEnabled(e); + QmlAbstractBinding::setEnabled(e, flags); } int QmlBinding_ObjProperty::propertyIndex() @@ -168,21 +171,24 @@ int QmlBinding_ObjProperty::propertyIndex() return m_propertyIdx; } -void QmlBinding_ObjProperty::update() +void QmlBinding_ObjProperty::update(QmlMetaProperty::WriteFlags flags) { if (!m_enabled) return; QObject *value = 0; - void *a[] = { &value, 0 }; + int status = -1; + void *ra[] = { &value, 0, &status }; // Read QMetaObject::metacall(m_context, QMetaObject::ReadProperty, - m_contextIdx, a); + m_contextIdx, ra); + + void *wa[] = { &value, 0, &status, &flags }; // Write QMetaObject::metacall(m_object, QMetaObject::WriteProperty, - m_propertyIdx, a); + m_propertyIdx, wa); // Connect notify if needed. Only need to connect once, so we set // m_notifyIdx back to -1 afterwards diff --git a/src/declarative/qml/qmlbindingoptimizations_p.h b/src/declarative/qml/qmlbindingoptimizations_p.h index 4862007..d0a4df4 100644 --- a/src/declarative/qml/qmlbindingoptimizations_p.h +++ b/src/declarative/qml/qmlbindingoptimizations_p.h @@ -69,9 +69,9 @@ public: virtual ~QmlBinding_Id(); // Inherited from QmlAbstractBinding - virtual void setEnabled(bool); + virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags); virtual int propertyIndex(); - virtual void update(); + virtual void update(QmlMetaProperty::WriteFlags flags); void reset(); @@ -96,11 +96,12 @@ public: QObject *context, int contextIdx, int notifyIdx); // Inherited from QmlAbstractBinding - virtual void setEnabled(bool); + virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags); virtual int propertyIndex(); + virtual void update(QmlMetaProperty::WriteFlags flags); private Q_SLOTS: - virtual void update(); + void update() { update(QmlMetaProperty::DontRemoveBinding); } private: bool m_enabled; diff --git a/src/declarative/qml/qmlcompileddata.cpp b/src/declarative/qml/qmlcompileddata.cpp index 8c3c355..7032a3b 100644 --- a/src/declarative/qml/qmlcompileddata.cpp +++ b/src/declarative/qml/qmlcompileddata.cpp @@ -150,7 +150,7 @@ int QmlCompiledData::indexForLocation(const QmlParser::LocationSpan &l) } QmlCompiledData::QmlCompiledData() -: importCache(0) +: importCache(0), root(0) { } @@ -189,7 +189,7 @@ const QMetaObject *QmlCompiledData::TypeReference::metaObject() const return type->metaObject(); } else { Q_ASSERT(component); - return &static_cast<QmlComponentPrivate *>(QObjectPrivate::get(component))->cc->root; + return static_cast<QmlComponentPrivate *>(QObjectPrivate::get(component))->cc->root; } } diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 670e442..431f9f6 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -195,14 +195,14 @@ bool QmlCompiler::testLiteralAssignment(const QMetaProperty &prop, QString string = v->value.asScript(); if (!prop.isWritable()) - COMPILE_EXCEPTION(v, "Invalid property assignment:" << QLatin1String(prop.name()) << "is a read-only property"); + COMPILE_EXCEPTION(v, "Invalid property assignment:" << QString::fromUtf8(prop.name()) << "is a read-only property"); if (prop.isEnumType()) { int value; if (prop.isFlagType()) { - value = prop.enumerator().keysToValue(string.toLatin1().constData()); + value = prop.enumerator().keysToValue(string.toUtf8().constData()); } else - value = prop.enumerator().keyToValue(string.toLatin1().constData()); + value = prop.enumerator().keyToValue(string.toUtf8().constData()); if (value == -1) COMPILE_EXCEPTION(v, "Invalid property assignment: unknown enumeration"); return true; @@ -336,9 +336,9 @@ void QmlCompiler::genLiteralAssignment(const QMetaProperty &prop, if (prop.isEnumType()) { int value; if (prop.isFlagType()) { - value = prop.enumerator().keysToValue(string.toLatin1().constData()); + value = prop.enumerator().keysToValue(string.toUtf8().constData()); } else - value = prop.enumerator().keyToValue(string.toLatin1().constData()); + value = prop.enumerator().keyToValue(string.toUtf8().constData()); instr.type = QmlInstruction::StoreInteger; instr.storeInteger.propertyIndex = prop.propertyIndex(); @@ -595,7 +595,7 @@ bool QmlCompiler::compile(QmlEngine *engine, ref.ref = tref.unit; ref.ref->addref(); } - ref.className = parserRef->name.toLatin1(); + ref.className = parserRef->name.toUtf8(); out->types << ref; } @@ -647,7 +647,13 @@ void QmlCompiler::compileTree(Object *tree) output->importCache = output->imports.cache(engine); Q_ASSERT(tree->metatype); - static_cast<QMetaObject &>(output->root) = *tree->metaObject(); + + if (tree->metadata.isEmpty()) { + output->root = tree->metatype; + } else { + static_cast<QMetaObject &>(output->rootData) = *tree->metaObject(); + output->root = &output->rootData; + } if (!tree->metadata.isEmpty()) QmlEnginePrivate::get(engine)->registerCompositeType(output); } @@ -666,7 +672,7 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt) obj->className = tr.className; // This object is a "Component" element - if (obj->metatype == &QmlComponent::staticMetaObject) { + if (tr.type && obj->metatype == &QmlComponent::staticMetaObject) { COMPILE_CHECK(buildComponent(obj, ctxt)); return true; } @@ -780,7 +786,9 @@ bool QmlCompiler::buildObject(Object *obj, const BindingContext &ctxt) void QmlCompiler::genObject(QmlParser::Object *obj) { - if (obj->metatype == &QmlComponent::staticMetaObject) { + const QmlCompiledData::TypeReference &tr = + output->types.at(obj->type); + if (tr.type && obj->metatype == &QmlComponent::staticMetaObject) { genComponent(obj); return; } @@ -833,6 +841,8 @@ void QmlCompiler::genObject(QmlParser::Object *obj) QmlInstruction script; script.type = QmlInstruction::StoreScript; script.line = 0; // ### + script.storeScript.fileName = output->indexForString(obj->scriptBlocksFile.at(ii)); + script.storeScript.lineNumber = obj->scriptBlocksLineNumber.at(ii); script.storeScript.value = output->indexForString(obj->scriptBlocks.at(ii)); output->bytecode << script; } @@ -1054,6 +1064,8 @@ bool QmlCompiler::buildComponent(QmlParser::Object *obj, bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) { QString scriptCode; + QString sourceUrl; + int lineNumber = 1; if (script->properties.count() == 1 && script->properties.begin().key() == QByteArray("source")) { @@ -1066,8 +1078,7 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) source->values.at(0)->object || !source->values.at(0)->value.isString()) COMPILE_EXCEPTION(source, "Invalid Script source value"); - QString sourceUrl = - output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString(); + sourceUrl = output->url.resolved(QUrl(source->values.at(0)->value.asString())).toString(); for (int ii = 0; ii < unit->resources.count(); ++ii) { if (unit->resources.at(ii)->url == sourceUrl) { @@ -1079,10 +1090,14 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) } else if (!script->properties.isEmpty()) { COMPILE_EXCEPTION(*script->properties.begin(), "Properties cannot be set on Script block"); } else if (script->defaultProperty) { + sourceUrl = output->url.toString(); + QmlParser::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, "Invalid Script block"); @@ -1105,8 +1120,11 @@ bool QmlCompiler::buildScript(QmlParser::Object *obj, QmlParser::Object *script) } } - if (!scriptCode.isEmpty()) + if (!scriptCode.isEmpty()) { obj->scriptBlocks.append(scriptCode); + obj->scriptBlocksFile.append(sourceUrl); + obj->scriptBlocksLineNumber.append(lineNumber); + } return true; } @@ -1521,6 +1539,24 @@ void QmlCompiler::genPropertyAssignment(QmlParser::Property *prop, store.assignValueSource.castValue = valueType->propertyValueSourceCast(); output->bytecode << store; + } else if (v->type == Value::ValueInterceptor) { + genObject(v->object); + + QmlInstruction store; + store.type = QmlInstruction::StoreValueInterceptor; + store.line = v->object->location.start.line; + if (valueTypeProperty) { + store.assignValueInterceptor.property = QmlMetaPropertyPrivate::saveValueType(valueTypeProperty->index, prop->index); + store.assignValueInterceptor.owner = 1; + } else { + store.assignValueInterceptor.property = + QmlMetaPropertyPrivate::saveProperty(prop->index); + store.assignValueInterceptor.owner = 0; + } + QmlType *valueType = QmlMetaType::qmlType(v->object->metatype); + store.assignValueInterceptor.castValue = valueType->propertyValueInterceptorCast(); + output->bytecode << store; + } else if (v->type == Value::PropertyBinding) { genBindingAssignment(v, prop, obj, valueTypeProperty); @@ -1625,7 +1661,7 @@ bool QmlCompiler::buildAttachedProperty(QmlParser::Property *prop, // font.pointSize: 12 // font.family: "Helvetica" // } -// font is a nested property. size and family are not. +// font is a nested property. pointSize and family are not. bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, QmlParser::Object *obj, const BindingContext &ctxt) @@ -1638,7 +1674,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, static_cast<QmlEnginePrivate *>(QObjectPrivate::get(engine)); if (ep->valueTypes[prop->type]) { COMPILE_CHECK(buildValueTypeProperty(ep->valueTypes[prop->type], - prop->value, ctxt.incr())); + prop->value, obj, ctxt.incr())); obj->addValueTypeProperty(prop); } else { COMPILE_EXCEPTION(prop, "Invalid property access"); @@ -1662,6 +1698,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, bool QmlCompiler::buildValueTypeProperty(QObject *type, QmlParser::Object *obj, + QmlParser::Object *baseObj, const BindingContext &ctxt) { if (obj->defaultProperty) @@ -1683,13 +1720,16 @@ bool QmlCompiler::buildValueTypeProperty(QObject *type, if (value->object) { bool isPropertyValue = output->types.at(value->object->type).type->propertyValueSourceCast() != -1; - if (!isPropertyValue) { + bool isPropertyInterceptor = output->types.at(value->object->type).type->propertyValueInterceptorCast() != -1; + if (!isPropertyValue && !isPropertyInterceptor) { COMPILE_EXCEPTION(prop, "Invalid property use"); } else { COMPILE_CHECK(buildObject(value->object, ctxt)); - value->type = Value::ValueSource; - } + if (isPropertyInterceptor && prop->parent->synthdata.isEmpty()) + buildDynamicMeta(baseObj, ForceCreation); + value->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor; + } } else if (value->value.isScript()) { // ### Check for writability BindingReference reference; @@ -1854,8 +1894,12 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop, // Will be true if the assigned type inherits QmlPropertyValueSource bool isPropertyValue = false; - if (QmlType *valueType = QmlMetaType::qmlType(v->object->metatype)) + // Will be true if the assigned type inherits QmlPropertyValueInterceptor + bool isPropertyInterceptor = false; + if (QmlType *valueType = QmlMetaType::qmlType(v->object->metatype)) { isPropertyValue = valueType->propertyValueSourceCast() != -1; + isPropertyInterceptor = valueType->propertyValueInterceptorCast() != -1; + } // We want to raw metaObject here as the raw metaobject is the // actual property type before we applied any extensions that might @@ -1869,7 +1913,7 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop, if (propertyMetaObject) { const QMetaObject *c = v->object->metatype; while(c) { - isAssignable |= (c == propertyMetaObject); + isAssignable |= (QmlMetaPropertyPrivate::equal(c, propertyMetaObject)); c = c->superClass(); } } @@ -1892,11 +1936,13 @@ bool QmlCompiler::buildPropertyObjectAssignment(QmlParser::Property *prop, component->getDefaultProperty()->addValue(componentValue); v->object = component; COMPILE_CHECK(buildPropertyObjectAssignment(prop, obj, v, ctxt)); - } else if (isPropertyValue) { + } else if (isPropertyValue || isPropertyInterceptor) { // Assign as a property value source COMPILE_CHECK(buildObject(v->object, ctxt)); - v->type = Value::ValueSource; + if (isPropertyInterceptor && prop->parent->synthdata.isEmpty()) + buildDynamicMeta(prop->parent, ForceCreation); + v->type = isPropertyValue ? Value::ValueSource : Value::ValueInterceptor; } else { COMPILE_EXCEPTION(v->object, "Cannot assign object to property"); } @@ -2002,7 +2048,8 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) Q_ASSERT(obj); Q_ASSERT(obj->metatype); - if (obj->dynamicProperties.isEmpty() && + if (mode != ForceCreation && + obj->dynamicProperties.isEmpty() && obj->dynamicSignals.isEmpty() && obj->dynamicSlots.isEmpty()) return true; @@ -2062,7 +2109,7 @@ bool QmlCompiler::buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode) Q_ASSERT(tdata->status == QmlCompositeTypeData::Complete); QmlCompiledData *data = tdata->toCompiledComponent(engine); - customTypeName = data->root.className(); + customTypeName = data->root->className(); } else { customTypeName = qmltype->typeName(); } @@ -2226,28 +2273,44 @@ bool QmlCompiler::compileAlias(QMetaObjectBuilder &builder, QStringList alias = astNodeToStringList(node); - if (alias.count() != 2) + if (alias.count() != 1 && alias.count() != 2) COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); if (!compileState.ids.contains(alias.at(0))) COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); Object *idObject = compileState.ids[alias.at(0)]; - int propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); - if (-1 == propIdx) - COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); + QByteArray typeName; + + int propIdx = -1; + bool writable = false; + if (alias.count() == 2) { + propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); + + if (-1 == propIdx) + COMPILE_EXCEPTION(prop.defaultValue, "Invalid alias location"); + + QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); + writable = aliasProperty.isWritable(); - QMetaProperty aliasProperty = idObject->metaObject()->property(propIdx); + if (aliasProperty.isEnumType()) + typeName = "int"; // Avoid introducing a dependency on the aliased metaobject + else + typeName = aliasProperty.typeName(); + } else { + typeName = idObject->metaObject()->className(); + typeName += "*"; + } data.append((const char *)&idObject->idIndex, sizeof(idObject->idIndex)); data.append((const char *)&propIdx, sizeof(propIdx)); builder.addSignal(prop.name + "Changed()"); QMetaPropertyBuilder propBuilder = - builder.addProperty(prop.name, aliasProperty.typeName(), - builder.methodCount() - 1); + builder.addProperty(prop.name, typeName.constData(), builder.methodCount() - 1); propBuilder.setScriptable(true); + propBuilder.setWritable(writable); return true; } @@ -2322,7 +2385,7 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding, store.assignBinding.value = output->indexForByteArray(ref.compiledData); store.assignBinding.context = ref.bindingContext.stack; store.assignBinding.owner = ref.bindingContext.owner; - store.line = prop->location.end.line; + store.line = binding->location.start.line; Q_ASSERT(ref.bindingContext.owner == 0 || (ref.bindingContext.owner != 0 && valueTypeProperty)); @@ -2418,7 +2481,7 @@ bool QmlCompiler::canCoerce(int to, QmlParser::Object *from) const QMetaObject *fromMo = from->metaObject(); while (fromMo) { - if (fromMo == toMo) + if (QmlMetaPropertyPrivate::equal(fromMo, toMo)) return true; fromMo = fromMo->superClass(); } @@ -2437,7 +2500,7 @@ bool QmlCompiler::canCoerce(int to, int from) QmlEnginePrivate::get(engine)->rawMetaObjectForType(from); while (fromMo) { - if (fromMo == toMo) + if (QmlMetaPropertyPrivate::equal(fromMo, toMo)) return true; fromMo = fromMo->superClass(); } @@ -2465,7 +2528,7 @@ QStringList QmlCompiler::deferredProperties(QmlParser::Object *obj) return QStringList(); QMetaClassInfo classInfo = mo->classInfo(idx); - QStringList rv = QString(QLatin1String(classInfo.value())).split(QLatin1Char(',')); + QStringList rv = QString::fromUtf8(classInfo.value()).split(QLatin1Char(',')); return rv; } diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index 1d27342..ecf3344 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -104,7 +104,8 @@ public: int type; }; - QAbstractDynamicMetaObject root; + const QMetaObject *root; + QAbstractDynamicMetaObject rootData; QList<QString> primitives; QList<float> floatData; QList<int> intData; @@ -191,6 +192,7 @@ private: const BindingContext &ctxt); bool buildValueTypeProperty(QObject *type, QmlParser::Object *obj, + QmlParser::Object *baseObj, const BindingContext &ctxt); bool buildListProperty(QmlParser::Property *prop, QmlParser::Object *obj, @@ -209,7 +211,7 @@ private: bool doesPropertyExist(QmlParser::Property *prop, QmlParser::Object *obj); bool testLiteralAssignment(const QMetaProperty &prop, QmlParser::Value *value); - enum DynamicMetaMode { IgnoreAliases, ResolveAliases }; + enum DynamicMetaMode { IgnoreAliases, ResolveAliases, ForceCreation }; bool mergeDynamicMetaProperties(QmlParser::Object *obj); bool buildDynamicMeta(QmlParser::Object *obj, DynamicMetaMode mode); bool checkDynamicMeta(QmlParser::Object *obj); diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp index 5b1cbeb..9a761b2 100644 --- a/src/declarative/qml/qmlcomponent.cpp +++ b/src/declarative/qml/qmlcomponent.cpp @@ -573,7 +573,7 @@ void QmlComponentPrivate::completeCreate() bindValues.at(ii); for (int jj = 0; jj < bv.count; ++jj) { if(bv.at(jj)) - bv.at(jj)->setEnabled(true); + bv.at(jj)->setEnabled(true, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } QmlEnginePrivate::clear(bv); } diff --git a/src/declarative/qml/qmlcompositetypemanager.cpp b/src/declarative/qml/qmlcompositetypemanager.cpp index 71b4ef0..13bd02c 100644 --- a/src/declarative/qml/qmlcompositetypemanager.cpp +++ b/src/declarative/qml/qmlcompositetypemanager.cpp @@ -119,7 +119,7 @@ QmlCompositeTypeData::toCompiledComponent(QmlEngine *engine) compiledComponent = new QmlCompiledData; compiledComponent->url = imports.baseUrl(); - compiledComponent->name = compiledComponent->url.toString().toLatin1(); // ### + compiledComponent->name = compiledComponent->url.toString().toUtf8(); QmlCompiler compiler; if (!compiler.compile(engine, this, compiledComponent)) { @@ -443,7 +443,7 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit) int waiting = 0; for (int ii = 0; ii < types.count(); ++ii) { QmlScriptParser::TypeReference *parserRef = types.at(ii); - QByteArray typeName = parserRef->name.toLatin1(); + QByteArray typeName = parserRef->name.toUtf8(); QmlCompositeTypeData::TypeReference ref; @@ -458,7 +458,7 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit) if (typeNamespace) { QmlError error; error.setUrl(unit->imports.baseUrl()); - error.setDescription(tr("Namespace %1 cannot be used as a type").arg(QLatin1String(typeName))); + error.setDescription(tr("Namespace %1 cannot be used as a type").arg(QString::fromUtf8(typeName))); if (!parserRef->refObjects.isEmpty()) { QmlParser::Object *obj = parserRef->refObjects.first(); error.setLine(obj->location.start.line); @@ -500,7 +500,7 @@ void QmlCompositeTypeManager::compile(QmlCompositeTypeData *unit) { QmlError error; error.setUrl(unit->imports.baseUrl()); - error.setDescription(tr("Type %1 unavailable").arg(QLatin1String(typeName))); + error.setDescription(tr("Type %1 unavailable").arg(QString::fromUtf8(typeName))); if (!parserRef->refObjects.isEmpty()) { QmlParser::Object *obj = parserRef->refObjects.first(); error.setLine(obj->location.start.line); diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index f6795aa..43a4741 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -61,8 +61,11 @@ QmlContextPrivate::QmlContextPrivate() { } -void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject) +void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject, + const QString &fileName, int lineNumber) { + Q_Q(QmlContext); + if (!engine) return; @@ -70,29 +73,15 @@ void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject) QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(scriptValue); + scriptContext->pushScope(enginePriv->contextClass->newContext(q, scopeObject)); - if (scopeObject) - scriptContext->pushScope(enginePriv->objectClass->newQObject(scopeObject)); - QScriptValue scope = scriptEngine->newObject(); scriptContext->setActivationObject(scope); - QScriptValue val = scriptEngine->evaluate(script); + QScriptValue val = scriptEngine->evaluate(script, fileName, lineNumber); - if (scriptEngine->hasUncaughtException()) { - if (scriptEngine->uncaughtException().isError()){ - QScriptValue exception = scriptEngine->uncaughtException(); - if (!exception.property(QLatin1String("fileName")).toString().isEmpty()){ - qWarning() << exception.property(QLatin1String("fileName")).toString() - << scriptEngine->uncaughtExceptionLineNumber() - << exception.toString(); - - } else { - qmlInfo(scopeObject) << exception.toString(); - } - } - } + if (scriptEngine->hasUncaughtException()) + QmlExpressionPrivate::printException(scriptEngine); scriptEngine->popContext(); @@ -139,10 +128,6 @@ void QmlContextPrivate::init() if (parent) parent->d_func()->childContexts.insert(q); - - //set scope chain - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - scriptValue = QmlEnginePrivate::get(engine)->contextClass->newContext(q); } void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority) diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index d18bfda..9a77e94 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -91,10 +91,9 @@ public: QObjectList defaultObjects; int highPriorityCount; - QScriptValue scriptValue; - QList<QScriptValue> scripts; - void addScript(const QString &script, QObject *scope); + void addScript(const QString &script, QObject *scope, + const QString &fileName = QString(), int lineNumber = 1); QUrl url; diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp index 6d2c58c..939d008 100644 --- a/src/declarative/qml/qmlcontextscriptclass.cpp +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -47,8 +47,9 @@ QT_BEGIN_NAMESPACE struct ContextData : public QScriptDeclarativeClass::Object { - ContextData(QmlContext *c) : context(c) {} + ContextData(QmlContext *c, QObject *o) : context(c), scopeObject(o) {} QGuard<QmlContext> context; + QGuard<QObject> scopeObject; }; /* @@ -57,7 +58,7 @@ struct ContextData : public QScriptDeclarativeClass::Object { */ QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine) : QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), - lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1) + lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1) { } @@ -65,11 +66,11 @@ QmlContextScriptClass::~QmlContextScriptClass() { } -QScriptValue QmlContextScriptClass::newContext(QmlContext *context) +QScriptValue QmlContextScriptClass::newContext(QmlContext *context, QObject *scopeObject) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - return newObject(scriptEngine, this, new ContextData(context)); + return newObject(scriptEngine, this, new ContextData(context, scopeObject)); } QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v) @@ -81,24 +82,27 @@ QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v) return data->context; } -#include <QDebug> QScriptClass::QueryFlags QmlContextScriptClass::queryProperty(Object *object, const Identifier &name, QScriptClass::QueryFlags flags) { Q_UNUSED(flags); + lastScopeObject = 0; lastContext = 0; lastData = 0; lastPropertyIndex = -1; lastDefaultObject = -1; QmlContext *bindContext = ((ContextData *)object)->context.data(); + QObject *scopeObject = ((ContextData *)object)->scopeObject.data(); if (!bindContext) return 0; while (bindContext) { - QScriptClass::QueryFlags rv = queryProperty(bindContext, name, flags); + QScriptClass::QueryFlags rv = + queryProperty(bindContext, scopeObject, name, flags); + scopeObject = 0; // Only applies to the first context if (rv) return rv; bindContext = bindContext->parentContext(); } @@ -107,7 +111,8 @@ QmlContextScriptClass::queryProperty(Object *object, const Identifier &name, } QScriptClass::QueryFlags -QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier &name, +QmlContextScriptClass::queryProperty(QmlContext *bindContext, QObject *scopeObject, + const Identifier &name, QScriptClass::QueryFlags flags) { QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); @@ -129,6 +134,24 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier & } } + for (int ii = 0; ii < cp->scripts.count(); ++ii) { + lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name); + if (lastFunction.isValid()) { + lastContext = bindContext; + return QScriptClass::HandlesReadAccess; + } + } + + if (scopeObject) { + QScriptClass::QueryFlags rv = + ep->objectClass->queryProperty(scopeObject, name, flags, 0); + if (rv) { + lastScopeObject = scopeObject; + lastContext = bindContext; + return rv; + } + } + for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) { QScriptClass::QueryFlags rv = ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, 0); @@ -140,13 +163,6 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier & } } - for (int ii = 0; ii < cp->scripts.count(); ++ii) { - lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name); - if (lastFunction.isValid()) { - lastContext = bindContext; - return QScriptClass::HandlesReadAccess; - } - } return 0; } @@ -160,8 +176,11 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); + if (lastScopeObject) { - if (lastData) { + return ep->objectClass->property(lastScopeObject, name); + + } else if (lastData) { if (lastData->type) return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->type); @@ -197,7 +216,7 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n void QmlContextScriptClass::setProperty(Object *object, const Identifier &name, const QScriptValue &value) { - Q_ASSERT(lastDefaultObject != -1); + Q_ASSERT(lastScopeObject || lastDefaultObject != -1); QmlContext *bindContext = lastContext; Q_ASSERT(bindContext); @@ -205,7 +224,11 @@ void QmlContextScriptClass::setProperty(Object *object, const Identifier &name, QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); - ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value); + if (lastScopeObject) { + ep->objectClass->setProperty(lastScopeObject, name, value); + } else { + ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value); + } } QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h index 761a115..126c8fe 100644 --- a/src/declarative/qml/qmlcontextscriptclass_p.h +++ b/src/declarative/qml/qmlcontextscriptclass_p.h @@ -67,7 +67,7 @@ public: QmlContextScriptClass(QmlEngine *); ~QmlContextScriptClass(); - QScriptValue newContext(QmlContext *); + QScriptValue newContext(QmlContext *, QObject * = 0); QmlContext *contextFromValue(const QScriptValue &); @@ -78,11 +78,13 @@ protected: virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); private: - QScriptClass::QueryFlags queryProperty(QmlContext *, const Identifier &, + QScriptClass::QueryFlags queryProperty(QmlContext *, QObject *scopeObject, + const Identifier &, QScriptClass::QueryFlags flags); QmlEngine *engine; + QObject *lastScopeObject; QmlContext *lastContext; QmlTypeNameCache::Data *lastData; int lastPropertyIndex; diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index ccdf6cf..245ddc0 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -970,7 +970,7 @@ struct QmlEnginePrivate::ImportedNamespace { int vmin = minversions.at(i); if (isBuiltin.at(i)) { - QByteArray qt = urls.at(i).toLatin1(); + QByteArray qt = urls.at(i).toUtf8(); qt += "/"; qt += type; QmlType *t = QmlMetaType::qmlType(qt,vmaj,vmin); @@ -982,7 +982,7 @@ struct QmlEnginePrivate::ImportedNamespace { return true; } } else { - QUrl url = QUrl(urls.at(i) + QLatin1String("/" + type + ".qml")); + QUrl url = QUrl(urls.at(i) + QLatin1String("/") + QString::fromUtf8(type) + QLatin1String(".qml")); if (vmaj || vmin) { // Check version file - XXX cache these in QmlEngine! QFile qmldir(QUrl(urls.at(i)+QLatin1String("/qmldir")).toLocalFile()); @@ -1101,7 +1101,7 @@ public: if (s->find(unqualifiedtype,vmajor,vminor,type_return,url_return)) return true; if (s->urls.count() == 1 && !s->isBuiltin[0] && !s->isLibrary[0] && url_return) { - *url_return = QUrl(s->urls[0]+QLatin1String("/")).resolved(QUrl(QLatin1String(unqualifiedtype + ".qml"))); + *url_return = QUrl(s->urls[0]+QLatin1String("/")).resolved(QUrl(QString::fromUtf8(unqualifiedtype) + QLatin1String(".qml"))); return true; } } @@ -1323,7 +1323,7 @@ bool QmlEnginePrivate::addToImport(Imports* imports, const QString& uri, const Q */ bool QmlEnginePrivate::resolveType(const Imports& imports, const QByteArray& type, QmlType** type_return, QUrl* url_return, int *vmaj, int *vmin, ImportedNamespace** ns_return) const { - ImportedNamespace* ns = imports.d->findNamespace(QLatin1String(type)); + ImportedNamespace* ns = imports.d->findNamespace(QString::fromUtf8(type)); if (ns) { if (qmlImportTrace()) qDebug() << "QmlEngine::resolveType" << type << "is namespace for" << ns->urls; @@ -1379,7 +1379,7 @@ static void *voidptr_constructor(const void *v) void QmlEnginePrivate::registerCompositeType(QmlCompiledData *data) { - QByteArray name = data->root.className(); + QByteArray name = data->root->className(); QByteArray ptr = name + "*"; QByteArray lst = "QmlList<" + ptr + ">*"; @@ -1417,7 +1417,7 @@ const QMetaObject *QmlEnginePrivate::rawMetaObjectForType(int t) const { QHash<int, QmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t); if (iter != m_compositeTypes.end()) { - return &(*iter)->root; + return (*iter)->root; } else { return QmlMetaType::rawMetaObjectForType(t); } @@ -1427,7 +1427,7 @@ const QMetaObject *QmlEnginePrivate::metaObjectForType(int t) const { QHash<int, QmlCompiledData*>::ConstIterator iter = m_compositeTypes.find(t); if (iter != m_compositeTypes.end()) { - return &(*iter)->root; + return (*iter)->root; } else { return QmlMetaType::metaObjectForType(t); } diff --git a/src/declarative/qml/qmlenginedebug.cpp b/src/declarative/qml/qmlenginedebug.cpp index 16129ee..e20616a 100644 --- a/src/declarative/qml/qmlenginedebug.cpp +++ b/src/declarative/qml/qmlenginedebug.cpp @@ -325,8 +325,8 @@ void QmlEngineDebugServer::propertyChanged(int id, int objectId, const QByteArra QString objectName = o->objectName(); if (objectName.isEmpty()) objectName = QLatin1String("<unnamed>"); - v = QLatin1String(o->metaObject()->className()) + - QLatin1String(": ") + objectName; + v = QString::fromUtf8(o->metaObject()->className()) + + QLatin1String(": ") + objectName; } if (v.isNull()) v = value.toString(); diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 23e1700..76ca2c1 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -89,8 +89,11 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, const QString &expr, } void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, - QObject *me) + QObject *me, const QUrl &url, int lineNumber) { + data->fileName = url.toString(); + data->line = lineNumber; + quint32 *exprData = (quint32 *)expr; Q_ASSERT(*exprData == BasicScriptEngineData || *exprData == PreTransformedQtScriptData); @@ -107,14 +110,12 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); if (!dd->programs.at(progIdx)) { - dd->programs[progIdx] = new QScriptProgram(scriptEngine->compile(data->expression)); + dd->programs[progIdx] = + new QScriptProgram(scriptEngine->compile(data->expression, data->fileName, data->line)); } - QmlContextPrivate *ctxtPriv = ctxt->d_func(); QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(ctxtPriv->scriptValue); - if (me) - scriptContext->pushScope(ep->objectClass->newQObject(me)); + scriptContext->pushScope(ep->contextClass->newContext(ctxt, me)); data->expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]); @@ -145,11 +146,12 @@ QmlExpression::QmlExpression() /*! \internal */ QmlExpression::QmlExpression(QmlContext *ctxt, void *expr, QmlRefCount *rc, QObject *me, + const QUrl &url, int lineNumber, QmlExpressionPrivate &dd) : QObject(dd, 0) { Q_D(QmlExpression); - d->init(ctxt, expr, rc, me); + d->init(ctxt, expr, rc, me, url, lineNumber); } /*! @@ -210,7 +212,7 @@ QString QmlExpression::expression() const { Q_D(const QmlExpression); if (d->data->sse.isValid()) - return QLatin1String(d->data->sse.expression()); + return QString::fromUtf8(d->data->sse.expression()); else return d->data->expression; } @@ -251,6 +253,28 @@ QVariant QmlExpressionPrivate::evalSSE() return rv; } +void QmlExpressionPrivate::printException(QScriptEngine *scriptEngine) +{ + if (scriptEngine->hasUncaughtException() && + scriptEngine->uncaughtException().isError()) { + + QString fileName; + int lineNumber = scriptEngine->uncaughtExceptionLineNumber(); + + QScriptValue exception = scriptEngine->uncaughtException(); + QLatin1String fileNameProp("fileName"); + + if (!exception.property(fileNameProp).toString().isEmpty()){ + fileName = exception.property(fileNameProp).toString(); + } else { + fileName = QLatin1String("<Unknown File>"); + } + + qWarning().nospace() << qPrintable(fileName) << ":" << lineNumber << ": " + << qPrintable(exception.toString()); + } +} + QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) { #ifdef Q_ENABLE_PERFORMANCE_LOG @@ -270,10 +294,7 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) if (!data->expressionFunctionValid) { QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(ctxtPriv->scriptValue); - - if (data->me) - scriptContext->pushScope(ep->objectClass->newQObject(data->me)); + scriptContext->pushScope(ep->contextClass->newContext(data->context(), data->me)); if (data->expressionRewritten) { data->expressionFunction = scriptEngine->evaluate(data->expression, @@ -291,19 +312,8 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) QScriptValue svalue = data->expressionFunction.call(); - if (scriptEngine->hasUncaughtException()) { - if (scriptEngine->uncaughtException().isError()){ - QScriptValue exception = scriptEngine->uncaughtException(); - QLatin1String fileNameProp("fileName"); - if (!exception.property(fileNameProp).toString().isEmpty()){ - qWarning() << exception.property(fileNameProp).toString() - << scriptEngine->uncaughtExceptionLineNumber() - << exception.toString(); - } else { - qWarning() << exception.toString(); - } - } - } + if (scriptEngine->hasUncaughtException()) + printException(scriptEngine); if (secondaryScope) ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount); diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h index c295a1c..b85e0a7 100644 --- a/src/declarative/qml/qmlexpression.h +++ b/src/declarative/qml/qmlexpression.h @@ -89,8 +89,8 @@ Q_SIGNALS: protected: QmlExpression(QmlContext *, const QString &, QObject *, QmlExpressionPrivate &dd); - QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me, - QmlExpressionPrivate &dd); + QmlExpression(QmlContext *, void *, QmlRefCount *rc, QObject *me, const QUrl &, + int, QmlExpressionPrivate &dd); private Q_SLOTS: void __q_notify(); diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h index 33016e6..d9bb27b 100644 --- a/src/declarative/qml/qmlexpression_p.h +++ b/src/declarative/qml/qmlexpression_p.h @@ -136,7 +136,7 @@ public: }; void init(QmlContext *, const QString &, QObject *); - void init(QmlContext *, void *, QmlRefCount *, QObject *); + void init(QmlContext *, void *, QmlRefCount *, QObject *, const QUrl &, int); QmlExpressionData *data; @@ -150,6 +150,8 @@ public: static QmlExpressionPrivate *get(QmlExpression *expr) { return static_cast<QmlExpressionPrivate *>(QObjectPrivate::get(expr)); } + + static void printException(QScriptEngine *); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlinfo.cpp b/src/declarative/qml/qmlinfo.cpp index bae1682..e3c0225 100644 --- a/src/declarative/qml/qmlinfo.cpp +++ b/src/declarative/qml/qmlinfo.cpp @@ -95,7 +95,7 @@ QmlInfo::QmlInfo(QObject *object) location += QLatin1String(":"); location += QString::number(ddata->columnNumber); location += QLatin1String(")"); - *this << location.toLatin1().constData(); + *this << qPrintable(location); } else { *this << "(unknown location):"; } diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp index 18439f4..a465445 100644 --- a/src/declarative/qml/qmlinstruction.cpp +++ b/src/declarative/qml/qmlinstruction.cpp @@ -149,6 +149,9 @@ void QmlCompiledData::dump(QmlInstruction *instr, int idx) case QmlInstruction::StoreValueSource: qWarning() << idx << "\t" << line << "\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property << "\t" << instr->assignValueSource.castValue; break; + case QmlInstruction::StoreValueInterceptor: + qWarning() << idx << "\t" << line << "\t" << "STORE_VALUE_INTERCEPTOR\t" << instr->assignValueInterceptor.property << "\t" << instr->assignValueInterceptor.castValue; + break; case QmlInstruction::BeginObject: qWarning() << idx << "\t" << line << "\t" << "BEGIN\t\t\t" << instr->begin.castValue; break; diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h index 1dcdace..5265d42 100644 --- a/src/declarative/qml/qmlinstruction_p.h +++ b/src/declarative/qml/qmlinstruction_p.h @@ -130,6 +130,7 @@ public: StoreIdOptBinding, /* assignIdOptBinding */ StoreObjPropBinding, /* assignObjPropBinding */ StoreValueSource, /* assignValueSource */ + StoreValueInterceptor, /* assignValueInterceptor */ BeginObject, /* begin */ @@ -190,6 +191,11 @@ public: } assignValueSource; struct { int property; + int owner; + int castValue; + } assignValueInterceptor; //### merge with above + struct { + int property; int value; short context; short owner; @@ -240,6 +246,8 @@ public: } storeString; struct { int value; + int fileName; + int lineNumber; } storeScript; struct { int propertyIndex; diff --git a/src/declarative/qml/qmlintegercache.cpp b/src/declarative/qml/qmlintegercache.cpp index 564faaa..89a18a1 100644 --- a/src/declarative/qml/qmlintegercache.cpp +++ b/src/declarative/qml/qmlintegercache.cpp @@ -87,7 +87,7 @@ QmlIntegerCache *QmlIntegerCache::createForEnums(QmlType *type, QmlEngine *engin QMetaEnum enumerator = mo->enumerator(ii); for (int jj = 0; jj < enumerator.keyCount(); ++jj) { - QString name = QLatin1String(enumerator.key(jj)); + QString name = QString::fromUtf8(enumerator.key(jj)); int value = enumerator.value(jj); if (!name.at(0).isUpper()) diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 302ce8c..79022e7 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -174,7 +174,7 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) if (typeData) { QmlType *t = 0; - enginePrivate->resolveType(typeData->imports, name.toLatin1(), &t, 0, 0, 0, 0); + enginePrivate->resolveType(typeData->imports, name.toUtf8(), &t, 0, 0, 0, 0); if (t && t->attachedPropertiesFunction()) { attachedFunc = t->index(); } @@ -467,7 +467,7 @@ QStringList QmlMetaProperty::properties(QObject *obj) const QMetaObject *mo = obj->metaObject(); for (int ii = 0; ii < mo->propertyCount(); ++ii) { QMetaProperty prop = mo->property(ii); - rv << QLatin1String(prop.name()); + rv << QString::fromUtf8(prop.name()); } return rv; @@ -487,7 +487,7 @@ QString QmlMetaProperty::name() const else valueType = QmlValueTypeFactory::valueType(d->core.propType); Q_ASSERT(valueType); - rv += QLatin1String(valueType->metaObject()->property(d->valueTypeCoreIdx).name()); + rv += QString::fromUtf8(valueType->metaObject()->property(d->valueTypeCoreIdx).name()); if (!ep) delete valueType; @@ -559,17 +559,17 @@ QmlAbstractBinding *QmlMetaProperty::binding() const is assumed by the caller. */ QmlAbstractBinding * -QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding) const +QmlMetaProperty::setBinding(QmlAbstractBinding *newBinding, QmlMetaProperty::WriteFlags flags) const { if (!isProperty() || (type() & Attached) || !d->object) return 0; - return d->setBinding(d->object, d->core, newBinding); + return d->setBinding(d->object, d->core, newBinding, flags); } QmlAbstractBinding * QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data &core, - QmlAbstractBinding *newBinding) + QmlAbstractBinding *newBinding, QmlMetaProperty::WriteFlags flags) { QmlDeclarativeData *data = QmlDeclarativeData::get(object, 0 != newBinding); @@ -581,7 +581,7 @@ QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data binding->setEnabled(false); if (newBinding) - newBinding->setEnabled(true); + newBinding->setEnabled(true, flags); return binding; // ### QmlAbstractBinding; } @@ -591,7 +591,7 @@ QmlMetaPropertyPrivate::setBinding(QObject *object, const QmlPropertyCache::Data } if (newBinding) - newBinding->setEnabled(true); + newBinding->setEnabled(true, flags); return 0; } @@ -654,7 +654,7 @@ QMetaMethod QmlMetaPropertyPrivate::findSignal(QObject *obj, const QString &name int methods = mo->methodCount(); for (int ii = methods - 1; ii >= 0; --ii) { QMetaMethod method = mo->method(ii); - QString methodName = QLatin1String(method.signature()); + QString methodName = QString::fromUtf8(method.signature()); int idx = methodName.indexOf(QLatin1Char('(')); methodName = methodName.left(idx); @@ -698,30 +698,6 @@ QVariant QmlMetaProperty::read() const return QVariant(); } -void QmlMetaPropertyPrivate::writeSignalProperty(const QVariant &value) -{ - QString expr = value.toString(); - const QObjectList &children = object->children(); - - for (int ii = 0; ii < children.count(); ++ii) { - QmlBoundSignal *sig = QmlBoundSignal::cast(children.at(ii)); - if (sig && sig->index() == core.coreIndex) { - if (expr.isEmpty()) { - sig->disconnect(); - sig->deleteLater(); - } else { - sig->expression()->setExpression(expr); - } - return; - } - } - - if (!expr.isEmpty()) { - // XXX scope - (void *)new QmlBoundSignal(qmlContext(object), expr, object, q->method(), object); - } -} - QVariant QmlMetaPropertyPrivate::readValueProperty() { uint type = q->type(); @@ -752,11 +728,52 @@ QVariant QmlMetaPropertyPrivate::readValueProperty() } } +//### +//writeEnumProperty MIRRORS the relelvant bit of QMetaProperty::write AND MUST BE KEPT IN SYNC! +//### +bool QmlMetaPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags) +{ + if (!object || !prop.isWritable()) + return false; + + QVariant v = value; + uint t = QVariant::Invalid; + if (prop.isEnumType()) { + QMetaEnum menum = prop.enumerator(); + if (v.type() == QVariant::String +#ifdef QT3_SUPPORT + || v.type() == QVariant::CString +#endif + ) { + if (prop.isFlagType()) + v = QVariant(menum.keysToValue(value.toByteArray())); + else + v = QVariant(menum.keyToValue(value.toByteArray())); + } else if (v.type() != QVariant::Int && v.type() != QVariant::UInt) { + int enumMetaTypeId = QMetaType::type(QByteArray(menum.scope()) + "::" + menum.name()); + if ((enumMetaTypeId == 0) || (v.userType() != enumMetaTypeId) || !v.constData()) + return false; + v = QVariant(*reinterpret_cast<const int *>(v.constData())); + } + v.convert(QVariant::Int); + } + + // the status variable is changed by qt_metacall to indicate what it did + // this feature is currently only used by QtDBus and should not be depended + // upon. Don't change it without looking into QDBusAbstractInterface first + // -1 (unchanged): normal qt_metacall, result stored in argv[0] + // changed: result stored directly in value, return the value of status + int status = -1; + void *argv[] = { v.data(), &v, &status, &flags }; + QMetaObject::metacall(object, QMetaObject::WriteProperty, idx, argv); + return status; +} + void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value, - QmlMetaProperty::WriteSource source) + QmlMetaProperty::WriteFlags flags) { // Remove any existing bindings on this property - if (source != QmlMetaProperty::Binding) + if (!(flags & QmlMetaProperty::DontRemoveBinding)) delete q->setBinding(0); uint type = q->type(); @@ -776,22 +793,23 @@ void QmlMetaPropertyPrivate::writeValueProperty(const QVariant &value, QmlPropertyCache::Data data = core; data.coreIndex = valueTypeCoreIdx; data.propType = valueTypePropType; - write(writeBack, data, value, context); + write(writeBack, data, value, context, flags); - writeBack->write(object, core.coreIndex); + writeBack->write(object, core.coreIndex, flags); if (!ep) delete writeBack; } else { - write(object, core, value, context); + write(object, core, value, context, flags); } } void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data &property, - const QVariant &value, QmlContext *context) + const QVariant &value, QmlContext *context, QmlMetaProperty::WriteFlags flags) { int coreIdx = property.coreIndex; + int status = -1; //for dbus if (property.flags & QmlPropertyCache::Data::IsEnumType) { QMetaProperty prop = object->metaObject()->property(property.coreIndex); @@ -803,7 +821,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data if (qFuzzyCompare(fractional, (double)0.0)) v.convert(QVariant::Int); } - prop.write(object, v); + writeEnumProperty(prop, coreIdx, object, v, flags); return; } @@ -819,7 +837,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data u = value.toUrl(); found = true; } else if (vt == QVariant::ByteArray) { - u = QUrl(QLatin1String(value.toByteArray())); + u = QUrl(QString::fromUtf8(value.toByteArray())); found = true; } else if (vt == QVariant::String) { u = QUrl(value.toString()); @@ -829,21 +847,19 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data if (found) { if (context && u.isRelative() && !u.isEmpty()) u = context->baseUrl().resolved(u); - void *a[1]; - a[0] = &u; - QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); + int status = -1; + void *argv[] = { &u, 0, &status, &flags }; + QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, argv); } } else if (vt == t) { - void *a[1]; - a[0] = (void *)value.constData(); + void *a[] = { (void *)value.constData(), 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else if (qMetaTypeId<QVariant>() == t) { - void *a[1]; - a[0] = (void *)&value; + void *a[] = { (void *)&value, 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else if (property.flags & QmlPropertyCache::Data::IsQObjectDerived) { @@ -858,7 +874,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data const QMetaObject *propMo = QmlMetaType::rawMetaObjectForType(t); while (valMo) { - if (valMo == propMo) + if (equal(valMo, propMo)) break; valMo = valMo->superClass(); } @@ -867,7 +883,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data if (valMo || !o) { - void *args[] = { &o, 0 }; + void *args[] = { &o, 0, &status, &flags }; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, args); @@ -912,7 +928,7 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data const QMetaObject *objMo = obj->metaObject(); bool found = false; while(!found && objMo) { - if (objMo == mo) + if (equal(objMo, mo)) found = true; else objMo = objMo->superClass(); @@ -933,16 +949,14 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data QVariant v = value; if (v.convert((QVariant::Type)t)) { - void *a[1]; - a[0] = (void *)v.constData(); + void *a[] = { (void *)v.constData(), 0, &status, &flags}; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } else if ((uint)t >= QVariant::UserType && vt == QVariant::String) { QmlMetaType::StringConverter con = QmlMetaType::customStringConverter(t); if (con) { QVariant v = con(value.toString()); if (v.userType() == t) { - void *a[1]; - a[0] = (void *)v.constData(); + void *a[] = { (void *)v.constData(), 0, &status, &flags}; QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, a); } } @@ -955,21 +969,17 @@ void QmlMetaPropertyPrivate::write(QObject *object, const QmlPropertyCache::Data */ void QmlMetaProperty::write(const QVariant &value) const { - write(value, Other); + write(value, 0); } -void QmlMetaProperty::write(const QVariant &value, WriteSource source) const +void QmlMetaProperty::write(const QVariant &value, QmlMetaProperty::WriteFlags flags) const { if (!d->object) return; - if (type() & SignalProperty) { - - d->writeSignalProperty(value); + if (type() & Property && d->core.isValid()) { - } else if (d->core.isValid()) { - - d->writeValueProperty(value, source); + d->writeValueProperty(value, flags); } } @@ -1201,4 +1211,13 @@ QmlMetaProperty QmlMetaProperty::createProperty(QObject *obj, return prop; } +/*! + Returns true if lhs and rhs refer to the same metaobject data +*/ +bool QmlMetaPropertyPrivate::equal(const QMetaObject *lhs, const QMetaObject *rhs) +{ + return lhs == rhs || (1 && lhs && rhs && lhs->d.stringdata == rhs->d.stringdata); +} + + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlmetaproperty.h b/src/declarative/qml/qmlmetaproperty.h index 8c34ece..b0ae28c 100644 --- a/src/declarative/qml/qmlmetaproperty.h +++ b/src/declarative/qml/qmlmetaproperty.h @@ -88,8 +88,9 @@ public: QVariant read() const; void write(const QVariant &) const; - enum WriteSource { Animation, Binding, Other }; - void write(const QVariant &, WriteSource) const; + enum WriteFlag { BypassInterceptor = 0x01, DontRemoveBinding = 0x02 }; + Q_DECLARE_FLAGS(WriteFlags, WriteFlag) + void write(const QVariant &, QmlMetaProperty::WriteFlags) const; bool hasChangedNotifier() const; bool needsChangedNotifier() const; @@ -126,7 +127,8 @@ public: QMetaProperty property() const; QmlAbstractBinding *binding() const; - QmlAbstractBinding *setBinding(QmlAbstractBinding *) const; + QmlAbstractBinding *setBinding(QmlAbstractBinding *, + QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding) const; QmlExpression *signalExpression() const; QmlExpression *setSignalExpression(QmlExpression *) const; @@ -139,6 +141,7 @@ private: QmlMetaPropertyPrivate *d; }; typedef QList<QmlMetaProperty> QmlMetaProperties; + Q_DECLARE_OPERATORS_FOR_FLAGS(QmlMetaProperty::WriteFlags) QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 00b9c3a..7288266 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -96,15 +96,18 @@ public: int propertyType() const; QmlMetaProperty::PropertyCategory propertyCategory() const; - void writeSignalProperty(const QVariant &); - QVariant readValueProperty(); - void writeValueProperty(const QVariant &, QmlMetaProperty::WriteSource); - static void write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *); - static QmlAbstractBinding *setBinding(QObject *, const QmlPropertyCache::Data &, QmlAbstractBinding *); + void writeValueProperty(const QVariant &, QmlMetaProperty::WriteFlags); + static bool writeEnumProperty(const QMetaProperty &prop, int idx, QObject *object, const QVariant &value, int flags); + static void write(QObject *, const QmlPropertyCache::Data &, const QVariant &, QmlContext *, + QmlMetaProperty::WriteFlags flags = 0); + static QmlAbstractBinding *setBinding(QObject *, const QmlPropertyCache::Data &, QmlAbstractBinding *, + QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding); static quint32 saveValueType(int, int); static quint32 saveProperty(int); + + static bool equal(const QMetaObject *, const QMetaObject *); }; QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp index c40232f..5198f9f 100644 --- a/src/declarative/qml/qmlmetatype.cpp +++ b/src/declarative/qml/qmlmetatype.cpp @@ -128,6 +128,7 @@ public: const QMetaObject *m_attachedPropertiesType; int m_parserStatusCast; int m_propertyValueSourceCast; + int m_propertyValueInterceptorCast; QmlPrivate::CreateFunc m_extFunc; const QMetaObject *m_extMetaObject; int m_index; @@ -140,8 +141,8 @@ public: QmlTypePrivate::QmlTypePrivate() : m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_qmlListId(0), m_opFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), - m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_extFunc(0), m_extMetaObject(0), - m_index(-1), m_customParser(0), m_isSetup(false) + m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_propertyValueInterceptorCast(-1), + m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), m_isSetup(false) { } @@ -169,7 +170,8 @@ QmlType::QmlType(int type, int listType, int qmlListType, const QMetaObject *metaObject, QmlAttachedPropertiesFunc attachedPropertiesFunc, const QMetaObject *attachedType, - int parserStatusCast, int propertyValueSourceCast, QmlPrivate::CreateFunc extFunc, + int parserStatusCast, int propertyValueSourceCast, int propertyValueInterceptorCast, + QmlPrivate::CreateFunc extFunc, const QMetaObject *extMetaObject, int index, QmlCustomParser *customParser) : d(new QmlTypePrivate) @@ -187,6 +189,7 @@ QmlType::QmlType(int type, int listType, int qmlListType, d->m_attachedPropertiesType = attachedType; d->m_parserStatusCast = parserStatusCast; d->m_propertyValueSourceCast = propertyValueSourceCast; + d->m_propertyValueInterceptorCast = propertyValueInterceptorCast; d->m_extFunc = extFunc; d->m_index = index; d->m_customParser = customParser; @@ -412,6 +415,11 @@ int QmlType::propertyValueSourceCast() const return d->m_propertyValueSourceCast; } +int QmlType::propertyValueInterceptorCast() const +{ + return d->m_propertyValueInterceptorCast; +} + QVariant QmlType::fromObject(QObject *obj) const { QVariant rv; @@ -467,7 +475,7 @@ int QmlMetaType::registerInterface(const QmlPrivate::MetaTypeIds &id, int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Func func, const char *uri, int version_maj, int version_min_from, int version_min_to, const char *cname, const QMetaObject *mo, QmlAttachedPropertiesFunc attach, const QMetaObject *attachMo, - int pStatus, int object, int valueSource, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser) + int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser) { Q_UNUSED(object); @@ -492,7 +500,7 @@ int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Fun QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId, func, name, version_maj, version_min_from, version_min_to, mo, attach, attachMo, pStatus, - valueSource, extFunc, extmo, index, parser); + valueSource, valueInterceptor, extFunc, extmo, index, parser); data->types.append(type); data->idToType.insert(type->typeId(), type); @@ -539,6 +547,17 @@ int QmlMetaType::qmlPropertyValueSourceCast(int userType) return -1; } +int QmlMetaType::qmlPropertyValueInterceptorCast(int userType) +{ + QReadLocker lock(metaTypeDataLock()); + QmlMetaTypeData *data = metaTypeData(); + QmlType *type = data->idToType.value(userType); + if (type && type->typeId() == userType) + return type->propertyValueInterceptorCast(); + else + return -1; +} + QObject *QmlMetaType::toQObject(const QVariant &v) { if (!isObject(v.userType())) diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h index 02c817d..42c278c 100644 --- a/src/declarative/qml/qmlmetatype.h +++ b/src/declarative/qml/qmlmetatype.h @@ -48,6 +48,7 @@ #include <QtDeclarative/qmlprivate.h> #include <QtDeclarative/qmlparserstatus.h> #include <QtDeclarative/qmlpropertyvaluesource.h> +#include <QtDeclarative/qmlpropertyvalueinterceptor.h> QT_BEGIN_HEADER @@ -60,7 +61,7 @@ class QmlCustomParser; class Q_DECLARATIVE_EXPORT QmlMetaType { public: - static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, int vmaj, int vmin_from, int vmin_to, const char *qmlName, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, int valueSource, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *); + static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, int vmaj, int vmin_from, int vmin_to, const char *qmlName, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, int valueSource, int valueInterceptor, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *); static int registerInterface(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *); static bool copy(int type, void *data, const void *copy = 0); @@ -80,6 +81,7 @@ public: static QObject *toQObject(const QVariant &); static int qmlParserStatusCast(int); static int qmlPropertyValueSourceCast(int); + static int qmlPropertyValueInterceptorCast(int); static int listType(int); static bool clear(const QVariant &); static bool append(const QVariant &, const QVariant &); @@ -146,6 +148,7 @@ public: QVariant fromObject(QObject *) const; const char *interfaceIId() const; int propertyValueSourceCast() const; + int propertyValueInterceptorCast() const; int index() const; private: @@ -153,7 +156,7 @@ private: friend class QmlTypePrivate; friend class QmlMetaTypeData; QmlType(int, int, int, QmlPrivate::Func, const char *, int); - QmlType(int, int, int, QmlPrivate::Func, const char *, int, int, int, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *); + QmlType(int, int, int, QmlPrivate::Func, const char *, int, int, int, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, int, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *); ~QmlType(); QmlTypePrivate *d; @@ -176,6 +179,7 @@ int qmlRegisterType(const char *typeName) QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(), QmlPrivate::StaticCastSelector<T,QObject>::cast(), QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(), + QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(), 0, 0, 0); } @@ -196,7 +200,8 @@ int qmlRegisterType(const char *uri, int version_maj, int version_min_from, int QmlPrivate::attachedPropertiesMetaObject<T>(), QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(), QmlPrivate::StaticCastSelector<T,QObject>::cast(), - QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(), + QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(), + QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(), 0, 0, 0); } @@ -224,6 +229,7 @@ int qmlRegisterExtendedType(const char *typeName) QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(), QmlPrivate::StaticCastSelector<T,QObject>::cast(), QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(), + QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(), &QmlPrivate::CreateParent<E>::create, &E::staticMetaObject, 0); } @@ -253,6 +259,7 @@ int qmlRegisterExtendedType(const char *uri, int version_maj, int version_min_fr QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(), QmlPrivate::StaticCastSelector<T,QObject>::cast(), QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(), + QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(), &QmlPrivate::CreateParent<E>::create, &E::staticMetaObject, 0); } @@ -290,6 +297,7 @@ int qmlRegisterCustomType(const char *uri, int version_maj, int version_min_from QmlPrivate::StaticCastSelector<T,QmlParserStatus>::cast(), QmlPrivate::StaticCastSelector<T,QObject>::cast(), QmlPrivate::StaticCastSelector<T,QmlPropertyValueSource>::cast(), + QmlPrivate::StaticCastSelector<T,QmlPropertyValueInterceptor>::cast(), 0, 0, parser); } diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp index 41573a2..80f2786 100644 --- a/src/declarative/qml/qmlobjectscriptclass.cpp +++ b/src/declarative/qml/qmlobjectscriptclass.cpp @@ -267,7 +267,7 @@ QScriptValue QmlObjectScriptClass::tostring(QScriptContext *context, QScriptEngi if(obj){ QString objectName = obj->objectName(); - ret += QLatin1String(obj->metaObject()->className()); + ret += QString::fromUtf8(obj->metaObject()->className()); ret += QLatin1String("(0x"); ret += QString::number((quintptr)obj,16); diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index 8c46939..bae263a 100644 --- a/src/declarative/qml/qmlparser.cpp +++ b/src/declarative/qml/qmlparser.cpp @@ -282,6 +282,9 @@ void QmlParser::Value::dump(int indent) const case Value::ValueSource: type = "ValueSource"; break; + case Value::ValueInterceptor: + type = "ValueInterceptor"; + break; case Value::CreatedObject: type = "CreatedObject"; break; diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index 16862eb..88d7d77 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -168,6 +168,8 @@ namespace QmlParser // Script blocks that were nested under this object QStringList scriptBlocks; + QStringList scriptBlocksFile; + QList<int> scriptBlocksLineNumber; // The bytes to cast instances by to get to the QmlParserStatus // interface. -1 indicates the type doesn't support this interface. @@ -273,6 +275,8 @@ namespace QmlParser PropertyBinding, // This is used as a QmlPropertyValueSource assignment ValueSource, + // This is used as a QmlPropertyValueInterceptor assignment + ValueInterceptor, // This is used as a property QObject assignment CreatedObject, // This is used as a signal object assignment diff --git a/src/declarative/qml/qmlpropertycache.cpp b/src/declarative/qml/qmlpropertycache.cpp index 63ce00c..e00126f 100644 --- a/src/declarative/qml/qmlpropertycache.cpp +++ b/src/declarative/qml/qmlpropertycache.cpp @@ -52,7 +52,7 @@ void QmlPropertyCache::Data::load(const QMetaProperty &p) propType = qMetaTypeId<QVariant>(); coreIndex = p.propertyIndex(); notifyIndex = p.notifySignalIndex(); - name = QLatin1String(p.name()); + name = QString::fromUtf8(p.name()); if (p.isConstant()) flags |= Data::IsConstant; @@ -76,7 +76,7 @@ void QmlPropertyCache::Data::load(const QMetaProperty &p) void QmlPropertyCache::Data::load(const QMetaMethod &m) { - name = QLatin1String(m.signature()); + name = QString::fromUtf8(m.signature()); int parenIdx = name.indexOf(QLatin1Char('(')); Q_ASSERT(parenIdx != -1); name = name.left(parenIdx); @@ -120,7 +120,7 @@ QmlPropertyCache::Data QmlPropertyCache::create(const QMetaObject *metaObject, int methodCount = metaObject->methodCount(); for (int ii = methodCount - 1; ii >= 0; --ii) { QMetaMethod m = metaObject->method(ii); - QString methodName = QLatin1String(m.signature()); + QString methodName = QString::fromUtf8(m.signature()); int parenIdx = methodName.indexOf(QLatin1Char('(')); Q_ASSERT(parenIdx != -1); @@ -151,7 +151,7 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject cache->indexCache.resize(propCount); for (int ii = propCount - 1; ii >= 0; --ii) { QMetaProperty p = metaObject->property(ii); - QString propName = QLatin1String(p.name()); + QString propName = QString::fromUtf8(p.name()); RData *data = new RData; data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName); @@ -172,7 +172,7 @@ QmlPropertyCache *QmlPropertyCache::create(QmlEngine *engine, const QMetaObject int methodCount = metaObject->methodCount(); for (int ii = methodCount - 1; ii >= 0; --ii) { QMetaMethod m = metaObject->method(ii); - QString methodName = QLatin1String(m.signature()); + QString methodName = QString::fromUtf8(m.signature()); int parenIdx = methodName.indexOf(QLatin1Char('(')); Q_ASSERT(parenIdx != -1); diff --git a/src/declarative/qml/qmlpropertycache_p.h b/src/declarative/qml/qmlpropertycache_p.h index f1b1219..91b0c53 100644 --- a/src/declarative/qml/qmlpropertycache_p.h +++ b/src/declarative/qml/qmlpropertycache_p.h @@ -132,7 +132,7 @@ QmlPropertyCache::Data::Data() { } -bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data::Data &other) +bool QmlPropertyCache::Data::operator==(const QmlPropertyCache::Data &other) { return flags == other.flags && propType == other.propType && diff --git a/src/declarative/qml/qmlpropertyvalueinterceptor.cpp b/src/declarative/qml/qmlpropertyvalueinterceptor.cpp new file mode 100644 index 0000000..86905e6 --- /dev/null +++ b/src/declarative/qml/qmlpropertyvalueinterceptor.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlpropertyvalueinterceptor.h" +#include "qml.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QmlPropertyValueInterceptor + \brief The QmlPropertyValueInterceptor class is inherited by property interceptors such as Behavior. + + This class intercepts property writes, allowing for custom handling. For example, Behavior uses this + interception to provide a default animation for all changes to a property's value. + */ + +/*! + Constructs a QmlPropertyValueInterceptor. +*/ +QmlPropertyValueInterceptor::QmlPropertyValueInterceptor() +{ +} + +QmlPropertyValueInterceptor::~QmlPropertyValueInterceptor() +{ +} + +/*! + \fn void QmlPropertyValueInterceptor::setTarget(const QmlMetaProperty &property) + Set the target \a property for the value interceptor. This method will + be called by the QML engine when assigning a value interceptor. +*/ + +/*! + \fn void QmlPropertyValueInterceptor::write(const QVariant &value) + This method will be called when a new \a value is assigned to the property being intercepted. +*/ + +QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlpropertyvalueinterceptor.h b/src/declarative/qml/qmlpropertyvalueinterceptor.h new file mode 100644 index 0000000..678c12c --- /dev/null +++ b/src/declarative/qml/qmlpropertyvalueinterceptor.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLPROPERTYVALUEINTERCEPTOR_H +#define QMLPROPERTYVALUEINTERCEPTOR_H + +#include <QtCore/qobject.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QmlMetaProperty; +class Q_DECLARATIVE_EXPORT QmlPropertyValueInterceptor +{ +public: + QmlPropertyValueInterceptor(); + virtual ~QmlPropertyValueInterceptor(); + virtual void setTarget(const QmlMetaProperty &property) = 0; + virtual void write(const QVariant &value) = 0; +}; +Q_DECLARE_INTERFACE(QmlPropertyValueInterceptor, "com.trolltech.qml.QmlPropertyValueInterceptor") + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QMLPROPERTYVALUEINTERCEPTOR_H diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index 1c7bf83..57e40b6 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -87,12 +87,12 @@ class ProcessAST: protected AST::Visitor const State &state = top(); if (state.property) { State s(state.property->getValue(), - state.property->getValue()->getProperty(name.toLatin1())); + state.property->getValue()->getProperty(name.toUtf8())); s.property->location = location; push(s); } else { State s(state.object, - state.object->getProperty(name.toLatin1())); + state.object->getProperty(name.toUtf8())); s.property->location = location; push(s); @@ -312,7 +312,7 @@ ProcessAST::defineObjectBinding_helper(AST::UiQualifiedId *propertyName, // XXX this doesn't do anything (_scope never builds up) _scope.append(resolvableObjectType); - obj->typeName = qualifiedNameId().toLatin1(); + obj->typeName = qualifiedNameId().toUtf8(); _scope.removeLast(); obj->location = location; diff --git a/src/declarative/qml/qmlvaluetype.cpp b/src/declarative/qml/qmlvaluetype.cpp index 4ae2070..84c9ecb 100644 --- a/src/declarative/qml/qmlvaluetype.cpp +++ b/src/declarative/qml/qmlvaluetype.cpp @@ -97,9 +97,10 @@ void QmlPointFValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlPointFValueType::write(QObject *obj, int idx) +void QmlPointFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &point, 0 }; + int status = -1; + void *a[] = { &point, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -144,9 +145,10 @@ void QmlPointValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlPointValueType::write(QObject *obj, int idx) +void QmlPointValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &point, 0 }; + int status = -1; + void *a[] = { &point, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -191,9 +193,10 @@ void QmlSizeFValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlSizeFValueType::write(QObject *obj, int idx) +void QmlSizeFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &size, 0 }; + int status = -1; + void *a[] = { &size, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -238,9 +241,10 @@ void QmlSizeValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlSizeValueType::write(QObject *obj, int idx) +void QmlSizeValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &size, 0 }; + int status = -1; + void *a[] = { &size, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -285,9 +289,10 @@ void QmlRectFValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlRectFValueType::write(QObject *obj, int idx) +void QmlRectFValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &rect, 0 }; + int status = -1; + void *a[] = { &rect, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -352,9 +357,10 @@ void QmlRectValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlRectValueType::write(QObject *obj, int idx) +void QmlRectValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &rect, 0 }; + int status = -1; + void *a[] = { &rect, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -419,9 +425,10 @@ void QmlVector3DValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlVector3DValueType::write(QObject *obj, int idx) +void QmlVector3DValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &vector, 0 }; + int status = -1; + void *a[] = { &vector, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } @@ -476,9 +483,10 @@ void QmlFontValueType::read(QObject *obj, int idx) QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); } -void QmlFontValueType::write(QObject *obj, int idx) +void QmlFontValueType::write(QObject *obj, int idx, QmlMetaProperty::WriteFlags flags) { - void *a[] = { &font, 0 }; + int status = -1; + void *a[] = { &font, 0, &status, &flags }; QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); } diff --git a/src/declarative/qml/qmlvaluetype_p.h b/src/declarative/qml/qmlvaluetype_p.h index da5e972..d3adf1e 100644 --- a/src/declarative/qml/qmlvaluetype_p.h +++ b/src/declarative/qml/qmlvaluetype_p.h @@ -58,6 +58,7 @@ #include <QtCore/qvariant.h> #include <QtGui/qvector3d.h> #include <QtGui/qfont.h> +#include <QmlMetaProperty> QT_BEGIN_NAMESPACE @@ -67,7 +68,7 @@ class QmlValueType : public QObject public: QmlValueType(QObject *parent = 0); virtual void read(QObject *, int) = 0; - virtual void write(QObject *, int) = 0; + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags flags) = 0; virtual QVariant value() = 0; virtual void setValue(QVariant) = 0; }; @@ -92,7 +93,7 @@ public: QmlPointFValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -114,7 +115,7 @@ public: QmlPointValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -136,7 +137,7 @@ public: QmlSizeFValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -158,7 +159,7 @@ public: QmlSizeValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -182,7 +183,7 @@ public: QmlRectFValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -211,7 +212,7 @@ public: QmlRectValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -239,7 +240,7 @@ public: QmlVector3DValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); @@ -267,7 +268,7 @@ public: QmlFontValueType(QObject *parent = 0); virtual void read(QObject *, int); - virtual void write(QObject *, int); + virtual void write(QObject *, int, QmlMetaProperty::WriteFlags); virtual QVariant value(); virtual void setValue(QVariant value); diff --git a/src/declarative/qml/qmlvaluetypescriptclass.cpp b/src/declarative/qml/qmlvaluetypescriptclass.cpp index 6fd674a..6a7bdeb 100644 --- a/src/declarative/qml/qmlvaluetypescriptclass.cpp +++ b/src/declarative/qml/qmlvaluetypescriptclass.cpp @@ -132,7 +132,7 @@ void QmlValueTypeScriptClass::setProperty(QScriptValue &object, 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); + ref.type->write(ref.object, ref.property, 0); } QVariant QmlValueTypeScriptClass::toVariant(const QScriptValue &val) diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp index e4eef64..675f5ae 100644 --- a/src/declarative/qml/qmlvme.cpp +++ b/src/declarative/qml/qmlvme.cpp @@ -155,6 +155,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlEnginePrivate *ep = QmlEnginePrivate::get(ctxt->engine()); QmlContextPrivate *cp = (QmlContextPrivate *)QObjectPrivate::get(ctxt); + int status = -1; //for dbus + QmlMetaProperty::WriteFlags flags = QmlMetaProperty::BypassInterceptor; + for (int ii = start; !isError() && ii < (start + count); ++ii) { QmlInstruction &instr = comp->bytecode[ii]; @@ -275,10 +278,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreVariant: { QObject *target = stack.top(); - void *a[1]; // XXX - can be more efficient QVariant v = QmlStringConverters::variantFromString(primitives.at(instr.storeString.value)); - a[0] = (void *)&v; + void *a[] = { &v, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeString.propertyIndex, a); } @@ -287,8 +289,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreString: { QObject *target = stack.top(); - void *a[1]; - a[0] = (void *)&primitives.at(instr.storeString.value); + void *a[] = { (void *)&primitives.at(instr.storeString.value), 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeString.propertyIndex, a); } @@ -297,9 +298,8 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreUrl: { QObject *target = stack.top(); - void *a[1]; QUrl u(primitives.at(instr.storeUrl.value)); - a[0] = (void *)&u; + void *a[] = { &u, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeUrl.propertyIndex, a); } @@ -309,8 +309,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, { QObject *target = stack.top(); float f = instr.storeFloat.value; - void *a[1]; - a[0] = &f; + void *a[] = { &f, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeFloat.propertyIndex, a); } @@ -320,8 +319,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, { QObject *target = stack.top(); double d = instr.storeDouble.value; - void *a[1]; - a[0] = &d; + void *a[] = { &d, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeDouble.propertyIndex, a); } @@ -330,8 +328,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreBool: { QObject *target = stack.top(); - void *a[1]; - a[0] = (void *)&instr.storeBool.value; + void *a[] = { (void *)&instr.storeBool.value, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeBool.propertyIndex, a); } @@ -340,8 +337,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreInteger: { QObject *target = stack.top(); - void *a[1]; - a[0] = (void *)&instr.storeInteger.value; + void *a[] = { (void *)&instr.storeInteger.value, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeInteger.propertyIndex, a); } @@ -350,9 +346,8 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreColor: { QObject *target = stack.top(); - void *a[1]; QColor c = QColor::fromRgba(instr.storeColor.value); - a[0] = (void *)&c; + void *a[] = { &c, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeColor.propertyIndex, a); } @@ -361,9 +356,8 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreDate: { QObject *target = stack.top(); - void *a[1]; QDate d = QDate::fromJulianDay(instr.storeDate.value); - a[0] = (void *)&d; + void *a[] = { &d, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeDate.propertyIndex, a); } @@ -372,13 +366,12 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreTime: { QObject *target = stack.top(); - void *a[1]; QTime t; t.setHMS(intData.at(instr.storeTime.valueIndex), intData.at(instr.storeTime.valueIndex+1), intData.at(instr.storeTime.valueIndex+2), intData.at(instr.storeTime.valueIndex+3)); - a[0] = (void *)&t; + void *a[] = { &t, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeTime.propertyIndex, a); } @@ -387,14 +380,13 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreDateTime: { QObject *target = stack.top(); - void *a[1]; QTime t; t.setHMS(intData.at(instr.storeDateTime.valueIndex+1), intData.at(instr.storeDateTime.valueIndex+2), intData.at(instr.storeDateTime.valueIndex+3), intData.at(instr.storeDateTime.valueIndex+4)); QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t); - a[0] = (void *)&dt; + void *a[] = { &dt, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeDateTime.propertyIndex, a); } @@ -403,10 +395,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StorePoint: { QObject *target = stack.top(); - void *a[1]; QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)).toPoint(); - a[0] = (void *)&p; + void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } @@ -415,10 +406,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StorePointF: { QObject *target = stack.top(); - void *a[1]; QPointF p(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)); - a[0] = (void *)&p; + void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } @@ -427,10 +417,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreSize: { QObject *target = stack.top(); - void *a[1]; QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)).toSize(); - a[0] = (void *)&p; + void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } @@ -439,10 +428,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreSizeF: { QObject *target = stack.top(); - void *a[1]; QSizeF s(floatData.at(instr.storeRealPair.valueIndex), floatData.at(instr.storeRealPair.valueIndex+1)); - a[0] = (void *)&s; + void *a[] = { &s, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRealPair.propertyIndex, a); } @@ -451,12 +439,11 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreRect: { QObject *target = stack.top(); - void *a[1]; QRect r = QRectF(floatData.at(instr.storeRect.valueIndex), floatData.at(instr.storeRect.valueIndex+1), floatData.at(instr.storeRect.valueIndex+2), floatData.at(instr.storeRect.valueIndex+3)).toRect(); - a[0] = (void *)&r; + void *a[] = { &r, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRect.propertyIndex, a); } @@ -465,12 +452,11 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreRectF: { QObject *target = stack.top(); - void *a[1]; QRectF r(floatData.at(instr.storeRect.valueIndex), floatData.at(instr.storeRect.valueIndex+1), floatData.at(instr.storeRect.valueIndex+2), floatData.at(instr.storeRect.valueIndex+3)); - a[0] = (void *)&r; + void *a[] = { &r, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeRect.propertyIndex, a); } @@ -479,11 +465,10 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreVector3D: { QObject *target = stack.top(); - void *a[1]; QVector3D p(floatData.at(instr.storeVector3D.valueIndex), floatData.at(instr.storeVector3D.valueIndex+1), floatData.at(instr.storeVector3D.valueIndex+2)); - a[0] = (void *)&p; + void *a[] = { &p, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeVector3D.propertyIndex, a); } @@ -494,9 +479,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QObject *assignObj = stack.pop(); QObject *target = stack.top(); - void *a[1]; - a[0] = (void *)&assignObj; - + void *a[] = { (void *)&assignObj, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeObject.propertyIndex, a); } @@ -506,7 +489,6 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::AssignCustomType: { QObject *target = stack.top(); - void *a[1]; QmlCompiledData::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex); const QString &primitive = primitives.at(data.index); QmlMetaType::StringConverter converter = @@ -518,7 +500,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type)) VME_EXCEPTION("Cannot assign value" << primitive << "to property" << prop.name()); - a[0] = (void *)v.data(); + void *a[] = { (void *)v.data(), 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.assignCustomType.propertyIndex, a); } @@ -533,7 +515,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, int sigIdx = instr.assignSignalObject.signal; const QByteArray &pr = datas.at(sigIdx); - QmlMetaProperty prop(target, QLatin1String(pr)); + QmlMetaProperty prop(target, QString::fromUtf8(pr)); if (prop.type() & QmlMetaProperty::SignalProperty) { QMetaMethod method = QmlMetaType::defaultMethod(assign); @@ -567,7 +549,9 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, case QmlInstruction::StoreScript: { QObject *target = stack.top(); - cp->addScript(primitives.at(instr.storeScript.value), target); + cp->addScript(primitives.at(instr.storeScript.value), target, + primitives.at(instr.storeScript.fileName), + instr.storeScript.lineNumber); } break; @@ -597,12 +581,11 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, if (stack.count() == 1 && bindingSkipList.testBit(coreIndex)) break; - QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, 0); + QmlBinding *bind = new QmlBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->url, instr.line, 0); bindValues.append(bind); bind->m_mePtr = &bindValues.values[bindValues.count - 1]; bind->setTarget(mp); bind->addToObject(target); - bind->setSourceLocation(comp->url, instr.line); } break; @@ -654,6 +637,20 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, } break; + case QmlInstruction::StoreValueInterceptor: + { + QObject *obj = stack.pop(); + QmlPropertyValueInterceptor *vi = reinterpret_cast<QmlPropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.assignValueInterceptor.castValue); + QObject *target = stack.at(stack.count() - 1 - instr.assignValueInterceptor.owner); + QmlMetaProperty prop; + prop.restore(instr.assignValueInterceptor.property, target, ctxt); + obj->setParent(target); + vi->setTarget(prop); + QmlVMEMetaObject *mo = static_cast<QmlVMEMetaObject *>((QMetaObject*)target->metaObject()); + mo->registerInterceptor(prop.coreIndex(), vi); + } + break; + case QmlInstruction::StoreObjectQmlList: { QObject *assign = stack.pop(); @@ -705,8 +702,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QObject *target = stack.top(); QVariant v = QVariant::fromValue(assign); - void *a[1]; - a[0] = (void *)&v; + void *a[] = { &v, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.storeObject.propertyIndex, a); } @@ -725,8 +721,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, if (iid) { void *ptr = assign->qt_metacast(iid); if (ptr) { - void *a[1]; - a[0] = &ptr; + void *a[] = { &ptr, 0, &status, &flags }; QMetaObject::metacall(target, QMetaObject::WriteProperty, coreIdx, a); @@ -848,7 +843,7 @@ QObject *QmlVME::run(QStack<QObject *> &stack, QmlContext *ctxt, QmlValueType *valueHandler = static_cast<QmlValueType *>(stack.pop()); QObject *target = stack.top(); - valueHandler->write(target, instr.fetchValue.property); + valueHandler->write(target, instr.fetchValue.property, QmlMetaProperty::BypassInterceptor); } break; diff --git a/src/declarative/qml/qmlvmemetaobject.cpp b/src/declarative/qml/qmlvmemetaobject.cpp index f473743..e5acc51 100644 --- a/src/declarative/qml/qmlvmemetaobject.cpp +++ b/src/declarative/qml/qmlvmemetaobject.cpp @@ -100,6 +100,24 @@ QmlVMEMetaObject::~QmlVMEMetaObject() int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) { int id = _id; + if(c == QMetaObject::WriteProperty) { + int flags = *reinterpret_cast<int*>(a[3]); + if (!(flags & QmlMetaProperty::BypassInterceptor) + && !aInterceptors.isEmpty() + && aInterceptors.testBit(id)) { + QmlPropertyValueInterceptor *vi = interceptors.value(id); + if (id >= propOffset) { + id -= propOffset; + if (id < metaData->propertyCount) { + vi->write(QVariant(data[id].type(), a[0])); + return -1; + } + } else { + vi->write(QVariant(property(id).type(), a[0])); + return -1; + } + } + } if(c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) { if (id >= propOffset) { id -= propOffset; @@ -181,20 +199,32 @@ int QmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a) (QmlContextPrivate *)QObjectPrivate::get(ctxt); QObject *target = ctxtPriv->idValues[d->contextIdx].data(); - if (!target) return -1; + if (!target) { + if (d->propertyIdx == -1) + *reinterpret_cast<QObject **>(a[0]) = target; + return -1; + } if (c == QMetaObject::ReadProperty && !aConnected.testBit(id)) { int sigIdx = methodOffset + id + metaData->propertyCount; QMetaObject::connect(ctxt, d->contextIdx + ctxtPriv->notifyIndex, object, sigIdx); - QMetaProperty prop = - target->metaObject()->property(d->propertyIdx); - if (prop.hasNotifySignal()) - QMetaObject::connect(target, prop.notifySignalIndex(), - object, sigIdx); + if (d->propertyIdx != -1) { + QMetaProperty prop = + target->metaObject()->property(d->propertyIdx); + if (prop.hasNotifySignal()) + QMetaObject::connect(target, prop.notifySignalIndex(), + object, sigIdx); + } aConnected.setBit(id); } - return QMetaObject::metacall(target, c, d->propertyIdx, a); + + if (d->propertyIdx == -1) { + *reinterpret_cast<QObject **>(a[0]) = target; + return -1; + } else { + return QMetaObject::metacall(target, c, d->propertyIdx, a); + } } return -1; @@ -253,4 +283,13 @@ void QmlVMEMetaObject::listChanged(int id) activate(object, methodOffset + id, 0); } +void QmlVMEMetaObject::registerInterceptor(int index, QmlPropertyValueInterceptor *interceptor) +{ + if (aInterceptors.isEmpty()) + aInterceptors.resize(propertyCount() + metaData->propertyCount); + aInterceptors.setBit(index); + interceptors.insert(index, interceptor); +} + + QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlvmemetaobject_p.h b/src/declarative/qml/qmlvmemetaobject_p.h index 1c26241..d376f4c 100644 --- a/src/declarative/qml/qmlvmemetaobject_p.h +++ b/src/declarative/qml/qmlvmemetaobject_p.h @@ -104,6 +104,8 @@ public: QmlRefCount * = 0); ~QmlVMEMetaObject(); + void registerInterceptor(int index, QmlPropertyValueInterceptor *interceptor); + protected: virtual int metaCall(QMetaObject::Call _c, int _id, void **_a); @@ -117,6 +119,8 @@ private: QVariant *data; QBitArray aConnected; + QBitArray aInterceptors; + QHash<int, QmlPropertyValueInterceptor*> interceptors; QAbstractDynamicMetaObject *parent; diff --git a/src/declarative/qml/qmlxmlhttprequest.cpp b/src/declarative/qml/qmlxmlhttprequest.cpp index 0bc927c..5117a00 100644 --- a/src/declarative/qml/qmlxmlhttprequest.cpp +++ b/src/declarative/qml/qmlxmlhttprequest.cpp @@ -1105,7 +1105,7 @@ void QmlXMLHttpRequest::downloadProgress(qint64 bytes) m_status = m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); m_statusText = - QLatin1String(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); + QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); // ### We assume if this is called the headers are now available if (m_state < HeadersReceived) { @@ -1127,7 +1127,7 @@ void QmlXMLHttpRequest::error(QNetworkReply::NetworkError error) m_status = m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); m_statusText = - QLatin1String(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); + QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); m_responseEntityBody = QByteArray(); m_errorFlag = true; @@ -1146,7 +1146,7 @@ void QmlXMLHttpRequest::finished() m_status = m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); m_statusText = - QLatin1String(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); + QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray()); if (m_state < HeadersReceived) { m_state = HeadersReceived; diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp index 3edbc5f..ed5018d 100644 --- a/src/declarative/util/qmlanimation.cpp +++ b/src/declarative/util/qmlanimation.cpp @@ -73,7 +73,7 @@ QEasingCurve stringToCurve(const QString &curve) QString easeName = curve.trimmed(); if (!easeName.endsWith(QLatin1Char(')'))) { qWarning("QEasingCurve: Unmatched perenthesis in easing function '%s'", - curve.toLatin1().constData()); + qPrintable(curve)); return easingCurve; } @@ -83,7 +83,7 @@ QEasingCurve stringToCurve(const QString &curve) normalizedCurve = easeName.left(idx); if (!normalizedCurve.startsWith(QLatin1String("ease"))) { qWarning("QEasingCurve: Easing function '%s' must start with 'ease'", - curve.toLatin1().constData()); + qPrintable(curve)); } props = prop_str.split(QLatin1Char(',')); @@ -95,10 +95,10 @@ QEasingCurve stringToCurve(const QString &curve) static int index = QEasingCurve::staticMetaObject.indexOfEnumerator("Type"); static QMetaEnum me = QEasingCurve::staticMetaObject.enumerator(index); - int value = me.keyToValue(normalizedCurve.toLatin1().constData()); + int value = me.keyToValue(normalizedCurve.toUtf8().constData()); if (value < 0) { qWarning("QEasingCurve: Unknown easing curve '%s'", - curve.toLatin1().constData()); + qPrintable(curve)); value = 0; } easingCurve.setType((QEasingCurve::Type)value); @@ -109,7 +109,7 @@ QEasingCurve stringToCurve(const QString &curve) if (sep == -1) { qWarning("QEasingCurve: Improperly specified property in easing function '%s'", - curve.toLatin1().constData()); + qPrintable(curve)); return easingCurve; } @@ -119,7 +119,7 @@ QEasingCurve stringToCurve(const QString &curve) if (propName.isEmpty() || !isOk) { qWarning("QEasingCurve: Improperly specified property in easing function '%s'", - curve.toLatin1().constData()); + qPrintable(curve)); return easingCurve; } @@ -972,7 +972,7 @@ void QmlPropertyAction::setValue(const QVariant &v) void QmlPropertyActionPrivate::doAction() { - property.write(value); + property.write(value, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } QAbstractAnimation *QmlPropertyAction::qtAnimation() @@ -1007,9 +1007,7 @@ void QmlPropertyAction::transition(QmlStateActions &actions, { for (int ii = 0; ii < actions.count(); ++ii) { const Action &action = actions.at(ii); - QmlBehavior::_ignore = true; - action.property.write(action.toValue); - QmlBehavior::_ignore = false; + action.property.write(action.toValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } } }; @@ -1020,9 +1018,11 @@ void QmlPropertyAction::transition(QmlStateActions &actions, 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; } QmlSetPropertyAnimationAction *data = new QmlSetPropertyAnimationAction; @@ -1070,6 +1070,8 @@ void QmlPropertyAction::transition(QmlStateActions &actions, } else { delete data; } + if (targetNeedsReset) + d->target = 0; } QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,PropertyAction,QmlPropertyAction) @@ -1714,10 +1716,10 @@ void QmlPropertyAnimationPrivate::valueChanged(qreal r) } if (r == 1.) { - property.write(to); + property.write(to, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } else { if (interpolator) - property.write(interpolator(from.constData(), to.constData(), r)); + property.write(interpolator(from.constData(), to.constData(), r), QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } } @@ -1773,9 +1775,8 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, for (int ii = 0; ii < actions.count(); ++ii) { Action &action = actions[ii]; - QmlBehavior::_ignore = true; if (v == 1.) - action.property.write(action.toValue); + action.property.write(action.toValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); else { if (action.fromValue.isNull()) { action.fromValue = action.property.read(); @@ -1790,9 +1791,8 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, } } if (interpolator) - action.property.write(interpolator(action.fromValue.constData(), action.toValue.constData(), v)); + action.property.write(interpolator(action.fromValue.constData(), action.toValue.constData(), v), QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } - QmlBehavior::_ignore = false; } } }; @@ -1805,9 +1805,11 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, bool useType = (props.isEmpty() && d->defaultToInterpolatorType) ? true : false; + bool targetNeedsReset = false; if (d->userProperty.isValid() && props.isEmpty() && !target()) { props.append(d->userProperty.value.name()); d->target = d->userProperty.value.object(); + targetNeedsReset = true; } PropertyUpdater *data = new PropertyUpdater; @@ -1874,6 +1876,8 @@ void QmlPropertyAnimation::transition(QmlStateActions &actions, } else { delete data; } + if (targetNeedsReset) + d->target = 0; } QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,PropertyAnimation,QmlPropertyAnimation) diff --git a/src/declarative/util/qmlconnection.cpp b/src/declarative/util/qmlconnection.cpp index c77d0f6..2a7cf6c 100644 --- a/src/declarative/util/qmlconnection.cpp +++ b/src/declarative/util/qmlconnection.cpp @@ -163,7 +163,7 @@ void QmlConnection::connectIfValid() if (lparen >= 0 && d->signal.length() > lparen+2) { QStringList l = d->signal.mid(lparen+1,d->signal.length()-lparen-2).split(QLatin1Char(',')); foreach (const QString &s, l) { - sigparams.append(s.toLatin1()); + sigparams.append(s.toUtf8()); } } QString signalname = d->signal.left(lparen); @@ -172,7 +172,7 @@ void QmlConnection::connectIfValid() int methods = mo->methodCount(); for (int ii = 0; ii < methods; ++ii) { QMetaMethod method = mo->method(ii); - QString methodName = QLatin1String(method.signature()); + QString methodName = QString::fromUtf8(method.signature()); int idx = methodName.indexOf(QLatin1Char('(')); methodName = methodName.left(idx); if (methodName == signalname && (lparen<0 || method.parameterNames() == sigparams)) { diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index 062ab48..4dc9bc5 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -233,7 +233,7 @@ struct ModelNode QHash<QString, ModelNode *>::iterator it; for (it = properties.begin(); it != properties.end(); ++it) { if (!(*it)->values.isEmpty()) - objectCache->setValue(it.key().toLatin1(), (*it)->values.first()); + objectCache->setValue(it.key().toUtf8(), (*it)->values.first()); } } return objectCache; @@ -252,7 +252,7 @@ struct ModelNode properties.insert(prop,n); } if (objectCache) - objectCache->setValue(prop.toLatin1(), val); + objectCache->setValue(prop.toUtf8(), val); } QmlListModel *modelCache; @@ -709,7 +709,7 @@ bool QmlListModelParser::compileProperty(const QmlCustomParserProperty &prop, QL qvariant_cast<QmlParser::Variant>(value); int ref = data.count(); - QByteArray d = variant.asScript().toLatin1(); + QByteArray d = variant.asScript().toUtf8(); d.append('\0'); data.append(d); @@ -799,7 +799,7 @@ void QmlListModelParser::setCustomData(QObject *obj, const QByteArray &d) { ModelNode *n = nodes.top(); ModelNode *n2 = new ModelNode; - n->properties.insert(QLatin1String(data + instr.dataIdx), n2); + n->properties.insert(QString::fromUtf8(data + instr.dataIdx), n2); nodes.push(n2); } break; diff --git a/src/declarative/util/qmlpropertychanges.cpp b/src/declarative/util/qmlpropertychanges.cpp index a5a08bc..b07a79f 100644 --- a/src/declarative/util/qmlpropertychanges.cpp +++ b/src/declarative/util/qmlpropertychanges.cpp @@ -230,17 +230,18 @@ void QmlPropertyChangesPrivate::decode() ds >> isScript; ds >> data; - if (isScript) { - QmlMetaProperty prop = property(name); //### can we avoid or reuse? + QmlMetaProperty prop = property(name); //### better way to check for signal property? + if (prop.type() == QmlMetaProperty::SignalProperty) { QmlExpression *expression = new QmlExpression(qmlContext(q), data.toString(), object); expression->setTrackChange(false); - if (prop.type() == QmlMetaProperty::SignalProperty) { - QmlReplaceSignalHandler *handler = new QmlReplaceSignalHandler; - handler->property = prop; - handler->expression = expression; - signalReplacements << handler; - } else - expressions << qMakePair(name, expression); + QmlReplaceSignalHandler *handler = new QmlReplaceSignalHandler; + handler->property = prop; + handler->expression = expression; + signalReplacements << handler; + } else if (isScript) { + QmlExpression *expression = new QmlExpression(qmlContext(q), data.toString(), object); + expression->setTrackChange(false); + expressions << qMakePair(name, expression); } else { properties << qMakePair(name, data); } diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp index 3c85db7..98facd9 100644 --- a/src/declarative/util/qmlstate.cpp +++ b/src/declarative/util/qmlstate.cpp @@ -350,6 +350,7 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever if (action.event) { if (!action.event->isReversable()) continue; + action.event->saveOriginals(); for (jj = 0; jj < d->revertList.count(); ++jj) { ActionEvent *event = d->revertList.at(jj).event; if (event && event->typeName() == action.event->typeName()) { @@ -359,9 +360,6 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever } } } - if (!found) - action.event->saveOriginals(); - //### do we ever need to do saveOriginals when found == true? } else { action.fromBinding = action.property.binding(); diff --git a/src/declarative/util/qmltransitionmanager.cpp b/src/declarative/util/qmltransitionmanager.cpp index 3e2e05f..7eaccac 100644 --- a/src/declarative/util/qmltransitionmanager.cpp +++ b/src/declarative/util/qmltransitionmanager.cpp @@ -144,9 +144,9 @@ void QmlTransitionManager::transition(const QList<Action> &list, for (int ii = 0; ii < applyList.size(); ++ii) { const Action &action = applyList.at(ii); if (action.toBinding) { - action.property.setBinding(action.toBinding); + action.property.setBinding(action.toBinding, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } else if (!action.event) { - action.property.write(action.toValue); + action.property.write(action.toValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } else if (action.event->isReversable()) { if (action.reverseEvent) action.event->reverse(); @@ -187,7 +187,7 @@ void QmlTransitionManager::transition(const QList<Action> &list, if (action.toBinding) action.property.setBinding(0); // Make sure this is disabled during the transition - action.property.write(action.fromValue); + action.property.write(action.fromValue, QmlMetaProperty::BypassInterceptor | QmlMetaProperty::DontRemoveBinding); } } @@ -223,7 +223,7 @@ void QmlTransitionManager::transition(const QList<Action> &list, } // Any actions remaining have not been handled by the transition and should - // be applied immediately. We skip applying transitions, as they are all + // be applied immediately. We skip applying bindings, as they are all // applied at the end in applyBindings() to avoid any nastiness mid // transition foreach(const Action &action, applyList) { @@ -232,13 +232,12 @@ void QmlTransitionManager::transition(const QList<Action> &list, action.event->reverse(); else action.event->execute(); - } else if (!action.event) { + } else if (!action.event && !action.toBinding) { action.property.write(action.toValue); } } if (!transition) d->applyBindings(); - } void QmlTransitionManager::cancel() |