aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Jones <martin.jones@nokia.com>2012-03-30 10:48:50 +1000
committerQt by Nokia <qt-info@nokia.com>2012-03-30 07:40:32 +0200
commit2ab873ed5fbb43404f119ef05b412485665a975f (patch)
treee66167b3e2d8712f96931734b1c7c62842c283f7
parentab45c8da80968c4fabdb121c7eea48164d2216ff (diff)
Size loaded item before bindings are evaluated
If the Loader size is set explicitly we can set the item size before the bindings are run, and avoiding an additional anchor layout. Also ensure item implict size changes are propagated/notified in the Loader. Change-Id: Ie22b018b22be8457ccf30b907a26e44260b9cef7 Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
-rw-r--r--src/quick/items/qquickimplicitsizeitem.cpp12
-rw-r--r--src/quick/items/qquickitem.cpp12
-rw-r--r--src/quick/items/qquickitem_p.h2
-rw-r--r--src/quick/items/qquickitemchangelistener_p.h2
-rw-r--r--src/quick/items/qquickloader.cpp71
-rw-r--r--src/quick/items/qquickloader_p_p.h7
-rw-r--r--tests/auto/quick/qquickloader/data/implicitSize.qml5
-rw-r--r--tests/auto/quick/qquickloader/tst_qquickloader.cpp12
8 files changed, 102 insertions, 21 deletions
diff --git a/src/quick/items/qquickimplicitsizeitem.cpp b/src/quick/items/qquickimplicitsizeitem.cpp
index 427be42312..1de8e0ab73 100644
--- a/src/quick/items/qquickimplicitsizeitem.cpp
+++ b/src/quick/items/qquickimplicitsizeitem.cpp
@@ -47,12 +47,24 @@ QT_BEGIN_NAMESPACE
void QQuickImplicitSizeItemPrivate::implicitWidthChanged()
{
Q_Q(QQuickImplicitSizeItem);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::ImplicitWidth) {
+ change.listener->itemImplicitWidthChanged(q);
+ }
+ }
emit q->implicitWidthChanged();
}
void QQuickImplicitSizeItemPrivate::implicitHeightChanged()
{
Q_Q(QQuickImplicitSizeItem);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::ImplicitHeight) {
+ change.listener->itemImplicitHeightChanged(q);
+ }
+ }
emit q->implicitHeightChanged();
}
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 6eddd0d0ba..10003d4e81 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -4502,6 +4502,12 @@ void QQuickItem::resetWidth()
void QQuickItemPrivate::implicitWidthChanged()
{
Q_Q(QQuickItem);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::ImplicitWidth) {
+ change.listener->itemImplicitWidthChanged(q);
+ }
+ }
emit q->implicitWidthChanged();
}
@@ -4624,6 +4630,12 @@ void QQuickItem::resetHeight()
void QQuickItemPrivate::implicitHeightChanged()
{
Q_Q(QQuickItem);
+ for (int ii = 0; ii < changeListeners.count(); ++ii) {
+ const QQuickItemPrivate::ChangeListener &change = changeListeners.at(ii);
+ if (change.types & QQuickItemPrivate::ImplicitHeight) {
+ change.listener->itemImplicitHeightChanged(q);
+ }
+ }
emit q->implicitHeightChanged();
}
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 01e8b4d335..89c09ed015 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -302,6 +302,8 @@ public:
Parent = 0x20,
Children = 0x40,
Rotation = 0x80,
+ ImplicitWidth = 0x100,
+ ImplicitHeight = 0x200
};
Q_DECLARE_FLAGS(ChangeTypes, ChangeType)
diff --git a/src/quick/items/qquickitemchangelistener_p.h b/src/quick/items/qquickitemchangelistener_p.h
index 3a5c25f5f5..cbdfb2b18b 100644
--- a/src/quick/items/qquickitemchangelistener_p.h
+++ b/src/quick/items/qquickitemchangelistener_p.h
@@ -74,6 +74,8 @@ public:
virtual void itemChildRemoved(QQuickItem *, QQuickItem *) {}
virtual void itemParentChanged(QQuickItem *, QQuickItem *) {}
virtual void itemRotationChanged(QQuickItem *) {}
+ virtual void itemImplicitWidthChanged(QQuickItem *) {}
+ virtual void itemImplicitHeightChanged(QQuickItem *) {}
virtual QQuickAnchorsPrivate *anchorPrivate() { return 0; }
};
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index f41ba44943..730dfd45d4 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -52,9 +52,11 @@
QT_BEGIN_NAMESPACE
+static const QQuickItemPrivate::ChangeTypes watchedChanges
+ = QQuickItemPrivate::Geometry | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight;
+
QQuickLoaderPrivate::QQuickLoaderPrivate()
: item(0), component(0), itemContext(0), incubator(0), updatingSize(false),
- itemWidthValid(false), itemHeightValid(false),
active(true), loadingFromSource(false), asynchronous(false)
{
}
@@ -69,16 +71,23 @@ QQuickLoaderPrivate::~QQuickLoaderPrivate()
void QQuickLoaderPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry)
{
- if (resizeItem == item) {
- if (!updatingSize && newGeometry.width() != oldGeometry.width())
- itemWidthValid = true;
- if (!updatingSize && newGeometry.height() != oldGeometry.height())
- itemHeightValid = true;
+ if (resizeItem == item)
_q_updateSize(false);
- }
QQuickItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry);
}
+void QQuickLoaderPrivate::itemImplicitWidthChanged(QQuickItem *)
+{
+ Q_Q(QQuickLoader);
+ q->setImplicitWidth(getImplicitWidth());
+}
+
+void QQuickLoaderPrivate::itemImplicitHeightChanged(QQuickItem *)
+{
+ Q_Q(QQuickLoader);
+ q->setImplicitHeight(getImplicitHeight());
+}
+
void QQuickLoaderPrivate::clear()
{
Q_Q(QQuickLoader);
@@ -103,7 +112,7 @@ void QQuickLoaderPrivate::clear()
if (item) {
QQuickItemPrivate *p = QQuickItemPrivate::get(item);
- p->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
+ p->removeItemChangeListener(this, watchedChanges);
// We can't delete immediately because our item may have triggered
// the Loader to load a different item.
@@ -117,14 +126,32 @@ void QQuickLoaderPrivate::clear()
void QQuickLoaderPrivate::initResize()
{
QQuickItemPrivate *p = QQuickItemPrivate::get(item);
- p->addItemChangeListener(this, QQuickItemPrivate::Geometry);
- // We may override the item's size, so we need to remember
- // whether the item provided its own valid size.
- itemWidthValid = p->widthValid;
- itemHeightValid = p->heightValid;
+ p->addItemChangeListener(this, watchedChanges);
_q_updateSize();
}
+qreal QQuickLoaderPrivate::getImplicitWidth() const
+{
+ Q_Q(const QQuickLoader);
+ // If the Loader has a valid width then Loader has set an explicit width on the
+ // item, and we want the item's implicitWidth. If the Loader's width has
+ // not been set then its implicitWidth is the width of the item.
+ if (item)
+ return q->widthValid() ? item->implicitWidth() : item->width();
+ return QQuickImplicitSizeItemPrivate::getImplicitWidth();
+}
+
+qreal QQuickLoaderPrivate::getImplicitHeight() const
+{
+ Q_Q(const QQuickLoader);
+ // If the Loader has a valid height then Loader has set an explicit height on the
+ // item, and we want the item's implicitHeight. If the Loader's height has
+ // not been set then its implicitHeight is the height of the item.
+ if (item)
+ return q->heightValid() ? item->implicitHeight() : item->height();
+ return QQuickImplicitSizeItemPrivate::getImplicitHeight();
+}
+
/*!
\qmlclass Loader QQuickLoader
\inqmlmodule QtQuick 2
@@ -245,7 +272,7 @@ QQuickLoader::~QQuickLoader()
Q_D(QQuickLoader);
if (d->item) {
QQuickItemPrivate *p = QQuickItemPrivate::get(d->item);
- p->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
+ p->removeItemChangeListener(d, watchedChanges);
}
}
@@ -284,7 +311,7 @@ void QQuickLoader::setActive(bool newVal)
} else {
if (d->item) {
QQuickItemPrivate *p = QQuickItemPrivate::get(d->item);
- p->removeItemChangeListener(d, QQuickItemPrivate::Geometry);
+ p->removeItemChangeListener(d, watchedChanges);
// We can't delete immediately because our item may have triggered
// the Loader to load a different item.
@@ -553,6 +580,14 @@ void QQuickLoaderPrivate::setInitialState(QObject *obj)
QQuickItem *item = qobject_cast<QQuickItem*>(obj);
if (item) {
+ // If the item doesn't have an explicit size, but the Loader
+ // does, then set the item's size now before bindings are
+ // evaluated, otherwise we will end up resizing the item
+ // later and triggering any affected bindings/anchors.
+ if (widthValid && !QQuickItemPrivate::get(item)->widthValid)
+ item->setWidth(q->width());
+ if (heightValid && !QQuickItemPrivate::get(item)->heightValid)
+ item->setHeight(q->height());
QQml_setParent_noEvent(itemContext, obj);
QQml_setParent_noEvent(item, q);
item->setParentItem(q);
@@ -812,15 +847,13 @@ void QQuickLoaderPrivate::_q_updateSize(bool loaderGeometryChanged)
updatingSize = true;
- qreal iWidth = !itemWidthValid ? item->implicitWidth() : item->width();
- qreal iHeight = !itemHeightValid ? item->implicitHeight() : item->height();
- q->setImplicitSize(iWidth, iHeight);
-
if (loaderGeometryChanged && q->widthValid())
item->setWidth(q->width());
if (loaderGeometryChanged && q->heightValid())
item->setHeight(q->height());
+ q->setImplicitSize(getImplicitWidth(), getImplicitHeight());
+
updatingSize = false;
}
diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h
index 1ad7756ed8..0978911315 100644
--- a/src/quick/items/qquickloader_p_p.h
+++ b/src/quick/items/qquickloader_p_p.h
@@ -87,6 +87,8 @@ public:
~QQuickLoaderPrivate();
void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+ void itemImplicitWidthChanged(QQuickItem *);
+ void itemImplicitHeightChanged(QQuickItem *);
void clear();
void initResize();
void load();
@@ -97,6 +99,9 @@ public:
QUrl resolveSourceUrl(QQmlV8Function *args);
v8::Handle<v8::Object> extractInitialPropertyValues(QQmlV8Function *args, QObject *loader, bool *error);
+ virtual qreal getImplicitWidth() const;
+ virtual qreal getImplicitHeight() const;
+
QUrl source;
QQuickItem *item;
QQmlComponent *component;
@@ -105,8 +110,6 @@ public:
v8::Persistent<v8::Object> initialPropertyValues;
v8::Persistent<v8::Object> qmlGlobalForIpv;
bool updatingSize: 1;
- bool itemWidthValid : 1;
- bool itemHeightValid : 1;
bool active : 1;
bool loadingFromSource : 1;
bool asynchronous : 1;
diff --git a/tests/auto/quick/qquickloader/data/implicitSize.qml b/tests/auto/quick/qquickloader/data/implicitSize.qml
index 5c8c8348ed..ae8c0b8b30 100644
--- a/tests/auto/quick/qquickloader/data/implicitSize.qml
+++ b/tests/auto/quick/qquickloader/data/implicitSize.qml
@@ -3,12 +3,17 @@ import QtQuick 2.0
Rectangle {
property real implWidth: 0
property real implHeight: 0
+ function changeImplicitSize () {
+ loader.item.implicitWidth = 200
+ loader.item.implicitHeight = 300
+ }
color: "green"
width: loader.implicitWidth+50
height: loader.implicitHeight+50
Loader {
id: loader
+ objectName: "loader"
sourceComponent: Item {
anchors.centerIn: parent
diff --git a/tests/auto/quick/qquickloader/tst_qquickloader.cpp b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
index 01781f7b54..ea35897004 100644
--- a/tests/auto/quick/qquickloader/tst_qquickloader.cpp
+++ b/tests/auto/quick/qquickloader/tst_qquickloader.cpp
@@ -842,6 +842,18 @@ void tst_QQuickLoader::implicitSize()
QCOMPARE(item->property("implHeight").toReal(), 100.);
QCOMPARE(item->property("implWidth").toReal(), 100.);
+ QQuickLoader *loader = item->findChild<QQuickLoader*>("loader");
+ QSignalSpy implWidthSpy(loader, SIGNAL(implicitWidthChanged()));
+ QSignalSpy implHeightSpy(loader, SIGNAL(implicitHeightChanged()));
+
+ QMetaObject::invokeMethod(item, "changeImplicitSize");
+
+ QCOMPARE(loader->property("implicitWidth").toReal(), 200.);
+ QCOMPARE(loader->property("implicitHeight").toReal(), 300.);
+
+ QCOMPARE(implWidthSpy.count(), 1);
+ QCOMPARE(implHeightSpy.count(), 1);
+
delete item;
}