summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/graphicsview/qgraphicslayout.cpp145
-rw-r--r--src/gui/graphicsview/qgraphicslayout.h2
-rw-r--r--src/gui/graphicsview/qgraphicslayout_p.cpp9
-rw-r--r--src/gui/graphicsview/qgraphicslinearlayout.cpp8
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp105
-rw-r--r--tests/auto/q3combobox/tst_q3combobox.cpp4
-rw-r--r--tests/auto/q3progressbar/tst_q3progressbar.cpp9
-rw-r--r--tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp3
-rw-r--r--tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp321
-rw-r--r--tests/auto/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp40
-rw-r--r--tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp41
-rw-r--r--tests/benchmarks/gui/graphicsview/graphicsview.pro1
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicslayout/qgraphicslayout.pro6
-rw-r--r--tests/benchmarks/gui/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp153
-rw-r--r--tests/manual/qgraphicslayout/flicker/flicker.pro8
-rw-r--r--tests/manual/qgraphicslayout/flicker/main.cpp56
-rw-r--r--tests/manual/qgraphicslayout/flicker/window.cpp73
-rw-r--r--tests/manual/qgraphicslayout/flicker/window.h284
18 files changed, 1135 insertions, 133 deletions
diff --git a/src/gui/graphicsview/qgraphicslayout.cpp b/src/gui/graphicsview/qgraphicslayout.cpp
index ed213f1..e50989c 100644
--- a/src/gui/graphicsview/qgraphicslayout.cpp
+++ b/src/gui/graphicsview/qgraphicslayout.cpp
@@ -167,7 +167,7 @@ QGraphicsLayout::QGraphicsLayout(QGraphicsLayoutItem *parent)
" neither a QGraphicsWidget nor QGraphicsLayout");
}
}
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType);
+ d_func()->sizePolicy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType);
setOwnedByLayout(true);
}
@@ -188,7 +188,7 @@ QGraphicsLayout::QGraphicsLayout(QGraphicsLayoutPrivate &dd, QGraphicsLayoutItem
" neither a QGraphicsWidget nor QGraphicsLayout");
}
}
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType);
+ d_func()->sizePolicy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, QSizePolicy::DefaultType);
setOwnedByLayout(true);
}
@@ -269,12 +269,20 @@ void QGraphicsLayout::activate()
return;
Q_ASSERT(!parentItem->isLayout());
- setGeometry(parentItem->contentsRect()); // relayout children
-
- // ### bug, should be parentItem ?
- parentLayoutItem()->updateGeometry(); // bubble up; will set activated to false
- // ### too many resizes? maybe we should walk up the chain to the
- // ### top-level layouted layoutItem and call activate there.
+ if (QGraphicsLayout::instantInvalidatePropagation()) {
+ QGraphicsWidget *parentWidget = static_cast<QGraphicsWidget*>(parentItem);
+ if (!parentWidget->parentLayoutItem()) {
+ // we've reached the topmost widget, resize it
+ bool wasResized = parentWidget->testAttribute(Qt::WA_Resized);
+ parentWidget->resize(parentWidget->size());
+ parentWidget->setAttribute(Qt::WA_Resized, wasResized);
+ }
+
+ setGeometry(parentItem->contentsRect()); // relayout children
+ } else {
+ setGeometry(parentItem->contentsRect()); // relayout children
+ parentLayoutItem()->updateGeometry();
+ }
}
/*!
@@ -300,32 +308,36 @@ bool QGraphicsLayout::isActivated() const
*/
void QGraphicsLayout::invalidate()
{
- // only mark layouts as invalid (activated = false) if we can post a LayoutRequest event.
- QGraphicsLayoutItem *layoutItem = this;
- while (layoutItem && layoutItem->isLayout()) {
- // we could call updateGeometry(), but what if that method
- // does not call the base implementation? In addition, updateGeometry()
- // does more than we need.
- layoutItem->d_func()->sizeHintCacheDirty = true;
- layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true;
- layoutItem = layoutItem->parentLayoutItem();
- }
- if (layoutItem) {
- layoutItem->d_func()->sizeHintCacheDirty = true;
- layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true;
- }
-
- bool postIt = layoutItem ? !layoutItem->isLayout() : false;
- if (postIt) {
- layoutItem = this;
- while (layoutItem && layoutItem->isLayout()
- && static_cast<QGraphicsLayout*>(layoutItem)->d_func()->activated) {
- static_cast<QGraphicsLayout*>(layoutItem)->d_func()->activated = false;
+ if (QGraphicsLayout::instantInvalidatePropagation()) {
+ updateGeometry();
+ } else {
+ // only mark layouts as invalid (activated = false) if we can post a LayoutRequest event.
+ QGraphicsLayoutItem *layoutItem = this;
+ while (layoutItem && layoutItem->isLayout()) {
+ // we could call updateGeometry(), but what if that method
+ // does not call the base implementation? In addition, updateGeometry()
+ // does more than we need.
+ layoutItem->d_func()->sizeHintCacheDirty = true;
+ layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true;
layoutItem = layoutItem->parentLayoutItem();
}
- if (layoutItem && !layoutItem->isLayout()) {
- // If a layout has a parent that is not a layout it must be a QGraphicsWidget.
- QApplication::postEvent(static_cast<QGraphicsWidget *>(layoutItem), new QEvent(QEvent::LayoutRequest));
+ if (layoutItem) {
+ layoutItem->d_func()->sizeHintCacheDirty = true;
+ layoutItem->d_func()->sizeHintWithConstraintCacheDirty = true;
+ }
+
+ bool postIt = layoutItem ? !layoutItem->isLayout() : false;
+ if (postIt) {
+ layoutItem = this;
+ while (layoutItem && layoutItem->isLayout()
+ && static_cast<QGraphicsLayout*>(layoutItem)->d_func()->activated) {
+ static_cast<QGraphicsLayout*>(layoutItem)->d_func()->activated = false;
+ layoutItem = layoutItem->parentLayoutItem();
+ }
+ if (layoutItem && !layoutItem->isLayout()) {
+ // If a layout has a parent that is not a layout it must be a QGraphicsWidget.
+ QApplication::postEvent(static_cast<QGraphicsWidget *>(layoutItem), new QEvent(QEvent::LayoutRequest));
+ }
}
}
}
@@ -335,12 +347,27 @@ void QGraphicsLayout::invalidate()
*/
void QGraphicsLayout::updateGeometry()
{
- QGraphicsLayoutItem::updateGeometry();
- if (QGraphicsLayoutItem *parentItem = parentLayoutItem()) {
- if (parentItem->isLayout()) {
+ Q_D(QGraphicsLayout);
+ if (QGraphicsLayout::instantInvalidatePropagation()) {
+ d->activated = false;
+ QGraphicsLayoutItem::updateGeometry();
+
+ QGraphicsLayoutItem *parentItem = parentLayoutItem();
+ if (!parentItem)
+ return;
+
+ if (parentItem->isLayout())
+ static_cast<QGraphicsLayout *>(parentItem)->invalidate();
+ else
parentItem->updateGeometry();
- } else {
- invalidate();
+ } else {
+ QGraphicsLayoutItem::updateGeometry();
+ if (QGraphicsLayoutItem *parentItem = parentLayoutItem()) {
+ if (parentItem->isLayout()) {
+ parentItem->updateGeometry();
+ } else {
+ invalidate();
+ }
}
}
}
@@ -446,6 +473,50 @@ void QGraphicsLayout::addChildLayoutItem(QGraphicsLayoutItem *layoutItem)
d->addChildLayoutItem(layoutItem);
}
+static bool g_instantInvalidatePropagation = false;
+
+/*!
+ \internal
+ \since 4.8
+ \see instantInvalidatePropagation
+
+ Calling this function with \a enable set to true will enable a feature that
+ makes propagation of invalidation up to ancestor layout items to be done in
+ one go. It will propagate up the parentLayoutItem() hierarchy until it has
+ reached the root. If the root item is a QGraphicsWidget, it will *post* a
+ layout request to it. When the layout request is consumed it will traverse
+ down the hierarchy of layouts and widgets and activate all layouts that is
+ invalid (not activated). This is the recommended behaviour.
+
+ If not set it will also propagate up the parentLayoutItem() hierarchy, but
+ it will stop at the \i first \i widget it encounters, and post a layout
+ request to the widget. When the layout request is consumed, this might
+ cause it to continue propagation up to the parentLayoutItem() of the
+ widget. It will continue in this fashion until it has reached a widget with
+ no parentLayoutItem(). This strategy might cause drawing artifacts, since
+ it is not done in one go, and the consumption of layout requests might be
+ interleaved by consumption of paint events, which might cause significant
+ flicker.
+ Note, this is not the recommended behavior, but for compatibility reasons
+ this is the default behaviour.
+*/
+void QGraphicsLayout::setInstantInvalidatePropagation(bool enable)
+{
+ g_instantInvalidatePropagation = enable;
+}
+
+/*!
+ \internal
+ \since 4.8
+ \see setInstantInvalidatePropagation
+
+ returns true if the complete widget/layout hierarchy is rearranged in one go.
+*/
+bool QGraphicsLayout::instantInvalidatePropagation()
+{
+ return g_instantInvalidatePropagation;
+}
+
QT_END_NAMESPACE
#endif //QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicslayout.h b/src/gui/graphicsview/qgraphicslayout.h
index c622fb8..6031174 100644
--- a/src/gui/graphicsview/qgraphicslayout.h
+++ b/src/gui/graphicsview/qgraphicslayout.h
@@ -76,6 +76,8 @@ public:
virtual QGraphicsLayoutItem *itemAt(int i) const = 0;
virtual void removeAt(int index) = 0;
+ static void setInstantInvalidatePropagation(bool enable);
+ static bool instantInvalidatePropagation();
protected:
QGraphicsLayout(QGraphicsLayoutPrivate &, QGraphicsLayoutItem *);
void addChildLayoutItem(QGraphicsLayoutItem *layoutItem);
diff --git a/src/gui/graphicsview/qgraphicslayout_p.cpp b/src/gui/graphicsview/qgraphicslayout_p.cpp
index c2d4a08..6afdc19 100644
--- a/src/gui/graphicsview/qgraphicslayout_p.cpp
+++ b/src/gui/graphicsview/qgraphicslayout_p.cpp
@@ -180,8 +180,13 @@ void QGraphicsLayoutPrivate::activateRecursive(QGraphicsLayoutItem *item)
{
if (item->isLayout()) {
QGraphicsLayout *layout = static_cast<QGraphicsLayout *>(item);
- if (layout->d_func()->activated)
- layout->invalidate();
+ if (layout->d_func()->activated) {
+ if (QGraphicsLayout::instantInvalidatePropagation()) {
+ return;
+ } else {
+ layout->invalidate(); // ### LOOKS SUSPICIOUSLY WRONG!!???
+ }
+ }
for (int i = layout->count() - 1; i >= 0; --i) {
QGraphicsLayoutItem *childItem = layout->itemAt(i);
diff --git a/src/gui/graphicsview/qgraphicslinearlayout.cpp b/src/gui/graphicsview/qgraphicslinearlayout.cpp
index 5591638..40f9b1d 100644
--- a/src/gui/graphicsview/qgraphicslinearlayout.cpp
+++ b/src/gui/graphicsview/qgraphicslinearlayout.cpp
@@ -275,17 +275,13 @@ void QGraphicsLinearLayout::insertItem(int index, QGraphicsLayoutItem *item)
qWarning("QGraphicsLinearLayout::insertItem: cannot insert itself");
return;
}
- Q_ASSERT(item);
-
- //the order of the following instructions is very important because
- //invalidating the layout before adding the child item will make the layout happen
- //before we try to paint the item
- invalidate();
d->addChildLayoutItem(item);
+ Q_ASSERT(item);
d->fixIndex(&index);
d->engine.insertRow(index, d->orientation);
new QGridLayoutItem(&d->engine, item, d->gridRow(index), d->gridColumn(index), 1, 1, 0, index);
+ invalidate();
}
/*!
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index 675a5c5..141e305 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -354,8 +354,10 @@ void QGraphicsWidget::setGeometry(const QRectF &rect)
newGeom = rect;
newGeom.setSize(rect.size().expandedTo(effectiveSizeHint(Qt::MinimumSize))
.boundedTo(effectiveSizeHint(Qt::MaximumSize)));
- if (newGeom == d->geom)
- return;
+
+ if (newGeom == d->geom) {
+ goto relayoutChildrenAndReturn;
+ }
// setPos triggers ItemPositionChange, which can adjust position
wd->inSetGeometry = 1;
@@ -363,8 +365,9 @@ void QGraphicsWidget::setGeometry(const QRectF &rect)
wd->inSetGeometry = 0;
newGeom.moveTopLeft(pos());
- if (newGeom == d->geom)
- return;
+ if (newGeom == d->geom) {
+ goto relayoutChildrenAndReturn;
+ }
// Update and prepare to change the geometry (remove from index) if the size has changed.
if (wd->scene) {
@@ -375,35 +378,54 @@ void QGraphicsWidget::setGeometry(const QRectF &rect)
}
// Update the layout item geometry
- bool moved = oldPos != pos();
- if (moved) {
- // Send move event.
- QGraphicsSceneMoveEvent event;
- event.setOldPos(oldPos);
- event.setNewPos(pos());
- QApplication::sendEvent(this, &event);
- if (wd->inSetPos) {
- //set the new pos
- d->geom.moveTopLeft(pos());
- emit geometryChanged();
- return;
+ {
+ bool moved = oldPos != pos();
+ if (moved) {
+ // Send move event.
+ QGraphicsSceneMoveEvent event;
+ event.setOldPos(oldPos);
+ event.setNewPos(pos());
+ QApplication::sendEvent(this, &event);
+ if (wd->inSetPos) {
+ //set the new pos
+ d->geom.moveTopLeft(pos());
+ emit geometryChanged();
+ goto relayoutChildrenAndReturn;
+ }
+ }
+ QSizeF oldSize = size();
+ QGraphicsLayoutItem::setGeometry(newGeom);
+ // Send resize event
+ bool resized = newGeom.size() != oldSize;
+ if (resized) {
+ QGraphicsSceneResizeEvent re;
+ re.setOldSize(oldSize);
+ re.setNewSize(newGeom.size());
+ if (oldSize.width() != newGeom.size().width())
+ emit widthChanged();
+ if (oldSize.height() != newGeom.size().height())
+ emit heightChanged();
+ QGraphicsLayout *lay = wd->layout;
+ if (QGraphicsLayout::instantInvalidatePropagation()) {
+ if (!lay || lay->isActivated()) {
+ QApplication::sendEvent(this, &re);
+ }
+ } else {
+ QApplication::sendEvent(this, &re);
+ }
}
}
- QSizeF oldSize = size();
- QGraphicsLayoutItem::setGeometry(newGeom);
- // Send resize event
- bool resized = newGeom.size() != oldSize;
- if (resized) {
- QGraphicsSceneResizeEvent re;
- re.setOldSize(oldSize);
- re.setNewSize(newGeom.size());
- if (oldSize.width() != newGeom.size().width())
- emit widthChanged();
- if (oldSize.height() != newGeom.size().height())
- emit heightChanged();
- QApplication::sendEvent(this, &re);
- }
+
emit geometryChanged();
+relayoutChildrenAndReturn:
+ if (QGraphicsLayout::instantInvalidatePropagation()) {
+ if (QGraphicsLayout *lay = wd->layout) {
+ if (!lay->isActivated()) {
+ QEvent layoutRequest(QEvent::LayoutRequest);
+ QApplication::sendEvent(this, &layoutRequest);
+ }
+ }
+ }
}
/*!
@@ -1052,16 +1074,31 @@ void QGraphicsWidget::updateGeometry()
QGraphicsLayoutItem *parentItem = parentLayoutItem();
if (parentItem && parentItem->isLayout()) {
- parentItem->updateGeometry();
+ if (QGraphicsLayout::instantInvalidatePropagation()) {
+ static_cast<QGraphicsLayout *>(parentItem)->invalidate();
+ } else {
+ parentItem->updateGeometry();
+ }
} else {
if (parentItem) {
+ // This is for custom layouting
QGraphicsWidget *parentWid = parentWidget(); //###
if (parentWid->isVisible())
QApplication::postEvent(parentWid, new QEvent(QEvent::LayoutRequest));
+ } else {
+ /**
+ * If this is the topmost widget, post a LayoutRequest event to the widget.
+ * When the event is received, it will start flowing all the way down to the leaf
+ * widgets in one go. This will make a relayout flicker-free.
+ */
+ if (QGraphicsLayout::instantInvalidatePropagation())
+ QApplication::postEvent(static_cast<QGraphicsWidget *>(this), new QEvent(QEvent::LayoutRequest));
+ }
+ if (!QGraphicsLayout::instantInvalidatePropagation()) {
+ bool wasResized = testAttribute(Qt::WA_Resized);
+ resize(size()); // this will restrict the size
+ setAttribute(Qt::WA_Resized, wasResized);
}
- bool wasResized = testAttribute(Qt::WA_Resized);
- resize(size()); // this will restrict the size
- setAttribute(Qt::WA_Resized, wasResized);
}
}
diff --git a/tests/auto/q3combobox/tst_q3combobox.cpp b/tests/auto/q3combobox/tst_q3combobox.cpp
index 17bd861..825acb2 100644
--- a/tests/auto/q3combobox/tst_q3combobox.cpp
+++ b/tests/auto/q3combobox/tst_q3combobox.cpp
@@ -1004,6 +1004,10 @@ void tst_Q3ComboBox::wheelEvent()
void tst_Q3ComboBox::task231724_clear()
{
+#ifdef Q_WS_MACX
+ return; // On Mac, we don't use a ListBox for the popup
+#endif
+
Q3ComboBox box;
for ( int i = 0; i <50; i++ ) {
diff --git a/tests/auto/q3progressbar/tst_q3progressbar.cpp b/tests/auto/q3progressbar/tst_q3progressbar.cpp
index 745e2d5..3a0c3e2 100644
--- a/tests/auto/q3progressbar/tst_q3progressbar.cpp
+++ b/tests/auto/q3progressbar/tst_q3progressbar.cpp
@@ -45,6 +45,7 @@
#include <qapplication.h>
#include <qdebug.h>
#include <q3progressbar.h>
+#include "../../shared/util.h"
//TESTED_CLASS=
//TESTED_FILES=
@@ -106,7 +107,7 @@ void tst_Q3ProgressBar::setProgress()
{
MyCustomProgressBar * m_progressBar = new MyCustomProgressBar();
m_progressBar->show();
- QApplication::processEvents();
+ QTest::qWaitForWindowShown(m_progressBar);
//case with total steps = 0
m_progressBar->setTotalSteps(0);
@@ -114,10 +115,9 @@ void tst_Q3ProgressBar::setProgress()
m_progressBar->paintNumber = 0;
m_progressBar->setProgress(m_progressBar->progress() + 1);
QCOMPARE(oldValue + 1,m_progressBar->progress());
- QApplication::processEvents();
// It might be > 1 because it is animated.
- QVERIFY(m_progressBar->paintNumber >= 1);
+ QTRY_VERIFY(m_progressBar->paintNumber >= 1);
qDebug() << "Animation test: paintNumber =" << m_progressBar->paintNumber;
//standard case
@@ -125,10 +125,9 @@ void tst_Q3ProgressBar::setProgress()
m_progressBar->setProgress(0);
m_progressBar->paintNumber = 0;
m_progressBar->setProgress(m_progressBar->progress() + 1);
- QApplication::processEvents();
// It might be > 1 because other events might cause painting.
- QVERIFY(m_progressBar->paintNumber >= 1);
+ QTRY_VERIFY(m_progressBar->paintNumber >= 1);
qDebug() << "Standard test: paintNumber =" << m_progressBar->paintNumber;
}
diff --git a/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp b/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
index e7c63d5..447385a 100644
--- a/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
+++ b/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
@@ -1091,6 +1091,9 @@ void tst_QGraphicsAnchorLayout::setSpacing()
#ifdef Q_WS_MAC
QTest::qWait(200);
#endif
+
+ // 21x21
+ QCOMPARE(p->size(), QSizeF(41, 41));
QCOMPARE(a->geometry(), QRectF(0, 0, 20, 20));
QCOMPARE(b->geometry(), QRectF(21, 0, 20, 20));
QCOMPARE(c->geometry(), QRectF(0, 21, 41, 20));
diff --git a/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp b/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp
index 979f03d..29ea074 100644
--- a/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp
+++ b/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp
@@ -62,6 +62,7 @@ private slots:
void compressLayoutRequest();
void automaticReparenting();
void verifyActivate();
+ void invalidate();
void constructors();
void alternativeLayoutItems();
void ownership();
@@ -95,6 +96,14 @@ void tst_QGraphicsLayout::sizeHints()
}
+enum FunctionType {
+ SetGeometry = 0,
+ Invalidate,
+ NumFunctionTypes
+};
+
+
+
class TestGraphicsWidget : public QGraphicsWidget {
public:
TestGraphicsWidget(QGraphicsWidget *parent = 0) : QGraphicsWidget(parent)
@@ -108,9 +117,28 @@ public:
int eventCount(QEvent::Type type) {
return m_eventCount.value(int(type));
}
+
void clearEventCount() {
m_eventCount.clear();
}
+
+ void clearCounters() {
+ m_eventCount.clear();
+ functionCount.clear();
+ }
+
+ void setGeometry(const QRectF &rect)
+ {
+ QGraphicsWidget::setGeometry(rect);
+ ++(functionCount[SetGeometry]);
+ }
+
+ void callUpdateGeometry()
+ {
+ // updateGeometry() is protected
+ QGraphicsWidget::updateGeometry();
+ }
+ QMap<FunctionType, int> functionCount;
private:
QMap<int, int> m_eventCount;
};
@@ -122,6 +150,8 @@ void tst_QGraphicsLayout::compressLayoutRequest()
TestGraphicsWidget *tw = new TestGraphicsWidget();
scene.addItem(tw);
view.show();
+
+ QTest::qWaitForWindowShown(&view);
QGraphicsLinearLayout *lout = new QGraphicsLinearLayout(tw);
for (int i = 0; i < 4; ++i) {
QGraphicsWidget *gw = new QGraphicsWidget(tw);
@@ -217,17 +247,27 @@ class TestLayout : public QGraphicsLinearLayout
TestLayout(QGraphicsLayoutItem *parent = 0)
: QGraphicsLinearLayout(parent)
{
- m_count = 0;
+ setContentsMargins(0,0,0,0);
+ setSpacing(0);
}
- void setGeometry(const QRectF &rect) {
-
- ++m_count;
+ void setGeometry(const QRectF &rect)
+ {
+ ++(functionCount[SetGeometry]);
QGraphicsLinearLayout::setGeometry(rect);
}
+ void invalidate()
+ {
+ ++(functionCount[Invalidate]);
+ QGraphicsLinearLayout::invalidate();
+ }
+
+ void clearCounters() {
+ functionCount.clear();
+ }
- int m_count;
+ QMap<FunctionType, int> functionCount;
};
void tst_QGraphicsLayout::verifyActivate()
@@ -242,13 +282,278 @@ void tst_QGraphicsLayout::verifyActivate()
lout->addItem(w);
window->setLayout(lout);
- QCOMPARE(lout->m_count, 0);
+ QCOMPARE(lout->functionCount[SetGeometry], 0);
window->setVisible(false);
- QCOMPARE(lout->m_count, 0);
+ QCOMPARE(lout->functionCount[SetGeometry], 0);
window->setVisible(true);
// on polish or the first time a widget is shown, the widget is resized.
- QCOMPARE(lout->m_count, 1);
+ QCOMPARE(lout->functionCount[SetGeometry], 1);
+
+}
+
+static void clearAllCounters(TestGraphicsWidget *widget)
+{
+ if (!widget)
+ return;
+ widget->clearCounters();
+ TestLayout *layout = static_cast<TestLayout *>(widget->layout());
+ if (layout) {
+ layout->clearCounters();
+ for (int i = layout->count() - 1; i >=0; --i) {
+ QGraphicsLayoutItem *item = layout->itemAt(i);
+ if (item->isLayout()) {
+ // ### Not used ATM
+ //TestLayout *lay = static_cast<TestLayout*>(static_cast<QGraphicsLayout*>(item));
+ //clearAllCounters(lay);
+ } else {
+ TestGraphicsWidget *wid = static_cast<TestGraphicsWidget *>(item);
+ clearAllCounters(wid);
+ }
+ }
+ }
+}
+
+static void activateAndReset(TestGraphicsWidget *widget)
+{
+ QApplication::sendPostedEvents();
+ QApplication::processEvents();
+ if (widget->layout())
+ widget->layout()->activate();
+ clearAllCounters(widget);
+}
+
+
+void tst_QGraphicsLayout::invalidate()
+{
+ QGraphicsLayout::setInstantInvalidatePropagation(true);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ TestGraphicsWidget *a = new TestGraphicsWidget;
+ a->setData(0, QString("a"));
+ scene.addItem(a);
+ TestLayout *alay = new TestLayout(a);
+ TestGraphicsWidget *b = new TestGraphicsWidget;
+ b->setData(0, QString("b"));
+ alay->addItem(b);
+ TestLayout *blay = new TestLayout(b);
+ TestGraphicsWidget *e = new TestGraphicsWidget;
+ e->setData(0, QString("e"));
+ blay->addItem(e);
+
+
+ TestGraphicsWidget *c = new TestGraphicsWidget;
+ c->setData(0, QString("c"));
+ alay->addItem(c);
+ TestLayout *clay = new TestLayout(c);
+ TestGraphicsWidget *f = new TestGraphicsWidget;
+ f->setData(0, QString("f"));
+ clay->addItem(f);
+
+ TestGraphicsWidget *d = new TestGraphicsWidget;
+ d->setData(0, QString("d"));
+ alay->addItem(d);
+ TestLayout *dlay = new TestLayout(d);
+ TestGraphicsWidget *g = new TestGraphicsWidget;
+ g->setData(0, QString("g"));
+ dlay->addItem(g);
+
+ view.show();
+
+ {
+ clearAllCounters(a);
+
+ QCoreApplication::sendPostedEvents();
+ QCoreApplication::processEvents();
+
+ alay->activate();
+ QCOMPARE(alay->isActivated(), true);
+ QCOMPARE(blay->isActivated(), true);
+ QCOMPARE(clay->isActivated(), true);
+ QCOMPARE(dlay->isActivated(), true);
+ }
+
+ {
+ clearAllCounters(a);
+ e->callUpdateGeometry();
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), false);
+ QCOMPARE(clay->isActivated(), true);
+ QCOMPARE(dlay->isActivated(), true);
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+
+ // should only invalidate ascendants of e
+ QCOMPARE(blay->functionCount[Invalidate], 1);
+ QCOMPARE(alay->functionCount[Invalidate], 1);
+ // not siblings
+ QCOMPARE(clay->functionCount[Invalidate], 0);
+ QCOMPARE(dlay->functionCount[Invalidate], 0);
+
+ QApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+ }
+
+ {
+ activateAndReset(a);
+ f->callUpdateGeometry();
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), true);
+ QCOMPARE(clay->isActivated(), false);
+ QCOMPARE(dlay->isActivated(), true);
+
+ QCoreApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+
+ QCOMPARE(a->functionCount[SetGeometry], 1);
+ QCOMPARE(alay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(b->functionCount[SetGeometry], 1);
+ QCOMPARE(c->functionCount[SetGeometry], 1);
+ QCOMPARE(d->functionCount[SetGeometry], 1);
+ // Since nothing really changed, blay and dlay don't need
+ // to be resized.
+ QCOMPARE(blay->functionCount[SetGeometry], 0);
+ QCOMPARE(clay->functionCount[SetGeometry], 1);
+ QCOMPARE(dlay->functionCount[SetGeometry], 0);
+
+ QCOMPARE(f->functionCount[SetGeometry], 1);
+
+ QCOMPARE(a->size(), QSizeF(150, 50));
+ }
+
+ {
+ activateAndReset(a);
+ f->setPreferredSize(QSizeF(60,50));
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), true);
+ QCOMPARE(clay->isActivated(), false);
+ QCOMPARE(dlay->isActivated(), true);
+
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCoreApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+
+ QCOMPARE(a->functionCount[SetGeometry], 1);
+ QCOMPARE(alay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(b->functionCount[SetGeometry], 1);
+ QCOMPARE(c->functionCount[SetGeometry], 1);
+ QCOMPARE(d->functionCount[SetGeometry], 1);
+ // f actually got wider, need to rearrange its siblings
+ QCOMPARE(blay->functionCount[SetGeometry], 1);
+ QCOMPARE(clay->functionCount[SetGeometry], 1);
+ QCOMPARE(dlay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(e->functionCount[SetGeometry], 1);
+ QCOMPARE(f->functionCount[SetGeometry], 1);
+ QCOMPARE(g->functionCount[SetGeometry], 1);
+
+ QVERIFY(e->size().width() < f->size().width());
+ QVERIFY(g->size().width() < f->size().width());
+ }
+
+ {
+ // resize f so much that it'll force a resize of the top widget
+ // this will currently generate two setGeometry() calls on the child layout
+ // of the top widget.
+ activateAndReset(a);
+ f->setPreferredSize(QSizeF());
+ f->setMinimumSize(QSizeF(200,50));
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), true);
+ QCOMPARE(clay->isActivated(), false);
+ QCOMPARE(dlay->isActivated(), true);
+
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCoreApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+
+ QCOMPARE(a->functionCount[SetGeometry], 1);
+
+ /* well, ideally one call to setGeometry(), but it will currently
+ * get two calls to setGeometry():
+ * 1. The first LayoutRequest will call activate() - that will call
+ * setGeometry() on the layout. This geometry will be based on
+ * the widget geometry which is not correct at this moment.
+ * (it is still 150 wide)
+ * 2. Next, we check if the widget is top level, and then we call
+ * parentWidget->resize(parentWidget->size());
+ * This will be adjusted to be minimum 200 pixels wide.
+ * The new size will then be propagated down to the layout
+ *
+ */
+ QCOMPARE(alay->functionCount[SetGeometry], 2);
+
+ QCOMPARE(b->functionCount[SetGeometry], 2);
+ QCOMPARE(c->functionCount[SetGeometry], 2);
+ QCOMPARE(d->functionCount[SetGeometry], 2);
+ // f actually got wider, need to rearrange its siblings
+ QCOMPARE(blay->functionCount[SetGeometry], 1);
+ QCOMPARE(clay->functionCount[SetGeometry], 1);
+ QCOMPARE(dlay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(e->functionCount[SetGeometry], 1);
+ QCOMPARE(f->functionCount[SetGeometry], 1);
+ QCOMPARE(g->functionCount[SetGeometry], 1);
+
+ QVERIFY(e->size().width() < f->size().width());
+ QVERIFY(g->size().width() < f->size().width());
+ }
+
+ {
+ f->setPreferredSize(QSizeF());
+ f->setMinimumSize(QSizeF());
+ a->adjustSize();
+ activateAndReset(a);
+ // update two different leaf widgets,
+ // eventCount and functionCount should never be >= 2
+ e->callUpdateGeometry();
+ g->callUpdateGeometry();
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), false);
+ QCOMPARE(clay->isActivated(), true);
+ QCOMPARE(dlay->isActivated(), false);
+
+ QCoreApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 1);
+
+ QCOMPARE(a->functionCount[SetGeometry], 1);
+ QCOMPARE(alay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(b->functionCount[SetGeometry], 1);
+ QCOMPARE(c->functionCount[SetGeometry], 1);
+ QCOMPARE(d->functionCount[SetGeometry], 1);
+ // f actually got wider, need to rearrange its siblings
+ QCOMPARE(blay->functionCount[SetGeometry], 1);
+ QCOMPARE(clay->functionCount[SetGeometry], 0);
+ QCOMPARE(dlay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(e->functionCount[SetGeometry], 1);
+ QCOMPARE(f->functionCount[SetGeometry], 0);
+ QCOMPARE(g->functionCount[SetGeometry], 1);
+
+ }
+
+ QGraphicsLayout::setInstantInvalidatePropagation(false);
}
class Layout : public QGraphicsLayout
diff --git a/tests/auto/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp b/tests/auto/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp
index 62ba1b4..8f8ac67 100644
--- a/tests/auto/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp
+++ b/tests/auto/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp
@@ -94,6 +94,7 @@ private slots:
void itemSpacing();
void setStretchFactor_data();
void setStretchFactor();
+ void testStretch();
void defaultStretchFactors_data();
void defaultStretchFactors();
void sizeHint_data();
@@ -667,6 +668,10 @@ void tst_QGraphicsLinearLayout::invalidate()
layout.setContentsMargins(0, 0, 0, 0);
view.show();
widget->show();
+ //QTest::qWait(1000);
+ QTest::qWaitForWindowShown(&view);
+ qApp->processEvents();
+ layout.layoutRequest = 0;
layout.setContentsMargins(1, 2, 3, 4);
QApplication::sendPostedEvents(0, 0);
@@ -1130,6 +1135,41 @@ void tst_QGraphicsLinearLayout::setStretchFactor()
delete widget;
}
+void tst_QGraphicsLinearLayout::testStretch()
+{
+ QGraphicsScene scene;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ QGraphicsWidget *form = new QGraphicsWidget(0, Qt::Window);
+
+ scene.addItem(form);
+ form->setMinimumSize(600, 600);
+ form->setMaximumSize(600, 600);
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Horizontal, form);
+ QGraphicsWidget *w1 = new RectWidget;
+ w1->setPreferredSize(100,100);
+ w1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ QGraphicsWidget *w2 = new RectWidget;
+ w2->setPreferredSize(200,200);
+ w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addItem(w1);
+ layout->addStretch(2);
+ layout->addItem(w2);
+ QCOMPARE(layout->count(), 2);
+ QVERIFY(layout->itemAt(0) == w1);
+ QVERIFY(layout->itemAt(1) == w2);
+ layout->activate();
+
+ //view->setSceneRect(-50, -50, 800, 800);
+ //view->show();
+ //QTest::qWaitForWindowShown(view);
+ //QTest::qWait(5000);
+ QCOMPARE(form->geometry().size(), QSizeF(600,600));
+ QCOMPARE(w1->geometry(), QRectF(0, 0, 100, 100));
+ QCOMPARE(w2->geometry(), QRectF(400, 0, 200, 200));
+}
+
void tst_QGraphicsLinearLayout::defaultStretchFactors_data()
{
QTest::addColumn<Qt::Orientation>("orientation");
diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
index e8e2e23..887026c 100644
--- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -186,7 +186,6 @@ private slots:
void task250119_shortcutContext();
void QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems();
void QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems();
- void QT_BUG_13865_doublePaintWhenAddingASubItem();
};
@@ -3367,46 +3366,6 @@ void tst_QGraphicsWidget::QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems()
//This should not crash
}
-
-struct GreenWidget : public QGraphicsWidget
-{
- GreenWidget() : count(0)
- {
- }
-
- void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * )
- {
- count++;
- painter->setPen(Qt::green);
- painter->drawRect(option->rect.adjusted(0,0,-1,-1));
- }
-
- int count;
-};
-
-void tst_QGraphicsWidget::QT_BUG_13865_doublePaintWhenAddingASubItem()
-{
- QGraphicsScene scene;
- QGraphicsView view(&scene);
- QGraphicsWidget *widget = new QGraphicsWidget;
- widget->resize(100, 100);
- scene.addItem(widget);
- QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(widget);
-
- view.show();
- QTest::qWaitForWindowShown(&view);
- QApplication::processEvents();
-
-
- GreenWidget *sub = new GreenWidget;
- layout->addItem(sub);
-
- QTest::qWait(100);
- QCOMPARE(sub->count, 1); //it should only be painted once
-
-}
-
-
QTEST_MAIN(tst_QGraphicsWidget)
#include "tst_qgraphicswidget.moc"
diff --git a/tests/benchmarks/gui/graphicsview/graphicsview.pro b/tests/benchmarks/gui/graphicsview/graphicsview.pro
index e4fed19..1509466 100644
--- a/tests/benchmarks/gui/graphicsview/graphicsview.pro
+++ b/tests/benchmarks/gui/graphicsview/graphicsview.pro
@@ -3,6 +3,7 @@ SUBDIRS = \
functional \
qgraphicsanchorlayout \
qgraphicsitem \
+ qgraphicslayout \
qgraphicsscene \
qgraphicsview \
qgraphicswidget
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicslayout/qgraphicslayout.pro b/tests/benchmarks/gui/graphicsview/qgraphicslayout/qgraphicslayout.pro
new file mode 100644
index 0000000..19e2979
--- /dev/null
+++ b/tests/benchmarks/gui/graphicsview/qgraphicslayout/qgraphicslayout.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+TEMPLATE = app
+TARGET = tst_bench_qgraphicslayout
+
+SOURCES += tst_qgraphicslayout.cpp
+
diff --git a/tests/benchmarks/gui/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp b/tests/benchmarks/gui/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp
new file mode 100644
index 0000000..4bdcfb3
--- /dev/null
+++ b/tests/benchmarks/gui/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtGui/qgraphicslayout.h>
+#include <QtGui/qgraphicslinearlayout.h>
+#include <QtGui/qgraphicswidget.h>
+#include <QtGui/qgraphicsview.h>
+
+class tst_QGraphicsLayout : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QGraphicsLayout() {}
+ ~tst_QGraphicsLayout() {}
+
+private slots:
+ void invalidate();
+};
+
+
+class RectWidget : public QGraphicsWidget
+{
+public:
+ RectWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0) : QGraphicsWidget(parent, wFlags), setGeometryCalls(0) {}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ painter->drawRoundRect(rect());
+ painter->drawLine(rect().topLeft(), rect().bottomRight());
+ painter->drawLine(rect().bottomLeft(), rect().topRight());
+ }
+
+ void setGeometry(const QRectF &rect)
+ {
+ //qDebug() << "setGeometry():" << this->data(0).toString();
+ setGeometryCalls->insert(this, rect);
+ QGraphicsWidget::setGeometry(rect);
+ }
+
+ void callUpdateGeometry() {
+ QGraphicsWidget::updateGeometry();
+ }
+
+ QMap<RectWidget*, QRectF> *setGeometryCalls;
+};
+
+/**
+ * Test to see how much time is needed to resize all widgets in a
+ * layout-widget-layout-widget-.... hierarchy from the point where a
+ * leaf widget changes its size hint. (updateGeometry() is called).
+ *
+ * If you run the test for 4.7 you'll get some really high numbers, but
+ * that's because they also include painting (and possible processing of
+ * some other events).
+ */
+void tst_QGraphicsLayout::invalidate()
+{
+ QGraphicsLayout::setInstantInvalidatePropagation(true);
+ QGraphicsScene scene;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ QMap<RectWidget*, QRectF> setGeometryCalls;
+
+ RectWidget *window = new RectWidget(0, Qt::Window);
+ window->setGeometryCalls = &setGeometryCalls;
+ window->setData(0, QString(QChar('a')));
+
+ scene.addItem(window);
+ RectWidget *leaf = 0;
+ const int depth = 100;
+ RectWidget *parent = window;
+ for (int i = 1; i < depth; ++i) {
+ QGraphicsLinearLayout *l = new QGraphicsLinearLayout(parent);
+ l->setContentsMargins(0,0,0,0);
+ RectWidget *child = new RectWidget;
+ child->setData(0, QString(QChar('a' + i)));
+ child->setGeometryCalls = &setGeometryCalls;
+ l->addItem(child);
+ parent = child;
+ }
+ leaf = parent;
+ leaf->setMinimumSize(QSizeF(1,1));
+
+ view->show();
+
+ QTest::qWaitForWindowShown(view);
+
+ // ...then measure...
+
+ int pass = 1;
+
+ // should be as small as possible, to reduce overhead of painting
+ QSizeF size(1, 1);
+ setGeometryCalls.clear();
+ QBENCHMARK {
+ leaf->setMinimumSize(size);
+ leaf->setMaximumSize(size);
+ while (setGeometryCalls.count() < depth) {
+ QApplication::sendPostedEvents();
+ }
+ // force a resize on each widget, this will ensure
+ // that each iteration will resize all 50 widgets
+ int w = int(size.width());
+ w^=2;
+ size.setWidth(w);
+ }
+ delete view;
+ QGraphicsLayout::setInstantInvalidatePropagation(false);
+}
+
+QTEST_MAIN(tst_QGraphicsLayout)
+
+#include "tst_qgraphicslayout.moc"
diff --git a/tests/manual/qgraphicslayout/flicker/flicker.pro b/tests/manual/qgraphicslayout/flicker/flicker.pro
new file mode 100644
index 0000000..323a30f
--- /dev/null
+++ b/tests/manual/qgraphicslayout/flicker/flicker.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+HEADERS += window.h
+SOURCES += main.cpp window.cpp
diff --git a/tests/manual/qgraphicslayout/flicker/main.cpp b/tests/manual/qgraphicslayout/flicker/main.cpp
new file mode 100644
index 0000000..7e75c2b
--- /dev/null
+++ b/tests/manual/qgraphicslayout/flicker/main.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#include <windows.h>
+#include "window.h"
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ Window *window = new Window();
+ window->resize(800, 600);
+
+ window->show();
+
+ return app.exec();
+
+}
diff --git a/tests/manual/qgraphicslayout/flicker/window.cpp b/tests/manual/qgraphicslayout/flicker/window.cpp
new file mode 100644
index 0000000..ee4db3f
--- /dev/null
+++ b/tests/manual/qgraphicslayout/flicker/window.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "window.h"
+
+void SlowWidget::setGeometry(const QRectF &rect)
+{
+ bool reiterate = false;
+ Statistics &stats = *m_stats;
+ if (stats.relayoutClicked) {
+ ++(stats.setGeometryTracker[this]);
+ ++stats.setGeometryCount;
+ qDebug() << "setGeometryCount:" << stats.setGeometryCount;
+ if (stats.setGeometryTracker.count() == m_window->m_depthSpinBox->value()) {
+ ++stats.currentBenchmarkIteration;
+ qDebug() << "currentBenchmarkIteration:" << stats.currentBenchmarkIteration;
+ if (stats.currentBenchmarkIteration == m_window->m_benchmarkIterationsSpinBox->value()) {
+ if (stats.output)
+ stats.output->setText(tr("DONE. Elapsed: %1, setGeometryCount: %2").arg(stats.time.elapsed()).arg(stats.setGeometryCount));
+ } else {
+ reiterate = true;
+ }
+ stats.setGeometryTracker.clear();
+
+ }
+ }
+
+ QGraphicsWidget::setGeometry(rect);
+
+ if (reiterate) {
+ m_window->doAgain();
+ //QTimer::singleShot(0, m_window, SLOT(doAgain()));
+ }
+}
+
diff --git a/tests/manual/qgraphicslayout/flicker/window.h b/tests/manual/qgraphicslayout/flicker/window.h
new file mode 100644
index 0000000..b4c42c0
--- /dev/null
+++ b/tests/manual/qgraphicslayout/flicker/window.h
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WINDOW_H
+#define WINDOW_H
+
+
+#include <QtGui>
+
+static void qSleep(int msec)
+{
+
+ struct Thread : public QThread
+ {
+ static void wait(int msec)
+ {
+ QThread::msleep(msec);
+ }
+ };
+ Thread::wait(msec);
+}
+
+struct Statistics {
+ Statistics() : output(0),
+ setGeometryCount(0), currentBenchmarkIteration(0), relayoutClicked(false), sleepMsecs(0)
+ {
+ }
+ QMap<QGraphicsWidget*, int> setGeometryTracker;
+ QTime time;
+ int setGeometryCount;
+ int sleepMsecs;
+ QLabel *output;
+ void sleep()
+ {
+ qSleep(sleepMsecs);
+ }
+ int currentBenchmarkIteration;
+ bool relayoutClicked;
+
+};
+
+
+class Window;
+
+class SlowWidget : public QGraphicsWidget {
+public:
+ SlowWidget(QGraphicsWidget *w = 0, Qt::WindowFlags wFlags = 0) : QGraphicsWidget(w, wFlags)
+ {
+ m_window = 0;
+ }
+
+ void setStats(Statistics *stats)
+ {
+ m_stats = stats;
+ }
+
+ void setWindow(Window *window)
+ {
+ m_window = window;
+ }
+
+ void setGeometry(const QRectF &rect);
+
+ bool event(QEvent *e)
+ {
+ if (e->type() == QEvent::LayoutRequest) {
+ if (m_stats->sleepMsecs > 0) {
+ m_stats->sleep();
+ qDebug("sleep %d ms\n", m_stats->sleepMsecs);
+ }
+ }
+ return QGraphicsWidget::event(e);
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ painter->setBrush(m_brush);
+ painter->drawRoundRect(rect());
+ painter->drawLine(rect().topLeft(), rect().bottomRight());
+ painter->drawLine(rect().bottomLeft(), rect().topRight());
+ }
+
+ void setBrush(const QBrush &brush)
+ {
+ m_brush = brush;
+ }
+private:
+ QBrush m_brush;
+ Statistics *m_stats;
+ Window *m_window;
+};
+
+class Window : public QWidget {
+ Q_OBJECT
+public:
+ Window() : QWidget()
+ {
+ QGraphicsView *m_view = new QGraphicsView(&scene);
+
+ m_window = 0;
+ m_leaf = 0;
+
+ m_button = new QPushButton(tr("Relayout"));
+ m_button->setObjectName("button");
+
+ m_sleepLabel = new QLabel(tr("Sleep:"));
+ m_sleepSpinBox = new QSpinBox;
+ m_sleepSpinBox->setRange(0, 1000);
+ m_sleepSpinBox->setSingleStep(10);
+
+ m_depthLabel = new QLabel(tr("Depth:"));
+ m_depthSpinBox = new QSpinBox;
+ m_depthSpinBox->setObjectName("depthSpinBox");
+ m_depthSpinBox->setRange(1, 200);
+ m_depthSpinBox->setSingleStep(5);
+
+ m_benchmarkIterationsLabel = new QLabel(tr("Benchmark iterations"));
+ m_benchmarkIterationsSpinBox = new QSpinBox;
+ m_benchmarkIterationsSpinBox->setObjectName("benchmarkIterationsSpinBox");
+ m_benchmarkIterationsSpinBox->setRange(1, 1000);
+ m_benchmarkIterationsSpinBox->setValue(41);
+ m_benchmarkIterationsSpinBox->setSingleStep(10);
+
+ m_instantCheckBox = new QCheckBox(tr("Instant propagation"));
+ m_instantCheckBox->setObjectName("instantPropagationCheckbox");
+ QGraphicsLayout::setInstantInvalidatePropagation(true);
+ m_instantCheckBox->setChecked(QGraphicsLayout::instantInvalidatePropagation());
+
+ m_resultLabel = new QLabel(tr("Press relayout to start test"));
+
+ QHBoxLayout *hbox = new QHBoxLayout;
+ hbox->addWidget(m_sleepLabel);
+ hbox->addWidget(m_sleepSpinBox);
+ hbox->addWidget(m_depthLabel);
+ hbox->addWidget(m_depthSpinBox);
+ hbox->addWidget(m_benchmarkIterationsLabel);
+ hbox->addWidget(m_benchmarkIterationsSpinBox);
+ hbox->addWidget(m_instantCheckBox);
+ hbox->addWidget(m_resultLabel);
+ hbox->addStretch();
+ hbox->addWidget(m_button);
+
+ QVBoxLayout *vbox = new QVBoxLayout;
+ vbox->addWidget(m_view);
+ vbox->addLayout(hbox);
+ setLayout(vbox);
+
+ metaObject()->connectSlotsByName(this);
+
+ m_depthSpinBox->setValue(20); // triggers purposedly on_depthSpinBox_valueChanged
+ }
+
+private slots:
+ void on_depthSpinBox_valueChanged(int value)
+ {
+ m_stats.relayoutClicked = false;
+ if (m_window) {
+ QApplication::processEvents();
+ delete m_window;
+ }
+ m_window = new SlowWidget(0, Qt::Window);
+ m_window->setStats(&m_stats);
+ m_window->setWindow(this);
+ QColor col(Qt::black);
+ m_window->setBrush(col);
+ scene.addItem(m_window);
+ m_leaf = 0;
+ const int depth = value;
+ SlowWidget *parent = m_window;
+ for (int i = 1; i < depth; ++i) {
+ QGraphicsLinearLayout *l = new QGraphicsLinearLayout(parent);
+ l->setContentsMargins(2,2,2,2);
+ SlowWidget *child = new SlowWidget;
+ QColor col;
+ col.setHsl(0, 0, 255*i/(depth - 1));
+ child->setBrush(col);
+ child->setStats(&m_stats);
+ child->setWindow(this);
+ l->addItem(child);
+ parent = child;
+ }
+ m_leaf = parent;
+ }
+
+ void on_button_clicked(bool /*check = false*/)
+ {
+ m_stats.relayoutClicked = true;
+ if (m_leaf) {
+ QSizeF sz = m_leaf->size();
+ int w = int(sz.width());
+ w^=16;
+ sz = QSizeF(w,w);
+ m_stats.output = m_resultLabel;
+ m_stats.output->setText(QString("wait..."));
+ m_stats.setGeometryCount = 0;
+ m_stats.setGeometryTracker.clear();
+ m_stats.sleepMsecs = m_sleepSpinBox->value();
+ m_stats.time.start();
+ m_stats.currentBenchmarkIteration = 0;
+ m_leaf->setMinimumSize(sz);
+ m_leaf->setMaximumSize(sz);
+ }
+ }
+
+ void on_instantPropagationCheckbox_toggled(bool checked)
+ {
+ QGraphicsLayout::setInstantInvalidatePropagation(checked);
+ }
+
+public slots:
+ void doAgain()
+ {
+ if (m_leaf) {
+ QSizeF sz = m_leaf->size();
+ int w = int(sz.width());
+ w^=16;
+ sz = QSizeF(w,w);
+ m_leaf->setMinimumSize(sz);
+ m_leaf->setMaximumSize(sz);
+ }
+ }
+
+private:
+public:
+ QGraphicsScene scene;
+ QGraphicsView *m_view;
+ QPushButton *m_button;
+ QLabel *m_sleepLabel;
+ QSpinBox *m_sleepSpinBox;
+ QLabel *m_depthLabel;
+ QSpinBox *m_depthSpinBox;
+ QLabel *m_benchmarkIterationsLabel;
+ QSpinBox *m_benchmarkIterationsSpinBox;
+ QCheckBox *m_instantCheckBox;
+ QLabel *m_resultLabel;
+ QGraphicsWidget *m_leaf;
+ SlowWidget *m_window;
+ Statistics m_stats;
+
+
+};
+
+
+#endif //WINDOW_H