summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-05-11 03:59:01 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-05-11 03:59:01 (GMT)
commit010dae33653c76359e857aadfbdfeb4841c01d2f (patch)
tree09cc7c453f723a0a0f8c0b43b996c80ffe244350
parent554999e97a350b3c04123a6ef03d21a841ab73ad (diff)
parenta6fd1205fd5c375d603b0c225f9e03fa57473f29 (diff)
downloadQt-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.cpp13
-rw-r--r--src/declarative/fx/qfxanchors.cpp192
-rw-r--r--src/declarative/fx/qfxanchors_p.h6
-rw-r--r--src/declarative/fx/qfxtextedit.cpp2
-rw-r--r--src/declarative/fx/qfxvisualitemmodel.cpp1
-rw-r--r--src/declarative/qml/qmlbindablevalue.cpp185
-rw-r--r--src/declarative/qml/qmlbindablevalue_p.h1
-rw-r--r--src/declarative/qml/qmlcontext_p.h2
-rw-r--r--src/declarative/util/qmlopenmetaobject.cpp120
-rw-r--r--src/declarative/util/qmlopenmetaobject.h17
-rw-r--r--src/declarative/util/qmlstate.cpp17
-rw-r--r--src/declarative/util/qmlstate_p.h1
-rw-r--r--tests/auto/declarative/anchors/anchors.pro5
-rw-r--r--tests/auto/declarative/anchors/data/loop1.qml6
-rw-r--r--tests/auto/declarative/anchors/data/loop2.qml18
-rw-r--r--tests/auto/declarative/anchors/tst_anchors.cpp52
-rw-r--r--tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp39
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)