diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-05-11 03:59:01 (GMT) |
---|---|---|
committer | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-05-11 03:59:01 (GMT) |
commit | 010dae33653c76359e857aadfbdfeb4841c01d2f (patch) | |
tree | 09cc7c453f723a0a0f8c0b43b996c80ffe244350 | |
parent | 554999e97a350b3c04123a6ef03d21a841ab73ad (diff) | |
parent | a6fd1205fd5c375d603b0c225f9e03fa57473f29 (diff) | |
download | Qt-010dae33653c76359e857aadfbdfeb4841c01d2f.zip Qt-010dae33653c76359e857aadfbdfeb4841c01d2f.tar.gz Qt-010dae33653c76359e857aadfbdfeb4841c01d2f.tar.bz2 |
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
-rw-r--r-- | src/corelib/kernel/qabstractitemmodel.cpp | 13 | ||||
-rw-r--r-- | src/declarative/fx/qfxanchors.cpp | 192 | ||||
-rw-r--r-- | src/declarative/fx/qfxanchors_p.h | 6 | ||||
-rw-r--r-- | src/declarative/fx/qfxtextedit.cpp | 2 | ||||
-rw-r--r-- | src/declarative/fx/qfxvisualitemmodel.cpp | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlbindablevalue.cpp | 185 | ||||
-rw-r--r-- | src/declarative/qml/qmlbindablevalue_p.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext_p.h | 2 | ||||
-rw-r--r-- | src/declarative/util/qmlopenmetaobject.cpp | 120 | ||||
-rw-r--r-- | src/declarative/util/qmlopenmetaobject.h | 17 | ||||
-rw-r--r-- | src/declarative/util/qmlstate.cpp | 17 | ||||
-rw-r--r-- | src/declarative/util/qmlstate_p.h | 1 | ||||
-rw-r--r-- | tests/auto/declarative/anchors/anchors.pro | 5 | ||||
-rw-r--r-- | tests/auto/declarative/anchors/data/loop1.qml | 6 | ||||
-rw-r--r-- | tests/auto/declarative/anchors/data/loop2.qml | 18 | ||||
-rw-r--r-- | tests/auto/declarative/anchors/tst_anchors.cpp | 52 | ||||
-rw-r--r-- | tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp | 39 |
17 files changed, 439 insertions, 238 deletions
diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index a23c137..00a3306 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -471,12 +471,12 @@ const QHash<int,QByteArray> &QAbstractItemModelPrivate::defaultRoleNames() { static QHash<int,QByteArray> roleNames; if (roleNames.isEmpty()) { - roleNames[Qt::DisplayRole] = "Display"; - roleNames[Qt::DecorationRole] = "Decoration"; - roleNames[Qt::EditRole] = "Edit"; - roleNames[Qt::ToolTipRole] = "ToolTip"; - roleNames[Qt::StatusTipRole] = "StatusTip"; - roleNames[Qt::WhatsThisRole] = "WhatsThis"; + roleNames[Qt::DisplayRole] = "display"; + roleNames[Qt::DecorationRole] = "decoration"; + roleNames[Qt::EditRole] = "edit"; + roleNames[Qt::ToolTipRole] = "toolTip"; + roleNames[Qt::StatusTipRole] = "statusTip"; + roleNames[Qt::WhatsThisRole] = "whatsThis"; } return roleNames; @@ -1859,6 +1859,7 @@ void QAbstractItemModel::setRoleNames(const QHash<int,QByteArray> &roleNames) const QHash<int,QByteArray> &QAbstractItemModel::roleNames() const { Q_D(const QAbstractItemModel); + qDebug() << "roles" << d->roleNames; return d->roleNames; } diff --git a/src/declarative/fx/qfxanchors.cpp b/src/declarative/fx/qfxanchors.cpp index 540e1cb..f570663 100644 --- a/src/declarative/fx/qfxanchors.cpp +++ b/src/declarative/fx/qfxanchors.cpp @@ -424,23 +424,31 @@ void QFxAnchors::updateTopAnchor() { Q_D(QFxAnchors); if (d->usedAnchors & HasTopAnchor) { - //Handle stretching - bool invalid = true; - int height = 0; - if (d->usedAnchors & HasBottomAnchor) { - invalid = d->calcStretch(d->top, d->bottom, d->topMargin, -d->bottomMargin, QFxAnchorLine::Top, height); - } else if (d->usedAnchors & HasVCenterAnchor) { - invalid = d->calcStretch(d->top, d->vCenter, d->topMargin, d->vCenterOffset, QFxAnchorLine::Top, height); - height *= 2; - } - if (!invalid) - d->item->setHeight(height); + if (!d->updatingVerticalAnchor) { + d->updatingVerticalAnchor = true; - //Handle top - if (d->top.item == d->item->itemParent()) { - d->item->setY(adjustedPosition(d->top.item, d->top.anchorLine) + d->topMargin); - } else if (d->top.item->itemParent() == d->item->itemParent()) { - d->item->setY(position(d->top.item, d->top.anchorLine) + d->topMargin); + //Handle stretching + bool invalid = true; + int height = 0; + if (d->usedAnchors & HasBottomAnchor) { + invalid = d->calcStretch(d->top, d->bottom, d->topMargin, -d->bottomMargin, QFxAnchorLine::Top, height); + } else if (d->usedAnchors & HasVCenterAnchor) { + invalid = d->calcStretch(d->top, d->vCenter, d->topMargin, d->vCenterOffset, QFxAnchorLine::Top, height); + height *= 2; + } + if (!invalid) + d->item->setHeight(height); + + //Handle top + if (d->top.item == d->item->itemParent()) { + d->item->setY(adjustedPosition(d->top.item, d->top.anchorLine) + d->topMargin); + } else if (d->top.item->itemParent() == d->item->itemParent()) { + d->item->setY(position(d->top.item, d->top.anchorLine) + d->topMargin); + } + + d->updatingVerticalAnchor = false; + } else { + qmlInfo(d->item) << "Anchor loop detected on vertical anchor."; } } } @@ -449,20 +457,28 @@ void QFxAnchors::updateBottomAnchor() { Q_D(QFxAnchors); if (d->usedAnchors & HasBottomAnchor) { - //Handle stretching (top + bottom case is handled in updateLeftAnchor) - if (d->usedAnchors & HasVCenterAnchor) { - int height = 0; - bool invalid = d->calcStretch(d->vCenter, d->bottom, d->vCenterOffset, -d->bottomMargin, - QFxAnchorLine::Top, height); - if (!invalid) - d->item->setHeight(height*2); - } - - //Handle bottom - if (d->bottom.item == d->item->itemParent()) { - d->item->setY(adjustedPosition(d->bottom.item, d->bottom.anchorLine) - d->item->height() - d->bottomMargin); - } else if (d->bottom.item->itemParent() == d->item->itemParent()) { - d->item->setY(position(d->bottom.item, d->bottom.anchorLine) - d->item->height() - d->bottomMargin); + if (!d->updatingVerticalAnchor) { + d->updatingVerticalAnchor = true; + + //Handle stretching (top + bottom case is handled in updateLeftAnchor) + if (d->usedAnchors & HasVCenterAnchor) { + int height = 0; + bool invalid = d->calcStretch(d->vCenter, d->bottom, d->vCenterOffset, -d->bottomMargin, + QFxAnchorLine::Top, height); + if (!invalid) + d->item->setHeight(height*2); + } + + //Handle bottom + if (d->bottom.item == d->item->itemParent()) { + d->item->setY(adjustedPosition(d->bottom.item, d->bottom.anchorLine) - d->item->height() - d->bottomMargin); + } else if (d->bottom.item->itemParent() == d->item->itemParent()) { + d->item->setY(position(d->bottom.item, d->bottom.anchorLine) - d->item->height() - d->bottomMargin); + } + + d->updatingVerticalAnchor = false; + } else { + qmlInfo(d->item) << "Anchor loop detected on vertical anchor."; } } } @@ -471,14 +487,22 @@ void QFxAnchors::updateVCenterAnchor() { Q_D(QFxAnchors); if (d->usedAnchors & HasVCenterAnchor) { - //(stetching handled in other update functions) + if (!d->updatingVerticalAnchor) { + d->updatingVerticalAnchor = true; - //Handle vCenter - if (d->vCenter.item == d->item->itemParent()) { - d->item->setY(adjustedPosition(d->vCenter.item, d->vCenter.anchorLine) - - d->item->height()/2 + d->vCenterOffset); - } else if (d->vCenter.item->itemParent() == d->item->itemParent()) { - d->item->setY(position(d->vCenter.item, d->vCenter.anchorLine) - d->item->height()/2 + d->vCenterOffset); + //(stetching handled in other update functions) + + //Handle vCenter + if (d->vCenter.item == d->item->itemParent()) { + d->item->setY(adjustedPosition(d->vCenter.item, d->vCenter.anchorLine) + - d->item->height()/2 + d->vCenterOffset); + } else if (d->vCenter.item->itemParent() == d->item->itemParent()) { + d->item->setY(position(d->vCenter.item, d->vCenter.anchorLine) - d->item->height()/2 + d->vCenterOffset); + } + + d->updatingVerticalAnchor = false; + } else { + qmlInfo(d->item) << "Anchor loop detected on vertical anchor."; } } } @@ -487,23 +511,31 @@ void QFxAnchors::updateLeftAnchor() { Q_D(QFxAnchors); if (d->usedAnchors & HasLeftAnchor) { - //Handle stretching - bool invalid = true; - int width = 0; - if (d->usedAnchors & HasRightAnchor) { - invalid = d->calcStretch(d->left, d->right, d->leftMargin, -d->rightMargin, QFxAnchorLine::Left, width); - } else if (d->usedAnchors & HasHCenterAnchor) { - invalid = d->calcStretch(d->left, d->hCenter, d->leftMargin, d->hCenterOffset, QFxAnchorLine::Left, width); - width *= 2; - } - if (!invalid) - d->item->setWidth(width); + if (!d->updatingHorizontalAnchor) { + d->updatingHorizontalAnchor = true; - //Handle left - if (d->left.item == d->item->itemParent()) { - d->item->setX(adjustedPosition(d->left.item, d->left.anchorLine) + d->leftMargin); - } else if (d->left.item->itemParent() == d->item->itemParent()) { - d->item->setX(position(d->left.item, d->left.anchorLine) + d->leftMargin); + //Handle stretching + bool invalid = true; + int width = 0; + if (d->usedAnchors & HasRightAnchor) { + invalid = d->calcStretch(d->left, d->right, d->leftMargin, -d->rightMargin, QFxAnchorLine::Left, width); + } else if (d->usedAnchors & HasHCenterAnchor) { + invalid = d->calcStretch(d->left, d->hCenter, d->leftMargin, d->hCenterOffset, QFxAnchorLine::Left, width); + width *= 2; + } + if (!invalid) + d->item->setWidth(width); + + //Handle left + if (d->left.item == d->item->itemParent()) { + d->item->setX(adjustedPosition(d->left.item, d->left.anchorLine) + d->leftMargin); + } else if (d->left.item->itemParent() == d->item->itemParent()) { + d->item->setX(position(d->left.item, d->left.anchorLine) + d->leftMargin); + } + + d->updatingHorizontalAnchor = false; + } else { + qmlInfo(d->item) << "Anchor loop detected on horizontal anchor."; } } } @@ -512,20 +544,28 @@ void QFxAnchors::updateRightAnchor() { Q_D(QFxAnchors); if (d->usedAnchors & HasRightAnchor) { - //Handle stretching (left + right case is handled in updateLeftAnchor) - if (d->usedAnchors & HasHCenterAnchor) { - int width = 0; - bool invalid = d->calcStretch(d->hCenter, d->right, d->hCenterOffset, -d->rightMargin, - QFxAnchorLine::Left, width); - if (!invalid) - d->item->setWidth(width*2); - } - - //Handle right - if (d->right.item == d->item->itemParent()) { - d->item->setX(adjustedPosition(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin); - } else if (d->right.item->itemParent() == d->item->itemParent()) { - d->item->setX(position(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin); + if (!d->updatingHorizontalAnchor) { + d->updatingHorizontalAnchor = true; + + //Handle stretching (left + right case is handled in updateLeftAnchor) + if (d->usedAnchors & HasHCenterAnchor) { + int width = 0; + bool invalid = d->calcStretch(d->hCenter, d->right, d->hCenterOffset, -d->rightMargin, + QFxAnchorLine::Left, width); + if (!invalid) + d->item->setWidth(width*2); + } + + //Handle right + if (d->right.item == d->item->itemParent()) { + d->item->setX(adjustedPosition(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin); + } else if (d->right.item->itemParent() == d->item->itemParent()) { + d->item->setX(position(d->right.item, d->right.anchorLine) - d->item->width() - d->rightMargin); + } + + d->updatingHorizontalAnchor = false; + } else { + qmlInfo(d->item) << "Anchor loop detected on horizontal anchor."; } } } @@ -534,11 +574,19 @@ void QFxAnchors::updateHCenterAnchor() { Q_D(QFxAnchors); if (d->usedAnchors & HasHCenterAnchor) { - //Handle hCenter - if (d->hCenter.item == d->item->itemParent()) { - d->item->setX(adjustedPosition(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset); - } else if (d->hCenter.item->itemParent() == d->item->itemParent()) { - d->item->setX(position(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset); + if (!d->updatingHorizontalAnchor) { + d->updatingHorizontalAnchor = true; + + //Handle hCenter + if (d->hCenter.item == d->item->itemParent()) { + d->item->setX(adjustedPosition(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset); + } else if (d->hCenter.item->itemParent() == d->item->itemParent()) { + d->item->setX(position(d->hCenter.item, d->hCenter.anchorLine) - d->item->width()/2 + d->hCenterOffset); + } + + d->updatingHorizontalAnchor = false; + } else { + qmlInfo(d->item) << "Anchor loop detected on horizontal anchor."; } } } diff --git a/src/declarative/fx/qfxanchors_p.h b/src/declarative/fx/qfxanchors_p.h index 3a5d1c7..76f83a8 100644 --- a/src/declarative/fx/qfxanchors_p.h +++ b/src/declarative/fx/qfxanchors_p.h @@ -64,7 +64,8 @@ class QFxAnchorsPrivate : public QObjectPrivate public: QFxAnchorsPrivate() : item(0), usedAnchors(0), fill(0), centeredIn(0), leftMargin(0), rightMargin(0), - topMargin(0), bottomMargin(0), vCenterOffset(0), hCenterOffset(0) + topMargin(0), bottomMargin(0), vCenterOffset(0), hCenterOffset(0), + updatingHorizontalAnchor(false), updatingVerticalAnchor(false) { } @@ -99,6 +100,9 @@ public: int bottomMargin; int vCenterOffset; int hCenterOffset; + + bool updatingHorizontalAnchor; + bool updatingVerticalAnchor; }; QT_END_NAMESPACE diff --git a/src/declarative/fx/qfxtextedit.cpp b/src/declarative/fx/qfxtextedit.cpp index 3bc9696..42f5743 100644 --- a/src/declarative/fx/qfxtextedit.cpp +++ b/src/declarative/fx/qfxtextedit.cpp @@ -821,7 +821,6 @@ void QFxTextEditPrivate::updateDefaultTextOption() QTextOption::WrapMode oldWrapMode = opt.wrapMode(); -qDebug() << "wrap mode is" << opt.wrapMode(); if (wrap) opt.setWrapMode(QTextOption::WordWrap); else @@ -829,7 +828,6 @@ qDebug() << "wrap mode is" << opt.wrapMode(); if (oldWrapMode == opt.wrapMode() && oldAlignment == opt.alignment()) return; -qDebug() << "wrap mode set to" << opt.wrapMode(); document->setDefaultTextOption(opt); } diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp index 9428281..61f08de 100644 --- a/src/declarative/fx/qfxvisualitemmodel.cpp +++ b/src/declarative/fx/qfxvisualitemmodel.cpp @@ -47,6 +47,7 @@ #include "qhash.h" #include "qlist.h" #include "private/qobject_p.h" +#include "private/qmetaobjectbuilder_p.h" #include "qmlopenmetaobject.h" #include "qmllistaccessor.h" #include "qfxvisualitemmodel.h" diff --git a/src/declarative/qml/qmlbindablevalue.cpp b/src/declarative/qml/qmlbindablevalue.cpp index 9f4886a..d5157b6 100644 --- a/src/declarative/qml/qmlbindablevalue.cpp +++ b/src/declarative/qml/qmlbindablevalue.cpp @@ -43,16 +43,17 @@ #include "qmlbindablevalue.h" #include "qmlbindablevalue_p.h" #include <qmlcontext.h> +#include <qmlinfo.h> #include <QVariant> #include <qfxperf.h> #include <QtCore/qdebug.h> - QT_BEGIN_NAMESPACE + DEFINE_BOOL_CONFIG_OPTION(scriptWarnings, QML_SCRIPT_WARNINGS); QmlBindableValuePrivate::QmlBindableValuePrivate() -: inited(false), mePtr(0) +: inited(false), updating(false), mePtr(0) { } @@ -121,102 +122,110 @@ void QmlBindableValue::update() if (!d->inited) return; - if (d->property.propertyCategory() == QmlMetaProperty::List) { - QVariant value = this->value(); - int listType = QmlMetaType::listType(d->property.propertyType()); - - if (value.userType() == qMetaTypeId<QList<QObject *> >()) { - const QList<QObject *> &list = - qvariant_cast<QList<QObject *> >(value); - QVariant listVar = d->property.read(); - QmlMetaType::clear(listVar); - for (int ii = 0; ii < list.count(); ++ii) { - QVariant v = QmlMetaType::fromObject(list.at(ii), listType); - QmlMetaType::append(listVar, v); - } + if (!d->updating) { + d->updating = true; + + if (d->property.propertyCategory() == QmlMetaProperty::List) { + QVariant value = this->value(); + int listType = QmlMetaType::listType(d->property.propertyType()); + + if (value.userType() == qMetaTypeId<QList<QObject *> >()) { + const QList<QObject *> &list = + qvariant_cast<QList<QObject *> >(value); + QVariant listVar = d->property.read(); + QmlMetaType::clear(listVar); + for (int ii = 0; ii < list.count(); ++ii) { + QVariant v = QmlMetaType::fromObject(list.at(ii), listType); + QmlMetaType::append(listVar, v); + } - } else if (value.type() == uint(listType) || - value.userType() == listType) { - QVariant listVar = d->property.read(); - QmlMetaType::clear(listVar); - QmlMetaType::append(listVar, value); - } - } else if (d->property.propertyCategory() == QmlMetaProperty::QmlList) { - // XXX - optimize! - QVariant value = this->value(); - QVariant list = d->property.read(); - QmlPrivate::ListInterface *li = - *(QmlPrivate::ListInterface **)list.constData(); - - int type = li->type(); - - if (QObject *obj = QmlMetaType::toQObject(value)) { - const QMetaObject *mo = - QmlMetaType::rawMetaObjectForType(type); - - const QMetaObject *objMo = obj->metaObject(); - bool found = false; - while(!found && objMo) { - if (objMo == mo) - found = true; - else - objMo = objMo->superClass(); + } else if (value.type() == uint(listType) || + value.userType() == listType) { + QVariant listVar = d->property.read(); + QmlMetaType::clear(listVar); + QmlMetaType::append(listVar, value); } + } else if (d->property.propertyCategory() == QmlMetaProperty::QmlList) { + // XXX - optimize! + QVariant value = this->value(); + QVariant list = d->property.read(); + QmlPrivate::ListInterface *li = + *(QmlPrivate::ListInterface **)list.constData(); + + int type = li->type(); + + if (QObject *obj = QmlMetaType::toQObject(value)) { + const QMetaObject *mo = + QmlMetaType::rawMetaObjectForType(type); + + const QMetaObject *objMo = obj->metaObject(); + bool found = false; + while(!found && objMo) { + if (objMo == mo) + found = true; + else + objMo = objMo->superClass(); + } - if (!found) { - qWarning() << "Unable to assign object to list"; - return; - } + if (!found) { + qWarning() << "Unable to assign object to list"; + return; + } - // NOTE: This assumes a cast to QObject does not alter - // the object pointer - void *d = (void *)&obj; - li->append(d); - } - } else if (d->property.propertyCategory() == QmlMetaProperty::Bindable) { - - // NOTE: We assume that only core properties can have - // propertyType == Bindable - int idx = d->property.coreIndex(); - Q_ASSERT(idx != -1); - - void *a[1]; - QmlBindableValue *t = this; - a[0] = (void *)&t; - d->property.object()->qt_metacall(QMetaObject::WriteProperty, - idx, a); - - } else if (d->property.propertyCategory() == QmlMetaProperty::Object) { - - QVariant value = this->value(); - if ((int)value.type() != qMetaTypeId<QObject *>()) { - if (scriptWarnings()) { - if (!value.isValid()) { - qWarning() << "QmlBindableValue: Unable to assign invalid value to object property"; - } else { - qWarning() << "QmlBindableValue: Unable to assign non-object to object property"; + // NOTE: This assumes a cast to QObject does not alter + // the object pointer + void *d = (void *)&obj; + li->append(d); + } + } else if (d->property.propertyCategory() == QmlMetaProperty::Bindable) { + + // NOTE: We assume that only core properties can have + // propertyType == Bindable + int idx = d->property.coreIndex(); + Q_ASSERT(idx != -1); + + void *a[1]; + QmlBindableValue *t = this; + a[0] = (void *)&t; + d->property.object()->qt_metacall(QMetaObject::WriteProperty, + idx, a); + + } else if (d->property.propertyCategory() == QmlMetaProperty::Object) { + + QVariant value = this->value(); + if ((int)value.type() != qMetaTypeId<QObject *>()) { + if (scriptWarnings()) { + if (!value.isValid()) { + qWarning() << "QmlBindableValue: Unable to assign invalid value to object property"; + } else { + qWarning() << "QmlBindableValue: Unable to assign non-object to object property"; + } } + return; } - return; - } - // NOTE: This assumes a cast to QObject does not alter the - // object pointer - QObject *obj = *(QObject **)value.data(); + // NOTE: This assumes a cast to QObject does not alter the + // object pointer + QObject *obj = *(QObject **)value.data(); + + // NOTE: We assume that only core properties can have + // propertyType == Object + int idx = d->property.coreIndex(); + Q_ASSERT(idx != -1); - // NOTE: We assume that only core properties can have - // propertyType == Object - int idx = d->property.coreIndex(); - Q_ASSERT(idx != -1); + void *a[1]; + a[0] = (void *)&obj; + d->property.object()->qt_metacall(QMetaObject::WriteProperty, + idx, a); - void *a[1]; - a[0] = (void *)&obj; - d->property.object()->qt_metacall(QMetaObject::WriteProperty, - idx, a); + } else if (d->property.propertyCategory() == QmlMetaProperty::Normal) { + QVariant value = this->value(); + d->property.write(value); + } - } else if (d->property.propertyCategory() == QmlMetaProperty::Normal) { - QVariant value = this->value(); - d->property.write(value); + d->updating = false; + } else { + qmlInfo(d->property.object()) << "Binding loop detected for property" << d->property.name(); } } diff --git a/src/declarative/qml/qmlbindablevalue_p.h b/src/declarative/qml/qmlbindablevalue_p.h index 70c001b..d9af0ef 100644 --- a/src/declarative/qml/qmlbindablevalue_p.h +++ b/src/declarative/qml/qmlbindablevalue_p.h @@ -55,6 +55,7 @@ public: QmlBindableValuePrivate(); bool inited; + bool updating; QmlMetaProperty property; QmlBindableValue **mePtr; diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index c265474..f527bb8 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -51,7 +51,9 @@ QT_BEGIN_NAMESPACE class QmlContext; +class QmlExpression; class QmlEngine; +class QmlExpression; class QmlCompiledComponent; class QmlContextPrivate : public QObjectPrivate diff --git a/src/declarative/util/qmlopenmetaobject.cpp b/src/declarative/util/qmlopenmetaobject.cpp index fc20fa9..d0dd817 100644 --- a/src/declarative/util/qmlopenmetaobject.cpp +++ b/src/declarative/util/qmlopenmetaobject.cpp @@ -40,102 +40,124 @@ ****************************************************************************/ #include "qmlopenmetaobject.h" +#include "private/qmetaobjectbuilder_p.h" #include <QDebug> QT_BEGIN_NAMESPACE + +class QmlOpenMetaObjectPrivate +{ +public: + QmlOpenMetaObjectPrivate() : parent(0), mem(0) {} + + bool autoCreate; + QAbstractDynamicMetaObject *parent; + int propertyOffset; + int signalOffset; + QList<QVariant> data; + QHash<QByteArray, int> names; + QMetaObjectBuilder mob; + QMetaObject *mem; + QObject *object; +}; + QmlOpenMetaObject::QmlOpenMetaObject(QObject *obj, bool automatic) -: autoCreate(automatic), parent(0), mem(0), _object(obj) +: d(new QmlOpenMetaObjectPrivate) { - mob.setSuperClass(obj->metaObject()); - mob.setClassName(obj->metaObject()->className()); - mob.setFlags(QMetaObjectBuilder::DynamicMetaObject); + d->autoCreate = automatic; + d->object = obj; + + d->mob.setSuperClass(obj->metaObject()); + d->mob.setClassName(obj->metaObject()->className()); + d->mob.setFlags(QMetaObjectBuilder::DynamicMetaObject); QObjectPrivate *op = QObjectPrivate::get(obj); if (op->metaObject) - mob.setSuperClass(op->metaObject); + d->mob.setSuperClass(op->metaObject); - mem = mob.toMetaObject(); - *static_cast<QMetaObject *>(this) = *mem; + d->mem = d->mob.toMetaObject(); + *static_cast<QMetaObject *>(this) = *d->mem; op->metaObject = this; - _propertyOffset = propertyOffset(); - _signalOffset = methodOffset(); + d->propertyOffset = propertyOffset(); + d->signalOffset = methodOffset(); } QmlOpenMetaObject::~QmlOpenMetaObject() { - if (parent) - delete parent; - qFree(mem); + if (d->parent) + delete d->parent; + qFree(d->mem); + delete d; } int QmlOpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a) { if (( c == QMetaObject::ReadProperty || c == QMetaObject::WriteProperty) - && id >= _propertyOffset) { - int propId = id - _propertyOffset; + && id >= d->propertyOffset) { + int propId = id - d->propertyOffset; if (c == QMetaObject::ReadProperty) { propertyRead(propId); - *reinterpret_cast<QVariant *>(a[0]) = data[propId]; + *reinterpret_cast<QVariant *>(a[0]) = d->data[propId]; } else if (c == QMetaObject::WriteProperty) { - if (data[propId] != *reinterpret_cast<QVariant *>(a[0])) { + if (d->data[propId] != *reinterpret_cast<QVariant *>(a[0])) { propertyWrite(propId); - data[propId] = *reinterpret_cast<QVariant *>(a[0]); - activate(_object, _signalOffset + propId, 0); + d->data[propId] = *reinterpret_cast<QVariant *>(a[0]); + activate(d->object, d->signalOffset + propId, 0); } } return -1; } else { - if (parent) - return parent->metaCall(c, id, a); + if (d->parent) + return d->parent->metaCall(c, id, a); else - return _object->qt_metacall(c, id, a); + return d->object->qt_metacall(c, id, a); } } QVariant QmlOpenMetaObject::value(int id) const { - Q_ASSERT(id >= 0 && id < data.count()); - return data.at(id); + Q_ASSERT(id >= 0 && id < d->data.count()); + return d->data.at(id); } void QmlOpenMetaObject::setValue(int id, const QVariant &value) { - Q_ASSERT(id >= 0 && id < data.count()); - data[id] = value; - activate(_object, id + _signalOffset, 0); + Q_ASSERT(id >= 0 && id < d->data.count()); + d->data[id] = value; + activate(d->object, id + d->signalOffset, 0); } QVariant QmlOpenMetaObject::value(const QByteArray &name) const { - QHash<QByteArray, int>::ConstIterator iter = names.find(name); - if (iter == names.end()) + QHash<QByteArray, int>::ConstIterator iter = d->names.find(name); + if (iter == d->names.end()) return QVariant(); - return data.at(*iter); + return d->data.at(*iter); } void QmlOpenMetaObject::setValue(const QByteArray &name, const QVariant &val) { - QHash<QByteArray, int>::ConstIterator iter = names.find(name); + QHash<QByteArray, int>::ConstIterator iter = d->names.find(name); int id = -1; - if (iter == names.end()) { - id = doCreateProperty(name.constData()) - _propertyOffset; + if (iter == d->names.end()) { + id = doCreateProperty(name.constData()) - d->propertyOffset; } else { id = *iter; } - if (data[id] == val) + if (d->data[id] == val) return; - data[id] = val; - activate(_object, id + _signalOffset, 0); + d->data[id] = val; + activate(d->object, id + d->signalOffset, 0); } int QmlOpenMetaObject::createProperty(const char *name, const char *) { - if (autoCreate) + if (d->autoCreate) return doCreateProperty(name); else return -1; @@ -143,17 +165,17 @@ int QmlOpenMetaObject::createProperty(const char *name, const char *) int QmlOpenMetaObject::doCreateProperty(const char *name) { - int id = mob.propertyCount(); - mob.addSignal("__" + QByteArray::number(id) + "()"); - QMetaPropertyBuilder build = mob.addProperty(name, "QVariant", id); + int id = d->mob.propertyCount(); + d->mob.addSignal("__" + QByteArray::number(id) + "()"); + QMetaPropertyBuilder build = d->mob.addProperty(name, "QVariant", id); build.setDynamic(true); - data << propertyCreated(id, build); - qFree(mem); - mem = mob.toMetaObject(); - *static_cast<QMetaObject *>(this) = *mem; - names.insert(name, id); + d->data << propertyCreated(id, build); + qFree(d->mem); + d->mem = d->mob.toMetaObject(); + *static_cast<QMetaObject *>(this) = *d->mem; + d->names.insert(name, id); - return _propertyOffset + id; + return d->propertyOffset + id; } void QmlOpenMetaObject::propertyRead(int) @@ -171,19 +193,19 @@ QVariant QmlOpenMetaObject::propertyCreated(int, QMetaPropertyBuilder &) int QmlOpenMetaObject::count() const { - return data.count(); + return d->data.count(); } QByteArray QmlOpenMetaObject::name(int idx) const { - Q_ASSERT(idx >= 0 && idx < data.count()); + Q_ASSERT(idx >= 0 && idx < d->data.count()); - return mob.property(idx).name(); + return d->mob.property(idx).name(); } QObject *QmlOpenMetaObject::object() const { - return _object; + return d->object; } QT_END_NAMESPACE diff --git a/src/declarative/util/qmlopenmetaobject.h b/src/declarative/util/qmlopenmetaobject.h index 17cecd87..f842f96 100644 --- a/src/declarative/util/qmlopenmetaobject.h +++ b/src/declarative/util/qmlopenmetaobject.h @@ -43,16 +43,16 @@ #define QMLOPENMETAOBJECT_H #include <QMetaObject> -#include "private/qmetaobjectbuilder_p.h" -#include <private/qobject_p.h> +#include <QtCore/private/qobject_p.h> #include <QObject> - QT_BEGIN_HEADER QT_BEGIN_NAMESPACE QT_MODULE(Declarative) +class QmlOpenMetaObjectPrivate; +class QMetaPropertyBuilder; class Q_DECLARATIVE_EXPORT QmlOpenMetaObject : public QAbstractDynamicMetaObject { public: @@ -78,15 +78,8 @@ protected: private: int doCreateProperty(const char *); - bool autoCreate; - QAbstractDynamicMetaObject *parent; - int _propertyOffset; - int _signalOffset; - QList<QVariant> data; - QHash<QByteArray, int> names; - QMetaObjectBuilder mob; - QMetaObject *mem; - QObject *_object; + + QmlOpenMetaObjectPrivate *d; }; diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp index cd33f5e..194cc1b 100644 --- a/src/declarative/util/qmlstate.cpp +++ b/src/declarative/util/qmlstate.cpp @@ -247,17 +247,20 @@ static void dump(const QmlStateOperation::ActionList &list) } #endif -void QmlStatePrivate::complete() +void QmlStatePrivate::applyBindings() { - Q_Q(QmlState); - //apply bindings (now that all transitions are complete) - ////////////////////////////////////////////////////////// foreach(const Action &action, bindingsList) { if (action.bv && !action.toBinding.isEmpty()) { action.bv->setExpression(action.toBinding); } } - ////////////////////////////////////////////////////////// +} + +void QmlStatePrivate::complete() +{ + Q_Q(QmlState); + //apply bindings (now that all transitions are complete) + applyBindings(); for (int ii = 0; ii < reverting.count(); ++ii) { for (int jj = 0; jj < revertList.count(); ++jj) { @@ -369,7 +372,7 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever a.toValue = d->revertList.at(ii).value; a.toBinding = d->revertList.at(ii).binding; if (!a.toBinding.isEmpty()) { - a.fromBinding = d->revertList.at(ii).bv->expression(); //### relies on clearExpression not clearing string + a.fromBinding = d->revertList.at(ii).bv->expression(); a.bv = d->revertList.at(ii).bv; } applyList << a; @@ -456,6 +459,8 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever else action.property.write(action.toValue); } + if (!trans) + d->applyBindings(); //### merge into above foreach? } QML_DEFINE_TYPE(QmlStateOperation,StateOperation); diff --git a/src/declarative/util/qmlstate_p.h b/src/declarative/util/qmlstate_p.h index 20d1c1a..28e1781 100644 --- a/src/declarative/util/qmlstate_p.h +++ b/src/declarative/util/qmlstate_p.h @@ -69,6 +69,7 @@ public: QmlStateGroup *group; QmlStateOperation::ActionList generateActionList(QmlStateGroup *) const; + void applyBindings(); void complete(); }; diff --git a/tests/auto/declarative/anchors/anchors.pro b/tests/auto/declarative/anchors/anchors.pro new file mode 100644 index 0000000..7b22cfb --- /dev/null +++ b/tests/auto/declarative/anchors/anchors.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +contains(QT_CONFIG,declarative): QT += declarative +SOURCES += tst_anchors.cpp + +DEFINES += SRCDIR=\\\"$$PWD\\\" diff --git a/tests/auto/declarative/anchors/data/loop1.qml b/tests/auto/declarative/anchors/data/loop1.qml new file mode 100644 index 0000000..a4de1bf --- /dev/null +++ b/tests/auto/declarative/anchors/data/loop1.qml @@ -0,0 +1,6 @@ +Rect { + id: rect + width: 120; height: 200; color: "white" + Text { id: Text1; anchors.right: Text2.right; text: "Hello" } + Text { id: Text2; anchors.right: Text1.right; anchors.rightMargin: 10; text: "World" } +} diff --git a/tests/auto/declarative/anchors/data/loop2.qml b/tests/auto/declarative/anchors/data/loop2.qml new file mode 100644 index 0000000..4b2c74e --- /dev/null +++ b/tests/auto/declarative/anchors/data/loop2.qml @@ -0,0 +1,18 @@ +Rect { + id: container; + width: 600; + height: 600; + + Image { + id: Image1 + source: "http://labs.trolltech.com/blogs/wp-content/uploads/2009/03/3311388091_ac2a257feb.jpg" + anchors.right: Image2.left + } + + Image { + id: Image2 + source: "http://labs.trolltech.com/blogs/wp-content/uploads/2009/03/oslo_groupphoto.jpg" + anchors.left: Image1.right + anchors.leftMargin: 20 + } +} diff --git a/tests/auto/declarative/anchors/tst_anchors.cpp b/tests/auto/declarative/anchors/tst_anchors.cpp new file mode 100644 index 0000000..7d920af --- /dev/null +++ b/tests/auto/declarative/anchors/tst_anchors.cpp @@ -0,0 +1,52 @@ +#include <qtest.h> +#include <QtDeclarative/qmlengine.h> +#include <QtDeclarative/qmlcomponent.h> +#include <QtDeclarative/qfxview.h> +#include <QtDeclarative/qfximage.h> +#include <QtDeclarative/qfxtext.h> + +class tst_anchors : public QObject +{ + Q_OBJECT +public: + tst_anchors() {} + +private slots: + void loops(); +}; + +// mostly testing that we don't crash +void tst_anchors::loops() +{ + { + QFxView *view = new QFxView; + + view->setUrl(QUrl("file://" SRCDIR "/data/loop1.qml")); + + //### ignoreMessage doesn't seem to work + //QTest::ignoreMessage(QtWarningMsg, "QML QFxText (unknown location): Anchor loop detected on horizontal anchor."); + //QTest::ignoreMessage(QtWarningMsg, "QML QFxText (unknown location): Anchor loop detected on horizontal anchor."); + view->execute(); + qApp->processEvents(); + + delete view; + } + + { + QFxView *view = new QFxView; + + view->setUrl(QUrl("file://" SRCDIR "/data/loop2.qml")); + + //### ignoreMessage doesn't seem to work + //QTest::ignoreMessage(QtWarningMsg, "QML QFxImage (unknown location): Anchor loop detected on horizontal anchor."); + //QTest::ignoreMessage(QtWarningMsg, "QML QFxImage (unknown location): Anchor loop detected on horizontal anchor."); + view->execute(); + qApp->processEvents(); + + delete view; + } +} + +QTEST_MAIN(tst_anchors) + +#include "tst_anchors.moc" diff --git a/tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp b/tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp index 0875690..ca840f4 100644 --- a/tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp +++ b/tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp @@ -7,7 +7,7 @@ class MyQmlObject : public QObject Q_OBJECT Q_PROPERTY(bool trueProperty READ trueProperty) Q_PROPERTY(bool falseProperty READ falseProperty) - Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty) + Q_PROPERTY(QString stringProperty READ stringProperty WRITE setStringProperty NOTIFY stringChanged) public: MyQmlObject(): m_methodCalled(false), m_methodIntCalled(false) {} @@ -15,7 +15,13 @@ public: bool falseProperty() const { return false; } QString stringProperty() const { return m_string; } - void setStringProperty(const QString &s) { m_string = s; } + void setStringProperty(const QString &s) + { + if (s == m_string) + return; + m_string = s; + emit stringChanged(); + } bool methodCalled() const { return m_methodCalled; } bool methodIntCalled() const { return m_methodIntCalled; } @@ -24,6 +30,7 @@ public: signals: void basicSignal(); void argumentSignal(int a, QString b, qreal c); + void stringChanged(); public slots: void method() { m_methodCalled = true; } @@ -41,6 +48,22 @@ private: QML_DECLARE_TYPE(MyQmlObject); QML_DEFINE_TYPE(MyQmlObject,MyQmlObject); +class MyQmlContainer : public QObject +{ + Q_OBJECT + Q_PROPERTY(QList<MyQmlContainer*>* children READ children) +public: + MyQmlContainer() {} + + QList<MyQmlContainer*> *children() { return &m_children; } + +private: + QList<MyQmlContainer*> m_children; +}; + +QML_DECLARE_TYPE(MyQmlContainer); +QML_DEFINE_TYPE(MyQmlContainer,MyQmlContainer); + class tst_qmlbindengine : public QObject { Q_OBJECT @@ -51,6 +74,7 @@ private slots: void boolPropertiesEvaluateAsBool(); void methods(); void signalAssignment(); + void bindingLoop(); private: QmlEngine engine; @@ -117,6 +141,17 @@ void tst_qmlbindengine::methods() QCOMPARE(object->methodIntCalled(), true); } } +#include <QDebug> +void tst_qmlbindengine::bindingLoop() +{ + QmlComponent component(&engine, "MyQmlContainer { children : [ "\ + "MyQmlObject { id: Object1; stringProperty: \"hello\" + Object2.stringProperty }, "\ + "MyQmlObject { id: Object2; stringProperty: \"hello\" + Object1.stringProperty } ] }"); + //### ignoreMessage doesn't seem to work here + //QTest::ignoreMessage(QtWarningMsg, "QML MyQmlObject (unknown location): Binding loop detected for property \"stringProperty\""); + QObject *object = component.create(); + QVERIFY(object != 0); +} QTEST_MAIN(tst_qmlbindengine) |