summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWarwick Allison <warwick.allison@nokia.com>2009-05-11 05:57:50 (GMT)
committerWarwick Allison <warwick.allison@nokia.com>2009-05-11 05:57:50 (GMT)
commitb3526f5edf6425289ef2aa5c8adfc89892817ac0 (patch)
tree6291a50711e80dbe7037f52d71f538b1a5410741
parent7f22443b3cb6cd56a906dbb6edb0c2f7a1314887 (diff)
parent692931ae2fec4fa8fc4ebcbcff20c952d6319536 (diff)
downloadQt-b3526f5edf6425289ef2aa5c8adfc89892817ac0.zip
Qt-b3526f5edf6425289ef2aa5c8adfc89892817ac0.tar.gz
Qt-b3526f5edf6425289ef2aa5c8adfc89892817ac0.tar.bz2
Merge branch 'kinetic-declarativeui' of git@scm.dev.nokia.troll.no:qt/kinetic into kinetic-declarativeui
-rw-r--r--demos/declarative/flickr/flickr.qml2
-rw-r--r--demos/declarative/webbrowser/content/RectSoftShadow.qml2
-rw-r--r--demos/declarative/webbrowser/content/pics/footer.sci6
-rw-r--r--demos/declarative/webbrowser/webbrowser.qml4
-rw-r--r--src/corelib/kernel/qabstractitemmodel.cpp13
-rw-r--r--src/declarative/canvas/qsimplecanvasitem.cpp1
-rw-r--r--src/declarative/fx/qfxanchors.cpp438
-rw-r--r--src/declarative/fx/qfxanchors.h30
-rw-r--r--src/declarative/fx/qfxanchors_p.h10
-rw-r--r--src/declarative/fx/qfxtextedit.cpp2
-rw-r--r--src/declarative/fx/qfxvisualitemmodel.cpp1
-rw-r--r--src/declarative/qml/qmlbindablevalue.cpp188
-rw-r--r--src/declarative/qml/qmlbindablevalue_p.h3
-rw-r--r--src/declarative/qml/qmlcompiler.cpp28
-rw-r--r--src/declarative/qml/qmlcomponent.cpp40
-rw-r--r--src/declarative/qml/qmlcomponent_p.h7
-rw-r--r--src/declarative/qml/qmlcontext.cpp44
-rw-r--r--src/declarative/qml/qmlcontext.h1
-rw-r--r--src/declarative/qml/qmlcontext_p.h8
-rw-r--r--src/declarative/qml/qmldeclarativedata_p.h1
-rw-r--r--src/declarative/qml/qmlengine.cpp55
-rw-r--r--src/declarative/qml/qmlengine_p.h31
-rw-r--r--src/declarative/qml/qmlexpression.h1
-rw-r--r--src/declarative/qml/qmlinstruction_p.h2
-rw-r--r--src/declarative/qml/qmlparserstatus.cpp12
-rw-r--r--src/declarative/qml/qmlparserstatus.h7
-rw-r--r--src/declarative/qml/qmlvme.cpp35
-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.cpp67
36 files changed, 905 insertions, 370 deletions
diff --git a/demos/declarative/flickr/flickr.qml b/demos/declarative/flickr/flickr.qml
index 092aef6..fa3bc35 100644
--- a/demos/declarative/flickr/flickr.qml
+++ b/demos/declarative/flickr/flickr.qml
@@ -153,7 +153,7 @@ Item {
}
PathAttribute { name: "scale"; value: 1 }
- PathAttribute { name: "angle"; value: -45 }
+ PathAttribute { name: "angle"; value: 45 }
}
}
diff --git a/demos/declarative/webbrowser/content/RectSoftShadow.qml b/demos/declarative/webbrowser/content/RectSoftShadow.qml
index 5817f00..1734433 100644
--- a/demos/declarative/webbrowser/content/RectSoftShadow.qml
+++ b/demos/declarative/webbrowser/content/RectSoftShadow.qml
@@ -24,7 +24,7 @@ Item {
source: "pics/softshadow-bottom.png"
x: 0
y: parent.height
- width: webview.width*webview.scale
+ width: WebView.width*WebView.scale
height: 16
}
}
diff --git a/demos/declarative/webbrowser/content/pics/footer.sci b/demos/declarative/webbrowser/content/pics/footer.sci
new file mode 100644
index 0000000..be1d086
--- /dev/null
+++ b/demos/declarative/webbrowser/content/pics/footer.sci
@@ -0,0 +1,6 @@
+gridLeft: 5
+gridTop: 0
+gridBottom: 0
+gridRight: 5
+imageFile: footer.png
+
diff --git a/demos/declarative/webbrowser/webbrowser.qml b/demos/declarative/webbrowser/webbrowser.qml
index c754543..4b03b63 100644
--- a/demos/declarative/webbrowser/webbrowser.qml
+++ b/demos/declarative/webbrowser/webbrowser.qml
@@ -73,7 +73,7 @@ Item {
color: "white"
styleColor: "black"
- style: Raised
+ style: "Raised"
font.family: "Helvetica"
font.size: 10
@@ -85,7 +85,7 @@ Item {
anchors.rightMargin: 4
anchors.top: Header.top
anchors.topMargin: 4
- hAlign: AlignHCenter
+ hAlign: "AlignHCenter"
}
Item {
width: parent.width
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/canvas/qsimplecanvasitem.cpp b/src/declarative/canvas/qsimplecanvasitem.cpp
index c8c949a..12c725c 100644
--- a/src/declarative/canvas/qsimplecanvasitem.cpp
+++ b/src/declarative/canvas/qsimplecanvasitem.cpp
@@ -1343,6 +1343,7 @@ QSimpleCanvasItem::~QSimpleCanvasItem()
parent()->remChild(this);
delete d->graphicsItem;
} else {
+ update();
setOptions(MouseFilter, false);
if (d->canvas){
diff --git a/src/declarative/fx/qfxanchors.cpp b/src/declarative/fx/qfxanchors.cpp
index 540e1cb..53d0187 100644
--- a/src/declarative/fx/qfxanchors.cpp
+++ b/src/declarative/fx/qfxanchors.cpp
@@ -43,9 +43,10 @@
#include "qfxitem.h"
#include <QDebug>
#include <QtDeclarative/qmlinfo.h>
-
+#include <QtDeclarative/qmlbindablevalue.h>
QT_BEGIN_NAMESPACE
+
QML_DEFINE_TYPE(QFxAnchors,Anchors);
//TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)?
@@ -227,7 +228,7 @@ void QFxAnchors::setCenteredIn(QFxItem* c)
setVerticalCenter(c->verticalCenter());
}
-void QFxAnchorsPrivate::connectVHelper(const QFxAnchorLine &edge, const char *slotString)
+void QFxAnchorsPrivate::connectVHelper(const QFxAnchorLine &edge)
{
//### should we do disconnects first? (will it be called more than once?)
Q_Q(QFxAnchors);
@@ -235,7 +236,7 @@ void QFxAnchorsPrivate::connectVHelper(const QFxAnchorLine &edge, const char *sl
switch(edge.anchorLine) {
case QFxAnchorLine::Bottom:
case QFxAnchorLine::VCenter:
- QObject::connect(edge.item, SIGNAL(heightChanged()), q, slotString);
+ QObject::connect(edge.item, SIGNAL(heightChanged()), q, SLOT(updateVerticalAnchors()));
break;
case QFxAnchorLine::Top: //no connection needed
default:
@@ -244,13 +245,13 @@ void QFxAnchorsPrivate::connectVHelper(const QFxAnchorLine &edge, const char *sl
} else if (edge.item->itemParent() == item->itemParent()) { //siblings
switch(edge.anchorLine) {
case QFxAnchorLine::Top:
- QObject::connect(edge.item, SIGNAL(topChanged()), q, slotString);
+ QObject::connect(edge.item, SIGNAL(topChanged()), q, SLOT(updateVerticalAnchors()));
break;
case QFxAnchorLine::Bottom:
- QObject::connect(edge.item, SIGNAL(bottomChanged()), q, slotString);
+ QObject::connect(edge.item, SIGNAL(bottomChanged()), q, SLOT(updateVerticalAnchors()));
break;
case QFxAnchorLine::VCenter:
- QObject::connect(edge.item, SIGNAL(vcenterChanged()), q, slotString);
+ QObject::connect(edge.item, SIGNAL(vcenterChanged()), q, SLOT(updateVerticalAnchors()));
break;
default:
break;
@@ -267,49 +268,44 @@ void QFxAnchors::connectVAnchors()
return;
if (d->usedAnchors & HasTopAnchor) {
- const char *slotStr = SLOT(updateTopAnchor());
-
//Handle stretching connections (if we have multiple horizontal anchors)
QFxAnchorLine *edge = 0;
if (d->usedAnchors & HasBottomAnchor) {
edge = &d->bottom;
- connect(this, SIGNAL(bottomMarginChanged()), this, slotStr);
+ connect(this, SIGNAL(bottomMarginChanged()), this, SLOT(updateVerticalAnchors()));
} else if (d->usedAnchors & HasVCenterAnchor) {
edge = &d->vCenter;
- connect(this, SIGNAL(verticalCenterOffsetChanged()), this, slotStr);
+ connect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors()));
}
if (edge) {
//we need to stretch
- d->connectVHelper(*edge, slotStr);
+ d->connectVHelper(*edge);
}
//Handle top
- d->connectVHelper(d->top, slotStr);
- connect(this, SIGNAL(topMarginChanged()), this, slotStr);
- updateTopAnchor();
+ d->connectVHelper(d->top);
+ connect(this, SIGNAL(topMarginChanged()), this, SLOT(updateVerticalAnchors()));
+ updateVerticalAnchors();
} else if (d->usedAnchors & HasBottomAnchor) {
- const char *slotStr = SLOT(updateBottomAnchor());
-
//Handle stretching connections (if we have multiple horizontal anchors)
if (d->usedAnchors & HasVCenterAnchor) {
- d->connectVHelper(d->vCenter, slotStr);
- connect(this, SIGNAL(verticalCenterOffsetChanged()), this, slotStr);
+ d->connectVHelper(d->vCenter);
+ connect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors()));
}
//Handle bottom
- d->connectVHelper(d->bottom, slotStr);
- connect(this, SIGNAL(bottomMarginChanged()), this, slotStr);
- updateBottomAnchor();
+ d->connectVHelper(d->bottom);
+ connect(this, SIGNAL(bottomMarginChanged()), this, SLOT(updateVerticalAnchors()));
+ updateVerticalAnchors();
} else if (d->usedAnchors & HasVCenterAnchor) {
//Handle vCenter
- const char *slotStr = SLOT(updateVCenterAnchor());
- d->connectVHelper(d->vCenter, slotStr);
- connect(this, SIGNAL(verticalCenterOffsetChanged()), this, slotStr);
- updateVCenterAnchor();
+ d->connectVHelper(d->vCenter);
+ connect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors()));
+ updateVerticalAnchors();
}
}
-void QFxAnchorsPrivate::connectHHelper(const QFxAnchorLine &edge, const char *slotString)
+void QFxAnchorsPrivate::connectHHelper(const QFxAnchorLine &edge)
{
//### should we do disconnects first? (will it be called more than once?)
Q_Q(QFxAnchors);
@@ -317,7 +313,7 @@ void QFxAnchorsPrivate::connectHHelper(const QFxAnchorLine &edge, const char *sl
switch(edge.anchorLine) {
case QFxAnchorLine::Right:
case QFxAnchorLine::HCenter:
- QObject::connect(edge.item, SIGNAL(widthChanged()), q, slotString);
+ QObject::connect(edge.item, SIGNAL(widthChanged()), q, SLOT(updateHorizontalAnchors()));
break;
case QFxAnchorLine::Left: //no connection needed
default:
@@ -326,13 +322,13 @@ void QFxAnchorsPrivate::connectHHelper(const QFxAnchorLine &edge, const char *sl
} else if (edge.item->itemParent() == item->itemParent()) { //siblings
switch(edge.anchorLine) {
case QFxAnchorLine::Left:
- QObject::connect(edge.item, SIGNAL(leftChanged()), q, slotString);
+ QObject::connect(edge.item, SIGNAL(leftChanged()), q, SLOT(updateHorizontalAnchors()));
break;
case QFxAnchorLine::Right:
- QObject::connect(edge.item, SIGNAL(rightChanged()), q, slotString);
+ QObject::connect(edge.item, SIGNAL(rightChanged()), q, SLOT(updateHorizontalAnchors()));
break;
case QFxAnchorLine::HCenter:
- QObject::connect(edge.item, SIGNAL(hcenterChanged()), q, slotString);
+ QObject::connect(edge.item, SIGNAL(hcenterChanged()), q, SLOT(updateHorizontalAnchors()));
break;
default:
break;
@@ -349,45 +345,40 @@ void QFxAnchors::connectHAnchors()
return;
if (d->usedAnchors & HasLeftAnchor) {
- const char *slotStr = SLOT(updateLeftAnchor());
-
//Handle stretching connections (if we have multiple horizontal anchors)
QFxAnchorLine *edge = 0;
if (d->usedAnchors & HasRightAnchor) {
edge = &d->right;
- connect(this, SIGNAL(rightMarginChanged()), this, slotStr);
+ connect(this, SIGNAL(rightMarginChanged()), this, SLOT(updateHorizontalAnchors()));
} else if (d->usedAnchors & HasHCenterAnchor) {
edge = &d->hCenter;
- connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, slotStr);
+ connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors()));
}
if (edge) {
//we need to stretch
- d->connectHHelper(*edge, slotStr);
+ d->connectHHelper(*edge);
}
//Handle left
- d->connectHHelper(d->left, slotStr);
- connect(this, SIGNAL(leftMarginChanged()), this, slotStr);
- updateLeftAnchor();
+ d->connectHHelper(d->left);
+ connect(this, SIGNAL(leftMarginChanged()), this, SLOT(updateHorizontalAnchors()));
+ updateHorizontalAnchors();
} else if (d->usedAnchors & HasRightAnchor) {
- const char *slotStr = SLOT(updateRightAnchor());
-
//Handle stretching connections (if we have multiple horizontal anchors)
if (d->usedAnchors & HasHCenterAnchor) {
- d->connectHHelper(d->hCenter, slotStr);
- connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, slotStr);
+ d->connectHHelper(d->hCenter);
+ connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors()));
}
//Handle right
- d->connectHHelper(d->right, slotStr);
- connect(this, SIGNAL(rightMarginChanged()), this, slotStr);
- updateRightAnchor();
+ d->connectHHelper(d->right);
+ connect(this, SIGNAL(rightMarginChanged()), this, SLOT(updateHorizontalAnchors()));
+ updateHorizontalAnchors();
} else if (d->usedAnchors & HasHCenterAnchor) {
//Handle hCenter
- const char *slotStr = SLOT(updateHCenterAnchor());
- d->connectHHelper(d->hCenter, slotStr);
- connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, slotStr);
- updateHCenterAnchor();
+ d->connectHHelper(d->hCenter);
+ connect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors()));
+ updateHorizontalAnchors();
}
}
@@ -420,126 +411,168 @@ bool QFxAnchorsPrivate::calcStretch(const QFxAnchorLine &edge1,
return invalid;
}
-void QFxAnchors::updateTopAnchor()
+void QFxAnchors::updateVerticalAnchors()
{
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);
-
- //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);
- }
- }
-}
-
-void QFxAnchors::updateBottomAnchor()
-{
- Q_D(QFxAnchors);
- if (d->usedAnchors & HasBottomAnchor) {
- //Handle stretching (top + bottom case is handled in updateLeftAnchor)
- if (d->usedAnchors & HasVCenterAnchor) {
+ if (!d->updatingVerticalAnchor) {
+ d->updatingVerticalAnchor = true;
+ if (d->usedAnchors & HasTopAnchor) {
+ //Handle stretching
+ bool invalid = true;
int height = 0;
- bool invalid = d->calcStretch(d->vCenter, d->bottom, d->vCenterOffset, -d->bottomMargin,
- QFxAnchorLine::Top, height);
+ 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*2);
- }
+ 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);
+ }
+ } else if (d->usedAnchors & HasBottomAnchor) {
+ //Handle stretching (top + bottom case is handled above)
+ 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);
+ }
- //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);
+
+ } else if (d->usedAnchors & HasVCenterAnchor) {
+ //(stetching handled above)
+
+ //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.";
}
}
-void QFxAnchors::updateVCenterAnchor()
+void QFxAnchors::updateHorizontalAnchors()
{
Q_D(QFxAnchors);
- if (d->usedAnchors & HasVCenterAnchor) {
- //(stetching handled in other update functions)
+ if (!d->updatingHorizontalAnchor) {
+ d->updatingHorizontalAnchor = 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);
+ //alternate implementation (needs performance testing)
+ /*switch(d->usedAnchors & QFxAnchors::Horizontal_Mask) {
+ case 0x03: //(HasLeftAnchor | HasRightAnchor)
+ {
+ int width = 0;
+ if (!d->calcStretch(d->left, d->right, d->leftMargin, -d->rightMargin, QFxAnchorLine::Left, width))
+ d->item->setWidth(width);
+ //fall though
}
- }
-}
-
-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;
+ case 0x11: //(HasLeftAnchor | HasHCenterAnchor)
+ {
+ if (d->usedAnchors & HasHCenterAnchor) {
+ int width = 0;
+ if (!d->calcStretch(d->left, d->hCenter, d->leftMargin, d->hCenterOffset, QFxAnchorLine::Left, width))
+ d->item->setWidth(width*2);
+ }
+ //fall though
}
- 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);
+ case HasLeftAnchor:
+ 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);
+ }
+ break;
+ case 0x12: //(HasRightAnchor | HasHCenterAnchor)
+ {
+ int width = 0;
+ if (!d->calcStretch(d->hCenter, d->right, d->hCenterOffset, -d->rightMargin, QFxAnchorLine::Left, width))
+ d->item->setWidth(width*2);
+ //fall though
}
- }
-}
+ case HasRightAnchor:
+ 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);
+ }
+ break;
+ case HasHCenterAnchor:
+ 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);
+ }
+ break;
+ default:
+ break;
+ }*/
-void QFxAnchors::updateRightAnchor()
-{
- Q_D(QFxAnchors);
- if (d->usedAnchors & HasRightAnchor) {
- //Handle stretching (left + right case is handled in updateLeftAnchor)
- if (d->usedAnchors & HasHCenterAnchor) {
+ if (d->usedAnchors & HasLeftAnchor) {
+ //Handle stretching
+ bool invalid = true;
int width = 0;
- bool invalid = d->calcStretch(d->hCenter, d->right, d->hCenterOffset, -d->rightMargin,
- QFxAnchorLine::Left, width);
+ 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*2);
+ 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);
+ }
+ } else 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);
+ }
+ } else 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);
+ }
}
- //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);
- }
- }
-}
-
-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);
- }
+ d->updatingHorizontalAnchor = false;
+ } else {
+ qmlInfo(d->item) << "Anchor loop detected on horizontal anchor.";
}
}
@@ -562,6 +595,24 @@ void QFxAnchors::setTop(const QFxAnchorLine &edge)
d->top = edge;
}
+void QFxAnchors::resetTop()
+{
+ Q_D(QFxAnchors);
+
+ //update flags
+ d->usedAnchors &= ~HasTopAnchor;
+
+ //clear binding
+ QmlMetaProperty prop(this, "top");
+ prop.binding()->clearExpression();
+
+ //disconnect signal/slot connections as needed
+ disconnect(this, SIGNAL(topMarginChanged()), this, SLOT(updateVerticalAnchors()));
+ disconnect(d->top.item, 0, this, 0);
+
+ updateVerticalAnchors();
+}
+
QFxAnchorLine QFxAnchors::bottom() const
{
Q_D(const QFxAnchors);
@@ -579,7 +630,24 @@ void QFxAnchors::setBottom(const QFxAnchorLine &edge)
d->checkVValid();
d->bottom = edge;
+}
+
+void QFxAnchors::resetBottom()
+{
+ Q_D(QFxAnchors);
+
+ //update flags
+ d->usedAnchors &= ~HasBottomAnchor;
+
+ //clear binding
+ QmlMetaProperty prop(this, "bottom");
+ prop.binding()->clearExpression();
+
+ //disconnect signal/slot connections as needed
+ disconnect(this, SIGNAL(bottomMarginChanged()), this, SLOT(updateVerticalAnchors()));
+ disconnect(d->bottom.item, 0, this, 0);
+ updateVerticalAnchors();
}
QFxAnchorLine QFxAnchors::verticalCenter() const
@@ -601,6 +669,24 @@ void QFxAnchors::setVerticalCenter(const QFxAnchorLine &edge)
d->vCenter = edge;
}
+void QFxAnchors::resetVerticalCenter()
+{
+ Q_D(QFxAnchors);
+
+ //update flags
+ d->usedAnchors &= ~HasVCenterAnchor;
+
+ //clear binding
+ QmlMetaProperty prop(this, "verticalCenter");
+ prop.binding()->clearExpression();
+
+ //disconnect signal/slot connections as needed
+ disconnect(this, SIGNAL(verticalCenterOffsetChanged()), this, SLOT(updateVerticalAnchors()));
+ disconnect(d->vCenter.item, 0, this, 0);
+
+ updateVerticalAnchors();
+}
+
QFxAnchorLine QFxAnchors::left() const
{
Q_D(const QFxAnchors);
@@ -620,6 +706,24 @@ void QFxAnchors::setLeft(const QFxAnchorLine &edge)
d->left = edge;
}
+void QFxAnchors::resetLeft()
+{
+ Q_D(QFxAnchors);
+
+ //update flags
+ d->usedAnchors &= ~HasLeftAnchor;
+
+ //clear binding
+ QmlMetaProperty prop(this, "left");
+ prop.binding()->clearExpression();
+
+ //disconnect signal/slot connections as needed
+ disconnect(this, SIGNAL(leftMarginChanged()), this, SLOT(updateHorizontalAnchors()));
+ disconnect(d->left.item, 0, this, 0);
+
+ updateHorizontalAnchors();
+}
+
QFxAnchorLine QFxAnchors::right() const
{
Q_D(const QFxAnchors);
@@ -637,7 +741,24 @@ void QFxAnchors::setRight(const QFxAnchorLine &edge)
d->checkHValid();
d->right = edge;
+}
+
+void QFxAnchors::resetRight()
+{
+ Q_D(QFxAnchors);
+
+ //update flags
+ d->usedAnchors &= ~HasRightAnchor;
+
+ //clear binding
+ QmlMetaProperty prop(this, "right");
+ prop.binding()->clearExpression();
+
+ //disconnect signal/slot connections as needed
+ disconnect(this, SIGNAL(rightMarginChanged()), this, SLOT(updateHorizontalAnchors()));
+ disconnect(d->right.item, 0, this, 0);
+ updateHorizontalAnchors();
}
QFxAnchorLine QFxAnchors::horizontalCenter() const
@@ -659,6 +780,24 @@ void QFxAnchors::setHorizontalCenter(const QFxAnchorLine &edge)
d->hCenter = edge;
}
+void QFxAnchors::resetHorizontalCenter()
+{
+ Q_D(QFxAnchors);
+
+ //update flags
+ d->usedAnchors &= ~HasHCenterAnchor;
+
+ //clear binding
+ QmlMetaProperty prop(this, "horizontalCenter");
+ prop.binding()->clearExpression();
+
+ //disconnect signal/slot connections as needed
+ disconnect(this, SIGNAL(horizontalCenterOffsetChanged()), this, SLOT(updateHorizontalAnchors()));
+ disconnect(d->hCenter.item, 0, this, 0);
+
+ updateHorizontalAnchors();
+}
+
int QFxAnchors::leftMargin() const
{
Q_D(const QFxAnchors);
@@ -854,4 +993,5 @@ bool QFxAnchorsPrivate::checkVAnchorValid(QFxAnchorLine anchor) const
return true;
}
+
QT_END_NAMESPACE
diff --git a/src/declarative/fx/qfxanchors.h b/src/declarative/fx/qfxanchors.h
index 3a250b9..5a8cc1a 100644
--- a/src/declarative/fx/qfxanchors.h
+++ b/src/declarative/fx/qfxanchors.h
@@ -84,12 +84,12 @@ class Q_DECLARATIVE_EXPORT QFxAnchors : public QObject
{
Q_OBJECT
- Q_PROPERTY(QFxAnchorLine left READ left WRITE setLeft);
- Q_PROPERTY(QFxAnchorLine right READ right WRITE setRight);
- Q_PROPERTY(QFxAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter);
- Q_PROPERTY(QFxAnchorLine top READ top WRITE setTop);
- Q_PROPERTY(QFxAnchorLine bottom READ bottom WRITE setBottom);
- Q_PROPERTY(QFxAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter);
+ Q_PROPERTY(QFxAnchorLine left READ left WRITE setLeft RESET resetLeft);
+ Q_PROPERTY(QFxAnchorLine right READ right WRITE setRight RESET resetRight);
+ Q_PROPERTY(QFxAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter);
+ Q_PROPERTY(QFxAnchorLine top READ top WRITE setTop RESET resetTop);
+ Q_PROPERTY(QFxAnchorLine bottom READ bottom WRITE setBottom RESET resetBottom);
+ Q_PROPERTY(QFxAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter);
Q_PROPERTY(int leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged);
Q_PROPERTY(int rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged);
Q_PROPERTY(int horizontalCenterOffset READ horizontalCenterOffset WRITE setHorizontalCenterOffset NOTIFY horizontalCenterOffsetChanged());
@@ -109,27 +109,35 @@ public:
HasBottomAnchor = 0x08,
HasHCenterAnchor = 0x10,
HasVCenterAnchor = 0x20,
- HasBaselineAnchor = 0x40
+ HasBaselineAnchor = 0x40,
+ Horizontal_Mask = HasLeftAnchor | HasRightAnchor | HasHCenterAnchor,
+ Vertical_Mask = HasTopAnchor | HasBottomAnchor | HasVCenterAnchor | HasBaselineAnchor
};
Q_DECLARE_FLAGS(UsedAnchors, UsedAnchor);
QFxAnchorLine left() const;
void setLeft(const QFxAnchorLine &edge);
+ Q_INVOKABLE void resetLeft(); //### temporarily invokable for testing
QFxAnchorLine right() const;
void setRight(const QFxAnchorLine &edge);
+ void resetRight();
QFxAnchorLine horizontalCenter() const;
void setHorizontalCenter(const QFxAnchorLine &edge);
+ void resetHorizontalCenter();
QFxAnchorLine top() const;
void setTop(const QFxAnchorLine &edge);
+ void resetTop();
QFxAnchorLine bottom() const;
void setBottom(const QFxAnchorLine &edge);
+ void resetBottom();
QFxAnchorLine verticalCenter() const;
void setVerticalCenter(const QFxAnchorLine &edge);
+ void resetVerticalCenter();
int leftMargin() const;
void setLeftMargin(int);
@@ -172,12 +180,8 @@ Q_SIGNALS:
private Q_SLOTS:
void fillChanged();
- void updateLeftAnchor();
- void updateRightAnchor();
- void updateHCenterAnchor();
- void updateTopAnchor();
- void updateBottomAnchor();
- void updateVCenterAnchor();
+ void updateHorizontalAnchors();
+ void updateVerticalAnchors();
private:
//### should item be a friend? (and make some of the public methods private or protected)
diff --git a/src/declarative/fx/qfxanchors_p.h b/src/declarative/fx/qfxanchors_p.h
index 3a5d1c7..82c2086 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)
{
}
@@ -76,8 +77,8 @@ public:
bool checkVValid() const;
bool checkHAnchorValid(QFxAnchorLine anchor) const;
bool checkVAnchorValid(QFxAnchorLine anchor) const;
- void connectHHelper(const QFxAnchorLine &anchorLine, const char *slotString);
- void connectVHelper(const QFxAnchorLine &anchorLine, const char *slotString);
+ void connectHHelper(const QFxAnchorLine &anchorLine);
+ void connectVHelper(const QFxAnchorLine &anchorLine);
bool calcStretch(const QFxAnchorLine &edge1, const QFxAnchorLine &edge2, int offset1, int offset2, QFxAnchorLine::AnchorLine line, int &stretch);
QFxItem *item;
@@ -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 fb46a0e..74c9b5b 100644
--- a/src/declarative/fx/qfxtextedit.cpp
+++ b/src/declarative/fx/qfxtextedit.cpp
@@ -851,7 +851,6 @@ void QFxTextEditPrivate::updateDefaultTextOption()
QTextOption::WrapMode oldWrapMode = opt.wrapMode();
-qDebug() << "wrap mode is" << opt.wrapMode();
if (wrap)
opt.setWrapMode(QTextOption::WordWrap);
else
@@ -859,7 +858,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 3950f82..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)
+: inited(false), updating(false), mePtr(0)
{
}
@@ -75,6 +76,9 @@ QmlBindableValue::QmlBindableValue(const QString &str, QObject *obj, bool sse, Q
QmlBindableValue::~QmlBindableValue()
{
+ Q_D(QmlBindableValue);
+ if(d->mePtr)
+ *(d->mePtr) = 0;
}
void QmlBindableValue::setTarget(const QmlMetaProperty &prop)
@@ -118,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 b6de5b7..d9af0ef 100644
--- a/src/declarative/qml/qmlbindablevalue_p.h
+++ b/src/declarative/qml/qmlbindablevalue_p.h
@@ -55,7 +55,10 @@ public:
QmlBindableValuePrivate();
bool inited;
+ bool updating;
QmlMetaProperty property;
+
+ QmlBindableValue **mePtr;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 13fc332..a40b7c8 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -526,6 +526,8 @@ void QmlCompiler::compileTree(Object *tree)
init.type = QmlInstruction::Init;
init.line = 0;
init.init.dataSize = 0;
+ init.init.bindingsSize = 0;
+ init.init.parserStatusSize = 0;
output->bytecode << init;
if (!compileObject(tree, 0)) // Compile failed
@@ -663,6 +665,9 @@ bool QmlCompiler::compileComponent(Object *obj, int ctxt)
if (obj->defaultProperty && obj->defaultProperty->values.count())
root = obj->defaultProperty->values.first()->object;
+ if (!root)
+ COMPILE_EXCEPTION("Cannot create empty component specification");
+
COMPILE_CHECK(compileComponentFromRoot(root, ctxt));
if (idProp && idProp->values.count()) {
@@ -698,6 +703,8 @@ bool QmlCompiler::compileComponentFromRoot(Object *obj, int ctxt)
QmlInstruction init;
init.type = QmlInstruction::Init;
init.init.dataSize = 0;
+ init.init.bindingsSize = 0;
+ init.init.parserStatusSize = 0;
init.line = obj->location.start.line;
output->bytecode << init;
@@ -1378,6 +1385,8 @@ int QmlCompiler::optimizeExpressions(int start, int end, int patch)
QHash<QString, int> ids;
int saveCount = 0;
int newInstrs = 0;
+ int bindingsCount = 0;
+ int parserStatusCount = 0;
for (int ii = start; ii <= end; ++ii) {
const QmlInstruction &instr = output->bytecode.at(ii);
@@ -1400,6 +1409,17 @@ int QmlCompiler::optimizeExpressions(int start, int end, int patch)
ii += instr.createComponent.count - 1;
continue;
}
+
+ if (instr.type == QmlInstruction::AssignBinding ||
+ instr.type == QmlInstruction::AssignCompiledBinding ||
+ instr.type == QmlInstruction::StoreBinding ||
+ instr.type == QmlInstruction::StoreCompiledBinding) {
+ ++bindingsCount;
+ } else if (instr.type == QmlInstruction::TryBeginObject ||
+ instr.type == QmlInstruction::BeginObject) {
+ ++parserStatusCount;
+ }
+
if (instr.type == QmlInstruction::StoreCompiledBinding) {
QmlBasicScript s(output->datas.at(instr.assignBinding.value).constData());
@@ -1437,12 +1457,12 @@ int QmlCompiler::optimizeExpressions(int start, int end, int patch)
++newInstrs;
}
}
- }
-
+ }
}
- if (saveCount)
- output->bytecode[patch].init.dataSize = saveCount;
+ output->bytecode[patch].init.dataSize = saveCount;
+ output->bytecode[patch].init.bindingsSize = bindingsCount;
+ output->bytecode[patch].init.parserStatusSize = parserStatusCount;;
return newInstrs;
}
diff --git a/src/declarative/qml/qmlcomponent.cpp b/src/declarative/qml/qmlcomponent.cpp
index 027c2a8..da8f26d 100644
--- a/src/declarative/qml/qmlcomponent.cpp
+++ b/src/declarative/qml/qmlcomponent.cpp
@@ -171,6 +171,11 @@ QmlComponent::~QmlComponent()
}
if (d->cc)
d->cc->release();
+
+ for(int ii = 0; ii < d->bindValues.count(); ++ii)
+ QmlEnginePrivate::clear(d->bindValues[ii]);
+ for(int ii = 0; ii < d->parserStatus.count(); ++ii)
+ QmlEnginePrivate::clear(d->parserStatus[ii]);
}
/*!
@@ -483,10 +488,10 @@ QObject *QmlComponent::beginCreate(QmlContext *context)
if (ep->rootComponent == this) {
ep->rootComponent = 0;
- d->bindValues = ep->currentBindValues;
- d->parserStatus = ep->currentParserStatus;
- ep->currentBindValues.clear();
- ep->currentParserStatus.clear();
+ d->bindValues = ep->bindValues;
+ d->parserStatus = ep->parserStatus;
+ ep->bindValues.clear();
+ ep->parserStatus.clear();
d->completePending = true;
}
} else {
@@ -511,16 +516,29 @@ void QmlComponent::completeCreate()
#ifdef Q_ENABLE_PERFORMANCE_LOG
QFxPerfTimer<QFxPerf::BindInit> bi;
#endif
- for (int ii = 0; ii < d->bindValues.count(); ++ii)
- d->bindValues.at(ii)->init();
+ for (int ii = 0; ii < d->bindValues.count(); ++ii) {
+ QmlEnginePrivate::SimpleList<QmlBindableValue> bv =
+ d->bindValues.at(ii);
+ for (int jj = 0; jj < bv.count; ++jj) {
+ if(bv.at(jj))
+ bv.at(jj)->init();
+ }
+ QmlEnginePrivate::clear(bv);
+ }
}
- QSet<QmlParserStatus *> done;
+
for (int ii = 0; ii < d->parserStatus.count(); ++ii) {
- QmlParserStatus *ps = d->parserStatus.at(ii);
- if (!done.contains(ps)) {
- done.insert(ps);
- ps->componentComplete();
+ QmlEnginePrivate::SimpleList<QmlParserStatus> ps =
+ d->parserStatus.at(ii);
+
+ for (int jj = 0; jj < ps.count; ++jj) {
+ QmlParserStatus *status = ps.at(jj);
+ if (status && status->d) {
+ status->d = 0;
+ status->componentComplete();
+ }
}
+ QmlEnginePrivate::clear(ps);
}
d->bindValues.clear();
diff --git a/src/declarative/qml/qmlcomponent_p.h b/src/declarative/qml/qmlcomponent_p.h
index 6a5345e..4de47c6 100644
--- a/src/declarative/qml/qmlcomponent_p.h
+++ b/src/declarative/qml/qmlcomponent_p.h
@@ -46,6 +46,7 @@
#include <QStringList>
#include <QList>
#include "private/qobject_p.h"
+#include "private/qmlengine_p.h"
#include "private/qmlcompositetypemanager_p.h"
#include <qmlerror.h>
#include "qmlcomponent.h"
@@ -75,8 +76,10 @@ public:
int start;
int count;
QmlCompiledComponent *cc;
- QList<QmlBindableValue *> bindValues;
- QList<QmlParserStatus *> parserStatus;
+
+ QList<QmlEnginePrivate::SimpleList<QmlBindableValue> > bindValues;
+ QList<QmlEnginePrivate::SimpleList<QmlParserStatus> > parserStatus;
+
bool completePending;
QmlEngine *engine;
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index dfcf413..df5f90e 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -86,6 +86,10 @@ void QmlContextPrivate::destroyed(QObject *obj)
void QmlContextPrivate::init()
{
Q_Q(QmlContext);
+
+ if (parent)
+ parent->d_func()->childContexts.insert(q);
+
//set scope chain
QScriptEngine *scriptEngine = engine->scriptEngine();
QScriptValue scopeObj =
@@ -231,8 +235,48 @@ QmlContext::QmlContext(QmlContext *parentContext, QObject *parent)
*/
QmlContext::~QmlContext()
{
+ Q_D(QmlContext);
+ if (d->parent)
+ d->parent->d_func()->childContexts.remove(this);
+
+ for (QSet<QmlContext *>::ConstIterator iter = d->childContexts.begin();
+ iter != d->childContexts.end();
+ ++iter) {
+ (*iter)->d_func()->invalidateEngines();
+ (*iter)->d_func()->parent = 0;
+ }
+
+ for (QSet<QmlExpression *>::ConstIterator iter =
+ d->childExpressions.begin();
+ iter != d->childExpressions.end();
+ ++iter) {
+ (*iter)->d->ctxt = 0;
+ }
+
+ for (int ii = 0; ii < d->contextObjects.count(); ++ii) {
+ QObjectPrivate *p = QObjectPrivate::get(d->contextObjects.at(ii));
+ QmlSimpleDeclarativeData *data =
+ static_cast<QmlSimpleDeclarativeData *>(p->declarativeData);
+ if(data && (data->flags & QmlSimpleDeclarativeData::Extended)) {
+ data->context = 0;
+ } else {
+ p->declarativeData = 0;
+ }
+ }
+ d->contextObjects.clear();
}
+void QmlContextPrivate::invalidateEngines()
+{
+ if (!engine)
+ return;
+ engine = 0;
+ for (QSet<QmlContext *>::ConstIterator iter = childContexts.begin();
+ iter != childContexts.end();
+ ++iter) {
+ (*iter)->d_func()->invalidateEngines();
+ }
+}
/*!
Return the context's QmlEngine, or 0 if the context has no QmlEngine or the
diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h
index 39d565a..935c7ca 100644
--- a/src/declarative/qml/qmlcontext.h
+++ b/src/declarative/qml/qmlcontext.h
@@ -95,6 +95,7 @@ private:
friend class QmlComponent;
friend class QmlScriptPrivate;
friend class QmlBoundSignalProxy;
+ friend class QmlSimpleDeclarativeData;
QmlContext(QmlEngine *);
};
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
index d7c6d29..f527bb8 100644
--- a/src/declarative/qml/qmlcontext_p.h
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -47,10 +47,13 @@
#include <private/qmldeclarativedata_p.h>
#include <qhash.h>
#include <qscriptvalue.h>
+#include <QtCore/qset.h>
QT_BEGIN_NAMESPACE
class QmlContext;
+class QmlExpression;
class QmlEngine;
+class QmlExpression;
class QmlCompiledComponent;
class QmlContextPrivate : public QObjectPrivate
@@ -87,7 +90,12 @@ public:
};
void addDefaultObject(QObject *, Priority);
+ void invalidateEngines();
+ QSet<QmlContext *> childContexts;
+ QSet<QmlExpression *> childExpressions;
+
QmlSimpleDeclarativeData contextData;
+ QObjectList contextObjects;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmldeclarativedata_p.h b/src/declarative/qml/qmldeclarativedata_p.h
index a934442..fb7a015 100644
--- a/src/declarative/qml/qmldeclarativedata_p.h
+++ b/src/declarative/qml/qmldeclarativedata_p.h
@@ -51,6 +51,7 @@ class QmlSimpleDeclarativeData : public QDeclarativeData
public:
QmlSimpleDeclarativeData() : flags(0), context(0) {}
+ virtual void destroyed(QObject *);
enum Flag { Extended = 0x00000001 };
quint32 flags;
QmlContext *context;
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 50c0981..c39a0d5 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -70,6 +70,7 @@
#include <QtCore/qdir.h>
#include <qmlcomponent.h>
#include "private/qmlmetaproperty_p.h"
+#include <private/qmlbindablevalue_p.h>
QT_BEGIN_NAMESPACE
@@ -160,6 +161,34 @@ QmlEnginePrivate::~QmlEnginePrivate()
objectClass = 0;
delete networkAccessManager;
networkAccessManager = 0;
+
+ for(int ii = 0; ii < bindValues.count(); ++ii)
+ clear(bindValues[ii]);
+ for(int ii = 0; ii < parserStatus.count(); ++ii)
+ clear(parserStatus[ii]);
+}
+
+void QmlEnginePrivate::clear(SimpleList<QmlBindableValue> &bvs)
+{
+ for (int ii = 0; ii < bvs.count; ++ii) {
+ QmlBindableValue *bv = bvs.at(ii);
+ if(bv) {
+ QmlBindableValuePrivate *p =
+ static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bv));
+ p->mePtr = 0;
+ }
+ }
+ bvs.clear();
+}
+
+void QmlEnginePrivate::clear(SimpleList<QmlParserStatus> &pss)
+{
+ for (int ii = 0; ii < pss.count; ++ii) {
+ QmlParserStatus *ps = pss.at(ii);
+ if(ps)
+ ps->d = 0;
+ }
+ pss.clear();
}
void QmlEnginePrivate::init()
@@ -630,11 +659,10 @@ void QmlEngine::setContextForObject(QObject *object, QmlContext *context)
if (!data) {
priv->declarativeData = &context->d_func()->contextData;
} else {
- // ### - Don't have to use extended data here
- QmlExtendedDeclarativeData *data = new QmlExtendedDeclarativeData;
data->context = context;
- priv->declarativeData = data;
}
+
+ context->d_func()->contextObjects.append(object);
}
QmlContext *qmlContext(const QObject *obj)
@@ -684,8 +712,15 @@ QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object)
return rv;
}
-void QmlExtendedDeclarativeData::destroyed(QObject *)
+void QmlSimpleDeclarativeData::destroyed(QObject *object)
+{
+ if (context)
+ context->d_func()->contextObjects.removeAll(object);
+}
+
+void QmlExtendedDeclarativeData::destroyed(QObject *object)
{
+ QmlSimpleDeclarativeData::destroyed(object);
delete this;
}
@@ -770,6 +805,8 @@ QmlExpression::QmlExpression(QmlContext *ctxt, void *expr,
d->ctxt = ctxt;
if(ctxt && ctxt->engine())
d->id = ctxt->engine()->d_func()->getUniqueId();
+ if(ctxt)
+ ctxt->d_func()->childExpressions.insert(this);
d->me = me;
}
@@ -781,6 +818,8 @@ QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expr,
d->ctxt = ctxt;
if(ctxt && ctxt->engine())
d->id = ctxt->engine()->d_func()->getUniqueId();
+ if(ctxt)
+ ctxt->d_func()->childExpressions.insert(this);
d->me = me;
}
@@ -798,6 +837,8 @@ QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression,
d->ctxt = ctxt;
if(ctxt && ctxt->engine())
d->id = ctxt->engine()->d_func()->getUniqueId();
+ if(ctxt)
+ ctxt->d_func()->childExpressions.insert(this);
d->me = scope;
}
@@ -806,6 +847,8 @@ QmlExpression::QmlExpression(QmlContext *ctxt, const QString &expression,
*/
QmlExpression::~QmlExpression()
{
+ if (d->ctxt)
+ d->ctxt->d_func()->childExpressions.remove(this);
delete d; d = 0;
}
@@ -815,7 +858,7 @@ QmlExpression::~QmlExpression()
*/
QmlEngine *QmlExpression::engine() const
{
- return d->ctxt->engine();
+ return d->ctxt?d->ctxt->engine():0;
}
/*!
@@ -892,7 +935,7 @@ void BindExpressionProxy::changed()
QVariant QmlExpression::value()
{
QVariant rv;
- if (!d->ctxt || (!d->sse.isValid() && d->expression.isEmpty()))
+ if (!d->ctxt || !engine() || (!d->sse.isValid() && d->expression.isEmpty()))
return rv;
#ifdef Q_ENABLE_PERFORMANCE_LOG
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index 63df0ba..9402fa9 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -107,8 +107,35 @@ public:
QScriptEngine scriptEngine;
- QList<QmlBindableValue *> currentBindValues;
- QList<QmlParserStatus *> currentParserStatus;
+ template<class T>
+ struct SimpleList {
+ SimpleList()
+ : count(0), values(0) {}
+ SimpleList(int r)
+ : count(0), values(new T*[r]) {}
+
+ int count;
+ T **values;
+
+ void append(T *v) {
+ values[count++] = v;
+ }
+
+ T *at(int idx) const {
+ return values[idx];
+ }
+
+ void clear() {
+ delete [] values;
+ }
+ };
+
+ static void clear(SimpleList<QmlBindableValue> &);
+ static void clear(SimpleList<QmlParserStatus> &);
+
+ QList<SimpleList<QmlBindableValue> > bindValues;
+ QList<SimpleList<QmlParserStatus> > parserStatus;
+
QmlComponent *rootComponent;
mutable QNetworkAccessManager *networkAccessManager;
diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h
index bb6980a..2c6b1ad 100644
--- a/src/declarative/qml/qmlexpression.h
+++ b/src/declarative/qml/qmlexpression.h
@@ -87,6 +87,7 @@ protected:
private:
friend class BindExpressionProxy;
friend class QmlDebugger;
+ friend class QmlContext;
QmlExpressionPrivate *d;
};
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index 02e084d..86bddf8 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -173,6 +173,8 @@ public:
union {
struct {
int dataSize;
+ int bindingsSize;
+ int parserStatusSize;
} init;
struct {
int type;
diff --git a/src/declarative/qml/qmlparserstatus.cpp b/src/declarative/qml/qmlparserstatus.cpp
index 71b7adf..fceac05 100644
--- a/src/declarative/qml/qmlparserstatus.cpp
+++ b/src/declarative/qml/qmlparserstatus.cpp
@@ -48,11 +48,17 @@ QT_BEGIN_NAMESPACE
\brief The QmlParserStatus class provides updates on the parser state.
*/
-/*!
- Destroys the parser status instance.
-*/
+/*! \internal */
+QmlParserStatus::QmlParserStatus()
+: d(0)
+{
+}
+
+/*! \internal */
QmlParserStatus::~QmlParserStatus()
{
+ if(d)
+ (*d) = 0;
}
/*!
diff --git a/src/declarative/qml/qmlparserstatus.h b/src/declarative/qml/qmlparserstatus.h
index bb3691c..0e58229 100644
--- a/src/declarative/qml/qmlparserstatus.h
+++ b/src/declarative/qml/qmlparserstatus.h
@@ -53,11 +53,18 @@ QT_MODULE(Declarative)
class Q_DECLARATIVE_EXPORT QmlParserStatus
{
public:
+ QmlParserStatus();
virtual ~QmlParserStatus();
virtual void classBegin();
virtual void classComplete();
virtual void componentComplete();
+
+private:
+ friend class QmlVME;
+ friend class QmlComponent;
+ friend class QmlEnginePrivate;
+ QmlParserStatus **d;
};
Q_DECLARE_INTERFACE(QmlParserStatus, "com.trolltech.qml.QmlParserStatus");
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index ca4f9c9..e42b2fc 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -62,6 +62,8 @@
#include <private/qmlcomponent_p.h>
#include "private/qmlvmemetaobject_p.h"
#include <QtCore/qdebug.h>
+#include <QtCore/qvarlengtharray.h>
+#include <private/qmlbindablevalue_p.h>
QT_BEGIN_NAMESPACE
Q_DECLARE_PERFORMANCE_LOG(QFxCompiler) {
@@ -219,9 +221,8 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
#ifdef Q_ENABLE_PERFORMANCE_LOG
QFxPerfTimer<QFxPerf::CompileRun> cr;
#endif
-
- QList<QmlParserStatus *> parserStatuses;
- QList<QmlBindableValue *> bindableValues;
+ QmlEnginePrivate::SimpleList<QmlBindableValue> bindValues;
+ QmlEnginePrivate::SimpleList<QmlParserStatus> parserStatus;
QStack<QObject *> stack;
QStack<ListInstance> qliststack;
@@ -252,6 +253,11 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
::memset(savedObjects, 0,
sizeof(QObject *)*instr.init.dataSize);
}
+
+ if (instr.init.bindingsSize)
+ bindValues = QmlEnginePrivate::SimpleList<QmlBindableValue>(instr.init.bindingsSize);
+ if (instr.init.parserStatusSize)
+ parserStatus = QmlEnginePrivate::SimpleList<QmlParserStatus>(instr.init.parserStatusSize);
}
break;
@@ -523,8 +529,10 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
#endif
QObject *target = stack.top();
QmlParserStatus *status = reinterpret_cast<QmlParserStatus *>(reinterpret_cast<char *>(target) + instr.begin.castValue);
+ parserStatus.append(status);
+ status->d = &parserStatus.values[parserStatus.count - 1];
+
status->classBegin();
- parserStatuses << status;
}
break;
@@ -634,10 +642,13 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
VME_EXCEPTION("Cannot assign a binding to read-only property" << mp.name());
QmlBindableValue *bind = new QmlBindableValue((void *)datas.at(instr.assignBinding.value).constData(), comp, context, 0);
+ bindValues.append(bind);
+ QmlBindableValuePrivate *p =
+ static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bind));
+ p->mePtr = &bindValues.values[bindValues.count - 1];
QFx_setParent_noEvent(bind, target);
bind->setTarget(mp);
- bindableValues << bind;
}
break;
@@ -656,10 +667,13 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
VME_EXCEPTION("Cannot assign a binding to read-only property" << mp.name());
QmlBindableValue *bind = new QmlBindableValue(primitives.at(instr.assignBinding.value), context, false);
+ bindValues.append(bind);
+ QmlBindableValuePrivate *p =
+ static_cast<QmlBindableValuePrivate *>(QObjectPrivate::get(bind));
+ p->mePtr = &bindValues.values[bindValues.count - 1];
QFx_setParent_noEvent(bind, target);
bind->setTarget(mp);
- bindableValues << bind;
}
break;
@@ -1045,12 +1059,17 @@ QObject *QmlVME::run(QmlContext *ctxt, QmlCompiledComponent *comp, int start, in
if (!stack.isEmpty()) {
delete stack.at(0);
}
+
+ QmlEnginePrivate::clear(bindValues);
+ QmlEnginePrivate::clear(parserStatus);
return 0;
}
QmlEnginePrivate *ep = ctxt->engine()->d_func();
- ep->currentBindValues << bindableValues;
- ep->currentParserStatus << parserStatuses;
+ if (bindValues.count)
+ ep->bindValues << bindValues;
+ if (parserStatus.count)
+ ep->parserStatus << parserStatus;
comp->dumpPost();
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..683a7b9
--- /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 here
+ //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..c63caf4 100644
--- a/tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp
+++ b/tests/auto/declarative/qmlbindengine/tst_qmlbindengine.cpp
@@ -1,13 +1,15 @@
#include <qtest.h>
#include <QtDeclarative/qmlcomponent.h>
#include <QtDeclarative/qmlengine.h>
+#include <QtDeclarative/qmlexpression.h>
+#include <QtDeclarative/qmlcontext.h>
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 +17,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 +32,7 @@ public:
signals:
void basicSignal();
void argumentSignal(int a, QString b, qreal c);
+ void stringChanged();
public slots:
void method() { m_methodCalled = true; }
@@ -41,6 +50,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 +76,8 @@ private slots:
void boolPropertiesEvaluateAsBool();
void methods();
void signalAssignment();
+ void bindingLoop();
+ void contextPropertiesTriggerReeval();
private:
QmlEngine engine;
@@ -118,6 +145,42 @@ void tst_qmlbindengine::methods()
}
}
+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);
+}
+
+class MyExpression : public QmlExpression
+{
+public:
+ MyExpression(QmlContext *ctxt, const QString &expr)
+ : QmlExpression(ctxt, expr, 0), changed(false)
+ {
+ }
+
+ bool changed;
+};
+
+void tst_qmlbindengine::contextPropertiesTriggerReeval()
+{
+ QmlContext context(engine.rootContext());
+ context.setContextProperty("testProp", QVariant(1));
+
+ MyExpression expr(&context, "testProp + 1");
+ QCOMPARE(expr.changed, false);
+ QCOMPARE(expr.value(), QVariant(2));
+
+ context.setContextProperty("testProp", QVariant(2));
+ QCOMPARE(expr.changed, true);
+ QCOMPARE(expr.value(), QVariant(3));
+}
+
QTEST_MAIN(tst_qmlbindengine)
#include "tst_qmlbindengine.moc"