summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets/kernel
diff options
context:
space:
mode:
authorJo Asplin <jo.asplin@nokia.com>2011-10-20 13:17:26 +0200
committerQt by Nokia <qt-info@nokia.com>2011-10-20 19:45:41 +0200
commit9f1aa866bda7678261f2f441d4cfd5bb524c2411 (patch)
tree5028f578122e7feb9200d571405494c73d96db89 /tests/auto/widgets/kernel
parent78d02e93aca5325fc5be9bfd275862795207abaa (diff)
Moved tests into integrationtests/ and widgets/
Task-number: QTBUG-19013 Change-Id: Ibb776f5967c0645ce6d22ef7afdc40657c575461 Reviewed-by: Holger Ihrig <holger.ihrig@nokia.com>
Diffstat (limited to 'tests/auto/widgets/kernel')
-rw-r--r--tests/auto/widgets/kernel/kernel.pro17
-rw-r--r--tests/auto/widgets/kernel/qaction/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qaction/qaction.pro5
-rw-r--r--tests/auto/widgets/kernel/qaction/tst_qaction.cpp373
-rw-r--r--tests/auto/widgets/kernel/qactiongroup/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qactiongroup/qactiongroup.pro5
-rw-r--r--tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp247
-rw-r--r--tests/auto/widgets/kernel/qapplication/.gitignore3
-rw-r--r--tests/auto/widgets/kernel/qapplication/desktopsettingsaware/desktopsettingsaware.pro14
-rw-r--r--tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp54
-rw-r--r--tests/auto/widgets/kernel/qapplication/heart.svg55
-rw-r--r--tests/auto/widgets/kernel/qapplication/modal/base.cpp62
-rw-r--r--tests/auto/widgets/kernel/qapplication/modal/base.h64
-rw-r--r--tests/auto/widgets/kernel/qapplication/modal/main.cpp54
-rw-r--r--tests/auto/widgets/kernel/qapplication/modal/modal.pro9
-rw-r--r--tests/auto/widgets/kernel/qapplication/qapplication.pro7
-rw-r--r--tests/auto/widgets/kernel/qapplication/test/test.pro27
-rw-r--r--tests/auto/widgets/kernel/qapplication/tmp/README3
-rw-r--r--tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp2107
-rw-r--r--tests/auto/widgets/kernel/qapplication/wincmdline/main.cpp53
-rw-r--r--tests/auto/widgets/kernel/qapplication/wincmdline/wincmdline.pro8
-rw-r--r--tests/auto/widgets/kernel/qboxlayout/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qboxlayout/qboxlayout.pro5
-rw-r--r--tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp280
-rw-r--r--tests/auto/widgets/kernel/qdesktopwidget/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qdesktopwidget/qdesktopwidget.pro3
-rw-r--r--tests/auto/widgets/kernel/qdesktopwidget/tst_qdesktopwidget.cpp187
-rw-r--r--tests/auto/widgets/kernel/qformlayout/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qformlayout/qformlayout.pro3
-rw-r--r--tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp913
-rw-r--r--tests/auto/widgets/kernel/qgridlayout/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qgridlayout/qgridlayout.pro10
-rw-r--r--tests/auto/widgets/kernel/qgridlayout/sortdialog.ui135
-rw-r--r--tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp1646
-rw-r--r--tests/auto/widgets/kernel/qinputcontext/qinputcontext.pro7
-rw-r--r--tests/auto/widgets/kernel/qinputcontext/tst_qinputcontext.cpp398
-rw-r--r--tests/auto/widgets/kernel/qlayout/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qlayout/baseline/smartmaxsize1792
-rw-r--r--tests/auto/widgets/kernel/qlayout/qlayout.pro16
-rw-r--r--tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp345
-rw-r--r--tests/auto/widgets/kernel/qsound/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qsound/4.wavbin0 -> 5538 bytes
-rw-r--r--tests/auto/widgets/kernel/qsound/qsound.pro10
-rw-r--r--tests/auto/widgets/kernel/qsound/tst_qsound.cpp88
-rw-r--r--tests/auto/widgets/kernel/qstackedlayout/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qstackedlayout/qstackedlayout.pro6
-rw-r--r--tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp372
-rw-r--r--tests/auto/widgets/kernel/qtooltip/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qtooltip/qtooltip.pro5
-rw-r--r--tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp186
-rw-r--r--tests/auto/widgets/kernel/qwidget/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qwidget/geometry-fullscreen.datbin0 -> 46 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/geometry-maximized.datbin0 -> 46 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/geometry.datbin0 -> 46 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/qwidget.pro23
-rw-r--r--tests/auto/widgets/kernel/qwidget/qwidget.qrc7
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data0.qsnapbin0 -> 722 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data1.qsnapbin0 -> 1509 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data2.qsnapbin0 -> 7965 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data3.qsnapbin0 -> 8265 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data0.qsnapbin0 -> 710 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data1.qsnapbin0 -> 1497 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data2.qsnapbin0 -> 7953 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data3.qsnapbin0 -> 8253 bytes
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp9472
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.h52
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.mm83
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro8
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp326
-rw-r--r--tests/auto/widgets/kernel/qwidgetaction/.gitignore1
-rw-r--r--tests/auto/widgets/kernel/qwidgetaction/qwidgetaction.pro5
-rw-r--r--tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp405
73 files changed, 19968 insertions, 0 deletions
diff --git a/tests/auto/widgets/kernel/kernel.pro b/tests/auto/widgets/kernel/kernel.pro
new file mode 100644
index 0000000000..2e55f8eba2
--- /dev/null
+++ b/tests/auto/widgets/kernel/kernel.pro
@@ -0,0 +1,17 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qaction \
+ qactiongroup \
+ qapplication \
+ qboxlayout \
+ qdesktopwidget \
+ qformlayout \
+ qgridlayout \
+ qinputcontext \
+ qlayout \
+ qsound \
+ qstackedlayout \
+ qtooltip \
+ qwidget \
+ qwidget_window \
+ qwidgetaction \
diff --git a/tests/auto/widgets/kernel/qaction/.gitignore b/tests/auto/widgets/kernel/qaction/.gitignore
new file mode 100644
index 0000000000..bf81f5bf2c
--- /dev/null
+++ b/tests/auto/widgets/kernel/qaction/.gitignore
@@ -0,0 +1 @@
+tst_qaction
diff --git a/tests/auto/widgets/kernel/qaction/qaction.pro b/tests/auto/widgets/kernel/qaction/qaction.pro
new file mode 100644
index 0000000000..9c3648d52f
--- /dev/null
+++ b/tests/auto/widgets/kernel/qaction/qaction.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qaction.cpp
+
+
diff --git a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
new file mode 100644
index 0000000000..637ec144d2
--- /dev/null
+++ b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
@@ -0,0 +1,373 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qapplication.h>
+#include <qevent.h>
+#include <qaction.h>
+#include <qmenu.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QAction : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QAction();
+ virtual ~tst_QAction();
+
+
+ void updateState(QActionEvent *e);
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+private slots:
+ void getSetCheck();
+ void setText_data();
+ void setText();
+ void setIconText_data() { setText_data(); }
+ void setIconText();
+ void actionEvent();
+ void setStandardKeys();
+ void alternateShortcuts();
+ void enabledVisibleInteraction();
+ void task200823_tooltip();
+ void task229128TriggeredSignalWithoutActiongroup();
+ void task229128TriggeredSignalWhenInActiongroup();
+
+private:
+ int m_lastEventType;
+ QAction *m_lastAction;
+ QWidget *m_tstWidget;
+};
+
+// Testing get/set functions
+void tst_QAction::getSetCheck()
+{
+ QAction obj1(0);
+ // QActionGroup * QAction::actionGroup()
+ // void QAction::setActionGroup(QActionGroup *)
+ QActionGroup *var1 = new QActionGroup(0);
+ obj1.setActionGroup(var1);
+ QCOMPARE(var1, obj1.actionGroup());
+ obj1.setActionGroup((QActionGroup *)0);
+ QCOMPARE((QActionGroup *)0, obj1.actionGroup());
+ delete var1;
+
+ // QMenu * QAction::menu()
+ // void QAction::setMenu(QMenu *)
+ QMenu *var2 = new QMenu(0);
+ obj1.setMenu(var2);
+ QCOMPARE(var2, obj1.menu());
+ obj1.setMenu((QMenu *)0);
+ QCOMPARE((QMenu *)0, obj1.menu());
+ delete var2;
+
+ QCOMPARE(obj1.priority(), QAction::NormalPriority);
+ obj1.setPriority(QAction::LowPriority);
+ QCOMPARE(obj1.priority(), QAction::LowPriority);
+}
+
+class MyWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ MyWidget(tst_QAction *tst, QWidget *parent = 0) : QWidget(parent) { this->tst = tst; }
+
+protected:
+ virtual void actionEvent(QActionEvent *e) { tst->updateState(e); }
+
+private:
+ tst_QAction *tst;
+};
+
+tst_QAction::tst_QAction()
+{
+}
+
+tst_QAction::~tst_QAction()
+{
+
+}
+
+void tst_QAction::initTestCase()
+{
+ m_lastEventType = 0;
+ m_lastAction = 0;
+
+ MyWidget *mw = new MyWidget(this);
+ m_tstWidget = mw;
+ mw->show();
+ qApp->setActiveWindow(mw);
+}
+
+void tst_QAction::cleanupTestCase()
+{
+ QWidget *testWidget = m_tstWidget;
+ if (testWidget) {
+ testWidget->hide();
+ delete testWidget;
+ }
+}
+
+void tst_QAction::setText_data()
+{
+ QTest::addColumn<QString>("text");
+ QTest::addColumn<QString>("iconText");
+ QTest::addColumn<QString>("textFromIconText");
+
+ //next we fill it with data
+ QTest::newRow("Normal") << "Action" << "Action" << "Action";
+ QTest::newRow("Ampersand") << "Search && Destroy" << "Search & Destroy" << "Search && Destroy";
+ QTest::newRow("Mnemonic and ellipsis") << "O&pen File ..." << "Open File" << "Open File";
+}
+
+void tst_QAction::setText()
+{
+ QFETCH(QString, text);
+
+ QAction action(0);
+ action.setText(text);
+
+ QCOMPARE(action.text(), text);
+
+ QFETCH(QString, iconText);
+ QCOMPARE(action.iconText(), iconText);
+}
+
+void tst_QAction::setIconText()
+{
+ QFETCH(QString, iconText);
+
+ QAction action(0);
+ action.setIconText(iconText);
+ QCOMPARE(action.iconText(), iconText);
+
+ QFETCH(QString, textFromIconText);
+ QCOMPARE(action.text(), textFromIconText);
+}
+
+
+void tst_QAction::updateState(QActionEvent *e)
+{
+ if (!e) {
+ m_lastEventType = 0;
+ m_lastAction = 0;
+ } else {
+ m_lastEventType = (int)e->type();
+ m_lastAction = e->action();
+ }
+}
+
+void tst_QAction::actionEvent()
+{
+ QAction a(0);
+ a.setText("action text");
+
+ // add action
+ m_tstWidget->addAction(&a);
+ qApp->processEvents();
+
+ QCOMPARE(m_lastEventType, (int)QEvent::ActionAdded);
+ QCOMPARE(m_lastAction, &a);
+
+ // change action
+ a.setText("new action text");
+ qApp->processEvents();
+
+ QCOMPARE(m_lastEventType, (int)QEvent::ActionChanged);
+ QCOMPARE(m_lastAction, &a);
+
+ // remove action
+ m_tstWidget->removeAction(&a);
+ qApp->processEvents();
+
+ QCOMPARE(m_lastEventType, (int)QEvent::ActionRemoved);
+ QCOMPARE(m_lastAction, &a);
+}
+
+//basic testing of standard keys
+void tst_QAction::setStandardKeys()
+{
+ QAction act(0);
+ act.setShortcut(QKeySequence("CTRL+L"));
+ QList<QKeySequence> list;
+ act.setShortcuts(list);
+ act.setShortcuts(QKeySequence::Copy);
+ QVERIFY(act.shortcut() == act.shortcuts().first());
+
+ QList<QKeySequence> expected;
+#if defined(Q_WS_MAC)
+ expected << QKeySequence("CTRL+C");
+#elif defined(Q_WS_WIN) || defined(Q_WS_QWS) || defined(Q_WS_QPA)
+ expected << QKeySequence("CTRL+C") << QKeySequence("CTRL+INSERT");
+#else
+ expected << QKeySequence("CTRL+C") << QKeySequence("F16") << QKeySequence("CTRL+INSERT");
+#endif
+ QVERIFY(act.shortcuts() == expected);
+}
+
+
+void tst_QAction::alternateShortcuts()
+{
+ //test the alternate shortcuts (by adding more than 1 shortcut)
+
+ QWidget *wid = m_tstWidget;
+
+ {
+ QAction act(wid);
+ wid->addAction(&act);
+ QList<QKeySequence> shlist = QList<QKeySequence>() << QKeySequence("CTRL+P") << QKeySequence("CTRL+A");
+ act.setShortcuts(shlist);
+
+ QSignalSpy spy(&act, SIGNAL(triggered()));
+
+ act.setAutoRepeat(true);
+ QTest::keyClick(wid, Qt::Key_A, Qt::ControlModifier);
+ QCOMPARE(spy.count(), 1); //act should have been triggered
+
+ act.setAutoRepeat(false);
+ QTest::keyClick(wid, Qt::Key_A, Qt::ControlModifier);
+ QCOMPARE(spy.count(), 2); //act should have been triggered a 2nd time
+
+ //end of the scope of the action, it will be destroyed and removed from wid
+ //This action should also unregister its shortcuts
+ }
+
+
+ //this tests a crash (if the action did not unregister its alternate shortcuts)
+ QTest::keyClick(wid, Qt::Key_A, Qt::ControlModifier);
+}
+
+void tst_QAction::enabledVisibleInteraction()
+{
+ QAction act(0);
+ // check defaults
+ QVERIFY(act.isEnabled());
+ QVERIFY(act.isVisible());
+
+ // !visible => !enabled
+ act.setVisible(false);
+ QVERIFY(!act.isEnabled());
+ act.setVisible(true);
+ QVERIFY(act.isEnabled());
+ act.setEnabled(false);
+ QVERIFY(act.isVisible());
+
+ // check if shortcut is disabled if not visible
+ m_tstWidget->addAction(&act);
+ act.setShortcut(QKeySequence("Ctrl+T"));
+ QSignalSpy spy(&act, SIGNAL(triggered()));
+ act.setEnabled(true);
+ act.setVisible(false);
+ QTest::keyClick(m_tstWidget, Qt::Key_T, Qt::ControlModifier);
+ QCOMPARE(spy.count(), 0); //act is not visible, so don't trigger
+ act.setVisible(false);
+ act.setEnabled(true);
+ QTest::keyClick(m_tstWidget, Qt::Key_T, Qt::ControlModifier);
+ QCOMPARE(spy.count(), 0); //act is not visible, so don't trigger
+ act.setVisible(true);
+ act.setEnabled(true);
+ QTest::keyClick(m_tstWidget, Qt::Key_T, Qt::ControlModifier);
+ QCOMPARE(spy.count(), 1); //act is visible and enabled, so trigger
+}
+
+void tst_QAction::task200823_tooltip()
+{
+ QAction *action = new QAction("foo", 0);
+ QString shortcut("ctrl+o");
+ action->setShortcut(shortcut);
+
+ // we want a non-standard tooltip that shows the shortcut
+ action->setToolTip(QString("%1 (%2)").arg(action->text()).arg(action->shortcut().toString()));
+
+ QString ref = QString("foo (%1)").arg(QKeySequence(shortcut).toString());
+ QCOMPARE(action->toolTip(), ref);
+}
+
+void tst_QAction::task229128TriggeredSignalWithoutActiongroup()
+{
+ // test without a group
+ QAction *actionWithoutGroup = new QAction("Test", qApp);
+ QSignalSpy spyWithoutGroup(actionWithoutGroup, SIGNAL(triggered(bool)));
+ QCOMPARE(spyWithoutGroup.count(), 0);
+ actionWithoutGroup->trigger();
+ // signal should be emitted
+ QCOMPARE(spyWithoutGroup.count(), 1);
+
+ // it is now a checkable checked action
+ actionWithoutGroup->setCheckable(true);
+ actionWithoutGroup->setChecked(true);
+ spyWithoutGroup.clear();
+ QCOMPARE(spyWithoutGroup.count(), 0);
+ actionWithoutGroup->trigger();
+ // signal should be emitted
+ QCOMPARE(spyWithoutGroup.count(), 1);
+}
+
+void tst_QAction::task229128TriggeredSignalWhenInActiongroup()
+{
+ QActionGroup ag(0);
+ QAction *action = new QAction("Test", &ag);
+ QAction *checkedAction = new QAction("Test 2", &ag);
+ ag.addAction(action);
+ action->setCheckable(true);
+ ag.addAction(checkedAction);
+ checkedAction->setCheckable(true);
+ checkedAction->setChecked(true);
+
+ QSignalSpy actionSpy(checkedAction, SIGNAL(triggered(bool)));
+ QSignalSpy actionGroupSpy(&ag, SIGNAL(triggered(QAction *)));
+ QCOMPARE(actionGroupSpy.count(), 0);
+ QCOMPARE(actionSpy.count(), 0);
+ checkedAction->trigger();
+ // check that both the group and the action have emitted the signal
+ QCOMPARE(actionGroupSpy.count(), 1);
+ QCOMPARE(actionSpy.count(), 1);
+}
+
+QTEST_MAIN(tst_QAction)
+#include "tst_qaction.moc"
diff --git a/tests/auto/widgets/kernel/qactiongroup/.gitignore b/tests/auto/widgets/kernel/qactiongroup/.gitignore
new file mode 100644
index 0000000000..daba003e96
--- /dev/null
+++ b/tests/auto/widgets/kernel/qactiongroup/.gitignore
@@ -0,0 +1 @@
+tst_qactiongroup
diff --git a/tests/auto/widgets/kernel/qactiongroup/qactiongroup.pro b/tests/auto/widgets/kernel/qactiongroup/qactiongroup.pro
new file mode 100644
index 0000000000..9b8636968b
--- /dev/null
+++ b/tests/auto/widgets/kernel/qactiongroup/qactiongroup.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qactiongroup.cpp
+
+
diff --git a/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp b/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
new file mode 100644
index 0000000000..406298807a
--- /dev/null
+++ b/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
@@ -0,0 +1,247 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <qmainwindow.h>
+#include <qmenu.h>
+#include <qaction.h>
+
+class tst_QActionGroup : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void enabledPropagation();
+ void visiblePropagation();
+ void exclusive();
+ void separators();
+ void testActionInTwoQActionGroup();
+ void unCheckCurrentAction();
+};
+
+void tst_QActionGroup::enabledPropagation()
+{
+ QActionGroup testActionGroup( 0 );
+
+ QAction* childAction = new QAction( &testActionGroup );
+ QAction* anotherChildAction = new QAction( &testActionGroup );
+ QAction* freeAction = new QAction(0);
+
+ QVERIFY( testActionGroup.isEnabled() );
+ QVERIFY( childAction->isEnabled() );
+
+ testActionGroup.setEnabled( false );
+ QVERIFY( !testActionGroup.isEnabled() );
+ QVERIFY( !childAction->isEnabled() );
+ QVERIFY( !anotherChildAction->isEnabled() );
+
+ childAction->setEnabled(true);
+ QVERIFY( !childAction->isEnabled());
+
+ anotherChildAction->setEnabled( false );
+
+ testActionGroup.setEnabled( true );
+ QVERIFY( testActionGroup.isEnabled() );
+ QVERIFY( childAction->isEnabled() );
+ QVERIFY( !anotherChildAction->isEnabled() );
+
+ testActionGroup.setEnabled( false );
+ QAction *lastChildAction = new QAction(&testActionGroup);
+
+ QVERIFY(!lastChildAction->isEnabled());
+ testActionGroup.setEnabled( true );
+ QVERIFY(lastChildAction->isEnabled());
+
+ freeAction->setEnabled(false);
+ testActionGroup.addAction(freeAction);
+ QVERIFY(!freeAction->isEnabled());
+ delete freeAction;
+}
+
+void tst_QActionGroup::visiblePropagation()
+{
+ QActionGroup testActionGroup( 0 );
+
+ QAction* childAction = new QAction( &testActionGroup );
+ QAction* anotherChildAction = new QAction( &testActionGroup );
+ QAction* freeAction = new QAction(0);
+
+ QVERIFY( testActionGroup.isVisible() );
+ QVERIFY( childAction->isVisible() );
+
+ testActionGroup.setVisible( false );
+ QVERIFY( !testActionGroup.isVisible() );
+ QVERIFY( !childAction->isVisible() );
+ QVERIFY( !anotherChildAction->isVisible() );
+
+ anotherChildAction->setVisible(false);
+
+ testActionGroup.setVisible( true );
+ QVERIFY( testActionGroup.isVisible() );
+ QVERIFY( childAction->isVisible() );
+
+ QVERIFY( !anotherChildAction->isVisible() );
+
+ testActionGroup.setVisible( false );
+ QAction *lastChildAction = new QAction(&testActionGroup);
+
+ QVERIFY(!lastChildAction->isVisible());
+ testActionGroup.setVisible( true );
+ QVERIFY(lastChildAction->isVisible());
+
+ freeAction->setVisible(false);
+ testActionGroup.addAction(freeAction);
+ QVERIFY(!freeAction->isVisible());
+ delete freeAction;
+}
+
+void tst_QActionGroup::exclusive()
+{
+ QActionGroup group(0);
+ group.setExclusive(false);
+ QVERIFY( !group.isExclusive() );
+
+ QAction* actOne = new QAction( &group );
+ actOne->setCheckable( true );
+ QAction* actTwo = new QAction( &group );
+ actTwo->setCheckable( true );
+ QAction* actThree = new QAction( &group );
+ actThree->setCheckable( true );
+
+ group.setExclusive( true );
+ QVERIFY( !actOne->isChecked() );
+ QVERIFY( !actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+
+ actOne->setChecked( true );
+ QVERIFY( actOne->isChecked() );
+ QVERIFY( !actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+
+ actTwo->setChecked( true );
+ QVERIFY( !actOne->isChecked() );
+ QVERIFY( actTwo->isChecked() );
+ QVERIFY( !actThree->isChecked() );
+}
+
+void tst_QActionGroup::separators()
+{
+ QMainWindow mw;
+ QMenu menu(&mw);
+ QActionGroup actGroup(&mw);
+
+ mw.show();
+
+#ifdef QT_SOFTKEYS_ENABLED
+ // Softkeys add extra "Select" and "Back" actions to menu by default.
+ // Two first actions will be Select and Back when softkeys are enabled
+ int numSoftkeyActions = 2;
+#else
+ int numSoftkeyActions = 0;
+#endif
+
+ QAction *action = new QAction(&actGroup);
+ action->setText("test one");
+
+ QAction *separator = new QAction(&actGroup);
+ separator->setSeparator(true);
+ actGroup.addAction(separator);
+
+ QListIterator<QAction*> it(actGroup.actions());
+ while (it.hasNext())
+ menu.addAction(it.next());
+
+ QCOMPARE((int)menu.actions().size(), 2 + numSoftkeyActions);
+
+ it = QListIterator<QAction*>(actGroup.actions());
+ while (it.hasNext())
+ menu.removeAction(it.next());
+
+ QCOMPARE((int)menu.actions().size(), 0 + numSoftkeyActions);
+
+ action = new QAction(&actGroup);
+ action->setText("test two");
+
+ it = QListIterator<QAction*>(actGroup.actions());
+ while (it.hasNext())
+ menu.addAction(it.next());
+
+ QCOMPARE((int)menu.actions().size(), 3 + numSoftkeyActions);
+}
+
+void tst_QActionGroup::testActionInTwoQActionGroup()
+{
+ QAction action1("Action 1", this);
+
+ QActionGroup group1(this);
+ QActionGroup group2(this);
+
+ group1.addAction(&action1);
+ group2.addAction(&action1);
+
+ QCOMPARE(action1.actionGroup(), &group2);
+ QCOMPARE(group2.actions().first(), &action1);
+ QCOMPARE(group1.actions().isEmpty(), true);
+}
+
+void tst_QActionGroup::unCheckCurrentAction()
+{
+ QActionGroup group(0);
+ QAction action1(&group) ,action2(&group);
+ action1.setCheckable(true);
+ action2.setCheckable(true);
+ QVERIFY(!action1.isChecked());
+ QVERIFY(!action2.isChecked());
+ action1.setChecked(true);
+ QVERIFY(action1.isChecked());
+ QVERIFY(!action2.isChecked());
+ QAction *current = group.checkedAction();
+ QCOMPARE(current, &action1);
+ current->setChecked(false);
+ QVERIFY(!action1.isChecked());
+ QVERIFY(!action2.isChecked());
+ QVERIFY(group.checkedAction() == 0);
+}
+
+
+QTEST_MAIN(tst_QActionGroup)
+#include "tst_qactiongroup.moc"
diff --git a/tests/auto/widgets/kernel/qapplication/.gitignore b/tests/auto/widgets/kernel/qapplication/.gitignore
new file mode 100644
index 0000000000..ca666e480a
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/.gitignore
@@ -0,0 +1,3 @@
+tst_qapplication
+desktopsettingsaware/desktopsettingsaware
+wincmdline/wincmdline
diff --git a/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/desktopsettingsaware.pro b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/desktopsettingsaware.pro
new file mode 100644
index 0000000000..216a9710c7
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/desktopsettingsaware.pro
@@ -0,0 +1,14 @@
+######################################################################
+# Automatically generated by qmake (2.00a) Mon Jul 11 11:30:34 2005
+######################################################################
+
+TEMPLATE = app
+DEPENDPATH += .
+INCLUDEPATH += .
+wince*:TARGET = ../desktopsettingsaware
+
+# Input
+QT += widgets
+SOURCES += main.cpp
+CONFIG += qt warn_on create_prl link_prl
+CONFIG -= app_bundle
diff --git a/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp
new file mode 100644
index 0000000000..9e2172829a
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QApplication>
+#include <QComboBox>
+
+int main(int argc, char **argv) {
+ QApplication::setDesktopSettingsAware(false);
+ QApplication app(argc, argv);
+ QComboBox box;
+ box.insertItem(0, "foo");
+ box.setEditable(true);
+ box.show();
+ return 0;
+}
diff --git a/tests/auto/widgets/kernel/qapplication/heart.svg b/tests/auto/widgets/kernel/qapplication/heart.svg
new file mode 100644
index 0000000000..8c982cd93c
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/heart.svg
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) --><svg viewBox="100 200 550 500" height="841.88976pt" id="svg1" inkscape:version="0.40+cvs" sodipodi:docbase="C:\Documents and Settings\Jon Phillips\My Documents\projects\clipart-project\submissions" sodipodi:docname="heart-left-highlight.svg" sodipodi:version="0.32" width="595.27559pt" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg">
+<metadata>
+<rdf:RDF xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<cc:Work rdf:about="">
+<dc:title>Heart Left-Highlight</dc:title>
+<dc:description>This is a normal valentines day heart.</dc:description>
+<dc:subject>
+<rdf:Bag>
+<rdf:li>holiday</rdf:li>
+<rdf:li>valentines</rdf:li>
+<rdf:li></rdf:li>
+<rdf:li>valentine</rdf:li>
+<rdf:li>hash(0x8a091c0)</rdf:li>
+<rdf:li>hash(0x8a0916c)</rdf:li>
+<rdf:li>signs_and_symbols</rdf:li>
+<rdf:li>hash(0x8a091f0)</rdf:li>
+<rdf:li>day</rdf:li>
+</rdf:Bag>
+</dc:subject>
+<dc:publisher>
+<cc:Agent rdf:about="http://www.openclipart.org">
+<dc:title>Jon Phillips</dc:title>
+</cc:Agent>
+</dc:publisher>
+<dc:creator>
+<cc:Agent>
+<dc:title>Jon Phillips</dc:title>
+</cc:Agent>
+</dc:creator>
+<dc:rights>
+<cc:Agent>
+<dc:title>Jon Phillips</dc:title>
+</cc:Agent>
+</dc:rights>
+<dc:date></dc:date>
+<dc:format>image/svg+xml</dc:format>
+<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+<cc:license rdf:resource="http://web.resource.org/cc/PublicDomain"/>
+<dc:language>en</dc:language>
+</cc:Work>
+<cc:License rdf:about="http://web.resource.org/cc/PublicDomain">
+<cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
+<cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
+<cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
+</cc:License>
+</rdf:RDF>
+</metadata>
+<defs id="defs3"/>
+<sodipodi:namedview bordercolor="#666666" borderopacity="1.0" id="base" inkscape:current-layer="layer1" inkscape:cx="549.40674" inkscape:cy="596.00159" inkscape:document-units="px" inkscape:guide-bbox="true" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:window-height="615" inkscape:window-width="866" inkscape:window-x="88" inkscape:window-y="116" inkscape:zoom="0.35000000" pagecolor="#ffffff" showguides="true"/>
+<g id="layer1" inkscape:groupmode="layer" inkscape:label="Layer 1">
+<path d="M 263.41570,235.14588 C 197.17570,235.14588 143.41575,288.90587 143.41575,355.14588 C 143.41575,489.90139 279.34890,525.23318 371.97820,658.45392 C 459.55244,526.05056 600.54070,485.59932 600.54070,355.14588 C 600.54070,288.90588 546.78080,235.14587 480.54070,235.14588 C 432.49280,235.14588 391.13910,263.51631 371.97820,304.33338 C 352.81740,263.51630 311.46370,235.14587 263.41570,235.14588 z " id="path7" sodipodi:nodetypes="ccccccc" style="fill:#e60000;fill-opacity:1.0000000;stroke:#000000;stroke-width:18.700001;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"/>
+<path d="M 265.00000,253.59375 C 207.04033,253.59375 160.00000,300.63407 160.00000,358.59375 C 160.00000,476.50415 278.91857,507.43251 359.96875,624.00000 C 366.52868,614.08205 220.00000,478.47309 220.00000,378.59375 C 220.00000,320.63407 267.04033,273.59375 325.00000,273.59375 C 325.50453,273.59375 325.99718,273.64912 326.50000,273.65625 C 309.22436,261.07286 288.00557,253.59374 265.00000,253.59375 z " id="path220" sodipodi:nodetypes="ccccccc" style="fill:#e6e6e6;fill-opacity:0.64556962;stroke:none;stroke-width:18.700001;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"/>
+</g>
+</svg>
diff --git a/tests/auto/widgets/kernel/qapplication/modal/base.cpp b/tests/auto/widgets/kernel/qapplication/modal/base.cpp
new file mode 100644
index 0000000000..2f7b4ad529
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/modal/base.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "base.h"
+
+base::base(QWidget *parent) :
+ QWidget(parent)
+{
+ m_timer = new QTimer(this);
+ m_modalStarted = false;
+ m_timer->setSingleShot(false);
+ connect(m_timer, SIGNAL(timeout()), this, SLOT(periodicTimer()));
+ m_timer->start(5000);
+}
+
+void base::periodicTimer()
+{
+ if(m_modalStarted)
+ exit(0);
+ m_modalDialog = new QDialog(this);
+ m_modalDialog->setModal(true);
+ m_modalDialog->show();
+ m_modalStarted = true;
+}
diff --git a/tests/auto/widgets/kernel/qapplication/modal/base.h b/tests/auto/widgets/kernel/qapplication/modal/base.h
new file mode 100644
index 0000000000..e1f36e11bd
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/modal/base.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BASE_H
+#define BASE_H
+
+#include <QWidget>
+#include <QTimer>
+#include <QDialog>
+
+class base : public QWidget
+{
+Q_OBJECT
+ QTimer *m_timer;
+ bool m_modalStarted;
+ QDialog *m_modalDialog;
+public:
+ explicit base(QWidget *parent = 0);
+
+signals:
+
+public slots:
+ void periodicTimer();
+};
+
+#endif // BASE_H
diff --git a/tests/auto/widgets/kernel/qapplication/modal/main.cpp b/tests/auto/widgets/kernel/qapplication/modal/main.cpp
new file mode 100644
index 0000000000..53c6008eb5
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/modal/main.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+
+#include <QApplication>
+#include "base.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ QApplication::setAttribute(Qt::AA_NativeWindows); //QTBUG-15774
+ base *b = new base();
+ Q_UNUSED(b);
+ return app.exec();
+}
diff --git a/tests/auto/widgets/kernel/qapplication/modal/modal.pro b/tests/auto/widgets/kernel/qapplication/modal/modal.pro
new file mode 100644
index 0000000000..9ed69769bb
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/modal/modal.pro
@@ -0,0 +1,9 @@
+TEMPLATE = app
+QT += widgets
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+SOURCES += main.cpp \
+ base.cpp
+DESTDIR = ./
+HEADERS += base.h
diff --git a/tests/auto/widgets/kernel/qapplication/qapplication.pro b/tests/auto/widgets/kernel/qapplication/qapplication.pro
new file mode 100644
index 0000000000..becc6c6f4b
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/qapplication.pro
@@ -0,0 +1,7 @@
+TEMPLATE = subdirs
+SUBDIRS = test \
+ desktopsettingsaware \
+ modal \
+ wincmdline
+
+
diff --git a/tests/auto/widgets/kernel/qapplication/test/test.pro b/tests/auto/widgets/kernel/qapplication/test/test.pro
new file mode 100644
index 0000000000..65aae7b0b9
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/test/test.pro
@@ -0,0 +1,27 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += ../tst_qapplication.cpp
+TARGET = ../tst_qapplication
+
+wince* {
+ additional.files = ../desktopsettingsaware/desktopsettingsaware.exe
+ additional.path = desktopsettingsaware
+ someTest.files = test.pro
+ someTest.path = test
+ DEPLOYMENT += additional deploy someTest
+}
+
+win32 {
+ CONFIG(debug, debug|release) {
+ TARGET = ../../debug/tst_qapplication
+} else {
+ TARGET = ../../release/tst_qapplication
+ }
+}
+
+mac*:CONFIG+=insignificant_test
+
+CONFIG += insignificant_test # QTBUG-21402
diff --git a/tests/auto/widgets/kernel/qapplication/tmp/README b/tests/auto/widgets/kernel/qapplication/tmp/README
new file mode 100644
index 0000000000..e758961ddf
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/tmp/README
@@ -0,0 +1,3 @@
+this dummy directory is needed for the QApplication::libraryPaths() autotest
+that calls QDir(applicationDirPath + "/tmp/..").canonicalPath(). canonicalPath()
+stat()'s the given directory, so if the tmp directory doesn't exist it fails...
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
new file mode 100644
index 0000000000..c37dfc609e
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
@@ -0,0 +1,2107 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+//#define QT_TST_QAPP_DEBUG
+#include <qdebug.h>
+
+#include <QtTest/QtTest>
+
+#include "qabstracteventdispatcher.h"
+#include <QtGui>
+#include <QtWidgets>
+
+#include "private/qapplication_p.h"
+#include "private/qstylesheetstyle_p.h"
+#ifdef Q_OS_WINCE
+#include <windows.h>
+#endif
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QApplication : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QApplication();
+ virtual ~tst_QApplication();
+
+public slots:
+ void init();
+ void cleanup();
+private slots:
+ void sendEventsOnProcessEvents(); // this must be the first test
+ void getSetCheck();
+ void staticSetup();
+
+ void alert();
+
+ void multiple_data();
+ void multiple();
+
+ void nonGui();
+
+ void setFont_data();
+ void setFont();
+
+ void args_data();
+ void args();
+
+ void lastWindowClosed();
+ void quitOnLastWindowClosed();
+ void closeAllWindows();
+ void testDeleteLater();
+ void testDeleteLaterProcessEvents();
+
+ void libraryPaths();
+ void libraryPaths_qt_plugin_path();
+ void libraryPaths_qt_plugin_path_2();
+
+ void sendPostedEvents();
+
+ void thread();
+ void desktopSettingsAware();
+
+ void setActiveWindow();
+
+ void focusChanged();
+ void focusOut();
+
+ void execAfterExit();
+
+ void wheelScrollLines();
+
+ void task109149();
+
+ void style();
+
+ void allWidgets();
+ void topLevelWidgets();
+
+ void setAttribute();
+
+ void windowsCommandLine_data();
+ void windowsCommandLine();
+
+ void touchEventPropagation();
+
+ void qtbug_12673();
+
+ void globalStaticObjectDestruction(); // run this last
+};
+
+class EventSpy : public QObject
+{
+ Q_OBJECT
+
+public:
+ QList<int> recordedEvents;
+ bool eventFilter(QObject *, QEvent *event)
+ {
+ recordedEvents.append(event->type());
+ return false;
+ }
+};
+
+void tst_QApplication::sendEventsOnProcessEvents()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+
+ EventSpy spy;
+ app.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&app, new QEvent(QEvent::Type(QEvent::User + 1)));
+ QCoreApplication::processEvents();
+ QVERIFY(spy.recordedEvents.contains(QEvent::User + 1));
+}
+
+class MyInputContext : public QInputContext
+{
+public:
+ MyInputContext() : QInputContext() {}
+ QString identifierName() { return QString("NoName"); }
+ QString language() { return QString("NoLanguage"); }
+ void reset() {}
+ bool isComposing() const { return false; }
+};
+
+// Testing get/set functions
+void tst_QApplication::getSetCheck()
+{
+ int argc = 0;
+ QApplication obj1(argc, 0, QApplication::GuiServer);
+ MyInputContext *var1 = new MyInputContext;
+
+ // QApplication takes ownership, so check for reparenting:
+ obj1.setInputContext(var1);
+ QCOMPARE(var1->parent(), static_cast<QObject *>(&obj1));
+
+ // Test for self-assignment:
+ obj1.setInputContext(obj1.inputContext());
+ QVERIFY(obj1.inputContext());
+ QCOMPARE(static_cast<QInputContext *>(var1), obj1.inputContext());
+
+ // Resetting the input context to 0 is not allowed:
+ QTest::ignoreMessage(QtWarningMsg, "QApplication::setInputContext: called with 0 input context");
+ obj1.setInputContext(0);
+
+ QCOMPARE(static_cast<QInputContext *>(var1), obj1.inputContext());
+}
+
+class CloseEventTestWindow : public QWidget
+{
+public:
+ CloseEventTestWindow(QWidget *parent = 0)
+ : QWidget(parent)
+ {
+ }
+
+ void closeEvent(QCloseEvent *event)
+ {
+ QWidget dialog;
+ dialog.show();
+ dialog.close();
+
+ hide();
+ event->ignore();
+ }
+};
+
+static char *argv0;
+
+tst_QApplication::tst_QApplication()
+{
+#ifdef Q_OS_WINCE
+ // Clean up environment previously to launching test
+ qputenv("QT_PLUGIN_PATH", QByteArray());
+#endif
+}
+
+tst_QApplication::~tst_QApplication()
+{
+
+}
+
+void tst_QApplication::init()
+{
+// TODO: Add initialization code here.
+// This will be executed immediately before each test is run.
+}
+
+void tst_QApplication::cleanup()
+{
+// TODO: Add cleanup code here.
+// This will be executed immediately after each test is run.
+}
+
+void tst_QApplication::staticSetup()
+{
+ QVERIFY(!qApp);
+
+ QStyle *style = QStyleFactory::create(QLatin1String("Windows"));
+ QVERIFY(style);
+ QApplication::setStyle(style);
+
+ QPalette pal;
+ QApplication::setPalette(pal);
+
+ /*QFont font;
+ QApplication::setFont(font);*/
+
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+}
+
+
+// QApp subclass that exits the event loop after 150ms
+class TestApplication : public QApplication
+{
+public:
+ TestApplication( int &argc, char **argv )
+ : QApplication( argc, argv, QApplication::GuiServer )
+ {
+ startTimer( 150 );
+ }
+
+ void timerEvent( QTimerEvent * )
+ {
+ quit();
+ }
+};
+
+void tst_QApplication::alert()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ app.alert(0, 0);
+
+ QWidget widget;
+ QWidget widget2;
+ app.alert(&widget, 100);
+ widget.show();
+ widget2.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&widget);
+ qt_x11_wait_for_window_manager(&widget2);
+#endif
+ QTest::qWait(100);
+ app.alert(&widget, -1);
+ app.alert(&widget, 250);
+ widget2.activateWindow();
+ QApplication::setActiveWindow(&widget2);
+ app.alert(&widget, 0);
+ widget.activateWindow();
+ QApplication::setActiveWindow(&widget);
+ app.alert(&widget, 200);
+ app.syncX();
+}
+
+void tst_QApplication::multiple_data()
+{
+ QTest::addColumn<QStringList>("features");
+
+ // return a list of things to try
+ QTest::newRow( "data0" ) << QStringList( "" );
+ QTest::newRow( "data1" ) << QStringList( "QFont" );
+ QTest::newRow( "data2" ) << QStringList( "QPixmap" );
+ QTest::newRow( "data3" ) << QStringList( "QWidget" );
+}
+
+void tst_QApplication::multiple()
+{
+ QFETCH(QStringList,features);
+
+ int i = 0;
+ int argc = 0;
+ while ( i++ < 5 ) {
+ TestApplication app( argc, 0 );
+
+ if ( features.contains( "QFont" ) ) {
+ // create font and force loading
+ QFont font( "Arial", 12 );
+ QFontInfo finfo( font );
+ finfo.exactMatch();
+ }
+ if ( features.contains( "QPixmap" ) ) {
+ QPixmap pix( 100, 100 );
+ pix.fill( Qt::black );
+ }
+ if ( features.contains( "QWidget" ) ) {
+ QWidget widget;
+ }
+
+ QVERIFY(!app.exec());
+ }
+}
+
+void tst_QApplication::nonGui()
+{
+#ifdef Q_OS_HPUX
+ // ### This is only to allow us to generate a test report for now.
+ QSKIP("This test shuts down the window manager on HP-UX.", SkipAll);
+#endif
+
+ int argc = 0;
+ QApplication app(argc, 0, false);
+ QCOMPARE(qApp, &app);
+}
+
+void tst_QApplication::setFont_data()
+{
+ QTest::addColumn<QString>("family");
+ QTest::addColumn<int>("pointsize");
+ QTest::addColumn<bool>("beforeAppConstructor");
+
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer); // Needed for QFontDatabase
+
+ int cnt = 0;
+ QFontDatabase fdb;
+ QStringList families = fdb.families();
+ for (QStringList::const_iterator itr = families.begin();
+ itr != families.end();
+ ++itr) {
+ if (cnt < 3) {
+ QString family = *itr;
+ QStringList styles = fdb.styles(family);
+ if (styles.size() > 0) {
+ QString style = styles.first();
+ QList<int> sizes = fdb.pointSizes(family, style);
+ if (!sizes.size())
+ sizes = fdb.standardSizes();
+ if (sizes.size() > 0) {
+ QTest::newRow(QString("data%1a").arg(cnt).toLatin1().constData())
+ << family
+ << sizes.first()
+ << false;
+ QTest::newRow(QString("data%1b").arg(cnt).toLatin1().constData())
+ << family
+ << sizes.first()
+ << true;
+ }
+ }
+ }
+ ++cnt;
+ }
+
+ QTest::newRow("nonexistingfont") << "nosuchfont_probably_quiteunlikely"
+ << 0 << false;
+ QTest::newRow("nonexistingfont") << "nosuchfont_probably_quiteunlikely"
+ << 0 << true;
+
+ QTest::newRow("largescaleable") << "smoothtimes" << 100 << false;
+ QTest::newRow("largescaleable") << "smoothtimes" << 100 << true;
+
+ QTest::newRow("largeunscaleale") << "helvetica" << 100 << false;
+ QTest::newRow("largeunscaleale") << "helvetica" << 100 << true;
+}
+
+void tst_QApplication::setFont()
+{
+ QFETCH( QString, family );
+ QFETCH( int, pointsize );
+ QFETCH( bool, beforeAppConstructor );
+
+ QFont font( family, pointsize );
+ if (beforeAppConstructor) {
+ QApplication::setFont( font );
+ QCOMPARE(QApplication::font(), font);
+ }
+
+ int argc = 0;
+ QApplication app( argc, 0, QApplication::GuiServer );
+ if (!beforeAppConstructor)
+ QApplication::setFont( font );
+
+ QCOMPARE( app.font(), font );
+}
+
+void tst_QApplication::args_data()
+{
+ QTest::addColumn<int>("argc_in");
+ QTest::addColumn<QString>("args_in");
+ QTest::addColumn<int>("argc_out");
+ QTest::addColumn<QString>("args_out");
+
+ QTest::newRow( "App name" ) << 1 << "/usr/bin/appname" << 1 << "/usr/bin/appname";
+ QTest::newRow( "No arguments" ) << 0 << QString() << 0 << QString();
+ QTest::newRow( "App name, style" ) << 3 << "/usr/bin/appname -style motif" << 1 << "/usr/bin/appname";
+ QTest::newRow( "App name, style, arbitrary, reverse" ) << 5 << "/usr/bin/appname -style motif -arbitrary -reverse"
+ << 2 << "/usr/bin/appname -arbitrary";
+}
+
+void tst_QApplication::task109149()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QApplication::setFont(QFont("helvetica", 100));
+
+ QWidget w;
+ w.setWindowTitle("hello");
+ w.show();
+
+ app.processEvents();
+}
+
+static char ** QString2cstrings( const QString &args )
+{
+ static QList<QByteArray> cache;
+
+ int i;
+ char **argarray = 0;
+ QStringList list = args.split(' ');;
+ argarray = new char*[list.count()+1];
+
+ for (i = 0; i < (int)list.count(); ++i ) {
+ QByteArray l1 = list[i].toLatin1();
+ argarray[i] = l1.data();
+ cache.append(l1);
+ }
+ argarray[i] = 0;
+
+ return argarray;
+}
+
+static QString cstrings2QString( char **args )
+{
+ QString string;
+ if ( !args )
+ return string;
+
+ int i = 0;
+ while ( args[i] ) {
+ string += args[i];
+ if ( args[i+1] )
+ string += " ";
+ ++i;
+ }
+ return string;
+}
+
+void tst_QApplication::args()
+{
+ QFETCH( int, argc_in );
+ QFETCH( QString, args_in );
+ QFETCH( int, argc_out );
+ QFETCH( QString, args_out );
+
+ char **argv = QString2cstrings( args_in );
+
+ QApplication app( argc_in, argv, QApplication::GuiServer );
+ QString argv_out = cstrings2QString(argv);
+
+ QCOMPARE( argc_in, argc_out );
+ QCOMPARE( argv_out, args_out );
+
+ delete [] argv;
+}
+
+class CloseWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ CloseWidget()
+ {
+ startTimer(500);
+ }
+
+protected:
+ void timerEvent(QTimerEvent *)
+ {
+ close();
+ }
+
+};
+
+void tst_QApplication::lastWindowClosed()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+
+ QSignalSpy spy(&app, SIGNAL(lastWindowClosed()));
+
+ QPointer<QDialog> dialog = new QDialog;
+ QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose));
+ QTimer::singleShot(1000, dialog, SLOT(accept()));
+ dialog->exec();
+ QVERIFY(dialog);
+ QCOMPARE(spy.count(), 0);
+
+ QPointer<CloseWidget>widget = new CloseWidget;
+ QVERIFY(widget->testAttribute(Qt::WA_QuitOnClose));
+ QObject::connect(&app, SIGNAL(lastWindowClosed()), widget, SLOT(deleteLater()));
+ app.exec();
+ QVERIFY(!widget);
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+
+#if 0
+ // everything is closed, so doing this should not emit lastWindowClosed() again
+ QMetaObject::invokeMethod(dialog, "close", Qt::QueuedConnection);
+ QTimer::singleShot(1000, &app, SLOT(quit()));
+ app.exec();
+ QCOMPARE(spy.count(), 0);
+#endif
+
+ delete dialog;
+
+ // show 3 windows, close them, should only get lastWindowClosed once
+ QWidget w1;
+ QWidget w2;
+ QWidget w3;
+ w1.show();
+ w2.show();
+ w3.show();
+
+ QTimer::singleShot(1000, &app, SLOT(closeAllWindows()));
+ app.exec();
+ QCOMPARE(spy.count(), 1);
+}
+
+class QuitOnLastWindowClosedDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ QPushButton *okButton;
+
+ QuitOnLastWindowClosedDialog()
+ {
+ QHBoxLayout *hbox = new QHBoxLayout(this);
+ okButton = new QPushButton("&ok", this);
+
+ hbox->addWidget(okButton);
+ connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(okButton, SIGNAL(clicked()), this, SLOT(ok_clicked()));
+ }
+
+public slots:
+ void ok_clicked()
+ {
+ QDialog other;
+
+ QTimer timer;
+ connect(&timer, SIGNAL(timeout()), &other, SLOT(accept()));
+ QSignalSpy spy(&timer, SIGNAL(timeout()));
+ QSignalSpy appSpy(qApp, SIGNAL(lastWindowClosed()));
+
+ timer.start(1000);
+ other.exec();
+
+ // verify that the eventloop ran and let the timer fire
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(appSpy.count(), 1);
+ }
+};
+
+class QuitOnLastWindowClosedWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ QuitOnLastWindowClosedWindow()
+ { }
+
+public slots:
+ void execDialogThenShow()
+ {
+ QDialog dialog;
+ QTimer timer1;
+ connect(&timer1, SIGNAL(timeout()), &dialog, SLOT(accept()));
+ QSignalSpy spy1(&timer1, SIGNAL(timeout()));
+ timer1.setSingleShot(true);
+ timer1.start(1000);
+ dialog.exec();
+ QCOMPARE(spy1.count(), 1);
+
+ show();
+ }
+};
+
+void tst_QApplication::quitOnLastWindowClosed()
+{
+ {
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+
+ QuitOnLastWindowClosedDialog d;
+ d.show();
+ QTimer::singleShot(1000, d.okButton, SLOT(animateClick()));
+
+ QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
+ app.exec();
+
+ // lastWindowClosed() signal should only be sent after the last dialog is closed
+ QCOMPARE(appSpy.count(), 2);
+ }
+ {
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
+
+ QDialog dialog;
+ QTimer timer1;
+ connect(&timer1, SIGNAL(timeout()), &dialog, SLOT(accept()));
+ QSignalSpy spy1(&timer1, SIGNAL(timeout()));
+ timer1.setSingleShot(true);
+ timer1.start(1000);
+ dialog.exec();
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(appSpy.count(), 0);
+
+ QTimer timer2;
+ connect(&timer2, SIGNAL(timeout()), &app, SLOT(quit()));
+ QSignalSpy spy2(&timer2, SIGNAL(timeout()));
+ timer2.setSingleShot(true);
+ timer2.start(1000);
+ int returnValue = app.exec();
+ QCOMPARE(returnValue, 0);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(appSpy.count(), 0);
+ }
+ {
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QTimer timer;
+ timer.setInterval(100);
+
+ QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
+ QSignalSpy spy2(&timer, SIGNAL(timeout()));
+
+ QPointer<QMainWindow> mainWindow = new QMainWindow;
+ QPointer<QDialog> dialog = new QDialog(mainWindow);
+
+ QVERIFY(app.quitOnLastWindowClosed());
+ QVERIFY(mainWindow->testAttribute(Qt::WA_QuitOnClose));
+ QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose));
+
+ mainWindow->show();
+ dialog->show();
+
+ timer.start();
+ QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application
+ QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't
+
+ app.exec();
+
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(spy2.count() < 15); // Should be around 10 if closing caused the quit
+ }
+ {
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QTimer timer;
+ timer.setInterval(100);
+
+ QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
+ QSignalSpy spy2(&timer, SIGNAL(timeout()));
+
+ QPointer<CloseEventTestWindow> mainWindow = new CloseEventTestWindow;
+
+ QVERIFY(app.quitOnLastWindowClosed());
+ QVERIFY(mainWindow->testAttribute(Qt::WA_QuitOnClose));
+
+ mainWindow->show();
+
+ timer.start();
+ QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application
+ QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't
+
+ app.exec();
+
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(spy2.count() > 15); // Should be around 20 if closing did not caused the quit
+ }
+ {
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
+
+ // exec a dialog for 1 second, then show the window
+ QuitOnLastWindowClosedWindow window;
+ QTimer::singleShot(0, &window, SLOT(execDialogThenShow()));
+
+ QTimer timer;
+ QSignalSpy timerSpy(&timer, SIGNAL(timeout()));
+ connect(&timer, SIGNAL(timeout()), &window, SLOT(close()));
+ timer.setSingleShot(true);
+ timer.start(2000);
+ int returnValue = app.exec();
+ QCOMPARE(returnValue, 0);
+ // failure here means the timer above didn't fire, and the
+ // quit was caused the the dialog being closed (not the window)
+ QCOMPARE(timerSpy.count(), 1);
+ QCOMPARE(appSpy.count(), 2);
+ }
+}
+
+class PromptOnCloseWidget : public QWidget
+{
+public:
+ void closeEvent(QCloseEvent *event)
+ {
+ QMessageBox *messageBox = new QMessageBox(this);
+ messageBox->setWindowTitle("Unsaved data");
+ messageBox->setText("Would you like to save or discard your current data?");
+ messageBox->setStandardButtons(QMessageBox::Save|QMessageBox::Discard|QMessageBox::Cancel);
+ messageBox->setDefaultButton(QMessageBox::Save);
+
+ messageBox->show();
+ QTest::qWaitForWindowShown(messageBox);
+
+ // verify that all windows are visible
+ foreach (QWidget *w, qApp->topLevelWidgets())
+ QVERIFY(w->isVisible());
+ // flush event queue
+ qApp->processEvents();
+ // close all windows
+ qApp->closeAllWindows();
+
+ if (messageBox->standardButton(messageBox->clickedButton()) == QMessageBox::Cancel)
+ event->ignore();
+ else
+ event->accept();
+
+ delete messageBox;
+ }
+};
+
+void tst_QApplication::closeAllWindows()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+
+ // create some windows
+ new QWidget;
+ new QWidget;
+ new QWidget;
+
+ // show all windows
+ foreach (QWidget *w, app.topLevelWidgets()) {
+ w->show();
+ QTest::qWaitForWindowShown(w);
+ }
+ // verify that they are visible
+ foreach (QWidget *w, app.topLevelWidgets())
+ QVERIFY(w->isVisible());
+ // empty event queue
+ app.processEvents();
+ // close all windows
+ app.closeAllWindows();
+ // all windows should no longer be visible
+ foreach (QWidget *w, app.topLevelWidgets())
+ QVERIFY(!w->isVisible());
+
+ // add a window that prompts the user when closed
+ PromptOnCloseWidget *promptOnCloseWidget = new PromptOnCloseWidget;
+ // show all windows
+ foreach (QWidget *w, app.topLevelWidgets()) {
+ w->show();
+ QTest::qWaitForWindowShown(w);
+ }
+ // close the last window to open the prompt (eventloop recurses)
+ promptOnCloseWidget->close();
+ // all windows should not be visible, except the one that opened the prompt
+ foreach (QWidget *w, app.topLevelWidgets()) {
+ if (w == promptOnCloseWidget)
+ QVERIFY(w->isVisible());
+ else
+ QVERIFY(!w->isVisible());
+ }
+
+ qDeleteAll(app.topLevelWidgets());
+}
+
+bool isPathListIncluded(const QStringList &l, const QStringList &r)
+{
+ int size = r.count();
+ if (size > l.count())
+ return false;
+#if defined (Q_OS_WIN)
+ Qt::CaseSensitivity cs = Qt::CaseInsensitive;
+#else
+ Qt::CaseSensitivity cs = Qt::CaseSensitive;
+#endif
+ int i = 0, j = 0;
+ for ( ; i < l.count() && j < r.count(); ++i) {
+ if (QDir::toNativeSeparators(l[i]).compare(QDir::toNativeSeparators(r[j]), cs) == 0) {
+ ++j;
+ i = -1;
+ }
+ }
+ return j == r.count();
+}
+
+#define QT_TST_QAPP_DEBUG
+void tst_QApplication::libraryPaths()
+{
+ {
+#ifndef Q_OS_WINCE
+ QString testDir = QDir::current().canonicalPath() + "/test";
+#else
+ // On Windows CE we need QApplication object to have valid
+ // current Path. Therefore we need to identify it ourselves
+ // here for the test.
+ QFileInfo filePath;
+ wchar_t module_name[MAX_PATH];
+ GetModuleFileName(0, module_name, MAX_PATH);
+ filePath = QString::fromWCharArray(module_name);
+ QString testDir = filePath.path() + "/test";
+#endif
+ QApplication::setLibraryPaths(QStringList() << testDir);
+ QCOMPARE(QApplication::libraryPaths(), (QStringList() << testDir));
+
+ // creating QApplication adds the applicationDirPath to the libraryPath
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QString appDirPath = QDir(app.applicationDirPath()).canonicalPath();
+
+ QStringList actual = QApplication::libraryPaths();
+ actual.sort();
+ QStringList expected = QSet<QString>::fromList((QStringList() << testDir << appDirPath)).toList();
+ expected.sort();
+
+ QVERIFY2(isPathListIncluded(actual, expected),
+ qPrintable("actual:\n - " + actual.join("\n - ") +
+ "\nexpected:\n - " + expected.join("\n - ")));
+ }
+ {
+ // creating QApplication adds the applicationDirPath and plugin install path to the libraryPath
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QString appDirPath = app.applicationDirPath();
+ QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
+
+ QStringList actual = QApplication::libraryPaths();
+ actual.sort();
+
+ QStringList expected = QSet<QString>::fromList((QStringList() << installPathPlugins << appDirPath)).toList();
+ expected.sort();
+
+ QVERIFY2(isPathListIncluded(actual, expected),
+ qPrintable("actual:\n - " + actual.join("\n - ") +
+ "\nexpected:\n - " + expected.join("\n - ")));
+
+ // setting the library paths overrides everything
+ QString testDir = QDir::currentPath() + "/test";
+ QApplication::setLibraryPaths(QStringList() << testDir);
+ QVERIFY2(isPathListIncluded(QApplication::libraryPaths(), (QStringList() << testDir)),
+ qPrintable("actual:\n - " + QApplication::libraryPaths().join("\n - ") +
+ "\nexpected:\n - " + testDir));
+ }
+ {
+#ifdef QT_TST_QAPP_DEBUG
+ qDebug() << "Initial library path:" << QApplication::libraryPaths();
+#endif
+
+ int count = QApplication::libraryPaths().count();
+#if 0
+ // this test doesn't work if KDE 4 is installed
+ QCOMPARE(count, 1); // before creating QApplication, only the PluginsPath is in the libraryPaths()
+#endif
+ QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
+ QApplication::addLibraryPath(installPathPlugins);
+#ifdef QT_TST_QAPP_DEBUG
+ qDebug() << "installPathPlugins" << installPathPlugins;
+ qDebug() << "After adding plugins path:" << QApplication::libraryPaths();
+#endif
+ QCOMPARE(QApplication::libraryPaths().count(), count);
+
+ QApplication::addLibraryPath(QDir::currentPath() + "/test");
+ QCOMPARE(QApplication::libraryPaths().count(), count + 1);
+
+ // creating QApplication adds the applicationDirPath to the libraryPath
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QString appDirPath = app.applicationDirPath();
+ qDebug() << QApplication::libraryPaths();
+ // On Windows CE these are identical and might also be the case for other
+ // systems too
+ if (appDirPath != installPathPlugins)
+ QCOMPARE(QApplication::libraryPaths().count(), count + 2);
+ }
+ {
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+
+#ifdef QT_TST_QAPP_DEBUG
+ qDebug() << "Initial library path:" << app.libraryPaths();
+#endif
+ int count = app.libraryPaths().count();
+ QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
+ app.addLibraryPath(installPathPlugins);
+#ifdef QT_TST_QAPP_DEBUG
+ qDebug() << "installPathPlugins" << installPathPlugins;
+ qDebug() << "After adding plugins path:" << app.libraryPaths();
+#endif
+ QCOMPARE(app.libraryPaths().count(), count);
+
+ QString appDirPath = app.applicationDirPath();
+
+ app.addLibraryPath(appDirPath);
+#ifdef Q_OS_WINCE
+ app.addLibraryPath(appDirPath + "/../..");
+#else
+ app.addLibraryPath(appDirPath + "/..");
+#endif
+#ifdef QT_TST_QAPP_DEBUG
+ qDebug() << "appDirPath" << appDirPath;
+ qDebug() << "After adding appDirPath && appDirPath + /..:" << app.libraryPaths();
+#endif
+ QCOMPARE(app.libraryPaths().count(), count + 1);
+#ifdef Q_OS_MAC
+ app.addLibraryPath(appDirPath + "/../MacOS");
+#else
+ app.addLibraryPath(appDirPath + "/tmp/..");
+#endif
+#ifdef QT_TST_QAPP_DEBUG
+ qDebug() << "After adding appDirPath + /tmp/..:" << app.libraryPaths();
+#endif
+ QCOMPARE(app.libraryPaths().count(), count + 1);
+ }
+}
+
+void tst_QApplication::libraryPaths_qt_plugin_path()
+{
+ int argc = 1;
+
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QString appDirPath = app.applicationDirPath();
+
+ // Our hook into libraryPaths() initialization: Set the QT_PLUGIN_PATH environment variable
+ QString installPathPluginsDeCanon = appDirPath + QString::fromLatin1("/tmp/..");
+ QByteArray ascii = installPathPluginsDeCanon.toAscii();
+ qputenv("QT_PLUGIN_PATH", ascii);
+
+ QVERIFY(!app.libraryPaths().contains(appDirPath + QString::fromLatin1("/tmp/..")));
+}
+
+void tst_QApplication::libraryPaths_qt_plugin_path_2()
+{
+#ifdef Q_OS_UNIX
+ QByteArray validPath = QDir("/tmp").canonicalPath().toLatin1();
+ QByteArray nonExistentPath = "/nonexistent";
+ QByteArray pluginPath = validPath + ":" + nonExistentPath;
+#elif defined(Q_OS_WIN)
+# ifdef Q_OS_WINCE
+ QByteArray validPath = "/Temp";
+ QByteArray nonExistentPath = "/nonexistent";
+ QByteArray pluginPath = validPath + ";" + nonExistentPath;
+# else
+ QByteArray validPath = "C:\\windows";
+ QByteArray nonExistentPath = "Z:\\nonexistent";
+ QByteArray pluginPath = validPath + ";" + nonExistentPath;
+# endif
+#endif
+
+ {
+ // Our hook into libraryPaths() initialization: Set the QT_PLUGIN_PATH environment variable
+ qputenv("QT_PLUGIN_PATH", pluginPath);
+
+ int argc = 1;
+
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+
+ // library path list should contain the default plus the one valid path
+ QStringList expected =
+ QStringList()
+ << QLibraryInfo::location(QLibraryInfo::PluginsPath)
+ << QDir(app.applicationDirPath()).canonicalPath()
+ << QDir(QDir::fromNativeSeparators(QString::fromLatin1(validPath))).canonicalPath();
+# ifdef Q_OS_WINCE
+ expected = QSet<QString>::fromList(expected).toList();
+# endif
+ QVERIFY2(isPathListIncluded(app.libraryPaths(), expected),
+ qPrintable("actual:\n - " + app.libraryPaths().join("\n - ") +
+ "\nexpected:\n - " + expected.join("\n - ")));
+ }
+
+ {
+ int argc = 1;
+
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+
+ // library paths are initialized by the QApplication, setting
+ // the environment variable here doesn't work
+ qputenv("QT_PLUGIN_PATH", pluginPath);
+
+ // library path list should contain the default
+ QStringList expected =
+ QStringList()
+ << QLibraryInfo::location(QLibraryInfo::PluginsPath)
+ << app.applicationDirPath();
+# ifdef Q_OS_WINCE
+ expected = QSet<QString>::fromList(expected).toList();
+# endif
+ QVERIFY(isPathListIncluded(app.libraryPaths(), expected));
+
+ qputenv("QT_PLUGIN_PATH", QByteArray());
+ }
+}
+
+class SendPostedEventsTester : public QObject
+{
+ Q_OBJECT
+public:
+ QList<int> eventSpy;
+ bool event(QEvent *e);
+private slots:
+ void doTest();
+};
+
+bool SendPostedEventsTester::event(QEvent *e)
+{
+ eventSpy.append(e->type());
+ return QObject::event(e);
+}
+
+void SendPostedEventsTester::doTest()
+{
+ QPointer<SendPostedEventsTester> p = this;
+ QApplication::postEvent(this, new QEvent(QEvent::User));
+ // DeferredDelete should not be delivered until returning from this function
+ QApplication::postEvent(this, new QEvent(QEvent::DeferredDelete));
+
+ QEventLoop eventLoop;
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p != 0);
+
+ QCOMPARE(eventSpy.count(), 2);
+ QCOMPARE(eventSpy.at(0), int(QEvent::MetaCall));
+ QCOMPARE(eventSpy.at(1), int(QEvent::User));
+ eventSpy.clear();
+}
+
+void tst_QApplication::sendPostedEvents()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ SendPostedEventsTester *tester = new SendPostedEventsTester;
+ QMetaObject::invokeMethod(tester, "doTest", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
+ QPointer<SendPostedEventsTester> p = tester;
+ (void) app.exec();
+ QVERIFY(p == 0);
+}
+
+void tst_QApplication::thread()
+{
+ QThread *currentThread = QThread::currentThread();
+ // no app, but still have a valid thread
+ QVERIFY(currentThread != 0);
+
+ // the thread should be running and not finished
+ QVERIFY(currentThread->isRunning());
+ QVERIFY(!currentThread->isFinished());
+
+ // this should probably be in the tst_QObject::thread() test, but
+ // we put it here since we want to make sure that objects created
+ // *before* the QApplication has a thread
+ QObject object;
+ QObject child(&object);
+ QVERIFY(object.thread() == currentThread);
+ QVERIFY(child.thread() == currentThread);
+
+ {
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+
+ // current thread still valid
+ QVERIFY(QThread::currentThread() != 0);
+ // thread should be the same as before
+ QCOMPARE(QThread::currentThread(), currentThread);
+
+ // app's thread should be the current thread
+ QCOMPARE(app.thread(), currentThread);
+
+ // the thread should still be running and not finished
+ QVERIFY(currentThread->isRunning());
+ QVERIFY(!currentThread->isFinished());
+
+ QTestEventLoop::instance().enterLoop(1);
+ }
+
+ // app dead, current thread still valid
+ QVERIFY(QThread::currentThread() != 0);
+ QCOMPARE(QThread::currentThread(), currentThread);
+
+ // the thread should still be running and not finished
+ QVERIFY(currentThread->isRunning());
+ QVERIFY(!currentThread->isFinished());
+
+ // should still have a thread
+ QVERIFY(object.thread() == currentThread);
+ QVERIFY(child.thread() == currentThread);
+
+ // do the test again, making sure that the thread is the same as
+ // before
+ {
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+
+ // current thread still valid
+ QVERIFY(QThread::currentThread() != 0);
+ // thread should be the same as before
+ QCOMPARE(QThread::currentThread(), currentThread);
+
+ // app's thread should be the current thread
+ QCOMPARE(app.thread(), currentThread);
+
+ // the thread should be running and not finished
+ QVERIFY(currentThread->isRunning());
+ QVERIFY(!currentThread->isFinished());
+
+ // should still have a thread
+ QVERIFY(object.thread() == currentThread);
+ QVERIFY(child.thread() == currentThread);
+
+ QTestEventLoop::instance().enterLoop(1);
+ }
+
+ // app dead, current thread still valid
+ QVERIFY(QThread::currentThread() != 0);
+ QCOMPARE(QThread::currentThread(), currentThread);
+
+ // the thread should still be running and not finished
+ QVERIFY(currentThread->isRunning());
+ QVERIFY(!currentThread->isFinished());
+
+ // should still have a thread
+ QVERIFY(object.thread() == currentThread);
+ QVERIFY(child.thread() == currentThread);
+}
+
+class DeleteLaterWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ DeleteLaterWidget(QApplication *_app, QWidget *parent = 0)
+ : QWidget(parent) { app = _app; child_deleted = false; }
+
+ bool child_deleted;
+ QApplication *app;
+
+public slots:
+ void runTest();
+ void checkDeleteLater();
+ void childDeleted() { child_deleted = true; }
+};
+
+
+void DeleteLaterWidget::runTest()
+{
+ QObject *stillAlive = qFindChild<QObject*>(this, "deleteLater");
+
+ QWidget *w = new QWidget(this);
+ connect(w, SIGNAL(destroyed()), this, SLOT(childDeleted()));
+
+ w->deleteLater();
+ QVERIFY(!child_deleted);
+
+ QDialog dlg;
+ QTimer::singleShot(500, &dlg, SLOT(reject()));
+ dlg.exec();
+
+ QVERIFY(!child_deleted);
+ app->processEvents();
+ QVERIFY(!child_deleted);
+
+ QTimer::singleShot(500, this, SLOT(checkDeleteLater()));
+
+ app->processEvents();
+
+ QVERIFY(!stillAlive); // verify at the end to make test terminate
+}
+
+void DeleteLaterWidget::checkDeleteLater()
+{
+ QVERIFY(child_deleted);
+
+ close();
+}
+
+void tst_QApplication::testDeleteLater()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+ connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
+
+ DeleteLaterWidget *wgt = new DeleteLaterWidget(&app);
+ QTimer::singleShot(500, wgt, SLOT(runTest()));
+
+ QObject *object = new QObject(wgt);
+ object->setObjectName("deleteLater");
+ object->deleteLater();
+
+ QObject *stillAlive = qFindChild<QObject*>(wgt, "deleteLater");
+ QVERIFY(stillAlive);
+
+ app.exec();
+
+ delete wgt;
+
+}
+
+class EventLoopNester : public QObject
+{
+ Q_OBJECT
+public slots:
+ void deleteLaterAndEnterLoop()
+ {
+ QEventLoop eventLoop;
+ QPointer<QObject> p(this);
+ deleteLater();
+ /*
+ DeferredDelete events are compressed, meaning this second
+ deleteLater() will *not* delete the object in the nested
+ event loop
+ */
+ QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
+ QTimer::singleShot(1000, &eventLoop, SLOT(quit()));
+ eventLoop.exec();
+ QVERIFY(p);
+ }
+ void deleteLaterAndExitLoop()
+ {
+ // Check that 'p' is not deleted before exec returns, since the call
+ // to QEventLoop::quit() should stop 'eventLoop' from processing
+ // any more events (that is, delete later) until we return to the
+ // _current_ event loop:
+ QEventLoop eventLoop;
+ QPointer<QObject> p(this);
+ QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p); // not dead yet
+ }
+
+ void processEventsOnly()
+ {
+ QApplication::processEvents();
+ }
+ void processEventsWithDeferredDeletion()
+ {
+ QApplication::processEvents(QEventLoop::DeferredDeletion);
+ }
+ void sendPostedEventsWithDeferredDelete()
+ {
+ QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ }
+ void deleteLaterAndProcessEvents1()
+ {
+ QEventLoop eventLoop;
+
+ QPointer<QObject> p = this;
+ deleteLater();
+
+ // trying to delete this object in a deeper eventloop just won't work
+ QMetaObject::invokeMethod(this,
+ "processEventsOnly",
+ Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p);
+ QMetaObject::invokeMethod(this,
+ "processEventsWithDeferredDeletion",
+ Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p);
+ QMetaObject::invokeMethod(this,
+ "sendPostedEventsWithDeferredDelete",
+ Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p);
+
+ // trying to delete it from this eventloop still doesn't work
+ QApplication::processEvents();
+ QVERIFY(p);
+
+ // however, it *will* work with this magic incantation
+ QApplication::processEvents(QEventLoop::DeferredDeletion);
+ QVERIFY(!p);
+ }
+
+ void deleteLaterAndProcessEvents2()
+ {
+ QEventLoop eventLoop;
+
+ QPointer<QObject> p = this;
+ deleteLater();
+
+ // trying to delete this object in a deeper eventloop just won't work
+ QMetaObject::invokeMethod(this,
+ "processEventsOnly",
+ Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p);
+ QMetaObject::invokeMethod(this,
+ "processEventsWithDeferredDeletion",
+ Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p);
+ QMetaObject::invokeMethod(this,
+ "sendPostedEventsWithDeferredDelete",
+ Qt::QueuedConnection);
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ eventLoop.exec();
+ QVERIFY(p);
+
+ // trying to delete it from this eventloop still doesn't work
+ QApplication::processEvents();
+ QVERIFY(p);
+
+ // however, it *will* work with this magic incantation
+ QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(!p);
+ }
+};
+
+void tst_QApplication::testDeleteLaterProcessEvents()
+{
+ int argc = 0;
+
+ // Calling processEvents() with no event dispatcher does nothing.
+ QObject *object = new QObject;
+ QPointer<QObject> p(object);
+ object->deleteLater();
+ QApplication::processEvents();
+ QVERIFY(p);
+ delete object;
+
+ {
+ QApplication app(argc, 0, QApplication::GuiServer);
+ // If you call processEvents() with an event dispatcher present, but
+ // outside any event loops, deferred deletes are not processed unless
+ // QEventLoop::DeferredDeletion is passed.
+ object = new QObject;
+ p = object;
+ object->deleteLater();
+ app.processEvents();
+ QVERIFY(p);
+ app.processEvents(QEventLoop::ProcessEventsFlag(0x10)); // 0x10 == QEventLoop::DeferredDeletion
+ QVERIFY(!p);
+
+ // sendPostedEvents(0, DeferredDelete); also works
+ object = new QObject;
+ p = object;
+ object->deleteLater();
+ app.processEvents();
+ QVERIFY(p);
+ QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QVERIFY(!p);
+
+ // If you call deleteLater() on an object when there is no parent
+ // event loop, and then enter an event loop, the object will get
+ // deleted.
+ object = new QObject;
+ p = object;
+ object->deleteLater();
+ QEventLoop loop;
+ QTimer::singleShot(1000, &loop, SLOT(quit()));
+ loop.exec();
+ QVERIFY(!p);
+ }
+ {
+ // When an object is in an event loop, then calls deleteLater() and enters
+ // an event loop recursively, it should not die until the parent event
+ // loop continues.
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QEventLoop loop;
+ EventLoopNester *nester = new EventLoopNester;
+ p = nester;
+ QTimer::singleShot(3000, &loop, SLOT(quit()));
+ QTimer::singleShot(0, nester, SLOT(deleteLaterAndEnterLoop()));
+
+ loop.exec();
+ QVERIFY(!p);
+ }
+
+ {
+ // When the event loop that calls deleteLater() is exited
+ // immediately, the object should die when returning to the
+ // parent event loop
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QEventLoop loop;
+ EventLoopNester *nester = new EventLoopNester;
+ p = nester;
+ QTimer::singleShot(3000, &loop, SLOT(quit()));
+ QTimer::singleShot(0, nester, SLOT(deleteLaterAndExitLoop()));
+
+ loop.exec();
+ QVERIFY(!p);
+ }
+
+ {
+ // when the event loop that calls deleteLater() also calls
+ // processEvents() immediately afterwards, the object should
+ // not die until the parent loop continues
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QEventLoop loop;
+ EventLoopNester *nester = new EventLoopNester();
+ p = nester;
+ QTimer::singleShot(3000, &loop, SLOT(quit()));
+ QTimer::singleShot(0, nester, SLOT(deleteLaterAndProcessEvents1()));
+
+ loop.exec();
+ QVERIFY(!p);
+ }
+
+ {
+ // when the event loop that calls deleteLater() also calls
+ // processEvents() immediately afterwards, the object should
+ // not die until the parent loop continues
+ QApplication app(argc, 0, QApplication::GuiServer);
+ QEventLoop loop;
+ EventLoopNester *nester = new EventLoopNester();
+ p = nester;
+ QTimer::singleShot(3000, &loop, SLOT(quit()));
+ QTimer::singleShot(0, nester, SLOT(deleteLaterAndProcessEvents2()));
+
+ loop.exec();
+ QVERIFY(!p);
+ }
+}
+
+/*
+ Test for crash with QApplication::setDesktopSettingsAware(false).
+*/
+void tst_QApplication::desktopSettingsAware()
+{
+#ifndef QT_NO_PROCESS
+ QProcess testProcess;
+#ifdef Q_OS_WINCE
+ int argc = 0;
+ QApplication tmpApp(argc, 0, QApplication::GuiServer);
+ testProcess.start("desktopsettingsaware/desktopsettingsaware");
+#else
+#if defined(Q_OS_WIN) && defined(QT_DEBUG)
+ testProcess.start("desktopsettingsaware/debug/desktopsettingsaware");
+#elif defined(Q_OS_WIN)
+ testProcess.start("desktopsettingsaware/release/desktopsettingsaware");
+#else
+ testProcess.start("desktopsettingsaware/desktopsettingsaware");
+#endif
+#endif
+ QVERIFY(testProcess.waitForFinished(10000));
+ QCOMPARE(int(testProcess.state()), int(QProcess::NotRunning));
+ QVERIFY(int(testProcess.error()) != int(QProcess::Crashed));
+#endif
+}
+
+void tst_QApplication::setActiveWindow()
+{
+ int argc = 0;
+ QApplication MyApp(argc, 0, QApplication::GuiServer);
+
+ QWidget* w = new QWidget;
+ QVBoxLayout* layout = new QVBoxLayout(w);
+
+ QLineEdit* pb1 = new QLineEdit("Testbutton1", w);
+ QLineEdit* pb2 = new QLineEdit("Test Line Edit", w);
+
+ layout->addWidget(pb1);
+ layout->addWidget(pb2);
+
+ pb2->setFocus();
+ pb2->setParent(0);
+ delete pb2;
+
+ w->show();
+ QApplication::setActiveWindow(w); // needs this on twm (focus follows mouse)
+ QVERIFY(pb1->hasFocus());
+ delete w;
+}
+
+
+/* This might fail on some X11 window managers? */
+void tst_QApplication::focusChanged()
+{
+ int argc = 0;
+ QApplication app(argc, 0, QApplication::GuiServer);
+
+ QSignalSpy spy(&app, SIGNAL(focusChanged(QWidget *, QWidget *)));
+ QWidget *now = 0;
+ QWidget *old = 0;
+
+ QWidget parent1;
+ QHBoxLayout hbox1(&parent1);
+ QLabel lb1(&parent1);
+ QLineEdit le1(&parent1);
+ QPushButton pb1(&parent1);
+ hbox1.addWidget(&lb1);
+ hbox1.addWidget(&le1);
+ hbox1.addWidget(&pb1);
+
+ QCOMPARE(spy.count(), 0);
+
+ parent1.show();
+ QApplication::setActiveWindow(&parent1); // needs this on twm (focus follows mouse)
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).count(), 2);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &le1);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == 0);
+ spy.clear();
+ QCOMPARE(spy.count(), 0);
+
+ pb1.setFocus();
+ QCOMPARE(spy.count(), 1);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &pb1);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &le1);
+ spy.clear();
+
+ lb1.setFocus();
+ QCOMPARE(spy.count(), 1);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &lb1);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &pb1);
+ spy.clear();
+
+ lb1.clearFocus();
+ QCOMPARE(spy.count(), 1);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == 0);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &lb1);
+ spy.clear();
+
+ QWidget parent2;
+ QHBoxLayout hbox2(&parent2);
+ QLabel lb2(&parent2);
+ QLineEdit le2(&parent2);
+ QPushButton pb2(&parent2);
+ hbox2.addWidget(&lb2);
+ hbox2.addWidget(&le2);
+ hbox2.addWidget(&pb2);
+
+ parent2.show();
+ QApplication::setActiveWindow(&parent2); // needs this on twm (focus follows mouse)
+ QVERIFY(spy.count() > 0); // one for deactivation, one for activation on Windows
+ old = qVariantValue<QWidget*>(spy.at(spy.count()-1).at(0));
+ now = qVariantValue<QWidget*>(spy.at(spy.count()-1).at(1));
+ QVERIFY(now == &le2);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == 0);
+ spy.clear();
+
+ QTestKeyEvent tab(QTest::Press, Qt::Key_Tab, 0, 0);
+ QTestKeyEvent backtab(QTest::Press, Qt::Key_Backtab, 0, 0);
+ QTestMouseEvent click(QTest::MouseClick, Qt::LeftButton, 0, QPoint(5, 5), 0);
+
+ bool tabAllControls = true;
+#ifdef Q_WS_MAC
+ // Mac has two modes, one where you tab to everything, one where you can
+ // only tab to input controls, here's what we get. Determine which ones we
+ // should get.
+ QSettings appleSettings(QLatin1String("apple.com"));
+ QVariant appleValue = appleSettings.value(QLatin1String("AppleKeyboardUIMode"), 0);
+ tabAllControls = (appleValue.toInt() & 0x2);
+#endif
+
+ tab.simulate(now);
+ if (!tabAllControls) {
+ QVERIFY(spy.count() == 0);
+ QVERIFY(now == QApplication::focusWidget());
+ } else {
+ QVERIFY(spy.count() > 0);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &pb2);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &le2);
+ spy.clear();
+ }
+
+ if (!tabAllControls) {
+ QVERIFY(spy.count() == 0);
+ QVERIFY(now == QApplication::focusWidget());
+ } else {
+ tab.simulate(now);
+ QVERIFY(spy.count() > 0);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &le2);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &pb2);
+ spy.clear();
+ }
+
+ if (!tabAllControls) {
+ QVERIFY(spy.count() == 0);
+ QVERIFY(now == QApplication::focusWidget());
+ } else {
+ backtab.simulate(now);
+ QVERIFY(spy.count() > 0);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &pb2);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &le2);
+ spy.clear();
+ }
+
+
+ if (!tabAllControls) {
+ QVERIFY(spy.count() == 0);
+ QVERIFY(now == QApplication::focusWidget());
+ old = &pb2;
+ } else {
+ backtab.simulate(now);
+ QVERIFY(spy.count() > 0);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &le2);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &pb2);
+ spy.clear();
+ }
+
+ click.simulate(old);
+ if (!(pb2.focusPolicy() & Qt::ClickFocus)) {
+ QVERIFY(spy.count() == 0);
+ QVERIFY(now == QApplication::focusWidget());
+ } else {
+ QVERIFY(spy.count() > 0);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &pb2);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &le2);
+ spy.clear();
+
+ click.simulate(old);
+ QVERIFY(spy.count() > 0);
+ old = qVariantValue<QWidget*>(spy.at(0).at(0));
+ now = qVariantValue<QWidget*>(spy.at(0).at(1));
+ QVERIFY(now == &le2);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &pb2);
+ spy.clear();
+ }
+
+ parent1.activateWindow();
+ QApplication::setActiveWindow(&parent1); // needs this on twm (focus follows mouse)
+ QVERIFY(spy.count() == 1 || spy.count() == 2); // one for deactivation, one for activation on Windows
+
+ //on windows, the change of focus is made in 2 steps
+ //(the focusChanged SIGNAL is emitted twice)
+ if (spy.count()==1)
+ old = qVariantValue<QWidget*>(spy.at(spy.count()-1).at(0));
+ else
+ old = qVariantValue<QWidget*>(spy.at(spy.count()-2).at(0));
+ now = qVariantValue<QWidget*>(spy.at(spy.count()-1).at(1));
+ QVERIFY(now == &le1);
+ QVERIFY(now == QApplication::focusWidget());
+ QVERIFY(old == &le2);
+ spy.clear();
+}
+
+class LineEdit : public QLineEdit
+{
+public:
+ LineEdit(QWidget *parent = 0) : QLineEdit(parent) { }
+
+protected:
+ void focusOutEvent(QFocusEvent *e) {
+ QLineEdit::focusOutEvent(e);
+ if (objectName() == "le1")
+ setStyleSheet("");
+ }
+
+ void focusInEvent(QFocusEvent *e) {
+ QLineEdit::focusInEvent(e);
+ if (objectName() == "le2")
+ setStyleSheet("");
+ }
+};
+
+void tst_QApplication::focusOut()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+
+ // Tests the case where the style pointer changes when on focus in/out
+ // (the above is the case when the stylesheet changes)
+ QWidget w;
+ QLineEdit *le1 = new LineEdit(&w);
+ le1->setObjectName("le1");
+ le1->setStyleSheet("background: #fee");
+ le1->setFocus();
+
+ QLineEdit *le2 = new LineEdit(&w);
+ le2->setObjectName("le2");
+ le2->setStyleSheet("background: #fee");
+ le2->move(100, 100);
+ w.show();
+
+ QTest::qWait(2000);
+ le2->setFocus();
+ QTest::qWait(2000);
+}
+
+void tst_QApplication::execAfterExit()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
+ // this should be ignored, as exec() will reset the exitCode
+ QApplication::exit(1);
+ int exitCode = app.exec();
+ QCOMPARE(exitCode, 0);
+
+ // the quitNow flag should have been reset, so we can spin an
+ // eventloop after QApplication::exec() returns
+ QEventLoop eventLoop;
+ QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
+ exitCode = eventLoop.exec();
+ QCOMPARE(exitCode, 0);
+}
+
+void tst_QApplication::wheelScrollLines()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ // If wheelScrollLines returns 0, the mose wheel will be disabled.
+ QVERIFY(app.wheelScrollLines() > 0);
+}
+
+void tst_QApplication::style()
+{
+ int argc = 1;
+
+ {
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QPointer<QStyle> style = app.style();
+ app.setStyle(new QWindowsStyle);
+ QVERIFY(style.isNull());
+ }
+
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+
+ // qApp style can never be 0
+ QVERIFY(QApplication::style() != 0);
+}
+
+void tst_QApplication::allWidgets()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QWidget *w = new QWidget;
+ QVERIFY(app.allWidgets().contains(w)); // uncreate widget test
+ QVERIFY(app.allWidgets().contains(w)); // created widget test
+ delete w;
+ w = 0;
+ QVERIFY(!app.allWidgets().contains(w)); // removal test
+}
+
+void tst_QApplication::topLevelWidgets()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QWidget *w = new QWidget;
+ w->show();
+#ifndef QT_NO_CLIPBOARD
+ QClipboard *clipboard = QApplication::clipboard();
+ QString originalText = clipboard->text();
+ clipboard->setText(QString("newText"));
+#endif
+ app.processEvents();
+ QVERIFY(QApplication::topLevelWidgets().contains(w));
+ QCOMPARE(QApplication::topLevelWidgets().count(), 1);
+ delete w;
+ w = 0;
+ app.processEvents();
+ QCOMPARE(QApplication::topLevelWidgets().count(), 0);
+}
+
+
+
+void tst_QApplication::setAttribute()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QVERIFY(!QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
+ QWidget *w = new QWidget;
+ QVERIFY(!w->testAttribute(Qt::WA_WState_Created));
+ delete w;
+
+ QApplication::setAttribute(Qt::AA_ImmediateWidgetCreation);
+ QVERIFY(QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
+ w = new QWidget;
+ QVERIFY(w->testAttribute(Qt::WA_WState_Created));
+ QWidget *w2 = new QWidget(w);
+ w2->setParent(0);
+ QVERIFY(w2->testAttribute(Qt::WA_WState_Created));
+ delete w;
+ delete w2;
+
+ QApplication::setAttribute(Qt::AA_ImmediateWidgetCreation, false);
+ QVERIFY(!QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
+ w = new QWidget;
+ QVERIFY(!w->testAttribute(Qt::WA_WState_Created));
+ delete w;
+}
+
+void tst_QApplication::windowsCommandLine_data()
+{
+#if defined(Q_OS_WIN)
+ QTest::addColumn<QString>("args");
+ QTest::addColumn<QString>("expected");
+
+ QTest::newRow("hello world")
+ << QString("Hello \"World\"")
+ << QString("Hello \"World\"");
+ QTest::newRow("sql")
+ << QString("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PNR' AND TABLE_TYPE = 'VIEW' ORDER BY TABLE_NAME")
+ << QString("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PNR' AND TABLE_TYPE = 'VIEW' ORDER BY TABLE_NAME");
+#endif
+}
+
+void tst_QApplication::windowsCommandLine()
+{
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ QFETCH(QString, args);
+ QFETCH(QString, expected);
+
+ QProcess testProcess;
+#if defined(QT_DEBUG)
+ testProcess.start("wincmdline/debug/wincmdline", QStringList(args));
+#else
+ testProcess.start("wincmdline/release/wincmdline", QStringList(args));
+#endif
+ QVERIFY(testProcess.waitForFinished(10000));
+ QByteArray error = testProcess.readAllStandardError();
+ QString procError(error);
+ QCOMPARE(procError, expected);
+#endif
+}
+
+class TouchEventPropagationTestWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ bool seenTouchEvent, acceptTouchEvent, seenMouseEvent, acceptMouseEvent;
+
+ TouchEventPropagationTestWidget(QWidget *parent = 0)
+ : QWidget(parent), seenTouchEvent(false), acceptTouchEvent(false), seenMouseEvent(false), acceptMouseEvent(false)
+ { }
+
+ void reset()
+ {
+ seenTouchEvent = acceptTouchEvent = seenMouseEvent = acceptMouseEvent = false;
+ }
+
+ bool event(QEvent *event)
+ {
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ // qDebug() << objectName() << "seenMouseEvent = true";
+ seenMouseEvent = true;
+ event->setAccepted(acceptMouseEvent);
+ break;
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
+ // qDebug() << objectName() << "seenTouchEvent = true";
+ seenTouchEvent = true;
+ event->setAccepted(acceptTouchEvent);
+ break;
+ default:
+ return QWidget::event(event);
+ }
+ return true;
+ }
+};
+
+void tst_QApplication::touchEventPropagation()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+
+ QList<QTouchEvent::TouchPoint> pressedTouchPoints;
+ QTouchEvent::TouchPoint press(0);
+ press.setState(Qt::TouchPointPressed);
+ pressedTouchPoints << press;
+
+ QList<QTouchEvent::TouchPoint> releasedTouchPoints;
+ QTouchEvent::TouchPoint release(0);
+ release.setState(Qt::TouchPointReleased);
+ releasedTouchPoints << release;
+
+ {
+ // touch event behavior on a window
+ TouchEventPropagationTestWidget window;
+ window.setObjectName("1. window");
+
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ window.setAttribute(Qt::WA_AcceptTouchEvents);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ window.acceptTouchEvent = true;
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+ }
+
+ {
+ // touch event behavior on a window with a child widget
+ TouchEventPropagationTestWidget window;
+ window.setObjectName("2. window");
+ TouchEventPropagationTestWidget widget(&window);
+ widget.setObjectName("2. widget");
+
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(!widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.setAttribute(Qt::WA_AcceptTouchEvents);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.acceptMouseEvent = true;
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.acceptTouchEvent = true;
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(!window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.setAttribute(Qt::WA_AcceptTouchEvents, false);
+ window.setAttribute(Qt::WA_AcceptTouchEvents);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(!widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ window.acceptTouchEvent = true;
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(!widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+
+ window.reset();
+ widget.reset();
+ widget.acceptMouseEvent = true; // doesn't matter, touch events are propagated first
+ window.acceptTouchEvent = true;
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints);
+ qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints);
+ QVERIFY(!widget.seenTouchEvent);
+ QVERIFY(!widget.seenMouseEvent);
+ QVERIFY(window.seenTouchEvent);
+ QVERIFY(!window.seenMouseEvent);
+ }
+}
+
+void tst_QApplication::qtbug_12673()
+{
+ QProcess testProcess;
+ QStringList arguments;
+#ifdef Q_OS_MAC
+ testProcess.start("modal/modal.app", arguments);
+#else
+ testProcess.start("modal/modal", arguments);
+#endif
+ QVERIFY(testProcess.waitForFinished(20000));
+ QCOMPARE(testProcess.exitStatus(), QProcess::NormalExit);
+}
+
+/*
+ This test is meant to ensure that certain objects (public & commonly used)
+ can safely be used in a Q_GLOBAL_STATIC such that their destructors are
+ executed *after* the destruction of QApplication.
+ */
+Q_GLOBAL_STATIC(QLocale, tst_qapp_locale);
+Q_GLOBAL_STATIC(QProcess, tst_qapp_process);
+Q_GLOBAL_STATIC(QFileSystemWatcher, tst_qapp_fileSystemWatcher);
+Q_GLOBAL_STATIC(QSharedMemory, tst_qapp_sharedMemory);
+Q_GLOBAL_STATIC(QElapsedTimer, tst_qapp_elapsedTimer);
+Q_GLOBAL_STATIC(QMutex, tst_qapp_mutex);
+Q_GLOBAL_STATIC(QWidget, tst_qapp_widget);
+Q_GLOBAL_STATIC(QPixmap, tst_qapp_pixmap);
+Q_GLOBAL_STATIC(QFont, tst_qapp_font);
+Q_GLOBAL_STATIC(QRegion, tst_qapp_region);
+Q_GLOBAL_STATIC(QFontDatabase, tst_qapp_fontDatabase);
+Q_GLOBAL_STATIC(QCursor, tst_qapp_cursor);
+
+void tst_QApplication::globalStaticObjectDestruction()
+{
+ int argc = 1;
+ QApplication app(argc, &argv0, QApplication::GuiServer);
+ QVERIFY(tst_qapp_locale());
+ QVERIFY(tst_qapp_process());
+ QVERIFY(tst_qapp_fileSystemWatcher());
+ QVERIFY(tst_qapp_sharedMemory());
+ QVERIFY(tst_qapp_elapsedTimer());
+ QVERIFY(tst_qapp_mutex());
+ QVERIFY(tst_qapp_widget());
+ QVERIFY(tst_qapp_pixmap());
+ QVERIFY(tst_qapp_font());
+ QVERIFY(tst_qapp_region());
+ QVERIFY(tst_qapp_fontDatabase());
+ QVERIFY(tst_qapp_cursor());
+}
+
+//QTEST_APPLESS_MAIN(tst_QApplication)
+int main(int argc, char *argv[])
+{
+ tst_QApplication tc;
+ argv0 = argv[0];
+ return QTest::qExec(&tc, argc, argv);
+}
+
+#include "tst_qapplication.moc"
diff --git a/tests/auto/widgets/kernel/qapplication/wincmdline/main.cpp b/tests/auto/widgets/kernel/qapplication/wincmdline/main.cpp
new file mode 100644
index 0000000000..d0f802231a
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/wincmdline/main.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QApplication>
+#include <stdio.h>
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ if (argc > 1)
+ fprintf(stderr, "%s", argv[1]);
+ else
+ fprintf(stderr, "Failed");
+ fflush(stderr);
+ return 0;
+}
+
diff --git a/tests/auto/widgets/kernel/qapplication/wincmdline/wincmdline.pro b/tests/auto/widgets/kernel/qapplication/wincmdline/wincmdline.pro
new file mode 100644
index 0000000000..3ba8f48167
--- /dev/null
+++ b/tests/auto/widgets/kernel/qapplication/wincmdline/wincmdline.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += widgets
+SOURCES += main.cpp
+
+
diff --git a/tests/auto/widgets/kernel/qboxlayout/.gitignore b/tests/auto/widgets/kernel/qboxlayout/.gitignore
new file mode 100644
index 0000000000..034edba563
--- /dev/null
+++ b/tests/auto/widgets/kernel/qboxlayout/.gitignore
@@ -0,0 +1 @@
+tst_qboxlayout
diff --git a/tests/auto/widgets/kernel/qboxlayout/qboxlayout.pro b/tests/auto/widgets/kernel/qboxlayout/qboxlayout.pro
new file mode 100644
index 0000000000..c37f12f74f
--- /dev/null
+++ b/tests/auto/widgets/kernel/qboxlayout/qboxlayout.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qboxlayout.cpp
+
+
diff --git a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
new file mode 100644
index 0000000000..4e5b357de5
--- /dev/null
+++ b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui>
+#include <QtWidgets>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QBoxLayout : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QBoxLayout();
+ virtual ~tst_QBoxLayout();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void insertSpacerItem();
+ void sizeHint();
+ void sizeConstraints();
+ void setGeometry();
+ void setStyleShouldChangeSpacing();
+
+ void taskQTBUG_7103_minMaxWidthNotRespected();
+};
+
+class CustomLayoutStyle : public QWindowsStyle
+{
+ Q_OBJECT
+public:
+ CustomLayoutStyle() : QWindowsStyle()
+ {
+ hspacing = 5;
+ vspacing = 10;
+ }
+
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption * option = 0,
+ const QWidget * widget = 0 ) const;
+
+ int hspacing;
+ int vspacing;
+};
+
+int CustomLayoutStyle::pixelMetric(PixelMetric metric, const QStyleOption * option /*= 0*/,
+ const QWidget * widget /*= 0*/ ) const
+{
+ switch (metric) {
+ case PM_LayoutLeftMargin:
+ return 0;
+ break;
+ case PM_LayoutTopMargin:
+ return 3;
+ break;
+ case PM_LayoutRightMargin:
+ return 6;
+ break;
+ case PM_LayoutBottomMargin:
+ return 9;
+ break;
+ case PM_LayoutHorizontalSpacing:
+ return hspacing;
+ case PM_LayoutVerticalSpacing:
+ return vspacing;
+ break;
+ default:
+ break;
+ }
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+}
+
+
+tst_QBoxLayout::tst_QBoxLayout()
+{
+}
+
+tst_QBoxLayout::~tst_QBoxLayout()
+{
+}
+
+void tst_QBoxLayout::initTestCase()
+{
+}
+
+void tst_QBoxLayout::cleanupTestCase()
+{
+}
+
+void tst_QBoxLayout::init()
+{
+}
+
+void tst_QBoxLayout::cleanup()
+{
+}
+
+void tst_QBoxLayout::insertSpacerItem()
+{
+ QWidget *window = new QWidget;
+
+ QSpacerItem *spacer1 = new QSpacerItem(20, 10, QSizePolicy::Expanding, QSizePolicy::Expanding);
+ QSpacerItem *spacer2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ QBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(new QLineEdit("Foooooooooooooooooooooooooo"));
+ layout->addSpacerItem(spacer1);
+ layout->addWidget(new QLineEdit("Baaaaaaaaaaaaaaaaaaaaaaaaar"));
+ layout->insertSpacerItem(0, spacer2);
+ window->setLayout(layout);
+
+ QVERIFY(layout->itemAt(0) == spacer2);
+ QVERIFY(layout->itemAt(2) == spacer1);
+
+ window->show();
+}
+
+void tst_QBoxLayout::sizeHint()
+{
+ QWidget *window = new QWidget;
+ QHBoxLayout *lay1 = new QHBoxLayout;
+ QHBoxLayout *lay2 = new QHBoxLayout;
+ QLabel *label = new QLabel("widget twooooooooooooooooooooooooooooooooooooooooooooooooooooooo");
+ lay2->addWidget(label);
+ lay1->addLayout(lay2);
+ window->setLayout(lay1);
+ window->show();
+ label->setText("foooooooo baaaaaaar");
+ QSize sh = lay1->sizeHint();
+ QApplication::processEvents();
+ // Note that this is not strictly required behaviour - actually
+ // the preferred behaviour would be that sizeHint returns
+ // the same value regardless of what's lying in the event queue.
+ // (i.e. we would check for equality here instead)
+ QVERIFY(lay1->sizeHint() != sh);
+}
+
+void tst_QBoxLayout::sizeConstraints()
+{
+ QWidget *window = new QWidget;
+ QHBoxLayout *lay = new QHBoxLayout;
+ lay->addWidget(new QLabel("foooooooooooooooooooooooooooooooooooo"));
+ lay->addWidget(new QLabel("baaaaaaaaaaaaaaaaaaaaaaaaaaaaaar"));
+ lay->setSizeConstraint(QLayout::SetFixedSize);
+ window->setLayout(lay);
+ window->show();
+ QApplication::processEvents();
+ QSize sh = window->sizeHint();
+ lay->takeAt(1);
+ QVERIFY(sh.width() >= window->sizeHint().width() &&
+ sh.height() >= window->sizeHint().height());
+
+}
+
+void tst_QBoxLayout::setGeometry()
+{
+ QWidget toplevel;
+ QWidget w(&toplevel);
+ QVBoxLayout *lay = new QVBoxLayout;
+ lay->setMargin(0);
+ lay->setSpacing(0);
+ QHBoxLayout *lay2 = new QHBoxLayout;
+ QDial *dial = new QDial;
+ lay2->addWidget(dial);
+ lay2->setAlignment(Qt::AlignTop);
+ lay2->setAlignment(Qt::AlignRight);
+ lay->addLayout(lay2);
+ w.setLayout(lay);
+ toplevel.show();
+
+ QRect newGeom(0, 0, 70, 70);
+ lay2->setGeometry(newGeom);
+ QVERIFY2(newGeom.contains(dial->geometry()), "dial->geometry() should be smaller and within newGeom");
+}
+
+void tst_QBoxLayout::setStyleShouldChangeSpacing()
+{
+
+ QWidget *window = new QWidget;
+ QHBoxLayout *hbox = new QHBoxLayout(window);
+ QPushButton *pb1 = new QPushButton(tr("The spacing between this"));
+ QPushButton *pb2 = new QPushButton(tr("and this button should depend on the style of the parent widget"));;
+ pb1->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ pb2->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ hbox->addWidget(pb1);
+ hbox->addWidget(pb2);
+ CustomLayoutStyle *style1 = new CustomLayoutStyle;
+ style1->hspacing = 6;
+ window->setStyle(style1);
+ window->show();
+
+ QTest::qWait(100);
+ int spacing = pb2->geometry().left() - pb1->geometry().right() - 1;
+ QCOMPARE(spacing, 6);
+
+ CustomLayoutStyle *style2 = new CustomLayoutStyle();
+ style2->hspacing = 10;
+ window->setStyle(style2);
+ QTest::qWait(100);
+ spacing = pb2->geometry().left() - pb1->geometry().right() - 1;
+ QCOMPARE(spacing, 10);
+
+ delete window;
+ delete style1;
+ delete style2;
+}
+
+void tst_QBoxLayout::taskQTBUG_7103_minMaxWidthNotRespected()
+{
+ QLabel *label = new QLabel("Qt uses standard C++, but makes extensive use of the C pre-processor to enrich the language. Qt can also be used in several other programming languages via language bindings. It runs on all major platforms, and has extensive internationalization support. Non-GUI features include SQL database access, XML parsing, thread management, network support and a unified cross-platform API for file handling.");
+ label->setWordWrap(true);
+ label->setFixedWidth(200);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(label);
+ layout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Expanding));
+
+ QWidget widget;
+ widget.setLayout(layout);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+
+ int height = label->height();
+
+ QRect g = widget.geometry();
+ g.setWidth(600);
+ widget.setGeometry(g);
+
+ QTest::qWait(50);
+
+ QCOMPARE(label->height(), height);
+}
+
+QTEST_MAIN(tst_QBoxLayout)
+#include "tst_qboxlayout.moc"
diff --git a/tests/auto/widgets/kernel/qdesktopwidget/.gitignore b/tests/auto/widgets/kernel/qdesktopwidget/.gitignore
new file mode 100644
index 0000000000..d6f7cc7ca9
--- /dev/null
+++ b/tests/auto/widgets/kernel/qdesktopwidget/.gitignore
@@ -0,0 +1 @@
+tst_qdesktopwidget
diff --git a/tests/auto/widgets/kernel/qdesktopwidget/qdesktopwidget.pro b/tests/auto/widgets/kernel/qdesktopwidget/qdesktopwidget.pro
new file mode 100644
index 0000000000..730b273c4f
--- /dev/null
+++ b/tests/auto/widgets/kernel/qdesktopwidget/qdesktopwidget.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qdesktopwidget.cpp
diff --git a/tests/auto/widgets/kernel/qdesktopwidget/tst_qdesktopwidget.cpp b/tests/auto/widgets/kernel/qdesktopwidget/tst_qdesktopwidget.cpp
new file mode 100644
index 0000000000..e7e3abeb25
--- /dev/null
+++ b/tests/auto/widgets/kernel/qdesktopwidget/tst_qdesktopwidget.cpp
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtWidgets/QDesktopWidget>
+#include <QDebug>
+
+//TESTED_CLASS=
+
+class tst_QDesktopWidget : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QDesktopWidget();
+ virtual ~tst_QDesktopWidget();
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void numScreens();
+ void primaryScreen();
+ void screenNumberForQWidget();
+ void screenNumberForQPoint();
+ void availableGeometry();
+ void screenGeometry();
+};
+
+tst_QDesktopWidget::tst_QDesktopWidget()
+{
+}
+
+tst_QDesktopWidget::~tst_QDesktopWidget()
+{
+}
+
+void tst_QDesktopWidget::init()
+{
+}
+
+void tst_QDesktopWidget::cleanup()
+{
+}
+
+void tst_QDesktopWidget::numScreens()
+{
+ QDesktopWidget desktop;
+ QVERIFY(desktop.numScreens() > 0);
+}
+
+void tst_QDesktopWidget::primaryScreen()
+{
+ QDesktopWidget desktop;
+ QVERIFY(desktop.primaryScreen() >= 0);
+ QVERIFY(desktop.primaryScreen() < desktop.numScreens());
+}
+
+void tst_QDesktopWidget::availableGeometry()
+{
+ QDesktopWidget desktop;
+ QTest::ignoreMessage(QtWarningMsg, "QDesktopWidget::availableGeometry(): Attempt "
+ "to get the available geometry of a null widget");
+ desktop.availableGeometry((QWidget *)0);
+
+ QRect total;
+ QRect available;
+
+ for (int i = 0; i < desktop.screenCount(); ++i) {
+ total = desktop.screenGeometry(i);
+ available = desktop.availableGeometry(i);
+ QVERIFY(total.contains(available));
+ }
+
+ total = desktop.screenGeometry();
+ available = desktop.availableGeometry();
+ QVERIFY(total.contains(available));
+ QCOMPARE(desktop.availableGeometry(desktop.primaryScreen()), available);
+ QCOMPARE(desktop.screenGeometry(desktop.primaryScreen()), total);
+}
+
+void tst_QDesktopWidget::screenNumberForQWidget()
+{
+ QDesktopWidget desktop;
+
+ QCOMPARE(desktop.screenNumber(0), 0);
+
+ QWidget widget;
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QVERIFY(widget.isVisible());
+
+ int widgetScreen = desktop.screenNumber(&widget);
+ QVERIFY(widgetScreen > -1);
+ QVERIFY(widgetScreen < desktop.numScreens());
+}
+
+void tst_QDesktopWidget::screenNumberForQPoint()
+{
+ // make sure QDesktopWidget::screenNumber(QPoint) returns the correct screen
+ QDesktopWidget *desktopWidget = QApplication::desktop();
+ QRect allScreens;
+ for (int i = 0; i < desktopWidget->numScreens(); ++i) {
+ QRect screenGeometry = desktopWidget->screenGeometry(i);
+ QCOMPARE(desktopWidget->screenNumber(screenGeometry.center()), i);
+ allScreens |= screenGeometry;
+ }
+
+ // make sure QDesktopWidget::screenNumber(QPoint) returns a valid screen for points that aren't on any screen
+ int screen;
+ screen = desktopWidget->screenNumber(allScreens.topLeft() - QPoint(1, 1));
+
+#ifdef Q_WS_QWS
+ QEXPECT_FAIL("", "Task 151710", Abort);
+#endif
+ QVERIFY(screen >= 0 && screen < desktopWidget->numScreens());
+ screen = desktopWidget->screenNumber(allScreens.topRight() + QPoint(1, 1));
+ QVERIFY(screen >= 0 && screen < desktopWidget->numScreens());
+ screen = desktopWidget->screenNumber(allScreens.bottomLeft() - QPoint(1, 1));
+ QVERIFY(screen >= 0 && screen < desktopWidget->numScreens());
+ screen = desktopWidget->screenNumber(allScreens.bottomRight() + QPoint(1, 1));
+ QVERIFY(screen >= 0 && screen < desktopWidget->numScreens());
+}
+
+void tst_QDesktopWidget::screenGeometry()
+{
+ QDesktopWidget *desktopWidget = QApplication::desktop();
+ QTest::ignoreMessage(QtWarningMsg, "QDesktopWidget::screenGeometry(): Attempt "
+ "to get the screen geometry of a null widget");
+ QRect r = desktopWidget->screenGeometry((QWidget *)0);
+ QVERIFY(r.isNull());
+ QWidget widget;
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ r = desktopWidget->screenGeometry(&widget);
+
+ QRect total;
+ QRect available;
+ for (int i = 0; i < desktopWidget->screenCount(); ++i) {
+ total = desktopWidget->screenGeometry(i);
+ available = desktopWidget->availableGeometry(i);
+ }
+}
+
+QTEST_MAIN(tst_QDesktopWidget)
+#include "tst_qdesktopwidget.moc"
+
diff --git a/tests/auto/widgets/kernel/qformlayout/.gitignore b/tests/auto/widgets/kernel/qformlayout/.gitignore
new file mode 100644
index 0000000000..24e93d561f
--- /dev/null
+++ b/tests/auto/widgets/kernel/qformlayout/.gitignore
@@ -0,0 +1 @@
+tst_qformlayout
diff --git a/tests/auto/widgets/kernel/qformlayout/qformlayout.pro b/tests/auto/widgets/kernel/qformlayout/qformlayout.pro
new file mode 100644
index 0000000000..24c452af9f
--- /dev/null
+++ b/tests/auto/widgets/kernel/qformlayout/qformlayout.pro
@@ -0,0 +1,3 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qformlayout.cpp
diff --git a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
new file mode 100644
index 0000000000..4425205eb9
--- /dev/null
+++ b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
@@ -0,0 +1,913 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qlayout.h>
+#include <qapplication.h>
+#include <qwidget.h>
+#include <qwindowsstyle.h>
+#include <qsizepolicy.h>
+
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QPlastiqueStyle>
+#include <QtWidgets/QWindowsStyle>
+#include <QStyleFactory>
+
+#include <qformlayout.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QFormLayout : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QFormLayout();
+ ~tst_QFormLayout();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void rowCount();
+ void buddies();
+ void getItemPosition();
+ void wrapping();
+ void spacing();
+ void contentsRect();
+
+ void setFormStyle();
+ void setFieldGrowthPolicy();
+ void setRowWrapPolicy();
+ void setLabelAlignment();
+ void setFormAlignment();
+
+/*
+ void setHorizontalSpacing(int spacing);
+ int horizontalSpacing() const;
+ void setVerticalSpacing(int spacing);
+ int verticalSpacing() const;
+*/
+
+ void addRow();
+ void insertRow_QWidget_QWidget();
+ void insertRow_QWidget_QLayout();
+ void insertRow_QString_QWidget();
+ void insertRow_QString_QLayout();
+ void insertRow_QWidget();
+ void insertRow_QLayout();
+ void setWidget();
+ void setLayout();
+
+/*
+ QLayoutItem *itemAt(int row, ItemRole role) const;
+ void getItemPosition(int index, int *rowPtr, ItemRole *rolePtr) const;
+ void getLayoutPosition(QWidget *widget, int *rowPtr, ItemRole *rolePtr) const;
+ void getItemPosition(QLayoutItem *item, int *rowPtr, ItemRole *rolePtr) const;
+ QWidget *labelForField(QWidget *widget) const;
+ QWidget *labelForField(QLayoutItem *item) const;
+
+ void addItem(QLayoutItem *item);
+*/
+
+ void itemAt();
+ void takeAt();
+ void layoutAlone();
+/*
+ void setGeometry(const QRect &rect);
+ QSize minimumSize() const;
+ QSize sizeHint() const;
+
+ bool hasHeightForWidth() const;
+ int heightForWidth(int width) const;
+ Qt::Orientations expandingDirections() const;
+*/
+
+};
+
+tst_QFormLayout::tst_QFormLayout()
+{
+}
+
+tst_QFormLayout::~tst_QFormLayout()
+{
+}
+
+void tst_QFormLayout::initTestCase()
+{
+}
+
+void tst_QFormLayout::cleanupTestCase()
+{
+}
+
+void tst_QFormLayout::init()
+{
+}
+
+void tst_QFormLayout::cleanup()
+{
+}
+
+void tst_QFormLayout::rowCount()
+{
+ QWidget *w = new QWidget;
+ QFormLayout *fl = new QFormLayout(w);
+
+ fl->addRow(tr("Label 1"), new QLineEdit);
+ fl->addRow(tr("Label 2"), new QLineEdit);
+ fl->addRow(tr("Label 3"), new QLineEdit);
+ QCOMPARE(fl->rowCount(), 3);
+
+ fl->addRow(new QWidget);
+ fl->addRow(new QHBoxLayout);
+ QCOMPARE(fl->rowCount(), 5);
+
+ fl->insertRow(1, tr("Label 0.5"), new QLineEdit);
+ QCOMPARE(fl->rowCount(), 6);
+
+ //TODO: remove items
+
+ delete w;
+}
+
+void tst_QFormLayout::buddies()
+{
+ QWidget *w = new QWidget;
+ QFormLayout *fl = new QFormLayout(w);
+
+ //normal buddy case
+ QLineEdit *le = new QLineEdit;
+ fl->addRow(tr("Label 1"), le);
+ QLabel *label = qobject_cast<QLabel *>(fl->labelForField(le));
+ QVERIFY(label);
+ QWidget *lew = le;
+ QCOMPARE(label->buddy(), lew);
+
+ //null label
+ QLineEdit *le2 = new QLineEdit;
+ fl->addRow(0, le2);
+ QWidget *label2 = fl->labelForField(le2);
+ QVERIFY(label2 == 0);
+
+ //no label
+ QLineEdit *le3 = new QLineEdit;
+ fl->addRow(le3);
+ QWidget *label3 = fl->labelForField(le3);
+ QVERIFY(label3 == 0);
+
+ //TODO: empty label?
+
+ delete w;
+}
+
+void tst_QFormLayout::getItemPosition()
+{
+ QWidget *w = new QWidget;
+ QFormLayout *fl = new QFormLayout(w);
+
+ QList<QLabel*> labels;
+ QList<QLineEdit*> fields;
+ for (int i = 0; i < 5; ++i) {
+ labels.append(new QLabel(QString("Label %1").arg(i+1)));
+ fields.append(new QLineEdit);
+ fl->addRow(labels[i], fields[i]);
+ }
+
+ //a field
+ {
+ int row;
+ QFormLayout::ItemRole role;
+ fl->getWidgetPosition(fields[3], &row, &role);
+ QCOMPARE(row, 3);
+ QCOMPARE(role, QFormLayout::FieldRole);
+ }
+
+ //a label
+ {
+ int row;
+ QFormLayout::ItemRole role;
+ fl->getWidgetPosition(labels[2], &row, &role);
+ QCOMPARE(row, 2);
+ QCOMPARE(role, QFormLayout::LabelRole);
+ }
+
+ //a layout that's been inserted
+ {
+ QVBoxLayout *vbl = new QVBoxLayout;
+ fl->insertRow(2, "Label 1.5", vbl);
+ int row;
+ QFormLayout::ItemRole role;
+ fl->getLayoutPosition(vbl, &row, &role);
+ QCOMPARE(row, 2);
+ QCOMPARE(role, QFormLayout::FieldRole);
+ }
+
+ delete w;
+}
+
+void tst_QFormLayout::wrapping()
+{
+ QWidget *w = new QWidget;
+ QFormLayout *fl = new QFormLayout(w);
+ fl->setRowWrapPolicy(QFormLayout::WrapLongRows);
+
+ QLineEdit *le = new QLineEdit;
+ QLabel *lbl = new QLabel("A long label");
+ le->setMinimumWidth(200);
+ fl->addRow(lbl, le);
+
+ w->setFixedWidth(240);
+ w->show();
+
+ QCOMPARE(le->geometry().y() > lbl->geometry().y(), true);
+
+ //TODO: additional tests covering different wrapping cases
+
+ delete w;
+}
+
+class CustomLayoutStyle : public QWindowsStyle
+{
+ Q_OBJECT
+public:
+ CustomLayoutStyle()
+ {
+ hspacing = 5;
+ vspacing = 10;
+ }
+
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption * option = 0,
+ const QWidget * widget = 0 ) const;
+
+ int hspacing;
+ int vspacing;
+};
+
+int CustomLayoutStyle::pixelMetric(PixelMetric metric, const QStyleOption * option /*= 0*/,
+ const QWidget * widget /*= 0*/ ) const
+{
+ switch (metric) {
+ case PM_LayoutHorizontalSpacing:
+ return hspacing;
+ case PM_LayoutVerticalSpacing:
+ return vspacing;
+ break;
+ default:
+ break;
+ }
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+}
+
+void tst_QFormLayout::spacing()
+{
+ //TODO: confirm spacing behavior
+ QWidget *w = new QWidget;
+ CustomLayoutStyle *style = new CustomLayoutStyle;
+ style->hspacing = 5;
+ style->vspacing = 10;
+ w->setStyle(style);
+ QFormLayout *fl = new QFormLayout(w);
+ QCOMPARE(style->hspacing, fl->horizontalSpacing());
+ QCOMPARE(style->vspacing, fl->verticalSpacing());
+
+ //QCOMPARE(fl->spacing(), -1);
+ fl->setVerticalSpacing(5);
+ QCOMPARE(5, fl->horizontalSpacing());
+ QCOMPARE(5, fl->verticalSpacing());
+ //QCOMPARE(fl->spacing(), 5);
+ fl->setVerticalSpacing(-1);
+ QCOMPARE(style->hspacing, fl->horizontalSpacing());
+ QCOMPARE(style->vspacing, fl->verticalSpacing());
+
+ style->hspacing = 5;
+ style->vspacing = 5;
+ //QCOMPARE(fl->spacing(), 5);
+
+ fl->setHorizontalSpacing(20);
+ //QCOMPARE(fl->spacing(), -1);
+ style->vspacing = 20;
+ QCOMPARE(fl->horizontalSpacing(), 20);
+ QCOMPARE(fl->verticalSpacing(), 20);
+ //QCOMPARE(fl->spacing(), 20);
+ fl->setHorizontalSpacing(-1);
+ //QCOMPARE(fl->spacing(), -1);
+ style->hspacing = 20;
+ //QCOMPARE(fl->spacing(), 20);
+
+ delete w;
+ delete style;
+}
+
+void tst_QFormLayout::contentsRect()
+{
+ QWidget w;
+ QFormLayout form;
+ w.setLayout(&form);
+ form.addRow("Label", new QPushButton(&w));
+ w.show();
+/*#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(&w); // wait for the show
+#endif*/
+ int l, t, r, b;
+ form.getContentsMargins(&l, &t, &r, &b);
+ QRect geom = form.geometry();
+
+ QCOMPARE(geom.adjusted(+l, +t, -r, -b), form.contentsRect());
+}
+
+
+class DummyMacStyle : public QCommonStyle
+{
+public:
+ virtual int styleHint ( StyleHint hint, const QStyleOption * option = 0, const QWidget * widget = 0, QStyleHintReturn * returnData = 0 ) const
+ {
+ switch(hint) {
+ case SH_FormLayoutFormAlignment:
+ return Qt::AlignHCenter | Qt::AlignTop;
+ case SH_FormLayoutLabelAlignment:
+ return Qt::AlignRight;
+ case SH_FormLayoutWrapPolicy:
+ return QFormLayout::DontWrapRows;
+ case SH_FormLayoutFieldGrowthPolicy:
+ return QFormLayout::FieldsStayAtSizeHint;
+ default:
+ return QCommonStyle::styleHint(hint, option, widget, returnData);
+ }
+ }
+};
+
+class DummyQtopiaStyle : public QCommonStyle
+{
+public:
+ virtual int styleHint ( StyleHint hint, const QStyleOption * option = 0, const QWidget * widget = 0, QStyleHintReturn * returnData = 0 ) const
+ {
+ switch(hint) {
+ case SH_FormLayoutFormAlignment:
+ return Qt::AlignLeft | Qt::AlignTop;
+ case SH_FormLayoutLabelAlignment:
+ return Qt::AlignRight;
+ case SH_FormLayoutWrapPolicy:
+ return QFormLayout::WrapLongRows;
+ case SH_FormLayoutFieldGrowthPolicy:
+ return QFormLayout::AllNonFixedFieldsGrow;
+ default:
+ return QCommonStyle::styleHint(hint, option, widget, returnData);
+ }
+ }
+};
+
+void tst_QFormLayout::setFormStyle()
+{
+ QWidget widget;
+ QFormLayout layout;
+ widget.setLayout(&layout);
+
+#ifndef QT_NO_STYLE_PLASTIQUE
+ widget.setStyle(new QPlastiqueStyle());
+
+ QVERIFY(layout.labelAlignment() == Qt::AlignRight);
+ QVERIFY(layout.formAlignment() == (Qt::AlignLeft | Qt::AlignTop));
+ QVERIFY(layout.fieldGrowthPolicy() == QFormLayout::ExpandingFieldsGrow);
+ QVERIFY(layout.rowWrapPolicy() == QFormLayout::DontWrapRows);
+#endif
+
+ widget.setStyle(new QWindowsStyle());
+
+ QVERIFY(layout.labelAlignment() == Qt::AlignLeft);
+ QVERIFY(layout.formAlignment() == (Qt::AlignLeft | Qt::AlignTop));
+ QVERIFY(layout.fieldGrowthPolicy() == QFormLayout::AllNonFixedFieldsGrow);
+ QVERIFY(layout.rowWrapPolicy() == QFormLayout::DontWrapRows);
+
+ /* can't directly create mac style or qtopia style, since
+ this test is cross platform.. so create dummy styles that
+ return all the right stylehints.
+ */
+ widget.setStyle(new DummyMacStyle());
+
+ QVERIFY(layout.labelAlignment() == Qt::AlignRight);
+ QVERIFY(layout.formAlignment() == (Qt::AlignHCenter | Qt::AlignTop));
+ QVERIFY(layout.fieldGrowthPolicy() == QFormLayout::FieldsStayAtSizeHint);
+ QVERIFY(layout.rowWrapPolicy() == QFormLayout::DontWrapRows);
+
+ widget.setStyle(new DummyQtopiaStyle());
+
+ QVERIFY(layout.labelAlignment() == Qt::AlignRight);
+ QVERIFY(layout.formAlignment() == (Qt::AlignLeft | Qt::AlignTop));
+ QVERIFY(layout.fieldGrowthPolicy() == QFormLayout::AllNonFixedFieldsGrow);
+ QVERIFY(layout.rowWrapPolicy() == QFormLayout::WrapLongRows);
+}
+
+void tst_QFormLayout::setFieldGrowthPolicy()
+{
+ QWidget window;
+ QLineEdit fld1, fld2, fld3;
+ fld1.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ fld2.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ fld3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+
+ QFormLayout layout;
+ layout.addRow("One:", &fld1);
+ layout.addRow("Two:", &fld2);
+ layout.addRow("Three:", &fld3);
+ window.setLayout(&layout);
+ window.resize(1000, 200);
+
+ for (int i = 0; i < 3; ++i) {
+ layout.setFieldGrowthPolicy(i == 0 ? QFormLayout::FieldsStayAtSizeHint :
+ i == 1 ? QFormLayout::ExpandingFieldsGrow :
+ QFormLayout::AllNonFixedFieldsGrow);
+ layout.activate();
+
+ if (i == 0) {
+ QVERIFY(fld1.width() == fld2.width());
+ QVERIFY(fld2.width() == fld3.width());
+ } else if (i == 1) {
+ QVERIFY(fld1.width() == fld2.width());
+ QVERIFY(fld2.width() < fld3.width());
+ } else {
+ QVERIFY(fld1.width() < fld2.width());
+ QVERIFY(fld2.width() == fld3.width());
+ }
+ }
+}
+
+void tst_QFormLayout::setRowWrapPolicy()
+{
+}
+
+void tst_QFormLayout::setLabelAlignment()
+{
+}
+
+void tst_QFormLayout::setFormAlignment()
+{
+}
+
+void tst_QFormLayout::addRow()
+{
+ QFormLayout layout;
+ QWidget w1, w2, w3;
+ QHBoxLayout l1, l2, l3;
+ QLabel lbl1, lbl2;
+
+ QCOMPARE(layout.rowCount(), 0);
+
+ layout.addRow(&lbl1, &w1);
+ layout.addRow(&lbl2, &l1);
+ layout.addRow("Foo:", &w2);
+ layout.addRow("Bar:", &l2);
+ layout.addRow(&w3);
+ layout.addRow(&l3);
+
+ QCOMPARE(layout.rowCount(), 6);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::LabelRole)->widget() == &lbl1);
+ QVERIFY(layout.itemAt(1, QFormLayout::LabelRole)->widget() == &lbl2);
+ QVERIFY(layout.itemAt(2, QFormLayout::LabelRole)->widget()->property("text") == "Foo:");
+ QVERIFY(layout.itemAt(3, QFormLayout::LabelRole)->widget()->property("text") == "Bar:");
+ QVERIFY(layout.itemAt(4, QFormLayout::LabelRole) == 0);
+ QVERIFY(layout.itemAt(5, QFormLayout::LabelRole) == 0);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::FieldRole)->widget() == &w1);
+ QVERIFY(layout.itemAt(1, QFormLayout::FieldRole)->layout() == &l1);
+ QVERIFY(layout.itemAt(2, QFormLayout::FieldRole)->widget() == &w2);
+ QVERIFY(layout.itemAt(3, QFormLayout::FieldRole)->layout() == &l2);
+// ### should have a third role, FullRowRole?
+// QVERIFY(layout.itemAt(4, QFormLayout::FieldRole) == 0);
+// QVERIFY(layout.itemAt(5, QFormLayout::FieldRole) == 0);
+}
+
+void tst_QFormLayout::insertRow_QWidget_QWidget()
+{
+ QFormLayout layout;
+ QLabel lbl1, lbl2, lbl3, lbl4;
+ QLineEdit fld1, fld2, fld3, fld4;
+
+ layout.insertRow(0, &lbl1, &fld1);
+ QCOMPARE(layout.rowCount(), 1);
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(&lbl1, &row, &role);
+ QCOMPARE(row, 0);
+ QCOMPARE(int(role), int(QFormLayout::LabelRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(&fld1, &row, &role);
+ QCOMPARE(row, 0);
+ QCOMPARE(int(role), int(QFormLayout::FieldRole));
+ }
+
+ // check that negative values append
+ layout.insertRow(-2, &lbl2, &fld2);
+ QCOMPARE(layout.rowCount(), 2);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::LabelRole)->widget() == &lbl1);
+ QVERIFY(layout.itemAt(1, QFormLayout::LabelRole)->widget() == &lbl2);
+
+ // check that too large values append
+ layout.insertRow(100, &lbl3, &fld3);
+ QCOMPARE(layout.rowCount(), 3);
+ QCOMPARE(layout.count(), 6);
+
+ layout.insertRow(3, (QWidget *)0, (QWidget *)0);
+ QCOMPARE(layout.rowCount(), 4);
+ QCOMPARE(layout.count(), 6);
+
+ layout.insertRow(4, (QWidget *)0, &fld4);
+ QCOMPARE(layout.rowCount(), 5);
+ QCOMPARE(layout.count(), 7);
+
+ layout.insertRow(5, &lbl4, (QWidget *)0);
+ QCOMPARE(layout.rowCount(), 6);
+ QCOMPARE(layout.count(), 8);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::LabelRole)->widget() == &lbl1);
+ QVERIFY(layout.itemAt(1, QFormLayout::LabelRole)->widget() == &lbl2);
+ QVERIFY(layout.itemAt(2, QFormLayout::LabelRole)->widget() == &lbl3);
+ QVERIFY(layout.itemAt(3, QFormLayout::LabelRole) == 0);
+ QVERIFY(layout.itemAt(4, QFormLayout::LabelRole) == 0);
+ QVERIFY(layout.itemAt(5, QFormLayout::LabelRole)->widget() == &lbl4);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::FieldRole)->widget() == &fld1);
+ QVERIFY(layout.itemAt(1, QFormLayout::FieldRole)->widget() == &fld2);
+ QVERIFY(layout.itemAt(2, QFormLayout::FieldRole)->widget() == &fld3);
+ QVERIFY(layout.itemAt(3, QFormLayout::FieldRole) == 0);
+ QVERIFY(layout.itemAt(4, QFormLayout::FieldRole)->widget() == &fld4);
+ QVERIFY(layout.itemAt(5, QFormLayout::FieldRole) == 0);
+}
+
+void tst_QFormLayout::insertRow_QWidget_QLayout()
+{
+ QFormLayout layout;
+ QLabel lbl1, lbl2, lbl3, lbl4;
+ QHBoxLayout fld1, fld2, fld3, fld4;
+
+ layout.insertRow(0, &lbl1, &fld1);
+ QCOMPARE(layout.rowCount(), 1);
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(&lbl1, &row, &role);
+ QCOMPARE(row, 0);
+ QCOMPARE(int(role), int(QFormLayout::LabelRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getLayoutPosition(&fld1, &row, &role);
+ QCOMPARE(row, 0);
+ QCOMPARE(int(role), int(QFormLayout::FieldRole));
+ }
+
+ // check that negative values append
+ layout.insertRow(-2, &lbl2, &fld2);
+ QCOMPARE(layout.rowCount(), 2);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::LabelRole)->widget() == &lbl1);
+ QVERIFY(layout.itemAt(1, QFormLayout::LabelRole)->widget() == &lbl2);
+
+ // check that too large values append
+ layout.insertRow(100, &lbl3, &fld3);
+ QCOMPARE(layout.rowCount(), 3);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::LabelRole)->widget() == &lbl1);
+ QVERIFY(layout.itemAt(1, QFormLayout::LabelRole)->widget() == &lbl2);
+ QVERIFY(layout.itemAt(2, QFormLayout::LabelRole)->widget() == &lbl3);
+
+ QVERIFY(layout.itemAt(0, QFormLayout::FieldRole)->layout() == &fld1);
+ QVERIFY(layout.itemAt(1, QFormLayout::FieldRole)->layout() == &fld2);
+ QVERIFY(layout.itemAt(2, QFormLayout::FieldRole)->layout() == &fld3);
+}
+
+void tst_QFormLayout::insertRow_QString_QWidget()
+{
+ QFormLayout layout;
+ QLineEdit fld1, fld2, fld3;
+
+ layout.insertRow(-5, "&Name:", &fld1);
+ QLabel *label1 = qobject_cast<QLabel *>(layout.itemAt(0, QFormLayout::LabelRole)->widget());
+ QVERIFY(label1 != 0);
+ QVERIFY(label1->buddy() == &fld1);
+
+ layout.insertRow(0, "&Email:", &fld2);
+ QLabel *label2 = qobject_cast<QLabel *>(layout.itemAt(0, QFormLayout::LabelRole)->widget());
+ QVERIFY(label2 != 0);
+ QVERIFY(label2->buddy() == &fld2);
+
+ layout.insertRow(5, "&Age:", &fld3);
+ QLabel *label3 = qobject_cast<QLabel *>(layout.itemAt(2, QFormLayout::LabelRole)->widget());
+ QVERIFY(label3 != 0);
+ QVERIFY(label3->buddy() == &fld3);
+}
+
+void tst_QFormLayout::insertRow_QString_QLayout()
+{
+ QFormLayout layout;
+ QHBoxLayout fld1, fld2, fld3;
+
+ layout.insertRow(-5, "&Name:", &fld1);
+ QLabel *label1 = qobject_cast<QLabel *>(layout.itemAt(0, QFormLayout::LabelRole)->widget());
+ QVERIFY(label1 != 0);
+ QVERIFY(label1->buddy() == 0);
+
+ QCOMPARE(layout.rowCount(), 1);
+
+ layout.insertRow(0, "&Email:", &fld2);
+ QLabel *label2 = qobject_cast<QLabel *>(layout.itemAt(0, QFormLayout::LabelRole)->widget());
+ QVERIFY(label2 != 0);
+ QVERIFY(label2->buddy() == 0);
+
+ QCOMPARE(layout.rowCount(), 2);
+
+ layout.insertRow(5, "&Age:", &fld3);
+ QLabel *label3 = qobject_cast<QLabel *>(layout.itemAt(2, QFormLayout::LabelRole)->widget());
+ QVERIFY(label3 != 0);
+ QVERIFY(label3->buddy() == 0);
+
+ QCOMPARE(layout.rowCount(), 3);
+}
+
+void tst_QFormLayout::insertRow_QWidget()
+{
+ // ### come back to this later
+}
+
+void tst_QFormLayout::insertRow_QLayout()
+{
+ // ### come back to this later
+}
+
+void tst_QFormLayout::setWidget()
+{
+ QFormLayout layout;
+
+ QWidget w1;
+ QWidget w2;
+ QWidget w3;
+ QWidget w4;
+
+ QCOMPARE(layout.count(), 0);
+ QCOMPARE(layout.rowCount(), 0);
+
+ layout.setWidget(5, QFormLayout::LabelRole, &w1);
+ QCOMPARE(layout.count(), 1);
+ QCOMPARE(layout.rowCount(), 6);
+
+ layout.setWidget(3, QFormLayout::FieldRole, &w2);
+ layout.setWidget(3, QFormLayout::LabelRole, &w3);
+ QCOMPARE(layout.count(), 3);
+ QCOMPARE(layout.rowCount(), 6);
+
+ // should be ignored and generate warnings
+ layout.setWidget(3, QFormLayout::FieldRole, &w4);
+ layout.setWidget(-1, QFormLayout::FieldRole, &w4);
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(&w1, &row, &role);
+ QCOMPARE(row, 5);
+ QCOMPARE(int(role), int(QFormLayout::LabelRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(&w2, &row, &role);
+ QCOMPARE(row, 3);
+ QCOMPARE(int(role), int(QFormLayout::FieldRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(&w3, &row, &role);
+ QCOMPARE(row, 3);
+ QCOMPARE(int(role), int(QFormLayout::LabelRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(&w4, &row, &role);
+ QCOMPARE(row, -1);
+ QCOMPARE(int(role), -123);
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getWidgetPosition(0, &row, &role);
+ QCOMPARE(row, -1);
+ QCOMPARE(int(role), -123);
+ }
+}
+
+void tst_QFormLayout::setLayout()
+{
+ QFormLayout layout;
+
+ QHBoxLayout l1;
+ QHBoxLayout l2;
+ QHBoxLayout l3;
+ QHBoxLayout l4;
+
+ QCOMPARE(layout.count(), 0);
+ QCOMPARE(layout.rowCount(), 0);
+
+ layout.setLayout(5, QFormLayout::LabelRole, &l1);
+ QCOMPARE(layout.count(), 1);
+ QCOMPARE(layout.rowCount(), 6);
+
+ layout.setLayout(3, QFormLayout::FieldRole, &l2);
+ layout.setLayout(3, QFormLayout::LabelRole, &l3);
+ QCOMPARE(layout.count(), 3);
+ QCOMPARE(layout.rowCount(), 6);
+
+ // should be ignored and generate warnings
+ layout.setLayout(3, QFormLayout::FieldRole, &l4);
+ layout.setLayout(-1, QFormLayout::FieldRole, &l4);
+ QCOMPARE(layout.count(), 3);
+ QCOMPARE(layout.rowCount(), 6);
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getLayoutPosition(&l1, &row, &role);
+ QCOMPARE(row, 5);
+ QCOMPARE(int(role), int(QFormLayout::LabelRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getLayoutPosition(&l2, &row, &role);
+ QCOMPARE(row, 3);
+ QCOMPARE(int(role), int(QFormLayout::FieldRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getLayoutPosition(&l3, &row, &role);
+ QCOMPARE(row, 3);
+ QCOMPARE(int(role), int(QFormLayout::LabelRole));
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getLayoutPosition(&l4, &row, &role);
+ QCOMPARE(row, -1);
+ QCOMPARE(int(role), -123);
+ }
+
+ {
+ int row = -1;
+ QFormLayout::ItemRole role = QFormLayout::ItemRole(-123);
+ layout.getLayoutPosition(0, &row, &role);
+ QCOMPARE(row, -1);
+ QCOMPARE(int(role), -123);
+ }
+}
+
+void tst_QFormLayout::itemAt()
+{
+ QFormLayout layout;
+
+ QWidget w1;
+ QWidget w2;
+ QWidget w3;
+ QWidget w4;
+ QWidget w5;
+ QHBoxLayout l6;
+
+ layout.setWidget(5, QFormLayout::LabelRole, &w1);
+ layout.setWidget(3, QFormLayout::FieldRole, &w2);
+ layout.setWidget(3, QFormLayout::LabelRole, &w3);
+ layout.addRow(&w4, &w5);
+ layout.addRow("Foo:", &l6);
+
+ QCOMPARE(layout.count(), 7);
+
+ QBitArray scoreBoard(7);
+ for (int i = 0; i < 7; ++i) {
+ QLayoutItem *item = layout.itemAt(i);
+ QVERIFY(item != 0);
+
+ if (item->widget() == &w1) {
+ scoreBoard[0] = true;
+ } else if (item->widget() == &w2) {
+ scoreBoard[1] = true;
+ } else if (item->widget() == &w3) {
+ scoreBoard[2] = true;
+ } else if (item->widget() == &w4) {
+ scoreBoard[3] = true;
+ } else if (item->widget() == &w5) {
+ scoreBoard[4] = true;
+ } else if (item->layout() == &l6) {
+ scoreBoard[5] = true;
+ } else if (qobject_cast<QLabel *>(item->widget())) {
+ scoreBoard[6] = true;
+ }
+ }
+ QCOMPARE(scoreBoard.count(false), 0);
+}
+
+void tst_QFormLayout::takeAt()
+{
+ QFormLayout layout;
+
+ QWidget w1;
+ QWidget w2;
+ QWidget w3;
+ QWidget w4;
+ QWidget w5;
+ QHBoxLayout l6;
+
+ layout.setWidget(5, QFormLayout::LabelRole, &w1);
+ layout.setWidget(3, QFormLayout::FieldRole, &w2);
+ layout.setWidget(3, QFormLayout::LabelRole, &w3);
+ layout.addRow(&w4, &w5);
+ layout.addRow("Foo:", &l6);
+
+ QCOMPARE(layout.count(), 7);
+
+ for (int i = 6; i >= 0; --i) {
+ layout.takeAt(0);
+ QCOMPARE(layout.count(), i);
+ }
+}
+
+void tst_QFormLayout::layoutAlone()
+{
+ QWidget w;
+ QFormLayout layout;
+ layout.setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
+ w.setLayout(&layout);
+ QLabel label("Here is a strange test case");
+ layout.setWidget(0, QFormLayout::LabelRole, &label);
+ QHBoxLayout hlay;
+ layout.setLayout(1, QFormLayout::LabelRole, &hlay);
+ QCOMPARE(layout.count(), 2);
+ w.show();
+ layout.activate();
+ QTest::qWait(500);
+}
+
+QTEST_MAIN(tst_QFormLayout)
+
+#include "tst_qformlayout.moc"
diff --git a/tests/auto/widgets/kernel/qgridlayout/.gitignore b/tests/auto/widgets/kernel/qgridlayout/.gitignore
new file mode 100644
index 0000000000..bce8f2f91e
--- /dev/null
+++ b/tests/auto/widgets/kernel/qgridlayout/.gitignore
@@ -0,0 +1 @@
+tst_qgridlayout
diff --git a/tests/auto/widgets/kernel/qgridlayout/qgridlayout.pro b/tests/auto/widgets/kernel/qgridlayout/qgridlayout.pro
new file mode 100644
index 0000000000..6bd42fe432
--- /dev/null
+++ b/tests/auto/widgets/kernel/qgridlayout/qgridlayout.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qgridlayout.cpp
+FORMS += sortdialog.ui
+
+
+
diff --git a/tests/auto/widgets/kernel/qgridlayout/sortdialog.ui b/tests/auto/widgets/kernel/qgridlayout/sortdialog.ui
new file mode 100644
index 0000000000..04af84d01b
--- /dev/null
+++ b/tests/auto/widgets/kernel/qgridlayout/sortdialog.ui
@@ -0,0 +1,135 @@
+<ui version="4.0" >
+ <author></author>
+ <comment></comment>
+ <exportmacro></exportmacro>
+ <class>SortDialog</class>
+ <widget class="QDialog" name="SortDialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>304</width>
+ <height>370</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Sort</string>
+ </property>
+ <layout class="QGridLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item rowspan="2" row="0" column="1" >
+ <layout class="QVBoxLayout" >
+ <property name="margin" >
+ <number>0</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="okButton" >
+ <property name="text" >
+ <string>OK</string>
+ </property>
+ <property name="default" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="moreButton" >
+ <property name="text" >
+ <string>&amp;More</string>
+ </property>
+ <property name="checkable" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>1</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="0" >
+ <widget class="QGroupBox" name="primaryGroupBox" >
+ <layout class="QHBoxLayout" >
+ <property name="margin" >
+ <number>8</number>
+ </property>
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <item row="0" column="0" >
+ <widget class="QComboBox" name="primaryColumnCombo" >
+ <property name="minimumSize" >
+ <size>
+ <width>0</width>
+ <height>100</height>
+ </size>
+ </property>
+ <item>
+ <property name="text" >
+ <string>None</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <pixmapfunction></pixmapfunction>
+ <tabstops>
+ <tabstop>primaryColumnCombo</tabstop>
+ <tabstop>okButton</tabstop>
+ <tabstop>moreButton</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>okButton</sender>
+ <signal>clicked()</signal>
+ <receiver>SortDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel" >
+ <x>257</x>
+ <y>25</y>
+ </hint>
+ <hint type="destinationlabel" >
+ <x>283</x>
+ <y>268</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
new file mode 100644
index 0000000000..100b7eb892
--- /dev/null
+++ b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
@@ -0,0 +1,1646 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qlayout.h>
+#include <qapplication.h>
+#include <qwidget.h>
+#include <qwindowsstyle.h>
+#include <qsizepolicy.h>
+//#include <QtGui>
+
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QRadioButton>
+#include <QtWidgets/QWindowsStyle>
+#include <QStyleFactory>
+
+#include "../../../platformquirks.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/kernel/qlayout.cpp gui/kernel/qlayout.h
+
+
+class tst_QGridLayout : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QGridLayout();
+ virtual ~tst_QGridLayout();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void getItemPosition();
+ void itemAtPosition();
+ void badDistributionBug();
+ void setMinAndMaxSize();
+ void spacingAndSpacers();
+
+ void spacingsAndMargins();
+ void spacingsAndMargins_data();
+ void minMaxSize_data();
+ void minMaxSize();
+
+ void styleDependentSpacingsAndMargins_data();
+ void styleDependentSpacingsAndMargins();
+ void layoutSpacingImplementation_data();
+ void layoutSpacingImplementation();
+ void spacing();
+ void spacerWithSpacing();
+ void contentsRect();
+ void distributeMultiCell();
+
+private:
+ QWidget *testWidget;
+ QGridLayout *testLayout;
+ QWidget *w1;
+ QWidget *w2;
+ QWidget *w3;
+ QSpacerItem *sp;
+
+ QGridLayout *m_grid;
+ QWidget *m_toplevel;
+};
+
+
+tst_QGridLayout::tst_QGridLayout()
+{
+ m_grid = 0;
+ m_toplevel = 0;
+}
+
+tst_QGridLayout::~tst_QGridLayout()
+{
+ delete m_toplevel;
+}
+
+void tst_QGridLayout::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+ // Create the test class
+ testWidget = new QWidget(0);
+
+ testLayout = new QGridLayout(testWidget);
+
+ w1 = new QWidget(testWidget);
+ w1->setPalette(QPalette(Qt::red));
+ testLayout->addWidget(w1, 0, 0);
+
+ w2 = new QWidget(testWidget);
+ testLayout->addWidget(w2, 1, 1, 2, 2);
+ w2->setPalette(QPalette(Qt::green));
+
+ w3 = new QWidget(testWidget);
+ testLayout->addWidget(w3, 0, 1, 1, 2);
+ w3->setPalette(QPalette(Qt::blue));
+
+ sp = new QSpacerItem(4, 4);
+ testLayout->addItem(sp, 1, 3, 2, 1);
+
+ testWidget->resize( 200, 200 );
+ testWidget->show();
+}
+
+void tst_QGridLayout::cleanupTestCase()
+{
+ delete testWidget;
+ testWidget = 0;
+}
+
+void tst_QGridLayout::init()
+{
+}
+
+void tst_QGridLayout::cleanup()
+{
+}
+
+void tst_QGridLayout::getItemPosition()
+{
+ QLayoutItem *item;
+ int counter = 0;
+
+ bool seenW1 = false;
+ bool seenW2 = false;
+ bool seenW3 = false;
+ bool seenSpacer = false;
+
+ while ((item = testLayout->itemAt(counter))) {
+ QWidget *w = item->widget();
+ int r,c,rs,cs;
+ testLayout->getItemPosition(counter, &r, &c, &rs, &cs);
+
+// qDebug() << "item" << counter << "has" <<r << c << rs << cs;
+
+ if (w == w1) {
+ QVERIFY(!seenW1);
+ seenW1 = true;
+ QCOMPARE(r, 0);
+ QCOMPARE(c, 0);
+ QCOMPARE(rs, 1);
+ QCOMPARE(cs, 1);
+ } else if (w == w2) {
+ QVERIFY(!seenW2);
+ seenW2 = true;
+ QCOMPARE(r, 1);
+ QCOMPARE(c, 1);
+ QCOMPARE(rs, 2);
+ QCOMPARE(cs, 2);
+ } else if (w == w3) {
+ QVERIFY(!seenW3);
+ seenW3 = true;
+ QCOMPARE(r, 0);
+ QCOMPARE(c, 1);
+ QCOMPARE(rs, 1);
+ QCOMPARE(cs, 2);
+ } else {
+ QVERIFY(!w);
+ QVERIFY(!seenSpacer);
+ seenSpacer = true;
+ QCOMPARE(r, 1);
+ QCOMPARE(c, 3);
+ QCOMPARE(rs, 2);
+ QCOMPARE(cs, 1);
+ }
+ ++counter;
+ }
+ QCOMPARE(counter, 4);
+ QVERIFY(seenW1);
+ QVERIFY(seenW2);
+ QVERIFY(seenW3);
+ QVERIFY(seenSpacer);
+}
+
+void tst_QGridLayout::itemAtPosition()
+{
+ void *table[4][5] = {
+ { w1, w3, w3, 0, 0 },
+ { 0, w2, w2, sp, 0 },
+ { 0, w2, w2, sp, 0 },
+ { 0, 0, 0, 0, 0 }
+ };
+
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 5; ++col) {
+ QLayoutItem *item = testLayout->itemAtPosition(row, col);
+ QVERIFY(item == table[row][col]
+ || (item && item->widget() == table[row][col]));
+ }
+ }
+}
+
+#include "ui_sortdialog.h"
+
+void tst_QGridLayout::badDistributionBug()
+{
+ QDialog dialog;
+ Ui::SortDialog ui;
+ ui.setupUi(&dialog);
+ ui.gridLayout->setMargin(0);
+ ui.gridLayout->setSpacing(0);
+ ui.vboxLayout->setMargin(0);
+ ui.vboxLayout->setSpacing(0);
+ ui.okButton->setFixedHeight(20);
+ ui.moreButton->setFixedHeight(20);
+ ui.primaryGroupBox->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ ui.primaryGroupBox->setFixedHeight(200);
+
+ QSize minSize = dialog.layout()->minimumSize();
+ QCOMPARE(minSize.height(), 200);
+}
+
+void tst_QGridLayout::setMinAndMaxSize()
+{
+ QWidget widget;
+ QGridLayout layout(&widget);
+ layout.setMargin(0);
+ layout.setSpacing(0);
+ layout.setSizeConstraint(QLayout::SetMinAndMaxSize);
+ widget.show();
+
+ QWidget leftChild;
+ leftChild.setPalette(QPalette(Qt::red));
+ leftChild.setMinimumSize(100, 100);
+ leftChild.setMaximumSize(200, 200);
+ layout.addWidget(&leftChild, 0, 0);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumSize(), leftChild.minimumSize());
+ QCOMPARE(widget.maximumSize(), leftChild.maximumSize());
+
+ QWidget rightChild;
+ rightChild.setPalette(QPalette(Qt::green));
+ rightChild.setMinimumSize(100, 100);
+ rightChild.setMaximumSize(200, 200);
+ layout.addWidget(&rightChild, 0, 2);
+ QApplication::sendPostedEvents(0, 0);
+
+ QCOMPARE(widget.minimumWidth(),
+ leftChild.minimumWidth() + rightChild.minimumWidth());
+ QCOMPARE(widget.minimumHeight(),
+ qMax(leftChild.minimumHeight(), rightChild.minimumHeight()));
+ QCOMPARE(widget.maximumWidth(),
+ leftChild.maximumWidth() + rightChild.maximumWidth());
+ QCOMPARE(widget.maximumHeight(),
+ qMax(leftChild.maximumHeight(), rightChild.maximumHeight()));
+
+
+ static const int colMin = 100;
+ layout.setColumnMinimumWidth(1, colMin);
+ QCOMPARE(layout.columnMinimumWidth(1), colMin);
+
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumWidth(),
+ leftChild.minimumWidth() + rightChild.minimumWidth() + colMin);
+ QCOMPARE(widget.maximumWidth(),
+ leftChild.maximumWidth() + rightChild.maximumWidth() + colMin);
+ QCOMPARE(widget.minimumHeight(),
+ qMax(leftChild.minimumHeight(), rightChild.minimumHeight()));
+ QCOMPARE(widget.maximumHeight(),
+ qMax(leftChild.maximumHeight(), rightChild.maximumHeight()));
+
+
+
+ layout.setColumnStretch(1,1);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumWidth(),
+ leftChild.minimumWidth() + rightChild.minimumWidth() + colMin);
+ QCOMPARE(widget.maximumWidth(), QLAYOUTSIZE_MAX);
+ QCOMPARE(widget.minimumHeight(),
+ qMax(leftChild.minimumHeight(), rightChild.minimumHeight()));
+ QCOMPARE(widget.maximumHeight(),
+ qMax(leftChild.maximumHeight(), rightChild.maximumHeight()));
+
+
+
+ layout.setColumnStretch(1,0);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumWidth(),
+ leftChild.minimumWidth() + rightChild.minimumWidth() + colMin);
+ QCOMPARE(widget.maximumWidth(),
+ leftChild.maximumWidth() + rightChild.maximumWidth() + colMin);
+ QCOMPARE(widget.minimumHeight(),
+ qMax(leftChild.minimumHeight(), rightChild.minimumHeight()));
+ QCOMPARE(widget.maximumHeight(),
+ qMax(leftChild.maximumHeight(), rightChild.maximumHeight()));
+
+
+
+ layout.setColumnMinimumWidth(1, 0);
+
+ static const int spacerS = 250;
+ QSpacerItem *spacer = new QSpacerItem(spacerS, spacerS);
+ layout.addItem(spacer, 0, 1);
+ QApplication::sendPostedEvents(0, 0);
+
+ QCOMPARE(widget.minimumWidth(),
+ leftChild.minimumWidth() + rightChild.minimumWidth() + spacerS);
+ QCOMPARE(widget.maximumWidth(), QLAYOUTSIZE_MAX);
+ QCOMPARE(widget.minimumHeight(),
+ qMax(qMax(leftChild.minimumHeight(), rightChild.minimumHeight()), spacerS));
+ QCOMPARE(widget.maximumHeight(),
+ qMax(leftChild.maximumHeight(), rightChild.maximumHeight()));
+
+
+ spacer->changeSize(spacerS, spacerS, QSizePolicy::Fixed, QSizePolicy::Minimum);
+ layout.invalidate();
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumWidth(),
+ leftChild.minimumWidth() + rightChild.minimumWidth() + spacerS);
+ QCOMPARE(widget.maximumWidth(),
+ leftChild.maximumWidth() + rightChild.maximumWidth() + spacerS);
+
+
+ layout.removeItem(spacer);
+
+ rightChild.hide();
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumSize(), leftChild.minimumSize());
+ QCOMPARE(widget.maximumSize(), leftChild.maximumSize());
+
+ rightChild.show();
+ layout.removeWidget(&rightChild);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumSize(), leftChild.minimumSize());
+ QCOMPARE(widget.maximumSize(), leftChild.maximumSize());
+
+ QWidget bottomChild(&widget);
+ bottomChild.setPalette(QPalette(Qt::green));
+ bottomChild.setMinimumSize(100, 100);
+ bottomChild.setMaximumSize(200, 200);
+ layout.addWidget(&bottomChild, 1, 0);
+ QApplication::sendPostedEvents(0, 0);
+
+ QCOMPARE(widget.minimumHeight(),
+ leftChild.minimumHeight() + bottomChild.minimumHeight());
+ QCOMPARE(widget.minimumWidth(),
+ qMax(leftChild.minimumWidth(), bottomChild.minimumWidth()));
+ QCOMPARE(widget.maximumHeight(),
+ leftChild.maximumHeight() + bottomChild.maximumHeight());
+ QCOMPARE(widget.maximumWidth(),
+ qMax(leftChild.maximumWidth(), bottomChild.maximumWidth()));
+
+ bottomChild.hide();
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumSize(), leftChild.minimumSize());
+ QCOMPARE(widget.maximumSize(), leftChild.maximumSize());
+
+ bottomChild.show();
+ layout.removeWidget(&bottomChild);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.minimumSize(), leftChild.minimumSize());
+ QCOMPARE(widget.maximumSize(), leftChild.maximumSize());
+}
+
+
+class SizeHinter : public QWidget
+{
+public:
+ SizeHinter(const QSize &s, QWidget *parent = 0)
+ : QWidget(parent), sh(s) { }
+ SizeHinter(int w, int h, QWidget *parent = 0)
+ : QWidget(parent), sh(QSize(w,h)) {}
+ void setSizeHint(QSize s) { sh = s; }
+ QSize sizeHint() const { return sh; }
+private:
+ QSize sh;
+};
+
+void tst_QGridLayout::spacingAndSpacers()
+{
+ QWidget widget;
+ QGridLayout layout(&widget);
+ layout.setMargin(0);
+ layout.setSpacing(0);
+ widget.show();
+
+ QSize expectedSizeHint;
+
+ SizeHinter leftChild(100,100);
+ leftChild.setPalette(QPalette(Qt::red));
+ layout.addWidget(&leftChild, 0, 0);
+ QApplication::sendPostedEvents(0, 0);
+ expectedSizeHint = leftChild.sizeHint();
+ QCOMPARE(widget.sizeHint(), expectedSizeHint);
+
+
+ SizeHinter rightChild(200,100);
+ rightChild.setPalette(QPalette(Qt::green));
+ layout.addWidget(&rightChild, 0, 2);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(rightChild.sizeHint(), QSize(200,100));
+
+ expectedSizeHint += QSize(rightChild.sizeHint().width(), 0);
+ QCOMPARE(widget.sizeHint(), expectedSizeHint);
+
+ layout.setColumnMinimumWidth(1, 100);
+ widget.adjustSize();
+ expectedSizeHint += QSize(100,0);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.sizeHint(), expectedSizeHint);
+
+ rightChild.hide();
+ QApplication::sendPostedEvents(0, 0);
+ expectedSizeHint -= QSize(rightChild.sizeHint().width(), 0);
+ QCOMPARE(widget.sizeHint(), expectedSizeHint);
+
+
+ layout.setColumnMinimumWidth(1, 0);
+ expectedSizeHint -= QSize(100, 0);
+ QCOMPARE(widget.sizeHint(), expectedSizeHint);
+
+ rightChild.show();
+
+#if 0
+ leftChild.setMaximumWidth(200);
+ rightChild.setMaximumWidth(200);
+
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.maximumWidth(), leftChild.maximumWidth() + rightChild.maximumWidth());
+#endif
+
+ layout.removeWidget(&rightChild);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(widget.sizeHint(), expectedSizeHint);
+
+
+}
+
+
+class Qt42Style : public QWindowsStyle
+{
+ Q_OBJECT
+public:
+ Qt42Style() : QWindowsStyle()
+ {
+ spacing = 6;
+ margin = 9;
+ margin_toplevel = 11;
+ }
+
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption * option = 0,
+ const QWidget * widget = 0 ) const;
+
+ int spacing;
+ int margin;
+ int margin_toplevel;
+
+};
+
+int Qt42Style::pixelMetric(PixelMetric metric, const QStyleOption * option /*= 0*/,
+ const QWidget * widget /*= 0*/ ) const
+{
+ switch (metric) {
+ case PM_DefaultLayoutSpacing:
+ return spacing;
+ break;
+ case PM_DefaultTopLevelMargin:
+ return margin_toplevel;
+ break;
+ case PM_DefaultChildMargin:
+ return margin;
+ break;
+ default:
+ break;
+ }
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+}
+
+
+typedef QList<QPoint> PointList;
+Q_DECLARE_METATYPE(PointList)
+
+
+class SizeHinterFrame : public QLabel
+{
+public:
+ SizeHinterFrame(QWidget *parent = 0)
+ : QLabel(parent)
+ {
+ init(-1);
+ }
+
+ SizeHinterFrame(const QSize &s, int numPixels = -1)
+ : QLabel(0), sh(s) {
+ init(numPixels);
+ }
+
+
+ SizeHinterFrame(int w, int h)
+ : QLabel(0), sh(QSize(w,h))
+ {
+ init(-1);
+ }
+
+ void setSizeHint(const QSize &s) { sh = s; }
+ QSize sizeHint() const { return sh; }
+ void setMinimumSizeHint(const QSize &s) { msh = s; }
+ QSize minimumSizeHint() const { return msh; }
+
+ virtual int heightForWidth(int width) const;
+
+ void setNumberOfPixels(int numPixels) {
+ m_numPixels = numPixels;
+ QSizePolicy sp = sizePolicy();
+ sp.setHeightForWidth(m_numPixels != -1);
+ setSizePolicy(sp);
+ }
+private:
+ void init(int numPixels = -1){
+ setText(QString::fromAscii("(%1,%2)").arg(sh.width()).arg(sh.height()));
+ setFrameStyle(QFrame::Box | QFrame::Plain);
+ setNumberOfPixels(numPixels);
+ }
+private:
+ QSize sh;
+ QSize msh;
+ int m_numPixels;
+};
+
+int SizeHinterFrame::heightForWidth(int width) const
+{
+ // Special hack if m_numPixels == -2 then we report that we are heightForWidth aware, but we
+ // return sizeHint().width() so that it should be laid out as if we had't any hfw.
+ // This enables us to run the tests twice and to see if we get the same results with hfw as without hfw.
+ if (m_numPixels == -2) {
+ return sizeHint().height();
+ }
+ if (m_numPixels == -1 || width == 0) return -1;
+ // this widget should always cover the same amount of pixels (provided that we don't get any rounding errors)
+ return (m_numPixels)/width;
+}
+
+void tst_QGridLayout::spacingsAndMargins_data()
+{
+ // input
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<QSize>("sizehint");
+ // expected
+ QTest::addColumn<PointList>("expectedpositions");
+
+ int child_offset_y = 11 + 100 + 6 + 9 ;
+ QTest::newRow("1x1 grid") << 1 << 1 << QSize(100, 100)
+ << (PointList() // toplevel
+ << QPoint( 11, 11)
+ // children
+ << QPoint( 20, child_offset_y)
+ );
+
+ QTest::newRow("2x1 grid") << 2 << 1 << QSize(100, 100)
+ << (PointList() // toplevel
+ << QPoint( 11, 11)
+ << QPoint( 11 + 100 + 6, 11)
+ // children
+ << QPoint( 20, child_offset_y)
+ << QPoint( 20 + 100 + 6, child_offset_y)
+ );
+
+ QTest::newRow("3x1 grid") << 3 << 1 << QSize(100, 100)
+ << (PointList() // toplevel
+ << QPoint( 11, 11)
+ << QPoint( 11 + 100 + 6, 11)
+ << QPoint( 11 + 100 + 6 + 100 + 6, 11)
+ // children
+ << QPoint( 20, child_offset_y)
+ << QPoint( 20 + 100 + 6, child_offset_y)
+ << QPoint( 20 + 100 + 6 + 100 + 6, child_offset_y)
+ );
+
+ child_offset_y = 11 + 9 + 100 + 6 + 100 + 6;
+ QTest::newRow("1x2 grid") << 1 << 2 << QSize(100, 100)
+ << (PointList() // toplevel
+ << QPoint( 11, 11)
+ << QPoint( 11, 11 + 100 + 6)
+ // children
+ << QPoint( 20, child_offset_y)
+ << QPoint( 20, child_offset_y + 100 + 6)
+ );
+#if defined (Q_OS_WINCE) //There is not enough screenspace to run the test in original size on Windows CE. We use smaller widgets.
+ child_offset_y = 11 + 9 + 50 + 6 + 50 + 6 + 50 + 6;
+ QTest::newRow("1x3 grid") << 1 << 3 << QSize(50, 50)
+ << (PointList() // toplevel
+ << QPoint( 11, 11)
+ << QPoint( 11, 11 + 50 + 6)
+ << QPoint( 11, 11 + 50 + 6 + 50 + 6)
+ // children
+ << QPoint( 20, child_offset_y)
+ << QPoint( 20, child_offset_y + 50 + 6)
+ << QPoint( 20, child_offset_y + 50 + 6 + 50 + 6)
+ );
+#else
+ child_offset_y = 11 + 9 + 100 + 6 + 100 + 6 + 100 + 6;
+ QTest::newRow("1x3 grid") << 1 << 3 << QSize(100, 100)
+ << (PointList() // toplevel
+ << QPoint( 11, 11)
+ << QPoint( 11, 11 + 100 + 6)
+ << QPoint( 11, 11 + 100 + 6 + 100 + 6)
+ // children
+ << QPoint( 20, child_offset_y)
+ << QPoint( 20, child_offset_y + 100 + 6)
+ << QPoint( 20, child_offset_y + 100 + 6 + 100 + 6)
+ );
+#endif
+
+ child_offset_y = 11 + 9 + 100 + 6 + 100 + 6;
+ QTest::newRow("2x2 grid") << 2 << 2 << QSize(100, 100)
+ << (PointList() // toplevel
+ << QPoint( 11, 11)
+ << QPoint( 11 + 100 + 6, 11)
+ << QPoint( 11, 11 + 100 + 6)
+ << QPoint( 11 + 100 + 6, 11 + 100 + 6)
+ // children
+ << QPoint( 20, child_offset_y)
+ << QPoint( 20 + 100 + 6, child_offset_y)
+ << QPoint( 20, child_offset_y + 100 + 6)
+ << QPoint( 20 + 100 + 6, child_offset_y + 100 + 6)
+ );
+}
+
+void tst_QGridLayout::spacingsAndMargins()
+{
+/*
+ The test tests a gridlayout as a child of a top-level widget,
+ and then a gridlayout as a child of a non-toplevel widget.
+
+ The expectedpositions should then contain the list of widget positions in the
+ first gridlayout, then followed by a list of widget positions in the second gridlayout.
+*/
+ QFETCH(int, columns);
+ QFETCH(int, rows);
+ QFETCH(QSize, sizehint);
+ QFETCH(PointList, expectedpositions);
+
+
+ QApplication::setStyle(new Qt42Style);
+ QWidget toplevel;
+ if(PlatformQuirks::isAutoMaximizing())
+ toplevel.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ QVBoxLayout vbox(&toplevel);
+ QGridLayout grid1;
+ vbox.addLayout(&grid1);
+
+ // a layout with a top-level parent widget
+ QList<QPointer<SizeHinterFrame> > sizehinters;
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < columns; ++j) {
+ SizeHinterFrame *sh = new SizeHinterFrame(sizehint);
+ sh->setMinimumSizeHint(sizehint);
+ sizehinters.append(sh);
+ grid1.addWidget(sh, i, j);
+ }
+ }
+
+ // Add the child widget
+ QWidget widget;
+ vbox.addWidget(&widget);
+ QGridLayout grid2;
+ widget.setLayout(&grid2);
+ // add a layout to the child widget
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < columns; ++j) {
+ SizeHinterFrame *sh = new SizeHinterFrame(sizehint);
+ sh->setMinimumSizeHint(sizehint);
+ sizehinters.append(sh);
+ grid2.addWidget(sh, i, j);
+ }
+ }
+
+ grid1.setColumnStretch(columns-1, 1);
+ grid1.setRowStretch(rows-1, 1);
+ toplevel.show();
+ toplevel.adjustSize();
+ QApplication::processEvents();
+ QTest::qWaitForWindowShown(&toplevel);
+
+ QSize topsize = toplevel.size();
+ QSize minimumsize = vbox.totalMinimumSize();
+
+ if (topsize.width() < minimumsize.width() || topsize.height() < minimumsize.height())
+ QSKIP("The screen is too small to run this test case", SkipSingle);
+
+// We are relying on the order here...
+ for (int pi = 0; pi < sizehinters.count(); ++pi) {
+ QPoint pt = sizehinters.at(pi)->mapTo(&toplevel, QPoint(0, 0));
+ QCOMPARE(pt, expectedpositions.at(pi));
+ }
+}
+
+
+
+
+struct SizeInfo {
+ SizeInfo(const QPoint &expected, const QSize &sh, const QSize &minimumSize = QSize(),
+ const QSize &maximumSize = QSize(), int numPixelsToCover = -1)
+ {
+ expectedPos = expected;
+ sizeHint = sh;
+ minSize = minimumSize;
+ maxSize = maximumSize;
+ hfwNumPixels = numPixelsToCover;
+ }
+
+ SizeInfo(const QRect &expected, const QSize &sh, const QSize &minimumSize = QSize(),
+ const QSize &maximumSize = QSize(), int numPixelsToCover = -1)
+ {
+ expectedPos = expected.topLeft();
+ expectedSize = expected.size();
+ sizeHint = sh;
+ minSize = minimumSize;
+ maxSize = maximumSize;
+ hfwNumPixels = numPixelsToCover;
+ }
+ SizeInfo(const SizeInfo& other) {
+ (*this)=other;
+ }
+
+ SizeInfo &operator=(const SizeInfo& other) {
+ expectedPos = other.expectedPos;
+ expectedSize = other.expectedSize;
+ sizeHint = other.sizeHint;
+ minSize = other.minSize;
+ maxSize = other.maxSize;
+ hfwNumPixels = other.hfwNumPixels;
+ return (*this);
+ }
+
+ QPoint expectedPos;
+ QSize expectedSize;
+ QSize sizeHint;
+ QSize minSize;
+ QSize maxSize;
+ int hfwNumPixels;
+};
+
+
+typedef QList<SizeInfo> SizeInfoList;
+Q_DECLARE_METATYPE(SizeInfoList)
+
+
+void tst_QGridLayout::minMaxSize_data()
+{
+ // input
+ QTest::addColumn<QString>("stylename");
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<int>("sizePolicy");
+ QTest::addColumn<QSize>("fixedSize");
+ //input and expected output
+ QTest::addColumn<SizeInfoList>("sizeinfos");
+
+ QTest::newRow("3x1 grid, extend to minimumSize") << QString() << 3 << 1
+ << int(QSizePolicy::Minimum) << QSize(152, 50) << (SizeInfoList()
+ << SizeInfo(QRect(10, 10, 43, 30), QSize( 75, 75), QSize(0,0))
+ << SizeInfo(QRect(10 + 45, 10, 43, 30), QSize(75, 75), QSize( 0, 0))
+ << SizeInfo(QRect(10 + 45 + 44, 10, 42, 30), QSize(75, 75), QSize( 0, 0))
+ );
+
+ QTest::newRow("1x1 grid, extend to minimumSize") << QString() << 1 << 1
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(10, 10), QSize( 90, 90), QSize(100,100))
+ );
+ QTest::newRow("2x1 grid, extend to minimumSize") << QString() << 2 << 1
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(10, 10), QSize( 90, 90), QSize(100,100))
+ << SizeInfo(QPoint(10 + 100 + 1, 10), QSize( 90, 90))
+ );
+ QTest::newRow("1x2 grid, extend to minimumSize") << QString() << 1 << 2
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(10, 10), QSize( 90, 90), QSize(100,100))
+ << SizeInfo(QPoint(10, 10 + 100 + 1), QSize( 90, 90))
+ );
+ QTest::newRow("2x1 grid, crop to maximumSize") << QString() << 2 << 1
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(10, 10), QSize(110,110), QSize(), QSize(100, 100))
+ << SizeInfo(QPoint(10 + 100 + 1, 10), QSize( 90, 90))
+ );
+ QTest::newRow("1x2 grid, crop to maximumSize") << QString() << 1 << 2
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(10, 10), QSize(110,110), QSize(), QSize(100, 100))
+ << SizeInfo(QPoint(10, 10 + 100 + 1), QSize( 90, 90))
+ );
+ QTest::newRow("1x3 grid, heightForWidth") << QString() << 1 << 3
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(10, 10), QSize(), QSize(200,100), QSize())
+ << SizeInfo(QPoint(10, 10 + 100 + 1), QSize(100,100), QSize(), QSize(), 100*100)
+ << SizeInfo(QPoint(10, 10 + 100 + 1 + 50 + 1), QSize(100,100), QSize(), QSize(100, 100))
+ );
+ QTest::newRow("2x1 grid, extend to minimumSize") << QString::fromAscii("motif") << 2 << 1
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(11, 11), QSize( 90, 90), QSize(100,100))
+ << SizeInfo(QPoint(11 + 100 + 6, 11), QSize( 90, 90))
+ );
+ QTest::newRow("2x1 grid, extend to minimumSize") << QString::fromAscii("windows") << 2 << 1
+ << int(QSizePolicy::Preferred) << QSize() << (SizeInfoList()
+ << SizeInfo(QPoint(11, 11), QSize( 90, 90), QSize(100,100))
+ << SizeInfo(QPoint(11 + 100 + 6, 11), QSize( 90, 90))
+ );
+
+}
+
+void tst_QGridLayout::minMaxSize()
+{
+/*
+ The test tests a gridlayout as a child of a top-level widget
+*/
+ // input
+ QFETCH(QString, stylename);
+ QFETCH(int, columns);
+ QFETCH(int, rows);
+ QFETCH(int, sizePolicy);
+ QFETCH(QSize, fixedSize);
+ //input and expected output
+ QFETCH(SizeInfoList, sizeinfos);
+
+ QStyle *style = 0;
+ if (stylename.isEmpty()) {
+ Qt42Style *s = new Qt42Style;
+ s->margin_toplevel = 10;
+ s->margin = 5;
+ s->spacing = 1;
+ style = static_cast<QStyle *>(s);
+ }else{
+ style = QStyleFactory::create(stylename);
+ if (!style) {
+ QSKIP( qPrintable(QString::fromLatin1("Qt has been compiled without style: %1").arg(stylename)), SkipSingle);
+ }
+ }
+ QApplication::setStyle(style);
+ if (!m_grid)
+ m_grid = new QGridLayout();
+ if (!m_toplevel)
+ m_toplevel = new QWidget();
+ if (fixedSize.isValid()) {
+ m_toplevel->setFixedSize(fixedSize);
+ } else {
+ m_toplevel->setMinimumSize(QSize(0,0));
+ m_toplevel->setMaximumSize(QSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX));
+ }
+ // Do a two-pass one using the real testdata, the other pass enables heightForWidth
+ // on the widget, but the heightForWidth() function just return sizeHint().width()
+ for (int pass = 0; pass < 2; ++pass) {
+ m_toplevel->hide();
+ QApplication::processEvents();
+ QTest::qWait(20);
+ // Test if removeItem uninitializes data properly
+ while (m_grid->count()) {
+ QLayoutItem *item = m_grid->itemAt(0);
+ m_grid->removeItem(item);
+ delete item->widget();
+ delete item;
+ }
+ m_toplevel->setLayout(m_grid);
+
+ // a layout with a top-level parent widget
+ QList<QPointer<SizeHinterFrame> > sizehinters;
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < columns; ++j) {
+ SizeInfo si = sizeinfos.at(sizehinters.count());
+ int numpixels = si.hfwNumPixels;
+ if (pass == 1 && numpixels == -1)
+ numpixels = -2; //### yuk, (and don't fake it if it already tests sizehint)
+ SizeHinterFrame *sh = new SizeHinterFrame(si.sizeHint, numpixels);
+ QSizePolicy sp = sh->sizePolicy();
+ sp.setHorizontalPolicy((QSizePolicy::Policy)sizePolicy);
+ sh->setSizePolicy(sp);
+ sh->setParent(m_toplevel);
+ if (si.minSize.isValid())
+ sh->setMinimumSize(si.minSize);
+ if (si.maxSize.isValid())
+ sh->setMaximumSize(si.maxSize);
+ sizehinters.append(sh);
+ m_grid->addWidget(sh, i, j);
+ }
+ }
+
+ m_toplevel->show();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(m_toplevel); // wait for the show
+#endif
+ QTest::qWait(40);
+ m_toplevel->adjustSize();
+ QTest::qWait(240); // wait for the implicit adjustSize
+ // If the following fails we might have to wait longer.
+ // If that does not help there is likely a problem with the implicit adjustSize in show()
+ if (!fixedSize.isValid()) {
+ // Note that this can fail if the desktop has large fonts on windows.
+ QTRY_COMPARE(m_toplevel->size(), m_toplevel->sizeHint());
+ }
+ // We are relying on the order here...
+ for (int pi = 0; pi < sizehinters.count(); ++pi) {
+ QPoint pt = sizehinters.at(pi)->mapTo(m_toplevel, QPoint(0, 0));
+ QCOMPARE(pt, sizeinfos.at(pi).expectedPos);
+ }
+ }
+}
+
+
+class CustomLayoutStyle : public QWindowsStyle
+{
+ Q_OBJECT
+public:
+ CustomLayoutStyle() : QWindowsStyle()
+ {
+ hspacing = 5;
+ vspacing = 10;
+ reimplementSubelementRect = false;
+ }
+
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption * option = 0,
+ const QWidget * widget = 0 ) const;
+ virtual QRect subElementRect(SubElement sr, const QStyleOption *opt,
+ const QWidget *widget) const;
+
+ int hspacing;
+ int vspacing;
+ bool reimplementSubelementRect;
+
+protected slots:
+ int layoutSpacingImplementation(QSizePolicy::ControlType control1,
+ QSizePolicy::ControlType control2,
+ Qt::Orientation orientation,
+ const QStyleOption *option = 0,
+ const QWidget *widget = 0) const;
+
+};
+
+QRect CustomLayoutStyle::subElementRect(SubElement sr, const QStyleOption *opt,
+ const QWidget *widget) const
+{
+ QRect rect;
+ if (reimplementSubelementRect) {
+ switch (sr) {
+ case SE_FrameLayoutItem:
+ rect = opt->rect;
+ rect.adjust(+4, +9, -4, 0); // The hspacing=5 and vspacing=10, so we keep it safe.
+ break;
+ case SE_GroupBoxLayoutItem:
+ rect = opt->rect.adjusted(0, +10, 0, 0);
+ break;
+ default:
+ break;
+ }
+ }
+ if (rect.isNull())
+ rect = QWindowsStyle::subElementRect(sr, opt, widget);
+ return rect;
+}
+
+#define CT1(c) CT2(c, c)
+#define CT2(c1, c2) ((uint)c1 << 16) | (uint)c2
+
+int CustomLayoutStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1,
+ QSizePolicy::ControlType control2,
+ Qt::Orientation orientation,
+ const QStyleOption * /*option = 0*/,
+ const QWidget * /*widget = 0*/) const
+{
+ if (orientation == Qt::Horizontal) {
+ switch (CT2(control1, control2)) {
+ case CT1(QSizePolicy::PushButton):
+ return 2;
+ break;
+ }
+ return 5;
+ } else {
+ switch (CT2(control1, control2)) {
+ case CT1(QSizePolicy::RadioButton):
+ return 2;
+ break;
+
+ }
+ return 10;
+ }
+}
+
+int CustomLayoutStyle::pixelMetric(PixelMetric metric, const QStyleOption * option /*= 0*/,
+ const QWidget * widget /*= 0*/ ) const
+{
+ switch (metric) {
+ case PM_LayoutLeftMargin:
+ return 0;
+ break;
+ case PM_LayoutTopMargin:
+ return 3;
+ break;
+ case PM_LayoutRightMargin:
+ return 6;
+ break;
+ case PM_LayoutBottomMargin:
+ return 9;
+ break;
+ case PM_LayoutHorizontalSpacing:
+ return hspacing;
+ case PM_LayoutVerticalSpacing:
+ return vspacing;
+ break;
+ default:
+ break;
+ }
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+}
+
+void tst_QGridLayout::styleDependentSpacingsAndMargins_data()
+{
+ // input
+ QTest::addColumn<int>("columns");
+ QTest::addColumn<int>("rows");
+ QTest::addColumn<QSize>("sizehint");
+ // expected
+ QTest::addColumn<PointList>("expectedpositions");
+
+ QTest::newRow("1x1 grid") << 1 << 1 << QSize(100, 100)
+ << (PointList() << QPoint(0, 3) );
+ QTest::newRow("2x1 grid") << 2 << 1 << QSize(100, 100)
+ << (PointList() << QPoint(0, 3)
+ << QPoint(0+100+5, 3));
+ QTest::newRow("3x1 grid") << 3 << 1 << QSize(100, 100)
+ << (PointList() << QPoint(0, 3)
+ << QPoint(0+100+5, 3)
+ << QPoint(0 + 2*105, 3));
+ QTest::newRow("1x2 grid") << 1 << 2 << QSize(100, 100)
+ << (PointList() << QPoint(0, 3)
+ << QPoint(0, 3+100+10));
+ QTest::newRow("1x3 grid") << 1 << 3 << QSize(100, 100)
+ << (PointList() << QPoint(0, 3)
+ << QPoint(0, 3+100+10)
+ << QPoint(0, 3+2*110));
+ QTest::newRow("2x2 grid") << 2 << 2 << QSize(100, 100)
+ << (PointList() << QPoint(0, 3) << QPoint(0+100+5, 3)
+ << QPoint(0, 3+100+10) << QPoint(0+100+5, 3+100+10));
+}
+
+
+void tst_QGridLayout::styleDependentSpacingsAndMargins()
+{
+ QFETCH(int, columns);
+ QFETCH(int, rows);
+ QFETCH(QSize, sizehint);
+ QFETCH(PointList, expectedpositions);
+
+ QApplication::setStyle(new CustomLayoutStyle());
+ QWidget widget;
+ QGridLayout layout(&widget);
+ QList<QPointer<SizeHinterFrame> > sizehinters;
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < columns; ++j) {
+ SizeHinterFrame *sh = new SizeHinterFrame(sizehint);
+ sh->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
+ sh->setParent(&widget);
+ sizehinters.append(sh);
+ layout.addWidget(sh, i, j);
+ }
+ }
+ layout.setColumnStretch(columns, 1);
+ layout.setRowStretch(rows, 1);
+ widget.show();
+ widget.adjustSize();
+ QApplication::processEvents();
+
+ for (int pi = 0; pi < expectedpositions.count(); ++pi) {
+ QCOMPARE(sizehinters.at(pi)->pos(), expectedpositions.at(pi));
+ }
+}
+
+void tst_QGridLayout::layoutSpacingImplementation_data()
+{
+ QTest::addColumn<QWidget*>("widget");
+ // expected
+ QTest::addColumn<PointList>("expectedpositions");
+ QTest::addColumn<int>("hSpacing");
+ QTest::addColumn<int>("vSpacing");
+ QTest::addColumn<bool>("customSubElementRect");
+
+ CustomLayoutStyle *style = new CustomLayoutStyle();
+ {
+ // If the layoutSpacing is negative, the layouting code will call
+ // layoutSpacingImplementation()
+ style->hspacing = -1;
+ style->vspacing = -1;
+ style->reimplementSubelementRect = false;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QVBoxLayout *layout = new QVBoxLayout();
+ QRadioButton *rb1 = new QRadioButton(QLatin1String("Radio 1"), w);
+ QRadioButton *rb2 = new QRadioButton(QLatin1String("Radio 2"), w);
+ QRadioButton *rb3 = new QRadioButton(QLatin1String("Radio 3"), w);
+ layout->addWidget(rb1, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(rb2, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(rb3, 0, Qt::AlignTop | Qt::AlignLeft);
+
+ QPushButton *b1 = new QPushButton(QLatin1String("Push 1"), w);
+ QPushButton *b2 = new QPushButton(QLatin1String("Push 2"), w);
+ QPushButton *b3 = new QPushButton(QLatin1String("Push 3"), w);
+ layout->addWidget(b1, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(b2, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(b3, 0, Qt::AlignTop | Qt::AlignLeft);
+
+ layout->addStretch(1);
+ w->setLayout(layout);
+ int rh = rb1->sizeHint().height();
+ int ph = b1->sizeHint().height();
+ QTest::newRow("1x6, radio + push buttons")
+ << w << (PointList()
+ << QPoint(0, 3)
+ << QPoint(0, 3 + rh + 2)
+ << QPoint(0, 3 + 2*(rh + 2))
+ << QPoint(0, 3 + 2*(rh + 2) + (rh + 10))
+ << QPoint(0, 3 + 2*(rh + 2) + (rh + 10 + ph + 10))
+ << QPoint(0, 3 + 2*(rh + 2) + rh + 10 + 2*(ph + 10)))
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+
+ {
+ style->hspacing = -1;
+ style->vspacing = -1;
+ style->reimplementSubelementRect = false;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QHBoxLayout *layout = new QHBoxLayout();
+ QLineEdit *le1 = new QLineEdit(w);
+ QLineEdit *le2 = new QLineEdit(w);
+ QLineEdit *le3 = new QLineEdit(w);
+ layout->addWidget(le1, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(le2, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(le3, 0, Qt::AlignTop | Qt::AlignLeft);
+
+ QPushButton *b1 = new QPushButton(QLatin1String("Push 1"), w);
+ QPushButton *b2 = new QPushButton(QLatin1String("Push 2"), w);
+ QPushButton *b3 = new QPushButton(QLatin1String("Push 3"), w);
+ layout->addWidget(b1, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(b2, 0, Qt::AlignTop | Qt::AlignLeft);
+ layout->addWidget(b3, 0, Qt::AlignTop | Qt::AlignLeft);
+
+ layout->addStretch(1);
+ w->setLayout(layout);
+ int lw = le1->sizeHint().width();
+ int pw = b1->sizeHint().width();
+ QTest::newRow("6x1, line edit + push buttons")
+ << w << (PointList()
+ << QPoint(0, 3)
+ << QPoint(0 + lw + 5, 3)
+ << QPoint(0 + 2*(lw + 5), 3)
+ << QPoint(0 + 3*(lw + 5), 3)
+ << QPoint(0 + 3*(lw + 5) + 1*(pw + 2), 3)
+ << QPoint(0 + 3*(lw + 5) + 2*(pw + 2), 3))
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+
+
+ {
+ style->hspacing = 5;
+ style->vspacing = 10;
+ style->reimplementSubelementRect = true;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QVBoxLayout *layout = new QVBoxLayout();
+ QPushButton *pb1 = new QPushButton(QLatin1String("Push 1"), w);
+
+ QGroupBox *g1 = new QGroupBox(QLatin1String("GroupBox 1"), w);
+
+ QRadioButton *rb = new QRadioButton(QLatin1String("Radio 1"), g1);
+ QVBoxLayout *g1layout = new QVBoxLayout();
+ g1layout->addWidget(rb);
+ g1->setLayout(g1layout);
+
+ QPushButton *pb3 = new QPushButton(QLatin1String("Push 3"), w);
+
+ layout->addWidget(pb1);
+ layout->addWidget(g1 );
+ layout->addWidget(pb3);
+
+ w->setLayout(layout);
+ QSize psh = pb1->sizeHint();
+ QSize gsh = g1->sizeHint();
+
+ QTest::newRow("subElementRect1")
+ << w << (PointList()
+ << QPoint(0, 3)
+ << QPoint(0, 3 + psh.height() + 10 - 10)
+ << QPoint(0, 3 + psh.height() + 10 - 10 + gsh.height() + 10)
+ )
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+
+
+ {
+ style->hspacing = 5;
+ style->vspacing = 10;
+ style->reimplementSubelementRect = true;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QGridLayout *layout = new QGridLayout();
+ QPushButton *pb1 = new QPushButton(QLatin1String("Push 1"), w);
+ QPushButton *pb2 = new QPushButton(QLatin1String("Push 2"), w);
+ QPushButton *pb3 = new QPushButton(QLatin1String("Push 3"), w);
+ QPushButton *pb4 = new QPushButton(QLatin1String("Push 4"), w);
+
+ layout->addWidget(pb1, 0, 0);
+ layout->addWidget(pb2, 0, 1);
+ layout->addWidget(pb3, 0, 2);
+ layout->addWidget(pb4, 1, 0, Qt::AlignTop);
+
+
+ QFrame *f1 = new QFrame(w);
+ f1->setFrameStyle(QFrame::Box | QFrame::Plain);
+ f1->setMinimumSize(100, 20);
+ f1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+
+ layout->addWidget(f1, 1, 1, Qt::AlignTop);
+
+
+ QPushButton *pb6 = new QPushButton(QLatin1String("Push 6"), w);
+ QPushButton *pb7 = new QPushButton(QLatin1String("Push 7"), w);
+ QPushButton *pb8 = new QPushButton(QLatin1String("Push 8"), w);
+ QPushButton *pb9 = new QPushButton(QLatin1String("Push 9"), w);
+ layout->addWidget(pb6, 1, 2, Qt::AlignTop);
+ layout->addWidget(pb7, 2, 0, Qt::AlignTop);
+ layout->addWidget(pb8, 2, 1, Qt::AlignTop);
+ layout->addWidget(pb9, 2, 2, Qt::AlignTop);
+
+ layout->setColumnStretch(2, 1);
+ layout->setRowStretch(2, 1);
+ w->setLayout(layout);
+ int c[3];
+ c[0] = pb1->sizeHint().width();
+ c[1] = f1->minimumSize().width() - 2*4;
+ c[2] = pb3->sizeHint().width();
+
+ int r[3];
+ r[0] = pb1->sizeHint().height();
+ r[1] = pb4->sizeHint().height();
+ r[2] = pb7->sizeHint().height();
+
+
+ QTest::newRow("subElementRect2")
+ << w << (PointList()
+ << QPoint(0, 3)
+ << QPoint(0 + c[0] + 5, 3)
+ << QPoint(0 + c[0] + 5 + c[1] + 5, 3)
+
+ << QPoint(0, 3 + r[0] + 10)
+ << QPoint(0 + c[0] + 5 - 4, 3 + r[0] + 10 - 9)
+ << QPoint(0 + c[0] + 5 + c[1] + 5, 3 + r[0] + 10)
+
+ << QPoint(0, 3 + r[0] + 10 + r[1] + 10)
+ << QPoint(0 + c[0] + 5, 3 + r[0] + 10 + r[1] + 10)
+ << QPoint(0 + c[0] + 5 + c[1] + 5, 3 + r[0] + 10 + r[1] + 10)
+
+ )
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+
+ {
+ style->hspacing = 5;
+ style->vspacing = 10;
+ style->reimplementSubelementRect = true;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QVBoxLayout *layout = new QVBoxLayout();
+ QPushButton *pb1 = new QPushButton(QLatin1String("Push 1"), w);
+
+ QGroupBox *g1 = new QGroupBox(QLatin1String("GroupBox 1"), w);
+
+ QRadioButton *rb = new QRadioButton(QLatin1String("Radio 1"), g1);
+ QVBoxLayout *g1layout = new QVBoxLayout();
+ g1layout->addWidget(rb);
+ g1->setLayout(g1layout);
+
+ QPushButton *pb3 = new QPushButton(QLatin1String("Push 3"), w);
+
+ pb1->setAttribute(Qt::WA_LayoutUsesWidgetRect, true);
+ g1->setAttribute(Qt::WA_LayoutUsesWidgetRect, true);
+ pb3->setAttribute(Qt::WA_LayoutUsesWidgetRect, true);
+ layout->addWidget(pb1);
+ layout->addWidget(g1 );
+ layout->addWidget(pb3);
+
+ w->setLayout(layout);
+ QSize psh = pb1->sizeHint();
+ QSize gsh = g1->sizeHint();
+
+ QTest::newRow("subElementRect1, use widgetRect")
+ << w << (PointList()
+ << QPoint(0, 3)
+ << QPoint(0, 3 + psh.height() + 10)
+ << QPoint(0, 3 + psh.height() + 10 + gsh.height() + 10)
+ )
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+
+
+ {
+ style->hspacing = 5;
+ style->vspacing = 10;
+ style->reimplementSubelementRect = true;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QVBoxLayout *layout = new QVBoxLayout();
+ QPushButton *pb1 = new QPushButton(QLatin1String("Push 1"), w);
+
+ QGroupBox *g1 = new QGroupBox(QLatin1String("GroupBox 1"), w);
+
+ QRadioButton *rb = new QRadioButton(QLatin1String("Radio 1"), g1);
+ QVBoxLayout *g1layout = new QVBoxLayout();
+ g1layout->addWidget(rb);
+ g1->setLayout(g1layout);
+
+ QPushButton *pb3 = new QPushButton(QLatin1String("Push 3"), w);
+
+ pb1->setAttribute(Qt::WA_LayoutUsesWidgetRect, false);
+ g1->setAttribute(Qt::WA_LayoutUsesWidgetRect, false);
+ pb3->setAttribute(Qt::WA_LayoutUsesWidgetRect, false);
+ layout->addWidget(pb1);
+ layout->addWidget(g1 );
+ layout->addWidget(pb3);
+
+ w->setLayout(layout);
+ QSize psh = pb1->sizeHint();
+ QSize gsh = g1->sizeHint();
+
+ QTest::newRow("subElementRect1, use layoutItemRect")
+ << w << (PointList()
+ << QPoint(0, 3)
+ << QPoint(0, 3 + psh.height() + 10 - 10)
+ << QPoint(0, 3 + psh.height() + 10 - 10 + gsh.height() + 10)
+ )
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+
+
+ {
+ /* A 3x4 gridlayout, modified arrowpad example:
+ * [PB]
+ * [PB] [PB]
+ * |PB|
+ * | |
+ * | |
+ *
+ * Here the bottom pushbutton has a span
+ */
+ style->hspacing = -1;
+ style->vspacing = -1;
+ style->reimplementSubelementRect = false;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QGridLayout *layout = new QGridLayout();
+ QPushButton *left = new QPushButton(w);
+ QPushButton *up = new QPushButton(w);
+ QPushButton *right = new QPushButton(w);
+ QPushButton *down = new QPushButton(w);
+
+ layout->addWidget(up, 0, 1);
+ layout->addWidget(left, 1, 0);
+ layout->addWidget(right, 1, 2);
+ layout->addWidget(down, 2, 1, 3, 1);
+
+ w->setLayout(layout);
+ int pw = up->sizeHint().width();
+ int ph = up->sizeHint().height();
+ QTest::newRow("arrowpad with span")
+ << w << (PointList()
+ << QPoint(0 + pw + 5, 3)
+ << QPoint(0, 3 + ph + 10)
+ << QPoint(0 + pw + 5 + pw + 5, 3 + ph + 10)
+ << QPoint(0 + pw + 5, 3 + ph + 10 + ph + 10)
+ )
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+
+
+ for (int yoff = 0; yoff < 5; ++yoff)
+ {
+ for (int xoff = 0; xoff < 5; ++xoff) {
+ /* A 3x4 gridlayout, modified arrowpad example:
+ * [empty cells]
+ * [PB]
+ * [PB] [PB]
+ * [PB]
+ *
+ * It has 0-4 empty rows at the top and 0-4 empty columns to the left.
+ */
+ style->hspacing = -1;
+ style->vspacing = -1;
+ style->reimplementSubelementRect = false;
+ QApplication::setStyle(style);
+ QWidget *w = new QWidget();
+ QGridLayout *layout = new QGridLayout();
+ QPushButton *left = new QPushButton(w);
+ QPushButton *up = new QPushButton(w);
+ QPushButton *right = new QPushButton(w);
+ QPushButton *down = new QPushButton(w);
+
+ layout->addWidget(up, yoff + 0, xoff + 1);
+ layout->addWidget(left, yoff + 1, xoff + 0);
+ layout->addWidget(right, yoff + 1, xoff + 2);
+ layout->addWidget(down, yoff + 2, xoff + 1, 3, 1);
+
+ w->setLayout(layout);
+ int pw = up->sizeHint().width();
+ int ph = up->sizeHint().height();
+ QByteArray testName = QString::fromAscii("arrowpad with %1 empty rows, %2 empty columns").arg(yoff).arg(xoff).toLatin1();
+ QTest::newRow(testName.data())
+ << w << (PointList()
+ << QPoint(0 + pw + 5, 3)
+ << QPoint(0, 3 + ph + 10)
+ << QPoint(0 + pw + 5 + pw + 5, 3 + ph + 10)
+ << QPoint(0 + pw + 5, 3 + ph + 10 + ph + 10)
+ )
+ << style->hspacing << style->vspacing << style->reimplementSubelementRect;
+ }
+ }
+
+}
+
+void tst_QGridLayout::layoutSpacingImplementation()
+{
+ QFETCH(QWidget *, widget);
+ QFETCH(PointList, expectedpositions);
+ QFETCH(int, hSpacing);
+ QFETCH(int, vSpacing);
+ QFETCH(bool, customSubElementRect);
+
+ QWidget toplevel;
+
+ CustomLayoutStyle *style = new CustomLayoutStyle();
+ style->hspacing = hSpacing;
+ style->vspacing = vSpacing;
+ style->reimplementSubelementRect = customSubElementRect;
+ QApplication::setStyle(style);
+ widget->setParent(&toplevel);
+ widget->resize(widget->sizeHint());
+ toplevel.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&toplevel); // wait for the show
+#endif
+
+ QLayout *layout = widget->layout();
+ QVERIFY(layout);
+ //QTest::qWait(2000);
+ for (int pi = 0; pi < expectedpositions.count(); ++pi) {
+ QLayoutItem *item = layout->itemAt(pi);
+ //qDebug() << item->widget()->pos();
+ QCOMPARE(item->widget()->pos(), expectedpositions.at(pi));
+ }
+}
+
+void tst_QGridLayout::spacing()
+{
+ QWidget w;
+ CustomLayoutStyle *style = new CustomLayoutStyle();
+ style->hspacing = 5;
+ style->vspacing = 10;
+ w.setStyle(style);
+ QGridLayout grid(&w);
+ QCOMPARE(style->hspacing, grid.horizontalSpacing());
+ QCOMPARE(style->vspacing, grid.verticalSpacing());
+
+ QCOMPARE(grid.spacing(), -1);
+ grid.setVerticalSpacing(5);
+ QCOMPARE(5, grid.horizontalSpacing());
+ QCOMPARE(5, grid.verticalSpacing());
+ QCOMPARE(grid.spacing(), 5);
+ grid.setVerticalSpacing(-1);
+ QCOMPARE(style->hspacing, grid.horizontalSpacing());
+ QCOMPARE(style->vspacing, grid.verticalSpacing());
+
+ style->hspacing = 5;
+ style->vspacing = 5;
+ QCOMPARE(grid.spacing(), 5);
+
+
+ grid.setHorizontalSpacing(20);
+ QCOMPARE(grid.spacing(), -1);
+ style->vspacing = 20;
+ QCOMPARE(grid.horizontalSpacing(), 20);
+ QCOMPARE(grid.verticalSpacing(), 20);
+ QCOMPARE(grid.spacing(), 20);
+ grid.setHorizontalSpacing(-1);
+ QCOMPARE(grid.spacing(), -1);
+ style->hspacing = 20;
+ QCOMPARE(grid.spacing(), 20);
+
+
+ delete style;
+}
+
+void populate(QGridLayout *layout, int row, int kind)
+{
+ if (kind == 0) {
+ QWidget *widget = new QWidget;
+ widget->setFixedSize(100, 100);
+ layout->addWidget(widget, row, 0);
+ } else if (kind == 1) {
+ layout->addItem(new QSpacerItem(10, 10), row, 0);
+ }
+}
+
+void tst_QGridLayout::spacerWithSpacing()
+{
+ // Tests all combinations of widget (w), spacer (s) and no layoutitem (-)
+ // to see if they are laid out correctly.
+ // Note that a combination of "s-" or "-s" should only give the height of "s"
+ const int expectedHeight[] = {
+ 302,// www
+ 211,// wws
+ 201,// ww-
+ 211,// wsw
+ 120,// wss
+ 110,// ws-
+ 201,// w-w
+ 110,// w-s
+ 100,// w--
+ 211,// sww
+ 120,// sws
+ 110,// sw-
+ 120,// ssw
+ 30,// sss
+ 20,// ss-
+ 110,// s-w
+ 20,// s-s
+ 10,// s--
+ 201,// -ww
+ 110,// -ws
+ 100,// -w-
+ 110,// -sw
+ 20,// -ss
+ 10,// -s-
+ 100,// --w
+ 10,// --s
+ 000 // ---
+ };
+ int ii = 0;
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ for (int k = 0; k < 3; ++k) {
+ QWidget window;
+ QGridLayout layout(&window);
+ layout.setSpacing(1);
+ layout.setMargin(0);
+ populate(&layout, 0, i);
+ populate(&layout, 1, j);
+ populate(&layout, 2, k);
+ QCOMPARE(window.sizeHint().height(), expectedHeight[ii]);
+#if 0
+ const char T[] = "ws-";
+ qWarning("%c%c%c: %.3d", i[T], j[T], k[T], window.sizeHint().height());
+#endif
+ ++ii;
+ }
+ }
+ }
+}
+
+void tst_QGridLayout::contentsRect()
+{
+ QWidget w;
+ QGridLayout grid;
+ w.setLayout(&grid);
+ grid.addWidget(new QPushButton(&w));
+ w.show();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(&w); // wait for the show
+#endif
+ int l, t, r, b;
+ grid.getContentsMargins(&l, &t, &r, &b);
+ QRect geom = grid.geometry();
+
+ QCOMPARE(geom.adjusted(+l, +t, -r, -b), grid.contentsRect());
+
+}
+
+void tst_QGridLayout::distributeMultiCell()
+{
+ QWidget w;
+ Qt42Style *style = new Qt42Style();
+ style->spacing = 9;
+
+ w.setStyle(style);
+ QGridLayout grid;
+ w.setLayout(&grid);
+
+ SizeHinter le1(200, 20, &w);
+ le1.setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+ SizeHinter le2(200, 20, &w);
+ le2.setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
+ SizeHinter box(80, 57, &w);
+ box.setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding));
+ box.setMinimumSize(80, 57);
+
+ grid.addWidget(&le1, 0, 0, 1, 1);
+ grid.addWidget(&le2, 1, 0, 1, 1);
+ grid.addWidget(&box, 0, 1, 2, 1);
+
+ QCOMPARE(box.sizeHint().height(), 57);
+ QCOMPARE(w.sizeHint().height(), 11 + 57 + 11);
+}
+
+QTEST_MAIN(tst_QGridLayout)
+#include "tst_qgridlayout.moc"
diff --git a/tests/auto/widgets/kernel/qinputcontext/qinputcontext.pro b/tests/auto/widgets/kernel/qinputcontext/qinputcontext.pro
new file mode 100644
index 0000000000..cdadb0c5ed
--- /dev/null
+++ b/tests/auto/widgets/kernel/qinputcontext/qinputcontext.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qinputcontext.cpp
+
+mac*:CONFIG+=insignificant_test
+
+CONFIG += insignificant_test # QTBUG-21402
diff --git a/tests/auto/widgets/kernel/qinputcontext/tst_qinputcontext.cpp b/tests/auto/widgets/kernel/qinputcontext/tst_qinputcontext.cpp
new file mode 100644
index 0000000000..9b6452851e
--- /dev/null
+++ b/tests/auto/widgets/kernel/qinputcontext/tst_qinputcontext.cpp
@@ -0,0 +1,398 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <qinputcontext.h>
+#include <qlineedit.h>
+#include <qplaintextedit.h>
+#include <qlayout.h>
+#include <qradiobutton.h>
+#include <qwindowsstyle.h>
+#include <qdesktopwidget.h>
+#include <qpushbutton.h>
+#include <qgraphicsview.h>
+#include <qgraphicsscene.h>
+
+#ifdef QT_WEBKIT_LIB
+#include <qwebview.h>
+#include <qgraphicswebview.h>
+#endif
+
+class tst_QInputContext : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QInputContext() : m_phoneIsQwerty(false) {}
+ virtual ~tst_QInputContext() {}
+
+public slots:
+ void cleanupTestCase() {}
+ void init() {}
+ void cleanup() {}
+private slots:
+ void maximumTextLength();
+ void filterMouseEvents();
+ void requestSoftwareInputPanel();
+ void closeSoftwareInputPanel();
+ void selections();
+ void focusProxy();
+
+private:
+ bool m_phoneIsQwerty;
+};
+
+void tst_QInputContext::maximumTextLength()
+{
+ QLineEdit le;
+
+ le.setMaxLength(15);
+ QVariant variant = le.inputMethodQuery(Qt::ImMaximumTextLength);
+ QVERIFY(variant.isValid());
+ QCOMPARE(variant.toInt(), 15);
+
+ QPlainTextEdit pte;
+ // For BC/historical reasons, QPlainTextEdit::inputMethodQuery is protected.
+ variant = static_cast<QWidget *>(&pte)->inputMethodQuery(Qt::ImMaximumTextLength);
+ QVERIFY(!variant.isValid());
+}
+
+class QFilterInputContext : public QInputContext
+{
+public:
+ QFilterInputContext() {}
+ ~QFilterInputContext() {}
+
+ QString identifierName() { return QString(); }
+ QString language() { return QString(); }
+
+ void reset() {}
+
+ bool isComposing() const { return false; }
+
+ bool filterEvent( const QEvent *event )
+ {
+ lastTypes.append(event->type());
+ return false;
+ }
+
+public:
+ QList<QEvent::Type> lastTypes;
+};
+
+void tst_QInputContext::filterMouseEvents()
+{
+ QLineEdit le;
+ le.show();
+ QApplication::setActiveWindow(&le);
+
+ QFilterInputContext *ic = new QFilterInputContext;
+ qApp->setInputContext(ic);
+ QTest::mouseClick(&le, Qt::LeftButton);
+
+ QVERIFY(ic->lastTypes.indexOf(QEvent::MouseButtonRelease) >= 0);
+}
+
+class RequestSoftwareInputPanelStyle : public QWindowsStyle
+{
+public:
+ RequestSoftwareInputPanelStyle()
+ : m_rsipBehavior(RSIP_OnMouseClickAndAlreadyFocused)
+ {
+#ifdef Q_OS_WINCE
+ qApp->setAutoSipEnabled(true);
+#endif
+ }
+ ~RequestSoftwareInputPanelStyle()
+ {
+ }
+
+ int styleHint(StyleHint hint, const QStyleOption *opt = 0,
+ const QWidget *widget = 0, QStyleHintReturn* returnData = 0) const
+ {
+ if (hint == SH_RequestSoftwareInputPanel) {
+ return m_rsipBehavior;
+ } else {
+ return QWindowsStyle::styleHint(hint, opt, widget, returnData);
+ }
+ }
+
+ RequestSoftwareInputPanel m_rsipBehavior;
+};
+
+void tst_QInputContext::requestSoftwareInputPanel()
+{
+ QStyle *oldStyle = qApp->style();
+ oldStyle->setParent(this); // Prevent it being deleted.
+ RequestSoftwareInputPanelStyle *newStyle = new RequestSoftwareInputPanelStyle;
+ qApp->setStyle(newStyle);
+
+ QWidget w;
+ QLayout *layout = new QVBoxLayout;
+ QLineEdit *le1, *le2;
+ le1 = new QLineEdit;
+ le2 = new QLineEdit;
+ layout->addWidget(le1);
+ layout->addWidget(le2);
+ w.setLayout(layout);
+
+ QFilterInputContext *ic = new QFilterInputContext;
+ qApp->setInputContext(ic);
+
+ w.show();
+ QApplication::setActiveWindow(&w);
+
+ // Testing single click panel activation.
+ newStyle->m_rsipBehavior = QStyle::RSIP_OnMouseClick;
+ QTest::mouseClick(le2, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QVERIFY(ic->lastTypes.indexOf(QEvent::RequestSoftwareInputPanel) >= 0);
+ ic->lastTypes.clear();
+
+ // Testing double click panel activation.
+ newStyle->m_rsipBehavior = QStyle::RSIP_OnMouseClickAndAlreadyFocused;
+ QTest::mouseClick(le1, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QVERIFY(ic->lastTypes.indexOf(QEvent::RequestSoftwareInputPanel) < 0);
+ QTest::mouseClick(le1, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QVERIFY(ic->lastTypes.indexOf(QEvent::RequestSoftwareInputPanel) >= 0);
+ ic->lastTypes.clear();
+
+ // Testing right mouse button
+ QTest::mouseClick(le1, Qt::RightButton, Qt::NoModifier, QPoint(5, 5));
+ QVERIFY(ic->lastTypes.indexOf(QEvent::RequestSoftwareInputPanel) < 0);
+
+ qApp->setStyle(oldStyle);
+ oldStyle->setParent(qApp);
+}
+
+void tst_QInputContext::closeSoftwareInputPanel()
+{
+ QWidget w;
+ QLayout *layout = new QVBoxLayout;
+ QLineEdit *le1, *le2;
+ QRadioButton *rb;
+ le1 = new QLineEdit;
+ le2 = new QLineEdit;
+ rb = new QRadioButton;
+ layout->addWidget(le1);
+ layout->addWidget(le2);
+ layout->addWidget(rb);
+ w.setLayout(layout);
+
+ QFilterInputContext *ic = new QFilterInputContext;
+ qApp->setInputContext(ic);
+
+ w.show();
+ QApplication::setActiveWindow(&w);
+
+ // Testing that panel doesn't close between two input methods aware widgets.
+ QTest::mouseClick(le1, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QTest::mouseClick(le2, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QVERIFY(ic->lastTypes.indexOf(QEvent::CloseSoftwareInputPanel) < 0);
+
+ // Testing that panel closes when focusing non-aware widget.
+ QTest::mouseClick(rb, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
+ QVERIFY(ic->lastTypes.indexOf(QEvent::CloseSoftwareInputPanel) >= 0);
+}
+
+void tst_QInputContext::selections()
+{
+ QLineEdit le;
+ le.setText("Test text");
+ le.setSelection(2, 2);
+ QCOMPARE(le.inputMethodQuery(Qt::ImCursorPosition).toInt(), 4);
+ QCOMPARE(le.inputMethodQuery(Qt::ImAnchorPosition).toInt(), 2);
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 5, 3, QVariant()));
+ QInputMethodEvent event("", attributes);
+ QApplication::sendEvent(&le, &event);
+ QCOMPARE(le.cursorPosition(), 8);
+ QCOMPARE(le.selectionStart(), 5);
+ QCOMPARE(le.inputMethodQuery(Qt::ImCursorPosition).toInt(), 8);
+ QCOMPARE(le.inputMethodQuery(Qt::ImAnchorPosition).toInt(), 5);
+}
+
+void tst_QInputContext::focusProxy()
+{
+ QWidget toplevel(0, Qt::X11BypassWindowManagerHint); toplevel.setObjectName("toplevel");
+ QWidget w(&toplevel); w.setObjectName("w");
+ QWidget proxy(&w); proxy.setObjectName("proxy");
+ QWidget proxy2(&w); proxy2.setObjectName("proxy2");
+ w.setFocusProxy(&proxy);
+ w.setAttribute(Qt::WA_InputMethodEnabled);
+ toplevel.show();
+ QApplication::setActiveWindow(&toplevel);
+ QTest::qWaitForWindowShown(&toplevel);
+ w.setFocus();
+ w.setAttribute(Qt::WA_NativeWindow); // we shouldn't crash!
+
+ proxy.setAttribute(Qt::WA_InputMethodEnabled);
+ proxy2.setAttribute(Qt::WA_InputMethodEnabled);
+
+ proxy2.setFocus();
+ w.setFocus();
+
+ QInputContext *gic = qApp->inputContext();
+ QVERIFY(gic);
+ QCOMPARE(gic->focusWidget(), &proxy);
+
+ // then change the focus proxy and check that input context is valid
+ QVERIFY(w.hasFocus());
+ QVERIFY(proxy.hasFocus());
+ QVERIFY(!proxy2.hasFocus());
+ w.setFocusProxy(&proxy2);
+ QVERIFY(!w.hasFocus());
+ QVERIFY(proxy.hasFocus());
+ QVERIFY(!proxy2.hasFocus());
+ QCOMPARE(gic->focusWidget(), &proxy);
+}
+
+#ifdef QT_WEBKIT_LIB
+class AutoWebView : public QWebView
+{
+ Q_OBJECT
+
+public:
+ AutoWebView()
+ : m_length(0)
+ , m_mode(QLineEdit::Normal)
+ {
+ updatePage();
+ }
+ ~AutoWebView() {}
+
+ void updatePage()
+ {
+ // The update might reset the input method parameters.
+ bool imEnabled = testAttribute(Qt::WA_InputMethodEnabled);
+ Qt::InputMethodHints hints = inputMethodHints();
+
+ QString page = "<html><body onLoad=\"document.forms.testform.testinput.focus()\">"
+ "<form name=\"testform\"><input name=\"testinput\" type=\"%1\" %2></form></body></html>";
+ if (m_mode == QLineEdit::Password)
+ page = page.arg("password");
+ else
+ page = page.arg("text");
+
+ if (m_length == 0)
+ page = page.arg("");
+ else
+ page = page.arg("maxlength=\"" + QString::number(m_length) + "\"");
+
+ setHtml(page);
+
+ setAttribute(Qt::WA_InputMethodEnabled, imEnabled);
+ setInputMethodHints(hints);
+ }
+ void setMaxLength(int length)
+ {
+ m_length = length;
+ updatePage();
+ }
+ void setEchoMode(QLineEdit::EchoMode mode)
+ {
+ m_mode = mode;
+ updatePage();
+ }
+
+ int m_length;
+ QLineEdit::EchoMode m_mode;
+};
+
+class AutoGraphicsWebView : public QGraphicsView
+{
+ Q_OBJECT
+
+public:
+ AutoGraphicsWebView()
+ : m_length(0)
+ , m_mode(QLineEdit::Normal)
+ {
+ m_scene.addItem(&m_view);
+ setScene(&m_scene);
+ m_view.setFocus();
+ updatePage();
+ }
+ ~AutoGraphicsWebView() {}
+
+ void updatePage()
+ {
+ // The update might reset the input method parameters.
+ bool imEnabled = testAttribute(Qt::WA_InputMethodEnabled);
+ Qt::InputMethodHints hints = inputMethodHints();
+
+ QString page = "<html><body onLoad=\"document.forms.testform.testinput.focus()\">"
+ "<form name=\"testform\"><input name=\"testinput\" type=\"%1\" %2></form></body></html>";
+ if (m_mode == QLineEdit::Password)
+ page = page.arg("password");
+ else
+ page = page.arg("text");
+
+ if (m_length == 0)
+ page = page.arg("");
+ else
+ page = page.arg("maxlength=\"" + QString::number(m_length) + "\"");
+
+ m_view.setHtml(page);
+
+ setAttribute(Qt::WA_InputMethodEnabled, imEnabled);
+ setInputMethodHints(hints);
+ }
+ void setMaxLength(int length)
+ {
+ m_length = length;
+ updatePage();
+ }
+ void setEchoMode(QLineEdit::EchoMode mode)
+ {
+ m_mode = mode;
+ updatePage();
+ }
+
+ int m_length;
+ QLineEdit::EchoMode m_mode;
+ QGraphicsScene m_scene;
+ QGraphicsWebView m_view;
+};
+#endif // QT_WEBKIT_LIB
+
+QTEST_MAIN(tst_QInputContext)
+#include "tst_qinputcontext.moc"
diff --git a/tests/auto/widgets/kernel/qlayout/.gitignore b/tests/auto/widgets/kernel/qlayout/.gitignore
new file mode 100644
index 0000000000..cc058e7cc3
--- /dev/null
+++ b/tests/auto/widgets/kernel/qlayout/.gitignore
@@ -0,0 +1 @@
+tst_qlayout
diff --git a/tests/auto/widgets/kernel/qlayout/baseline/smartmaxsize b/tests/auto/widgets/kernel/qlayout/baseline/smartmaxsize
new file mode 100644
index 0000000000..2d3ba2e72f
--- /dev/null
+++ b/tests/auto/widgets/kernel/qlayout/baseline/smartmaxsize
@@ -0,0 +1,1792 @@
+0 0 0 0 0 0 0
+1 0 1 0 0 0 524287
+2 0 2 0 0 0 524287
+3 0 4 0 0 0 524287
+4 0 0 0 10 0 0
+5 0 1 0 10 0 524287
+6 0 2 0 10 0 524287
+7 0 4 0 10 0 524287
+8 0 0 0 20 0 0
+9 0 1 0 20 0 524287
+10 0 2 0 20 0 524287
+11 0 4 0 20 0 524287
+12 0 0 0 16777215 0 0
+13 0 1 0 16777215 0 524287
+14 0 2 0 16777215 0 524287
+15 0 4 0 16777215 0 524287
+16 0 0 0 0 10 10
+17 0 1 0 0 10 524287
+18 0 2 0 0 10 524287
+19 0 4 0 0 10 524287
+20 0 0 0 10 10 10
+21 0 1 0 10 10 524287
+22 0 2 0 10 10 524287
+23 0 4 0 10 10 524287
+24 0 0 0 20 10 10
+25 0 1 0 20 10 524287
+26 0 2 0 20 10 524287
+27 0 4 0 20 10 524287
+28 0 0 0 16777215 10 10
+29 0 1 0 16777215 10 524287
+30 0 2 0 16777215 10 524287
+31 0 4 0 16777215 10 524287
+32 0 0 0 0 20 20
+33 0 1 0 0 20 524287
+34 0 2 0 0 20 524287
+35 0 4 0 0 20 524287
+36 0 0 0 10 20 20
+37 0 1 0 10 20 524287
+38 0 2 0 10 20 524287
+39 0 4 0 10 20 524287
+40 0 0 0 20 20 20
+41 0 1 0 20 20 524287
+42 0 2 0 20 20 524287
+43 0 4 0 20 20 524287
+44 0 0 0 16777215 20 20
+45 0 1 0 16777215 20 524287
+46 0 2 0 16777215 20 524287
+47 0 4 0 16777215 20 524287
+48 0 0 0 0 16777215 0
+49 0 1 0 0 16777215 524287
+50 0 2 0 0 16777215 524287
+51 0 4 0 0 16777215 524287
+52 0 0 0 10 16777215 10
+53 0 1 0 10 16777215 524287
+54 0 2 0 10 16777215 524287
+55 0 4 0 10 16777215 524287
+56 0 0 0 20 16777215 20
+57 0 1 0 20 16777215 524287
+58 0 2 0 20 16777215 524287
+59 0 4 0 20 16777215 524287
+60 0 0 0 16777215 16777215 16777215
+61 0 1 0 16777215 16777215 524287
+62 0 2 0 16777215 16777215 524287
+63 0 4 0 16777215 16777215 524287
+64 0 0 10 0 0 0
+65 0 1 10 0 0 524287
+66 0 2 10 0 0 524287
+67 0 4 10 0 0 524287
+68 0 0 10 10 0 0
+69 0 1 10 10 0 524287
+70 0 2 10 10 0 524287
+71 0 4 10 10 0 524287
+72 0 0 10 20 0 0
+73 0 1 10 20 0 524287
+74 0 2 10 20 0 524287
+75 0 4 10 20 0 524287
+76 0 0 10 16777215 0 0
+77 0 1 10 16777215 0 524287
+78 0 2 10 16777215 0 524287
+79 0 4 10 16777215 0 524287
+80 0 0 10 0 10 10
+81 0 1 10 0 10 524287
+82 0 2 10 0 10 524287
+83 0 4 10 0 10 524287
+84 0 0 10 10 10 10
+85 0 1 10 10 10 524287
+86 0 2 10 10 10 524287
+87 0 4 10 10 10 524287
+88 0 0 10 20 10 10
+89 0 1 10 20 10 524287
+90 0 2 10 20 10 524287
+91 0 4 10 20 10 524287
+92 0 0 10 16777215 10 10
+93 0 1 10 16777215 10 524287
+94 0 2 10 16777215 10 524287
+95 0 4 10 16777215 10 524287
+96 0 0 10 0 20 20
+97 0 1 10 0 20 524287
+98 0 2 10 0 20 524287
+99 0 4 10 0 20 524287
+100 0 0 10 10 20 20
+101 0 1 10 10 20 524287
+102 0 2 10 10 20 524287
+103 0 4 10 10 20 524287
+104 0 0 10 20 20 20
+105 0 1 10 20 20 524287
+106 0 2 10 20 20 524287
+107 0 4 10 20 20 524287
+108 0 0 10 16777215 20 20
+109 0 1 10 16777215 20 524287
+110 0 2 10 16777215 20 524287
+111 0 4 10 16777215 20 524287
+112 0 0 10 0 16777215 10
+113 0 1 10 0 16777215 524287
+114 0 2 10 0 16777215 524287
+115 0 4 10 0 16777215 524287
+116 0 0 10 10 16777215 10
+117 0 1 10 10 16777215 524287
+118 0 2 10 10 16777215 524287
+119 0 4 10 10 16777215 524287
+120 0 0 10 20 16777215 20
+121 0 1 10 20 16777215 524287
+122 0 2 10 20 16777215 524287
+123 0 4 10 20 16777215 524287
+124 0 0 10 16777215 16777215 16777215
+125 0 1 10 16777215 16777215 524287
+126 0 2 10 16777215 16777215 524287
+127 0 4 10 16777215 16777215 524287
+128 0 0 20 0 0 0
+129 0 1 20 0 0 524287
+130 0 2 20 0 0 524287
+131 0 4 20 0 0 524287
+132 0 0 20 10 0 0
+133 0 1 20 10 0 524287
+134 0 2 20 10 0 524287
+135 0 4 20 10 0 524287
+136 0 0 20 20 0 0
+137 0 1 20 20 0 524287
+138 0 2 20 20 0 524287
+139 0 4 20 20 0 524287
+140 0 0 20 16777215 0 0
+141 0 1 20 16777215 0 524287
+142 0 2 20 16777215 0 524287
+143 0 4 20 16777215 0 524287
+144 0 0 20 0 10 10
+145 0 1 20 0 10 524287
+146 0 2 20 0 10 524287
+147 0 4 20 0 10 524287
+148 0 0 20 10 10 10
+149 0 1 20 10 10 524287
+150 0 2 20 10 10 524287
+151 0 4 20 10 10 524287
+152 0 0 20 20 10 10
+153 0 1 20 20 10 524287
+154 0 2 20 20 10 524287
+155 0 4 20 20 10 524287
+156 0 0 20 16777215 10 10
+157 0 1 20 16777215 10 524287
+158 0 2 20 16777215 10 524287
+159 0 4 20 16777215 10 524287
+160 0 0 20 0 20 20
+161 0 1 20 0 20 524287
+162 0 2 20 0 20 524287
+163 0 4 20 0 20 524287
+164 0 0 20 10 20 20
+165 0 1 20 10 20 524287
+166 0 2 20 10 20 524287
+167 0 4 20 10 20 524287
+168 0 0 20 20 20 20
+169 0 1 20 20 20 524287
+170 0 2 20 20 20 524287
+171 0 4 20 20 20 524287
+172 0 0 20 16777215 20 20
+173 0 1 20 16777215 20 524287
+174 0 2 20 16777215 20 524287
+175 0 4 20 16777215 20 524287
+176 0 0 20 0 16777215 20
+177 0 1 20 0 16777215 524287
+178 0 2 20 0 16777215 524287
+179 0 4 20 0 16777215 524287
+180 0 0 20 10 16777215 20
+181 0 1 20 10 16777215 524287
+182 0 2 20 10 16777215 524287
+183 0 4 20 10 16777215 524287
+184 0 0 20 20 16777215 20
+185 0 1 20 20 16777215 524287
+186 0 2 20 20 16777215 524287
+187 0 4 20 20 16777215 524287
+188 0 0 20 16777215 16777215 16777215
+189 0 1 20 16777215 16777215 524287
+190 0 2 20 16777215 16777215 524287
+191 0 4 20 16777215 16777215 524287
+192 0 0 16777215 0 0 0
+193 0 1 16777215 0 0 524287
+194 0 2 16777215 0 0 524287
+195 0 4 16777215 0 0 524287
+196 0 0 16777215 10 0 0
+197 0 1 16777215 10 0 524287
+198 0 2 16777215 10 0 524287
+199 0 4 16777215 10 0 524287
+200 0 0 16777215 20 0 0
+201 0 1 16777215 20 0 524287
+202 0 2 16777215 20 0 524287
+203 0 4 16777215 20 0 524287
+204 0 0 16777215 16777215 0 0
+205 0 1 16777215 16777215 0 524287
+206 0 2 16777215 16777215 0 524287
+207 0 4 16777215 16777215 0 524287
+208 0 0 16777215 0 10 10
+209 0 1 16777215 0 10 524287
+210 0 2 16777215 0 10 524287
+211 0 4 16777215 0 10 524287
+212 0 0 16777215 10 10 10
+213 0 1 16777215 10 10 524287
+214 0 2 16777215 10 10 524287
+215 0 4 16777215 10 10 524287
+216 0 0 16777215 20 10 10
+217 0 1 16777215 20 10 524287
+218 0 2 16777215 20 10 524287
+219 0 4 16777215 20 10 524287
+220 0 0 16777215 16777215 10 10
+221 0 1 16777215 16777215 10 524287
+222 0 2 16777215 16777215 10 524287
+223 0 4 16777215 16777215 10 524287
+224 0 0 16777215 0 20 20
+225 0 1 16777215 0 20 524287
+226 0 2 16777215 0 20 524287
+227 0 4 16777215 0 20 524287
+228 0 0 16777215 10 20 20
+229 0 1 16777215 10 20 524287
+230 0 2 16777215 10 20 524287
+231 0 4 16777215 10 20 524287
+232 0 0 16777215 20 20 20
+233 0 1 16777215 20 20 524287
+234 0 2 16777215 20 20 524287
+235 0 4 16777215 20 20 524287
+236 0 0 16777215 16777215 20 20
+237 0 1 16777215 16777215 20 524287
+238 0 2 16777215 16777215 20 524287
+239 0 4 16777215 16777215 20 524287
+240 0 0 16777215 0 16777215 16777215
+241 0 1 16777215 0 16777215 524287
+242 0 2 16777215 0 16777215 524287
+243 0 4 16777215 0 16777215 524287
+244 0 0 16777215 10 16777215 16777215
+245 0 1 16777215 10 16777215 524287
+246 0 2 16777215 10 16777215 524287
+247 0 4 16777215 10 16777215 524287
+248 0 0 16777215 20 16777215 16777215
+249 0 1 16777215 20 16777215 524287
+250 0 2 16777215 20 16777215 524287
+251 0 4 16777215 20 16777215 524287
+252 0 0 16777215 16777215 16777215 16777215
+253 0 1 16777215 16777215 16777215 524287
+254 0 2 16777215 16777215 16777215 524287
+255 0 4 16777215 16777215 16777215 524287
+256 1 0 0 0 0 0
+257 1 1 0 0 0 524287
+258 1 2 0 0 0 524287
+259 1 4 0 0 0 524287
+260 1 0 0 10 0 0
+261 1 1 0 10 0 524287
+262 1 2 0 10 0 524287
+263 1 4 0 10 0 524287
+264 1 0 0 20 0 0
+265 1 1 0 20 0 524287
+266 1 2 0 20 0 524287
+267 1 4 0 20 0 524287
+268 1 0 0 16777215 0 0
+269 1 1 0 16777215 0 524287
+270 1 2 0 16777215 0 524287
+271 1 4 0 16777215 0 524287
+272 1 0 0 0 10 10
+273 1 1 0 0 10 524287
+274 1 2 0 0 10 524287
+275 1 4 0 0 10 524287
+276 1 0 0 10 10 10
+277 1 1 0 10 10 524287
+278 1 2 0 10 10 524287
+279 1 4 0 10 10 524287
+280 1 0 0 20 10 10
+281 1 1 0 20 10 524287
+282 1 2 0 20 10 524287
+283 1 4 0 20 10 524287
+284 1 0 0 16777215 10 10
+285 1 1 0 16777215 10 524287
+286 1 2 0 16777215 10 524287
+287 1 4 0 16777215 10 524287
+288 1 0 0 0 20 20
+289 1 1 0 0 20 524287
+290 1 2 0 0 20 524287
+291 1 4 0 0 20 524287
+292 1 0 0 10 20 20
+293 1 1 0 10 20 524287
+294 1 2 0 10 20 524287
+295 1 4 0 10 20 524287
+296 1 0 0 20 20 20
+297 1 1 0 20 20 524287
+298 1 2 0 20 20 524287
+299 1 4 0 20 20 524287
+300 1 0 0 16777215 20 20
+301 1 1 0 16777215 20 524287
+302 1 2 0 16777215 20 524287
+303 1 4 0 16777215 20 524287
+304 1 0 0 0 16777215 16777215
+305 1 1 0 0 16777215 524287
+306 1 2 0 0 16777215 524287
+307 1 4 0 0 16777215 524287
+308 1 0 0 10 16777215 16777215
+309 1 1 0 10 16777215 524287
+310 1 2 0 10 16777215 524287
+311 1 4 0 10 16777215 524287
+312 1 0 0 20 16777215 16777215
+313 1 1 0 20 16777215 524287
+314 1 2 0 20 16777215 524287
+315 1 4 0 20 16777215 524287
+316 1 0 0 16777215 16777215 16777215
+317 1 1 0 16777215 16777215 524287
+318 1 2 0 16777215 16777215 524287
+319 1 4 0 16777215 16777215 524287
+320 1 0 10 0 0 0
+321 1 1 10 0 0 524287
+322 1 2 10 0 0 524287
+323 1 4 10 0 0 524287
+324 1 0 10 10 0 0
+325 1 1 10 10 0 524287
+326 1 2 10 10 0 524287
+327 1 4 10 10 0 524287
+328 1 0 10 20 0 0
+329 1 1 10 20 0 524287
+330 1 2 10 20 0 524287
+331 1 4 10 20 0 524287
+332 1 0 10 16777215 0 0
+333 1 1 10 16777215 0 524287
+334 1 2 10 16777215 0 524287
+335 1 4 10 16777215 0 524287
+336 1 0 10 0 10 10
+337 1 1 10 0 10 524287
+338 1 2 10 0 10 524287
+339 1 4 10 0 10 524287
+340 1 0 10 10 10 10
+341 1 1 10 10 10 524287
+342 1 2 10 10 10 524287
+343 1 4 10 10 10 524287
+344 1 0 10 20 10 10
+345 1 1 10 20 10 524287
+346 1 2 10 20 10 524287
+347 1 4 10 20 10 524287
+348 1 0 10 16777215 10 10
+349 1 1 10 16777215 10 524287
+350 1 2 10 16777215 10 524287
+351 1 4 10 16777215 10 524287
+352 1 0 10 0 20 20
+353 1 1 10 0 20 524287
+354 1 2 10 0 20 524287
+355 1 4 10 0 20 524287
+356 1 0 10 10 20 20
+357 1 1 10 10 20 524287
+358 1 2 10 10 20 524287
+359 1 4 10 10 20 524287
+360 1 0 10 20 20 20
+361 1 1 10 20 20 524287
+362 1 2 10 20 20 524287
+363 1 4 10 20 20 524287
+364 1 0 10 16777215 20 20
+365 1 1 10 16777215 20 524287
+366 1 2 10 16777215 20 524287
+367 1 4 10 16777215 20 524287
+368 1 0 10 0 16777215 16777215
+369 1 1 10 0 16777215 524287
+370 1 2 10 0 16777215 524287
+371 1 4 10 0 16777215 524287
+372 1 0 10 10 16777215 16777215
+373 1 1 10 10 16777215 524287
+374 1 2 10 10 16777215 524287
+375 1 4 10 10 16777215 524287
+376 1 0 10 20 16777215 16777215
+377 1 1 10 20 16777215 524287
+378 1 2 10 20 16777215 524287
+379 1 4 10 20 16777215 524287
+380 1 0 10 16777215 16777215 16777215
+381 1 1 10 16777215 16777215 524287
+382 1 2 10 16777215 16777215 524287
+383 1 4 10 16777215 16777215 524287
+384 1 0 20 0 0 0
+385 1 1 20 0 0 524287
+386 1 2 20 0 0 524287
+387 1 4 20 0 0 524287
+388 1 0 20 10 0 0
+389 1 1 20 10 0 524287
+390 1 2 20 10 0 524287
+391 1 4 20 10 0 524287
+392 1 0 20 20 0 0
+393 1 1 20 20 0 524287
+394 1 2 20 20 0 524287
+395 1 4 20 20 0 524287
+396 1 0 20 16777215 0 0
+397 1 1 20 16777215 0 524287
+398 1 2 20 16777215 0 524287
+399 1 4 20 16777215 0 524287
+400 1 0 20 0 10 10
+401 1 1 20 0 10 524287
+402 1 2 20 0 10 524287
+403 1 4 20 0 10 524287
+404 1 0 20 10 10 10
+405 1 1 20 10 10 524287
+406 1 2 20 10 10 524287
+407 1 4 20 10 10 524287
+408 1 0 20 20 10 10
+409 1 1 20 20 10 524287
+410 1 2 20 20 10 524287
+411 1 4 20 20 10 524287
+412 1 0 20 16777215 10 10
+413 1 1 20 16777215 10 524287
+414 1 2 20 16777215 10 524287
+415 1 4 20 16777215 10 524287
+416 1 0 20 0 20 20
+417 1 1 20 0 20 524287
+418 1 2 20 0 20 524287
+419 1 4 20 0 20 524287
+420 1 0 20 10 20 20
+421 1 1 20 10 20 524287
+422 1 2 20 10 20 524287
+423 1 4 20 10 20 524287
+424 1 0 20 20 20 20
+425 1 1 20 20 20 524287
+426 1 2 20 20 20 524287
+427 1 4 20 20 20 524287
+428 1 0 20 16777215 20 20
+429 1 1 20 16777215 20 524287
+430 1 2 20 16777215 20 524287
+431 1 4 20 16777215 20 524287
+432 1 0 20 0 16777215 16777215
+433 1 1 20 0 16777215 524287
+434 1 2 20 0 16777215 524287
+435 1 4 20 0 16777215 524287
+436 1 0 20 10 16777215 16777215
+437 1 1 20 10 16777215 524287
+438 1 2 20 10 16777215 524287
+439 1 4 20 10 16777215 524287
+440 1 0 20 20 16777215 16777215
+441 1 1 20 20 16777215 524287
+442 1 2 20 20 16777215 524287
+443 1 4 20 20 16777215 524287
+444 1 0 20 16777215 16777215 16777215
+445 1 1 20 16777215 16777215 524287
+446 1 2 20 16777215 16777215 524287
+447 1 4 20 16777215 16777215 524287
+448 1 0 16777215 0 0 0
+449 1 1 16777215 0 0 524287
+450 1 2 16777215 0 0 524287
+451 1 4 16777215 0 0 524287
+452 1 0 16777215 10 0 0
+453 1 1 16777215 10 0 524287
+454 1 2 16777215 10 0 524287
+455 1 4 16777215 10 0 524287
+456 1 0 16777215 20 0 0
+457 1 1 16777215 20 0 524287
+458 1 2 16777215 20 0 524287
+459 1 4 16777215 20 0 524287
+460 1 0 16777215 16777215 0 0
+461 1 1 16777215 16777215 0 524287
+462 1 2 16777215 16777215 0 524287
+463 1 4 16777215 16777215 0 524287
+464 1 0 16777215 0 10 10
+465 1 1 16777215 0 10 524287
+466 1 2 16777215 0 10 524287
+467 1 4 16777215 0 10 524287
+468 1 0 16777215 10 10 10
+469 1 1 16777215 10 10 524287
+470 1 2 16777215 10 10 524287
+471 1 4 16777215 10 10 524287
+472 1 0 16777215 20 10 10
+473 1 1 16777215 20 10 524287
+474 1 2 16777215 20 10 524287
+475 1 4 16777215 20 10 524287
+476 1 0 16777215 16777215 10 10
+477 1 1 16777215 16777215 10 524287
+478 1 2 16777215 16777215 10 524287
+479 1 4 16777215 16777215 10 524287
+480 1 0 16777215 0 20 20
+481 1 1 16777215 0 20 524287
+482 1 2 16777215 0 20 524287
+483 1 4 16777215 0 20 524287
+484 1 0 16777215 10 20 20
+485 1 1 16777215 10 20 524287
+486 1 2 16777215 10 20 524287
+487 1 4 16777215 10 20 524287
+488 1 0 16777215 20 20 20
+489 1 1 16777215 20 20 524287
+490 1 2 16777215 20 20 524287
+491 1 4 16777215 20 20 524287
+492 1 0 16777215 16777215 20 20
+493 1 1 16777215 16777215 20 524287
+494 1 2 16777215 16777215 20 524287
+495 1 4 16777215 16777215 20 524287
+496 1 0 16777215 0 16777215 16777215
+497 1 1 16777215 0 16777215 524287
+498 1 2 16777215 0 16777215 524287
+499 1 4 16777215 0 16777215 524287
+500 1 0 16777215 10 16777215 16777215
+501 1 1 16777215 10 16777215 524287
+502 1 2 16777215 10 16777215 524287
+503 1 4 16777215 10 16777215 524287
+504 1 0 16777215 20 16777215 16777215
+505 1 1 16777215 20 16777215 524287
+506 1 2 16777215 20 16777215 524287
+507 1 4 16777215 20 16777215 524287
+508 1 0 16777215 16777215 16777215 16777215
+509 1 1 16777215 16777215 16777215 524287
+510 1 2 16777215 16777215 16777215 524287
+511 1 4 16777215 16777215 16777215 524287
+512 4 0 0 0 0 0
+513 4 1 0 0 0 524287
+514 4 2 0 0 0 524287
+515 4 4 0 0 0 524287
+516 4 0 0 10 0 0
+517 4 1 0 10 0 524287
+518 4 2 0 10 0 524287
+519 4 4 0 10 0 524287
+520 4 0 0 20 0 0
+521 4 1 0 20 0 524287
+522 4 2 0 20 0 524287
+523 4 4 0 20 0 524287
+524 4 0 0 16777215 0 0
+525 4 1 0 16777215 0 524287
+526 4 2 0 16777215 0 524287
+527 4 4 0 16777215 0 524287
+528 4 0 0 0 10 10
+529 4 1 0 0 10 524287
+530 4 2 0 0 10 524287
+531 4 4 0 0 10 524287
+532 4 0 0 10 10 10
+533 4 1 0 10 10 524287
+534 4 2 0 10 10 524287
+535 4 4 0 10 10 524287
+536 4 0 0 20 10 10
+537 4 1 0 20 10 524287
+538 4 2 0 20 10 524287
+539 4 4 0 20 10 524287
+540 4 0 0 16777215 10 10
+541 4 1 0 16777215 10 524287
+542 4 2 0 16777215 10 524287
+543 4 4 0 16777215 10 524287
+544 4 0 0 0 20 20
+545 4 1 0 0 20 524287
+546 4 2 0 0 20 524287
+547 4 4 0 0 20 524287
+548 4 0 0 10 20 20
+549 4 1 0 10 20 524287
+550 4 2 0 10 20 524287
+551 4 4 0 10 20 524287
+552 4 0 0 20 20 20
+553 4 1 0 20 20 524287
+554 4 2 0 20 20 524287
+555 4 4 0 20 20 524287
+556 4 0 0 16777215 20 20
+557 4 1 0 16777215 20 524287
+558 4 2 0 16777215 20 524287
+559 4 4 0 16777215 20 524287
+560 4 0 0 0 16777215 0
+561 4 1 0 0 16777215 524287
+562 4 2 0 0 16777215 524287
+563 4 4 0 0 16777215 524287
+564 4 0 0 10 16777215 10
+565 4 1 0 10 16777215 524287
+566 4 2 0 10 16777215 524287
+567 4 4 0 10 16777215 524287
+568 4 0 0 20 16777215 20
+569 4 1 0 20 16777215 524287
+570 4 2 0 20 16777215 524287
+571 4 4 0 20 16777215 524287
+572 4 0 0 16777215 16777215 16777215
+573 4 1 0 16777215 16777215 524287
+574 4 2 0 16777215 16777215 524287
+575 4 4 0 16777215 16777215 524287
+576 4 0 10 0 0 0
+577 4 1 10 0 0 524287
+578 4 2 10 0 0 524287
+579 4 4 10 0 0 524287
+580 4 0 10 10 0 0
+581 4 1 10 10 0 524287
+582 4 2 10 10 0 524287
+583 4 4 10 10 0 524287
+584 4 0 10 20 0 0
+585 4 1 10 20 0 524287
+586 4 2 10 20 0 524287
+587 4 4 10 20 0 524287
+588 4 0 10 16777215 0 0
+589 4 1 10 16777215 0 524287
+590 4 2 10 16777215 0 524287
+591 4 4 10 16777215 0 524287
+592 4 0 10 0 10 10
+593 4 1 10 0 10 524287
+594 4 2 10 0 10 524287
+595 4 4 10 0 10 524287
+596 4 0 10 10 10 10
+597 4 1 10 10 10 524287
+598 4 2 10 10 10 524287
+599 4 4 10 10 10 524287
+600 4 0 10 20 10 10
+601 4 1 10 20 10 524287
+602 4 2 10 20 10 524287
+603 4 4 10 20 10 524287
+604 4 0 10 16777215 10 10
+605 4 1 10 16777215 10 524287
+606 4 2 10 16777215 10 524287
+607 4 4 10 16777215 10 524287
+608 4 0 10 0 20 20
+609 4 1 10 0 20 524287
+610 4 2 10 0 20 524287
+611 4 4 10 0 20 524287
+612 4 0 10 10 20 20
+613 4 1 10 10 20 524287
+614 4 2 10 10 20 524287
+615 4 4 10 10 20 524287
+616 4 0 10 20 20 20
+617 4 1 10 20 20 524287
+618 4 2 10 20 20 524287
+619 4 4 10 20 20 524287
+620 4 0 10 16777215 20 20
+621 4 1 10 16777215 20 524287
+622 4 2 10 16777215 20 524287
+623 4 4 10 16777215 20 524287
+624 4 0 10 0 16777215 10
+625 4 1 10 0 16777215 524287
+626 4 2 10 0 16777215 524287
+627 4 4 10 0 16777215 524287
+628 4 0 10 10 16777215 10
+629 4 1 10 10 16777215 524287
+630 4 2 10 10 16777215 524287
+631 4 4 10 10 16777215 524287
+632 4 0 10 20 16777215 20
+633 4 1 10 20 16777215 524287
+634 4 2 10 20 16777215 524287
+635 4 4 10 20 16777215 524287
+636 4 0 10 16777215 16777215 16777215
+637 4 1 10 16777215 16777215 524287
+638 4 2 10 16777215 16777215 524287
+639 4 4 10 16777215 16777215 524287
+640 4 0 20 0 0 0
+641 4 1 20 0 0 524287
+642 4 2 20 0 0 524287
+643 4 4 20 0 0 524287
+644 4 0 20 10 0 0
+645 4 1 20 10 0 524287
+646 4 2 20 10 0 524287
+647 4 4 20 10 0 524287
+648 4 0 20 20 0 0
+649 4 1 20 20 0 524287
+650 4 2 20 20 0 524287
+651 4 4 20 20 0 524287
+652 4 0 20 16777215 0 0
+653 4 1 20 16777215 0 524287
+654 4 2 20 16777215 0 524287
+655 4 4 20 16777215 0 524287
+656 4 0 20 0 10 10
+657 4 1 20 0 10 524287
+658 4 2 20 0 10 524287
+659 4 4 20 0 10 524287
+660 4 0 20 10 10 10
+661 4 1 20 10 10 524287
+662 4 2 20 10 10 524287
+663 4 4 20 10 10 524287
+664 4 0 20 20 10 10
+665 4 1 20 20 10 524287
+666 4 2 20 20 10 524287
+667 4 4 20 20 10 524287
+668 4 0 20 16777215 10 10
+669 4 1 20 16777215 10 524287
+670 4 2 20 16777215 10 524287
+671 4 4 20 16777215 10 524287
+672 4 0 20 0 20 20
+673 4 1 20 0 20 524287
+674 4 2 20 0 20 524287
+675 4 4 20 0 20 524287
+676 4 0 20 10 20 20
+677 4 1 20 10 20 524287
+678 4 2 20 10 20 524287
+679 4 4 20 10 20 524287
+680 4 0 20 20 20 20
+681 4 1 20 20 20 524287
+682 4 2 20 20 20 524287
+683 4 4 20 20 20 524287
+684 4 0 20 16777215 20 20
+685 4 1 20 16777215 20 524287
+686 4 2 20 16777215 20 524287
+687 4 4 20 16777215 20 524287
+688 4 0 20 0 16777215 20
+689 4 1 20 0 16777215 524287
+690 4 2 20 0 16777215 524287
+691 4 4 20 0 16777215 524287
+692 4 0 20 10 16777215 20
+693 4 1 20 10 16777215 524287
+694 4 2 20 10 16777215 524287
+695 4 4 20 10 16777215 524287
+696 4 0 20 20 16777215 20
+697 4 1 20 20 16777215 524287
+698 4 2 20 20 16777215 524287
+699 4 4 20 20 16777215 524287
+700 4 0 20 16777215 16777215 16777215
+701 4 1 20 16777215 16777215 524287
+702 4 2 20 16777215 16777215 524287
+703 4 4 20 16777215 16777215 524287
+704 4 0 16777215 0 0 0
+705 4 1 16777215 0 0 524287
+706 4 2 16777215 0 0 524287
+707 4 4 16777215 0 0 524287
+708 4 0 16777215 10 0 0
+709 4 1 16777215 10 0 524287
+710 4 2 16777215 10 0 524287
+711 4 4 16777215 10 0 524287
+712 4 0 16777215 20 0 0
+713 4 1 16777215 20 0 524287
+714 4 2 16777215 20 0 524287
+715 4 4 16777215 20 0 524287
+716 4 0 16777215 16777215 0 0
+717 4 1 16777215 16777215 0 524287
+718 4 2 16777215 16777215 0 524287
+719 4 4 16777215 16777215 0 524287
+720 4 0 16777215 0 10 10
+721 4 1 16777215 0 10 524287
+722 4 2 16777215 0 10 524287
+723 4 4 16777215 0 10 524287
+724 4 0 16777215 10 10 10
+725 4 1 16777215 10 10 524287
+726 4 2 16777215 10 10 524287
+727 4 4 16777215 10 10 524287
+728 4 0 16777215 20 10 10
+729 4 1 16777215 20 10 524287
+730 4 2 16777215 20 10 524287
+731 4 4 16777215 20 10 524287
+732 4 0 16777215 16777215 10 10
+733 4 1 16777215 16777215 10 524287
+734 4 2 16777215 16777215 10 524287
+735 4 4 16777215 16777215 10 524287
+736 4 0 16777215 0 20 20
+737 4 1 16777215 0 20 524287
+738 4 2 16777215 0 20 524287
+739 4 4 16777215 0 20 524287
+740 4 0 16777215 10 20 20
+741 4 1 16777215 10 20 524287
+742 4 2 16777215 10 20 524287
+743 4 4 16777215 10 20 524287
+744 4 0 16777215 20 20 20
+745 4 1 16777215 20 20 524287
+746 4 2 16777215 20 20 524287
+747 4 4 16777215 20 20 524287
+748 4 0 16777215 16777215 20 20
+749 4 1 16777215 16777215 20 524287
+750 4 2 16777215 16777215 20 524287
+751 4 4 16777215 16777215 20 524287
+752 4 0 16777215 0 16777215 16777215
+753 4 1 16777215 0 16777215 524287
+754 4 2 16777215 0 16777215 524287
+755 4 4 16777215 0 16777215 524287
+756 4 0 16777215 10 16777215 16777215
+757 4 1 16777215 10 16777215 524287
+758 4 2 16777215 10 16777215 524287
+759 4 4 16777215 10 16777215 524287
+760 4 0 16777215 20 16777215 16777215
+761 4 1 16777215 20 16777215 524287
+762 4 2 16777215 20 16777215 524287
+763 4 4 16777215 20 16777215 524287
+764 4 0 16777215 16777215 16777215 16777215
+765 4 1 16777215 16777215 16777215 524287
+766 4 2 16777215 16777215 16777215 524287
+767 4 4 16777215 16777215 16777215 524287
+768 5 0 0 0 0 0
+769 5 1 0 0 0 524287
+770 5 2 0 0 0 524287
+771 5 4 0 0 0 524287
+772 5 0 0 10 0 0
+773 5 1 0 10 0 524287
+774 5 2 0 10 0 524287
+775 5 4 0 10 0 524287
+776 5 0 0 20 0 0
+777 5 1 0 20 0 524287
+778 5 2 0 20 0 524287
+779 5 4 0 20 0 524287
+780 5 0 0 16777215 0 0
+781 5 1 0 16777215 0 524287
+782 5 2 0 16777215 0 524287
+783 5 4 0 16777215 0 524287
+784 5 0 0 0 10 10
+785 5 1 0 0 10 524287
+786 5 2 0 0 10 524287
+787 5 4 0 0 10 524287
+788 5 0 0 10 10 10
+789 5 1 0 10 10 524287
+790 5 2 0 10 10 524287
+791 5 4 0 10 10 524287
+792 5 0 0 20 10 10
+793 5 1 0 20 10 524287
+794 5 2 0 20 10 524287
+795 5 4 0 20 10 524287
+796 5 0 0 16777215 10 10
+797 5 1 0 16777215 10 524287
+798 5 2 0 16777215 10 524287
+799 5 4 0 16777215 10 524287
+800 5 0 0 0 20 20
+801 5 1 0 0 20 524287
+802 5 2 0 0 20 524287
+803 5 4 0 0 20 524287
+804 5 0 0 10 20 20
+805 5 1 0 10 20 524287
+806 5 2 0 10 20 524287
+807 5 4 0 10 20 524287
+808 5 0 0 20 20 20
+809 5 1 0 20 20 524287
+810 5 2 0 20 20 524287
+811 5 4 0 20 20 524287
+812 5 0 0 16777215 20 20
+813 5 1 0 16777215 20 524287
+814 5 2 0 16777215 20 524287
+815 5 4 0 16777215 20 524287
+816 5 0 0 0 16777215 16777215
+817 5 1 0 0 16777215 524287
+818 5 2 0 0 16777215 524287
+819 5 4 0 0 16777215 524287
+820 5 0 0 10 16777215 16777215
+821 5 1 0 10 16777215 524287
+822 5 2 0 10 16777215 524287
+823 5 4 0 10 16777215 524287
+824 5 0 0 20 16777215 16777215
+825 5 1 0 20 16777215 524287
+826 5 2 0 20 16777215 524287
+827 5 4 0 20 16777215 524287
+828 5 0 0 16777215 16777215 16777215
+829 5 1 0 16777215 16777215 524287
+830 5 2 0 16777215 16777215 524287
+831 5 4 0 16777215 16777215 524287
+832 5 0 10 0 0 0
+833 5 1 10 0 0 524287
+834 5 2 10 0 0 524287
+835 5 4 10 0 0 524287
+836 5 0 10 10 0 0
+837 5 1 10 10 0 524287
+838 5 2 10 10 0 524287
+839 5 4 10 10 0 524287
+840 5 0 10 20 0 0
+841 5 1 10 20 0 524287
+842 5 2 10 20 0 524287
+843 5 4 10 20 0 524287
+844 5 0 10 16777215 0 0
+845 5 1 10 16777215 0 524287
+846 5 2 10 16777215 0 524287
+847 5 4 10 16777215 0 524287
+848 5 0 10 0 10 10
+849 5 1 10 0 10 524287
+850 5 2 10 0 10 524287
+851 5 4 10 0 10 524287
+852 5 0 10 10 10 10
+853 5 1 10 10 10 524287
+854 5 2 10 10 10 524287
+855 5 4 10 10 10 524287
+856 5 0 10 20 10 10
+857 5 1 10 20 10 524287
+858 5 2 10 20 10 524287
+859 5 4 10 20 10 524287
+860 5 0 10 16777215 10 10
+861 5 1 10 16777215 10 524287
+862 5 2 10 16777215 10 524287
+863 5 4 10 16777215 10 524287
+864 5 0 10 0 20 20
+865 5 1 10 0 20 524287
+866 5 2 10 0 20 524287
+867 5 4 10 0 20 524287
+868 5 0 10 10 20 20
+869 5 1 10 10 20 524287
+870 5 2 10 10 20 524287
+871 5 4 10 10 20 524287
+872 5 0 10 20 20 20
+873 5 1 10 20 20 524287
+874 5 2 10 20 20 524287
+875 5 4 10 20 20 524287
+876 5 0 10 16777215 20 20
+877 5 1 10 16777215 20 524287
+878 5 2 10 16777215 20 524287
+879 5 4 10 16777215 20 524287
+880 5 0 10 0 16777215 16777215
+881 5 1 10 0 16777215 524287
+882 5 2 10 0 16777215 524287
+883 5 4 10 0 16777215 524287
+884 5 0 10 10 16777215 16777215
+885 5 1 10 10 16777215 524287
+886 5 2 10 10 16777215 524287
+887 5 4 10 10 16777215 524287
+888 5 0 10 20 16777215 16777215
+889 5 1 10 20 16777215 524287
+890 5 2 10 20 16777215 524287
+891 5 4 10 20 16777215 524287
+892 5 0 10 16777215 16777215 16777215
+893 5 1 10 16777215 16777215 524287
+894 5 2 10 16777215 16777215 524287
+895 5 4 10 16777215 16777215 524287
+896 5 0 20 0 0 0
+897 5 1 20 0 0 524287
+898 5 2 20 0 0 524287
+899 5 4 20 0 0 524287
+900 5 0 20 10 0 0
+901 5 1 20 10 0 524287
+902 5 2 20 10 0 524287
+903 5 4 20 10 0 524287
+904 5 0 20 20 0 0
+905 5 1 20 20 0 524287
+906 5 2 20 20 0 524287
+907 5 4 20 20 0 524287
+908 5 0 20 16777215 0 0
+909 5 1 20 16777215 0 524287
+910 5 2 20 16777215 0 524287
+911 5 4 20 16777215 0 524287
+912 5 0 20 0 10 10
+913 5 1 20 0 10 524287
+914 5 2 20 0 10 524287
+915 5 4 20 0 10 524287
+916 5 0 20 10 10 10
+917 5 1 20 10 10 524287
+918 5 2 20 10 10 524287
+919 5 4 20 10 10 524287
+920 5 0 20 20 10 10
+921 5 1 20 20 10 524287
+922 5 2 20 20 10 524287
+923 5 4 20 20 10 524287
+924 5 0 20 16777215 10 10
+925 5 1 20 16777215 10 524287
+926 5 2 20 16777215 10 524287
+927 5 4 20 16777215 10 524287
+928 5 0 20 0 20 20
+929 5 1 20 0 20 524287
+930 5 2 20 0 20 524287
+931 5 4 20 0 20 524287
+932 5 0 20 10 20 20
+933 5 1 20 10 20 524287
+934 5 2 20 10 20 524287
+935 5 4 20 10 20 524287
+936 5 0 20 20 20 20
+937 5 1 20 20 20 524287
+938 5 2 20 20 20 524287
+939 5 4 20 20 20 524287
+940 5 0 20 16777215 20 20
+941 5 1 20 16777215 20 524287
+942 5 2 20 16777215 20 524287
+943 5 4 20 16777215 20 524287
+944 5 0 20 0 16777215 16777215
+945 5 1 20 0 16777215 524287
+946 5 2 20 0 16777215 524287
+947 5 4 20 0 16777215 524287
+948 5 0 20 10 16777215 16777215
+949 5 1 20 10 16777215 524287
+950 5 2 20 10 16777215 524287
+951 5 4 20 10 16777215 524287
+952 5 0 20 20 16777215 16777215
+953 5 1 20 20 16777215 524287
+954 5 2 20 20 16777215 524287
+955 5 4 20 20 16777215 524287
+956 5 0 20 16777215 16777215 16777215
+957 5 1 20 16777215 16777215 524287
+958 5 2 20 16777215 16777215 524287
+959 5 4 20 16777215 16777215 524287
+960 5 0 16777215 0 0 0
+961 5 1 16777215 0 0 524287
+962 5 2 16777215 0 0 524287
+963 5 4 16777215 0 0 524287
+964 5 0 16777215 10 0 0
+965 5 1 16777215 10 0 524287
+966 5 2 16777215 10 0 524287
+967 5 4 16777215 10 0 524287
+968 5 0 16777215 20 0 0
+969 5 1 16777215 20 0 524287
+970 5 2 16777215 20 0 524287
+971 5 4 16777215 20 0 524287
+972 5 0 16777215 16777215 0 0
+973 5 1 16777215 16777215 0 524287
+974 5 2 16777215 16777215 0 524287
+975 5 4 16777215 16777215 0 524287
+976 5 0 16777215 0 10 10
+977 5 1 16777215 0 10 524287
+978 5 2 16777215 0 10 524287
+979 5 4 16777215 0 10 524287
+980 5 0 16777215 10 10 10
+981 5 1 16777215 10 10 524287
+982 5 2 16777215 10 10 524287
+983 5 4 16777215 10 10 524287
+984 5 0 16777215 20 10 10
+985 5 1 16777215 20 10 524287
+986 5 2 16777215 20 10 524287
+987 5 4 16777215 20 10 524287
+988 5 0 16777215 16777215 10 10
+989 5 1 16777215 16777215 10 524287
+990 5 2 16777215 16777215 10 524287
+991 5 4 16777215 16777215 10 524287
+992 5 0 16777215 0 20 20
+993 5 1 16777215 0 20 524287
+994 5 2 16777215 0 20 524287
+995 5 4 16777215 0 20 524287
+996 5 0 16777215 10 20 20
+997 5 1 16777215 10 20 524287
+998 5 2 16777215 10 20 524287
+999 5 4 16777215 10 20 524287
+1000 5 0 16777215 20 20 20
+1001 5 1 16777215 20 20 524287
+1002 5 2 16777215 20 20 524287
+1003 5 4 16777215 20 20 524287
+1004 5 0 16777215 16777215 20 20
+1005 5 1 16777215 16777215 20 524287
+1006 5 2 16777215 16777215 20 524287
+1007 5 4 16777215 16777215 20 524287
+1008 5 0 16777215 0 16777215 16777215
+1009 5 1 16777215 0 16777215 524287
+1010 5 2 16777215 0 16777215 524287
+1011 5 4 16777215 0 16777215 524287
+1012 5 0 16777215 10 16777215 16777215
+1013 5 1 16777215 10 16777215 524287
+1014 5 2 16777215 10 16777215 524287
+1015 5 4 16777215 10 16777215 524287
+1016 5 0 16777215 20 16777215 16777215
+1017 5 1 16777215 20 16777215 524287
+1018 5 2 16777215 20 16777215 524287
+1019 5 4 16777215 20 16777215 524287
+1020 5 0 16777215 16777215 16777215 16777215
+1021 5 1 16777215 16777215 16777215 524287
+1022 5 2 16777215 16777215 16777215 524287
+1023 5 4 16777215 16777215 16777215 524287
+1024 7 0 0 0 0 0
+1025 7 1 0 0 0 524287
+1026 7 2 0 0 0 524287
+1027 7 4 0 0 0 524287
+1028 7 0 0 10 0 0
+1029 7 1 0 10 0 524287
+1030 7 2 0 10 0 524287
+1031 7 4 0 10 0 524287
+1032 7 0 0 20 0 0
+1033 7 1 0 20 0 524287
+1034 7 2 0 20 0 524287
+1035 7 4 0 20 0 524287
+1036 7 0 0 16777215 0 0
+1037 7 1 0 16777215 0 524287
+1038 7 2 0 16777215 0 524287
+1039 7 4 0 16777215 0 524287
+1040 7 0 0 0 10 10
+1041 7 1 0 0 10 524287
+1042 7 2 0 0 10 524287
+1043 7 4 0 0 10 524287
+1044 7 0 0 10 10 10
+1045 7 1 0 10 10 524287
+1046 7 2 0 10 10 524287
+1047 7 4 0 10 10 524287
+1048 7 0 0 20 10 10
+1049 7 1 0 20 10 524287
+1050 7 2 0 20 10 524287
+1051 7 4 0 20 10 524287
+1052 7 0 0 16777215 10 10
+1053 7 1 0 16777215 10 524287
+1054 7 2 0 16777215 10 524287
+1055 7 4 0 16777215 10 524287
+1056 7 0 0 0 20 20
+1057 7 1 0 0 20 524287
+1058 7 2 0 0 20 524287
+1059 7 4 0 0 20 524287
+1060 7 0 0 10 20 20
+1061 7 1 0 10 20 524287
+1062 7 2 0 10 20 524287
+1063 7 4 0 10 20 524287
+1064 7 0 0 20 20 20
+1065 7 1 0 20 20 524287
+1066 7 2 0 20 20 524287
+1067 7 4 0 20 20 524287
+1068 7 0 0 16777215 20 20
+1069 7 1 0 16777215 20 524287
+1070 7 2 0 16777215 20 524287
+1071 7 4 0 16777215 20 524287
+1072 7 0 0 0 16777215 16777215
+1073 7 1 0 0 16777215 524287
+1074 7 2 0 0 16777215 524287
+1075 7 4 0 0 16777215 524287
+1076 7 0 0 10 16777215 16777215
+1077 7 1 0 10 16777215 524287
+1078 7 2 0 10 16777215 524287
+1079 7 4 0 10 16777215 524287
+1080 7 0 0 20 16777215 16777215
+1081 7 1 0 20 16777215 524287
+1082 7 2 0 20 16777215 524287
+1083 7 4 0 20 16777215 524287
+1084 7 0 0 16777215 16777215 16777215
+1085 7 1 0 16777215 16777215 524287
+1086 7 2 0 16777215 16777215 524287
+1087 7 4 0 16777215 16777215 524287
+1088 7 0 10 0 0 0
+1089 7 1 10 0 0 524287
+1090 7 2 10 0 0 524287
+1091 7 4 10 0 0 524287
+1092 7 0 10 10 0 0
+1093 7 1 10 10 0 524287
+1094 7 2 10 10 0 524287
+1095 7 4 10 10 0 524287
+1096 7 0 10 20 0 0
+1097 7 1 10 20 0 524287
+1098 7 2 10 20 0 524287
+1099 7 4 10 20 0 524287
+1100 7 0 10 16777215 0 0
+1101 7 1 10 16777215 0 524287
+1102 7 2 10 16777215 0 524287
+1103 7 4 10 16777215 0 524287
+1104 7 0 10 0 10 10
+1105 7 1 10 0 10 524287
+1106 7 2 10 0 10 524287
+1107 7 4 10 0 10 524287
+1108 7 0 10 10 10 10
+1109 7 1 10 10 10 524287
+1110 7 2 10 10 10 524287
+1111 7 4 10 10 10 524287
+1112 7 0 10 20 10 10
+1113 7 1 10 20 10 524287
+1114 7 2 10 20 10 524287
+1115 7 4 10 20 10 524287
+1116 7 0 10 16777215 10 10
+1117 7 1 10 16777215 10 524287
+1118 7 2 10 16777215 10 524287
+1119 7 4 10 16777215 10 524287
+1120 7 0 10 0 20 20
+1121 7 1 10 0 20 524287
+1122 7 2 10 0 20 524287
+1123 7 4 10 0 20 524287
+1124 7 0 10 10 20 20
+1125 7 1 10 10 20 524287
+1126 7 2 10 10 20 524287
+1127 7 4 10 10 20 524287
+1128 7 0 10 20 20 20
+1129 7 1 10 20 20 524287
+1130 7 2 10 20 20 524287
+1131 7 4 10 20 20 524287
+1132 7 0 10 16777215 20 20
+1133 7 1 10 16777215 20 524287
+1134 7 2 10 16777215 20 524287
+1135 7 4 10 16777215 20 524287
+1136 7 0 10 0 16777215 16777215
+1137 7 1 10 0 16777215 524287
+1138 7 2 10 0 16777215 524287
+1139 7 4 10 0 16777215 524287
+1140 7 0 10 10 16777215 16777215
+1141 7 1 10 10 16777215 524287
+1142 7 2 10 10 16777215 524287
+1143 7 4 10 10 16777215 524287
+1144 7 0 10 20 16777215 16777215
+1145 7 1 10 20 16777215 524287
+1146 7 2 10 20 16777215 524287
+1147 7 4 10 20 16777215 524287
+1148 7 0 10 16777215 16777215 16777215
+1149 7 1 10 16777215 16777215 524287
+1150 7 2 10 16777215 16777215 524287
+1151 7 4 10 16777215 16777215 524287
+1152 7 0 20 0 0 0
+1153 7 1 20 0 0 524287
+1154 7 2 20 0 0 524287
+1155 7 4 20 0 0 524287
+1156 7 0 20 10 0 0
+1157 7 1 20 10 0 524287
+1158 7 2 20 10 0 524287
+1159 7 4 20 10 0 524287
+1160 7 0 20 20 0 0
+1161 7 1 20 20 0 524287
+1162 7 2 20 20 0 524287
+1163 7 4 20 20 0 524287
+1164 7 0 20 16777215 0 0
+1165 7 1 20 16777215 0 524287
+1166 7 2 20 16777215 0 524287
+1167 7 4 20 16777215 0 524287
+1168 7 0 20 0 10 10
+1169 7 1 20 0 10 524287
+1170 7 2 20 0 10 524287
+1171 7 4 20 0 10 524287
+1172 7 0 20 10 10 10
+1173 7 1 20 10 10 524287
+1174 7 2 20 10 10 524287
+1175 7 4 20 10 10 524287
+1176 7 0 20 20 10 10
+1177 7 1 20 20 10 524287
+1178 7 2 20 20 10 524287
+1179 7 4 20 20 10 524287
+1180 7 0 20 16777215 10 10
+1181 7 1 20 16777215 10 524287
+1182 7 2 20 16777215 10 524287
+1183 7 4 20 16777215 10 524287
+1184 7 0 20 0 20 20
+1185 7 1 20 0 20 524287
+1186 7 2 20 0 20 524287
+1187 7 4 20 0 20 524287
+1188 7 0 20 10 20 20
+1189 7 1 20 10 20 524287
+1190 7 2 20 10 20 524287
+1191 7 4 20 10 20 524287
+1192 7 0 20 20 20 20
+1193 7 1 20 20 20 524287
+1194 7 2 20 20 20 524287
+1195 7 4 20 20 20 524287
+1196 7 0 20 16777215 20 20
+1197 7 1 20 16777215 20 524287
+1198 7 2 20 16777215 20 524287
+1199 7 4 20 16777215 20 524287
+1200 7 0 20 0 16777215 16777215
+1201 7 1 20 0 16777215 524287
+1202 7 2 20 0 16777215 524287
+1203 7 4 20 0 16777215 524287
+1204 7 0 20 10 16777215 16777215
+1205 7 1 20 10 16777215 524287
+1206 7 2 20 10 16777215 524287
+1207 7 4 20 10 16777215 524287
+1208 7 0 20 20 16777215 16777215
+1209 7 1 20 20 16777215 524287
+1210 7 2 20 20 16777215 524287
+1211 7 4 20 20 16777215 524287
+1212 7 0 20 16777215 16777215 16777215
+1213 7 1 20 16777215 16777215 524287
+1214 7 2 20 16777215 16777215 524287
+1215 7 4 20 16777215 16777215 524287
+1216 7 0 16777215 0 0 0
+1217 7 1 16777215 0 0 524287
+1218 7 2 16777215 0 0 524287
+1219 7 4 16777215 0 0 524287
+1220 7 0 16777215 10 0 0
+1221 7 1 16777215 10 0 524287
+1222 7 2 16777215 10 0 524287
+1223 7 4 16777215 10 0 524287
+1224 7 0 16777215 20 0 0
+1225 7 1 16777215 20 0 524287
+1226 7 2 16777215 20 0 524287
+1227 7 4 16777215 20 0 524287
+1228 7 0 16777215 16777215 0 0
+1229 7 1 16777215 16777215 0 524287
+1230 7 2 16777215 16777215 0 524287
+1231 7 4 16777215 16777215 0 524287
+1232 7 0 16777215 0 10 10
+1233 7 1 16777215 0 10 524287
+1234 7 2 16777215 0 10 524287
+1235 7 4 16777215 0 10 524287
+1236 7 0 16777215 10 10 10
+1237 7 1 16777215 10 10 524287
+1238 7 2 16777215 10 10 524287
+1239 7 4 16777215 10 10 524287
+1240 7 0 16777215 20 10 10
+1241 7 1 16777215 20 10 524287
+1242 7 2 16777215 20 10 524287
+1243 7 4 16777215 20 10 524287
+1244 7 0 16777215 16777215 10 10
+1245 7 1 16777215 16777215 10 524287
+1246 7 2 16777215 16777215 10 524287
+1247 7 4 16777215 16777215 10 524287
+1248 7 0 16777215 0 20 20
+1249 7 1 16777215 0 20 524287
+1250 7 2 16777215 0 20 524287
+1251 7 4 16777215 0 20 524287
+1252 7 0 16777215 10 20 20
+1253 7 1 16777215 10 20 524287
+1254 7 2 16777215 10 20 524287
+1255 7 4 16777215 10 20 524287
+1256 7 0 16777215 20 20 20
+1257 7 1 16777215 20 20 524287
+1258 7 2 16777215 20 20 524287
+1259 7 4 16777215 20 20 524287
+1260 7 0 16777215 16777215 20 20
+1261 7 1 16777215 16777215 20 524287
+1262 7 2 16777215 16777215 20 524287
+1263 7 4 16777215 16777215 20 524287
+1264 7 0 16777215 0 16777215 16777215
+1265 7 1 16777215 0 16777215 524287
+1266 7 2 16777215 0 16777215 524287
+1267 7 4 16777215 0 16777215 524287
+1268 7 0 16777215 10 16777215 16777215
+1269 7 1 16777215 10 16777215 524287
+1270 7 2 16777215 10 16777215 524287
+1271 7 4 16777215 10 16777215 524287
+1272 7 0 16777215 20 16777215 16777215
+1273 7 1 16777215 20 16777215 524287
+1274 7 2 16777215 20 16777215 524287
+1275 7 4 16777215 20 16777215 524287
+1276 7 0 16777215 16777215 16777215 16777215
+1277 7 1 16777215 16777215 16777215 524287
+1278 7 2 16777215 16777215 16777215 524287
+1279 7 4 16777215 16777215 16777215 524287
+1280 3 0 0 0 0 0
+1281 3 1 0 0 0 524287
+1282 3 2 0 0 0 524287
+1283 3 4 0 0 0 524287
+1284 3 0 0 10 0 0
+1285 3 1 0 10 0 524287
+1286 3 2 0 10 0 524287
+1287 3 4 0 10 0 524287
+1288 3 0 0 20 0 0
+1289 3 1 0 20 0 524287
+1290 3 2 0 20 0 524287
+1291 3 4 0 20 0 524287
+1292 3 0 0 16777215 0 0
+1293 3 1 0 16777215 0 524287
+1294 3 2 0 16777215 0 524287
+1295 3 4 0 16777215 0 524287
+1296 3 0 0 0 10 10
+1297 3 1 0 0 10 524287
+1298 3 2 0 0 10 524287
+1299 3 4 0 0 10 524287
+1300 3 0 0 10 10 10
+1301 3 1 0 10 10 524287
+1302 3 2 0 10 10 524287
+1303 3 4 0 10 10 524287
+1304 3 0 0 20 10 10
+1305 3 1 0 20 10 524287
+1306 3 2 0 20 10 524287
+1307 3 4 0 20 10 524287
+1308 3 0 0 16777215 10 10
+1309 3 1 0 16777215 10 524287
+1310 3 2 0 16777215 10 524287
+1311 3 4 0 16777215 10 524287
+1312 3 0 0 0 20 20
+1313 3 1 0 0 20 524287
+1314 3 2 0 0 20 524287
+1315 3 4 0 0 20 524287
+1316 3 0 0 10 20 20
+1317 3 1 0 10 20 524287
+1318 3 2 0 10 20 524287
+1319 3 4 0 10 20 524287
+1320 3 0 0 20 20 20
+1321 3 1 0 20 20 524287
+1322 3 2 0 20 20 524287
+1323 3 4 0 20 20 524287
+1324 3 0 0 16777215 20 20
+1325 3 1 0 16777215 20 524287
+1326 3 2 0 16777215 20 524287
+1327 3 4 0 16777215 20 524287
+1328 3 0 0 0 16777215 16777215
+1329 3 1 0 0 16777215 524287
+1330 3 2 0 0 16777215 524287
+1331 3 4 0 0 16777215 524287
+1332 3 0 0 10 16777215 16777215
+1333 3 1 0 10 16777215 524287
+1334 3 2 0 10 16777215 524287
+1335 3 4 0 10 16777215 524287
+1336 3 0 0 20 16777215 16777215
+1337 3 1 0 20 16777215 524287
+1338 3 2 0 20 16777215 524287
+1339 3 4 0 20 16777215 524287
+1340 3 0 0 16777215 16777215 16777215
+1341 3 1 0 16777215 16777215 524287
+1342 3 2 0 16777215 16777215 524287
+1343 3 4 0 16777215 16777215 524287
+1344 3 0 10 0 0 0
+1345 3 1 10 0 0 524287
+1346 3 2 10 0 0 524287
+1347 3 4 10 0 0 524287
+1348 3 0 10 10 0 0
+1349 3 1 10 10 0 524287
+1350 3 2 10 10 0 524287
+1351 3 4 10 10 0 524287
+1352 3 0 10 20 0 0
+1353 3 1 10 20 0 524287
+1354 3 2 10 20 0 524287
+1355 3 4 10 20 0 524287
+1356 3 0 10 16777215 0 0
+1357 3 1 10 16777215 0 524287
+1358 3 2 10 16777215 0 524287
+1359 3 4 10 16777215 0 524287
+1360 3 0 10 0 10 10
+1361 3 1 10 0 10 524287
+1362 3 2 10 0 10 524287
+1363 3 4 10 0 10 524287
+1364 3 0 10 10 10 10
+1365 3 1 10 10 10 524287
+1366 3 2 10 10 10 524287
+1367 3 4 10 10 10 524287
+1368 3 0 10 20 10 10
+1369 3 1 10 20 10 524287
+1370 3 2 10 20 10 524287
+1371 3 4 10 20 10 524287
+1372 3 0 10 16777215 10 10
+1373 3 1 10 16777215 10 524287
+1374 3 2 10 16777215 10 524287
+1375 3 4 10 16777215 10 524287
+1376 3 0 10 0 20 20
+1377 3 1 10 0 20 524287
+1378 3 2 10 0 20 524287
+1379 3 4 10 0 20 524287
+1380 3 0 10 10 20 20
+1381 3 1 10 10 20 524287
+1382 3 2 10 10 20 524287
+1383 3 4 10 10 20 524287
+1384 3 0 10 20 20 20
+1385 3 1 10 20 20 524287
+1386 3 2 10 20 20 524287
+1387 3 4 10 20 20 524287
+1388 3 0 10 16777215 20 20
+1389 3 1 10 16777215 20 524287
+1390 3 2 10 16777215 20 524287
+1391 3 4 10 16777215 20 524287
+1392 3 0 10 0 16777215 16777215
+1393 3 1 10 0 16777215 524287
+1394 3 2 10 0 16777215 524287
+1395 3 4 10 0 16777215 524287
+1396 3 0 10 10 16777215 16777215
+1397 3 1 10 10 16777215 524287
+1398 3 2 10 10 16777215 524287
+1399 3 4 10 10 16777215 524287
+1400 3 0 10 20 16777215 16777215
+1401 3 1 10 20 16777215 524287
+1402 3 2 10 20 16777215 524287
+1403 3 4 10 20 16777215 524287
+1404 3 0 10 16777215 16777215 16777215
+1405 3 1 10 16777215 16777215 524287
+1406 3 2 10 16777215 16777215 524287
+1407 3 4 10 16777215 16777215 524287
+1408 3 0 20 0 0 0
+1409 3 1 20 0 0 524287
+1410 3 2 20 0 0 524287
+1411 3 4 20 0 0 524287
+1412 3 0 20 10 0 0
+1413 3 1 20 10 0 524287
+1414 3 2 20 10 0 524287
+1415 3 4 20 10 0 524287
+1416 3 0 20 20 0 0
+1417 3 1 20 20 0 524287
+1418 3 2 20 20 0 524287
+1419 3 4 20 20 0 524287
+1420 3 0 20 16777215 0 0
+1421 3 1 20 16777215 0 524287
+1422 3 2 20 16777215 0 524287
+1423 3 4 20 16777215 0 524287
+1424 3 0 20 0 10 10
+1425 3 1 20 0 10 524287
+1426 3 2 20 0 10 524287
+1427 3 4 20 0 10 524287
+1428 3 0 20 10 10 10
+1429 3 1 20 10 10 524287
+1430 3 2 20 10 10 524287
+1431 3 4 20 10 10 524287
+1432 3 0 20 20 10 10
+1433 3 1 20 20 10 524287
+1434 3 2 20 20 10 524287
+1435 3 4 20 20 10 524287
+1436 3 0 20 16777215 10 10
+1437 3 1 20 16777215 10 524287
+1438 3 2 20 16777215 10 524287
+1439 3 4 20 16777215 10 524287
+1440 3 0 20 0 20 20
+1441 3 1 20 0 20 524287
+1442 3 2 20 0 20 524287
+1443 3 4 20 0 20 524287
+1444 3 0 20 10 20 20
+1445 3 1 20 10 20 524287
+1446 3 2 20 10 20 524287
+1447 3 4 20 10 20 524287
+1448 3 0 20 20 20 20
+1449 3 1 20 20 20 524287
+1450 3 2 20 20 20 524287
+1451 3 4 20 20 20 524287
+1452 3 0 20 16777215 20 20
+1453 3 1 20 16777215 20 524287
+1454 3 2 20 16777215 20 524287
+1455 3 4 20 16777215 20 524287
+1456 3 0 20 0 16777215 16777215
+1457 3 1 20 0 16777215 524287
+1458 3 2 20 0 16777215 524287
+1459 3 4 20 0 16777215 524287
+1460 3 0 20 10 16777215 16777215
+1461 3 1 20 10 16777215 524287
+1462 3 2 20 10 16777215 524287
+1463 3 4 20 10 16777215 524287
+1464 3 0 20 20 16777215 16777215
+1465 3 1 20 20 16777215 524287
+1466 3 2 20 20 16777215 524287
+1467 3 4 20 20 16777215 524287
+1468 3 0 20 16777215 16777215 16777215
+1469 3 1 20 16777215 16777215 524287
+1470 3 2 20 16777215 16777215 524287
+1471 3 4 20 16777215 16777215 524287
+1472 3 0 16777215 0 0 0
+1473 3 1 16777215 0 0 524287
+1474 3 2 16777215 0 0 524287
+1475 3 4 16777215 0 0 524287
+1476 3 0 16777215 10 0 0
+1477 3 1 16777215 10 0 524287
+1478 3 2 16777215 10 0 524287
+1479 3 4 16777215 10 0 524287
+1480 3 0 16777215 20 0 0
+1481 3 1 16777215 20 0 524287
+1482 3 2 16777215 20 0 524287
+1483 3 4 16777215 20 0 524287
+1484 3 0 16777215 16777215 0 0
+1485 3 1 16777215 16777215 0 524287
+1486 3 2 16777215 16777215 0 524287
+1487 3 4 16777215 16777215 0 524287
+1488 3 0 16777215 0 10 10
+1489 3 1 16777215 0 10 524287
+1490 3 2 16777215 0 10 524287
+1491 3 4 16777215 0 10 524287
+1492 3 0 16777215 10 10 10
+1493 3 1 16777215 10 10 524287
+1494 3 2 16777215 10 10 524287
+1495 3 4 16777215 10 10 524287
+1496 3 0 16777215 20 10 10
+1497 3 1 16777215 20 10 524287
+1498 3 2 16777215 20 10 524287
+1499 3 4 16777215 20 10 524287
+1500 3 0 16777215 16777215 10 10
+1501 3 1 16777215 16777215 10 524287
+1502 3 2 16777215 16777215 10 524287
+1503 3 4 16777215 16777215 10 524287
+1504 3 0 16777215 0 20 20
+1505 3 1 16777215 0 20 524287
+1506 3 2 16777215 0 20 524287
+1507 3 4 16777215 0 20 524287
+1508 3 0 16777215 10 20 20
+1509 3 1 16777215 10 20 524287
+1510 3 2 16777215 10 20 524287
+1511 3 4 16777215 10 20 524287
+1512 3 0 16777215 20 20 20
+1513 3 1 16777215 20 20 524287
+1514 3 2 16777215 20 20 524287
+1515 3 4 16777215 20 20 524287
+1516 3 0 16777215 16777215 20 20
+1517 3 1 16777215 16777215 20 524287
+1518 3 2 16777215 16777215 20 524287
+1519 3 4 16777215 16777215 20 524287
+1520 3 0 16777215 0 16777215 16777215
+1521 3 1 16777215 0 16777215 524287
+1522 3 2 16777215 0 16777215 524287
+1523 3 4 16777215 0 16777215 524287
+1524 3 0 16777215 10 16777215 16777215
+1525 3 1 16777215 10 16777215 524287
+1526 3 2 16777215 10 16777215 524287
+1527 3 4 16777215 10 16777215 524287
+1528 3 0 16777215 20 16777215 16777215
+1529 3 1 16777215 20 16777215 524287
+1530 3 2 16777215 20 16777215 524287
+1531 3 4 16777215 20 16777215 524287
+1532 3 0 16777215 16777215 16777215 16777215
+1533 3 1 16777215 16777215 16777215 524287
+1534 3 2 16777215 16777215 16777215 524287
+1535 3 4 16777215 16777215 16777215 524287
+1536 13 0 0 0 0 0
+1537 13 1 0 0 0 524287
+1538 13 2 0 0 0 524287
+1539 13 4 0 0 0 524287
+1540 13 0 0 10 0 0
+1541 13 1 0 10 0 524287
+1542 13 2 0 10 0 524287
+1543 13 4 0 10 0 524287
+1544 13 0 0 20 0 0
+1545 13 1 0 20 0 524287
+1546 13 2 0 20 0 524287
+1547 13 4 0 20 0 524287
+1548 13 0 0 16777215 0 0
+1549 13 1 0 16777215 0 524287
+1550 13 2 0 16777215 0 524287
+1551 13 4 0 16777215 0 524287
+1552 13 0 0 0 10 10
+1553 13 1 0 0 10 524287
+1554 13 2 0 0 10 524287
+1555 13 4 0 0 10 524287
+1556 13 0 0 10 10 10
+1557 13 1 0 10 10 524287
+1558 13 2 0 10 10 524287
+1559 13 4 0 10 10 524287
+1560 13 0 0 20 10 10
+1561 13 1 0 20 10 524287
+1562 13 2 0 20 10 524287
+1563 13 4 0 20 10 524287
+1564 13 0 0 16777215 10 10
+1565 13 1 0 16777215 10 524287
+1566 13 2 0 16777215 10 524287
+1567 13 4 0 16777215 10 524287
+1568 13 0 0 0 20 20
+1569 13 1 0 0 20 524287
+1570 13 2 0 0 20 524287
+1571 13 4 0 0 20 524287
+1572 13 0 0 10 20 20
+1573 13 1 0 10 20 524287
+1574 13 2 0 10 20 524287
+1575 13 4 0 10 20 524287
+1576 13 0 0 20 20 20
+1577 13 1 0 20 20 524287
+1578 13 2 0 20 20 524287
+1579 13 4 0 20 20 524287
+1580 13 0 0 16777215 20 20
+1581 13 1 0 16777215 20 524287
+1582 13 2 0 16777215 20 524287
+1583 13 4 0 16777215 20 524287
+1584 13 0 0 0 16777215 16777215
+1585 13 1 0 0 16777215 524287
+1586 13 2 0 0 16777215 524287
+1587 13 4 0 0 16777215 524287
+1588 13 0 0 10 16777215 16777215
+1589 13 1 0 10 16777215 524287
+1590 13 2 0 10 16777215 524287
+1591 13 4 0 10 16777215 524287
+1592 13 0 0 20 16777215 16777215
+1593 13 1 0 20 16777215 524287
+1594 13 2 0 20 16777215 524287
+1595 13 4 0 20 16777215 524287
+1596 13 0 0 16777215 16777215 16777215
+1597 13 1 0 16777215 16777215 524287
+1598 13 2 0 16777215 16777215 524287
+1599 13 4 0 16777215 16777215 524287
+1600 13 0 10 0 0 0
+1601 13 1 10 0 0 524287
+1602 13 2 10 0 0 524287
+1603 13 4 10 0 0 524287
+1604 13 0 10 10 0 0
+1605 13 1 10 10 0 524287
+1606 13 2 10 10 0 524287
+1607 13 4 10 10 0 524287
+1608 13 0 10 20 0 0
+1609 13 1 10 20 0 524287
+1610 13 2 10 20 0 524287
+1611 13 4 10 20 0 524287
+1612 13 0 10 16777215 0 0
+1613 13 1 10 16777215 0 524287
+1614 13 2 10 16777215 0 524287
+1615 13 4 10 16777215 0 524287
+1616 13 0 10 0 10 10
+1617 13 1 10 0 10 524287
+1618 13 2 10 0 10 524287
+1619 13 4 10 0 10 524287
+1620 13 0 10 10 10 10
+1621 13 1 10 10 10 524287
+1622 13 2 10 10 10 524287
+1623 13 4 10 10 10 524287
+1624 13 0 10 20 10 10
+1625 13 1 10 20 10 524287
+1626 13 2 10 20 10 524287
+1627 13 4 10 20 10 524287
+1628 13 0 10 16777215 10 10
+1629 13 1 10 16777215 10 524287
+1630 13 2 10 16777215 10 524287
+1631 13 4 10 16777215 10 524287
+1632 13 0 10 0 20 20
+1633 13 1 10 0 20 524287
+1634 13 2 10 0 20 524287
+1635 13 4 10 0 20 524287
+1636 13 0 10 10 20 20
+1637 13 1 10 10 20 524287
+1638 13 2 10 10 20 524287
+1639 13 4 10 10 20 524287
+1640 13 0 10 20 20 20
+1641 13 1 10 20 20 524287
+1642 13 2 10 20 20 524287
+1643 13 4 10 20 20 524287
+1644 13 0 10 16777215 20 20
+1645 13 1 10 16777215 20 524287
+1646 13 2 10 16777215 20 524287
+1647 13 4 10 16777215 20 524287
+1648 13 0 10 0 16777215 16777215
+1649 13 1 10 0 16777215 524287
+1650 13 2 10 0 16777215 524287
+1651 13 4 10 0 16777215 524287
+1652 13 0 10 10 16777215 16777215
+1653 13 1 10 10 16777215 524287
+1654 13 2 10 10 16777215 524287
+1655 13 4 10 10 16777215 524287
+1656 13 0 10 20 16777215 16777215
+1657 13 1 10 20 16777215 524287
+1658 13 2 10 20 16777215 524287
+1659 13 4 10 20 16777215 524287
+1660 13 0 10 16777215 16777215 16777215
+1661 13 1 10 16777215 16777215 524287
+1662 13 2 10 16777215 16777215 524287
+1663 13 4 10 16777215 16777215 524287
+1664 13 0 20 0 0 0
+1665 13 1 20 0 0 524287
+1666 13 2 20 0 0 524287
+1667 13 4 20 0 0 524287
+1668 13 0 20 10 0 0
+1669 13 1 20 10 0 524287
+1670 13 2 20 10 0 524287
+1671 13 4 20 10 0 524287
+1672 13 0 20 20 0 0
+1673 13 1 20 20 0 524287
+1674 13 2 20 20 0 524287
+1675 13 4 20 20 0 524287
+1676 13 0 20 16777215 0 0
+1677 13 1 20 16777215 0 524287
+1678 13 2 20 16777215 0 524287
+1679 13 4 20 16777215 0 524287
+1680 13 0 20 0 10 10
+1681 13 1 20 0 10 524287
+1682 13 2 20 0 10 524287
+1683 13 4 20 0 10 524287
+1684 13 0 20 10 10 10
+1685 13 1 20 10 10 524287
+1686 13 2 20 10 10 524287
+1687 13 4 20 10 10 524287
+1688 13 0 20 20 10 10
+1689 13 1 20 20 10 524287
+1690 13 2 20 20 10 524287
+1691 13 4 20 20 10 524287
+1692 13 0 20 16777215 10 10
+1693 13 1 20 16777215 10 524287
+1694 13 2 20 16777215 10 524287
+1695 13 4 20 16777215 10 524287
+1696 13 0 20 0 20 20
+1697 13 1 20 0 20 524287
+1698 13 2 20 0 20 524287
+1699 13 4 20 0 20 524287
+1700 13 0 20 10 20 20
+1701 13 1 20 10 20 524287
+1702 13 2 20 10 20 524287
+1703 13 4 20 10 20 524287
+1704 13 0 20 20 20 20
+1705 13 1 20 20 20 524287
+1706 13 2 20 20 20 524287
+1707 13 4 20 20 20 524287
+1708 13 0 20 16777215 20 20
+1709 13 1 20 16777215 20 524287
+1710 13 2 20 16777215 20 524287
+1711 13 4 20 16777215 20 524287
+1712 13 0 20 0 16777215 16777215
+1713 13 1 20 0 16777215 524287
+1714 13 2 20 0 16777215 524287
+1715 13 4 20 0 16777215 524287
+1716 13 0 20 10 16777215 16777215
+1717 13 1 20 10 16777215 524287
+1718 13 2 20 10 16777215 524287
+1719 13 4 20 10 16777215 524287
+1720 13 0 20 20 16777215 16777215
+1721 13 1 20 20 16777215 524287
+1722 13 2 20 20 16777215 524287
+1723 13 4 20 20 16777215 524287
+1724 13 0 20 16777215 16777215 16777215
+1725 13 1 20 16777215 16777215 524287
+1726 13 2 20 16777215 16777215 524287
+1727 13 4 20 16777215 16777215 524287
+1728 13 0 16777215 0 0 0
+1729 13 1 16777215 0 0 524287
+1730 13 2 16777215 0 0 524287
+1731 13 4 16777215 0 0 524287
+1732 13 0 16777215 10 0 0
+1733 13 1 16777215 10 0 524287
+1734 13 2 16777215 10 0 524287
+1735 13 4 16777215 10 0 524287
+1736 13 0 16777215 20 0 0
+1737 13 1 16777215 20 0 524287
+1738 13 2 16777215 20 0 524287
+1739 13 4 16777215 20 0 524287
+1740 13 0 16777215 16777215 0 0
+1741 13 1 16777215 16777215 0 524287
+1742 13 2 16777215 16777215 0 524287
+1743 13 4 16777215 16777215 0 524287
+1744 13 0 16777215 0 10 10
+1745 13 1 16777215 0 10 524287
+1746 13 2 16777215 0 10 524287
+1747 13 4 16777215 0 10 524287
+1748 13 0 16777215 10 10 10
+1749 13 1 16777215 10 10 524287
+1750 13 2 16777215 10 10 524287
+1751 13 4 16777215 10 10 524287
+1752 13 0 16777215 20 10 10
+1753 13 1 16777215 20 10 524287
+1754 13 2 16777215 20 10 524287
+1755 13 4 16777215 20 10 524287
+1756 13 0 16777215 16777215 10 10
+1757 13 1 16777215 16777215 10 524287
+1758 13 2 16777215 16777215 10 524287
+1759 13 4 16777215 16777215 10 524287
+1760 13 0 16777215 0 20 20
+1761 13 1 16777215 0 20 524287
+1762 13 2 16777215 0 20 524287
+1763 13 4 16777215 0 20 524287
+1764 13 0 16777215 10 20 20
+1765 13 1 16777215 10 20 524287
+1766 13 2 16777215 10 20 524287
+1767 13 4 16777215 10 20 524287
+1768 13 0 16777215 20 20 20
+1769 13 1 16777215 20 20 524287
+1770 13 2 16777215 20 20 524287
+1771 13 4 16777215 20 20 524287
+1772 13 0 16777215 16777215 20 20
+1773 13 1 16777215 16777215 20 524287
+1774 13 2 16777215 16777215 20 524287
+1775 13 4 16777215 16777215 20 524287
+1776 13 0 16777215 0 16777215 16777215
+1777 13 1 16777215 0 16777215 524287
+1778 13 2 16777215 0 16777215 524287
+1779 13 4 16777215 0 16777215 524287
+1780 13 0 16777215 10 16777215 16777215
+1781 13 1 16777215 10 16777215 524287
+1782 13 2 16777215 10 16777215 524287
+1783 13 4 16777215 10 16777215 524287
+1784 13 0 16777215 20 16777215 16777215
+1785 13 1 16777215 20 16777215 524287
+1786 13 2 16777215 20 16777215 524287
+1787 13 4 16777215 20 16777215 524287
+1788 13 0 16777215 16777215 16777215 16777215
+1789 13 1 16777215 16777215 16777215 524287
+1790 13 2 16777215 16777215 16777215 524287
+1791 13 4 16777215 16777215 16777215 524287
diff --git a/tests/auto/widgets/kernel/qlayout/qlayout.pro b/tests/auto/widgets/kernel/qlayout/qlayout.pro
new file mode 100644
index 0000000000..28ca9dc86d
--- /dev/null
+++ b/tests/auto/widgets/kernel/qlayout/qlayout.pro
@@ -0,0 +1,16 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+
+SOURCES += tst_qlayout.cpp
+wince* {
+ addFiles.files = baseline
+ addFiles.path = .
+ DEPLOYMENT += addFiles
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD\\\"
+
+ test_data.files = baseline/*
+ test_data.path = $${target.path}/baseline
+ INSTALLS += test_data
+}
diff --git a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
new file mode 100644
index 0000000000..ea25700568
--- /dev/null
+++ b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
@@ -0,0 +1,345 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qcoreapplication.h>
+#include <qdebug.h>
+#include <qboxlayout.h>
+#include <qmenubar.h>
+#include <qdialog.h>
+#include <qsizegrip.h>
+#include <qlabel.h>
+#include <QtWidgets/QFrame>
+#include <QtWidgets/QWindowsStyle>
+#include <QtWidgets/QSizePolicy>
+#include <QPushButton>
+#include <QRadioButton>
+#include <private/qlayoutengine_p.h>
+
+#ifdef Q_WS_MAC
+# include <QtGui/QMacStyle>
+#endif
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QLayout : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QLayout();
+ virtual ~tst_QLayout();
+
+private slots:
+ void getSetCheck();
+ void geometry();
+ void smartMaxSize();
+ void setLayoutBugs();
+ void setContentsMargins();
+ void layoutItemRect();
+ void warnIfWrongParent();
+ void controlTypes();
+ void adjustSizeShouldMakeSureLayoutIsActivated();
+};
+
+tst_QLayout::tst_QLayout()
+{
+}
+
+tst_QLayout::~tst_QLayout()
+{
+}
+
+// Testing get/set functions
+void tst_QLayout::getSetCheck()
+{
+ QBoxLayout obj1(QBoxLayout::LeftToRight);
+ // QWidget * QLayout::menuBar()
+ // void QLayout::setMenuBar(QWidget *)
+ QMenuBar *var1 = new QMenuBar();
+ obj1.setMenuBar(var1);
+ QCOMPARE(static_cast<QWidget *>(var1), obj1.menuBar());
+ obj1.setMenuBar((QWidget *)0);
+ QCOMPARE((QWidget *)0, obj1.menuBar());
+ delete var1;
+}
+
+class SizeHinterFrame : public QFrame
+{
+public:
+ SizeHinterFrame(const QSize &sh, const QSize &msh = QSize())
+ : QFrame(0), sh(sh), msh(msh) {
+ setFrameStyle(QFrame::Box | QFrame::Plain);
+ }
+
+
+
+ void setSizeHint(const QSize &s) { sh = s; }
+ QSize sizeHint() const { return sh; }
+ QSize minimumSizeHint() const { return msh; }
+
+private:
+ QSize sh;
+ QSize msh;
+};
+
+
+void tst_QLayout::geometry()
+{
+ // For QWindowsStyle we know that QWidgetItem::geometry() and QWidget::geometry()
+ // should be the same.
+ QApplication::setStyle(new QWindowsStyle);
+ QWidget topLevel;
+ QWidget w(&topLevel);
+ QVBoxLayout layout(&w);
+ SizeHinterFrame widget(QSize(100,100));
+ layout.addWidget(&widget);
+ QLayoutItem *item = layout.itemAt(0);
+ topLevel.show();
+ QApplication::processEvents();
+ QCOMPARE(item->geometry().size(), QSize(100,100));
+
+ widget.setMinimumSize(QSize(110,110));
+ QCOMPARE(item->geometry().size(), QSize(110,110));
+
+ widget.setMinimumSize(QSize(0,0));
+ widget.setMaximumSize(QSize(90,90));
+ widget.setSizeHint(QSize(100,100));
+ QCOMPARE(item->geometry().size(), QSize(90,90));
+}
+
+void tst_QLayout::smartMaxSize()
+{
+ QVector<int> expectedWidths;
+
+ QFile f(QLatin1String(SRCDIR "/baseline/smartmaxsize"));
+
+ QCOMPARE(f.open(QIODevice::ReadOnly | QIODevice::Text), true);
+
+ QTextStream stream(&f);
+
+ while(!stream.atEnd()) {
+ QString line = stream.readLine(200);
+ expectedWidths.append(line.section(QLatin1Char(' '), 6, -1, QString::SectionSkipEmpty).toInt());
+ }
+ f.close();
+
+ int sizeCombinations[] = { 0, 10, 20, QWIDGETSIZE_MAX};
+ QSizePolicy::Policy policies[] = { QSizePolicy::Fixed,
+ QSizePolicy::Minimum,
+ QSizePolicy::Maximum,
+ QSizePolicy::Preferred,
+ QSizePolicy::Expanding,
+ QSizePolicy::MinimumExpanding,
+ QSizePolicy::Ignored
+ };
+ Qt::Alignment alignments[] = { 0,
+ Qt::AlignLeft,
+ Qt::AlignRight,
+ Qt::AlignHCenter
+ };
+
+ int expectedIndex = 0;
+ int regressionCount = 0;
+ for (size_t p = 0; p < sizeof(policies)/sizeof(QSizePolicy::Policy); ++p) {
+ QSizePolicy sizePolicy;
+ sizePolicy.setHorizontalPolicy(policies[p]);
+ for (size_t min = 0; min < sizeof(sizeCombinations)/sizeof(int); ++min) {
+ int minSize = sizeCombinations[min];
+ for (size_t max = 0; max < sizeof(sizeCombinations)/sizeof(int); ++max) {
+ int maxSize = sizeCombinations[max];
+ for (size_t sh = 0; sh < sizeof(sizeCombinations)/sizeof(int); ++sh) {
+ int sizeHint = sizeCombinations[sh];
+ for (size_t a = 0; a < sizeof(alignments)/sizeof(int); ++a) {
+ Qt::Alignment align = alignments[a];
+ QSize sz = qSmartMaxSize(QSize(sizeHint, 1), QSize(minSize, 1), QSize(maxSize, 1), sizePolicy, align);
+ int width = sz.width();
+#if 0
+ qDebug() << expectedIndex << sizePolicy.horizontalPolicy() << align << minSize << sizeHint << maxSize << width;
+#else
+ int expectedWidth = expectedWidths[expectedIndex];
+ if (width != expectedWidth) {
+ qDebug() << "error at index" << expectedIndex << ":" << sizePolicy.horizontalPolicy() << align << minSize << sizeHint << maxSize << width;
+ ++regressionCount;
+ }
+#endif
+ ++expectedIndex;
+ }
+ }
+ }
+ }
+ }
+ QCOMPARE(regressionCount, 0);
+}
+
+void tst_QLayout::setLayoutBugs()
+{
+ QWidget widget(0);
+ QHBoxLayout *hBoxLayout = new QHBoxLayout(&widget);
+
+ for(int i = 0; i < 6; ++i) {
+ QPushButton *pushButton = new QPushButton("Press me!", &widget);
+ hBoxLayout->addWidget(pushButton);
+ }
+
+ widget.setLayout(hBoxLayout);
+ QVERIFY(widget.layout() == hBoxLayout);
+
+ QWidget containerWidget(0);
+ containerWidget.setLayout(widget.layout());
+ QVERIFY(widget.layout() == 0);
+ QVERIFY(containerWidget.layout() == hBoxLayout);
+}
+
+class MyLayout : public QLayout
+{
+ public:
+ MyLayout() : invalidated(false) {}
+ virtual void invalidate() {invalidated = true;}
+ bool invalidated;
+ QSize sizeHint() const {return QSize();}
+ void addItem(QLayoutItem*) {}
+ QLayoutItem* itemAt(int) const {return 0;}
+ QLayoutItem* takeAt(int) {return 0;}
+ int count() const {return 0;}
+};
+
+void tst_QLayout::setContentsMargins()
+{
+ MyLayout layout;
+ layout.invalidated = false;
+ int left, top, right, bottom;
+
+ layout.setContentsMargins(52, 53, 54, 55);
+ QVERIFY(layout.invalidated);
+ layout.invalidated = false;
+
+ layout.getContentsMargins(&left, &top, &right, &bottom);
+ QCOMPARE(left, 52);
+ QCOMPARE(top, 53);
+ QCOMPARE(right, 54);
+ QCOMPARE(bottom, 55);
+
+ layout.setContentsMargins(52, 53, 54, 55);
+ QVERIFY(!layout.invalidated);
+}
+
+class EventReceiver : public QObject
+{
+public:
+ bool eventFilter(QObject *watched, QEvent *event)
+ {
+ if (event->type() == QEvent::Show) {
+ geom = static_cast<QWidget*>(watched)->geometry();
+ }
+ return false;
+ }
+ QRect geom;
+};
+
+void tst_QLayout::layoutItemRect()
+{
+#ifdef Q_WS_MAC
+ if (qobject_cast<QMacStyle*>(QApplication::style())) {
+ QWidget *window = new QWidget;
+ QRadioButton *radio = new QRadioButton(window);
+ QWidgetItem item(radio);
+ EventReceiver eventReceiver;
+ radio->installEventFilter(&eventReceiver);
+
+ radio->show();
+ QApplication::processEvents();
+ QApplication::processEvents();
+ QSize s = item.sizeHint();
+
+ item.setAlignment(Qt::AlignVCenter);
+ item.setGeometry(QRect(QPoint(0, 0), s));
+
+ QCOMPARE(radio->geometry().size(), radio->sizeHint());
+ delete radio;
+ }
+#endif
+}
+
+void tst_QLayout::warnIfWrongParent()
+{
+ QWidget root;
+ QHBoxLayout lay;
+ lay.setParent(&root);
+ QTest::ignoreMessage(QtWarningMsg, "QLayout::parentWidget: A layout can only have another layout as a parent.");
+ QCOMPARE(lay.parentWidget(), static_cast<QWidget*>(0));
+}
+
+void tst_QLayout::controlTypes()
+{
+ QVBoxLayout layout;
+ QCOMPARE(layout.controlTypes(), QSizePolicy::DefaultType);
+ QSizePolicy p;
+ QCOMPARE(p.controlType(),QSizePolicy::DefaultType);
+
+}
+
+void tst_QLayout::adjustSizeShouldMakeSureLayoutIsActivated()
+{
+ QWidget main;
+
+ QVBoxLayout *const layout = new QVBoxLayout(&main);
+ layout->setMargin(0);
+ SizeHinterFrame *frame = new SizeHinterFrame(QSize(200, 10), QSize(200, 8));
+ frame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ layout->addWidget(frame);
+
+ SizeHinterFrame *frame2 = new SizeHinterFrame(QSize(200, 10), QSize(200, 8));
+ frame2->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ layout->addWidget(frame2);
+
+ main.show();
+
+ frame2->hide();
+ main.adjustSize();
+ QCOMPARE(main.size(), QSize(200, 10));
+}
+
+QTEST_MAIN(tst_QLayout)
+#include "tst_qlayout.moc"
diff --git a/tests/auto/widgets/kernel/qsound/.gitignore b/tests/auto/widgets/kernel/qsound/.gitignore
new file mode 100644
index 0000000000..c9d313c2cf
--- /dev/null
+++ b/tests/auto/widgets/kernel/qsound/.gitignore
@@ -0,0 +1 @@
+tst_qsound
diff --git a/tests/auto/widgets/kernel/qsound/4.wav b/tests/auto/widgets/kernel/qsound/4.wav
new file mode 100644
index 0000000000..e31b060908
--- /dev/null
+++ b/tests/auto/widgets/kernel/qsound/4.wav
Binary files differ
diff --git a/tests/auto/widgets/kernel/qsound/qsound.pro b/tests/auto/widgets/kernel/qsound/qsound.pro
new file mode 100644
index 0000000000..18ebaf16a4
--- /dev/null
+++ b/tests/auto/widgets/kernel/qsound/qsound.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+SOURCES += tst_qsound.cpp
+
+wince* {
+ deploy.files += 4.wav
+ DEPLOYMENT += deploy
+ DEFINES += SRCDIR=\\\"\\\"
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
diff --git a/tests/auto/widgets/kernel/qsound/tst_qsound.cpp b/tests/auto/widgets/kernel/qsound/tst_qsound.cpp
new file mode 100644
index 0000000000..7450549f47
--- /dev/null
+++ b/tests/auto/widgets/kernel/qsound/tst_qsound.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui>
+
+class tst_QSound : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QSound( QObject* parent=0) : QObject(parent) {}
+
+private slots:
+ void checkFinished();
+
+ // Manual tests
+ void staticPlay();
+};
+
+void tst_QSound::checkFinished()
+{
+#if defined(Q_WS_QPA)
+ QSKIP("QSound is not implemented on Lighthouse", SkipAll);
+#else
+ QSound sound(SRCDIR"4.wav");
+ sound.setLoops(3);
+ sound.play();
+ QTest::qWait(5000);
+
+#if defined(Q_WS_QWS)
+ QEXPECT_FAIL("", "QSound buggy on embedded (task QTBUG-157)", Abort);
+#endif
+ QVERIFY(sound.isFinished() );
+#endif
+}
+
+void tst_QSound::staticPlay()
+{
+ QSKIP("Test disabled -- only for manual purposes", SkipAll);
+#if !defined(Q_WS_QPA)
+ // Check that you hear sound with static play also.
+ QSound::play(SRCDIR"4.wav");
+ QTest::qWait(2000);
+#endif
+}
+
+QTEST_MAIN(tst_QSound);
+#include "tst_qsound.moc"
diff --git a/tests/auto/widgets/kernel/qstackedlayout/.gitignore b/tests/auto/widgets/kernel/qstackedlayout/.gitignore
new file mode 100644
index 0000000000..4dca3e87bd
--- /dev/null
+++ b/tests/auto/widgets/kernel/qstackedlayout/.gitignore
@@ -0,0 +1 @@
+tst_qstackedlayout
diff --git a/tests/auto/widgets/kernel/qstackedlayout/qstackedlayout.pro b/tests/auto/widgets/kernel/qstackedlayout/qstackedlayout.pro
new file mode 100644
index 0000000000..30f074d9b1
--- /dev/null
+++ b/tests/auto/widgets/kernel/qstackedlayout/qstackedlayout.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qstackedlayout.cpp
+
+
+
diff --git a/tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp b/tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp
new file mode 100644
index 0000000000..de734877d7
--- /dev/null
+++ b/tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp
@@ -0,0 +1,372 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QLineEdit>
+#include <QStackedLayout>
+#include <qapplication.h>
+#include <qwidget.h>
+#include <QPushButton>
+
+//TESTED_CLASS=
+//TESTED_FILES=gui/kernel/qlayout.cpp gui/kernel/qlayout.h
+
+class tst_QStackedLayout : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QStackedLayout();
+ virtual ~tst_QStackedLayout();
+
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void getSetCheck();
+ void testCase();
+ void deleteCurrent();
+ void removeWidget();
+ void keepFocusAfterSetCurrent();
+
+private:
+ QWidget *testWidget;
+};
+
+// Testing get/set functions
+void tst_QStackedLayout::getSetCheck()
+{
+ QStackedLayout obj1;
+ // int QStackedLayout::currentIndex()
+ // void QStackedLayout::setCurrentIndex(int)
+ obj1.setCurrentIndex(0);
+ QCOMPARE(-1, obj1.currentIndex());
+ obj1.setCurrentIndex(INT_MIN);
+ QCOMPARE(-1, obj1.currentIndex());
+ obj1.setCurrentIndex(INT_MAX);
+ QCOMPARE(-1, obj1.currentIndex());
+
+ // QWidget * QStackedLayout::currentWidget()
+ // void QStackedLayout::setCurrentWidget(QWidget *)
+ QWidget *var2 = new QWidget();
+ obj1.addWidget(var2);
+ obj1.setCurrentWidget(var2);
+ QCOMPARE(var2, obj1.currentWidget());
+
+ obj1.setCurrentWidget((QWidget *)0);
+ QCOMPARE(obj1.currentWidget(), var2);
+
+ delete var2;
+}
+
+
+tst_QStackedLayout::tst_QStackedLayout()
+ : testWidget(0)
+{
+}
+
+tst_QStackedLayout::~tst_QStackedLayout()
+{
+}
+
+void tst_QStackedLayout::initTestCase()
+{
+}
+
+void tst_QStackedLayout::cleanupTestCase()
+{
+}
+
+void tst_QStackedLayout::init()
+{
+ if (testWidget) {
+ delete testWidget;
+ testWidget = 0;
+ }
+ testWidget = new QWidget(0);
+ testWidget->resize( 200, 200 );
+ testWidget->show();
+
+ // make sure the tests work with focus follows mouse
+ QCursor::setPos(testWidget->geometry().center());
+ testWidget->activateWindow();
+ QApplication::syncX();
+ QTest::qWait(250);
+}
+
+void tst_QStackedLayout::cleanup()
+{
+ delete testWidget;
+ testWidget = 0;
+}
+
+
+void tst_QStackedLayout::testCase()
+{
+ QStackedLayout onStack(testWidget);
+ QStackedLayout *testLayout = &onStack;
+ testWidget->setLayout(testLayout);
+
+ QSignalSpy spy(testLayout,SIGNAL(currentChanged(int)));
+
+ // Nothing in layout
+ QCOMPARE(testLayout->currentIndex(), -1);
+ QCOMPARE(testLayout->currentWidget(), static_cast<QWidget*>(0));
+ QCOMPARE(testLayout->count(), 0);
+
+ // One widget added to layout
+ QWidget *w1 = new QWidget(testWidget);
+ testLayout->addWidget(w1);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toInt(), 0);
+ spy.clear();
+ QCOMPARE(testLayout->currentIndex(), 0);
+ QCOMPARE(testLayout->currentWidget(), w1);
+ QCOMPARE(testLayout->count(), 1);
+
+ // Another widget added to layout
+ QWidget *w2 = new QWidget(testWidget);
+ testLayout->addWidget(w2);
+ QCOMPARE(testLayout->currentIndex(), 0);
+ QCOMPARE(testLayout->currentWidget(), w1);
+ QCOMPARE(testLayout->indexOf(w2), 1);
+ QCOMPARE(testLayout->count(), 2);
+
+ // Change the current index
+ testLayout->setCurrentIndex(1);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toInt(), 1);
+ spy.clear();
+ QCOMPARE(testLayout->currentIndex(), 1);
+ QCOMPARE(testLayout->currentWidget(), w2);
+
+ // First widget removed from layout
+ testLayout->removeWidget(w1);
+ QCOMPARE(testLayout->currentIndex(), 0);
+ QCOMPARE(testLayout->currentWidget(), w2);
+ QCOMPARE(testLayout->count(), 1);
+
+ // Second widget removed from layout; back to nothing
+ testLayout->removeWidget(w2);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).at(0).toInt(), -1);
+ spy.clear();
+ QCOMPARE(testLayout->currentIndex(), -1);
+ QCOMPARE(testLayout->currentWidget(), static_cast<QWidget*>(0));
+ QCOMPARE(testLayout->count(), 0);
+
+ // Another widget inserted at current index.
+ // Current index should become current index + 1, but the
+ // current widget should stay the same
+ testLayout->addWidget(w1);
+ QCOMPARE(testLayout->currentIndex(), 0);
+ QCOMPARE(testLayout->currentWidget(), w1);
+ testLayout->insertWidget(0, w2);
+ QCOMPARE(testLayout->currentIndex(), 1);
+ QCOMPARE(testLayout->currentWidget(), w1);
+ QVERIFY(w1->isVisible());
+ QVERIFY(!w2->isVisible());
+
+ testLayout->setCurrentWidget(w2);
+ // Another widget added, so we have: w2, w1, w3 with w2 current
+ QWidget *w3 = new QWidget(testWidget);
+ testLayout->addWidget(w3);
+ QCOMPARE(testLayout->indexOf(w2), 0);
+ QCOMPARE(testLayout->indexOf(w1), 1);
+ QCOMPARE(testLayout->indexOf(w3), 2);
+
+ // Set index to 1 and remove that widget (w1).
+ // Then, current index should still be 1, but w3
+ // should be the new current widget.
+ testLayout->setCurrentIndex(1);
+ testLayout->removeWidget(w1);
+ QCOMPARE(testLayout->currentIndex(), 1);
+ QCOMPARE(testLayout->currentWidget(), w3);
+ QVERIFY(w3->isVisible());
+
+ // Remove the current widget (w3).
+ // Since it's the last one in the list, current index should now
+ // become 0 and w2 becomes the current widget.
+ testLayout->removeWidget(w3);
+ QCOMPARE(testLayout->currentIndex(), 0);
+ QCOMPARE(testLayout->currentWidget(), w2);
+ QVERIFY(w2->isVisible());
+
+ // Make sure index is decremented when we remove a widget at index < current index
+ testLayout->addWidget(w1);
+ testLayout->addWidget(w3);
+ testLayout->setCurrentIndex(2);
+ testLayout->removeWidget(w2); // At index 0
+ QCOMPARE(testLayout->currentIndex(), 1);
+ QCOMPARE(testLayout->currentWidget(), w3);
+ QVERIFY(w3->isVisible());
+ testLayout->removeWidget(w1); // At index 0
+ QCOMPARE(testLayout->currentIndex(), 0);
+ QCOMPARE(testLayout->currentWidget(), w3);
+ QVERIFY(w3->isVisible());
+ testLayout->removeWidget(w3);
+ QCOMPARE(testLayout->currentIndex(), -1);
+ QCOMPARE(testLayout->currentWidget(), static_cast<QWidget*>(0));
+}
+
+void tst_QStackedLayout::deleteCurrent()
+{
+ QStackedLayout *testLayout = new QStackedLayout(testWidget);
+
+ QWidget *w1 = new QWidget;
+ testLayout->addWidget(w1);
+ QWidget *w2 = new QWidget;
+ testLayout->addWidget(w2);
+ QCOMPARE(testLayout->currentWidget(), w1);
+ delete testLayout->currentWidget();
+ QCOMPARE(testLayout->currentWidget(), w2);
+}
+
+void tst_QStackedLayout::removeWidget()
+{
+ if (testWidget->layout()) delete testWidget->layout();
+ QVBoxLayout *vbox = new QVBoxLayout(testWidget);
+
+ QPushButton *top = new QPushButton("top", testWidget); //add another widget that can receive focus
+ top->setObjectName("top");
+ vbox->addWidget(top);
+
+ QStackedLayout *testLayout = new QStackedLayout();
+ QPushButton *w1 = new QPushButton("1st", testWidget);
+ w1->setObjectName("1st");
+ testLayout->addWidget(w1);
+ QPushButton *w2 = new QPushButton("2nd", testWidget);
+ w2->setObjectName("2nd");
+ testLayout->addWidget(w2);
+ vbox->addLayout(testLayout);
+ top->setFocus();
+ QTest::qWait(100);
+ top->activateWindow();
+ QTest::qWait(100);
+ int i =0;
+ for (;;) {
+ if (QApplication::focusWidget() == top)
+ break;
+ else if (i >= 5)
+ QSKIP("Can't get focus", SkipSingle);
+ QTest::qWait(100);
+ ++i;
+ }
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(top));
+
+ // focus should stay at the 'top' widget
+ testLayout->removeWidget(w1);
+
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(top));
+}
+
+class LineEdit : public QLineEdit
+{
+public:
+ LineEdit() : hasFakeEditFocus(false)
+ { }
+
+ bool hasFakeEditFocus;
+
+protected:
+ bool isSingleFocusWidget() const
+ {
+ const QWidget *w = this;
+ while ((w = w->nextInFocusChain()) != this) {
+ if (w->isVisible() && static_cast<const QWidget*>(w->focusProxy()) != this
+ && w->focusPolicy() & Qt::TabFocus) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void focusInEvent(QFocusEvent *event)
+ {
+ QLineEdit::focusInEvent(event);
+ hasFakeEditFocus = isSingleFocusWidget();
+ }
+
+ void focusOutEvent(QFocusEvent *event)
+ {
+ hasFakeEditFocus = false;
+ QLineEdit::focusOutEvent(event);
+ }
+};
+
+void tst_QStackedLayout::keepFocusAfterSetCurrent()
+{
+ if (testWidget->layout()) delete testWidget->layout();
+ QStackedLayout *stackLayout = new QStackedLayout(testWidget);
+ testWidget->setFocusPolicy(Qt::NoFocus);
+
+ LineEdit *edit1 = new LineEdit;
+ LineEdit *edit2 = new LineEdit;
+ stackLayout->addWidget(edit1);
+ stackLayout->addWidget(edit2);
+
+ stackLayout->setCurrentIndex(0);
+
+ testWidget->show();
+ QApplication::setActiveWindow(testWidget);
+ QTest::qWaitForWindowShown(testWidget);
+ QApplication::processEvents();
+
+ edit1->setFocus();
+ edit1->activateWindow();
+ QTest::qWait(25);
+
+ QTRY_VERIFY(edit1->hasFocus());
+
+ stackLayout->setCurrentIndex(1);
+ QVERIFY(!edit1->hasFocus());
+ QVERIFY(edit2->hasFocus());
+ QVERIFY(edit2->hasFakeEditFocus);
+}
+
+QTEST_MAIN(tst_QStackedLayout)
+#include "tst_qstackedlayout.moc"
+
diff --git a/tests/auto/widgets/kernel/qtooltip/.gitignore b/tests/auto/widgets/kernel/qtooltip/.gitignore
new file mode 100644
index 0000000000..552a2a5dc6
--- /dev/null
+++ b/tests/auto/widgets/kernel/qtooltip/.gitignore
@@ -0,0 +1 @@
+tst_qtooltip
diff --git a/tests/auto/widgets/kernel/qtooltip/qtooltip.pro b/tests/auto/widgets/kernel/qtooltip/qtooltip.pro
new file mode 100644
index 0000000000..4da8917921
--- /dev/null
+++ b/tests/auto/widgets/kernel/qtooltip/qtooltip.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qtooltip.cpp
+
+CONFIG += insignificant_test # QTBUG-21402
diff --git a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
new file mode 100644
index 0000000000..3ff31ead62
--- /dev/null
+++ b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qtooltip.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QToolTip : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QToolTip() {}
+ virtual ~tst_QToolTip() {}
+
+public slots:
+ void initTestCase() {}
+ void cleanupTestCase() {}
+ void init() {}
+ void cleanup() {}
+
+private slots:
+
+ // task-specific tests below me
+ void task183679_data();
+ void task183679();
+ void whatsThis();
+ void setPalette();
+};
+
+class Widget_task183679 : public QWidget
+{
+ Q_OBJECT
+public:
+ Widget_task183679(QWidget *parent = 0) : QWidget(parent) {}
+
+ void showDelayedToolTip(int msecs)
+ {
+ QTimer::singleShot(msecs, this, SLOT(showToolTip()));
+ }
+
+private slots:
+ void showToolTip()
+ {
+ QToolTip::showText(mapToGlobal(QPoint(0, 0)), "tool tip text", this);
+ }
+};
+
+Q_DECLARE_METATYPE(Qt::Key)
+
+void tst_QToolTip::task183679_data()
+{
+ QTest::addColumn<Qt::Key>("key");
+ QTest::addColumn<bool>("visible");
+#ifdef Q_WS_MAC
+ const bool visibleAfterNonModifier = false;
+#else
+ const bool visibleAfterNonModifier = true;
+#endif
+ QTest::newRow("non-modifier") << Qt::Key_A << visibleAfterNonModifier;
+ QTest::newRow("Shift") << Qt::Key_Shift << true;
+ QTest::newRow("Control") << Qt::Key_Control << true;
+ QTest::newRow("Alt") << Qt::Key_Alt << true;
+ QTest::newRow("Meta") << Qt::Key_Meta << true;
+}
+
+void tst_QToolTip::task183679()
+{
+ QFETCH(Qt::Key, key);
+ QFETCH(bool, visible);
+
+ Widget_task183679 widget;
+ widget.show();
+ QApplication::setActiveWindow(&widget);
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(30);
+
+
+ widget.showDelayedToolTip(100);
+ QTest::qWait(300);
+ QTRY_VERIFY(QToolTip::isVisible());
+
+ QTest::keyPress(&widget, key);
+
+ // Important: the following delay must be larger than the duration of the timer potentially
+ // initiated by the key press (currently 300 msecs), but smaller than the minimum
+ // auto-close timeout (currently 10000 msecs)
+ QTest::qWait(1500);
+
+ QCOMPARE(QToolTip::isVisible(), visible);
+}
+
+#include <QWhatsThis>
+
+void tst_QToolTip::whatsThis()
+{
+ qApp->setStyleSheet( "QWidget { font-size: 72px; }" );
+ QWhatsThis::showText(QPoint(0,0), "THis is text");
+ QTest::qWait(400);
+ QWidget *whatsthis = 0;
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ if (widget->inherits("QWhatsThat")) {
+ whatsthis = widget;
+ break;
+ }
+ }
+ QVERIFY(whatsthis);
+ QVERIFY(whatsthis->isVisible());
+ QVERIFY(whatsthis->height() > 100); // Test QTBUG-2416
+ qApp->setStyleSheet("");
+}
+
+
+void tst_QToolTip::setPalette()
+{
+ //the previous test may still have a tooltip pending for deletion
+ QVERIFY(!QToolTip::isVisible());
+
+ QToolTip::showText(QPoint(), "tool tip text", 0);
+
+ QTRY_VERIFY(QToolTip::isVisible());
+
+ QWidget *toolTip = 0;
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ if (widget->windowType() == Qt::ToolTip
+ && widget->objectName() == QLatin1String("qtooltip_label"))
+ {
+ toolTip = widget;
+ break;
+ }
+ }
+
+ QVERIFY(toolTip);
+ QTRY_VERIFY(toolTip->isVisible());
+
+ const QPalette oldPalette = toolTip->palette();
+ QPalette newPalette = oldPalette;
+ newPalette.setColor(QPalette::ToolTipBase, Qt::red);
+ newPalette.setColor(QPalette::ToolTipText, Qt::blue);
+ QToolTip::setPalette(newPalette);
+ QCOMPARE(toolTip->palette(), newPalette);
+}
+
+QTEST_MAIN(tst_QToolTip)
+#include "tst_qtooltip.moc"
diff --git a/tests/auto/widgets/kernel/qwidget/.gitignore b/tests/auto/widgets/kernel/qwidget/.gitignore
new file mode 100644
index 0000000000..82a0ac9eba
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/.gitignore
@@ -0,0 +1 @@
+tst_qwidget
diff --git a/tests/auto/widgets/kernel/qwidget/geometry-fullscreen.dat b/tests/auto/widgets/kernel/qwidget/geometry-fullscreen.dat
new file mode 100644
index 0000000000..9802ee8b9e
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/geometry-fullscreen.dat
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/geometry-maximized.dat b/tests/auto/widgets/kernel/qwidget/geometry-maximized.dat
new file mode 100644
index 0000000000..df5bc2f94e
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/geometry-maximized.dat
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/geometry.dat b/tests/auto/widgets/kernel/qwidget/geometry.dat
new file mode 100644
index 0000000000..e5dcb2dc44
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/geometry.dat
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/qwidget.pro b/tests/auto/widgets/kernel/qwidget/qwidget.pro
new file mode 100644
index 0000000000..9c34e0c254
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/qwidget.pro
@@ -0,0 +1,23 @@
+load(qttest_p4)
+
+QT += widgets core-private gui-private widgets-private
+
+SOURCES += tst_qwidget.cpp
+RESOURCES = qwidget.qrc
+
+aix-g++*:QMAKE_CXXFLAGS+=-fpermissive
+
+CONFIG += x11inc
+
+mac:!qpa {
+ LIBS += -framework Security -framework AppKit -framework Carbon
+ OBJECTIVE_SOURCES += tst_qwidget_mac_helpers.mm
+}
+
+x11 {
+ LIBS += $$QMAKE_LIBS_X11
+}
+
+!wince*:win32: LIBS += -luser32 -lgdi32
+
+CONFIG+=insignificant_test
diff --git a/tests/auto/widgets/kernel/qwidget/qwidget.qrc b/tests/auto/widgets/kernel/qwidget/qwidget.qrc
new file mode 100644
index 0000000000..1399c4c9db
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/qwidget.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource>
+ <file>geometry.dat</file>
+ <file>geometry-maximized.dat</file>
+ <file>geometry-fullscreen.dat</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data0.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data0.qsnap
new file mode 100644
index 0000000000..b3473cdefe
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data1.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data1.qsnap
new file mode 100644
index 0000000000..10007733ca
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data1.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data2.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data2.qsnap
new file mode 100644
index 0000000000..cde5964a30
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data2.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data3.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data3.qsnap
new file mode 100644
index 0000000000..23ea1410e4
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Motif_data3.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data0.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data0.qsnap
new file mode 100644
index 0000000000..a8918c1d1b
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data0.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data1.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data1.qsnap
new file mode 100644
index 0000000000..0981cf5dd1
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data1.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data2.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data2.qsnap
new file mode 100644
index 0000000000..75d09136cf
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data2.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data3.qsnap b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data3.qsnap
new file mode 100644
index 0000000000..f58f74d030
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/testdata/paintEvent/res_Windows_data3.qsnap
Binary files differ
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
new file mode 100644
index 0000000000..ded0c5e061
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -0,0 +1,9472 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <qboxlayout.h>
+#include <qapplication.h>
+#include <qbitmap.h>
+#include <qdebug.h>
+#include <qeventloop.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qlistview.h>
+#include <qmessagebox.h>
+#include <qpainter.h>
+#include <qpoint.h>
+#include <qpushbutton.h>
+#include <qstyle.h>
+#include <qwidget.h>
+#include <qwindowsstyle.h>
+#include <qinputcontext.h>
+#include <qdesktopwidget.h>
+#include <private/qwidget_p.h>
+#include <private/qapplication_p.h>
+#include <qcalendarwidget.h>
+#include <qmainwindow.h>
+#include <qdockwidget.h>
+#include <qtoolbar.h>
+#include <QtGui/qpaintengine.h>
+#include <QtGui/qbackingstore.h>
+#include <QtGui/qguiapplication.h>
+#include <qmenubar.h>
+#include <qtableview.h>
+
+#include <QtWidgets/QGraphicsView>
+#include <QtWidgets/QGraphicsProxyWidget>
+
+#ifdef Q_WS_QWS
+# include <qscreen_qws.h>
+#endif
+
+// I *MUST* have QtTest afterwards or this test won't work with newer headers
+#if defined(Q_WS_MAC)
+# include <private/qt_mac_p.h>
+#undef verify
+#include "tst_qwidget_mac_helpers.h" // Abstract the ObjC stuff out so not everyone must run an ObjC++ compile.
+#endif
+
+#include <QtTest/QtTest>
+
+#if defined(Q_OS_WIN)
+# include <QtCore/qt_windows.h>
+# include <QtGui/private/qguiapplication_p.h>
+# include <QtGui/QPlatformNativeInterface>
+# include <QtGui/QPlatformIntegration>
+
+static HWND winHandleOf(const QWidget *w)
+{
+ static QPlatformNativeInterface *nativeInterface
+ = QGuiApplicationPrivate::instance()->platformIntegration()->nativeInterface();
+ if (void *handle = nativeInterface->nativeResourceForWindow("handle", w->window()->windowHandle()))
+ return reinterpret_cast<HWND>(handle);
+ qWarning() << "Cannot obtain native handle for " << w;
+ return 0;
+}
+#endif
+
+#if defined(Q_WS_WIN)
+# include <qt_windows.h>
+# if !defined(Q_OS_WINCE)
+#define Q_CHECK_PAINTEVENTS \
+ if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
+ QSKIP("desktop is not visible, this test would fail", SkipSingle);
+# else
+# define Q_CHECK_PAINTEVENTS
+# endif
+#elif defined(Q_WS_X11)
+# include <private/qt_x11_p.h>
+# include <qx11info_x11.h>
+#elif defined(Q_WS_QWS)
+# include <qwindowsystem_qws.h>
+#endif
+
+#if !defined(Q_WS_WIN)
+#define Q_CHECK_PAINTEVENTS
+#endif
+
+#if defined(Q_OS_WINCE_WM)
+#include <qguifunctions_wince.h>
+// taken from qguifunctions_wce.cpp
+#define SPI_GETPLATFORMTYPE 257
+bool qt_wince_is_platform(const QString &platformString) {
+ wchar_t tszPlatform[64];
+ if (SystemParametersInfo(SPI_GETPLATFORMTYPE,
+ sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0))
+ if (0 == _tcsicmp(reinterpret_cast<const wchar_t *> (platformString.utf16()), tszPlatform))
+ return true;
+ return false;
+}
+bool qt_wince_is_smartphone() {
+ return qt_wince_is_platform(QString::fromLatin1("Smartphone"));
+}
+#endif
+
+#ifdef Q_WS_MAC
+#include <Security/AuthSession.h>
+bool macHasAccessToWindowsServer()
+{
+ SecuritySessionId mySession;
+ SessionAttributeBits sessionInfo;
+ SessionGetInfo(callerSecuritySession, &mySession, &sessionInfo);
+ return (sessionInfo & sessionHasGraphicAccess);
+}
+#endif
+
+
+#if defined(Bool)
+#undef Bool
+#endif
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QWidget : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QWidget();
+ virtual ~tst_QWidget();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+private slots:
+ void getSetCheck();
+ void fontPropagation();
+ void fontPropagation2();
+ void palettePropagation();
+ void palettePropagation2();
+ void enabledPropagation();
+#ifndef QT_NO_DRAGANDDROP
+ void acceptDropsPropagation();
+#endif
+ void isEnabledTo();
+ void visible();
+ void visible_setWindowOpacity();
+ void isVisibleTo();
+ void isHidden();
+ void fonts();
+ void mapFromAndTo_data();
+ void mapFromAndTo();
+ void focusChainOnHide();
+ void focusChainOnReparent();
+ void setTabOrder();
+#ifdef Q_WS_WIN
+ void activation();
+#endif
+ void reparent();
+#ifndef Q_WS_X11
+ void windowState();
+#endif
+ void showMaximized();
+ void showFullScreen();
+ void showMinimized();
+ void showMinimizedKeepsFocus();
+#ifndef Q_WS_QWS
+ void icon();
+#endif
+ void hideWhenFocusWidgetIsChild();
+#ifndef Q_OS_IRIX
+ void normalGeometry();
+#endif
+ void setGeometry();
+#ifndef Q_OS_WINCE
+ void windowOpacity();
+#endif
+ void raise();
+ void lower();
+#ifndef QT_MAC_USE_COCOA
+ void stackUnder();
+#endif
+ void testContentsPropagation();
+#ifndef Q_OS_IRIX
+ void saveRestoreGeometry();
+ void restoreVersion1Geometry_data();
+ void restoreVersion1Geometry();
+#endif
+
+ void widgetAt();
+#ifdef Q_WS_MAC
+ void retainHIView();
+ void sheetOpacity();
+ void setMask();
+#endif
+ void optimizedResizeMove();
+ void optimizedResize_topLevel();
+ void resizeEvent();
+ void task110173();
+
+ void testDeletionInEventHandlers();
+
+ void childDeletesItsSibling();
+
+ void setMinimumSize();
+ void setMaximumSize();
+ void setFixedSize();
+
+ void ensureCreated();
+ void winIdChangeEvent();
+ void persistentWinId();
+ void showNativeChild();
+ void qobject_castInDestroyedSlot();
+
+ void showHideEvent_data();
+ void showHideEvent();
+
+ void lostUpdatesOnHide();
+
+ void update();
+ void isOpaque();
+
+#ifndef Q_WS_MAC
+ void scroll();
+#endif
+
+#ifndef Q_WS_X11
+ // tests QWidget::setGeometry()
+ void setWindowGeometry_data();
+ void setWindowGeometry();
+#endif
+
+#if !defined(Q_WS_X11) && !defined(Q_OS_IRIX)
+ // tests QWidget::move() and resize()
+ void windowMoveResize_data();
+ void windowMoveResize();
+#endif
+
+ void moveChild_data();
+ void moveChild();
+ void showAndMoveChild();
+
+#ifndef QT_MAC_USE_COCOA
+ void subtractOpaqueSiblings();
+#endif
+
+#ifdef Q_WS_WIN
+ void getDC();
+#ifndef Q_OS_WINCE
+ void setGeometry_win();
+#endif
+#endif
+
+ void setLocale();
+ void deleteStyle();
+ void multipleToplevelFocusCheck();
+ void setFocus();
+ void setCursor();
+ void setToolTip();
+ void testWindowIconChangeEventPropagation();
+#ifdef Q_WS_X11
+ void minAndMaxSizeWithX11BypassWindowManagerHint();
+ void showHideShow();
+ void clean_qt_x11_enforce_cursor();
+#endif
+
+ void compatibilityChildInsertedEvents();
+ void render();
+ void renderInvisible();
+ void renderWithPainter();
+ void render_task188133();
+ void render_task211796();
+ void render_task217815();
+#ifndef Q_OS_WINCE
+ void render_windowOpacity();
+#endif
+ void render_systemClip();
+ void render_systemClip2_data();
+ void render_systemClip2();
+ void render_systemClip3_data();
+ void render_systemClip3();
+ void render_task252837();
+ void render_worldTransform();
+
+ void setContentsMargins();
+
+#ifndef Q_OS_IRIX
+ void moveWindowInShowEvent_data();
+ void moveWindowInShowEvent();
+#endif
+
+ void repaintWhenChildDeleted();
+ void hideOpaqueChildWhileHidden();
+#if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS)
+ void updateWhileMinimized();
+#endif
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ void alienWidgets();
+#endif
+ void adjustSize();
+ void adjustSize_data();
+ void updateGeometry();
+ void updateGeometry_data();
+ void sendUpdateRequestImmediately();
+#ifndef Q_OS_IRIX
+ void doubleRepaint();
+#endif
+#ifndef Q_WS_MAC
+ void resizeInPaintEvent();
+ void opaqueChildren();
+#endif
+
+ void setMaskInResizeEvent();
+ void moveInResizeEvent();
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ // We don't support immediate repaint right after show on
+ // other platforms. Must be compatible with Qt 4.3.
+ void immediateRepaintAfterShow();
+ void immediateRepaintAfterInvalidateBuffer();
+#endif
+ void effectiveWinId();
+ void effectiveWinId2();
+ void customDpi();
+ void customDpiProperty();
+
+ void quitOnCloseAttribute();
+ void moveRect();
+
+#if defined (Q_WS_WIN)
+ void gdiPainting();
+ void paintOnScreenPossible();
+#endif
+ void reparentStaticWidget();
+ void QTBUG6883_reparentStaticWidget2();
+#ifdef Q_WS_QWS
+ void updateOutsideSurfaceClip();
+#endif
+ void translucentWidget();
+
+ void setClearAndResizeMask();
+ void maskedUpdate();
+#if defined(Q_WS_X11) || (defined(Q_WS_WIN) && !defined(Q_OS_WINCE_WM)) || defined(Q_WS_QWS) || defined(Q_WS_QPA)
+ void syntheticEnterLeave();
+ void taskQTBUG_4055_sendSyntheticEnterLeave();
+#endif
+ void windowFlags();
+ void initialPosForDontShowOnScreenWidgets();
+#ifdef Q_WS_X11
+ void paintOutsidePaintEvent();
+#endif
+ void updateOnDestroyedSignal();
+ void toplevelLineEditFocus();
+ void inputFocus_task257832();
+
+ void focusWidget_task254563();
+#ifndef Q_OS_WINCE_WM
+ void rectOutsideCoordinatesLimit_task144779();
+#endif
+ void setGraphicsEffect();
+
+#ifdef QT_BUILD_INTERNAL
+ void destroyBackingStore();
+#endif
+
+ void activateWindow();
+
+ void openModal_taskQTBUG_5804();
+
+ void focusProxyAndInputMethods();
+#ifdef QT_BUILD_INTERNAL
+ void scrollWithoutBackingStore();
+#endif
+
+ void taskQTBUG_7532_tabOrderWithFocusProxy();
+ void movedAndResizedAttributes();
+ void childAt();
+#ifdef Q_WS_MAC
+ void childAt_unifiedToolBar();
+ void taskQTBUG_11373();
+#endif
+ void taskQTBUG_17333_ResizeInfiniteRecursion();
+
+ void nativeChildFocus();
+
+private:
+ bool ensureScreenSize(int width, int height);
+ QWidget *testWidget;
+};
+
+bool tst_QWidget::ensureScreenSize(int width, int height)
+{
+ QSize available;
+#ifdef Q_WS_QWS
+ available = QDesktopWidget().availableGeometry().size();
+ if (available.width() < width || available.height() < height) {
+ QScreen *screen = QScreen::instance();
+ if (!screen)
+ return false;
+ screen->setMode(width, height, screen->depth());
+ }
+#endif // Q_WS_QWS
+
+ available = QDesktopWidget().availableGeometry().size();
+ return (available.width() >= width && available.height() >= height);
+}
+
+class MyInputContext : public QInputContext
+{
+public:
+ MyInputContext() : QInputContext() {}
+ QString identifierName() { return QString("NoName"); }
+ QString language() { return QString("NoLanguage"); }
+ void reset() {}
+ bool isComposing() const { return false; }
+};
+
+// Testing get/set functions
+void tst_QWidget::getSetCheck()
+{
+ QWidget obj1;
+ QWidget child1(&obj1);
+ // QStyle * QWidget::style()
+ // void QWidget::setStyle(QStyle *)
+ QWindowsStyle *var1 = new QWindowsStyle;
+ obj1.setStyle(var1);
+ QCOMPARE(static_cast<QStyle *>(var1), obj1.style());
+ obj1.setStyle((QStyle *)0);
+ QVERIFY(var1 != obj1.style());
+ QVERIFY(0 != obj1.style()); // style can never be 0 for a widget
+
+ // int QWidget::minimumWidth()
+ // void QWidget::setMinimumWidth(int)
+ obj1.setMinimumWidth(0);
+ QCOMPARE(obj1.minimumWidth(), 0);
+ obj1.setMinimumWidth(INT_MIN);
+ QCOMPARE(obj1.minimumWidth(), 0); // A widgets width can never be less than 0
+ obj1.setMinimumWidth(INT_MAX);
+#ifndef Q_WS_QWS //QWS doesn't allow toplevels to be bigger than the screen
+ QCOMPARE(obj1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
+#endif
+
+ child1.setMinimumWidth(0);
+ QCOMPARE(child1.minimumWidth(), 0);
+ child1.setMinimumWidth(INT_MIN);
+ QCOMPARE(child1.minimumWidth(), 0); // A widgets width can never be less than 0
+ child1.setMinimumWidth(INT_MAX);
+ QCOMPARE(child1.minimumWidth(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
+
+ // int QWidget::minimumHeight()
+ // void QWidget::setMinimumHeight(int)
+ obj1.setMinimumHeight(0);
+ QCOMPARE(obj1.minimumHeight(), 0);
+ obj1.setMinimumHeight(INT_MIN);
+ QCOMPARE(obj1.minimumHeight(), 0); // A widgets height can never be less than 0
+ obj1.setMinimumHeight(INT_MAX);
+#ifndef Q_WS_QWS //QWS doesn't allow toplevels to be bigger than the screen
+ QCOMPARE(obj1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
+#endif
+
+ child1.setMinimumHeight(0);
+ QCOMPARE(child1.minimumHeight(), 0);
+ child1.setMinimumHeight(INT_MIN);
+ QCOMPARE(child1.minimumHeight(), 0); // A widgets height can never be less than 0
+ child1.setMinimumHeight(INT_MAX);
+ QCOMPARE(child1.minimumHeight(), QWIDGETSIZE_MAX); // The largest minimum size should only be as big as the maximium
+
+ // int QWidget::maximumWidth()
+ // void QWidget::setMaximumWidth(int)
+ obj1.setMaximumWidth(0);
+ QCOMPARE(obj1.maximumWidth(), 0);
+ obj1.setMaximumWidth(INT_MIN);
+ QCOMPARE(obj1.maximumWidth(), 0); // A widgets width can never be less than 0
+ obj1.setMaximumWidth(INT_MAX);
+ QCOMPARE(obj1.maximumWidth(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX
+
+ // int QWidget::maximumHeight()
+ // void QWidget::setMaximumHeight(int)
+ obj1.setMaximumHeight(0);
+ QCOMPARE(obj1.maximumHeight(), 0);
+ obj1.setMaximumHeight(INT_MIN);
+ QCOMPARE(obj1.maximumHeight(), 0); // A widgets height can never be less than 0
+ obj1.setMaximumHeight(INT_MAX);
+ QCOMPARE(obj1.maximumHeight(), QWIDGETSIZE_MAX); // QWIDGETSIZE_MAX is the abs max, not INT_MAX
+
+ // back to normal
+ obj1.setMinimumWidth(0);
+ obj1.setMinimumHeight(0);
+ obj1.setMaximumWidth(QWIDGETSIZE_MAX);
+ obj1.setMaximumHeight(QWIDGETSIZE_MAX);
+
+ // const QPalette & QWidget::palette()
+ // void QWidget::setPalette(const QPalette &)
+ QPalette var6;
+ obj1.setPalette(var6);
+ QCOMPARE(var6, obj1.palette());
+ obj1.setPalette(QPalette());
+ QCOMPARE(QPalette(), obj1.palette());
+
+ // const QFont & QWidget::font()
+ // void QWidget::setFont(const QFont &)
+ QFont var7;
+ obj1.setFont(var7);
+ QCOMPARE(var7, obj1.font());
+ obj1.setFont(QFont());
+ QCOMPARE(QFont(), obj1.font());
+
+ // qreal QWidget::windowOpacity()
+ // void QWidget::setWindowOpacity(qreal)
+ obj1.setWindowOpacity(0.0);
+ QCOMPARE(0.0, obj1.windowOpacity());
+ obj1.setWindowOpacity(1.1f);
+ QCOMPARE(1.0, obj1.windowOpacity()); // 1.0 is the fullest opacity possible
+
+ // QWidget * QWidget::focusProxy()
+ // void QWidget::setFocusProxy(QWidget *)
+ QWidget *var9 = new QWidget();
+ obj1.setFocusProxy(var9);
+ QCOMPARE(var9, obj1.focusProxy());
+ obj1.setFocusProxy((QWidget *)0);
+ QCOMPARE((QWidget *)0, obj1.focusProxy());
+ delete var9;
+
+ // const QRect & QWidget::geometry()
+ // void QWidget::setGeometry(const QRect &)
+ qApp->processEvents();
+ QRect var10(10, 10, 100, 100);
+ obj1.setGeometry(var10);
+ qApp->processEvents();
+ qDebug() << obj1.geometry();
+ QCOMPARE(var10, obj1.geometry());
+ obj1.setGeometry(QRect(0,0,0,0));
+ qDebug() << obj1.geometry();
+ QCOMPARE(QRect(0,0,0,0), obj1.geometry());
+
+ // QLayout * QWidget::layout()
+ // void QWidget::setLayout(QLayout *)
+ QBoxLayout *var11 = new QBoxLayout(QBoxLayout::LeftToRight);
+ obj1.setLayout(var11);
+ QCOMPARE(static_cast<QLayout *>(var11), obj1.layout());
+ obj1.setLayout((QLayout *)0);
+ QCOMPARE(static_cast<QLayout *>(var11), obj1.layout()); // You cannot set a 0-pointer layout, that keeps the current
+ delete var11; // This will remove the layout from the widget
+ QCOMPARE((QLayout *)0, obj1.layout());
+
+ // bool QWidget::acceptDrops()
+ // void QWidget::setAcceptDrops(bool)
+ obj1.setAcceptDrops(false);
+ QCOMPARE(false, obj1.acceptDrops());
+ obj1.setAcceptDrops(true);
+ QCOMPARE(true, obj1.acceptDrops());
+
+ // QInputContext * QWidget::inputContext()
+ MyInputContext *var13 = new MyInputContext;
+ qApp->setInputContext(var13);
+ QCOMPARE((QInputContext *)0, obj1.inputContext()); // The widget by default doesn't have the WA_InputMethodEnabled attribute
+ obj1.setAttribute(Qt::WA_InputMethodEnabled);
+ QCOMPARE(static_cast<QInputContext *>(var13), obj1.inputContext());
+
+ // bool QWidget::autoFillBackground()
+ // void QWidget::setAutoFillBackground(bool)
+ obj1.setAutoFillBackground(false);
+ QCOMPARE(false, obj1.autoFillBackground());
+ obj1.setAutoFillBackground(true);
+ QCOMPARE(true, obj1.autoFillBackground());
+
+ delete var1;
+#if defined (Q_WS_WIN) && !defined(Q_OS_WINCE)
+ obj1.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
+ HWND handle = obj1.winId();
+ long flags = GetWindowLong(handle, GWL_STYLE);
+ QVERIFY(flags & WS_POPUP);
+#endif
+}
+
+tst_QWidget::tst_QWidget()
+{
+ QFont font;
+ font.setBold(true);
+ font.setPointSize(42);
+ qApp->setFont(font, "QPropagationTestWidget");
+
+ QPalette palette;
+ palette.setColor(QPalette::ToolTipBase, QColor(12, 13, 14));
+ palette.setColor(QPalette::Text, QColor(21, 22, 23));
+ qApp->setPalette(palette, "QPropagationTestWidget");
+
+ testWidget = 0;
+}
+
+tst_QWidget::~tst_QWidget()
+{
+}
+
+class BezierViewer : public QWidget {
+public:
+ BezierViewer( QWidget* parent=0, const char* name=0 );
+ void paintEvent( QPaintEvent* );
+ void setPoints( const QPolygonF& poly );
+private:
+ QPolygonF points;
+
+};
+
+void tst_QWidget::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+ // Create the test class
+ testWidget = new BezierViewer( 0, "testObject");
+ testWidget->resize(200,200);
+ testWidget->show();
+ QTest::qWaitForWindowShown(testWidget);
+ QTest::qWait(50);
+}
+
+void tst_QWidget::cleanupTestCase()
+{
+ delete testWidget;
+ testWidget = 0;
+}
+
+void tst_QWidget::init()
+{
+// TODO: Add initialization code here.
+// This will be executed immediately before each test is run.
+ testWidget->setFont(QFont());
+ testWidget->setPalette(QPalette());
+}
+
+void tst_QWidget::cleanup()
+{
+}
+
+// Helper class...
+
+BezierViewer::BezierViewer( QWidget* parent, const char* name )
+ : QWidget( parent )
+{
+ setObjectName(name);
+ QPalette pal;
+ pal.setColor(backgroundRole(), Qt::white);
+ setPalette(pal);
+}
+
+
+void BezierViewer::setPoints( const QPolygonF& a )
+{
+ points = a;
+}
+
+#include "private/qbezier_p.h"
+void BezierViewer::paintEvent( QPaintEvent* )
+{
+ if ( points.size() != 4 ) {
+#if defined(QT_CHECK_RANGE)
+ qWarning( "QPolygon::bezier: The array must have 4 control points" );
+#endif
+ return;
+ }
+
+ /* Calculate Bezier curve */
+ QPolygonF bezier = QBezier::fromPoints(points.at(0),points.at(1),points.at(2),points.at(3)).toPolygon();
+
+ QPainter painter( this );
+
+ /* Calculate scale to fit in window */
+ QRectF br = bezier.boundingRect() | points.boundingRect();
+ QRectF pr = rect();
+ int scl = qMax( qMin(pr.width()/br.width(), pr.height()/br.height()), qreal(1.) );
+ int border = scl-1;
+
+ /* Scale Bezier curve vertices */
+ for ( QPolygonF::Iterator it = bezier.begin(); it != bezier.end(); ++it ) {
+ it->setX( (it->x()-br.x()) * scl + border );
+ it->setY( (it->y()-br.y()) * scl + border );
+ }
+
+ /* Draw grid */
+ painter.setPen( Qt::lightGray );
+ int i;
+ for ( i = border; i <= pr.width(); i += scl ) {
+ painter.drawLine( i, 0, i, pr.height() );
+ }
+ for ( int j = border; j <= pr.height(); j += scl ) {
+ painter.drawLine( 0, j, pr.width(), j );
+ }
+
+ /* Write number of vertices */
+ painter.setPen( Qt::red );
+ painter.setFont( QFont("Helvetica", 14, QFont::DemiBold, TRUE ) );
+ QString caption;
+ caption.setNum( bezier.size() );
+ caption += QString::fromLatin1( " vertices" );
+ painter.drawText( 10, pr.height()-10, caption );
+
+ /* Draw Bezier curve */
+ painter.setPen( Qt::black );
+ painter.drawPolyline( bezier );
+
+ /* Scale and draw control points */
+ painter.setPen( Qt::darkGreen );
+ for ( QPolygonF::Iterator p1 = points.begin(); p1 != points.end(); ++p1 ) {
+ int x = (p1->x()-br.x()) * scl + border;
+ int y = (p1->y()-br.y()) * scl + border;
+ painter.drawLine( x-4, y-4, x+4, y+4 );
+ painter.drawLine( x+4, y-4, x-4, y+4 );
+ }
+
+ /* Draw vertices */
+ painter.setPen( Qt::red );
+ painter.setBrush( Qt::red );
+ for ( QPolygonF::Iterator p2 = bezier.begin(); p2 != bezier.end(); ++p2 )
+ painter.drawEllipse( p2->x()-1, p2->y()-1, 3, 3 );
+}
+
+void tst_QWidget::fontPropagation()
+{
+ QFont font = testWidget->font();
+ QWidget* childWidget = new QWidget( testWidget );
+ childWidget->show();
+ QCOMPARE( font, childWidget->font() );
+
+ font.setBold( TRUE );
+ testWidget->setFont( font );
+ QCOMPARE( font, testWidget->font() );
+ QCOMPARE( font, childWidget->font() );
+
+ QFont newFont = font;
+ newFont.setItalic( TRUE );
+ childWidget->setFont( newFont );
+ QWidget* grandChildWidget = new QWidget( childWidget );
+ QCOMPARE( font, testWidget->font() );
+ QCOMPARE( newFont, grandChildWidget->font() );
+
+ font.setUnderline( TRUE );
+ testWidget->setFont( font );
+
+ // the child and grand child should now have merged bold and
+ // underline
+ newFont.setUnderline( TRUE );
+
+ QCOMPARE( newFont, childWidget->font() );
+ QCOMPARE( newFont, grandChildWidget->font() );
+
+ // make sure font propagation continues working after reparenting
+ font = testWidget->font();
+ font.setPointSize(font.pointSize() + 2);
+ testWidget->setFont(font);
+
+ QWidget *one = new QWidget(testWidget);
+ QWidget *two = new QWidget(one);
+ QWidget *three = new QWidget(two);
+ QWidget *four = new QWidget(two);
+
+ four->setParent(three);
+ four->move(QPoint(0,0));
+
+ font.setPointSize(font.pointSize() + 2);
+ testWidget->setFont(font);
+
+ QCOMPARE(testWidget->font(), one->font());
+ QCOMPARE(one->font(), two->font());
+ QCOMPARE(two->font(), three->font());
+ QCOMPARE(three->font(), four->font());
+
+ QVERIFY(testWidget->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! one->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! two->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! three->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! four->testAttribute(Qt::WA_SetFont));
+
+ font.setPointSize(font.pointSize() + 2);
+ one->setFont(font);
+
+ QCOMPARE(one->font(), two->font());
+ QCOMPARE(two->font(), three->font());
+ QCOMPARE(three->font(), four->font());
+
+ QVERIFY(one->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! two->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! three->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! four->testAttribute(Qt::WA_SetFont));
+
+ font.setPointSize(font.pointSize() + 2);
+ two->setFont(font);
+
+ QCOMPARE(two->font(), three->font());
+ QCOMPARE(three->font(), four->font());
+
+ QVERIFY(two->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! three->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! four->testAttribute(Qt::WA_SetFont));
+
+ font.setPointSize(font.pointSize() + 2);
+ three->setFont(font);
+
+ QCOMPARE(three->font(), four->font());
+
+ QVERIFY(three->testAttribute(Qt::WA_SetFont));
+ QVERIFY(! four->testAttribute(Qt::WA_SetFont));
+
+ font.setPointSize(font.pointSize() + 2);
+ four->setFont(font);
+
+ QVERIFY(four->testAttribute(Qt::WA_SetFont));
+}
+
+class QPropagationTestWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ QPropagationTestWidget(QWidget *parent = 0)
+ : QWidget(parent)
+ { }
+};
+
+void tst_QWidget::fontPropagation2()
+{
+ // ! Note, the code below is executed in tst_QWidget's constructor.
+ // QFont font;
+ // font.setBold(true);
+ // font.setPointSize(42);
+ // qApp->setFont(font, "QPropagationTestWidget");
+
+ QWidget *root = new QWidget;
+ QWidget *child0 = new QWidget(root);
+ QWidget *child1 = new QWidget(child0);
+ QWidget *child2 = new QPropagationTestWidget(child1);
+ QWidget *child3 = new QWidget(child2);
+ QWidget *child4 = new QWidget(child3);
+ QWidget *child5 = new QWidget(child4);
+ root->show();
+
+ // Check that only the application fonts apply.
+ QCOMPARE(root->font(), QApplication::font());
+ QCOMPARE(child0->font(), QApplication::font());
+ QCOMPARE(child1->font(), QApplication::font());
+ QCOMPARE(child2->font().pointSize(), 42);
+ QVERIFY(child2->font().bold());
+ QCOMPARE(child3->font().pointSize(), 42);
+ QVERIFY(child3->font().bold());
+ QCOMPARE(child4->font().pointSize(), 42);
+ QVERIFY(child4->font().bold());
+ QCOMPARE(child5->font().pointSize(), 42);
+ QVERIFY(child5->font().bold());
+
+ // Set child0's font size to 15, and remove bold on child4.
+ QFont font;
+ font.setPointSize(15);
+ child0->setFont(font);
+ QFont unboldFont;
+ unboldFont.setBold(false);
+ child4->setFont(unboldFont);
+
+ // Check that the above settings propagate correctly.
+ QCOMPARE(root->font(), QApplication::font());
+ QCOMPARE(child0->font().pointSize(), 15);
+ QVERIFY(!child0->font().bold());
+ QCOMPARE(child1->font().pointSize(), 15);
+ QVERIFY(!child1->font().bold());
+ QCOMPARE(child2->font().pointSize(), 15);
+ QVERIFY(child2->font().bold());
+ QCOMPARE(child3->font().pointSize(), 15);
+ QVERIFY(child3->font().bold());
+ QCOMPARE(child4->font().pointSize(), 15);
+ QVERIFY(!child4->font().bold());
+ QCOMPARE(child5->font().pointSize(), 15);
+ QVERIFY(!child5->font().bold());
+
+ // Replace the app font for child2. Italic should propagate
+ // but the size should still be ignored. The previous bold
+ // setting is gone.
+ QFont italicSizeFont;
+ italicSizeFont.setItalic(true);
+ italicSizeFont.setPointSize(33);
+ qApp->setFont(italicSizeFont, "QPropagationTestWidget");
+
+ // Check that this propagates correctly.
+ QCOMPARE(root->font(), QApplication::font());
+ QCOMPARE(child0->font().pointSize(), 15);
+ QVERIFY(!child0->font().bold());
+ QVERIFY(!child0->font().italic());
+ QCOMPARE(child1->font().pointSize(), 15);
+ QVERIFY(!child1->font().bold());
+ QVERIFY(!child1->font().italic());
+ QCOMPARE(child2->font().pointSize(), 15);
+ QVERIFY(!child2->font().bold());
+ QVERIFY(child2->font().italic());
+ QCOMPARE(child3->font().pointSize(), 15);
+ QVERIFY(!child3->font().bold());
+ QVERIFY(child3->font().italic());
+ QCOMPARE(child4->font().pointSize(), 15);
+ QVERIFY(!child4->font().bold());
+ QVERIFY(child4->font().italic());
+ QCOMPARE(child5->font().pointSize(), 15);
+ QVERIFY(!child5->font().bold());
+ QVERIFY(child5->font().italic());
+}
+
+void tst_QWidget::palettePropagation()
+{
+ QPalette palette = testWidget->palette();
+ QWidget* childWidget = new QWidget( testWidget );
+ childWidget->show();
+ QCOMPARE( palette, childWidget->palette() );
+
+ palette.setColor( QPalette::Base, Qt::red );
+ testWidget->setPalette( palette );
+ QCOMPARE( palette, testWidget->palette() );
+ QCOMPARE( palette, childWidget->palette() );
+
+ QPalette newPalette = palette;
+ newPalette.setColor( QPalette::Highlight, Qt::green );
+ childWidget->setPalette( newPalette );
+ QWidget* grandChildWidget = new QWidget( childWidget );
+ QCOMPARE( palette, testWidget->palette() );
+ QCOMPARE( newPalette, grandChildWidget->palette() );
+
+ palette.setColor( QPalette::Text, Qt::blue );
+ testWidget->setPalette( palette );
+
+ // the child and grand child should now have merged green
+ // highlight and blue text
+ newPalette.setColor( QPalette::Text, Qt::blue);
+
+ QCOMPARE( newPalette, childWidget->palette() );
+ QCOMPARE( newPalette, grandChildWidget->palette() );
+}
+
+void tst_QWidget::palettePropagation2()
+{
+ // ! Note, the code below is executed in tst_QWidget's constructor.
+ // QPalette palette;
+ // font.setColor(QPalette::ToolTipBase, QColor(12, 13, 14));
+ // font.setColor(QPalette::Text, QColor(21, 22, 23));
+ // qApp->setPalette(palette, "QPropagationTestWidget");
+
+ QWidget *root = new QWidget;
+ QWidget *child0 = new QWidget(root);
+ QWidget *child1 = new QWidget(child0);
+ QWidget *child2 = new QPropagationTestWidget(child1);
+ QWidget *child3 = new QWidget(child2);
+ QWidget *child4 = new QWidget(child3);
+ QWidget *child5 = new QWidget(child4);
+ root->show();
+ QTest::qWait(100);
+
+ // These colors are unlikely to be imposed on the default palette of
+ // QWidget ;-).
+ QColor sysPalText(21, 22, 23);
+ QColor sysPalToolTipBase(12, 13, 14);
+ QColor overridePalText(42, 43, 44);
+ QColor overridePalToolTipBase(45, 46, 47);
+ QColor sysPalButton(99, 98, 97);
+
+ // Check that only the application fonts apply.
+ QPalette appPal = QApplication::palette();
+ QCOMPARE(root->palette(), appPal);
+ QCOMPARE(child0->palette(), appPal);
+ QCOMPARE(child1->palette(), appPal);
+ QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
+ QCOMPARE(child2->palette().color(QPalette::Text), sysPalText);
+ QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
+ QCOMPARE(child3->palette().color(QPalette::Text), sysPalText);
+ QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child4->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
+ QCOMPARE(child4->palette().color(QPalette::Text), sysPalText);
+ QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child5->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
+ QCOMPARE(child5->palette().color(QPalette::Text), sysPalText);
+ QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+
+ // Set child0's Text, and set ToolTipBase on child4.
+ QPalette textPalette;
+ textPalette.setColor(QPalette::Text, overridePalText);
+ child0->setPalette(textPalette);
+ QPalette toolTipPalette;
+ toolTipPalette.setColor(QPalette::ToolTipBase, overridePalToolTipBase);
+ child4->setPalette(toolTipPalette);
+
+ // Check that the above settings propagate correctly.
+ QCOMPARE(root->palette(), appPal);
+ QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child2->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
+ QCOMPARE(child2->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child3->palette().color(QPalette::ToolTipBase), sysPalToolTipBase);
+ QCOMPARE(child3->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+ QCOMPARE(child4->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child5->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+ QCOMPARE(child5->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+
+ // Replace the app palette for child2. Button should propagate but Text
+ // should still be ignored. The previous ToolTipBase setting is gone.
+ QPalette buttonPalette;
+ buttonPalette.setColor(QPalette::ToolTipText, sysPalButton);
+ qApp->setPalette(buttonPalette, "QPropagationTestWidget");
+
+ // Check that the above settings propagate correctly.
+ QCOMPARE(root->palette(), appPal);
+ QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child0->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child1->palette().color(QPalette::ToolTipText), appPal.color(QPalette::ToolTipText));
+ QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child2->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child2->palette().color(QPalette::ToolTipText), sysPalButton);
+ QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child3->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child3->palette().color(QPalette::ToolTipText), sysPalButton);
+ QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+ QCOMPARE(child4->palette().color(QPalette::ToolTipText), sysPalButton);
+ QCOMPARE(child5->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child5->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+ QCOMPARE(child5->palette().color(QPalette::ToolTipText), sysPalButton);
+}
+
+void tst_QWidget::enabledPropagation()
+{
+ QWidget* childWidget = new QWidget( testWidget );
+ childWidget->show();
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( childWidget->isEnabled() );
+
+ testWidget->setEnabled( FALSE );
+ QVERIFY( !testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+
+ testWidget->setDisabled( FALSE );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( childWidget->isEnabled() );
+
+ QWidget* grandChildWidget = new QWidget( childWidget );
+ QVERIFY( grandChildWidget->isEnabled() );
+
+ testWidget->setDisabled( TRUE );
+ QVERIFY( !testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+
+ grandChildWidget->setEnabled( FALSE );
+ testWidget->setEnabled( TRUE );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+
+ grandChildWidget->setEnabled( TRUE );
+ testWidget->setEnabled( FALSE );
+ childWidget->setDisabled( TRUE );
+ testWidget->setEnabled( TRUE );
+ QVERIFY( testWidget->isEnabled() );
+ QVERIFY( !childWidget->isEnabled() );
+ QVERIFY( !grandChildWidget->isEnabled() );
+}
+
+// Drag'n drop disabled in this build.
+#ifndef QT_NO_DRAGANDDROP
+void tst_QWidget::acceptDropsPropagation()
+{
+ QWidget *childWidget = new QWidget(testWidget);
+ childWidget->show();
+ QVERIFY(!testWidget->acceptDrops());
+ QVERIFY(!childWidget->acceptDrops());
+
+ testWidget->setAcceptDrops(true);
+ QVERIFY(testWidget->acceptDrops());
+ QVERIFY(!childWidget->acceptDrops());
+ QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered));
+
+ testWidget->setAcceptDrops(false);
+ QVERIFY(!testWidget->acceptDrops());
+ QVERIFY(!childWidget->acceptDrops());
+ QVERIFY(!childWidget->testAttribute(Qt::WA_DropSiteRegistered));
+
+ QWidget *grandChildWidget = new QWidget(childWidget);
+ QVERIFY(!grandChildWidget->acceptDrops());
+ QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
+
+ testWidget->setAcceptDrops(true);
+ QVERIFY(testWidget->acceptDrops());
+ QVERIFY(!childWidget->acceptDrops());
+ QVERIFY(childWidget->testAttribute(Qt::WA_DropSiteRegistered));
+ QVERIFY(!grandChildWidget->acceptDrops());
+ QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
+
+ grandChildWidget->setAcceptDrops(true);
+ testWidget->setAcceptDrops(false);
+ QVERIFY(!testWidget->acceptDrops());
+ QVERIFY(!childWidget->acceptDrops());
+ QVERIFY(grandChildWidget->acceptDrops());
+ QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
+
+ grandChildWidget->setAcceptDrops(false);
+ QVERIFY(!grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
+ testWidget->setAcceptDrops(true);
+ childWidget->setAcceptDrops(true);
+ testWidget->setAcceptDrops(false);
+ QVERIFY(!testWidget->acceptDrops());
+ QVERIFY(childWidget->acceptDrops());
+ QVERIFY(!grandChildWidget->acceptDrops());
+ QVERIFY(grandChildWidget->testAttribute(Qt::WA_DropSiteRegistered));
+}
+#endif
+
+void tst_QWidget::isEnabledTo()
+{
+ QWidget* childWidget = new QWidget( testWidget );
+ QWidget* grandChildWidget = new QWidget( childWidget );
+
+ QVERIFY( childWidget->isEnabledTo( testWidget ) );
+ QVERIFY( grandChildWidget->isEnabledTo( testWidget ) );
+
+ childWidget->setEnabled( FALSE );
+ QVERIFY( !childWidget->isEnabledTo( testWidget ) );
+ QVERIFY( grandChildWidget->isEnabledTo( childWidget ) );
+ QVERIFY( !grandChildWidget->isEnabledTo( testWidget ) );
+}
+
+void tst_QWidget::visible()
+{
+ // Ensure that the testWidget is hidden for this test at the
+ // start
+
+ testWidget->hide();
+ QVERIFY( !testWidget->isVisible() );
+ QWidget* childWidget = new QWidget( testWidget );
+ QVERIFY( !childWidget->isVisible() );
+
+ testWidget->show();
+ QVERIFY( testWidget->isVisible() );
+ QVERIFY( childWidget->isVisible() );
+
+ QWidget* grandChildWidget = new QWidget( childWidget );
+ QVERIFY( !grandChildWidget->isVisible() );
+ grandChildWidget->show();
+ QVERIFY( grandChildWidget->isVisible() );
+
+ grandChildWidget->hide();
+ testWidget->hide();
+ testWidget->show();
+ QVERIFY( !grandChildWidget->isVisible() );
+ QVERIFY( testWidget->isVisible() );
+ QVERIFY( childWidget->isVisible() );
+
+ grandChildWidget->show();
+ childWidget->hide();
+ testWidget->hide();
+ testWidget->show();
+ QVERIFY( testWidget->isVisible() );
+ QVERIFY( !childWidget->isVisible() );
+ QVERIFY( !grandChildWidget->isVisible() );
+
+ grandChildWidget->show();
+ QVERIFY( !grandChildWidget->isVisible() );
+}
+
+void tst_QWidget::setLocale()
+{
+ QWidget w;
+ QCOMPARE(w.locale(), QLocale());
+
+ w.setLocale(QLocale::Italian);
+ QCOMPARE(w.locale(), QLocale(QLocale::Italian));
+
+ QWidget child1(&w);
+ QCOMPARE(child1.locale(), QLocale(QLocale::Italian));
+
+ w.unsetLocale();
+ QCOMPARE(w.locale(), QLocale());
+ QCOMPARE(child1.locale(), QLocale());
+
+ w.setLocale(QLocale::French);
+ QCOMPARE(w.locale(), QLocale(QLocale::French));
+ QCOMPARE(child1.locale(), QLocale(QLocale::French));
+
+ child1.setLocale(QLocale::Italian);
+ QCOMPARE(w.locale(), QLocale(QLocale::French));
+ QCOMPARE(child1.locale(), QLocale(QLocale::Italian));
+
+ child1.unsetLocale();
+ QCOMPARE(w.locale(), QLocale(QLocale::French));
+ QCOMPARE(child1.locale(), QLocale(QLocale::French));
+
+ QWidget child2;
+ QCOMPARE(child2.locale(), QLocale());
+ child2.setParent(&w);
+ QCOMPARE(child2.locale(), QLocale(QLocale::French));
+}
+
+void tst_QWidget::visible_setWindowOpacity()
+{
+ testWidget->hide();
+ QVERIFY( !testWidget->isVisible() );
+ testWidget->setWindowOpacity(0.5);
+#ifdef Q_OS_WIN
+ QVERIFY(::IsWindowVisible(winHandleOf(testWidget)) == FALSE);
+#endif
+ testWidget->setWindowOpacity(1.0);
+}
+
+void tst_QWidget::isVisibleTo()
+{
+ // Ensure that the testWidget is hidden for this test at the
+ // start
+
+ testWidget->hide();
+ QWidget* childWidget = new QWidget( testWidget );
+ QVERIFY( childWidget->isVisibleTo( testWidget ) );
+ childWidget->hide();
+ QVERIFY( !childWidget->isVisibleTo( testWidget ) );
+
+ QWidget* grandChildWidget = new QWidget( childWidget );
+ QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) );
+ QVERIFY( grandChildWidget->isVisibleTo( childWidget ) );
+
+ testWidget->show();
+ childWidget->show();
+
+ QVERIFY( childWidget->isVisibleTo( testWidget ) );
+ grandChildWidget->hide();
+ QVERIFY( !grandChildWidget->isVisibleTo( childWidget ) );
+ QVERIFY( !grandChildWidget->isVisibleTo( testWidget ) );
+
+}
+
+void tst_QWidget::isHidden()
+{
+ // Ensure that the testWidget is hidden for this test at the
+ // start
+
+ testWidget->hide();
+ QVERIFY( testWidget->isHidden() );
+ QWidget* childWidget = new QWidget( testWidget );
+ QVERIFY( !childWidget->isHidden() );
+
+ testWidget->show();
+ QVERIFY( !testWidget->isHidden() );
+ QVERIFY( !childWidget->isHidden() );
+
+ QWidget* grandChildWidget = new QWidget( childWidget );
+ QVERIFY( grandChildWidget->isHidden() );
+ grandChildWidget->show();
+ QVERIFY( !grandChildWidget->isHidden() );
+
+ grandChildWidget->hide();
+ testWidget->hide();
+ testWidget->show();
+ QVERIFY( grandChildWidget->isHidden() );
+ QVERIFY( !testWidget->isHidden() );
+ QVERIFY( !childWidget->isHidden() );
+
+ grandChildWidget->show();
+ childWidget->hide();
+ testWidget->hide();
+ testWidget->show();
+ QVERIFY( !testWidget->isHidden() );
+ QVERIFY( childWidget->isHidden() );
+ QVERIFY( !grandChildWidget->isHidden() );
+
+ grandChildWidget->show();
+ QVERIFY( !grandChildWidget->isHidden() );
+}
+
+void tst_QWidget::fonts()
+{
+ // Tests setFont(), ownFont() and unsetFont()
+ QWidget* cleanTestWidget = new QWidget( testWidget );
+ QFont originalFont = cleanTestWidget->font();
+
+ QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
+ cleanTestWidget->setFont(QFont());
+ QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
+
+ QFont newFont( "times", 18 );
+ cleanTestWidget->setFont( newFont );
+ newFont = newFont.resolve( testWidget->font() );
+
+ QVERIFY( cleanTestWidget->testAttribute(Qt::WA_SetFont) );
+ QVERIFY( cleanTestWidget->font() == newFont );
+
+ cleanTestWidget->setFont(QFont());
+ QVERIFY( !cleanTestWidget->testAttribute(Qt::WA_SetFont) );
+ QVERIFY( cleanTestWidget->font() == originalFont );
+}
+
+void tst_QWidget::mapFromAndTo_data()
+{
+ QTest::addColumn<bool>("windowHidden");
+ QTest::addColumn<bool>("subWindow1Hidden");
+ QTest::addColumn<bool>("subWindow2Hidden");
+ QTest::addColumn<bool>("subSubWindowHidden");
+ QTest::addColumn<bool>("windowMinimized");
+ QTest::addColumn<bool>("subWindow1Minimized");
+
+ QTest::newRow("window 1 sub1 1 sub2 1 subsub 1") << false << false << false << false << false << false;
+ QTest::newRow("window 0 sub1 1 sub2 1 subsub 1") << true << false << false << false << false << false;
+ QTest::newRow("window 1 sub1 0 sub2 1 subsub 1") << false << true << false << false << false << false;
+ QTest::newRow("window 0 sub1 0 sub2 1 subsub 1") << true << true << false << false << false << false;
+ QTest::newRow("window 1 sub1 1 sub2 0 subsub 1") << false << false << true << false << false << false;
+ QTest::newRow("window 0 sub1 1 sub2 0 subsub 1") << true << false << true << false << false << false;
+ QTest::newRow("window 1 sub1 0 sub2 0 subsub 1") << false << true << true << false << false << false;
+ QTest::newRow("window 0 sub1 0 sub2 0 subsub 1") << true << true << true << false << false << false;
+ QTest::newRow("window 1 sub1 1 sub2 1 subsub 0") << false << false << false << true << false << false;
+ QTest::newRow("window 0 sub1 1 sub2 1 subsub 0") << true << false << false << true << false << false;
+ QTest::newRow("window 1 sub1 0 sub2 1 subsub 0") << false << true << false << true << false << false;
+ QTest::newRow("window 0 sub1 0 sub2 1 subsub 0") << true << true << false << true << false << false;
+ QTest::newRow("window 1 sub1 1 sub2 0 subsub 0") << false << false << true << true << false << false;
+ QTest::newRow("window 0 sub1 1 sub2 0 subsub 0") << true << false << true << true << false << false;
+ QTest::newRow("window 1 sub1 0 sub2 0 subsub 0") << false << true << true << true << false << false;
+ QTest::newRow("window 0 sub1 0 sub2 0 subsub 0") << true << true << true << true << false << false;
+ QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 windowMinimized") << false << false << false << false << true << false;
+ QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 windowMinimized") << true << false << false << false << true << false;
+ QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 windowMinimized") << false << true << false << false << true << false;
+ QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 windowMinimized") << true << true << false << false << true << false;
+ QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 windowMinimized") << false << false << true << false << true << false;
+ QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 windowMinimized") << true << false << true << false << true << false;
+ QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 windowMinimized") << false << true << true << false << true << false;
+ QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 windowMinimized") << true << true << true << false << true << false;
+ QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 windowMinimized") << false << false << false << true << true << false;
+ QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 windowMinimized") << true << false << false << true << true << false;
+ QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 windowMinimized") << false << true << false << true << true << false;
+ QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 windowMinimized") << true << true << false << true << true << false;
+ QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 windowMinimized") << false << false << true << true << true << false;
+ QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 windowMinimized") << true << false << true << true << true << false;
+ QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 windowMinimized") << false << true << true << true << true << false;
+ QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 windowMinimized") << true << true << true << true << true << false;
+ QTest::newRow("window 1 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << false << false << false << false << false << true;
+ QTest::newRow("window 0 sub1 1 sub2 1 subsub 1 subWindow1Minimized") << true << false << false << false << false << true;
+ QTest::newRow("window 1 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << false << true << false << false << false << true;
+ QTest::newRow("window 0 sub1 0 sub2 1 subsub 1 subWindow1Minimized") << true << true << false << false << false << true;
+ QTest::newRow("window 1 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << false << false << true << false << false << true;
+ QTest::newRow("window 0 sub1 1 sub2 0 subsub 1 subWindow1Minimized") << true << false << true << false << false << true;
+ QTest::newRow("window 1 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << false << true << true << false << false << true;
+ QTest::newRow("window 0 sub1 0 sub2 0 subsub 1 subWindow1Minimized") << true << true << true << false << false << true;
+ QTest::newRow("window 1 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << false << false << false << true << false << true;
+ QTest::newRow("window 0 sub1 1 sub2 1 subsub 0 subWindow1Minimized") << true << false << false << true << false << true;
+ QTest::newRow("window 1 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << false << true << false << true << false << true;
+ QTest::newRow("window 0 sub1 0 sub2 1 subsub 0 subWindow1Minimized") << true << true << false << true << false << true;
+ QTest::newRow("window 1 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << false << false << true << true << false << true;
+ QTest::newRow("window 0 sub1 1 sub2 0 subsub 0 subWindow1Minimized") << true << false << true << true << false << true;
+ QTest::newRow("window 1 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << false << true << true << true << false << true;
+ QTest::newRow("window 0 sub1 0 sub2 0 subsub 0 subWindow1Minimized") << true << true << true << true << false << true;
+
+
+}
+
+void tst_QWidget::mapFromAndTo()
+{
+ QFETCH(bool, windowHidden);
+ QFETCH(bool, subWindow1Hidden);
+ QFETCH(bool, subWindow2Hidden);
+ QFETCH(bool, subSubWindowHidden);
+ QFETCH(bool, windowMinimized);
+ QFETCH(bool, subWindow1Minimized);
+
+ // create a toplevel and two overlapping siblings
+ QWidget window;
+ window.setWindowFlags(window.windowFlags() | Qt::X11BypassWindowManagerHint);
+ QWidget *subWindow1 = new QWidget(&window);
+ QWidget *subWindow2 = new QWidget(&window);
+ QWidget *subSubWindow = new QWidget(subWindow1);
+
+ // set their geometries
+ window.setGeometry(100, 100, 100, 100);
+ subWindow1->setGeometry(50, 50, 100, 100);
+ subWindow2->setGeometry(75, 75, 100, 100);
+ subSubWindow->setGeometry(10, 10, 10, 10);
+
+#if !defined (Q_OS_WINCE) //still no proper minimizing
+ //update visibility
+ if (windowMinimized) {
+ if (!windowHidden) {
+ window.showMinimized();
+ QVERIFY(window.isMinimized());
+ }
+ } else {
+ window.setVisible(!windowHidden);
+ }
+ if (subWindow1Minimized) {
+ subWindow1->hide();
+ subWindow1->showMinimized();
+ QVERIFY(subWindow1->isMinimized());
+ } else {
+ subWindow1->setVisible(!subWindow1Hidden);
+ }
+#else
+ Q_UNUSED(windowHidden);
+ Q_UNUSED(subWindow1Hidden);
+ Q_UNUSED(windowMinimized);
+ Q_UNUSED(subWindow1Minimized);
+#endif
+
+ subWindow2->setVisible(!subWindow2Hidden);
+ subSubWindow->setVisible(!subSubWindowHidden);
+
+ // window
+ QCOMPARE(window.mapToGlobal(QPoint(0, 0)), QPoint(100, 100));
+ QCOMPARE(window.mapToGlobal(QPoint(10, 0)), QPoint(110, 100));
+ QCOMPARE(window.mapToGlobal(QPoint(0, 10)), QPoint(100, 110));
+ QCOMPARE(window.mapToGlobal(QPoint(-10, 0)), QPoint(90, 100));
+ QCOMPARE(window.mapToGlobal(QPoint(0, -10)), QPoint(100, 90));
+ QCOMPARE(window.mapToGlobal(QPoint(100, 100)), QPoint(200, 200));
+ QCOMPARE(window.mapToGlobal(QPoint(110, 100)), QPoint(210, 200));
+ QCOMPARE(window.mapToGlobal(QPoint(100, 110)), QPoint(200, 210));
+ QCOMPARE(window.mapFromGlobal(QPoint(100, 100)), QPoint(0, 0));
+ QCOMPARE(window.mapFromGlobal(QPoint(110, 100)), QPoint(10, 0));
+ QCOMPARE(window.mapFromGlobal(QPoint(100, 110)), QPoint(0, 10));
+ QCOMPARE(window.mapFromGlobal(QPoint(90, 100)), QPoint(-10, 0));
+ QCOMPARE(window.mapFromGlobal(QPoint(100, 90)), QPoint(0, -10));
+ QCOMPARE(window.mapFromGlobal(QPoint(200, 200)), QPoint(100, 100));
+ QCOMPARE(window.mapFromGlobal(QPoint(210, 200)), QPoint(110, 100));
+ QCOMPARE(window.mapFromGlobal(QPoint(200, 210)), QPoint(100, 110));
+ QCOMPARE(window.mapToParent(QPoint(0, 0)), QPoint(100, 100));
+ QCOMPARE(window.mapToParent(QPoint(10, 0)), QPoint(110, 100));
+ QCOMPARE(window.mapToParent(QPoint(0, 10)), QPoint(100, 110));
+ QCOMPARE(window.mapToParent(QPoint(-10, 0)), QPoint(90, 100));
+ QCOMPARE(window.mapToParent(QPoint(0, -10)), QPoint(100, 90));
+ QCOMPARE(window.mapToParent(QPoint(100, 100)), QPoint(200, 200));
+ QCOMPARE(window.mapToParent(QPoint(110, 100)), QPoint(210, 200));
+ QCOMPARE(window.mapToParent(QPoint(100, 110)), QPoint(200, 210));
+ QCOMPARE(window.mapFromParent(QPoint(100, 100)), QPoint(0, 0));
+ QCOMPARE(window.mapFromParent(QPoint(110, 100)), QPoint(10, 0));
+ QCOMPARE(window.mapFromParent(QPoint(100, 110)), QPoint(0, 10));
+ QCOMPARE(window.mapFromParent(QPoint(90, 100)), QPoint(-10, 0));
+ QCOMPARE(window.mapFromParent(QPoint(100, 90)), QPoint(0, -10));
+ QCOMPARE(window.mapFromParent(QPoint(200, 200)), QPoint(100, 100));
+ QCOMPARE(window.mapFromParent(QPoint(210, 200)), QPoint(110, 100));
+ QCOMPARE(window.mapFromParent(QPoint(200, 210)), QPoint(100, 110));
+
+ // first subwindow
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 0)), QPoint(150, 150));
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(10, 0)), QPoint(160, 150));
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(0, 10)), QPoint(150, 160));
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(-10, 0)), QPoint(140, 150));
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(0, -10)), QPoint(150, 140));
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 100)), QPoint(250, 250));
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(110, 100)), QPoint(260, 250));
+ QCOMPARE(subWindow1->mapToGlobal(QPoint(100, 110)), QPoint(250, 260));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 150)), QPoint(0, 0));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(160, 150)), QPoint(10, 0));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 160)), QPoint(0, 10));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(140, 150)), QPoint(-10, 0));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(150, 140)), QPoint(0, -10));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 250)), QPoint(100, 100));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(260, 250)), QPoint(110, 100));
+ QCOMPARE(subWindow1->mapFromGlobal(QPoint(250, 260)), QPoint(100, 110));
+ QCOMPARE(subWindow1->mapToParent(QPoint(0, 0)), QPoint(50, 50));
+ QCOMPARE(subWindow1->mapToParent(QPoint(10, 0)), QPoint(60, 50));
+ QCOMPARE(subWindow1->mapToParent(QPoint(0, 10)), QPoint(50, 60));
+ QCOMPARE(subWindow1->mapToParent(QPoint(-10, 0)), QPoint(40, 50));
+ QCOMPARE(subWindow1->mapToParent(QPoint(0, -10)), QPoint(50, 40));
+ QCOMPARE(subWindow1->mapToParent(QPoint(100, 100)), QPoint(150, 150));
+ QCOMPARE(subWindow1->mapToParent(QPoint(110, 100)), QPoint(160, 150));
+ QCOMPARE(subWindow1->mapToParent(QPoint(100, 110)), QPoint(150, 160));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(50, 50)), QPoint(0, 0));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(60, 50)), QPoint(10, 0));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(50, 60)), QPoint(0, 10));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(40, 50)), QPoint(-10, 0));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(50, 40)), QPoint(0, -10));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(150, 150)), QPoint(100, 100));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(160, 150)), QPoint(110, 100));
+ QCOMPARE(subWindow1->mapFromParent(QPoint(150, 160)), QPoint(100, 110));
+
+ // subsubwindow
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 0)), QPoint(160, 160));
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(10, 0)), QPoint(170, 160));
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, 10)), QPoint(160, 170));
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(-10, 0)), QPoint(150, 160));
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(0, -10)), QPoint(160, 150));
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 100)), QPoint(260, 260));
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(110, 100)), QPoint(270, 260));
+ QCOMPARE(subSubWindow->mapToGlobal(QPoint(100, 110)), QPoint(260, 270));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 160)), QPoint(0, 0));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(170, 160)), QPoint(10, 0));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 170)), QPoint(0, 10));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(150, 160)), QPoint(-10, 0));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(160, 150)), QPoint(0, -10));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 260)), QPoint(100, 100));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(270, 260)), QPoint(110, 100));
+ QCOMPARE(subSubWindow->mapFromGlobal(QPoint(260, 270)), QPoint(100, 110));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(0, 0)), QPoint(10, 10));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(10, 0)), QPoint(20, 10));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(0, 10)), QPoint(10, 20));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(-10, 0)), QPoint(0, 10));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(0, -10)), QPoint(10, 0));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(100, 100)), QPoint(110, 110));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(110, 100)), QPoint(120, 110));
+ QCOMPARE(subSubWindow->mapToParent(QPoint(100, 110)), QPoint(110, 120));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 10)), QPoint(0, 0));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(20, 10)), QPoint(10, 0));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 20)), QPoint(0, 10));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(0, 10)), QPoint(-10, 0));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(10, 0)), QPoint(0, -10));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 110)), QPoint(100, 100));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(120, 110)), QPoint(110, 100));
+ QCOMPARE(subSubWindow->mapFromParent(QPoint(110, 120)), QPoint(100, 110));
+}
+
+void tst_QWidget::focusChainOnReparent()
+{
+ QWidget window;
+ QWidget *child1 = new QWidget(&window);
+ QWidget *child2 = new QWidget(&window);
+ QWidget *child3 = new QWidget(&window);
+ QWidget *child21 = new QWidget(child2);
+ QWidget *child22 = new QWidget(child2);
+ QWidget *child4 = new QWidget(&window);
+
+ QWidget *expectedOriginalChain[8] = {&window, child1, child2, child3, child21, child22, child4, &window};
+ QWidget *w = &window;
+ for (int i = 0; i <8; ++i) {
+ QCOMPARE(w, expectedOriginalChain[i]);
+ w = w->nextInFocusChain();
+ }
+ for (int i = 7; i >= 0; --i) {
+ w = w->previousInFocusChain();
+ QCOMPARE(w, expectedOriginalChain[i]);
+ }
+
+ QWidget window2;
+ child2->setParent(&window2);
+
+ QWidget *expectedNewChain[5] = {&window2, child2, child21, child22, &window2};
+ w = &window2;
+ for (int i = 0; i <5; ++i) {
+ QCOMPARE(w, expectedNewChain[i]);
+ w = w->nextInFocusChain();
+ }
+ for (int i = 4; i >= 0; --i) {
+ w = w->previousInFocusChain();
+ QCOMPARE(w, expectedNewChain[i]);
+ }
+
+ QWidget *expectedOldChain[5] = {&window, child1, child3, child4, &window};
+ w = &window;
+ for (int i = 0; i <5; ++i) {
+ QCOMPARE(w, expectedOldChain[i]);
+ w = w->nextInFocusChain();
+ }
+ for (int i = 4; i >= 0; --i) {
+ w = w->previousInFocusChain();
+ QCOMPARE(w, expectedOldChain[i]);
+ }
+}
+
+
+void tst_QWidget::focusChainOnHide()
+{
+ testWidget->hide(); // We do not want to get disturbed by other widgets
+ // focus should move to the next widget in the focus chain when we hide it.
+ QWidget *parent = new QWidget();
+ parent->setObjectName(QLatin1String("Parent"));
+ parent->setFocusPolicy(Qt::StrongFocus);
+ QWidget *child = new QWidget(parent);
+ child->setObjectName(QLatin1String("child"));
+ child->setFocusPolicy(Qt::StrongFocus);
+ QWidget::setTabOrder(child, parent);
+
+ parent->show();
+ qApp->setActiveWindow(parent->window());
+ child->activateWindow();
+ child->setFocus();
+ qApp->processEvents();
+
+ QTRY_COMPARE(child->hasFocus(), true);
+ child->hide();
+ qApp->processEvents();
+
+ QTRY_COMPARE(parent->hasFocus(), true);
+ QCOMPARE(parent, qApp->focusWidget());
+
+ delete parent;
+ testWidget->show(); //don't disturb later tests
+}
+
+class Container : public QWidget
+{
+public:
+ QVBoxLayout* box;
+
+ Container()
+ {
+ box = new QVBoxLayout(this);
+ //(new QVBoxLayout(this))->setAutoAdd(true);
+ }
+
+ void tab()
+ {
+ focusNextPrevChild(TRUE);
+ }
+
+ void backTab()
+ {
+ focusNextPrevChild(FALSE);
+ }
+};
+
+class Composite : public QFrame
+{
+public:
+ Composite(QWidget* parent = 0, const char* name = 0)
+ : QFrame(parent)
+ {
+ setObjectName(name);
+ //QHBoxLayout* hbox = new QHBoxLayout(this, 2, 0);
+ //hbox->setAutoAdd(true);
+ QHBoxLayout* hbox = new QHBoxLayout(this);
+
+ lineEdit = new QLineEdit(this);
+ hbox->addWidget(lineEdit);
+
+ button = new QPushButton(this);
+ hbox->addWidget(button);
+ button->setFocusPolicy( Qt::NoFocus );
+
+ setFocusProxy( lineEdit );
+ setFocusPolicy( Qt::StrongFocus );
+
+ setTabOrder(lineEdit, button);
+ }
+
+private:
+ QLineEdit* lineEdit;
+ QPushButton* button;
+};
+
+#define NUM_WIDGETS 4
+
+void tst_QWidget::setTabOrder()
+{
+ QTest::qWait(100);
+
+ Container container;
+
+ Composite* comp[NUM_WIDGETS];
+
+ QLineEdit *firstEdit = new QLineEdit(&container);
+ container.box->addWidget(firstEdit);
+
+ int i = 0;
+ for(i = 0; i < NUM_WIDGETS; i++) {
+ comp[i] = new Composite(&container);
+ container.box->addWidget(comp[i]);
+ }
+
+ QLineEdit *lastEdit = new QLineEdit(&container);
+ container.box->addWidget(lastEdit);
+
+ container.setTabOrder(lastEdit, comp[NUM_WIDGETS-1]);
+ for(i = NUM_WIDGETS-1; i > 0; i--) {
+ container.setTabOrder(comp[i], comp[i-1]);
+ }
+ container.setTabOrder(comp[0], firstEdit);
+
+ int current = NUM_WIDGETS-1;
+ lastEdit->setFocus();
+
+ container.show();
+ container.activateWindow();
+ qApp->setActiveWindow(&container);
+#ifdef Q_WS_X11
+ QTest::qWaitForWindowShown(&container);
+ QTest::qWait(50);
+#endif
+
+ QTest::qWait(100);
+
+ QTRY_VERIFY(lastEdit->hasFocus());
+ container.tab();
+ do {
+ QVERIFY(comp[current]->focusProxy()->hasFocus());
+ container.tab();
+ current--;
+ } while (current >= 0);
+
+ QVERIFY(firstEdit->hasFocus());
+}
+
+#ifdef Q_WS_WIN
+void tst_QWidget::activation()
+{
+ Q_CHECK_PAINTEVENTS
+
+#if defined(Q_OS_WINCE)
+ int waitTime = 1000;
+#else
+ int waitTime = 100;
+#endif
+
+#ifdef Q_OS_WINCE
+ qApp->processEvents();
+#endif
+ QWidget widget1;
+ widget1.setWindowTitle("Widget1");
+
+ QWidget widget2;
+ widget2.setWindowTitle("Widget2");
+
+ widget1.show();
+ widget2.show();
+
+ QTest::qWait(waitTime);
+ QVERIFY(qApp->activeWindow() == &widget2);
+ widget2.showMinimized();
+ QTest::qWait(waitTime);
+
+ QVERIFY(qApp->activeWindow() == &widget1);
+ widget2.showMaximized();
+ QTest::qWait(waitTime);
+ QVERIFY(qApp->activeWindow() == &widget2);
+ widget2.showMinimized();
+ QTest::qWait(waitTime);
+ QVERIFY(qApp->activeWindow() == &widget1);
+ widget2.showNormal();
+ QTest::qWait(waitTime);
+#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
+ if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
+ QEXPECT_FAIL("", "MS introduced new behavior after XP", Continue);
+#endif
+ QTest::qWait(waitTime);
+ QVERIFY(qApp->activeWindow() == &widget2);
+ widget2.hide();
+ QTest::qWait(waitTime);
+ QVERIFY(qApp->activeWindow() == &widget1);
+}
+#endif
+
+// Many window managers do not support window state properly, which causes this test to fail.
+#ifndef Q_WS_X11
+void tst_QWidget::windowState()
+{
+#ifdef Q_OS_WINCE_WM
+ QPoint pos(500, 500);
+ QSize size(200, 200);
+ if (qt_wince_is_smartphone()) { //small screen
+ pos = QPoint(10,10);
+ size = QSize(100,100);
+ }
+#else
+ const QPoint pos(500, 500);
+ const QSize size(200, 200);
+#endif
+
+ QWidget widget1;
+ widget1.move(pos);
+ widget1.resize(size);
+ QCOMPARE(widget1.pos(), pos);
+ QCOMPARE(widget1.size(), size);
+ QTest::qWait(100);
+ widget1.setWindowTitle("Widget1");
+ QCOMPARE(widget1.pos(), pos);
+ QCOMPARE(widget1.size(), size);
+
+#define VERIFY_STATE(s) QCOMPARE(int(widget1.windowState() & stateMask), int(s))
+
+ const int stateMask = Qt::WindowMaximized|Qt::WindowMinimized|Qt::WindowFullScreen;
+
+ widget1.setWindowState(Qt::WindowMaximized);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowMaximized);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
+
+ widget1.show();
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowMaximized);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(100);
+ QVERIFY(!(widget1.windowState() & Qt::WindowMaximized));
+ QTRY_COMPARE(widget1.pos(), pos);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
+
+ widget1.setWindowState(Qt::WindowMinimized);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowMinimized);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
+
+ widget1.setWindowState(widget1.windowState() | Qt::WindowMaximized);
+ QTest::qWait(100);
+ VERIFY_STATE((Qt::WindowMinimized|Qt::WindowMaximized));
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowMaximized);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(100);
+ QVERIFY(!(widget1.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized)));
+ QTRY_COMPARE(widget1.pos(), pos);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
+
+ widget1.setWindowState(Qt::WindowFullScreen);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowFullScreen);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
+ QTest::qWait(100);
+ VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMinimized));
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowFullScreen);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
+
+ widget1.setWindowState(Qt::WindowNoState);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowNoState);
+ QTRY_COMPARE(widget1.pos(), pos);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
+
+ widget1.setWindowState(Qt::WindowFullScreen);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowFullScreen);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(100);
+ VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
+ QTest::qWait(100);
+ VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized|Qt::WindowMinimized));
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMinimized);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMinimized);
+ QTest::qWait(100);
+ VERIFY_STATE((Qt::WindowFullScreen|Qt::WindowMaximized));
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowFullScreen);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowFullScreen);
+ QTest::qWait(100);
+ VERIFY_STATE(Qt::WindowMaximized);
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowMaximized);
+
+ widget1.setWindowState(widget1.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(100);
+ QVERIFY(!(widget1.windowState() & stateMask));
+ QCOMPARE(widget1.windowHandle()->windowState(), Qt::WindowNoState);
+
+ QTRY_COMPARE(widget1.pos(), pos);
+ QTRY_COMPARE(widget1.size(), size);
+}
+#endif
+
+void tst_QWidget::showMaximized()
+{
+ QWidget plain;
+ QHBoxLayout *layout;
+ layout = new QHBoxLayout;
+ QWidget layouted;
+ QLineEdit le;
+ QLineEdit le2;
+ QLineEdit le3;
+
+ layout->addWidget(&le);
+ layout->addWidget(&le2);
+ layout->addWidget(&le3);
+
+ layouted.setLayout(layout);
+
+ plain.showMaximized();
+ QVERIFY(plain.windowState() & Qt::WindowMaximized);
+
+ plain.showNormal();
+ QVERIFY(!(plain.windowState() & Qt::WindowMaximized));
+
+ layouted.showMaximized();
+ QVERIFY(layouted.windowState() & Qt::WindowMaximized);
+
+ layouted.showNormal();
+ QVERIFY(!(layouted.windowState() & Qt::WindowMaximized));
+
+#if !defined(Q_WS_QWS) && !defined(Q_OS_WINCE) && !defined(Q_WS_QPA)
+//embedded may choose a different size to fit on the screen.
+ QCOMPARE(layouted.size(), layouted.sizeHint());
+#endif
+ layouted.showMaximized();
+ QVERIFY(layouted.isMaximized());
+ QVERIFY(layouted.isVisible());
+
+ layouted.hide();
+ QVERIFY(layouted.isMaximized());
+ QVERIFY(!layouted.isVisible());
+
+ layouted.showMaximized();
+ QVERIFY(layouted.isMaximized());
+ QVERIFY(layouted.isVisible());
+
+ layouted.showMinimized();
+ QVERIFY(layouted.isMinimized());
+ QVERIFY(layouted.isMaximized());
+
+ layouted.showMaximized();
+ QVERIFY(!layouted.isMinimized());
+ QVERIFY(layouted.isMaximized());
+ QVERIFY(layouted.isVisible());
+
+ layouted.showMinimized();
+ QVERIFY(layouted.isMinimized());
+ QVERIFY(layouted.isMaximized());
+
+ layouted.showMaximized();
+ QVERIFY(!layouted.isMinimized());
+ QVERIFY(layouted.isMaximized());
+ QVERIFY(layouted.isVisible());
+
+ {
+ QWidget frame;
+ QWidget widget(&frame);
+ widget.showMaximized();
+ QVERIFY(widget.isMaximized());
+ }
+
+ {
+ QWidget widget;
+ widget.setGeometry(0, 0, 10, 10);
+ widget.showMaximized();
+ QTRY_VERIFY(widget.size().width() > 20 && widget.size().height() > 20);
+ }
+}
+
+void tst_QWidget::showFullScreen()
+{
+ QWidget plain;
+ QHBoxLayout *layout;
+ QWidget layouted;
+ QLineEdit le;
+ QLineEdit le2;
+ QLineEdit le3;
+ layout = new QHBoxLayout;
+
+ layout->addWidget(&le);
+ layout->addWidget(&le2);
+ layout->addWidget(&le3);
+
+ layouted.setLayout(layout);
+
+ plain.showFullScreen();
+ QVERIFY(plain.windowState() & Qt::WindowFullScreen);
+
+ plain.showNormal();
+ QVERIFY(!(plain.windowState() & Qt::WindowFullScreen));
+
+ layouted.showFullScreen();
+ QVERIFY(layouted.windowState() & Qt::WindowFullScreen);
+
+ layouted.showNormal();
+ QVERIFY(!(layouted.windowState() & Qt::WindowFullScreen));
+
+#if !defined(Q_WS_QWS) && !defined(Q_OS_WINCE) && !defined(Q_WS_QPA)
+//embedded may choose a different size to fit on the screen.
+ QCOMPARE(layouted.size(), layouted.sizeHint());
+#endif
+
+ layouted.showFullScreen();
+ QVERIFY(layouted.isFullScreen());
+ QVERIFY(layouted.isVisible());
+
+ layouted.hide();
+ QVERIFY(layouted.isFullScreen());
+ QVERIFY(!layouted.isVisible());
+
+ layouted.showFullScreen();
+ QVERIFY(layouted.isFullScreen());
+ QVERIFY(layouted.isVisible());
+
+ layouted.showMinimized();
+ QVERIFY(layouted.isMinimized());
+ QVERIFY(layouted.isFullScreen());
+
+ layouted.showFullScreen();
+ QVERIFY(!layouted.isMinimized());
+ QVERIFY(layouted.isFullScreen());
+ QVERIFY(layouted.isVisible());
+
+ layouted.showMinimized();
+ QVERIFY(layouted.isMinimized());
+ QVERIFY(layouted.isFullScreen());
+
+ layouted.showFullScreen();
+ QVERIFY(!layouted.isMinimized());
+ QVERIFY(layouted.isFullScreen());
+ QVERIFY(layouted.isVisible());
+
+ {
+ QWidget frame;
+ QWidget widget(&frame);
+ widget.showFullScreen();
+ QVERIFY(widget.isFullScreen());
+ }
+}
+
+class ResizeWidget : public QWidget {
+public:
+ ResizeWidget(QWidget *p = 0) : QWidget(p)
+ {
+ m_resizeEventCount = 0;
+ }
+protected:
+ void resizeEvent(QResizeEvent *e){
+ QCOMPARE(size(), e->size());
+ ++m_resizeEventCount;
+ }
+
+public:
+ int m_resizeEventCount;
+};
+
+void tst_QWidget::resizeEvent()
+{
+ {
+ QWidget wParent;
+ ResizeWidget wChild(&wParent);
+ wParent.show();
+ QCOMPARE (wChild.m_resizeEventCount, 1); // initial resize event before paint
+ wParent.hide();
+ QSize safeSize(640,480);
+ if (wChild.size() == safeSize)
+ safeSize.setWidth(639);
+ wChild.resize(safeSize);
+ QCOMPARE (wChild.m_resizeEventCount, 1);
+ wParent.show();
+ QCOMPARE (wChild.m_resizeEventCount, 2);
+ }
+
+ {
+ ResizeWidget wTopLevel;
+ wTopLevel.show();
+ QCOMPARE (wTopLevel.m_resizeEventCount, 1); // initial resize event before paint for toplevels
+ wTopLevel.hide();
+ QSize safeSize(640,480);
+ if (wTopLevel.size() == safeSize)
+ safeSize.setWidth(639);
+ wTopLevel.resize(safeSize);
+ QCOMPARE (wTopLevel.m_resizeEventCount, 1);
+ wTopLevel.show();
+ QCOMPARE (wTopLevel.m_resizeEventCount, 2);
+ }
+}
+
+void tst_QWidget::showMinimized()
+{
+ QWidget plain;
+ plain.move(100, 100);
+ plain.resize(200, 200);
+ QPoint pos = plain.pos();
+
+ plain.showMinimized();
+ QVERIFY(plain.isMinimized());
+ QVERIFY(plain.isVisible());
+ QCOMPARE(plain.pos(), pos);
+
+ plain.showNormal();
+ QVERIFY(!plain.isMinimized());
+ QVERIFY(plain.isVisible());
+ QCOMPARE(plain.pos(), pos);
+
+ plain.showMinimized();
+ QVERIFY(plain.isMinimized());
+ QVERIFY(plain.isVisible());
+ QCOMPARE(plain.pos(), pos);
+
+ plain.hide();
+ QVERIFY(plain.isMinimized());
+ QVERIFY(!plain.isVisible());
+
+ plain.showMinimized();
+ QVERIFY(plain.isMinimized());
+ QVERIFY(plain.isVisible());
+
+ plain.setGeometry(200, 200, 300, 300);
+ plain.showNormal();
+ QCOMPARE(plain.geometry(), QRect(200, 200, 300, 300));
+
+ {
+ QWidget frame;
+ QWidget widget(&frame);
+ widget.showMinimized();
+ QVERIFY(widget.isMinimized());
+ }
+}
+
+void tst_QWidget::showMinimizedKeepsFocus()
+{
+ //here we test that minimizing a widget and restoring it doesn't change the focus inside of it
+ {
+ QWidget window;
+ QWidget child1(&window), child2(&window);
+ child1.setFocusPolicy(Qt::StrongFocus);
+ child2.setFocusPolicy(Qt::StrongFocus);
+ window.show();
+ qApp->setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ child2.setFocus();
+ QTest::qWait(50);
+
+ QTRY_COMPARE(window.focusWidget(), &child2);
+ QTRY_COMPARE(qApp->focusWidget(), &child2);
+
+ window.showMinimized();
+ QTest::qWait(10);
+ QTRY_VERIFY(window.isMinimized());
+ QTRY_COMPARE(window.focusWidget(), &child2);
+
+ window.showNormal();
+ QTest::qWait(10);
+ QTRY_COMPARE(window.focusWidget(), &child2);
+ }
+
+ //testing deletion of the focusWidget
+ {
+ QWidget window;
+ QWidget *child = new QWidget(&window);
+ child->setFocusPolicy(Qt::StrongFocus);
+ window.show();
+ qApp->setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ child->setFocus();
+ QTest::qWait(50);
+ QTRY_COMPARE(window.focusWidget(), child);
+ QTRY_COMPARE(qApp->focusWidget(), child);
+
+ delete child;
+ QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
+ }
+
+ //testing reparenting the focus widget
+ {
+ QWidget window;
+ QWidget *child = new QWidget(&window);
+ child->setFocusPolicy(Qt::StrongFocus);
+ window.show();
+ qApp->setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ child->setFocus();
+ QTest::qWait(50);
+ QTRY_COMPARE(window.focusWidget(), child);
+ QTRY_COMPARE(qApp->focusWidget(), child);
+
+ child->setParent(0);
+ QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
+ }
+
+ //testing setEnabled(false)
+ {
+ QWidget window;
+ QWidget *child = new QWidget(&window);
+ child->setFocusPolicy(Qt::StrongFocus);
+ window.show();
+ qApp->setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ child->setFocus();
+ QTest::qWait(10);
+ QTRY_COMPARE(window.focusWidget(), child);
+ QTRY_COMPARE(qApp->focusWidget(), child);
+
+ child->setEnabled(false);
+ QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
+ }
+
+ //testing clearFocus
+ {
+ QWidget window;
+ QWidget *firstchild = new QWidget(&window);
+ firstchild->setFocusPolicy(Qt::StrongFocus);
+ QWidget *child = new QWidget(&window);
+ child->setFocusPolicy(Qt::StrongFocus);
+ window.show();
+ qApp->setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ child->setFocus();
+ QTest::qWait(10);
+ QTRY_COMPARE(window.focusWidget(), child);
+ QTRY_COMPARE(qApp->focusWidget(), child);
+
+ child->clearFocus();
+ QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
+
+ window.showMinimized();
+ QTest::qWait(30);
+ QTRY_VERIFY(window.isMinimized());
+#ifdef Q_WS_QWS
+ QEXPECT_FAIL("", "QWS does not implement showMinimized()", Continue);
+#endif
+ QCOMPARE(window.focusWidget(), static_cast<QWidget*>(0));
+#ifdef Q_WS_QWS
+ QEXPECT_FAIL("", "QWS does not implement showMinimized()", Continue);
+#endif
+ QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget*>(0));
+
+ window.showNormal();
+ qApp->setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ QTest::qWait(30);
+#ifdef Q_WS_MAC
+ if (!macHasAccessToWindowsServer())
+ QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
+#endif
+ QTRY_COMPARE(window.focusWidget(), firstchild);
+#ifdef Q_WS_MAC
+ if (!macHasAccessToWindowsServer())
+ QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue);
+#endif
+ QTRY_COMPARE(qApp->focusWidget(), firstchild);
+ }
+}
+
+
+void tst_QWidget::reparent()
+{
+ QWidget parent;
+ parent.setWindowTitle("Toplevel");
+ parent.setGeometry(300, 300, 200, 150);
+
+ QWidget child(0);
+ child.setObjectName("child");
+ child.setGeometry(10, 10, 180, 130);
+ QPalette pal1;
+ pal1.setColor(child.backgroundRole(), Qt::white);
+ child.setPalette(pal1);
+
+ QWidget childTLW(&child, Qt::Window);
+ childTLW.setObjectName("childTLW");
+ childTLW.setGeometry(100, 100, 50, 50);
+ QPalette pal2;
+ pal2.setColor(childTLW.backgroundRole(), Qt::yellow);
+ childTLW.setPalette(pal2);
+
+ parent.show();
+ childTLW.show();
+ QTest::qWaitForWindowShown(&parent);
+
+#ifdef Q_OS_WINCE
+ parent.move(50, 50);
+#else
+ parent.move(300, 300);
+#endif
+
+ QPoint childPos = parent.mapToGlobal(child.pos());
+ QPoint tlwPos = childTLW.pos();
+
+ child.setParent(0, child.windowFlags() & ~Qt::WindowType_Mask);
+ child.setGeometry(childPos.x(), childPos.y(), child.width(), child.height());
+ child.show();
+
+#ifdef Q_WS_X11
+ // On X11, the window manager will apply NorthWestGravity rules to 'child', which
+ // means the top-left corner of the window frame will be placed at 'childPos',
+ // causing this test to fail
+#else
+ QCOMPARE(child.geometry().topLeft(), childPos);
+#endif
+ QTRY_COMPARE(childTLW.pos(), tlwPos);
+
+ // This following part of the test only makes sense on Windows.
+#ifdef Q_WS_WIN
+ QWidget childTLWChild(&childTLW);
+ childTLWChild.setObjectName("childTLWChild");
+
+ QWidget grandChild(&child);
+ grandChild.setObjectName("grandChild");
+ grandChild.setGeometry(10, 10, 160, 110);
+ QPalette pal3;
+ pal3.setColor(grandChild.backgroundRole(), Qt::red);
+ grandChild.setPalette(pal3);
+ //grandChild.setPaletteBackgroundColor(Qt::red);
+
+ QWidget grandChildTLW(&grandChild, Qt::Window);
+ grandChildTLW.setObjectName("grandChildTLW");
+ grandChildTLW.setGeometry(200, 200, 50, 50);
+ QPalette pal4;
+ pal4.setColor(grandChildTLW.backgroundRole(), Qt::yellow);
+ grandChildTLW.setPalette(pal4);
+ //grandChildTLW.setPaletteBackgroundColor(Qt::yellow);
+
+ QWidget grandChildTLWChild(&grandChildTLW);
+ grandChildTLWChild.setObjectName("grandChildTLWChild");
+
+ QVERIFY(IsWindow(childTLW.winId()));
+ QVERIFY(IsWindow(childTLWChild.winId()));
+ QVERIFY(IsWindow(grandChildTLW.winId()));
+ QVERIFY(IsWindow(grandChildTLWChild.winId()));
+
+ parent.show();
+
+ QVERIFY(IsWindow(childTLW.winId()));
+ QVERIFY(IsWindow(childTLWChild.winId()));
+ QVERIFY(IsWindow(grandChildTLW.winId()));
+ QVERIFY(IsWindow(grandChildTLWChild.winId()));
+
+ child.setParent(&parent);
+ child.move(10,10);
+ child.show();
+
+ // this appears to stabelize results
+ qApp->processEvents();
+
+ QVERIFY(IsWindow(childTLW.winId()));
+ QVERIFY(IsWindow(childTLWChild.winId()));
+
+ QVERIFY(IsWindow(grandChildTLW.winId()));
+ QVERIFY(IsWindow(grandChildTLWChild.winId()));
+#endif
+}
+
+// Qt/Embedded does it differently.
+#ifndef Q_WS_QWS
+void tst_QWidget::icon()
+{
+ QPixmap p(20,20);
+ p.fill(Qt::red);
+ testWidget->setWindowIcon(p);
+
+ QVERIFY(!testWidget->windowIcon().isNull());
+ testWidget->show();
+ QVERIFY(!testWidget->windowIcon().isNull());
+ testWidget->showFullScreen();
+ QVERIFY(!testWidget->windowIcon().isNull());
+ testWidget->showNormal();
+ QVERIFY(!testWidget->windowIcon().isNull());
+}
+#endif
+
+void tst_QWidget::hideWhenFocusWidgetIsChild()
+{
+ testWidget->activateWindow();
+ QWidget *parentWidget = new QWidget(testWidget);
+ parentWidget->setObjectName("parentWidget");
+ parentWidget->setGeometry(0, 0, 100, 100);
+ QLineEdit *edit = new QLineEdit(parentWidget);
+ edit->setObjectName("edit1");
+ QLineEdit *edit3 = new QLineEdit(parentWidget);
+ edit3->setObjectName("edit3");
+ edit3->move(0,50);
+ parentWidget->show();
+ QLineEdit *edit2 = new QLineEdit(testWidget);
+ edit2->setObjectName("edit2");
+ edit2->show();
+ edit2->move(110, 100);
+ edit->setFocus();
+ qApp->processEvents();
+ QString actualFocusWidget, expectedFocusWidget;
+#ifdef Q_WS_X11
+ if (!qApp->focusWidget())
+ QSKIP("Your window manager is too broken for this test", SkipAll);
+#endif
+ QVERIFY(qApp->focusWidget());
+ actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
+ expectedFocusWidget.sprintf("%p %s %s", edit, edit->objectName().toLatin1().constData(), edit->metaObject()->className());
+ QCOMPARE(actualFocusWidget, expectedFocusWidget);
+
+ parentWidget->hide();
+ qApp->processEvents();
+ actualFocusWidget.sprintf("%p %s %s", qApp->focusWidget(), qApp->focusWidget()->objectName().toLatin1().constData(), qApp->focusWidget()->metaObject()->className());
+ expectedFocusWidget.sprintf("%p %s %s", edit2, edit2->objectName().toLatin1().constData(), edit2->metaObject()->className());
+ QCOMPARE(actualFocusWidget, expectedFocusWidget);
+
+ delete edit2;
+ delete parentWidget;
+}
+
+// 4DWM issues on IRIX makes this test fail.
+#ifndef Q_OS_IRIX
+void tst_QWidget::normalGeometry()
+{
+ QWidget parent;
+ parent.setWindowTitle("NormalGeometry parent");
+ QWidget *child = new QWidget(&parent);
+
+ QCOMPARE(parent.normalGeometry(), parent.geometry());
+ QCOMPARE(child->normalGeometry(), QRect());
+
+ parent.setGeometry(100, 100, 200, 200);
+ parent.show();
+ QTest::qWaitForWindowShown(&parent);
+ QApplication::processEvents();
+
+ QRect geom = parent.geometry();
+ // ### the window manager places the top-left corner at
+ // ### 100,100... making geom something like 102,124 (offset by
+ // ### the frame/frame)... this indicates a rather large different
+ // ### between how X11 and Windows works
+ // QCOMPARE(geom, QRect(100, 100, 200, 200));
+ QCOMPARE(parent.normalGeometry(), geom);
+
+ parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(10);
+ QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
+ QTRY_VERIFY(parent.geometry() != geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(10);
+ QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
+ QTRY_COMPARE(parent.geometry(), geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.showMaximized();
+ QTest::qWait(10);
+ QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
+ QTRY_VERIFY(parent.geometry() != geom);
+ QCOMPARE(parent.normalGeometry(), geom);
+
+ parent.showNormal();
+ QTest::qWait(10);
+ QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
+ QTRY_COMPARE(parent.geometry(), geom);
+ QCOMPARE(parent.normalGeometry(), geom);
+
+ parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
+ QTest::qWait(10);
+ parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(10);
+ QTRY_VERIFY(parent.windowState() & (Qt::WindowMinimized|Qt::WindowMaximized));
+ // ### when minimized and maximized at the same time, the geometry
+ // ### does *NOT* have to be the normal geometry, it could be the
+ // ### maximized geometry.
+ // QCOMPARE(parent.geometry(), geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.setWindowState(parent.windowState() ^ Qt::WindowMinimized);
+ QTest::qWait(10);
+ QTRY_VERIFY(!(parent.windowState() & Qt::WindowMinimized));
+ QTRY_VERIFY(parent.windowState() & Qt::WindowMaximized);
+ QTRY_VERIFY(parent.geometry() != geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.setWindowState(parent.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(10);
+ QTRY_VERIFY(!(parent.windowState() & Qt::WindowMaximized));
+ QTRY_COMPARE(parent.geometry(), geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
+ QTest::qWait(10);
+ QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
+ QTRY_VERIFY(parent.geometry() != geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.setWindowState(parent.windowState() ^ Qt::WindowFullScreen);
+ QTest::qWait(10);
+ QVERIFY(!(parent.windowState() & Qt::WindowFullScreen));
+ QTRY_COMPARE(parent.geometry(), geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.showFullScreen();
+ QTest::qWait(10);
+ QTRY_VERIFY(parent.windowState() & Qt::WindowFullScreen);
+ QTRY_VERIFY(parent.geometry() != geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.showNormal();
+ QTest::qWait(10);
+ QTRY_VERIFY(!(parent.windowState() & Qt::WindowFullScreen));
+ QTRY_COMPARE(parent.geometry(), geom);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+
+ parent.showNormal();
+ parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
+ parent.setWindowState(Qt::WindowMinimized | Qt:: WindowFullScreen | Qt::WindowMaximized);
+ parent.setWindowState(Qt:: WindowFullScreen | Qt::WindowMaximized);
+ QTest::qWait(10);
+ QTRY_COMPARE(parent.normalGeometry(), geom);
+}
+#endif
+
+void tst_QWidget::setGeometry()
+{
+ QWidget tlw;
+ QWidget child(&tlw);
+
+ QRect tr(100,100,200,200);
+ QRect cr(50,50,50,50);
+ tlw.setGeometry(tr);
+ child.setGeometry(cr);
+ tlw.show();
+ QTest::qWait(50);
+ QCOMPARE(tlw.geometry().size(), tr.size());
+ QCOMPARE(child.geometry(), cr);
+
+ tlw.setParent(0, Qt::Window|Qt::FramelessWindowHint);
+ tr = QRect(0,0,100,100);
+ tr.moveTopLeft(QApplication::desktop()->availableGeometry().topLeft());
+ tlw.setGeometry(tr);
+ QCOMPARE(tlw.geometry(), tr);
+ tlw.show();
+ QTest::qWait(50);
+ if (tlw.frameGeometry() != tlw.geometry())
+ QSKIP("Your window manager is too broken for this test", SkipAll);
+ QCOMPARE(tlw.geometry(), tr);
+
+}
+
+// Windows CE does not support windowOpacity.
+#ifndef Q_OS_WINCE
+void tst_QWidget::windowOpacity()
+{
+ QWidget widget;
+ QWidget child(&widget);
+
+ // Initial value should be 1.0
+ QCOMPARE(widget.windowOpacity(), 1.0);
+ // children should always return 1.0
+ QCOMPARE(child.windowOpacity(), 1.0);
+
+ widget.setWindowOpacity(0.0);
+ QCOMPARE(widget.windowOpacity(), 0.0);
+ child.setWindowOpacity(0.0);
+ QCOMPARE(child.windowOpacity(), 1.0);
+
+ widget.setWindowOpacity(1.0);
+ QCOMPARE(widget.windowOpacity(), 1.0);
+ child.setWindowOpacity(1.0);
+ QCOMPARE(child.windowOpacity(), 1.0);
+
+ widget.setWindowOpacity(2.0);
+ QCOMPARE(widget.windowOpacity(), 1.0);
+ child.setWindowOpacity(2.0);
+ QCOMPARE(child.windowOpacity(), 1.0);
+
+ widget.setWindowOpacity(-1.0);
+ QCOMPARE(widget.windowOpacity(), 0.0);
+ child.setWindowOpacity(-1.0);
+ QCOMPARE(child.windowOpacity(), 1.0);
+}
+#endif
+
+class UpdateWidget : public QWidget
+{
+public:
+ UpdateWidget(QWidget *parent = 0) : QWidget(parent) {
+ reset();
+ }
+
+ void paintEvent(QPaintEvent *e) {
+ paintedRegion += e->region();
+ ++numPaintEvents;
+ if (resizeInPaintEvent) {
+ resizeInPaintEvent = false;
+ resize(size() + QSize(2, 2));
+ }
+ }
+
+ bool event(QEvent *event)
+ {
+ switch (event->type()) {
+ case QEvent::ZOrderChange:
+ ++numZOrderChangeEvents;
+ break;
+ case QEvent::UpdateRequest:
+ ++numUpdateRequestEvents;
+ break;
+ case QEvent::ActivationChange:
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate:
+ if (!updateOnActivationChangeAndFocusIn)
+ return true; // Filter out to avoid update() calls in QWidget.
+ break;
+ default:
+ break;
+ }
+ return QWidget::event(event);
+ }
+
+ void reset() {
+ numPaintEvents = 0;
+ numZOrderChangeEvents = 0;
+ numUpdateRequestEvents = 0;
+ updateOnActivationChangeAndFocusIn = false;
+ resizeInPaintEvent = false;
+ paintedRegion = QRegion();
+ }
+
+ int numPaintEvents;
+ int numZOrderChangeEvents;
+ int numUpdateRequestEvents;
+ bool updateOnActivationChangeAndFocusIn;
+ bool resizeInPaintEvent;
+ QRegion paintedRegion;
+};
+
+void tst_QWidget::lostUpdatesOnHide()
+{
+#ifndef Q_WS_MAC
+ UpdateWidget widget;
+ widget.setAttribute(Qt::WA_DontShowOnScreen);
+ widget.show();
+ widget.hide();
+ QTest::qWait(50);
+ widget.show();
+ QTest::qWait(50);
+
+ QCOMPARE(widget.numPaintEvents, 1);
+#endif
+}
+
+void tst_QWidget::raise()
+{
+ QTest::qWait(10);
+ QWidget *parent = new QWidget(0);
+ QList<UpdateWidget *> allChildren;
+
+ UpdateWidget *child1 = new UpdateWidget(parent);
+ child1->setAutoFillBackground(true);
+ allChildren.append(child1);
+
+ UpdateWidget *child2 = new UpdateWidget(parent);
+ child2->setAutoFillBackground(true);
+ allChildren.append(child2);
+
+ UpdateWidget *child3 = new UpdateWidget(parent);
+ child3->setAutoFillBackground(true);
+ allChildren.append(child3);
+
+ UpdateWidget *child4 = new UpdateWidget(parent);
+ child4->setAutoFillBackground(true);
+ allChildren.append(child4);
+
+ parent->show();
+ QTest::qWaitForWindowShown(parent);
+ QTest::qWait(10);
+
+#ifdef Q_OS_MAC
+ if (child1->internalWinId()) {
+ QSKIP("Cocoa has no Z-Order for views, we hack it, but it results in paint events.", SkipAll);
+ }
+#endif
+
+ QList<QObject *> list1;
+ list1 << child1 << child2 << child3 << child4;
+ QVERIFY(parent->children() == list1);
+ QCOMPARE(allChildren.count(), list1.count());
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedPaintEvents = child == child4 ? 1 : 0;
+ if (expectedPaintEvents == 0) {
+ QVERIFY(child->numPaintEvents == 0);
+ } else {
+ // show() issues multiple paint events on some window managers
+ QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
+ }
+ QCOMPARE(child->numZOrderChangeEvents, 0);
+ child->reset();
+ }
+
+ for (int i = 0; i < 5; ++i)
+ child2->raise();
+ QTest::qWait(50);
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedPaintEvents = child == child2 ? 1 : 0;
+ int expectedZOrderChangeEvents = child == child2 ? 1 : 0;
+#ifdef Q_OS_MAC
+ QSKIP("Not yet sure why this fails.", SkipSingle);
+#endif
+ QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
+ QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
+ child->reset();
+ }
+
+ QList<QObject *> list2;
+ list2 << child1 << child3 << child4 << child2;
+ QVERIFY(parent->children() == list2);
+
+ // Creates a widget on top of all the children and checks that raising one of
+ // the children underneath doesn't trigger a repaint on the covering widget.
+ QWidget topLevel;
+ parent->setParent(&topLevel);
+ topLevel.show();
+ QTest::qWaitForWindowShown(&topLevel);
+ QTest::qWait(50);
+
+ UpdateWidget *onTop = new UpdateWidget(&topLevel);
+ onTop->reset();
+ onTop->resize(topLevel.size());
+ onTop->setAutoFillBackground(true);
+ onTop->show();
+ QTest::qWait(50);
+ QTRY_VERIFY(onTop->numPaintEvents > 0);
+ onTop->reset();
+
+ // Reset all the children.
+ foreach (UpdateWidget *child, allChildren)
+ child->reset();
+
+ for (int i = 0; i < 5; ++i)
+ child3->raise();
+ QTest::qWait(50);
+
+ QCOMPARE(onTop->numPaintEvents, 0);
+ QCOMPARE(onTop->numZOrderChangeEvents, 0);
+
+ QList<QObject *> list3;
+ list3 << child1 << child4 << child2 << child3;
+ QVERIFY(parent->children() == list3);
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedPaintEvents = 0;
+ int expectedZOrderChangeEvents = child == child3 ? 1 : 0;
+ QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
+ QCOMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
+ child->reset();
+ }
+}
+
+// Cocoa has no Z-Order for views, we hack it, but it results in paint events.
+#ifndef QT_OS_MAC
+void tst_QWidget::lower()
+{
+ QWidget *parent = new QWidget(0);
+ QList<UpdateWidget *> allChildren;
+
+ UpdateWidget *child1 = new UpdateWidget(parent);
+ child1->setAutoFillBackground(true);
+ allChildren.append(child1);
+
+ UpdateWidget *child2 = new UpdateWidget(parent);
+ child2->setAutoFillBackground(true);
+ allChildren.append(child2);
+
+ UpdateWidget *child3 = new UpdateWidget(parent);
+ child3->setAutoFillBackground(true);
+ allChildren.append(child3);
+
+ UpdateWidget *child4 = new UpdateWidget(parent);
+ child4->setAutoFillBackground(true);
+ allChildren.append(child4);
+
+ parent->show();
+ QTest::qWaitForWindowShown(parent);
+ QTest::qWait(100);
+
+ QList<QObject *> list1;
+ list1 << child1 << child2 << child3 << child4;
+ QVERIFY(parent->children() == list1);
+ QCOMPARE(allChildren.count(), list1.count());
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedPaintEvents = child == child4 ? 1 : 0;
+ if (expectedPaintEvents == 0) {
+ QVERIFY(child->numPaintEvents == 0);
+ } else {
+ // show() issues multiple paint events on some window managers
+ QTRY_VERIFY(child->numPaintEvents >= expectedPaintEvents);
+ }
+ QCOMPARE(child->numZOrderChangeEvents, 0);
+ child->reset();
+ }
+
+ for (int i = 0; i < 5; ++i)
+ child4->lower();
+
+ QTest::qWait(100);
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedPaintEvents = child == child3 ? 1 : 0;
+ int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
+ QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
+ QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
+ child->reset();
+ }
+
+ QList<QObject *> list2;
+ list2 << child4 << child1 << child2 << child3;
+ QVERIFY(parent->children() == list2);
+
+ delete parent;
+}
+#endif
+
+// Cocoa has no Z-Order for views, we hack it, but it results in paint events.
+#ifndef QT_OS_MAC
+void tst_QWidget::stackUnder()
+{
+ QTest::qWait(10);
+ QWidget *parent = new QWidget(0);
+ QList<UpdateWidget *> allChildren;
+
+ UpdateWidget *child1 = new UpdateWidget(parent);
+ child1->setAutoFillBackground(true);
+ allChildren.append(child1);
+
+ UpdateWidget *child2 = new UpdateWidget(parent);
+ child2->setAutoFillBackground(true);
+ allChildren.append(child2);
+
+ UpdateWidget *child3 = new UpdateWidget(parent);
+ child3->setAutoFillBackground(true);
+ allChildren.append(child3);
+
+ UpdateWidget *child4 = new UpdateWidget(parent);
+ child4->setAutoFillBackground(true);
+ allChildren.append(child4);
+
+ parent->show();
+ QTest::qWaitForWindowShown(parent);
+ QTest::qWait(10);
+#ifdef Q_WS_QWS
+ QApplication::sendPostedEvents(); //glib workaround
+#endif
+
+ QList<QObject *> list1;
+ list1 << child1 << child2 << child3 << child4;
+ QVERIFY(parent->children() == list1);
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedPaintEvents = child == child4 ? 1 : 0;
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
+ if (expectedPaintEvents == 1 && child->numPaintEvents == 2)
+ QEXPECT_FAIL(0, "Mac and Windows issues double repaints for Z-Order change", Continue);
+#endif
+ QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
+ QCOMPARE(child->numZOrderChangeEvents, 0);
+ child->reset();
+ }
+
+ for (int i = 0; i < 5; ++i)
+ child4->stackUnder(child2);
+ QTest::qWait(10);
+
+ QList<QObject *> list2;
+ list2 << child1 << child4 << child2 << child3;
+ QVERIFY(parent->children() == list2);
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedPaintEvents = child == child3 ? 1 : 0;
+ int expectedZOrderChangeEvents = child == child4 ? 1 : 0;
+ QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents);
+ QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
+ child->reset();
+ }
+
+ for (int i = 0; i < 5; ++i)
+ child1->stackUnder(child3);
+ QTest::qWait(10);
+
+ QList<QObject *> list3;
+ list3 << child4 << child2 << child1 << child3;
+ QVERIFY(parent->children() == list3);
+
+ foreach (UpdateWidget *child, allChildren) {
+ int expectedZOrderChangeEvents = child == child1 ? 1 : 0;
+ if (child == child3) {
+#ifdef Q_OS_WINCE
+ qApp->processEvents();
+#endif
+#ifndef Q_WS_MAC
+ QEXPECT_FAIL(0, "See QTBUG-493", Continue);
+#endif
+ QCOMPARE(child->numPaintEvents, 0);
+ } else {
+ QCOMPARE(child->numPaintEvents, 0);
+ }
+ QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents);
+ child->reset();
+ }
+
+ delete parent;
+}
+#endif
+
+void drawPolygon(QPaintDevice *dev, int w, int h)
+{
+ QPainter p(dev);
+ p.fillRect(0, 0, w, h, Qt::white);
+
+ QPolygon a;
+ a << QPoint(0, 0) << QPoint(w/2, h/2) << QPoint(w, 0)
+ << QPoint(w/2, h) << QPoint(0, 0);
+
+ p.setPen(QPen(Qt::black, 1));
+ p.setBrush(Qt::DiagCrossPattern);
+ p.drawPolygon(a);
+}
+
+class ContentsPropagationWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ ContentsPropagationWidget(QWidget *parent = 0) : QWidget(parent)
+ {
+ QWidget *child = this;
+ for (int i=0; i<32; ++i) {
+ child = new QWidget(child);
+ child->setGeometry(i, i, 400 - i*2, 400 - i*2);
+ }
+ }
+
+ void setContentsPropagation(bool enable) {
+ foreach (QObject *child, children())
+ qobject_cast<QWidget *>(child)->setAutoFillBackground(!enable);
+ }
+
+protected:
+ void paintEvent(QPaintEvent *)
+ {
+ int w = width(), h = height();
+ drawPolygon(this, w, h);
+ }
+
+ QSize sizeHint() const { return QSize(500, 500); }
+};
+
+void tst_QWidget::testContentsPropagation()
+{
+ ContentsPropagationWidget widget;
+#ifdef Q_WS_QWS
+ widget.resize(500,500);
+#else
+ widget.setFixedSize(500, 500);
+#endif
+ widget.setContentsPropagation(false);
+ QPixmap widgetSnapshot = QPixmap::grabWidget(&widget);
+
+ QPixmap correct(500, 500);
+ drawPolygon(&correct, 500, 500);
+ //correct.save("correct.png", "PNG");
+
+ //widgetSnapshot.save("snap1.png", "PNG");
+ QVERIFY(widgetSnapshot.toImage() != correct.toImage());
+
+ widget.setContentsPropagation(true);
+ widgetSnapshot = QPixmap::grabWidget(&widget);
+ //widgetSnapshot.save("snap2.png", "PNG");
+
+ QCOMPARE(widgetSnapshot, correct);
+}
+
+/*
+ Test that saving and restoring window geometry with
+ saveGeometry() and restoreGeometry() works.
+*/
+// 4DWM issues on IRIX makes this test fail.
+#ifndef Q_OS_IRIX
+void tst_QWidget::saveRestoreGeometry()
+{
+ const QPoint position(100, 100);
+ const QSize size(200, 200);
+
+ QByteArray savedGeometry;
+
+ {
+ QWidget widget;
+ widget.move(position);
+ widget.resize(size);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+
+ QTRY_COMPARE(widget.pos(), position);
+ QCOMPARE(widget.size(), size);
+ savedGeometry = widget.saveGeometry();
+ }
+
+ {
+ QWidget widget;
+
+ const QByteArray empty;
+ const QByteArray one("a");
+ const QByteArray two("ab");
+ const QByteArray three("abc");
+ const QByteArray four("abca");
+ const QByteArray garbage("abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc");
+
+ QVERIFY(widget.restoreGeometry(empty) == false);
+ QVERIFY(widget.restoreGeometry(one) == false);
+ QVERIFY(widget.restoreGeometry(two) == false);
+ QVERIFY(widget.restoreGeometry(three) == false);
+ QVERIFY(widget.restoreGeometry(four) == false);
+ QVERIFY(widget.restoreGeometry(garbage) == false);
+
+ QVERIFY(widget.restoreGeometry(savedGeometry));
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+
+ QTRY_COMPARE(widget.pos(), position);
+ QCOMPARE(widget.size(), size);
+ widget.show();
+ QCOMPARE(widget.pos(), position);
+ QCOMPARE(widget.size(), size);
+ }
+
+ {
+ QWidget widget;
+ widget.move(position);
+ widget.resize(size);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(500);
+ QTRY_COMPARE(widget.geometry().size(), size);
+
+ QRect geom;
+
+ //Restore from Full screen
+ savedGeometry = widget.saveGeometry();
+ geom = widget.geometry();
+ widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
+ QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
+ QTest::qWait(500);
+ QVERIFY(widget.restoreGeometry(savedGeometry));
+ QTest::qWait(120);
+ QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
+ QTRY_COMPARE(widget.geometry(), geom);
+
+ //Restore to full screen
+ widget.setWindowState(widget.windowState() | Qt::WindowFullScreen);
+ QTest::qWait(120);
+ QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
+ QTest::qWait(500);
+ savedGeometry = widget.saveGeometry();
+ geom = widget.geometry();
+ widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
+ QTest::qWait(120);
+ QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
+ QTest::qWait(400);
+ QVERIFY(widget.restoreGeometry(savedGeometry));
+ QTest::qWait(120);
+ QTRY_VERIFY((widget.windowState() & Qt::WindowFullScreen));
+ QTRY_COMPARE(widget.geometry(), geom);
+ QVERIFY((widget.windowState() & Qt::WindowFullScreen));
+ widget.setWindowState(widget.windowState() ^ Qt::WindowFullScreen);
+ QTest::qWait(120);
+ QTRY_VERIFY(!(widget.windowState() & Qt::WindowFullScreen));
+ QTest::qWait(120);
+
+ //Restore from Maximised
+ widget.move(position);
+ widget.resize(size);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.size(), size);
+ QTest::qWait(500);
+ savedGeometry = widget.saveGeometry();
+ geom = widget.geometry();
+ widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
+ QTest::qWait(120);
+ QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
+ QTRY_VERIFY(widget.geometry() != geom);
+ QTest::qWait(500);
+ QVERIFY(widget.restoreGeometry(savedGeometry));
+ QTest::qWait(120);
+ QTRY_COMPARE(widget.geometry(), geom);
+
+ QVERIFY(!(widget.windowState() & Qt::WindowMaximized));
+
+ //Restore to maximised
+ widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
+ QTest::qWait(120);
+ QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
+ QTest::qWait(500);
+ geom = widget.geometry();
+ savedGeometry = widget.saveGeometry();
+ widget.setWindowState(widget.windowState() ^ Qt::WindowMaximized);
+ QTest::qWait(120);
+ QTRY_VERIFY(!(widget.windowState() & Qt::WindowMaximized));
+ QTest::qWait(500);
+ QVERIFY(widget.restoreGeometry(savedGeometry));
+ QTest::qWait(120);
+ QTRY_VERIFY((widget.windowState() & Qt::WindowMaximized));
+ QTRY_COMPARE(widget.geometry(), geom);
+ }
+}
+#endif
+
+// 4DWM issues on IRIX makes this test fail.
+#ifndef Q_OS_IRIX
+void tst_QWidget::restoreVersion1Geometry_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<uint>("expectedWindowState");
+ QTest::addColumn<QPoint>("expectedPosition");
+ QTest::addColumn<QSize>("expectedSize");
+ QTest::addColumn<QRect>("expectedNormalGeometry");
+ const QPoint position(100, 100);
+ const QSize size(200, 200);
+ const QRect normalGeometry(102, 124, 200, 200);
+
+ QTest::newRow("geometry.dat") << ":geometry.dat" << uint(Qt::WindowNoState) << position << size << normalGeometry;
+ QTest::newRow("geometry-maximized.dat") << ":geometry-maximized.dat" << uint(Qt::WindowMaximized) << position << size << normalGeometry;
+ QTest::newRow("geometry-fullscreen.dat") << ":geometry-fullscreen.dat" << uint(Qt::WindowFullScreen) << position << size << normalGeometry;
+}
+
+/*
+ Test that the current version of restoreGeometry() can restore geometry
+ saved width saveGeometry() version 1.0.
+*/
+void tst_QWidget::restoreVersion1Geometry()
+{
+ QFETCH(QString, fileName);
+ QFETCH(uint, expectedWindowState);
+ QFETCH(QPoint, expectedPosition);
+ QFETCH(QSize, expectedSize);
+ QFETCH(QRect, expectedNormalGeometry);
+
+ // WindowActive is uninteresting for this test
+ const uint WindowStateMask = Qt::WindowFullScreen | Qt::WindowMaximized | Qt::WindowMinimized;
+
+ QFile f(fileName);
+ QVERIFY(f.exists());
+ f.open(QIODevice::ReadOnly);
+ const QByteArray savedGeometry = f.readAll();
+ QCOMPARE(savedGeometry.count(), 46);
+ f.close();
+
+ QWidget widget;
+
+ QVERIFY(widget.restoreGeometry(savedGeometry));
+
+ QCOMPARE(uint(widget.windowState() & WindowStateMask), expectedWindowState);
+ if (expectedWindowState == Qt::WindowNoState) {
+ QCOMPARE(widget.pos(), expectedPosition);
+ QCOMPARE(widget.size(), expectedSize);
+ }
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(100);
+
+ if (expectedWindowState == Qt::WindowNoState) {
+ QTRY_COMPARE(widget.pos(), expectedPosition);
+ QTRY_COMPARE(widget.size(), expectedSize);
+ }
+
+ widget.showNormal();
+ QTest::qWait(10);
+
+ if (expectedWindowState != Qt::WindowNoState) {
+ // restoring from maximized or fullscreen, we can only restore to the normal geometry
+ QTRY_COMPARE(widget.geometry(), expectedNormalGeometry);
+ } else {
+ QTRY_COMPARE(widget.pos(), expectedPosition);
+ QTRY_COMPARE(widget.size(), expectedSize);
+ }
+
+#if 0
+ // Code for saving a new geometry*.dat files
+ {
+ QWidget widgetToSave;
+ widgetToSave.move(expectedPosition);
+ widgetToSave.resize(expectedSize);
+ widgetToSave.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&widget);
+#endif
+ QTest::qWait(500); // stabilize
+ widgetToSave.setWindowState(Qt::WindowStates(expectedWindowState));
+ QTest::qWait(500); // stabilize
+
+ QByteArray geometryToSave = widgetToSave.saveGeometry();
+
+ // Code for saving a new geometry.dat file.
+ f.setFileName(fileName.mid(1));
+ QVERIFY(f.open(QIODevice::WriteOnly)); // did you forget to 'p4 edit *.dat'? :)
+ f.write(geometryToSave);
+ f.close();
+ }
+#endif
+}
+#endif
+
+void tst_QWidget::widgetAt()
+{
+ Q_CHECK_PAINTEVENTS
+
+ QWidget *w1 = new QWidget(0, Qt::X11BypassWindowManagerHint);
+ w1->setGeometry(0,0,150,150);
+ w1->setObjectName("w1");
+
+ QWidget *w2 = new QWidget(0, Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint);
+ w2->setGeometry(50,50,100,100);
+ w2->setObjectName("w2");
+ w1->show();
+ QTest::qWaitForWindowShown(w1);
+ qApp->processEvents();
+ QWidget *wr;
+ QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
+ QCOMPARE(wr->objectName(), QString("w1"));
+
+ w2->show();
+ QTest::qWaitForWindowShown(w2);
+ qApp->processEvents();
+ qApp->processEvents();
+ qApp->processEvents();
+ QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)));
+ QCOMPARE(wr->objectName(), QString("w2"));
+
+ w2->lower();
+ qApp->processEvents();
+ QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w1"));
+ w2->raise();
+
+ qApp->processEvents();
+ QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
+
+ QWidget *w3 = new QWidget(w2);
+ w3->setGeometry(10,10,50,50);
+ w3->setObjectName("w3");
+ w3->show();
+ qApp->processEvents();
+ QTRY_VERIFY((wr = QApplication::widgetAt(100,100)) && wr->objectName() == QString("w3"));
+
+ w3->setAttribute(Qt::WA_TransparentForMouseEvents);
+ qApp->processEvents();
+ QTRY_VERIFY((wr = QApplication::widgetAt(100, 100)) && wr->objectName() == QString("w2"));
+
+ QRegion rgn = QRect(QPoint(0,0), w2->size());
+ QPoint point = w2->mapFromGlobal(QPoint(100,100));
+ rgn -= QRect(point, QSize(1,1));
+ w2->setMask(rgn);
+ qApp->processEvents();
+ QTest::qWait(10);
+#if defined(Q_OS_WINCE)
+ QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
+#endif
+#if defined(Q_WS_QPA)
+ QEXPECT_FAIL("", "Window mask not implemented on Lighthouse", Continue);
+#endif
+
+ QTRY_COMPARE(QApplication::widgetAt(100,100)->objectName(), w1->objectName());
+ QTRY_COMPARE(QApplication::widgetAt(101,101)->objectName(), w2->objectName());
+
+ QBitmap bitmap(w2->size());
+ QPainter p(&bitmap);
+ p.fillRect(bitmap.rect(), Qt::color1);
+ p.setPen(Qt::color0);
+ p.drawPoint(w2->mapFromGlobal(QPoint(100,100)));
+ p.end();
+ w2->setMask(bitmap);
+ qApp->processEvents();
+ QTest::qWait(10);
+#if defined(Q_OS_WINCE)
+ QEXPECT_FAIL("", "Windows CE does only support rectangular regions", Continue); //See also task 147191
+#endif
+#if defined(Q_WS_QPA)
+ QEXPECT_FAIL("", "Window mask not implemented on Lighthouse", Continue);
+#endif
+ QTRY_VERIFY(QApplication::widgetAt(100,100) == w1);
+ QTRY_VERIFY(QApplication::widgetAt(101,101) == w2);
+
+ delete w2;
+ delete w1;
+}
+
+#if defined(Q_WS_X11)
+bool getProperty(Display *display, Window target, Atom type, Atom property,
+ unsigned char** data, unsigned long* count)
+{
+ Atom atom_return;
+ int size;
+ unsigned long nitems, bytes_left;
+
+ int ret = XGetWindowProperty(display, target, property,
+ 0l, 1l, false,
+ type, &atom_return, &size,
+ &nitems, &bytes_left, data);
+ if (ret != Success || nitems < 1)
+ return false;
+
+ if (bytes_left != 0) {
+ XFree(*data);
+ unsigned long remain = ((size / 8) * nitems) + bytes_left;
+ ret = XGetWindowProperty(display, target,
+ property, 0l, remain, false,
+ type, &atom_return, &size,
+ &nitems, &bytes_left, data);
+ if (ret != Success)
+ return false;
+ }
+
+ *count = nitems;
+ return true;
+}
+
+QString textPropertyToString(Display *display, XTextProperty& text_prop)
+{
+ QString ret;
+ if (text_prop.value && text_prop.nitems > 0) {
+ if (text_prop.encoding == XA_STRING) {
+ ret = reinterpret_cast<char *>(text_prop.value);
+ } else {
+ text_prop.nitems = strlen(reinterpret_cast<char *>(text_prop.value));
+ char **list;
+ int num;
+ if (XmbTextPropertyToTextList(display, &text_prop, &list, &num) == Success
+ && num > 0 && *list) {
+ ret = QString::fromLocal8Bit(*list);
+ XFreeStringList(list);
+ }
+ }
+ }
+ return ret;
+}
+#endif
+
+void tst_QWidget::task110173()
+{
+ QWidget w;
+
+ QPushButton *pb1 = new QPushButton("click", &w);
+ pb1->setFocusPolicy(Qt::ClickFocus);
+ pb1->move(100, 100);
+
+ QPushButton *pb2 = new QPushButton("push", &w);
+ pb2->setFocusPolicy(Qt::ClickFocus);
+ pb2->move(300, 300);
+
+ QTest::keyClick( &w, Qt::Key_Tab );
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QTest::qWait(200);
+}
+
+class Widget : public QWidget
+{
+public:
+ Widget() : deleteThis(false) { setFocusPolicy(Qt::StrongFocus); }
+ void actionEvent(QActionEvent *) { if (deleteThis) delete this; }
+ void changeEvent(QEvent *) { if (deleteThis) delete this; }
+ void closeEvent(QCloseEvent *) { if (deleteThis) delete this; }
+ void hideEvent(QHideEvent *) { if (deleteThis) delete this; }
+ void focusOutEvent(QFocusEvent *) { if (deleteThis) delete this; }
+ void keyPressEvent(QKeyEvent *) { if (deleteThis) delete this; }
+ void keyReleaseEvent(QKeyEvent *) { if (deleteThis) delete this; }
+ void mouseDoubleClickEvent(QMouseEvent *) { if (deleteThis) delete this; }
+ void mousePressEvent(QMouseEvent *) { if (deleteThis) delete this; }
+ void mouseReleaseEvent(QMouseEvent *) { if (deleteThis) delete this; }
+ void mouseMoveEvent(QMouseEvent *) { if (deleteThis) delete this; }
+
+ bool deleteThis;
+};
+
+void tst_QWidget::testDeletionInEventHandlers()
+{
+ // closeEvent
+ QPointer<Widget> w = new Widget;
+ w->deleteThis = true;
+ w->close();
+ QVERIFY(w == 0);
+ delete w;
+
+ // focusOut (crashes)
+ //w = new Widget;
+ //w->show();
+ //w->setFocus();
+ //QVERIFY(qApp->focusWidget() == w);
+ //w->deleteThis = true;
+ //w->clearFocus();
+ //QVERIFY(w == 0);
+
+ // key press
+ w = new Widget;
+ w->show();
+ w->deleteThis = true;
+ QTest::keyPress(w, Qt::Key_A);
+ QVERIFY(w == 0);
+ delete w;
+
+ // key release
+ w = new Widget;
+ w->show();
+ w->deleteThis = true;
+ QTest::keyRelease(w, Qt::Key_A);
+ QVERIFY(w == 0);
+ delete w;
+
+ // mouse press
+ w = new Widget;
+ w->show();
+ w->deleteThis = true;
+ QTest::mousePress(w, Qt::LeftButton);
+ QVERIFY(w == 0);
+ delete w;
+
+ // mouse release
+ w = new Widget;
+ w->show();
+ w->deleteThis = true;
+ QTest::mouseRelease(w, Qt::LeftButton);
+ QVERIFY(w == 0);
+ delete w;
+
+ // mouse double click
+ w = new Widget;
+ w->show();
+ w->deleteThis = true;
+ QTest::mouseDClick(w, Qt::LeftButton);
+ QVERIFY(w == 0);
+ delete w;
+
+ // hide event (crashes)
+ //w = new Widget;
+ //w->show();
+ //w->deleteThis = true;
+ //w->hide();
+ //QVERIFY(w == 0);
+
+ // action event
+ w = new Widget;
+ w->deleteThis = true;
+ w->addAction(new QAction(w));
+ QVERIFY(w == 0);
+ delete w;
+
+ // change event
+ w = new Widget;
+ w->show();
+ w->deleteThis = true;
+ w->setMouseTracking(true);
+ QVERIFY(w == 0);
+ delete w;
+
+ w = new Widget;
+ w->setMouseTracking(true);
+ w->show();
+ w->deleteThis = true;
+ QMouseEvent me(QEvent::MouseMove, QPoint(0, 0), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
+ QApplication::sendEvent(w, &me);
+ QVERIFY(w == 0);
+ delete w;
+}
+
+#ifdef Q_WS_MAC
+
+/*
+ Test that retaining and releasing the HIView returned by QWidget::winId()
+ works even if the widget itself is deleted.
+*/
+void tst_QWidget::retainHIView()
+{
+ // Single window
+ {
+ const WidgetViewPair window = createAndRetain();
+ delete window.first;
+ QVERIFY(testAndRelease(window.second));
+ }
+
+ // Child widget
+ {
+ const WidgetViewPair parent = createAndRetain();
+ const WidgetViewPair child = createAndRetain(parent.first);
+
+ delete parent.first;
+ QVERIFY(testAndRelease(parent.second));
+ QVERIFY(testAndRelease(child.second));
+ }
+
+ // Multiple children
+ {
+ const WidgetViewPair parent = createAndRetain();
+ const WidgetViewPair child1 = createAndRetain(parent.first);
+ const WidgetViewPair child2 = createAndRetain(parent.first);
+
+ delete parent.first;
+ QVERIFY(testAndRelease(parent.second));
+ QVERIFY(testAndRelease(child1.second));
+ QVERIFY(testAndRelease(child2.second));
+ }
+
+ // Grandchild widget
+ {
+ const WidgetViewPair parent = createAndRetain();
+ const WidgetViewPair child = createAndRetain(parent.first);
+ const WidgetViewPair grandchild = createAndRetain(child.first);
+
+ delete parent.first;
+ QVERIFY(testAndRelease(parent.second));
+ QVERIFY(testAndRelease(child.second));
+ QVERIFY(testAndRelease(grandchild.second));
+ }
+
+ // Reparent child widget
+ {
+ const WidgetViewPair parent1 = createAndRetain();
+ const WidgetViewPair parent2 = createAndRetain();
+ const WidgetViewPair child = createAndRetain(parent1.first);
+
+ child.first->setParent(parent2.first);
+
+ delete parent1.first;
+ QVERIFY(testAndRelease(parent1.second));
+ delete parent2.first;
+ QVERIFY(testAndRelease(parent2.second));
+ QVERIFY(testAndRelease(child.second));
+ }
+
+ // Reparent window
+ {
+ const WidgetViewPair window1 = createAndRetain();
+ const WidgetViewPair window2 = createAndRetain();
+ const WidgetViewPair child1 = createAndRetain(window1.first);
+ const WidgetViewPair child2 = createAndRetain(window2.first);
+
+ window2.first->setParent(window1.first);
+
+ delete window2.first;
+ QVERIFY(testAndRelease(window2.second));
+ QVERIFY(testAndRelease(child2.second));
+ delete window1.first;
+ QVERIFY(testAndRelease(window1.second));
+ QVERIFY(testAndRelease(child1.second));
+ }
+
+ // Delete child widget
+ {
+ const WidgetViewPair parent = createAndRetain();
+ const WidgetViewPair child = createAndRetain(parent.first);
+
+ delete child.first;
+ QVERIFY(testAndRelease(child.second));
+ delete parent.first;
+ QVERIFY(testAndRelease(parent.second));
+ }
+}
+
+void tst_QWidget::sheetOpacity()
+{
+ QWidget tmpWindow;
+ QWidget sheet(&tmpWindow, Qt::Sheet);
+ tmpWindow.show();
+ sheet.show();
+ QCOMPARE(int(sheet.windowOpacity() * 255), 242); // 95%
+ sheet.setParent(0, Qt::Dialog);
+ QCOMPARE(int(sheet.windowOpacity() * 255), 255);
+}
+
+class MaskedPainter : public QWidget
+{
+public:
+ QRect mask;
+
+ MaskedPainter()
+ : mask(20, 20, 50, 50)
+ {
+ setMask(mask);
+ }
+
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter p(this);
+ p.fillRect(mask, QColor(Qt::red));
+ }
+};
+
+/*
+ Verifies that the entire area inside the mask is painted red.
+*/
+bool verifyWidgetMask(QWidget *widget, QRect mask)
+{
+ const QImage image = QPixmap::grabWindow(widget->winId()).toImage();
+
+ const QImage masked = image.copy(mask);
+ QImage red(masked);
+ red.fill(QColor(Qt::red).rgb());
+
+ return (masked == red);
+}
+
+void tst_QWidget::setMask()
+{
+ testWidget->hide(); // get this out of the way.
+
+ {
+ MaskedPainter w;
+ w.resize(200, 200);
+ w.show();
+ QTest::qWait(100);
+ QVERIFY(verifyWidgetMask(&w, w.mask));
+ }
+ {
+ MaskedPainter w;
+ w.resize(200, 200);
+ w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
+ w.show();
+ QTest::qWait(100);
+ QRect mask = w.mask;
+
+ QVERIFY(verifyWidgetMask(&w, mask));
+ }
+}
+#endif
+
+class StaticWidget : public QWidget
+{
+Q_OBJECT
+public:
+ bool partial;
+ bool gotPaintEvent;
+ QRegion paintedRegion;
+
+ StaticWidget(QWidget *parent = 0)
+ :QWidget(parent)
+ {
+ setAttribute(Qt::WA_StaticContents);
+ setAttribute(Qt::WA_OpaquePaintEvent);
+ setPalette(Qt::red); // Make sure we have an opaque palette.
+ setAutoFillBackground(true);
+ gotPaintEvent = false;
+ }
+
+ void paintEvent(QPaintEvent *e)
+ {
+ paintedRegion += e->region();
+ gotPaintEvent = true;
+// qDebug() << "paint" << e->region();
+ // Look for a full update, set partial to false if found.
+ foreach(QRect r, e->region().rects()) {
+ partial = (r != rect());
+ if (partial == false)
+ break;
+ }
+ }
+};
+
+/*
+ Test that widget resizes and moves can be done with minimal repaints when WA_StaticContents
+ and WA_OpaquePaintEvent is set. Test is mac-only for now.
+*/
+void tst_QWidget::optimizedResizeMove()
+{
+ QWidget parent;
+ parent.resize(400, 400);
+
+ StaticWidget staticWidget(&parent);
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(150, 150);
+ staticWidget.resize(150, 150);
+ parent.show();
+ QTest::qWaitForWindowShown(&parent);
+ QTest::qWait(20);
+ QTRY_COMPARE(staticWidget.gotPaintEvent, true);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(10, 10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, false);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, false);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(-10, 10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, false);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.resize(staticWidget.size() + QSize(10, 10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, true);
+ QCOMPARE(staticWidget.partial, true);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.resize(staticWidget.size() + QSize(-10, -10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, false);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.resize(staticWidget.size() + QSize(10, -10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, true);
+ QCOMPARE(staticWidget.partial, true);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(10, 10));
+ staticWidget.resize(staticWidget.size() + QSize(-10, -10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, false);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(10, 10));
+ staticWidget.resize(staticWidget.size() + QSize(10, 10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, true);
+ QCOMPARE(staticWidget.partial, true);
+
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
+ staticWidget.resize(staticWidget.size() + QSize(-10, -10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, false);
+
+ staticWidget.setAttribute(Qt::WA_StaticContents, false);
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(-10, -10));
+ staticWidget.resize(staticWidget.size() + QSize(-10, -10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, true);
+ QCOMPARE(staticWidget.partial, false);
+ staticWidget.setAttribute(Qt::WA_StaticContents, true);
+
+ staticWidget.setAttribute(Qt::WA_StaticContents, false);
+ staticWidget.gotPaintEvent = false;
+ staticWidget.move(staticWidget.pos() + QPoint(10, 10));
+ QTest::qWait(20);
+ QCOMPARE(staticWidget.gotPaintEvent, false);
+ staticWidget.setAttribute(Qt::WA_StaticContents, true);
+}
+
+void tst_QWidget::optimizedResize_topLevel()
+{
+#if defined(Q_WS_MAC) || defined(Q_WS_QWS)
+ QSKIP("We do not yet have static contents support for *top-levels* on this platform", SkipAll);
+#endif
+
+ StaticWidget topLevel;
+ topLevel.gotPaintEvent = false;
+ topLevel.show();
+ QTest::qWaitForWindowShown(&topLevel);
+ QTest::qWait(10);
+ QTRY_COMPARE(topLevel.gotPaintEvent, true);
+
+ topLevel.gotPaintEvent = false;
+ topLevel.partial = false;
+ topLevel.paintedRegion = QRegion();
+
+#ifndef Q_WS_WIN
+ topLevel.resize(topLevel.size() + QSize(10, 10));
+#else
+ // Static contents does not work when programmatically resizing
+ // top-levels with QWidget::resize. We do some funky stuff in
+ // setGeometry_sys. However, resizing it with the mouse or with
+ // a native function call works (it basically has to go through
+ // WM_RESIZE in QApplication). This is a corner case, though.
+ // See task 243708
+ const QRect frame = topLevel.frameGeometry();
+ MoveWindow(topLevel.winId(), frame.x(), frame.y(),
+ frame.width() + 10, frame.height() + 10,
+ true);
+#endif
+
+ QTest::qWait(100);
+
+ // Expected update region: New rect - old rect.
+ QRegion expectedUpdateRegion(topLevel.rect());
+ expectedUpdateRegion -= QRect(QPoint(), topLevel.size() - QSize(10, 10));
+
+ QTRY_COMPARE(topLevel.gotPaintEvent, true);
+ QCOMPARE(topLevel.partial, true);
+ QCOMPARE(topLevel.paintedRegion, expectedUpdateRegion);
+}
+
+class SiblingDeleter : public QWidget
+{
+public:
+ inline SiblingDeleter(QWidget *sibling, QWidget *parent)
+ : QWidget(parent), sibling(sibling) {}
+ inline virtual ~SiblingDeleter() { delete sibling; }
+
+private:
+ QPointer<QWidget> sibling;
+};
+
+
+void tst_QWidget::childDeletesItsSibling()
+{
+ QWidget *commonParent = new QWidget(0);
+ QPointer<QWidget> child = new QWidget(0);
+ QPointer<QWidget> siblingDeleter = new SiblingDeleter(child, commonParent);
+ child->setParent(commonParent);
+ delete commonParent; // don't crash
+ QVERIFY(!child);
+ QVERIFY(!siblingDeleter);
+
+}
+
+#ifdef Q_WS_QWS
+# define SET_SAFE_SIZE(w) \
+ do { \
+ QSize safeSize(qt_screen->width() - 250, qt_screen->height() - 250); \
+ if (!safeSize.isValid()) \
+ QSKIP("Screen size too small", SkipAll); \
+ if (defaultSize.width() > safeSize.width() || defaultSize.height() > safeSize.height()) { \
+ defaultSize = safeSize; \
+ w.resize(defaultSize); \
+ w.setAttribute(Qt::WA_Resized, false); \
+ } \
+ } while (false)
+#else
+# define SET_SAFE_SIZE(w)
+#endif
+
+
+void tst_QWidget::setMinimumSize()
+{
+ QWidget w;
+ QSize defaultSize = w.size();
+ SET_SAFE_SIZE(w);
+
+ w.setMinimumSize(defaultSize + QSize(100, 100));
+ QCOMPARE(w.size(), defaultSize + QSize(100, 100));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.setMinimumSize(defaultSize + QSize(50, 50));
+ QCOMPARE(w.size(), defaultSize + QSize(100, 100));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.setMinimumSize(defaultSize + QSize(200, 200));
+ QCOMPARE(w.size(), defaultSize + QSize(200, 200));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ // Setting a minimum size larger than the desktop does not work on WinCE,
+ // so skip this part of the test.
+#ifndef Q_OS_WINCE
+ QSize nonDefaultSize = defaultSize + QSize(5,5);
+ w.setMinimumSize(nonDefaultSize);
+ w.show();
+ QTest::qWait(50);
+ QVERIFY(w.height() >= nonDefaultSize.height());
+ QVERIFY(w.width() >= nonDefaultSize.width());
+#endif
+}
+
+void tst_QWidget::setMaximumSize()
+{
+ QWidget w;
+ QSize defaultSize = w.size();
+ SET_SAFE_SIZE(w);
+
+ w.setMinimumSize(defaultSize + QSize(100, 100));
+ QCOMPARE(w.size(), defaultSize + QSize(100, 100));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+ w.setMinimumSize(defaultSize);
+
+ w.setMaximumSize(defaultSize + QSize(200, 200));
+ QCOMPARE(w.size(), defaultSize + QSize(100, 100));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.setMaximumSize(defaultSize + QSize(50, 50));
+ QCOMPARE(w.size(), defaultSize + QSize(50, 50));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+#if 0
+ //we don't enforce maximum size on show, apparently
+ QSize nonDefaultSize = defaultSize - QSize(5,5);
+ w.setMaximumSize(nonDefaultSize);
+ w.show();
+ QTest::qWait(50);
+ qDebug() << nonDefaultSize << w.size();
+ QVERIFY(w.height() <= nonDefaultSize.height());
+ QVERIFY(w.width() <= nonDefaultSize.width());
+#endif
+}
+
+void tst_QWidget::setFixedSize()
+{
+ QWidget w;
+ QSize defaultSize = w.size();
+ SET_SAFE_SIZE(w);
+
+ w.setFixedSize(defaultSize + QSize(100, 100));
+ QCOMPARE(w.size(), defaultSize + QSize(100, 100));
+ QVERIFY(w.testAttribute(Qt::WA_Resized));
+
+ w.setFixedSize(defaultSize + QSize(200, 200));
+
+ QCOMPARE(w.minimumSize(), defaultSize + QSize(200,200));
+ QCOMPARE(w.maximumSize(), defaultSize + QSize(200,200));
+ QCOMPARE(w.size(), defaultSize + QSize(200, 200));
+ QVERIFY(w.testAttribute(Qt::WA_Resized));
+
+ w.setFixedSize(defaultSize + QSize(50, 50));
+ QCOMPARE(w.size(), defaultSize + QSize(50, 50));
+ QVERIFY(w.testAttribute(Qt::WA_Resized));
+
+ w.setAttribute(Qt::WA_Resized, false);
+ w.setFixedSize(defaultSize + QSize(50, 50));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.setFixedSize(defaultSize + QSize(150, 150));
+ w.show();
+ QTest::qWait(50);
+ QVERIFY(w.size() == defaultSize + QSize(150,150));
+}
+
+void tst_QWidget::ensureCreated()
+{
+ {
+ QWidget widget;
+ WId widgetWinId = widget.winId();
+ Q_UNUSED(widgetWinId);
+ QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
+ }
+
+ {
+ QWidget window;
+
+ QDialog dialog(&window);
+ dialog.setWindowModality(Qt::NonModal);
+
+ WId dialogWinId = dialog.winId();
+ Q_UNUSED(dialogWinId);
+ QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(window.testAttribute(Qt::WA_WState_Created));
+ }
+
+ {
+ QWidget window;
+
+ QDialog dialog(&window);
+ dialog.setWindowModality(Qt::WindowModal);
+
+ WId dialogWinId = dialog.winId();
+ Q_UNUSED(dialogWinId);
+ QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(window.testAttribute(Qt::WA_WState_Created));
+ }
+
+ {
+ QWidget window;
+
+ QDialog dialog(&window);
+ dialog.setWindowModality(Qt::ApplicationModal);
+
+ WId dialogWinId = dialog.winId();
+ Q_UNUSED(dialogWinId);
+ QVERIFY(dialog.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(window.testAttribute(Qt::WA_WState_Created));
+ }
+}
+
+class WinIdChangeWidget : public QWidget {
+public:
+ WinIdChangeWidget(QWidget *p = 0)
+ : QWidget(p)
+ {
+
+ }
+protected:
+ bool event(QEvent *e)
+ {
+ if (e->type() == QEvent::WinIdChange) {
+ m_winIdList.append(internalWinId());
+ return true;
+ }
+ return QWidget::event(e);
+ }
+public:
+ QList<WId> m_winIdList;
+ int winIdChangeEventCount() const { return m_winIdList.count(); }
+};
+
+void tst_QWidget::winIdChangeEvent()
+{
+ {
+ // Transforming an alien widget into a native widget
+ WinIdChangeWidget widget;
+ const WId winIdBefore = widget.internalWinId();
+ const WId winIdAfter = widget.winId();
+ QVERIFY(winIdBefore != winIdAfter);
+ QCOMPARE(widget.winIdChangeEventCount(), 1);
+ }
+
+ {
+ // Changing parent of a native widget
+ // Should cause winId of child to change, on all platforms
+ QWidget parent1, parent2;
+ WinIdChangeWidget child(&parent1);
+ const WId winIdBefore = child.winId();
+ QCOMPARE(child.winIdChangeEventCount(), 1);
+ child.setParent(&parent2);
+ const WId winIdAfter = child.internalWinId();
+ QVERIFY(winIdBefore != winIdAfter);
+ QCOMPARE(child.winIdChangeEventCount(), 3);
+ // winId is set to zero during reparenting
+ QVERIFY(0 == child.m_winIdList[1]);
+ }
+
+ {
+ // Changing grandparent of a native widget
+ QWidget grandparent1, grandparent2;
+ QWidget parent(&grandparent1);
+ WinIdChangeWidget child(&parent);
+ const WId winIdBefore = child.winId();
+ QCOMPARE(child.winIdChangeEventCount(), 1);
+ parent.setParent(&grandparent2);
+ const WId winIdAfter = child.internalWinId();
+ QCOMPARE(winIdBefore, winIdAfter);
+ QCOMPARE(child.winIdChangeEventCount(), 1);
+ }
+
+ {
+ // Changing parent of an alien widget
+ QWidget parent1, parent2;
+ WinIdChangeWidget child(&parent1);
+ const WId winIdBefore = child.internalWinId();
+ child.setParent(&parent2);
+ const WId winIdAfter = child.internalWinId();
+ QCOMPARE(winIdBefore, winIdAfter);
+ QCOMPARE(child.winIdChangeEventCount(), 0);
+ }
+
+ {
+ // Making native child widget into a top-level window
+ QWidget parent;
+ WinIdChangeWidget child(&parent);
+ child.winId();
+ const WId winIdBefore = child.internalWinId();
+ QCOMPARE(child.winIdChangeEventCount(), 1);
+ const Qt::WindowFlags flags = child.windowFlags();
+ child.setWindowFlags(flags | Qt::Window);
+ const WId winIdAfter = child.internalWinId();
+ QVERIFY(winIdBefore != winIdAfter);
+ QCOMPARE(child.winIdChangeEventCount(), 3);
+ // winId is set to zero during reparenting
+ QVERIFY(0 == child.m_winIdList[1]);
+ }
+}
+
+void tst_QWidget::persistentWinId()
+{
+ QWidget *parent = new QWidget;
+ QWidget *w1 = new QWidget;
+ QWidget *w2 = new QWidget;
+ QWidget *w3 = new QWidget;
+ w1->setParent(parent);
+ w2->setParent(w1);
+ w3->setParent(w2);
+
+ WId winId1 = w1->winId();
+ WId winId2 = w2->winId();
+ WId winId3 = w3->winId();
+
+ // reparenting should change the winId of the widget being reparented, but not of its children
+ w1->setParent(0);
+ QVERIFY(w1->winId() != winId1);
+ winId1 = w1->winId();
+ QCOMPARE(w2->winId(), winId2);
+ QCOMPARE(w3->winId(), winId3);
+
+ w1->setParent(parent);
+ QVERIFY(w1->winId() != winId1);
+ winId1 = w1->winId();
+ QCOMPARE(w2->winId(), winId2);
+ QCOMPARE(w3->winId(), winId3);
+
+ w2->setParent(0);
+ QVERIFY(w2->winId() != winId2);
+ winId2 = w2->winId();
+ QCOMPARE(w3->winId(), winId3);
+
+ w2->setParent(parent);
+ QVERIFY(w2->winId() != winId2);
+ winId2 = w2->winId();
+ QCOMPARE(w3->winId(), winId3);
+
+ w2->setParent(w1);
+ QVERIFY(w2->winId() != winId2);
+ winId2 = w2->winId();
+ QCOMPARE(w3->winId(), winId3);
+
+ w3->setParent(0);
+ QVERIFY(w3->winId() != winId3);
+ winId3 = w3->winId();
+
+ w3->setParent(w1);
+ QVERIFY(w3->winId() != winId3);
+ winId3 = w3->winId();
+
+ w3->setParent(w2);
+ QVERIFY(w3->winId() != winId3);
+ winId3 = w3->winId();
+
+ delete parent;
+}
+
+void tst_QWidget::showNativeChild()
+{
+ QWidget topLevel;
+ topLevel.setGeometry(0, 0, 100, 100);
+ QWidget child(&topLevel);
+ child.winId();
+ topLevel.show();
+ QTest::qWaitForWindowShown(&topLevel);
+}
+
+class ShowHideEventWidget : public QWidget
+{
+public:
+ int numberOfShowEvents, numberOfHideEvents;
+
+ ShowHideEventWidget(QWidget *parent = 0)
+ : QWidget(parent), numberOfShowEvents(0), numberOfHideEvents(0)
+ { }
+
+ void create()
+ { QWidget::create(); }
+
+ void showEvent(QShowEvent *)
+ { ++numberOfShowEvents; }
+
+ void hideEvent(QHideEvent *)
+ { ++numberOfHideEvents; }
+};
+
+void tst_QWidget::showHideEvent_data()
+{
+ QTest::addColumn<bool>("show");
+ QTest::addColumn<bool>("hide");
+ QTest::addColumn<bool>("create");
+ QTest::addColumn<int>("expectedShowEvents");
+ QTest::addColumn<int>("expectedHideEvents");
+
+ QTest::newRow("window: only show")
+ << true
+ << false
+ << false
+ << 1
+ << 0;
+ QTest::newRow("window: show/hide")
+ << true
+ << true
+ << false
+ << 1
+ << 1;
+ QTest::newRow("window: show/hide/create")
+ << true
+ << true
+ << true
+ << 1
+ << 1;
+ QTest::newRow("window: hide/create")
+ << false
+ << true
+ << true
+ << 0
+ << 0;
+ QTest::newRow("window: only hide")
+ << false
+ << true
+ << false
+ << 0
+ << 0;
+ QTest::newRow("window: nothing")
+ << false
+ << false
+ << false
+ << 0
+ << 0;
+}
+
+void tst_QWidget::showHideEvent()
+{
+ QFETCH(bool, show);
+ QFETCH(bool, hide);
+ QFETCH(bool, create);
+ QFETCH(int, expectedShowEvents);
+ QFETCH(int, expectedHideEvents);
+
+ ShowHideEventWidget widget;
+ if (show)
+ widget.show();
+ if (hide)
+ widget.hide();
+ if (create && !widget.testAttribute(Qt::WA_WState_Created))
+ widget.create();
+
+ QCOMPARE(widget.numberOfShowEvents, expectedShowEvents);
+ QCOMPARE(widget.numberOfHideEvents, expectedHideEvents);
+}
+
+void tst_QWidget::update()
+{
+ QTest::qWait(10); // Wait for the initStuff to do it's stuff.
+ Q_CHECK_PAINTEVENTS
+
+ UpdateWidget w;
+ w.setGeometry(50, 50, 100, 100);
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+
+ QApplication::processEvents();
+ QApplication::processEvents();
+
+#ifdef Q_OS_MAC
+ QEXPECT_FAIL(0, "Cocoa compositor says to paint this twice.", Continue);
+#endif
+ QTRY_COMPARE(w.numPaintEvents, 1);
+
+ QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
+ QCOMPARE(w.paintedRegion, w.visibleRegion());
+ w.reset();
+
+ UpdateWidget child(&w);
+ child.setGeometry(10, 10, 80, 80);
+ child.show();
+
+ QPoint childOffset = child.mapToParent(QPoint());
+
+ // widgets are transparent by default, so both should get repaints
+ {
+ QApplication::processEvents();
+ QApplication::processEvents();
+ QCOMPARE(child.numPaintEvents, 1);
+ QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
+ QCOMPARE(child.paintedRegion, child.visibleRegion());
+ QCOMPARE(w.numPaintEvents, 1);
+ QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
+ QCOMPARE(w.paintedRegion, child.visibleRegion().translated(childOffset));
+
+ w.reset();
+ child.reset();
+
+ w.update();
+ QApplication::processEvents();
+ QApplication::processEvents();
+ QCOMPARE(child.numPaintEvents, 1);
+ QCOMPARE(child.visibleRegion(), QRegion(child.rect()));
+ QCOMPARE(child.paintedRegion, child.visibleRegion());
+ QCOMPARE(w.numPaintEvents, 1);
+ QCOMPARE(w.visibleRegion(), QRegion(w.rect()));
+ QCOMPARE(w.paintedRegion, w.visibleRegion());
+ }
+
+ QPalette opaquePalette = child.palette();
+ opaquePalette.setColor(child.backgroundRole(), QColor(Qt::red));
+
+ // setting an opaque background on the child should prevent paint-events
+ // for the parent in the child area
+ {
+ child.setPalette(opaquePalette);
+ child.setAutoFillBackground(true);
+ QApplication::processEvents();
+
+ w.reset();
+ child.reset();
+
+ w.update();
+ QApplication::processEvents();
+ QApplication::processEvents();
+
+ QCOMPARE(w.numPaintEvents, 1);
+ QRegion expectedVisible = QRegion(w.rect())
+ - child.visibleRegion().translated(childOffset);
+ QCOMPARE(w.visibleRegion(), expectedVisible);
+ QCOMPARE(w.paintedRegion, expectedVisible);
+ QCOMPARE(child.numPaintEvents, 0);
+
+ w.reset();
+ child.reset();
+
+ child.update();
+ QApplication::processEvents();
+ QApplication::processEvents();
+
+ QCOMPARE(w.numPaintEvents, 0);
+ QCOMPARE(child.numPaintEvents, 1);
+ QCOMPARE(child.paintedRegion, child.visibleRegion());
+
+ w.reset();
+ child.reset();
+ }
+
+ // overlapping sibling
+ UpdateWidget sibling(&w);
+ child.setGeometry(10, 10, 20, 20);
+ sibling.setGeometry(15, 15, 20, 20);
+ sibling.show();
+
+ QApplication::processEvents();
+ w.reset();
+ child.reset();
+ sibling.reset();
+
+ const QPoint siblingOffset = sibling.mapToParent(QPoint());
+
+ sibling.update();
+ QApplication::processEvents();
+ QApplication::processEvents();
+
+ // child is opaque, sibling transparent
+ {
+ QCOMPARE(sibling.numPaintEvents, 1);
+ QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
+
+ QCOMPARE(child.numPaintEvents, 1);
+ QCOMPARE(child.paintedRegion.translated(childOffset),
+ child.visibleRegion().translated(childOffset)
+ & sibling.visibleRegion().translated(siblingOffset));
+
+ QCOMPARE(w.numPaintEvents, 1);
+ QCOMPARE(w.paintedRegion,
+ w.visibleRegion() & sibling.visibleRegion().translated(siblingOffset));
+ QCOMPARE(w.paintedRegion,
+ (w.visibleRegion() - child.visibleRegion().translated(childOffset))
+ & sibling.visibleRegion().translated(siblingOffset));
+
+ }
+ w.reset();
+ child.reset();
+ sibling.reset();
+
+ sibling.setPalette(opaquePalette);
+ sibling.setAutoFillBackground(true);
+
+ sibling.update();
+ QApplication::processEvents();
+ QApplication::processEvents();
+
+ // child opaque, sibling opaque
+ {
+ QCOMPARE(sibling.numPaintEvents, 1);
+ QCOMPARE(sibling.paintedRegion, sibling.visibleRegion());
+
+#ifdef Q_OS_MAC
+ if (child.internalWinId()) // child is native
+ QEXPECT_FAIL(0, "Cocoa compositor paints child and sibling", Continue);
+#endif
+ QCOMPARE(child.numPaintEvents, 0);
+ QCOMPARE(child.visibleRegion(),
+ QRegion(child.rect())
+ - sibling.visibleRegion().translated(siblingOffset - childOffset));
+
+ QCOMPARE(w.numPaintEvents, 0);
+ QCOMPARE(w.visibleRegion(),
+ QRegion(w.rect())
+ - child.visibleRegion().translated(childOffset)
+ - sibling.visibleRegion().translated(siblingOffset));
+ }
+}
+
+static inline bool isOpaque(QWidget *widget)
+{
+ if (!widget)
+ return false;
+ return qt_widget_private(widget)->isOpaque;
+}
+
+void tst_QWidget::isOpaque()
+{
+#ifndef Q_WS_MAC
+ QWidget w;
+ QVERIFY(::isOpaque(&w));
+
+ QWidget child(&w);
+ QVERIFY(!::isOpaque(&child));
+
+ child.setAutoFillBackground(true);
+ QVERIFY(::isOpaque(&child));
+
+ QPalette palette;
+
+ // background color
+
+ palette = child.palette();
+ palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 127));
+ child.setPalette(palette);
+ QVERIFY(!::isOpaque(&child));
+
+ palette.setColor(child.backgroundRole(), QColor(255, 0, 0, 255));
+ child.setPalette(palette);
+ QVERIFY(::isOpaque(&child));
+
+ palette.setColor(QPalette::Window, QColor(0, 0, 255, 127));
+ w.setPalette(palette);
+
+ QVERIFY(!::isOpaque(&w));
+
+ child.setAutoFillBackground(false);
+ QVERIFY(!::isOpaque(&child));
+
+ // Qt::WA_OpaquePaintEvent
+
+ child.setAttribute(Qt::WA_OpaquePaintEvent);
+ QVERIFY(::isOpaque(&child));
+
+ child.setAttribute(Qt::WA_OpaquePaintEvent, false);
+ QVERIFY(!::isOpaque(&child));
+
+ // Qt::WA_NoSystemBackground
+
+ child.setAttribute(Qt::WA_NoSystemBackground);
+ QVERIFY(!::isOpaque(&child));
+
+ child.setAttribute(Qt::WA_NoSystemBackground, false);
+ QVERIFY(!::isOpaque(&child));
+
+ palette.setColor(QPalette::Window, QColor(0, 0, 255, 255));
+ w.setPalette(palette);
+ QVERIFY(::isOpaque(&w));
+
+ w.setAttribute(Qt::WA_NoSystemBackground);
+ QVERIFY(!::isOpaque(&w));
+
+ w.setAttribute(Qt::WA_NoSystemBackground, false);
+ QVERIFY(::isOpaque(&w));
+
+ {
+ QPalette palette = QApplication::palette();
+ QPalette old = palette;
+ palette.setColor(QPalette::Window, Qt::transparent);
+ QApplication::setPalette(palette);
+
+ QWidget widget;
+ QVERIFY(!::isOpaque(&widget));
+
+ QApplication::setPalette(old);
+ QCOMPARE(::isOpaque(&widget), old.color(QPalette::Window).alpha() == 255);
+ }
+#endif
+}
+
+#ifndef Q_WS_MAC
+/*
+ Test that scrolling of a widget invalidates the correct regions
+*/
+void tst_QWidget::scroll()
+{
+ UpdateWidget updateWidget;
+ updateWidget.resize(500, 500);
+ updateWidget.reset();
+ updateWidget.show();
+ QTest::qWaitForWindowShown(&updateWidget);
+ QTest::qWait(50);
+ qApp->processEvents();
+ QTRY_VERIFY(updateWidget.numPaintEvents > 0);
+
+ {
+ updateWidget.reset();
+ updateWidget.scroll(10, 10);
+ qApp->processEvents();
+ QRegion dirty(QRect(0, 0, 500, 10));
+ dirty += QRegion(QRect(0, 10, 10, 490));
+ QCOMPARE(updateWidget.paintedRegion, dirty);
+ }
+
+ {
+ updateWidget.reset();
+ updateWidget.update(0, 0, 10, 10);
+ updateWidget.scroll(0, 10);
+ qApp->processEvents();
+ QRegion dirty(QRect(0, 0, 500, 10));
+ dirty += QRegion(QRect(0, 10, 10, 10));
+ QCOMPARE(updateWidget.paintedRegion, dirty);
+ }
+
+ {
+ updateWidget.reset();
+ updateWidget.update(0, 0, 100, 100);
+ updateWidget.scroll(10, 10, QRect(50, 50, 100, 100));
+ qApp->processEvents();
+ QRegion dirty(QRect(0, 0, 100, 50));
+ dirty += QRegion(QRect(0, 50, 150, 10));
+ dirty += QRegion(QRect(0, 60, 110, 40));
+ dirty += QRegion(QRect(50, 100, 60, 10));
+ dirty += QRegion(QRect(50, 110, 10, 40));
+ QCOMPARE(updateWidget.paintedRegion, dirty);
+ }
+
+ {
+ updateWidget.reset();
+ updateWidget.update(0, 0, 100, 100);
+ updateWidget.scroll(10, 10, QRect(100, 100, 100, 100));
+ qApp->processEvents();
+ QRegion dirty(QRect(0, 0, 100, 100));
+ dirty += QRegion(QRect(100, 100, 100, 10));
+ dirty += QRegion(QRect(100, 110, 10, 90));
+ QCOMPARE(updateWidget.paintedRegion, dirty);
+ }
+}
+#endif
+
+class DestroyedSlotChecker : public QObject
+{
+ Q_OBJECT
+
+public:
+ bool wasQWidget;
+
+ DestroyedSlotChecker()
+ : wasQWidget(false)
+ {
+ }
+
+public slots:
+ void destroyedSlot(QObject *object)
+ {
+ wasQWidget = (qobject_cast<QWidget *>(object) != 0 || object->isWidgetType());
+ }
+};
+
+/*
+ Test that qobject_cast<QWidget*> returns 0 in a slot
+ connected to QObject::destroyed.
+*/
+void tst_QWidget::qobject_castInDestroyedSlot()
+{
+ DestroyedSlotChecker checker;
+ QWidget *widget = new QWidget();
+
+ QObject::connect(widget, SIGNAL(destroyed(QObject *)), &checker, SLOT(destroyedSlot(QObject *)));
+ delete widget;
+
+ QVERIFY(checker.wasQWidget == true);
+}
+
+Q_DECLARE_METATYPE(QList<QRect>)
+
+// Since X11 WindowManager operations are all async, and we have no way to know if the window
+// manager has finished playing with the window geometry, this test can't be reliable on X11.
+#ifndef Q_WS_X11
+void tst_QWidget::setWindowGeometry_data()
+{
+ QTest::addColumn<QList<QRect> >("rects");
+ QTest::addColumn<int>("windowFlags");
+
+ QList<QList<QRect> > rects;
+ rects << (QList<QRect>()
+ << QRect(100, 100, 200, 200)
+ << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
+ << QRect(130, 100, 0, 200)
+ << QRect(100, 50, 200, 0)
+ << QRect(130, 50, 0, 0))
+ << (QList<QRect>()
+ << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
+ << QRect(130, 100, 0, 200)
+ << QRect(100, 50, 200, 0)
+ << QRect(130, 50, 0, 0)
+ << QRect(100, 100, 200, 200))
+ << (QList<QRect>()
+ << QRect(130, 100, 0, 200)
+ << QRect(100, 50, 200, 0)
+ << QRect(130, 50, 0, 0)
+ << QRect(100, 100, 200, 200)
+ << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100))
+ << (QList<QRect>()
+ << QRect(100, 50, 200, 0)
+ << QRect(130, 50, 0, 0)
+ << QRect(100, 100, 200, 200)
+ << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
+ << QRect(130, 100, 0, 200))
+ << (QList<QRect>()
+ << QRect(130, 50, 0, 0)
+ << QRect(100, 100, 200, 200)
+ << QApplication::desktop()->availableGeometry().adjusted(100, 100, -100, -100)
+ << QRect(130, 100, 0, 200)
+ << QRect(100, 50, 200, 0));
+
+ QList<int> windowFlags;
+ windowFlags << 0 << Qt::FramelessWindowHint;
+
+ foreach (QList<QRect> l, rects) {
+ QRect rect = l.first();
+ foreach (int windowFlag, windowFlags) {
+ QTest::newRow(QString("%1,%2 %3x%4, flags %5")
+ .arg(rect.x())
+ .arg(rect.y())
+ .arg(rect.width())
+ .arg(rect.height())
+ .arg(windowFlag, 0, 16).toAscii())
+ << l
+ << windowFlag;
+ }
+ }
+}
+
+void tst_QWidget::setWindowGeometry()
+{
+ QFETCH(QList<QRect>, rects);
+ QFETCH(int, windowFlags);
+ QRect rect = rects.takeFirst();
+
+ {
+ // test setGeometry() without actually showing the window
+ QWidget widget;
+ if (windowFlags != 0)
+ widget.setWindowFlags(Qt::WindowFlags(windowFlags));
+
+ widget.setGeometry(rect);
+ QTest::qWait(100);
+ QCOMPARE(widget.geometry(), rect);
+
+ // setGeometry() without showing
+ foreach (QRect r, rects) {
+ widget.setGeometry(r);
+ QTest::qWait(100);
+ QCOMPARE(widget.geometry(), r);
+ }
+ }
+
+ {
+ // setGeometry() first, then show()
+ QWidget widget;
+ if (windowFlags != 0)
+ widget.setWindowFlags(Qt::WindowFlags(windowFlags));
+
+ widget.setGeometry(rect);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(20);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // setGeometry() while shown
+ foreach (QRect r, rects) {
+ widget.setGeometry(r);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), r);
+ }
+ widget.setGeometry(rect);
+ QTest::qWait(20);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // now hide
+ widget.hide();
+ QTest::qWait(20);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // setGeometry() after hide()
+ foreach (QRect r, rects) {
+ widget.setGeometry(r);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), r);
+ }
+ widget.setGeometry(rect);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // show() again, geometry() should still be the same
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // final hide(), again geometry() should be unchanged
+ widget.hide();
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+ }
+
+ {
+ // show() first, then setGeometry()
+ QWidget widget;
+ if (windowFlags != 0)
+ widget.setWindowFlags(Qt::WindowFlags(windowFlags));
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ widget.setGeometry(rect);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // setGeometry() while shown
+ foreach (QRect r, rects) {
+ widget.setGeometry(r);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), r);
+ }
+ widget.setGeometry(rect);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // now hide
+ widget.hide();
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // setGeometry() after hide()
+ foreach (QRect r, rects) {
+ widget.setGeometry(r);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), r);
+ }
+ widget.setGeometry(rect);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // show() again, geometry() should still be the same
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+
+ // final hide(), again geometry() should be unchanged
+ widget.hide();
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.geometry(), rect);
+ }
+}
+#endif
+
+#if defined (Q_WS_WIN) && !defined(Q_OS_WINCE)
+void tst_QWidget::setGeometry_win()
+{
+ QWidget widget;
+ widget.setGeometry(0, 600, 100,100);
+ widget.show();
+ widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
+ QRect geom = widget.normalGeometry();
+ widget.close();
+ widget.setGeometry(geom);
+ widget.setWindowState(widget.windowState() | Qt::WindowMaximized);
+ widget.show();
+ RECT rt;
+ ::GetWindowRect(widget.internalWinId(), &rt);
+ QVERIFY(rt.left <= 0);
+ QVERIFY(rt.top <= 0);
+}
+#endif
+
+// Since X11 WindowManager operation are all async, and we have no way to know if the window
+// manager has finished playing with the window geometry, this test can't be reliable on X11.
+// 4DWM issues on IRIX also makes this test fail.
+#if !defined(Q_WS_X11) && !defined(Q_OS_IRIX)
+void tst_QWidget::windowMoveResize_data()
+{
+ setWindowGeometry_data();
+}
+
+void tst_QWidget::windowMoveResize()
+{
+ QFETCH(QList<QRect>, rects);
+ QFETCH(int, windowFlags);
+
+ QRect rect = rects.takeFirst();
+
+ {
+ // test setGeometry() without actually showing the window
+ QWidget widget;
+ if (windowFlags != 0)
+ widget.setWindowFlags(Qt::WindowFlags(windowFlags));
+
+ widget.move(rect.topLeft());
+ widget.resize(rect.size());
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // move() without showing
+ foreach (QRect r, rects) {
+ widget.move(r.topLeft());
+ widget.resize(r.size());
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), r.topLeft());
+ QTRY_COMPARE(widget.size(), r.size());
+ }
+ }
+
+ {
+ // move() first, then show()
+ QWidget widget;
+ if (windowFlags != 0)
+ widget.setWindowFlags(Qt::WindowFlags(windowFlags));
+
+ widget.move(rect.topLeft());
+ widget.resize(rect.size());
+ widget.show();
+
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // move() while shown
+ foreach (QRect r, rects) {
+#ifdef Q_WS_X11
+ if ((widget.width() == 0 || widget.height() == 0) && r.width() != 0 && r.height() != 0) {
+ QEXPECT_FAIL("130,100 0x200, flags 0",
+ "First resize after show of zero-sized gets wrong win_gravity.",
+ Continue);
+ QEXPECT_FAIL("100,50 200x0, flags 0",
+ "First resize after show of zero-sized gets wrong win_gravity.",
+ Continue);
+ QEXPECT_FAIL("130,50 0x0, flags 0",
+ "First resize after show of zero-sized gets wrong win_gravity.",
+ Continue);
+ }
+#endif
+ widget.move(r.topLeft());
+ widget.resize(r.size());
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), r.topLeft());
+ QTRY_COMPARE(widget.size(), r.size());
+ }
+ widget.move(rect.topLeft());
+ widget.resize(rect.size());
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // now hide
+ widget.hide();
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // move() after hide()
+ foreach (QRect r, rects) {
+ widget.move(r.topLeft());
+ widget.resize(r.size());
+ QApplication::processEvents();
+#if defined(Q_WS_MAC)
+ if (r.width() == 0 && r.height() > 0) {
+ widget.move(r.topLeft());
+ widget.resize(r.size());
+ }
+#endif
+ QTRY_COMPARE(widget.pos(), r.topLeft());
+ QTRY_COMPARE(widget.size(), r.size());
+ }
+ widget.move(rect.topLeft());
+ widget.resize(rect.size());
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // show() again, pos() should be the same
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // final hide(), again pos() should be unchanged
+ widget.hide();
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+ }
+
+ {
+ // show() first, then move()
+ QWidget widget;
+ if (windowFlags != 0)
+ widget.setWindowFlags(Qt::WindowFlags(windowFlags));
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+ widget.move(rect.topLeft());
+ widget.resize(rect.size());
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // move() while shown
+ foreach (QRect r, rects) {
+ widget.move(r.topLeft());
+ widget.resize(r.size());
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), r.topLeft());
+ QTRY_COMPARE(widget.size(), r.size());
+ }
+ widget.move(rect.topLeft());
+ widget.resize(rect.size());
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // now hide
+ widget.hide();
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // move() after hide()
+ foreach (QRect r, rects) {
+ widget.move(r.topLeft());
+ widget.resize(r.size());
+ QApplication::processEvents();
+#if defined(Q_WS_MAC)
+ if (r.width() == 0 && r.height() > 0) {
+ widget.move(r.topLeft());
+ widget.resize(r.size());
+ }
+#endif
+ QTRY_COMPARE(widget.pos(), r.topLeft());
+ QTRY_COMPARE(widget.size(), r.size());
+ }
+ widget.move(rect.topLeft());
+ widget.resize(rect.size());
+ QApplication::processEvents();
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // show() again, pos() should be the same
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+
+ // final hide(), again pos() should be unchanged
+ widget.hide();
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.pos(), rect.topLeft());
+ QTRY_COMPARE(widget.size(), rect.size());
+ }
+}
+#endif
+
+class ColorWidget : public QWidget
+{
+public:
+ ColorWidget(QWidget *parent = 0, const QColor &c = QColor(Qt::red))
+ : QWidget(parent, Qt::FramelessWindowHint), color(c)
+ {
+ QPalette opaquePalette = palette();
+ opaquePalette.setColor(backgroundRole(), color);
+ setPalette(opaquePalette);
+ setAutoFillBackground(true);
+ }
+
+ void paintEvent(QPaintEvent *e) {
+ r += e->region();
+ }
+
+ void reset() {
+ r = QRegion();
+ }
+
+ QColor color;
+ QRegion r;
+};
+
+#define VERIFY_COLOR(region, color) { \
+ const QRegion r = QRegion(region); \
+ for (int i = 0; i < r.rects().size(); ++i) { \
+ const QRect rect = r.rects().at(i); \
+ for (int t = 0; t < 5; t++) { \
+ const QPixmap pixmap = QPixmap::grabWindow(QDesktopWidget().winId(), \
+ rect.left(), rect.top(), \
+ rect.width(), rect.height()); \
+ QCOMPARE(pixmap.size(), rect.size()); \
+ QPixmap expectedPixmap(pixmap); /* ensure equal formats */ \
+ expectedPixmap.detach(); \
+ expectedPixmap.fill(color); \
+ QImage image = pixmap.toImage(); \
+ uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; \
+ uint firstPixel = image.pixel(0,0) | alphaCorrection; \
+ if ( firstPixel != QColor(color).rgb() && t < 4 ) \
+ { QTest::qWait(200); continue; } \
+ QCOMPARE(firstPixel, QColor(color).rgb()); \
+ QCOMPARE(pixmap, expectedPixmap); \
+ break; \
+ } \
+ } \
+}
+
+void tst_QWidget::moveChild_data()
+{
+ QTest::addColumn<QPoint>("offset");
+
+ QTest::newRow("right") << QPoint(20, 0);
+ QTest::newRow("down") << QPoint(0, 20);
+ QTest::newRow("left") << QPoint(-20, 0);
+ QTest::newRow("up") << QPoint(0, -20);
+}
+
+void tst_QWidget::moveChild()
+{
+ QFETCH(QPoint, offset);
+
+ ColorWidget parent;
+ // prevent custom styles
+ parent.setStyle(new QWindowsStyle);
+ ColorWidget child(&parent, Qt::blue);
+
+#ifndef Q_OS_WINCE
+ parent.setGeometry(QRect(QPoint(QApplication::desktop()->availableGeometry(&parent).topLeft()),
+ QSize(100, 100)));
+#else
+ parent.setGeometry(60, 60, 150, 150);
+#endif
+ child.setGeometry(25, 25, 50, 50);
+ QPoint childOffset = child.mapToGlobal(QPoint());
+
+ parent.show();
+ QTest::qWaitForWindowShown(&parent);
+ QTest::qWait(30);
+ const QPoint tlwOffset = parent.geometry().topLeft();
+
+ QTRY_COMPARE(parent.r, QRegion(parent.rect()) - child.geometry());
+ QTRY_COMPARE(child.r, QRegion(child.rect()));
+ VERIFY_COLOR(child.geometry().translated(tlwOffset),
+ child.color);
+ VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
+ parent.color);
+ parent.reset();
+ child.reset();
+
+ // move
+
+ const QRect oldGeometry = child.geometry();
+
+ QPoint pos = child.pos() + offset;
+ child.move(pos);
+ QTest::qWait(100);
+ QTRY_COMPARE(pos, child.pos());
+
+ QCOMPARE(parent.r, QRegion(oldGeometry) - child.geometry());
+#if !defined(Q_WS_MAC)
+ // should be scrolled in backingstore
+ QCOMPARE(child.r, QRegion());
+#endif
+ VERIFY_COLOR(child.geometry().translated(tlwOffset),
+ child.color);
+ VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset),
+ parent.color);
+}
+
+void tst_QWidget::showAndMoveChild()
+{
+ QWidget parent(0, Qt::FramelessWindowHint);
+ // prevent custom styles
+ parent.setStyle(new QWindowsStyle);
+
+ QDesktopWidget desktop;
+ QRect desktopDimensions = desktop.availableGeometry(&parent);
+ desktopDimensions = desktopDimensions.adjusted(64, 64, -64, -64);
+
+ parent.setGeometry(desktopDimensions);
+ parent.setPalette(Qt::red);
+ parent.show();
+ QTest::qWaitForWindowShown(&parent);
+ QTest::qWait(10);
+
+ const QPoint tlwOffset = parent.geometry().topLeft();
+ QWidget child(&parent);
+ child.resize(desktopDimensions.width()/2, desktopDimensions.height()/2);
+ child.setPalette(Qt::blue);
+ child.setAutoFillBackground(true);
+
+ // Ensure that the child is repainted correctly when moved right after show.
+ // NB! Do NOT processEvents() (or qWait()) in between show() and move().
+ child.show();
+ child.move(desktopDimensions.width()/2, desktopDimensions.height()/2);
+ qApp->processEvents();
+
+ VERIFY_COLOR(child.geometry().translated(tlwOffset), Qt::blue);
+ VERIFY_COLOR(QRegion(parent.geometry()) - child.geometry().translated(tlwOffset), Qt::red);
+}
+
+// Cocoa only has rect granularity.
+#ifndef QT_OS_MAC
+void tst_QWidget::subtractOpaqueSiblings()
+{
+ QWidget w;
+ w.setGeometry(50, 50, 300, 300);
+
+ ColorWidget *large = new ColorWidget(&w, Qt::red);
+ large->setGeometry(50, 50, 200, 200);
+
+ ColorWidget *medium = new ColorWidget(large, Qt::gray);
+ medium->setGeometry(50, 50, 100, 100);
+
+ ColorWidget *tall = new ColorWidget(&w, Qt::blue);
+ tall->setGeometry(100, 30, 50, 100);
+
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QTest::qWait(10);
+
+ large->reset();
+ medium->reset();
+ tall->reset();
+
+ medium->update();
+ QTest::qWait(10);
+
+ // QWidgetPrivate::subtractOpaqueSiblings() should prevent parts of medium
+ // to be repainted and tall from be repainted at all.
+
+ QTRY_COMPARE(large->r, QRegion());
+ QTRY_COMPARE(tall->r, QRegion());
+ QTRY_COMPARE(medium->r.translated(medium->mapTo(&w, QPoint())),
+ QRegion(medium->geometry().translated(large->pos()))
+ - tall->geometry());
+}
+#endif
+
+void tst_QWidget::deleteStyle()
+{
+ QWidget widget;
+ widget.setStyle(new QWindowsStyle);
+ widget.show();
+ delete widget.style();
+ qApp->processEvents();
+}
+
+#ifdef Q_WS_WIN
+void tst_QWidget::getDC()
+{
+ QWidget widget;
+ widget.setGeometry(0, 0, 2, 4);
+
+ HDC dc = widget.getDC();
+ QVERIFY(dc != 0);
+
+ widget.releaseDC(dc);
+}
+#endif
+
+class TopLevelFocusCheck: public QWidget
+{
+ Q_OBJECT
+public:
+ QLineEdit* edit;
+ TopLevelFocusCheck(QWidget* parent = 0) : QWidget(parent)
+ {
+ edit = new QLineEdit(this);
+ edit->hide();
+ edit->installEventFilter(this);
+ }
+
+public slots:
+ void mouseDoubleClickEvent ( QMouseEvent * /*event*/ )
+ {
+ edit->show();
+ edit->setFocus(Qt::OtherFocusReason);
+ qApp->processEvents();
+ }
+ bool eventFilter(QObject *obj, QEvent *event)
+ {
+ if (obj == edit && event->type()== QEvent::FocusOut) {
+ edit->hide();
+ return true;
+ }
+ return false;
+ }
+};
+
+void tst_QWidget::multipleToplevelFocusCheck()
+{
+ TopLevelFocusCheck w1;
+ TopLevelFocusCheck w2;
+
+ w1.resize(200, 200);
+ w1.show();
+ QTest::qWaitForWindowShown(&w1);
+ w2.resize(200,200);
+ w2.show();
+ QTest::qWaitForWindowShown(&w2);
+
+ QTest::qWait(100);
+
+ QApplication::setActiveWindow(&w1);
+ w1.activateWindow();
+ QApplication::processEvents();
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
+ QTest::qWait(50);
+ QTest::mouseDClick(&w1, Qt::LeftButton);
+ QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
+
+ w2.activateWindow();
+ QApplication::setActiveWindow(&w2);
+ QApplication::processEvents();
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
+ QTest::mouseClick(&w2, Qt::LeftButton);
+#ifdef Q_WS_QWS
+ QEXPECT_FAIL("", "embedded toplevels take focus anyway", Continue);
+#endif
+ QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
+
+ QTest::mouseDClick(&w2, Qt::LeftButton);
+ QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w2.edit));
+
+ w1.activateWindow();
+ QApplication::setActiveWindow(&w1);
+ QApplication::processEvents();
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1));
+ QTest::mouseDClick(&w1, Qt::LeftButton);
+ QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit));
+
+ w2.activateWindow();
+ QApplication::setActiveWindow(&w2);
+ QApplication::processEvents();
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2));
+ QTest::mouseClick(&w2, Qt::LeftButton);
+ QTRY_COMPARE(QApplication::focusWidget(), (QWidget *)0);
+}
+
+void tst_QWidget::setFocus()
+{
+ {
+ // move focus to another window
+ testWidget->activateWindow();
+ QApplication::setActiveWindow(testWidget);
+ if (testWidget->focusWidget())
+ testWidget->focusWidget()->clearFocus();
+ else
+ testWidget->clearFocus();
+
+ // window and children never shown, nobody gets focus
+ QWidget window;
+
+ QWidget child1(&window);
+ child1.setFocusPolicy(Qt::StrongFocus);
+
+ QWidget child2(&window);
+ child2.setFocusPolicy(Qt::StrongFocus);
+
+ child1.setFocus();
+ QVERIFY(!child1.hasFocus());
+ QCOMPARE(window.focusWidget(), &child1);
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child2.setFocus();
+ QVERIFY(!child2.hasFocus());
+ QCOMPARE(window.focusWidget(), &child2);
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+ }
+
+ {
+ // window and children show, but window not active, nobody gets focus
+ QWidget window;
+
+ QWidget child1(&window);
+ child1.setFocusPolicy(Qt::StrongFocus);
+
+ QWidget child2(&window);
+ child2.setFocusPolicy(Qt::StrongFocus);
+
+ window.show();
+
+ // note: window may be active, but we don't want it to be
+ testWidget->activateWindow();
+ QApplication::setActiveWindow(testWidget);
+ if (testWidget->focusWidget())
+ testWidget->focusWidget()->clearFocus();
+ else
+ testWidget->clearFocus();
+
+ child1.setFocus();
+ QVERIFY(!child1.hasFocus());
+ QCOMPARE(window.focusWidget(), &child1);
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child2.setFocus();
+ QVERIFY(!child2.hasFocus());
+ QCOMPARE(window.focusWidget(), &child2);
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+ }
+
+ {
+ // window and children show, but window *is* active, children get focus
+ QWidget window;
+
+ QWidget child1(&window);
+ child1.setFocusPolicy(Qt::StrongFocus);
+
+ QWidget child2(&window);
+ child2.setFocusPolicy(Qt::StrongFocus);
+
+ window.show();
+#ifdef Q_WS_X11
+ QApplication::setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+#else
+ window.activateWindow();
+ QApplication::processEvents();
+#endif
+
+ child1.setFocus();
+ QTRY_VERIFY(child1.hasFocus());
+ QCOMPARE(window.focusWidget(), &child1);
+ QCOMPARE(QApplication::focusWidget(), &child1);
+
+ child2.setFocus();
+ QVERIFY(child2.hasFocus());
+ QCOMPARE(window.focusWidget(), &child2);
+ QCOMPARE(QApplication::focusWidget(), &child2);
+ }
+
+ {
+ // window shown and active, children created, don't get focus, but get focus when shown
+ QWidget window;
+
+ window.show();
+#ifdef Q_WS_X11
+ QApplication::setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+#else
+ window.activateWindow();
+#endif
+
+ QWidget child1(&window);
+ child1.setFocusPolicy(Qt::StrongFocus);
+
+ QWidget child2(&window);
+ child2.setFocusPolicy(Qt::StrongFocus);
+
+ child1.setFocus();
+ QVERIFY(!child1.hasFocus());
+ QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child1.show();
+#ifdef Q_WS_X11
+ QApplication::setActiveWindow(&child1);
+ child1.activateWindow();
+#endif
+ QApplication::processEvents();
+ QTRY_VERIFY(child1.hasFocus());
+ QCOMPARE(window.focusWidget(), &child1);
+ QCOMPARE(QApplication::focusWidget(), &child1);
+
+ child2.setFocus();
+ QVERIFY(!child2.hasFocus());
+ QCOMPARE(window.focusWidget(), &child1);
+ QCOMPARE(QApplication::focusWidget(), &child1);
+
+ child2.show();
+ QVERIFY(child2.hasFocus());
+ QCOMPARE(window.focusWidget(), &child2);
+ QCOMPARE(QApplication::focusWidget(), &child2);
+ }
+
+ {
+ // window shown and active, children created, don't get focus,
+ // even after setFocus(), hide(), then show()
+ QWidget window;
+
+ window.show();
+#ifdef Q_WS_X11
+ QApplication::setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+#else
+ window.activateWindow();
+#endif
+
+ QWidget child1(&window);
+ child1.setFocusPolicy(Qt::StrongFocus);
+
+ QWidget child2(&window);
+ child2.setFocusPolicy(Qt::StrongFocus);
+
+ child1.setFocus();
+ QVERIFY(!child1.hasFocus());
+ QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child1.hide();
+ QVERIFY(!child1.hasFocus());
+ QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child1.show();
+ QVERIFY(!child1.hasFocus());
+ QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child2.setFocus();
+ QVERIFY(!child2.hasFocus());
+ QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child2.hide();
+ QVERIFY(!child2.hasFocus());
+ QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+
+ child2.show();
+ QVERIFY(!child2.hasFocus());
+ QCOMPARE(window.focusWidget(), static_cast<QWidget *>(0));
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(0));
+ }
+}
+
+class EventSpy : public QObject
+{
+public:
+ EventSpy(QWidget *widget, QEvent::Type event)
+ : m_widget(widget), eventToSpy(event), m_count(0)
+ {
+ if (m_widget)
+ m_widget->installEventFilter(this);
+ }
+
+ QWidget *widget() const { return m_widget; }
+ int count() const { return m_count; }
+ void clear() { m_count = 0; }
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event)
+ {
+ if (event->type() == eventToSpy)
+ ++m_count;
+ return QObject::eventFilter(object, event);
+ }
+
+private:
+ QWidget *m_widget;
+ QEvent::Type eventToSpy;
+ int m_count;
+};
+
+void tst_QWidget::setCursor()
+{
+#ifndef QT_NO_CURSOR
+ {
+ QWidget window;
+ QWidget child(&window);
+
+ QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+
+ window.setCursor(window.cursor());
+ QVERIFY(window.testAttribute(Qt::WA_SetCursor));
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window.cursor().shape());
+ }
+
+ // do it again, but with window show()n
+ {
+ QWidget window;
+ QWidget child(&window);
+ window.show();
+
+ QVERIFY(!window.testAttribute(Qt::WA_SetCursor));
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+
+ window.setCursor(window.cursor());
+ QVERIFY(window.testAttribute(Qt::WA_SetCursor));
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window.cursor().shape());
+ }
+
+
+ {
+ QWidget window;
+ QWidget child(&window);
+
+ window.setCursor(Qt::WaitCursor);
+ QVERIFY(window.testAttribute(Qt::WA_SetCursor));
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window.cursor().shape());
+ }
+
+ // same thing again, just with window show()n
+ {
+ QWidget window;
+ QWidget child(&window);
+
+ window.show();
+ window.setCursor(Qt::WaitCursor);
+ QVERIFY(window.testAttribute(Qt::WA_SetCursor));
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window.cursor().shape());
+ }
+
+ // reparenting child should not cause the WA_SetCursor to become set
+ {
+ QWidget window;
+ QWidget window2;
+ QWidget child(&window);
+
+ window.setCursor(Qt::WaitCursor);
+
+ child.setParent(0);
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), QCursor().shape());
+
+ child.setParent(&window2);
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window2.cursor().shape());
+
+ window2.setCursor(Qt::WaitCursor);
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window2.cursor().shape());
+ }
+
+ // again, with windows show()n
+ {
+ QWidget window;
+ QWidget window2;
+ QWidget child(&window);
+
+ window.setCursor(Qt::WaitCursor);
+ window.show();
+
+ child.setParent(0);
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), QCursor().shape());
+
+ child.setParent(&window2);
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window2.cursor().shape());
+
+ window2.show();
+ window2.setCursor(Qt::WaitCursor);
+ QVERIFY(!child.testAttribute(Qt::WA_SetCursor));
+ QCOMPARE(child.cursor().shape(), window2.cursor().shape());
+ }
+
+ // test if CursorChange is sent
+ {
+ QWidget widget;
+ EventSpy spy(&widget, QEvent::CursorChange);
+ QCOMPARE(spy.count(), 0);
+ widget.setCursor(QCursor(Qt::WaitCursor));
+ QCOMPARE(spy.count(), 1);
+ widget.unsetCursor();
+ QCOMPARE(spy.count(), 2);
+ }
+#endif
+}
+
+void tst_QWidget::setToolTip()
+{
+ QWidget widget;
+ EventSpy spy(&widget, QEvent::ToolTipChange);
+ QCOMPARE(spy.count(), 0);
+
+ QCOMPARE(widget.toolTip(), QString());
+ widget.setToolTip(QString("Hello"));
+ QCOMPARE(widget.toolTip(), QString("Hello"));
+ QCOMPARE(spy.count(), 1);
+ widget.setToolTip(QString());
+ QCOMPARE(widget.toolTip(), QString());
+ QCOMPARE(spy.count(), 2);
+
+ // Mouse over doesn't work on Windows mobile, so skip the rest of the test for that platform.
+#ifndef Q_OS_WINCE_WM
+ for (int pass = 0; pass < 2; ++pass) {
+ QWidget *popup = new QWidget(0, Qt::Popup);
+ popup->resize(150, 50);
+ QFrame *frame = new QFrame(popup);
+ frame->setGeometry(0, 0, 50, 50);
+ frame->setFrameStyle(QFrame::Box | QFrame::Plain);
+ EventSpy spy1(frame, QEvent::ToolTip);
+ EventSpy spy2(popup, QEvent::ToolTip);
+ frame->setMouseTracking(pass == 0 ? false : true);
+ frame->setToolTip(QLatin1String("TOOLTIP FRAME"));
+ popup->setToolTip(QLatin1String("TOOLTIP POPUP"));
+ popup->show();
+ QTest::qWaitForWindowShown(popup);
+ QTest::qWait(10);
+ QTest::mouseMove(frame);
+ QTest::qWait(900); // delay is 700
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 0);
+ if (pass == 0)
+ QTest::qWait(2200); // delay is 2000
+ QTest::mouseMove(popup);
+ delete popup;
+ }
+#endif
+}
+
+void tst_QWidget::testWindowIconChangeEventPropagation()
+{
+ // Create widget hierarchy.
+ QWidget topLevelWidget;
+ QWidget topLevelChild(&topLevelWidget);
+
+ QDialog dialog(&topLevelWidget);
+ QWidget dialogChild(&dialog);
+
+ QWidgetList widgets;
+ widgets << &topLevelWidget << &topLevelChild
+ << &dialog << &dialogChild;
+ QCOMPARE(widgets.count(), 4);
+
+ // Create spy lists.
+ QList <EventSpy *> applicationEventSpies;
+ QList <EventSpy *> widgetEventSpies;
+ foreach (QWidget *widget, widgets) {
+ applicationEventSpies.append(new EventSpy(widget, QEvent::ApplicationWindowIconChange));
+ widgetEventSpies.append(new EventSpy(widget, QEvent::WindowIconChange));
+ }
+
+ // QApplication::setWindowIcon
+ const QIcon windowIcon = qApp->style()->standardIcon(QStyle::SP_TitleBarMenuButton);
+ qApp->setWindowIcon(windowIcon);
+
+ for (int i = 0; i < widgets.count(); ++i) {
+ // Check QEvent::ApplicationWindowIconChange
+ EventSpy *spy = applicationEventSpies.at(i);
+ QWidget *widget = spy->widget();
+ if (widget->isWindow()) {
+ QCOMPARE(spy->count(), 1);
+ QCOMPARE(widget->windowIcon(), windowIcon);
+ } else {
+ QCOMPARE(spy->count(), 0);
+ }
+ spy->clear();
+
+ // Check QEvent::WindowIconChange
+ spy = widgetEventSpies.at(i);
+ QCOMPARE(spy->count(), 1);
+ spy->clear();
+ }
+
+ // Set icon on a top-level widget.
+ topLevelWidget.setWindowIcon(*new QIcon);
+
+ for (int i = 0; i < widgets.count(); ++i) {
+ // Check QEvent::ApplicationWindowIconChange
+ EventSpy *spy = applicationEventSpies.at(i);
+ QCOMPARE(spy->count(), 0);
+ spy->clear();
+
+ // Check QEvent::WindowIconChange
+ spy = widgetEventSpies.at(i);
+ QWidget *widget = spy->widget();
+ if (widget == &topLevelWidget) {
+ QCOMPARE(widget->windowIcon(), QIcon());
+ QCOMPARE(spy->count(), 1);
+ } else if (topLevelWidget.isAncestorOf(widget)) {
+ QCOMPARE(spy->count(), 1);
+ } else {
+ QCOMPARE(spy->count(), 0);
+ }
+ spy->clear();
+ }
+
+ // Cleanup.
+ for (int i = 0; i < widgets.count(); ++i) {
+ delete applicationEventSpies.at(i);
+ delete widgetEventSpies.at(i);
+ }
+ qApp->setWindowIcon(QIcon());
+}
+
+#ifdef Q_WS_X11
+void tst_QWidget::minAndMaxSizeWithX11BypassWindowManagerHint()
+{
+ // Same size as in QWidget::create_sys().
+ const QSize desktopSize = QApplication::desktop()->size();
+ const QSize originalSize(desktopSize.width() / 2, desktopSize.height() * 4 / 10);
+
+ { // Maximum size.
+ QWidget widget(0, Qt::X11BypassWindowManagerHint);
+
+ const QSize newMaximumSize = widget.size().boundedTo(originalSize) - QSize(10, 10);
+ widget.setMaximumSize(newMaximumSize);
+ QCOMPARE(widget.size(), newMaximumSize);
+
+ widget.show();
+ qt_x11_wait_for_window_manager(&widget);
+ QCOMPARE(widget.size(), newMaximumSize);
+ }
+
+ { // Minimum size.
+ QWidget widget(0, Qt::X11BypassWindowManagerHint);
+
+ const QSize newMinimumSize = widget.size().expandedTo(originalSize) + QSize(10, 10);
+ widget.setMinimumSize(newMinimumSize);
+ QCOMPARE(widget.size(), newMinimumSize);
+
+ widget.show();
+ qt_x11_wait_for_window_manager(&widget);
+ QCOMPARE(widget.size(), newMinimumSize);
+ }
+}
+
+class ShowHideShowWidget : public QWidget
+{
+ Q_OBJECT
+
+ int state;
+public:
+ bool gotExpectedMapNotify;
+
+ ShowHideShowWidget()
+ : state(0), gotExpectedMapNotify(false)
+ {
+ startTimer(1000);
+ }
+
+ void timerEvent(QTimerEvent *)
+ {
+ switch (state++) {
+ case 0:
+ show();
+ break;
+ case 1:
+ emit done();
+ break;
+ }
+ }
+
+ bool x11Event(XEvent *event)
+ {
+ if (state == 1 && event->type == MapNotify)
+ gotExpectedMapNotify = true;
+ return false;
+ }
+
+signals:
+ void done();
+};
+
+void tst_QWidget::showHideShow()
+{
+ ShowHideShowWidget w;
+ w.show();
+ w.hide();
+
+ QEventLoop eventLoop;
+ connect(&w, SIGNAL(done()), &eventLoop, SLOT(quit()));
+ eventLoop.exec();
+
+ QVERIFY(w.gotExpectedMapNotify);
+}
+
+void tst_QWidget::clean_qt_x11_enforce_cursor()
+{
+ {
+ QWidget window;
+ QWidget *w = new QWidget(&window);
+ QWidget *child = new QWidget(w);
+ child->setAttribute(Qt::WA_SetCursor, true);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ QTest::qWaitForWindowShown(&window);
+ QTest::qWait(100);
+ QCursor::setPos(window.geometry().center());
+ QTest::qWait(100);
+
+ child->setFocus();
+ QApplication::processEvents();
+ QTest::qWait(100);
+
+ delete w;
+ }
+
+ QGraphicsScene scene;
+ QLineEdit *edit = new QLineEdit;
+ scene.addWidget(edit);
+
+ // If the test didn't crash, then it passed.
+}
+#endif
+
+class EventRecorder : public QObject
+{
+ Q_OBJECT
+
+public:
+ typedef QList<QPair<QWidget *, QEvent::Type> > EventList;
+
+ EventRecorder(QObject *parent = 0)
+ : QObject(parent)
+ { }
+
+ EventList eventList()
+ {
+ return events;
+ }
+
+ void clear()
+ {
+ events.clear();
+ }
+
+ bool eventFilter(QObject *object, QEvent *event)
+ {
+ QWidget *widget = qobject_cast<QWidget *>(object);
+ if (widget && !event->spontaneous())
+ events.append(qMakePair(widget, event->type()));
+ return false;
+ }
+
+private:
+ EventList events;
+};
+
+void tst_QWidget::compatibilityChildInsertedEvents()
+{
+ EventRecorder::EventList expected;
+ bool accessibilityEnabled = false;
+
+ // Move away the cursor; otherwise it might result in an enter event if it's
+ // inside the widget when the widget is shown.
+ QCursor::setPos(qApp->desktop()->availableGeometry().bottomRight());
+ QTest::qWait(100);
+
+ {
+ // no children created, not shown
+ QWidget widget;
+ EventRecorder spy;
+ widget.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
+
+ QCoreApplication::sendPostedEvents();
+
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::PolishRequest)
+ << qMakePair(&widget, QEvent::Polish)
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
+ QCOMPARE(spy.eventList(), expected);
+ }
+
+ {
+ // no children, shown
+ QWidget widget;
+ EventRecorder spy;
+ widget.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
+
+ widget.show();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::WinIdChange)
+ << qMakePair(&widget, QEvent::Polish)
+ << qMakePair(&widget, QEvent::Move)
+ << qMakePair(&widget, QEvent::Resize)
+ << qMakePair(&widget, QEvent::Show);
+
+ if (accessibilityEnabled)
+ expected << qMakePair(&widget, QEvent::AccessibilityPrepare);
+ expected << qMakePair(&widget, QEvent::ShowToParent);
+ QCOMPARE(spy.eventList(), expected);
+ spy.clear();
+
+ QCoreApplication::sendPostedEvents();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::PolishRequest)
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 1));
+
+#ifdef Q_OS_MAC
+ expected << qMakePair(&widget, QEvent::UpdateLater);
+#endif
+ expected << qMakePair(&widget, QEvent::UpdateRequest);
+
+ QCOMPARE(spy.eventList(), expected);
+ }
+
+ {
+ // 2 children, not shown
+ QWidget widget;
+ EventRecorder spy;
+ widget.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
+
+ QWidget child1(&widget);
+ QWidget child2;
+ child2.setParent(&widget);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
+
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::ChildAdded)
+ << qMakePair(&widget, QEvent::ChildAdded);
+ QCOMPARE(spy.eventList(), expected);
+ spy.clear();
+
+ QCoreApplication::sendPostedEvents();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::PolishRequest)
+ << qMakePair(&widget, QEvent::Polish)
+ << qMakePair(&widget, QEvent::ChildPolished)
+ << qMakePair(&widget, QEvent::ChildPolished)
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
+ QCOMPARE(spy.eventList(), expected);
+ }
+
+ {
+ // 2 children, widget shown
+ QWidget widget;
+ EventRecorder spy;
+ widget.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
+
+ QWidget child1(&widget);
+ QWidget child2;
+ child2.setParent(&widget);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
+
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::ChildAdded)
+ << qMakePair(&widget, QEvent::ChildAdded);
+ QCOMPARE(spy.eventList(), expected);
+ spy.clear();
+
+ widget.show();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::WinIdChange)
+ << qMakePair(&widget, QEvent::Polish)
+ << qMakePair(&widget, QEvent::ChildPolished)
+ << qMakePair(&widget, QEvent::ChildPolished)
+ << qMakePair(&widget, QEvent::Move)
+ << qMakePair(&widget, QEvent::Resize)
+ << qMakePair(&widget, QEvent::Show);
+
+ if (accessibilityEnabled)
+ expected << qMakePair(&widget, QEvent::AccessibilityPrepare);
+ expected << qMakePair(&widget, QEvent::ShowToParent);
+ QCOMPARE(spy.eventList(), expected);
+ spy.clear();
+
+ QCoreApplication::sendPostedEvents();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::PolishRequest)
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
+
+#ifdef Q_OS_MAC
+ expected << qMakePair(&widget, QEvent::UpdateLater);
+#endif
+ expected << qMakePair(&widget, QEvent::UpdateRequest);
+
+ QCOMPARE(spy.eventList(), expected);
+ }
+
+ {
+ // 2 children, but one is reparented away, not shown
+ QWidget widget;
+ EventRecorder spy;
+ widget.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
+
+ QWidget child1(&widget);
+ QWidget child2;
+ child2.setParent(&widget);
+ child2.setParent(0);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
+
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::ChildAdded)
+ << qMakePair(&widget, QEvent::ChildAdded)
+ << qMakePair(&widget, QEvent::ChildRemoved);
+ QCOMPARE(spy.eventList(), expected);
+ spy.clear();
+
+ QCoreApplication::sendPostedEvents();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::PolishRequest)
+ << qMakePair(&widget, QEvent::Polish)
+ << qMakePair(&widget, QEvent::ChildPolished)
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
+ QCOMPARE(spy.eventList(), expected);
+ }
+
+ {
+ // 2 children, but one is reparented away, then widget is shown
+ QWidget widget;
+ EventRecorder spy;
+ widget.installEventFilter(&spy);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 1)));
+
+ QWidget child1(&widget);
+ QWidget child2;
+ child2.setParent(&widget);
+ child2.setParent(0);
+
+ QCoreApplication::postEvent(&widget, new QEvent(QEvent::Type(QEvent::User + 2)));
+
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::ChildAdded)
+ << qMakePair(&widget, QEvent::ChildAdded)
+ << qMakePair(&widget, QEvent::ChildRemoved);
+ QCOMPARE(spy.eventList(), expected);
+ spy.clear();
+
+ widget.show();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::WinIdChange)
+ << qMakePair(&widget, QEvent::Polish)
+ << qMakePair(&widget, QEvent::ChildPolished)
+ << qMakePair(&widget, QEvent::Move)
+ << qMakePair(&widget, QEvent::Resize)
+ << qMakePair(&widget, QEvent::Show);
+
+ if (accessibilityEnabled)
+ expected << qMakePair(&widget, QEvent::AccessibilityPrepare);
+ expected << qMakePair(&widget, QEvent::ShowToParent);
+ QCOMPARE(spy.eventList(), expected);
+ spy.clear();
+
+ QCoreApplication::sendPostedEvents();
+ expected =
+ EventRecorder::EventList()
+ << qMakePair(&widget, QEvent::PolishRequest)
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 1))
+ << qMakePair(&widget, QEvent::Type(QEvent::User + 2));
+
+#ifdef Q_OS_MAC
+ expected << qMakePair(&widget, QEvent::UpdateLater);
+#endif
+ expected << qMakePair(&widget, QEvent::UpdateRequest);
+
+ QCOMPARE(spy.eventList(), expected);
+ }
+}
+
+class RenderWidget : public QWidget
+{
+public:
+ RenderWidget(QWidget *source)
+ : source(source), ellipse(false) {}
+
+ void setEllipseEnabled(bool enable = true)
+ {
+ ellipse = enable;
+ update();
+ }
+
+protected:
+ void paintEvent(QPaintEvent *)
+ {
+ if (ellipse) {
+ QPainter painter(this);
+ painter.fillRect(rect(), Qt::red);
+ painter.end();
+ QRegion regionToRender = QRegion(0, 0, source->width(), source->height() / 2,
+ QRegion::Ellipse);
+ source->render(this, QPoint(0, 30), regionToRender);
+ } else {
+ source->render(this);
+ }
+ }
+
+private:
+ QWidget *source;
+ bool ellipse;
+};
+
+void tst_QWidget::render()
+{
+ return;
+ QCalendarWidget source;
+ // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
+ // is enabled on the screen
+ QFont f;
+ f.setStyleStrategy(QFont::NoAntialias);
+ source.setFont(f);
+ source.show();
+ QTest::qWaitForWindowShown(&source);
+
+ // Render the entire source into target.
+ RenderWidget target(&source);
+ target.resize(source.size());
+ target.show();
+
+ qApp->processEvents();
+ qApp->sendPostedEvents();
+ QTest::qWait(250);
+
+ QImage sourceImage = QPixmap::grabWidget(&source).toImage();
+ qApp->processEvents();
+ QImage targetImage = QPixmap::grabWidget(&target).toImage();
+ qApp->processEvents();
+ QCOMPARE(sourceImage, targetImage);
+
+ // Fill target.rect() will Qt::red and render
+ // QRegion(0, 0, source->width(), source->height() / 2, QRegion::Ellipse)
+ // of source into target with offset (0, 30).
+ target.setEllipseEnabled();
+ qApp->processEvents();
+ qApp->sendPostedEvents();
+
+ targetImage = QPixmap::grabWidget(&target).toImage();
+ QVERIFY(sourceImage != targetImage);
+
+ QCOMPARE(targetImage.pixel(target.width() / 2, 29), QColor(Qt::red).rgb());
+ QCOMPARE(targetImage.pixel(target.width() / 2, 30), sourceImage.pixel(source.width() / 2, 0));
+
+ // Test that a child widget properly fills its background
+ {
+ QWidget window;
+ window.resize(100, 100);
+ // prevent custom styles
+ window.setStyle(new QWindowsStyle);
+ window.show();
+ QTest::qWaitForWindowShown(&window);
+ QWidget child(&window);
+ child.resize(window.size());
+ child.show();
+
+ qApp->processEvents();
+ QCOMPARE(QPixmap::grabWidget(&child), QPixmap::grabWidget(&window));
+ }
+
+ { // Check that the target offset is correct.
+ QWidget widget;
+ widget.resize(200, 200);
+ widget.setAutoFillBackground(true);
+ widget.setPalette(Qt::red);
+ // prevent custom styles
+ widget.setStyle(new QWindowsStyle);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QImage image(widget.size(), QImage::Format_RGB32);
+ image.fill(QColor(Qt::blue).rgb());
+
+ // Target offset (0, 0)
+ widget.render(&image, QPoint(), QRect(20, 20, 100, 100));
+ QCOMPARE(image.pixel(0, 0), QColor(Qt::red).rgb());
+ QCOMPARE(image.pixel(99, 99), QColor(Qt::red).rgb());
+ QCOMPARE(image.pixel(100, 100), QColor(Qt::blue).rgb());
+
+ // Target offset (20, 20).
+ image.fill(QColor(Qt::blue).rgb());
+ widget.render(&image, QPoint(20, 20), QRect(20, 20, 100, 100));
+ QCOMPARE(image.pixel(0, 0), QColor(Qt::blue).rgb());
+ QCOMPARE(image.pixel(19, 19), QColor(Qt::blue).rgb());
+ QCOMPARE(image.pixel(20, 20), QColor(Qt::red).rgb());
+ QCOMPARE(image.pixel(119, 119), QColor(Qt::red).rgb());
+ QCOMPARE(image.pixel(120, 120), QColor(Qt::blue).rgb());
+ }
+}
+
+// On Windows the active palette is used instead of the inactive palette even
+// though the widget is invisible. This is probably related to task 178507/168682,
+// but for the renderInvisible test it doesn't matter, we're mostly interested
+// in testing the geometry so just workaround the palette issue for now.
+static void workaroundPaletteIssue(QWidget *widget)
+{
+#ifndef Q_WS_WIN
+ return;
+#endif
+ if (!widget)
+ return;
+
+ QWidget *navigationBar = qFindChild<QWidget *>(widget, QLatin1String("qt_calendar_navigationbar"));
+ QVERIFY(navigationBar);
+
+ QPalette palette = navigationBar->palette();
+ const QColor background = palette.color(QPalette::Inactive, navigationBar->backgroundRole());
+ const QColor highlightedText = palette.color(QPalette::Inactive, QPalette::HighlightedText);
+ palette.setColor(QPalette::Active, navigationBar->backgroundRole(), background);
+ palette.setColor(QPalette::Active, QPalette::HighlightedText, highlightedText);
+ navigationBar->setPalette(palette);
+}
+
+//#define RENDER_DEBUG
+void tst_QWidget::renderInvisible()
+{
+ QCalendarWidget *calendar = new QCalendarWidget;
+ // disable anti-aliasing to eliminate potential differences when subpixel antialiasing
+ // is enabled on the screen
+ QFont f;
+ f.setStyleStrategy(QFont::NoAntialias);
+ calendar->setFont(f);
+ calendar->show();
+ QTest::qWaitForWindowShown(calendar);
+
+ // Create a dummy focus widget to get rid of focus rect in reference image.
+ QLineEdit dummyFocusWidget;
+ dummyFocusWidget.show();
+ QTest::qWaitForWindowShown(&dummyFocusWidget);
+ qApp->processEvents();
+ QTest::qWait(120);
+
+ // Create normal reference image.
+ const QSize calendarSize = calendar->size();
+ QImage referenceImage(calendarSize, QImage::Format_ARGB32);
+ calendar->render(&referenceImage);
+#ifdef RENDER_DEBUG
+ referenceImage.save("referenceImage.png");
+#endif
+ QVERIFY(!referenceImage.isNull());
+
+ // Create resized reference image.
+ const QSize calendarSizeResized = calendar->size() + QSize(50, 50);
+ calendar->resize(calendarSizeResized);
+ qApp->processEvents();
+ QTest::qWait(30);
+ QImage referenceImageResized(calendarSizeResized, QImage::Format_ARGB32);
+ calendar->render(&referenceImageResized);
+#ifdef RENDER_DEBUG
+ referenceImageResized.save("referenceImageResized.png");
+#endif
+ QVERIFY(!referenceImageResized.isNull());
+
+ // Explicitly hide the calendar.
+ calendar->hide();
+ qApp->processEvents();
+ QTest::qWait(30);
+ workaroundPaletteIssue(calendar);
+
+ { // Make sure we get the same image when the calendar is explicitly hidden.
+ QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
+ calendar->render(&testImage);
+#ifdef RENDER_DEBUG
+ testImage.save("explicitlyHiddenCalendarResized.png");
+#endif
+ QCOMPARE(testImage, referenceImageResized);
+ }
+
+ // Now that we have reference images we can delete the source and re-create
+ // the calendar and check that we get the same images from a calendar which has never
+ // been visible, laid out or created (Qt::WA_WState_Created).
+ delete calendar;
+ calendar = new QCalendarWidget;
+ calendar->setFont(f);
+ workaroundPaletteIssue(calendar);
+
+ { // Never been visible, created or laid out.
+ QImage testImage(calendarSize, QImage::Format_ARGB32);
+ calendar->render(&testImage);
+#ifdef RENDER_DEBUG
+ testImage.save("neverBeenVisibleCreatedOrLaidOut.png");
+#endif
+ QCOMPARE(testImage, referenceImage);
+ }
+
+ calendar->hide();
+ qApp->processEvents();
+ QTest::qWait(30);
+
+ { // Calendar explicitly hidden.
+ QImage testImage(calendarSize, QImage::Format_ARGB32);
+ calendar->render(&testImage);
+#ifdef RENDER_DEBUG
+ testImage.save("explicitlyHiddenCalendar.png");
+#endif
+ QCOMPARE(testImage, referenceImage);
+ }
+
+ // Get navigation bar and explicitly hide it.
+ QWidget *navigationBar = qFindChild<QWidget *>(calendar, QLatin1String("qt_calendar_navigationbar"));
+ QVERIFY(navigationBar);
+ navigationBar->hide();
+
+ { // Check that the navigation bar isn't drawn when rendering the entire calendar.
+ QImage testImage(calendarSize, QImage::Format_ARGB32);
+ calendar->render(&testImage);
+#ifdef RENDER_DEBUG
+ testImage.save("calendarWithoutNavigationBar.png");
+#endif
+ QVERIFY(testImage != referenceImage);
+ }
+
+ { // Make sure the navigation bar renders correctly even though it's hidden.
+ QImage testImage(navigationBar->size(), QImage::Format_ARGB32);
+ navigationBar->render(&testImage);
+#ifdef RENDER_DEBUG
+ testImage.save("explicitlyHiddenNavigationBar.png");
+#endif
+ QCOMPARE(testImage, referenceImage.copy(navigationBar->rect()));
+ }
+
+ // Get next month button.
+ QWidget *nextMonthButton = qFindChild<QWidget *>(navigationBar, QLatin1String("qt_calendar_nextmonth"));
+ QVERIFY(nextMonthButton);
+
+ { // Render next month button.
+ // Fill test image with correct background color.
+ QImage testImage(nextMonthButton->size(), QImage::Format_ARGB32);
+ navigationBar->render(&testImage, QPoint(), QRegion(), QWidget::RenderFlags());
+#ifdef RENDER_DEBUG
+ testImage.save("nextMonthButtonBackground.png");
+#endif
+
+ // Set the button's background color to Qt::transparent; otherwise it will fill the
+ // background with QPalette::Window.
+ const QPalette originalPalette = nextMonthButton->palette();
+ QPalette palette = originalPalette;
+ palette.setColor(QPalette::Window, Qt::transparent);
+ nextMonthButton->setPalette(palette);
+
+ // Render the button on top of the background.
+ nextMonthButton->render(&testImage);
+#ifdef RENDER_DEBUG
+ testImage.save("nextMonthButton.png");
+#endif
+ const QRect buttonRect(nextMonthButton->mapTo(calendar, QPoint()), nextMonthButton->size());
+ QCOMPARE(testImage, referenceImage.copy(buttonRect));
+
+ // Restore palette.
+ nextMonthButton->setPalette(originalPalette);
+ }
+
+ // Navigation bar isn't explicitly hidden anymore.
+ navigationBar->show();
+ qApp->processEvents();
+ QTest::qWait(30);
+ QVERIFY(!calendar->isVisible());
+
+ // Now, completely mess up the layout. This will trigger an update on the layout
+ // when the calendar is visible or shown, but it's not. QWidget::render must therefore
+ // make sure the layout is activated before rendering.
+ QVERIFY(!calendar->isVisible());
+ calendar->resize(calendarSizeResized);
+ qApp->processEvents();
+
+ { // Make sure we get an image equal to the resized reference image.
+ QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
+ calendar->render(&testImage);
+#ifdef RENDER_DEBUG
+ testImage.save("calendarResized.png");
+#endif
+ QCOMPARE(testImage, referenceImageResized);
+ }
+
+ { // Make sure we lay out the widget correctly the first time it's rendered.
+ QCalendarWidget calendar;
+ const QSize calendarSize = calendar.sizeHint();
+
+ QImage image(2 * calendarSize, QImage::Format_ARGB32);
+ image.fill(QColor(Qt::red).rgb());
+ calendar.render(&image);
+
+ for (int i = calendarSize.height(); i < 2 * calendarSize.height(); ++i)
+ for (int j = calendarSize.width(); j < 2 * calendarSize.width(); ++j)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ }
+
+ { // Ensure that we don't call adjustSize() on invisible top-levels if render() is called
+ // right after widgets have been added/removed to/from its layout.
+ QWidget topLevel;
+ topLevel.setLayout(new QVBoxLayout);
+
+ QWidget *widget = new QLineEdit;
+ topLevel.layout()->addWidget(widget);
+
+ const QSize initialSize = topLevel.size();
+ QPixmap pixmap(topLevel.sizeHint());
+ topLevel.render(&pixmap); // triggers adjustSize()
+ const QSize finalSize = topLevel.size();
+ QVERIFY(finalSize != initialSize);
+
+ topLevel.layout()->removeWidget(widget);
+ QCOMPARE(topLevel.size(), finalSize);
+ topLevel.render(&pixmap);
+ QCOMPARE(topLevel.size(), finalSize);
+
+ topLevel.layout()->addWidget(widget);
+ QCOMPARE(topLevel.size(), finalSize);
+ topLevel.render(&pixmap);
+ QCOMPARE(topLevel.size(), finalSize);
+ }
+}
+
+void tst_QWidget::renderWithPainter()
+{
+ QWidget widget;
+ // prevent custom styles
+ widget.setStyle(new QWindowsStyle);
+ widget.show();
+ widget.resize(70, 50);
+ widget.setAutoFillBackground(true);
+ widget.setPalette(Qt::black);
+
+ // Render the entire widget onto the image.
+ QImage image(QSize(70, 50), QImage::Format_ARGB32);
+ image.fill(QColor(Qt::red).rgb());
+ QPainter painter(&image);
+ widget.render(&painter);
+
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
+ }
+
+ // Translate painter (10, 10).
+ painter.save();
+ image.fill(QColor(Qt::red).rgb());
+ painter.translate(10, 10);
+ widget.render(&painter);
+ painter.restore();
+
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j) {
+ if (i < 10 || j < 10)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ else
+ QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
+ }
+ }
+
+ // Pass target offset (10, 10) (the same as QPainter::translate).
+ image.fill(QColor(Qt::red).rgb());
+ widget.render(&painter, QPoint(10, 10));
+
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j) {
+ if (i < 10 || j < 10)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ else
+ QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
+ }
+ }
+
+ // Translate (10, 10) and pass target offset (10, 10).
+ painter.save();
+ image.fill(QColor(Qt::red).rgb());
+ painter.translate(10, 10);
+ widget.render(&painter, QPoint(10, 10));
+ painter.restore();
+
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j) {
+ if (i < 20 || j < 20)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ else
+ QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
+ }
+ }
+
+ // Rotate painter 90 degrees.
+ painter.save();
+ image.fill(QColor(Qt::red).rgb());
+ painter.rotate(90);
+ widget.render(&painter);
+ painter.restore();
+
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ }
+
+ // Translate and rotate.
+ image.fill(QColor(Qt::red).rgb());
+ widget.resize(40, 10);
+ painter.translate(10, 10);
+ painter.rotate(90);
+ widget.render(&painter);
+
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j) {
+ if (i >= 10 && j >= 0 && j < 10)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::black).rgb());
+ else
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ }
+ }
+
+ // Make sure QWidget::render does not modify the render hints set on the painter.
+ painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
+ | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing);
+ QPainter::RenderHints oldRenderHints = painter.renderHints();
+ widget.render(&painter);
+ QCOMPARE(painter.renderHints(), oldRenderHints);
+}
+
+void tst_QWidget::render_task188133()
+{
+ QMainWindow mainWindow;
+
+ // Make sure QWidget::render does not trigger QWidget::repaint/update
+ // and asserts for Qt::WA_WState_Created.
+ QPixmap pixmap = QPixmap::grabWidget(&mainWindow);
+}
+
+void tst_QWidget::render_task211796()
+{
+ class MyWidget : public QWidget
+ {
+ void resizeEvent(QResizeEvent *)
+ {
+ QPixmap pixmap(size());
+ render(&pixmap);
+ }
+ };
+
+ { // Please don't die in a resize recursion.
+ MyWidget widget;
+ widget.resize(200, 200);
+ widget.show();
+ }
+
+ { // Same check with a deeper hierarchy.
+ QWidget widget;
+ widget.show();
+ QWidget child(&widget);
+ MyWidget grandChild;
+ grandChild.setParent(&child);
+ grandChild.resize(100, 100);
+ child.show();
+ }
+}
+
+void tst_QWidget::render_task217815()
+{
+ // Make sure we don't change the size of the widget when calling
+ // render() and the widget has an explicit size set.
+ // This was a problem on Windows because we called createWinId(),
+ // which in turn enforced the size to be bigger than the smallest
+ // possible native window size (which is (115,something) on WinXP).
+ QWidget widget;
+ const QSize explicitSize(80, 20);
+ widget.resize(explicitSize);
+ QCOMPARE(widget.size(), explicitSize);
+
+ QPixmap pixmap(explicitSize);
+ widget.render(&pixmap);
+
+ QCOMPARE(widget.size(), explicitSize);
+}
+
+// Window Opacity is not supported on Windows CE.
+#ifndef Q_OS_WINCE
+void tst_QWidget::render_windowOpacity()
+{
+ const qreal opacity = 0.5;
+
+ { // Check that the painter opacity effects the widget drawing.
+ QWidget topLevel;
+ QWidget child(&topLevel);
+ child.resize(50, 50);
+ child.setPalette(Qt::red);
+ child.setAutoFillBackground(true);
+
+ QPixmap expected(child.size());
+#ifdef Q_WS_X11
+ if (expected.depth() < 24) {
+ QSKIP("This test won't give correct results with dithered pixmaps", SkipAll);
+ }
+#endif
+ expected.fill(Qt::green);
+ QPainter painter(&expected);
+ painter.setOpacity(opacity);
+ painter.fillRect(QRect(QPoint(0, 0), child.size()), Qt::red);
+ painter.end();
+
+ QPixmap result(child.size());
+ result.fill(Qt::green);
+ painter.begin(&result);
+ painter.setOpacity(opacity);
+ child.render(&painter);
+ painter.end();
+ QCOMPARE(result, expected);
+ }
+
+ { // Combine the opacity set on the painter with the widget opacity.
+ class MyWidget : public QWidget
+ {
+ public:
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter painter(this);
+ painter.setOpacity(opacity);
+ QCOMPARE(painter.opacity(), opacity);
+ painter.fillRect(rect(), Qt::red);
+ }
+ qreal opacity;
+ };
+
+ MyWidget widget;
+ widget.resize(50, 50);
+ widget.opacity = opacity;
+ widget.setPalette(Qt::blue);
+ widget.setAutoFillBackground(true);
+
+ QPixmap expected(widget.size());
+ expected.fill(Qt::green);
+ QPainter painter(&expected);
+ painter.setOpacity(opacity);
+ QPixmap pixmap(widget.size());
+ pixmap.fill(Qt::blue);
+ QPainter pixmapPainter(&pixmap);
+ pixmapPainter.setOpacity(opacity);
+ pixmapPainter.fillRect(QRect(QPoint(), widget.size()), Qt::red);
+ painter.drawPixmap(QPoint(), pixmap);
+ painter.end();
+
+ QPixmap result(widget.size());
+ result.fill(Qt::green);
+ painter.begin(&result);
+ painter.setOpacity(opacity);
+ widget.render(&painter);
+ painter.end();
+ QCOMPARE(result, expected);
+ }
+}
+#endif
+
+void tst_QWidget::render_systemClip()
+{
+ QWidget widget;
+ widget.setPalette(Qt::blue);
+ widget.resize(100, 100);
+
+ QImage image(widget.size(), QImage::Format_RGB32);
+ image.fill(QColor(Qt::red).rgb());
+
+ QPaintEngine *paintEngine = image.paintEngine();
+ QVERIFY(paintEngine);
+ paintEngine->setSystemClip(QRegion(0, 0, 50, 50));
+
+ QPainter painter(&image);
+ // Make sure we're using the same paint engine and has the right clip set.
+ QCOMPARE(painter.paintEngine(), paintEngine);
+ QCOMPARE(paintEngine->systemClip(), QRegion(0, 0, 50, 50));
+
+ // Translate painter outside system clip.
+ painter.translate(50, 0);
+ widget.render(&painter);
+
+#ifdef RENDER_DEBUG
+ image.save("outside_systemclip.png");
+#endif
+
+ // All pixels should be red.
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ }
+
+ // Restore painter and refill image with red.
+ image.fill(QColor(Qt::red).rgb());
+ painter.translate(-50, 0);
+
+ // Set transform on the painter.
+ QTransform transform;
+ transform.shear(0, 1);
+ painter.setTransform(transform);
+ widget.render(&painter);
+
+#ifdef RENDER_DEBUG
+ image.save("blue_triangle.png");
+#endif
+
+ // We should now have a blue triangle starting at scan line 1, and the rest should be red.
+ // rrrrrrrrrr
+ // brrrrrrrrr
+ // bbrrrrrrrr
+ // bbbrrrrrrr
+ // bbbbrrrrrr
+ // rrrrrrrrrr
+ // ...
+
+#ifndef Q_WS_MAC
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j) {
+ if (i < 50 && j < i)
+ QCOMPARE(image.pixel(j, i), QColor(Qt::blue).rgb());
+ else
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ }
+ }
+#else
+ // We don't paint directly on the image on the Mac, so we cannot do the pixel comparison
+ // as above due to QPainter::SmoothPixmapTransform. We therefore need to generate an
+ // expected image by first painting on a pixmap, and then draw the pixmap onto
+ // the image using QPainter::SmoothPixmapTransform. Then we can compare pixels :)
+ // The check is basically the same, except that it takes the smoothening into account.
+ QPixmap pixmap(50, 50);
+ const QRegion sysClip(0, 0, 50, 50);
+ widget.render(&pixmap, QPoint(), sysClip);
+
+ QImage expectedImage(widget.size(), QImage::Format_RGB32);
+ expectedImage.fill(QColor(Qt::red).rgb());
+ expectedImage.paintEngine()->setSystemClip(sysClip);
+
+ QPainter expectedImagePainter(&expectedImage);
+ expectedImagePainter.setTransform(QTransform().shear(0, 1));
+ // NB! This is the important part (SmoothPixmapTransform).
+ expectedImagePainter.setRenderHints(QPainter::SmoothPixmapTransform);
+ expectedImagePainter.drawPixmap(QPoint(0, 0), pixmap);
+ expectedImagePainter.end();
+
+ QCOMPARE(image, expectedImage);
+#endif
+}
+
+void tst_QWidget::render_systemClip2_data()
+{
+ QTest::addColumn<bool>("autoFillBackground");
+ QTest::addColumn<bool>("usePaintEvent");
+ QTest::addColumn<QColor>("expectedColor");
+
+ QTest::newRow("Only auto-fill background") << true << false << QColor(Qt::blue);
+ QTest::newRow("Only draw in paintEvent") << false << true << QColor(Qt::green);
+ QTest::newRow("Auto-fill background and draw in paintEvent") << true << true << QColor(Qt::green);
+}
+
+void tst_QWidget::render_systemClip2()
+{
+ QFETCH(bool, autoFillBackground);
+ QFETCH(bool, usePaintEvent);
+ QFETCH(QColor, expectedColor);
+
+ QVERIFY2(expectedColor != QColor(Qt::red), "Qt::red is the reference color for the image, pick another color");
+
+ class MyWidget : public QWidget
+ {
+ public:
+ bool usePaintEvent;
+ void paintEvent(QPaintEvent *)
+ {
+ if (usePaintEvent)
+ QPainter(this).fillRect(rect(), Qt::green);
+ }
+ };
+
+ MyWidget widget;
+ widget.usePaintEvent = usePaintEvent;
+ widget.setPalette(Qt::blue);
+ // NB! widget.setAutoFillBackground(autoFillBackground) won't do the
+ // trick here since the widget is a top-level. The background is filled
+ // regardless, unless Qt::WA_OpaquePaintEvent or Qt::WA_NoSystemBackground
+ // is set. We therefore use the opaque attribute to turn off auto-fill.
+ if (!autoFillBackground)
+ widget.setAttribute(Qt::WA_OpaquePaintEvent);
+ widget.resize(100, 100);
+
+ QImage image(widget.size(), QImage::Format_RGB32);
+ image.fill(QColor(Qt::red).rgb());
+
+ QPaintEngine *paintEngine = image.paintEngine();
+ QVERIFY(paintEngine);
+
+ QRegion systemClip(QRegion(50, 0, 50, 10));
+ systemClip += QRegion(90, 10, 10, 40);
+ paintEngine->setSystemClip(systemClip);
+
+ // Render entire widget directly onto device.
+ widget.render(&image);
+
+#ifdef RENDER_DEBUG
+ image.save("systemclip_with_device.png");
+#endif
+ // All pixels within the system clip should now be
+ // the expectedColor, and the rest should be red.
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j) {
+ if (systemClip.contains(QPoint(j, i)))
+ QCOMPARE(image.pixel(j, i), expectedColor.rgb());
+ else
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ }
+ }
+
+ // Refill image with red.
+ image.fill(QColor(Qt::red).rgb());
+ paintEngine->setSystemClip(systemClip);
+
+ // Do the same with an untransformed painter.
+ QPainter painter(&image);
+ //Make sure we're using the same paint engine and has the right clip set.
+ QCOMPARE(painter.paintEngine(), paintEngine);
+ QCOMPARE(paintEngine->systemClip(), systemClip);
+
+ widget.render(&painter);
+
+#ifdef RENDER_DEBUG
+ image.save("systemclip_with_untransformed_painter.png");
+#endif
+ // All pixels within the system clip should now be
+ // the expectedColor, and the rest should be red.
+ for (int i = 0; i < image.height(); ++i) {
+ for (int j = 0; j < image.width(); ++j) {
+ if (systemClip.contains(QPoint(j, i)))
+ QCOMPARE(image.pixel(j, i), expectedColor.rgb());
+ else
+ QCOMPARE(image.pixel(j, i), QColor(Qt::red).rgb());
+ }
+ }
+}
+
+void tst_QWidget::render_systemClip3_data()
+{
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<bool>("useSystemClip");
+
+ // Reference: http://en.wikipedia.org/wiki/Flag_of_Norway
+ QTest::newRow("Norwegian Civil Flag") << QSize(220, 160) << false;
+ QTest::newRow("Norwegian War Flag") << QSize(270, 160) << true;
+}
+
+// This test ensures that the current engine clip (systemClip + painter clip)
+// is preserved after QPainter::setClipRegion(..., Qt::ReplaceClip);
+void tst_QWidget::render_systemClip3()
+{
+ QFETCH(QSize, size);
+ QFETCH(bool, useSystemClip);
+
+ // Calculate the inner/outer cross of the flag.
+ QRegion outerCross(0, 0, size.width(), size.height());
+ outerCross -= QRect(0, 0, 60, 60);
+ outerCross -= QRect(100, 0, size.width() - 100, 60);
+ outerCross -= QRect(0, 100, 60, 60);
+ outerCross -= QRect(100, 100, size.width() - 100, 60);
+
+ QRegion innerCross(0, 0, size.width(), size.height());
+ innerCross -= QRect(0, 0, 70, 70);
+ innerCross -= QRect(90, 0, size.width() - 90, 70);
+ innerCross -= QRect(0, 90, 70, 70);
+ innerCross -= QRect(90, 90, size.width() - 90, 70);
+
+ const QRegion redArea(QRegion(0, 0, size.width(), size.height()) - outerCross);
+ const QRegion whiteArea(outerCross - innerCross);
+ const QRegion blueArea(innerCross);
+ QRegion systemClip;
+
+ // Okay, here's the image that should look like a Norwegian civil/war flag in the end.
+ QImage flag(size, QImage::Format_ARGB32);
+ flag.fill(QColor(Qt::transparent).rgba());
+
+ if (useSystemClip) {
+ QPainterPath warClip(QPoint(size.width(), 0));
+ warClip.lineTo(size.width() - 110, 60);
+ warClip.lineTo(size.width(), 80);
+ warClip.lineTo(size.width() - 110, 100);
+ warClip.lineTo(size.width(), 160);
+ warClip.closeSubpath();
+ systemClip = QRegion(0, 0, size.width(), size.height()) - QRegion(warClip.toFillPolygon().toPolygon());
+ flag.paintEngine()->setSystemClip(systemClip);
+ }
+
+ QPainter painter(&flag);
+ painter.fillRect(QRect(QPoint(), size), Qt::red); // Fill image background with red.
+ painter.setClipRegion(outerCross); // Limit widget painting to inside the outer cross.
+
+ // Here's the widget that's supposed to draw the inner/outer cross of the flag.
+ // The outer cross (white) should be drawn when the background is auto-filled, and
+ // the inner cross (blue) should be drawn in the paintEvent.
+ class MyWidget : public QWidget
+ { public:
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter painter(this);
+ // Be evil and try to paint outside the outer cross. This should not be
+ // possible since the shared painter is clipped to the outer cross.
+ painter.setClipRect(0, 0, 60, 60, Qt::ReplaceClip);
+ painter.fillRect(rect(), Qt::green);
+ painter.setClipRegion(clip, Qt::ReplaceClip);
+ painter.fillRect(rect(), Qt::blue);
+ }
+ QRegion clip;
+ };
+
+ MyWidget widget;
+ widget.clip = innerCross;
+ widget.setFixedSize(size);
+ widget.setPalette(Qt::white);
+ widget.setAutoFillBackground(true);
+ widget.render(&painter);
+
+#ifdef RENDER_DEBUG
+ flag.save("flag.png");
+#endif
+
+ // Let's make sure we got a Norwegian flag.
+ for (int i = 0; i < flag.height(); ++i) {
+ for (int j = 0; j < flag.width(); ++j) {
+ const QPoint pixel(j, i);
+ const QRgb pixelValue = flag.pixel(pixel);
+ if (useSystemClip && !systemClip.contains(pixel))
+ QCOMPARE(pixelValue, QColor(Qt::transparent).rgba());
+ else if (redArea.contains(pixel))
+ QCOMPARE(pixelValue, QColor(Qt::red).rgba());
+ else if (whiteArea.contains(pixel))
+ QCOMPARE(pixelValue, QColor(Qt::white).rgba());
+ else
+ QCOMPARE(pixelValue, QColor(Qt::blue).rgba());
+ }
+ }
+}
+
+void tst_QWidget::render_task252837()
+{
+ QWidget widget;
+ widget.resize(200, 200);
+
+ QPixmap pixmap(widget.size());
+ QPainter painter(&pixmap);
+ // Please do not crash.
+ widget.render(&painter);
+}
+
+void tst_QWidget::render_worldTransform()
+{
+ class MyWidget : public QWidget
+ { public:
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter painter(this);
+ // Make sure world transform is identity.
+ QCOMPARE(painter.worldTransform(), QTransform());
+
+ // Make sure device transform is correct.
+ const QPoint widgetOffset = geometry().topLeft();
+ QTransform expectedDeviceTransform = QTransform::fromTranslate(105, 5);
+ expectedDeviceTransform.rotate(90);
+ expectedDeviceTransform.translate(widgetOffset.x(), widgetOffset.y());
+ QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
+
+ // Set new world transform.
+ QTransform newWorldTransform = QTransform::fromTranslate(10, 10);
+ newWorldTransform.rotate(90);
+ painter.setWorldTransform(newWorldTransform);
+ QCOMPARE(painter.worldTransform(), newWorldTransform);
+
+ // Again, check device transform.
+ expectedDeviceTransform.translate(10, 10);
+ expectedDeviceTransform.rotate(90);
+ QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
+
+ painter.fillRect(QRect(0, 0, 20, 10), Qt::green);
+ }
+ };
+
+ MyWidget widget;
+ widget.setFixedSize(100, 100);
+ widget.setPalette(Qt::red);
+ widget.setAutoFillBackground(true);
+
+ MyWidget child;
+ child.setParent(&widget);
+ child.move(50, 50);
+ child.setFixedSize(50, 50);
+ child.setPalette(Qt::blue);
+ child.setAutoFillBackground(true);
+
+ QImage image(QSize(110, 110), QImage::Format_RGB32);
+ image.fill(QColor(Qt::black).rgb());
+
+ QPainter painter(&image);
+ painter.translate(105, 5);
+ painter.rotate(90);
+
+ const QTransform worldTransform = painter.worldTransform();
+ const QTransform deviceTransform = painter.deviceTransform();
+
+ // Render widgets onto image.
+ widget.render(&painter);
+#ifdef RENDER_DEBUG
+ image.save("render_worldTransform_image.png");
+#endif
+
+ // Ensure the transforms are unchanged after render.
+ QCOMPARE(painter.worldTransform(), painter.worldTransform());
+ QCOMPARE(painter.deviceTransform(), painter.deviceTransform());
+ painter.end();
+
+ // Paint expected image.
+ QImage expected(QSize(110, 110), QImage::Format_RGB32);
+ expected.fill(QColor(Qt::black).rgb());
+
+ QPainter expectedPainter(&expected);
+ expectedPainter.translate(105, 5);
+ expectedPainter.rotate(90);
+ expectedPainter.save();
+ expectedPainter.fillRect(widget.rect(),Qt::red);
+ expectedPainter.translate(10, 10);
+ expectedPainter.rotate(90);
+ expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
+ expectedPainter.restore();
+ expectedPainter.translate(50, 50);
+ expectedPainter.fillRect(child.rect(),Qt::blue);
+ expectedPainter.translate(10, 10);
+ expectedPainter.rotate(90);
+ expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
+ expectedPainter.end();
+
+#ifdef RENDER_DEBUG
+ expected.save("render_worldTransform_expected.png");
+#endif
+
+ QCOMPARE(image, expected);
+}
+
+void tst_QWidget::setContentsMargins()
+{
+ QLabel label("why does it always rain on me?");
+ QSize oldSize = label.sizeHint();
+ label.setFrameStyle(QFrame::Sunken | QFrame::Box);
+ QSize newSize = label.sizeHint();
+ QVERIFY(oldSize != newSize);
+
+ QLabel label2("why does it always rain on me?");
+ label2.show();
+ label2.setFrameStyle(QFrame::Sunken | QFrame::Box);
+ QCOMPARE(newSize, label2.sizeHint());
+
+ QLabel label3("why does it always rain on me?");
+ label3.setFrameStyle(QFrame::Sunken | QFrame::Box);
+ QCOMPARE(newSize, label3.sizeHint());
+}
+
+// 4DWM issues on IRIX makes this test fail.
+#ifndef Q_OS_IRIX
+void tst_QWidget::moveWindowInShowEvent_data()
+{
+ QTest::addColumn<QPoint>("initial");
+ QTest::addColumn<QPoint>("position");
+
+ QPoint p = QApplication::desktop()->availableGeometry().topLeft();
+
+ QTest::newRow("1") << p << (p + QPoint(10, 10));
+ QTest::newRow("2") << (p + QPoint(10,10)) << p;
+}
+
+void tst_QWidget::moveWindowInShowEvent()
+{
+ QFETCH(QPoint, initial);
+ QFETCH(QPoint, position);
+
+ class MoveWindowInShowEventWidget : public QWidget
+ {
+ public:
+ QPoint position;
+ void showEvent(QShowEvent *)
+ {
+ move(position);
+ }
+ };
+
+ MoveWindowInShowEventWidget widget;
+ widget.resize(QSize(qApp->desktop()->availableGeometry().size() / 3).expandedTo(QSize(1, 1)));
+ // move to this position in showEvent()
+ widget.position = position;
+
+ // put the widget in it's starting position
+ widget.move(initial);
+ QCOMPARE(widget.pos(), initial);
+
+ // show it
+ widget.show();
+ #ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&widget);
+ #endif
+ QTest::qWait(100);
+ // it should have moved
+ QCOMPARE(widget.pos(), position);
+}
+#endif
+
+void tst_QWidget::repaintWhenChildDeleted()
+{
+#ifdef Q_WS_WIN
+ if (QSysInfo::WindowsVersion & QSysInfo::WV_VISTA) {
+ QTest::qWait(1000);
+ }
+#endif
+ ColorWidget w(0, Qt::red);
+#if !defined(Q_OS_WINCE)
+ QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
+ startPoint.rx() += 50;
+ startPoint.ry() += 50;
+ w.setGeometry(QRect(startPoint, QSize(100, 100)));
+#else
+ w.setGeometry(60, 60, 110, 110);
+#endif
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QTest::qWait(10);
+ QTRY_COMPARE(w.r, QRegion(w.rect()));
+ w.r = QRegion();
+
+ {
+ const QPoint tlwOffset = w.geometry().topLeft();
+ ColorWidget child(&w, Qt::blue);
+ child.setGeometry(10, 10, 10, 10);
+ child.show();
+ QTest::qWait(10);
+ QTRY_COMPARE(child.r, QRegion(child.rect()));
+ w.r = QRegion();
+ }
+
+ QTest::qWait(10);
+ QTRY_COMPARE(w.r, QRegion(10, 10, 10, 10));
+}
+
+// task 175114
+void tst_QWidget::hideOpaqueChildWhileHidden()
+{
+ ColorWidget w(0, Qt::red);
+#if !defined(Q_OS_WINCE)
+ QPoint startPoint = QApplication::desktop()->availableGeometry(&w).topLeft();
+ startPoint.rx() += 50;
+ startPoint.ry() += 50;
+ w.setGeometry(QRect(startPoint, QSize(100, 100)));
+#else
+ w.setGeometry(60, 60, 110, 110);
+#endif
+
+ ColorWidget child(&w, Qt::blue);
+ child.setGeometry(10, 10, 80, 80);
+
+ ColorWidget child2(&child, Qt::white);
+ child2.setGeometry(10, 10, 60, 60);
+
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QTest::qWait(10);
+ QTRY_COMPARE(child2.r, QRegion(child2.rect()));
+ child.r = QRegion();
+ child2.r = QRegion();
+ w.r = QRegion();
+
+ child.hide();
+ child2.hide();
+ QTest::qWait(100);
+
+ QCOMPARE(w.r, QRegion(child.geometry()));
+
+ child.show();
+ QTest::qWait(100);
+ QCOMPARE(child.r, QRegion(child.rect()));
+ QCOMPARE(child2.r, QRegion());
+}
+
+// This test doesn't make sense without support for showMinimized().
+#if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS)
+void tst_QWidget::updateWhileMinimized()
+{
+ UpdateWidget widget;
+ // Filter out activation change and focus events to avoid update() calls in QWidget.
+ widget.updateOnActivationChangeAndFocusIn = false;
+ widget.reset();
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+ QTRY_VERIFY(widget.numPaintEvents > 0);
+ QTest::qWait(150);
+
+ // Minimize window.
+ widget.showMinimized();
+ QTest::qWait(110);
+
+ widget.reset();
+
+ // The widget is not visible on the screen (but isVisible() still returns true).
+ // Make sure update requests are discarded until the widget is shown again.
+ widget.update(0, 0, 50, 50);
+ QTest::qWait(10);
+ QCOMPARE(widget.numPaintEvents, 0);
+
+ // Restore window.
+ widget.showNormal();
+ QTest::qWait(30);
+ QTRY_COMPARE(widget.numPaintEvents, 1);
+ QCOMPARE(widget.paintedRegion, QRegion(0, 0, 50, 50));
+}
+#endif
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+class PaintOnScreenWidget: public QWidget
+{
+public:
+ PaintOnScreenWidget(QWidget *parent = 0, Qt::WindowFlags f = 0)
+ :QWidget(parent, f)
+ {
+ }
+#if defined(Q_WS_WIN)
+ // This is the only way to enable PaintOnScreen on Windows.
+ QPaintEngine * paintEngine () const {return 0;}
+#endif
+};
+
+void tst_QWidget::alienWidgets()
+{
+ qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
+ QWidget parent;
+ QWidget child(&parent);
+ QWidget grandChild(&child);
+ QWidget greatGrandChild(&grandChild);
+ parent.show();
+
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&parent);
+#endif
+
+ // Verify that the WA_WState_Created attribute is set
+ // and the top-level is the only native window.
+ QVERIFY(parent.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(parent.internalWinId());
+
+ QVERIFY(child.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(!child.internalWinId());
+
+ QVERIFY(grandChild.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(!grandChild.internalWinId());
+
+ QVERIFY(greatGrandChild.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(!greatGrandChild.internalWinId());
+
+ // Enforce native windows all the way up in the parent hierarchy
+ // if not WA_DontCreateNativeAncestors is set.
+ grandChild.setAttribute(Qt::WA_DontCreateNativeAncestors);
+ greatGrandChild.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(greatGrandChild.internalWinId());
+ QVERIFY(grandChild.internalWinId());
+ QVERIFY(!child.internalWinId());
+
+ {
+ // Ensure that hide() on an ancestor of a widget with
+ // Qt::WA_DontCreateNativeAncestors still gets unmapped
+ QWidget window;
+ QWidget widget(&window);
+ QWidget child(&widget);
+ child.setAttribute(Qt::WA_NativeWindow);
+ child.setAttribute(Qt::WA_DontCreateNativeAncestors);
+ window.show();
+ QVERIFY(child.testAttribute(Qt::WA_Mapped));
+ widget.hide();
+ QVERIFY(!child.testAttribute(Qt::WA_Mapped));
+ }
+
+ // Enforce a native window when calling QWidget::winId.
+ QVERIFY(child.winId());
+ QVERIFY(child.internalWinId());
+
+ // Check that paint on screen widgets (incl. children) are native.
+ PaintOnScreenWidget paintOnScreen(&parent);
+ QWidget paintOnScreenChild(&paintOnScreen);
+ paintOnScreen.show();
+ QVERIFY(paintOnScreen.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(!paintOnScreen.testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(!paintOnScreen.internalWinId());
+ QVERIFY(!paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(!paintOnScreenChild.internalWinId());
+
+ paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
+ QVERIFY(paintOnScreen.testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(paintOnScreen.internalWinId());
+ QVERIFY(paintOnScreenChild.testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(paintOnScreenChild.internalWinId());
+
+ // Check that widgets with the Qt::MSWindowsOwnDC attribute set
+ // are native.
+ QWidget msWindowsOwnDC(&parent, Qt::MSWindowsOwnDC);
+ msWindowsOwnDC.show();
+ QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(msWindowsOwnDC.testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(msWindowsOwnDC.internalWinId());
+
+ { // Enforce a native window when calling QWidget::handle() (on X11) or QWidget::getDC() (on Windows).
+ QWidget widget(&parent);
+ widget.show();
+ QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(!widget.internalWinId());
+#ifdef Q_WS_X11
+ widget.handle();
+#else
+ widget.getDC();
+#endif
+ QVERIFY(widget.internalWinId());
+ }
+
+#ifdef Q_WS_X11
+#ifndef QT_NO_XRENDER
+ { // Enforce a native window when calling QWidget::x11PictureHandle().
+ QWidget widget(&parent);
+ widget.show();
+ QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
+ QVERIFY(!widget.internalWinId());
+ widget.x11PictureHandle();
+ QVERIFY(widget.internalWinId());
+ }
+#endif
+
+ { // Make sure we don't create native windows when setting Qt::WA_X11NetWmWindowType attributes
+ // on alien widgets (see task 194231).
+ QWidget dummy;
+ QVERIFY(dummy.winId());
+ QWidget widget(&dummy);
+ widget.setAttribute(Qt::WA_X11NetWmWindowTypeToolBar);
+ QVERIFY(!widget.internalWinId());
+ }
+#endif
+
+
+ { // Make sure we create native ancestors when setting Qt::WA_PaintOnScreen before show().
+ QWidget topLevel;
+ QWidget child(&topLevel);
+ QWidget grandChild(&child);
+ PaintOnScreenWidget greatGrandChild(&grandChild);
+
+ greatGrandChild.setAttribute(Qt::WA_PaintOnScreen);
+ QVERIFY(!child.internalWinId());
+ QVERIFY(!grandChild.internalWinId());
+ QVERIFY(!greatGrandChild.internalWinId());
+
+ topLevel.show();
+ QVERIFY(child.internalWinId());
+ QVERIFY(grandChild.internalWinId());
+ QVERIFY(greatGrandChild.internalWinId());
+ }
+
+ { // Ensure that widgets reparented into Qt::WA_PaintOnScreen widgets become native.
+ QWidget topLevel;
+ QWidget *widget = new PaintOnScreenWidget(&topLevel);
+ widget->setAttribute(Qt::WA_PaintOnScreen);
+ QWidget *child = new QWidget;
+ QWidget *dummy = new QWidget(child);
+ QWidget *grandChild = new QWidget(child);
+ QWidget *dummy2 = new QWidget(grandChild);
+
+ child->setParent(widget);
+
+ QVERIFY(!topLevel.internalWinId());
+ QVERIFY(!child->internalWinId());
+ QVERIFY(!dummy->internalWinId());
+ QVERIFY(!grandChild->internalWinId());
+ QVERIFY(!dummy2->internalWinId());
+
+ topLevel.show();
+ QVERIFY(topLevel.internalWinId());
+ QVERIFY(widget->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(child->internalWinId());
+ QVERIFY(child->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(!child->testAttribute(Qt::WA_PaintOnScreen));
+ QVERIFY(!dummy->internalWinId());
+ QVERIFY(!dummy->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(!grandChild->internalWinId());
+ QVERIFY(!grandChild->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(!dummy2->internalWinId());
+ QVERIFY(!dummy2->testAttribute(Qt::WA_NativeWindow));
+ }
+
+ { // Ensure that ancestors of a Qt::WA_PaintOnScreen widget stay native
+ // if they are re-created (typically in QWidgetPrivate::setParent_sys) (task 210822).
+ QWidget window;
+ QWidget child(&window);
+
+ QWidget grandChild;
+ grandChild.setWindowTitle("This causes the widget to be created");
+
+ PaintOnScreenWidget paintOnScreenWidget;
+ paintOnScreenWidget.setAttribute(Qt::WA_PaintOnScreen);
+ paintOnScreenWidget.setParent(&grandChild);
+
+ grandChild.setParent(&child);
+
+ window.show();
+
+ QVERIFY(window.internalWinId());
+ QVERIFY(child.internalWinId());
+ QVERIFY(child.testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(grandChild.internalWinId());
+ QVERIFY(grandChild.testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(paintOnScreenWidget.internalWinId());
+ QVERIFY(paintOnScreenWidget.testAttribute(Qt::WA_NativeWindow));
+ }
+
+ { // Ensure that all siblings are native unless Qt::AA_DontCreateNativeWidgetSiblings is set.
+ qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, false);
+ QWidget mainWindow;
+ QWidget *toolBar = new QWidget(&mainWindow);
+ QWidget *dockWidget = new QWidget(&mainWindow);
+ QWidget *centralWidget = new QWidget(&mainWindow);
+
+ QWidget *button = new QWidget(centralWidget);
+ QWidget *mdiArea = new QWidget(centralWidget);
+
+ QWidget *horizontalScroll = new QWidget(mdiArea);
+ QWidget *verticalScroll = new QWidget(mdiArea);
+ QWidget *viewport = new QWidget(mdiArea);
+
+ viewport->setAttribute(Qt::WA_NativeWindow);
+ mainWindow.show();
+
+ // Ensure that the viewport and its siblings are native:
+ QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(verticalScroll->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(horizontalScroll->testAttribute(Qt::WA_NativeWindow));
+
+ // Ensure that the mdi area and its siblings are native:
+ QVERIFY(mdiArea->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(button->testAttribute(Qt::WA_NativeWindow));
+
+ // Ensure that the central widget and its siblings are native:
+ QVERIFY(centralWidget->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(dockWidget->testAttribute(Qt::WA_NativeWindow));
+ QVERIFY(toolBar->testAttribute(Qt::WA_NativeWindow));
+ }
+}
+#endif // Q_WS_WIN / Q_WS_X11
+
+class ASWidget : public QWidget
+{
+public:
+ ASWidget(QSize sizeHint, QSizePolicy sizePolicy, bool layout, bool hfwLayout, QWidget *parent = 0)
+ : QWidget(parent), mySizeHint(sizeHint)
+ {
+ setSizePolicy(sizePolicy);
+ if (layout) {
+ QSizePolicy sp = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ sp.setHeightForWidth(hfwLayout);
+
+ QVBoxLayout *vbox = new QVBoxLayout;
+ vbox->setMargin(0);
+ vbox->addWidget(new ASWidget(sizeHint + QSize(30, 20), sp, false, false));
+ setLayout(vbox);
+ }
+ }
+
+ QSize sizeHint() const {
+ if (layout())
+ return layout()->totalSizeHint();
+ return mySizeHint;
+ }
+ int heightForWidth(int width) const {
+ if (sizePolicy().hasHeightForWidth()) {
+ return width * 2;
+ } else {
+ return -1;
+ }
+ }
+
+ QSize mySizeHint;
+};
+
+void tst_QWidget::adjustSize_data()
+{
+ const int MagicW = 200;
+ const int MagicH = 100;
+
+ QTest::addColumn<QSize>("sizeHint");
+ QTest::addColumn<int>("hPolicy");
+ QTest::addColumn<int>("vPolicy");
+ QTest::addColumn<bool>("hfwSP");
+ QTest::addColumn<bool>("layout");
+ QTest::addColumn<bool>("hfwLayout");
+ QTest::addColumn<bool>("haveParent");
+ QTest::addColumn<QSize>("expectedSize");
+
+ QTest::newRow("1") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << false << false << false << QSize(5, qMax(6, MagicH));
+ QTest::newRow("2") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << true << false << false << false << QSize(5, qMax(10, MagicH));
+ QTest::newRow("3") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << false << false << QSize(35, 26);
+ QTest::newRow("4") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << true << false << QSize(35, 70);
+ QTest::newRow("5") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << false << false << false << QSize(100000, 100000);
+ QTest::newRow("6") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << true << false << false << false << QSize(100000, 100000);
+ QTest::newRow("7") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << false << false << QSize(100000, 100000);
+ QTest::newRow("8") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << true << false << QSize(100000, 100000);
+ QTest::newRow("9") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
+ << true << false << false << false << QSize(qMax(5, MagicW), 10);
+
+ QTest::newRow("1c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << false << false << true << QSize(5, 6);
+ QTest::newRow("2c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << true << false << false << true << QSize(5, 6 /* or 10 would be OK too, since hfw contradicts sizeHint() */);
+ QTest::newRow("3c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << false << true << QSize(35, 26);
+ QTest::newRow("4c") << QSize(5, 6) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << true << true << QSize(35, 70);
+ QTest::newRow("5c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << false << false << true << QSize(40001, 30001);
+ QTest::newRow("6c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << true << false << false << true << QSize(40001, 30001 /* or 80002 would be OK too, since hfw contradicts sizeHint() */);
+ QTest::newRow("7c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << false << true << QSize(40001 + 30, 30001 + 20);
+ QTest::newRow("8c") << QSize(40001, 30001) << int(QSizePolicy::Minimum) << int(QSizePolicy::Expanding)
+ << false << true << true << true << QSize(40001 + 30, 80002 + 60);
+ QTest::newRow("9c") << QSize(5, 6) << int(QSizePolicy::Expanding) << int(QSizePolicy::Minimum)
+ << true << false << false << true << QSize(5, 6);
+}
+
+void tst_QWidget::adjustSize()
+{
+ QFETCH(QSize, sizeHint);
+ QFETCH(int, hPolicy);
+ QFETCH(int, vPolicy);
+ QFETCH(bool, hfwSP);
+ QFETCH(bool, layout);
+ QFETCH(bool, hfwLayout);
+ QFETCH(bool, haveParent);
+ QFETCH(QSize, expectedSize);
+
+ QWidget *parent = new QWidget;
+
+ QSizePolicy sp = QSizePolicy(QSizePolicy::Policy(hPolicy), QSizePolicy::Policy(vPolicy));
+ sp.setHeightForWidth(hfwSP);
+
+ QWidget *child = new ASWidget(sizeHint, sp, layout, hfwLayout, haveParent ? parent : 0);
+ child->resize(123, 456);
+ child->adjustSize();
+ if (expectedSize == QSize(100000, 100000)) {
+ QVERIFY(child->size().width() < sizeHint.width());
+ QVERIFY(child->size().height() < sizeHint.height());
+ } else {
+#if defined (Q_OS_WINCE)
+ if (!haveParent) {
+ const QRect& desktopRect = qApp->desktop()->availableGeometry();
+ expectedSize.setWidth(qMin(expectedSize.width(), desktopRect.width()));
+ expectedSize.setHeight(qMin(expectedSize.height(), desktopRect.height()));
+ }
+#endif
+ QCOMPARE(child->size(), expectedSize);
+ }
+
+ delete parent;
+}
+
+class TestLayout : public QVBoxLayout
+{
+ Q_OBJECT
+public:
+ TestLayout(QWidget *w = 0) : QVBoxLayout(w)
+ {
+ invalidated = false;
+ }
+
+ void invalidate()
+ {
+ invalidated = true;
+ }
+
+ bool invalidated;
+};
+
+void tst_QWidget::updateGeometry_data()
+{
+ QTest::addColumn<QSize>("minSize");
+ QTest::addColumn<bool>("shouldInvalidate");
+ QTest::addColumn<QSize>("maxSize");
+ QTest::addColumn<bool>("shouldInvalidate2");
+ QTest::addColumn<int>("verticalSizePolicy");
+ QTest::addColumn<bool>("shouldInvalidate3");
+ QTest::addColumn<bool>("setVisible");
+ QTest::addColumn<bool>("shouldInvalidate4");
+
+ QTest::newRow("setMinimumSize")
+ << QSize(100, 100) << true
+ << QSize() << false
+ << int(QSizePolicy::Preferred) << false
+ << true << false;
+ QTest::newRow("setMaximumSize")
+ << QSize() << false
+ << QSize(100, 100) << true
+ << int(QSizePolicy::Preferred) << false
+ << true << false;
+ QTest::newRow("setMinimumSize, then maximumSize to a different size")
+ << QSize(100, 100) << true
+ << QSize(300, 300) << true
+ << int(QSizePolicy::Preferred) << false
+ << true << false;
+ QTest::newRow("setMinimumSize, then maximumSize to the same size")
+ << QSize(100, 100) << true
+ << QSize(100, 100) << true
+ << int(QSizePolicy::Preferred) << false
+ << true << false;
+ QTest::newRow("setMinimumSize, then maximumSize to the same size and then hide it")
+ << QSize(100, 100) << true
+ << QSize(100, 100) << true
+ << int(QSizePolicy::Preferred) << false
+ << false << true;
+ QTest::newRow("Change sizePolicy")
+ << QSize() << false
+ << QSize() << false
+ << int(QSizePolicy::Minimum) << true
+ << true << false;
+
+}
+
+void tst_QWidget::updateGeometry()
+{
+ QFETCH(QSize, minSize);
+ QFETCH(bool, shouldInvalidate);
+ QFETCH(QSize, maxSize);
+ QFETCH(bool, shouldInvalidate2);
+ QFETCH(int, verticalSizePolicy);
+ QFETCH(bool, shouldInvalidate3);
+ QFETCH(bool, setVisible);
+ QFETCH(bool, shouldInvalidate4);
+ QWidget parent;
+ parent.resize(200, 200);
+ TestLayout *lout = new TestLayout();
+ parent.setLayout(lout);
+ QWidget *child = new QWidget(&parent);
+ lout->addWidget(child);
+ parent.show();
+ QApplication::processEvents();
+
+ lout->invalidated = false;
+ if (minSize.isValid())
+ child->setMinimumSize(minSize);
+ QCOMPARE(lout->invalidated, shouldInvalidate);
+
+ lout->invalidated = false;
+ if (maxSize.isValid())
+ child->setMaximumSize(maxSize);
+ QCOMPARE(lout->invalidated, shouldInvalidate2);
+
+ lout->invalidated = false;
+ child->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, (QSizePolicy::Policy)verticalSizePolicy));
+ if (shouldInvalidate3)
+ QCOMPARE(lout->invalidated, true);
+
+ lout->invalidated = false;
+ if (!setVisible)
+ child->setVisible(false);
+ QCOMPARE(lout->invalidated, shouldInvalidate4);
+}
+
+void tst_QWidget::sendUpdateRequestImmediately()
+{
+#ifdef Q_WS_MAC
+ if (!QApplicationPrivate::graphicsSystem())
+ QSKIP("We only send update requests on the Mac when passing -graphicssystem", SkipAll);
+#endif
+
+ UpdateWidget updateWidget;
+ updateWidget.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&updateWidget);
+#endif
+
+ qApp->processEvents();
+#ifdef Q_WS_QWS
+ QApplication::sendPostedEvents(); //glib workaround
+#endif
+ updateWidget.reset();
+
+ QCOMPARE(updateWidget.numUpdateRequestEvents, 0);
+ updateWidget.repaint();
+ QCOMPARE(updateWidget.numUpdateRequestEvents, 1);
+}
+
+// 4DWM issues on IRIX makes this test fail.
+#ifndef Q_OS_IRIX
+void tst_QWidget::doubleRepaint()
+{
+#if defined(Q_WS_MAC)
+ if (!macHasAccessToWindowsServer())
+ QSKIP("Not having window server access causes the wrong number of repaints to be issues", SkipAll);
+#endif
+ UpdateWidget widget;
+ widget.setFocusPolicy(Qt::StrongFocus);
+ // Filter out activation change and focus events to avoid update() calls in QWidget.
+ widget.updateOnActivationChangeAndFocusIn = false;
+
+ // Show: 1 repaint
+ int expectedRepaints = 1;
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(10);
+ QTRY_COMPARE(widget.numPaintEvents, expectedRepaints);
+ widget.numPaintEvents = 0;
+
+ // Minmize: Should not trigger a repaint.
+ widget.showMinimized();
+ QTest::qWait(10);
+ QCOMPARE(widget.numPaintEvents, 0);
+ widget.numPaintEvents = 0;
+
+ // Restore: Should not trigger a repaint.
+ widget.showNormal();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(10);
+ QCOMPARE(widget.numPaintEvents, 0);
+}
+#endif
+
+#ifndef Q_WS_MAC
+// This test only makes sense on the Mac when passing -graphicssystem.
+void tst_QWidget::resizeInPaintEvent()
+{
+ QWidget window;
+ UpdateWidget widget(&window);
+ window.show();
+ QTest::qWaitForWindowShown(&window);
+ QTRY_VERIFY(widget.numPaintEvents > 0);
+
+ widget.reset();
+ QCOMPARE(widget.numPaintEvents, 0);
+
+ widget.resizeInPaintEvent = true;
+ // This will call resize in the paintEvent, which in turn will call
+ // invalidateBuffer() and a new update request should be posted.
+ widget.repaint();
+ QCOMPARE(widget.numPaintEvents, 1);
+ widget.numPaintEvents = 0;
+
+ QTest::qWait(10);
+ // Make sure the resize triggers another update.
+ QTRY_COMPARE(widget.numPaintEvents, 1);
+}
+
+void tst_QWidget::opaqueChildren()
+{
+ QWidget widget;
+ widget.resize(200, 200);
+
+ QWidget child(&widget);
+ child.setGeometry(-700, -700, 200, 200);
+
+ QWidget grandChild(&child);
+ grandChild.resize(200, 200);
+
+ QWidget greatGrandChild(&grandChild);
+ greatGrandChild.setGeometry(50, 50, 200, 200);
+ greatGrandChild.setPalette(Qt::red);
+ greatGrandChild.setAutoFillBackground(true); // Opaque child widget.
+
+ widget.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&widget);
+#endif
+ QTest::qWait(100);
+
+ // Child, grandChild and greatGrandChild are outside the ancestor clip.
+ QRegion expectedOpaqueRegion(50, 50, 150, 150);
+ QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
+
+ // Now they are all inside the ancestor clip.
+ child.setGeometry(50, 50, 150, 150);
+ QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
+
+ // Set mask on greatGrandChild.
+ const QRegion mask(10, 10, 50, 50);
+ greatGrandChild.setMask(mask);
+ expectedOpaqueRegion &= mask.translated(50, 50);
+ QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), expectedOpaqueRegion);
+
+ // Make greatGrandChild "transparent".
+ greatGrandChild.setAutoFillBackground(false);
+ QCOMPARE(qt_widget_private(&grandChild)->getOpaqueChildren(), QRegion());
+}
+#endif
+
+
+class MaskSetWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ MaskSetWidget(QWidget* p =0)
+ : QWidget(p) {}
+
+ void paintEvent(QPaintEvent* event) {
+ QPainter p(this);
+
+ paintedRegion += event->region();
+ foreach(QRect r, event->region().rects())
+ p.fillRect(r, Qt::red);
+ }
+
+ void resizeEvent(QResizeEvent*) {
+ setMask(QRegion(QRect(0, 0, width(), 10).normalized()));
+ }
+
+ QRegion paintedRegion;
+
+public slots:
+ void resizeDown() {
+ setGeometry(QRect(0, 50, 50, 50));
+ }
+
+ void resizeUp() {
+ setGeometry(QRect(0, 50, 150, 50));
+ }
+
+};
+
+void tst_QWidget::setMaskInResizeEvent()
+{
+ UpdateWidget w;
+ w.reset();
+ w.resize(200, 200);
+ w.setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
+ w.raise();
+
+ MaskSetWidget testWidget(&w);
+ testWidget.setGeometry(0, 0, 100, 100);
+ testWidget.setMask(QRegion(QRect(0,0,100,10)));
+ testWidget.show();
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QTest::qWait(30);
+ QTRY_VERIFY(w.numPaintEvents > 0);
+
+ w.reset();
+ testWidget.paintedRegion = QRegion();
+ QTimer::singleShot(0, &testWidget, SLOT(resizeDown()));
+ QTest::qWait(100);
+
+ QRegion expectedParentUpdate(0, 0, 100, 10); // Old testWidget area.
+ expectedParentUpdate += testWidget.geometry(); // New testWidget area.
+ QCOMPARE(w.paintedRegion, expectedParentUpdate);
+ QCOMPARE(testWidget.paintedRegion, testWidget.mask());
+
+ testWidget.paintedRegion = QRegion();
+ // Now resize the widget again, but in the oposite direction
+ QTimer::singleShot(0, &testWidget, SLOT(resizeUp()));
+ QTest::qWait(100);
+
+ QTRY_COMPARE(testWidget.paintedRegion, testWidget.mask());
+}
+
+class MoveInResizeWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ MoveInResizeWidget(QWidget* p = 0)
+ : QWidget(p)
+ {
+ setWindowFlags(Qt::FramelessWindowHint);
+ }
+
+ void resizeEvent(QResizeEvent*) {
+
+ move(QPoint(100,100));
+
+ static bool firstTime = true;
+ if (firstTime)
+ QTimer::singleShot(250, this, SLOT(resizeMe()));
+
+ firstTime = false;
+ }
+
+public slots:
+ void resizeMe() {
+ resize(100, 100);
+ }
+};
+
+void tst_QWidget::moveInResizeEvent()
+{
+ MoveInResizeWidget testWidget;
+ testWidget.setGeometry(50, 50, 200, 200);
+ testWidget.show();
+ QTest::qWaitForWindowShown(&testWidget);
+ QTest::qWait(300);
+
+ QRect expectedGeometry(100,100, 100, 100);
+ QTRY_COMPARE(testWidget.geometry(), expectedGeometry);
+}
+
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+void tst_QWidget::immediateRepaintAfterShow()
+{
+ UpdateWidget widget;
+ widget.show();
+ qApp->processEvents();
+ // On X11 in particular, we are now waiting for a MapNotify event before
+ // syncing the backing store. However, if someone request a repaint()
+ // we must repaint immediately regardless of the current state.
+ widget.numPaintEvents = 0;
+ widget.repaint();
+ QCOMPARE(widget.numPaintEvents, 1);
+}
+
+void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
+{
+ QWidget *widget = new UpdateWidget;
+ widget->show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(widget);
+#endif
+ QTest::qWait(200);
+
+ static_cast<UpdateWidget *>(widget)->numPaintEvents = 0;
+
+ // Marks the area covered by the widget as dirty in the backing store and
+ // posts an UpdateRequest event.
+ qt_widget_private(widget)->invalidateBuffer(widget->rect());
+ QCOMPARE(static_cast<UpdateWidget *>(widget)->numPaintEvents, 0);
+
+ // The entire widget is already dirty, but this time we want to update immediately
+ // by calling repaint(), and thus we have to repaint the widget and not wait for
+ // the UpdateRequest to be sent when we get back to the event loop.
+ widget->repaint();
+ QCOMPARE(static_cast<UpdateWidget *>(widget)->numPaintEvents, 1);
+
+ delete widget;
+}
+#endif
+
+void tst_QWidget::effectiveWinId()
+{
+ QWidget parent;
+ QWidget child(&parent);
+
+ // Shouldn't crash.
+ QVERIFY(!parent.effectiveWinId());
+ QVERIFY(!child.effectiveWinId());
+
+ parent.show();
+
+ QVERIFY(parent.effectiveWinId());
+ QVERIFY(child.effectiveWinId());
+}
+
+void tst_QWidget::effectiveWinId2()
+{
+ QWidget parent;
+
+ class MyWidget : public QWidget {
+ bool event(QEvent *e)
+ {
+ if (e->type() == QEvent::WinIdChange) {
+ // Shouldn't crash.
+ effectiveWinId();
+ }
+
+ return QWidget::event(e);
+ }
+ };
+
+ MyWidget child;
+ child.setParent(&parent);
+ parent.show();
+
+ child.setParent(0);
+ child.setParent(&parent);
+}
+
+class CustomWidget : public QWidget
+{
+public:
+ mutable int metricCallCount;
+
+ CustomWidget(QWidget *parent = 0) : QWidget(parent), metricCallCount(0) {}
+
+ virtual int metric(PaintDeviceMetric metric) const {
+ ++metricCallCount;
+ return QWidget::metric(metric);
+ }
+};
+
+void tst_QWidget::customDpi()
+{
+ QWidget *topLevel = new QWidget;
+ CustomWidget *custom = new CustomWidget(topLevel);
+ QWidget *child = new QWidget(custom);
+
+ custom->metricCallCount = 0;
+ topLevel->logicalDpiX();
+ QCOMPARE(custom->metricCallCount, 0);
+ custom->logicalDpiX();
+ QCOMPARE(custom->metricCallCount, 1);
+ child->logicalDpiX();
+ QCOMPARE(custom->metricCallCount, 2);
+
+ delete topLevel;
+}
+
+void tst_QWidget::customDpiProperty()
+{
+ QWidget *topLevel = new QWidget;
+ QWidget *middle = new CustomWidget(topLevel);
+ QWidget *child = new QWidget(middle);
+
+ const int initialDpiX = topLevel->logicalDpiX();
+ const int initialDpiY = topLevel->logicalDpiY();
+
+ middle->setProperty("_q_customDpiX", 300);
+ middle->setProperty("_q_customDpiY", 400);
+
+ QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
+ QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
+
+ QCOMPARE(middle->logicalDpiX(), 300);
+ QCOMPARE(middle->logicalDpiY(), 400);
+
+ QCOMPARE(child->logicalDpiX(), 300);
+ QCOMPARE(child->logicalDpiY(), 400);
+
+ middle->setProperty("_q_customDpiX", QVariant());
+ middle->setProperty("_q_customDpiY", QVariant());
+
+ QCOMPARE(topLevel->logicalDpiX(), initialDpiX);
+ QCOMPARE(topLevel->logicalDpiY(), initialDpiY);
+
+ QCOMPARE(middle->logicalDpiX(), initialDpiX);
+ QCOMPARE(middle->logicalDpiY(), initialDpiY);
+
+ QCOMPARE(child->logicalDpiX(), initialDpiX);
+ QCOMPARE(child->logicalDpiY(), initialDpiY);
+
+ delete topLevel;
+}
+
+void tst_QWidget::quitOnCloseAttribute()
+{
+ QWidget w;
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
+ w.setAttribute(Qt::WA_QuitOnClose, false);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
+
+ w.setAttribute(Qt::WA_QuitOnClose);
+ w.setWindowFlags(Qt::Tool);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
+
+ w.setAttribute(Qt::WA_QuitOnClose);
+ w.setWindowFlags(Qt::Popup);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
+
+ w.setAttribute(Qt::WA_QuitOnClose);
+ w.setWindowFlags(Qt::ToolTip);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
+
+ w.setAttribute(Qt::WA_QuitOnClose);
+ w.setWindowFlags(Qt::SplashScreen);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
+
+ w.setAttribute(Qt::WA_QuitOnClose);
+ w.setWindowFlags(Qt::SubWindow);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
+
+ w.setAttribute(Qt::WA_QuitOnClose);
+ w.setWindowFlags(Qt::Dialog);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
+ w.show();
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), true);
+ w.setWindowFlags(Qt::Tool);
+ QCOMPARE(w.testAttribute(Qt::WA_QuitOnClose), false);
+}
+
+void tst_QWidget::moveRect()
+{
+ QWidget widget;
+ widget.setUpdatesEnabled(false);
+ QWidget child(&widget);
+ child.setUpdatesEnabled(false);
+ child.setAttribute(Qt::WA_OpaquePaintEvent);
+ widget.show();
+ QTest::qWait(200);
+ child.move(10, 10); // Don't crash.
+}
+
+#ifdef Q_WS_WIN
+class GDIWidget : public QDialog
+{
+public:
+ GDIWidget() { setAttribute(Qt::WA_PaintOnScreen); }
+ QPaintEngine *paintEngine() const { return 0; }
+
+
+ void paintEvent(QPaintEvent *) {
+ HDC hdc = getDC();
+ SelectObject(hdc, CreateSolidBrush(RGB(255, 0, 0)));
+ Rectangle(hdc, 0, 0, 10, 10);
+
+ releaseDC(hdc);
+
+ QImage im = QPixmap::grabWindow(winId(), 0, 0, width(), height()).toImage();
+ color = im.pixel(1, 1);
+
+ accept();
+ }
+
+ QSize sizeHint() const {
+ return QSize(400, 300);
+ }
+
+ QColor color;
+};
+
+void tst_QWidget::gdiPainting()
+{
+ GDIWidget w;
+ w.exec();
+
+ QCOMPARE(w.color, QColor(255, 0, 0));
+
+}
+
+void tst_QWidget::paintOnScreenPossible()
+{
+ QWidget w1;
+ w1.setAttribute(Qt::WA_PaintOnScreen);
+ QVERIFY(!w1.testAttribute(Qt::WA_PaintOnScreen));
+
+ GDIWidget w2;
+ w2.setAttribute(Qt::WA_PaintOnScreen);
+ QVERIFY(w2.testAttribute(Qt::WA_PaintOnScreen));
+}
+#endif
+
+void tst_QWidget::reparentStaticWidget()
+{
+ QWidget window1;
+
+ QWidget *child = new QWidget(&window1);
+ child->setPalette(Qt::red);
+ child->setAutoFillBackground(true);
+ child->setAttribute(Qt::WA_StaticContents);
+ child->resize(100, 100);
+
+ QWidget *grandChild = new QWidget(child);
+ grandChild->setPalette(Qt::blue);
+ grandChild->setAutoFillBackground(true);
+ grandChild->resize(50, 50);
+ grandChild->setAttribute(Qt::WA_StaticContents);
+ window1.show();
+ QTest::qWaitForWindowShown(&window1);
+
+ QWidget window2;
+ window2.show();
+ QTest::qWaitForWindowShown(&window2);
+ QTest::qWait(20);
+
+ // Reparent into another top-level.
+ child->setParent(&window2);
+ child->show();
+
+ // Please don't crash.
+ window1.resize(window1.size() + QSize(2, 2));
+ QTest::qWait(20);
+
+ // Make sure we move all static children even though
+ // the reparented widget itself is non-static.
+ child->setAttribute(Qt::WA_StaticContents, false);
+ child->setParent(&window1);
+ child->show();
+
+ // Please don't crash.
+ window2.resize(window2.size() + QSize(2, 2));
+ QTest::qWait(20);
+
+ child->setParent(0);
+ child->show();
+ QTest::qWait(20);
+
+ // Please don't crash.
+ child->resize(child->size() + QSize(2, 2));
+ window2.resize(window2.size() + QSize(2, 2));
+ QTest::qWait(20);
+
+ QWidget *siblingOfGrandChild = new QWidget(child);
+ siblingOfGrandChild->show();
+ QTest::qWait(20);
+
+ // Nothing should happen when reparenting within the same top-level.
+ grandChild->setParent(siblingOfGrandChild);
+ grandChild->show();
+ QTest::qWait(20);
+
+ QWidget paintOnScreen;
+ paintOnScreen.setAttribute(Qt::WA_PaintOnScreen);
+ paintOnScreen.show();
+ QTest::qWaitForWindowShown(&paintOnScreen);
+ QTest::qWait(20);
+
+ child->setParent(&paintOnScreen);
+ child->show();
+ QTest::qWait(20);
+
+ // Please don't crash.
+ paintOnScreen.resize(paintOnScreen.size() + QSize(2, 2));
+ QTest::qWait(20);
+
+}
+
+void tst_QWidget::QTBUG6883_reparentStaticWidget2()
+{
+ QMainWindow mw;
+ QDockWidget *one = new QDockWidget("one", &mw);
+ mw.addDockWidget(Qt::LeftDockWidgetArea, one , Qt::Vertical);
+
+ QWidget *child = new QWidget();
+ child->setPalette(Qt::red);
+ child->setAutoFillBackground(true);
+ child->setAttribute(Qt::WA_StaticContents);
+ child->resize(100, 100);
+ one->setWidget(child);
+
+ QToolBar *mainTools = mw.addToolBar("Main Tools");
+ mainTools->addWidget(new QLineEdit);
+
+ mw.show();
+ QTest::qWaitForWindowShown(&mw);
+
+ one->setFloating(true);
+ QTest::qWait(20);
+ //do not crash
+}
+
+#ifdef Q_WS_QWS
+void tst_QWidget::updateOutsideSurfaceClip()
+{
+ UpdateWidget widget;
+ widget.setWindowFlags(Qt::FramelessWindowHint);
+ widget.resize(100, 100);
+ widget.raise();
+ widget.show();
+ QTest::qWait(200);
+ widget.reset();
+
+ // Move widget partially outside buffer and change the surface clip.
+ widget.move(-50, 0);
+ QTest::qWait(100);
+
+ // Update region is outside the surface clip and should not trigger a repaint.
+ widget.update(0, 0, 20, 20);
+ QTest::qWait(100);
+ QCOMPARE(widget.numPaintEvents, 0);
+
+ // Now, move the widget back so that the update region is inside the clip
+ // and make sure we get a repaint of the dirty area.
+ widget.move(0, 0);
+ QTest::qWait(100);
+ QCOMPARE(widget.numPaintEvents, 1);
+ QCOMPARE(widget.paintedRegion, QRegion(0, 0, 20, 20));
+}
+#endif
+class ColorRedWidget : public QWidget
+{
+public:
+ ColorRedWidget(QWidget *parent = 0)
+ : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::ToolTip)
+ {
+ }
+
+ void paintEvent(QPaintEvent *) {
+ QPainter p(this);
+ p.fillRect(rect(),Qt::red);
+ }
+};
+
+void tst_QWidget::translucentWidget()
+{
+ QPixmap pm(16,16);
+ pm.fill(Qt::red);
+ ColorRedWidget label;
+ label.setFixedSize(16,16);
+ label.setAttribute(Qt::WA_TranslucentBackground);
+ label.move(qApp->desktop()->availableGeometry().topLeft());
+ label.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&label);
+#endif
+ QTest::qWait(200);
+
+ QPixmap widgetSnapshot;
+
+#ifdef Q_WS_WIN
+ QWidget *desktopWidget = QApplication::desktop()->screen(0);
+ if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA)
+ widgetSnapshot = QPixmap::grabWindow(desktopWidget->winId(), 0,0, label.width(), label.height());
+ else
+#endif
+ widgetSnapshot = QPixmap::grabWindow(label.winId());
+ QImage actual = widgetSnapshot.toImage().convertToFormat(QImage::Format_RGB32);
+ QImage expected = pm.toImage().convertToFormat(QImage::Format_RGB32);
+ QCOMPARE(actual.size(),expected.size());
+ QCOMPARE(actual,expected);
+}
+
+class MaskResizeTestWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ MaskResizeTestWidget(QWidget* p =0)
+ : QWidget(p) {
+ setMask(QRegion(QRect(0, 0, 100, 100).normalized()));
+ }
+
+ void paintEvent(QPaintEvent* event) {
+ QPainter p(this);
+
+ paintedRegion += event->region();
+ foreach(QRect r, event->region().rects())
+ p.fillRect(r, Qt::red);
+ }
+
+ QRegion paintedRegion;
+
+public slots:
+ void enlargeMask() {
+ QRegion newMask(QRect(0, 0, 150, 150).normalized());
+ setMask(newMask);
+ }
+
+ void shrinkMask() {
+ QRegion newMask(QRect(0, 0, 50, 50).normalized());
+ setMask(newMask);
+ }
+
+};
+
+void tst_QWidget::setClearAndResizeMask()
+{
+ UpdateWidget topLevel;
+ topLevel.resize(150, 150);
+ topLevel.show();
+ QTest::qWaitForWindowShown(&topLevel);
+ QTRY_VERIFY(topLevel.numPaintEvents > 0);
+ topLevel.reset();
+
+ // Mask top-level widget
+ const QRegion topLevelMask(0, 0, 100, 100, QRegion::Ellipse);
+ topLevel.setMask(topLevelMask);
+ QCOMPARE(topLevel.mask(), topLevelMask);
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) // We don't control what's happening on other platforms.
+ // and ensure that the top-level doesn't get any update.
+ QCOMPARE(topLevel.numPaintEvents, 0);
+#endif
+
+ topLevel.reset();
+
+ // Clear top-level mask
+ topLevel.clearMask();
+ QCOMPARE(topLevel.mask(), QRegion());
+ QTest::qWait(10);
+ QRegion outsideOldMask(topLevel.rect());
+ outsideOldMask -= topLevelMask;
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) // We don't control what's happening on other platforms.
+ // and ensure that the top-level gets an update for the area outside the old mask.
+ QTRY_VERIFY(topLevel.numPaintEvents > 0);
+ QTRY_COMPARE(topLevel.paintedRegion, outsideOldMask);
+#endif
+
+ UpdateWidget child(&topLevel);
+ child.setAutoFillBackground(true); // NB! Opaque child.
+ child.setPalette(Qt::red);
+ child.resize(100, 100);
+ child.show();
+ QTest::qWait(10);
+
+ child.reset();
+ topLevel.reset();
+
+ // Mask child widget with a mask that is smaller than the rect
+ const QRegion childMask(0, 0, 50, 50);
+ child.setMask(childMask);
+ QTRY_COMPARE(child.mask(), childMask);
+ QTest::qWait(50);
+ // and ensure that the child widget doesn't get any update.
+#ifdef Q_WS_MAC
+ // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
+ if (child.internalWinId())
+ QCOMPARE(child.numPaintEvents, 1);
+ else
+#endif
+ QCOMPARE(child.numPaintEvents, 0);
+ // and the parent widget gets an update for the newly exposed area.
+ QTRY_COMPARE(topLevel.numPaintEvents, 1);
+ QRegion expectedParentExpose(child.rect());
+ expectedParentExpose -= childMask;
+ QCOMPARE(topLevel.paintedRegion, expectedParentExpose);
+
+ child.reset();
+ topLevel.reset();
+
+ // Clear child widget mask
+ child.clearMask();
+ QTRY_COMPARE(child.mask(), QRegion());
+ QTest::qWait(10);
+ // and ensure that that the child widget gets an update for the area outside the old mask.
+ QTRY_COMPARE(child.numPaintEvents, 1);
+ outsideOldMask = child.rect();
+#ifdef Q_WS_MAC
+ // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
+ if (!child.internalWinId())
+#endif
+ outsideOldMask -= childMask;
+ QCOMPARE(child.paintedRegion, outsideOldMask);
+ // and the parent widget doesn't get any update.
+ QCOMPARE(topLevel.numPaintEvents, 0);
+
+ child.reset();
+ topLevel.reset();
+
+ // Mask child widget with a mask that is bigger than the rect
+ child.setMask(QRegion(0, 0, 1000, 1000));
+ QTest::qWait(100);
+#ifdef Q_WS_MAC
+ // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
+ if (child.internalWinId())
+ QTRY_COMPARE(child.numPaintEvents, 1);
+ else
+#endif
+ // and ensure that we don't get any updates at all.
+ QTRY_COMPARE(child.numPaintEvents, 0);
+ QCOMPARE(topLevel.numPaintEvents, 0);
+
+ // ...and the same applies when clearing the mask.
+ child.clearMask();
+ QTest::qWait(100);
+#ifdef Q_WS_MAC
+ // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
+ if (child.internalWinId())
+ QTRY_VERIFY(child.numPaintEvents > 0);
+ else
+#endif
+ QCOMPARE(child.numPaintEvents, 0);
+ QCOMPARE(topLevel.numPaintEvents, 0);
+
+ QWidget resizeParent;
+ MaskResizeTestWidget resizeChild(&resizeParent);
+
+ resizeParent.resize(300,300);
+ resizeParent.raise();
+ resizeParent.setWindowFlags(Qt::WindowStaysOnTopHint);
+ resizeChild.setGeometry(50,50,200,200);
+ QPalette pal = resizeParent.palette();
+ pal.setColor(QPalette::Window, QColor(Qt::white));
+ resizeParent.setPalette(pal);
+
+ resizeParent.show();
+ QTest::qWaitForWindowShown(&resizeParent);
+ // Disable the size grip on the Mac; otherwise it'll be included when grabbing the window.
+ resizeParent.setFixedSize(resizeParent.size());
+ resizeChild.show();
+ QTest::qWait(100);
+ resizeChild.paintedRegion = QRegion();
+
+ QTimer::singleShot(100, &resizeChild, SLOT(shrinkMask()));
+ QTest::qWait(200);
+#ifdef Q_WS_MAC
+ // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
+ if (child.internalWinId())
+ QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
+ else
+#endif
+ QTRY_COMPARE(resizeChild.paintedRegion, QRegion());
+
+ resizeChild.paintedRegion = QRegion();
+ const QRegion oldMask = resizeChild.mask();
+ QTimer::singleShot(0, &resizeChild, SLOT(enlargeMask()));
+ QTest::qWait(100);
+#ifdef Q_WS_MAC
+ // Mac always issues a full update when calling setMask, and we cannot force it to not do so.
+ if (child.internalWinId())
+ QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask());
+ else
+#endif
+ QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask() - oldMask);
+}
+
+void tst_QWidget::maskedUpdate()
+{
+ UpdateWidget topLevel;
+ topLevel.resize(200, 200);
+ const QRegion topLevelMask(50, 50, 70, 70);
+ topLevel.setMask(topLevelMask);
+
+ UpdateWidget child(&topLevel);
+ child.setGeometry(20, 20, 180, 180);
+ const QRegion childMask(60, 60, 30, 30);
+ child.setMask(childMask);
+
+ UpdateWidget grandChild(&child);
+ grandChild.setGeometry(50, 50, 100, 100);
+ const QRegion grandChildMask(20, 20, 10, 10);
+ grandChild.setMask(grandChildMask);
+
+ topLevel.show();
+ QTest::qWaitForWindowShown(&topLevel);
+ QTRY_VERIFY(topLevel.numPaintEvents > 0);
+
+
+#define RESET_WIDGETS \
+ topLevel.reset(); \
+ child.reset(); \
+ grandChild.reset();
+
+#define CLEAR_MASK(widget) \
+ widget.clearMask(); \
+ QTest::qWait(100); \
+ RESET_WIDGETS;
+
+ // All widgets are transparent at this point, so any call to update() will result
+ // in composition, i.e. the update propagates to ancestors and children.
+
+ // TopLevel update.
+ RESET_WIDGETS;
+ topLevel.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, topLevelMask);
+ QTRY_COMPARE(child.paintedRegion, childMask);
+ QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
+
+ // Child update.
+ RESET_WIDGETS;
+ child.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, childMask.translated(child.pos()));
+ QTRY_COMPARE(child.paintedRegion, childMask);
+ QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
+
+ // GrandChild update.
+ RESET_WIDGETS;
+ grandChild.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, grandChildMask.translated(grandChild.mapTo(&topLevel, QPoint())));
+ QTRY_COMPARE(child.paintedRegion, grandChildMask.translated(grandChild.pos()));
+ QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
+
+ topLevel.setAttribute(Qt::WA_OpaquePaintEvent);
+ child.setAttribute(Qt::WA_OpaquePaintEvent);
+ grandChild.setAttribute(Qt::WA_OpaquePaintEvent);
+
+ // All widgets are now opaque, which means no composition, i.e.
+ // the update does not propate to ancestors and children.
+
+ // TopLevel update.
+ RESET_WIDGETS;
+ topLevel.update();
+ QTest::qWait(10);
+
+ QRegion expectedTopLevelUpdate = topLevelMask;
+ expectedTopLevelUpdate -= childMask.translated(child.pos()); // Subtract opaque children.
+ QTRY_COMPARE(topLevel.paintedRegion, expectedTopLevelUpdate);
+ QTRY_COMPARE(child.paintedRegion, QRegion());
+ QTRY_COMPARE(grandChild.paintedRegion, QRegion());
+
+ // Child update.
+ RESET_WIDGETS;
+ child.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, QRegion());
+ QRegion expectedChildUpdate = childMask;
+ expectedChildUpdate -= grandChildMask.translated(grandChild.pos()); // Subtract oapque children.
+ QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
+ QTRY_COMPARE(grandChild.paintedRegion, QRegion());
+
+ // GrandChild update.
+ RESET_WIDGETS;
+ grandChild.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, QRegion());
+ QTRY_COMPARE(child.paintedRegion, QRegion());
+ QTRY_COMPARE(grandChild.paintedRegion, grandChildMask);
+
+ // GrandChild update.
+ CLEAR_MASK(grandChild);
+ grandChild.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, QRegion());
+ QTRY_COMPARE(child.paintedRegion, QRegion());
+ QRegion expectedGrandChildUpdate = grandChild.rect();
+ // Clip with parent's mask.
+ expectedGrandChildUpdate &= childMask.translated(-grandChild.pos());
+ QCOMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
+
+ // GrandChild update.
+ CLEAR_MASK(child);
+ grandChild.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, QRegion());
+ QTRY_COMPARE(child.paintedRegion, QRegion());
+ expectedGrandChildUpdate = grandChild.rect();
+ // Clip with parent's mask.
+ expectedGrandChildUpdate &= topLevelMask.translated(-grandChild.mapTo(&topLevel, QPoint()));
+ QTRY_COMPARE(grandChild.paintedRegion, expectedGrandChildUpdate);
+
+ // Child update.
+ RESET_WIDGETS;
+ child.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, QRegion());
+ expectedChildUpdate = child.rect();
+ // Clip with parent's mask.
+ expectedChildUpdate &= topLevelMask.translated(-child.pos());
+ expectedChildUpdate -= grandChild.geometry(); // Subtract opaque children.
+ QTRY_COMPARE(child.paintedRegion, expectedChildUpdate);
+ QTRY_COMPARE(grandChild.paintedRegion, QRegion());
+
+ // GrandChild update.
+ CLEAR_MASK(topLevel);
+ grandChild.update();
+ QTest::qWait(10);
+
+ QTRY_COMPARE(topLevel.paintedRegion, QRegion());
+ QTRY_COMPARE(child.paintedRegion, QRegion());
+ QTRY_COMPARE(grandChild.paintedRegion, QRegion(grandChild.rect())); // Full update.
+}
+
+// Windows Mobile has no proper cursor support, so skip this test on that platform.
+#if defined(Q_WS_X11) || (defined(Q_WS_WIN) && !defined(Q_OS_WINCE_WM)) || defined(Q_WS_QWS) || defined(Q_WS_QPA)
+void tst_QWidget::syntheticEnterLeave()
+{
+ class MyWidget : public QWidget
+ {
+ public:
+ MyWidget(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numLeaveEvents(0) {}
+ void enterEvent(QEvent *) { ++numEnterEvents; }
+ void leaveEvent(QEvent *) { ++numLeaveEvents; }
+ int numEnterEvents;
+ int numLeaveEvents;
+ };
+
+ QCursor::setPos(QPoint(0,0));
+
+ MyWidget window;
+ window.setWindowFlags(Qt::WindowStaysOnTopHint);
+ window.resize(200, 200);
+
+ MyWidget *child1 = new MyWidget(&window);
+ child1->setPalette(Qt::blue);
+ child1->setAutoFillBackground(true);
+ child1->resize(200, 200);
+ child1->setCursor(Qt::OpenHandCursor);
+
+ MyWidget *child2 = new MyWidget(&window);
+ child2->resize(200, 200);
+
+ MyWidget *grandChild = new MyWidget(child2);
+ grandChild->setPalette(Qt::red);
+ grandChild->setAutoFillBackground(true);
+ grandChild->resize(200, 200);
+ grandChild->setCursor(Qt::WaitCursor);
+
+ window.show();
+ window.raise();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&window);
+#endif
+ QTest::qWait(300);
+
+#define RESET_EVENT_COUNTS \
+ window.numEnterEvents = 0; \
+ window.numLeaveEvents = 0; \
+ child1->numEnterEvents = 0; \
+ child1->numLeaveEvents = 0; \
+ child2->numEnterEvents = 0; \
+ child2->numLeaveEvents = 0; \
+ grandChild->numEnterEvents = 0; \
+ grandChild->numLeaveEvents = 0;
+
+ // Position the cursor in the middle of the window.
+ const QPoint globalPos = window.mapToGlobal(QPoint(100, 100));
+ QCursor::setPos(globalPos); // Enter child2 and grandChild.
+ QTest::qWait(300);
+
+ QCOMPARE(window.numLeaveEvents, 0);
+ QCOMPARE(child2->numLeaveEvents, 0);
+ QCOMPARE(grandChild->numLeaveEvents, 0);
+ QCOMPARE(child1->numLeaveEvents, 0);
+
+ // This event arrives asynchronously
+ QTRY_COMPARE(window.numEnterEvents, 1);
+ QCOMPARE(child2->numEnterEvents, 1);
+ QCOMPARE(grandChild->numEnterEvents, 1);
+ QCOMPARE(child1->numEnterEvents, 0);
+
+ RESET_EVENT_COUNTS;
+ child2->hide(); // Leave child2 and grandChild, enter child1.
+
+ QCOMPARE(window.numLeaveEvents, 0);
+ QCOMPARE(child2->numLeaveEvents, 1);
+ QCOMPARE(grandChild->numLeaveEvents, 1);
+ QCOMPARE(child1->numLeaveEvents, 0);
+
+ QCOMPARE(window.numEnterEvents, 0);
+ QCOMPARE(child2->numEnterEvents, 0);
+ QCOMPARE(grandChild->numEnterEvents, 0);
+ QCOMPARE(child1->numEnterEvents, 1);
+
+ RESET_EVENT_COUNTS;
+ child2->show(); // Leave child1, enter child2 and grandChild.
+
+ QCOMPARE(window.numLeaveEvents, 0);
+ QCOMPARE(child2->numLeaveEvents, 0);
+ QCOMPARE(grandChild->numLeaveEvents, 0);
+ QCOMPARE(child1->numLeaveEvents, 1);
+
+ QCOMPARE(window.numEnterEvents, 0);
+ QCOMPARE(child2->numEnterEvents, 1);
+ QCOMPARE(grandChild->numEnterEvents, 1);
+ QCOMPARE(child1->numEnterEvents, 0);
+
+ RESET_EVENT_COUNTS;
+ delete child2; // Enter child1 (and do not send leave events to child2 and grandChild).
+
+ QCOMPARE(window.numLeaveEvents, 0);
+ QCOMPARE(child1->numLeaveEvents, 0);
+
+ QCOMPARE(window.numEnterEvents, 0);
+ QCOMPARE(child1->numEnterEvents, 1);
+}
+#endif
+
+// Windows Mobile has no proper cursor support, so skip this test on that platform.
+#if defined(Q_WS_X11) || (defined(Q_WS_WIN) && !defined(Q_OS_WINCE_WM)) || defined(Q_WS_QWS) || defined(Q_WS_QPA)
+void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave()
+{
+ class SELParent : public QWidget
+ {
+ public:
+ SELParent(QWidget *parent = 0): QWidget(parent) { }
+
+ void mousePressEvent(QMouseEvent *) { child->show(); }
+ QWidget *child;
+ };
+
+ class SELChild : public QWidget
+ {
+ public:
+ SELChild(QWidget *parent = 0) : QWidget(parent), numEnterEvents(0), numMouseMoveEvents(0) {}
+ void enterEvent(QEvent *) { ++numEnterEvents; }
+ void mouseMoveEvent(QMouseEvent *event)
+ {
+ QCOMPARE(event->button(), Qt::NoButton);
+ QCOMPARE(event->buttons(), Qt::MouseButtons(Qt::NoButton));
+ ++numMouseMoveEvents;
+ }
+ void reset() { numEnterEvents = numMouseMoveEvents = 0; }
+ int numEnterEvents, numMouseMoveEvents;
+ };
+
+ QCursor::setPos(QPoint(0,0));
+
+ SELParent parent;
+ parent.resize(200, 200);
+ SELChild child(&parent);
+ child.resize(200, 200);
+ parent.show();
+ #ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&parent);
+ #endif
+ QTest::qWait(150);
+
+ QCursor::setPos(child.mapToGlobal(QPoint(100, 100)));
+ // Make sure the cursor has entered the child.
+ QTRY_VERIFY(child.numEnterEvents > 0);
+
+ child.hide();
+ child.reset();
+ child.show();
+
+ // Make sure the child gets enter event and no mouse move event.
+ QTRY_COMPARE(child.numEnterEvents, 1);
+ QCOMPARE(child.numMouseMoveEvents, 0);
+
+ child.hide();
+ child.reset();
+ child.setMouseTracking(true);
+ child.show();
+
+ // Make sure the child gets enter event and mouse move event.
+ // Note that we verify event->button() and event->buttons()
+ // in SELChild::mouseMoveEvent().
+ QTRY_COMPARE(child.numEnterEvents, 1);
+ QCOMPARE(child.numMouseMoveEvents, 1);
+
+ // Sending synthetic enter/leave trough the parent's mousePressEvent handler.
+ parent.child = &child;
+
+ child.hide();
+ child.reset();
+ QTest::mouseClick(&parent, Qt::LeftButton);
+
+ // Make sure the child gets enter event and one mouse move event.
+ QTRY_COMPARE(child.numEnterEvents, 1);
+ QCOMPARE(child.numMouseMoveEvents, 1);
+
+ child.hide();
+ child.reset();
+ child.setMouseTracking(false);
+ QTest::mouseClick(&parent, Qt::LeftButton);
+
+ // Make sure the child gets enter event and no mouse move event.
+ QTRY_COMPARE(child.numEnterEvents, 1);
+ QCOMPARE(child.numMouseMoveEvents, 0);
+ }
+#endif
+
+void tst_QWidget::windowFlags()
+{
+ QWidget w;
+ w.setWindowFlags(w.windowFlags() | Qt::FramelessWindowHint);
+ QVERIFY(w.windowFlags() & Qt::FramelessWindowHint);
+}
+
+void tst_QWidget::initialPosForDontShowOnScreenWidgets()
+{
+ { // Check default position.
+ const QPoint expectedPos(0, 0);
+ QWidget widget;
+ widget.setAttribute(Qt::WA_DontShowOnScreen);
+ widget.winId(); // Make sure create_sys is called.
+ QCOMPARE(widget.pos(), expectedPos);
+ QCOMPARE(widget.geometry().topLeft(), expectedPos);
+ }
+
+ { // Explicitly move to a position.
+ const QPoint expectedPos(100, 100);
+ QWidget widget;
+ widget.setAttribute(Qt::WA_DontShowOnScreen);
+ widget.move(expectedPos);
+ widget.winId(); // Make sure create_sys is called.
+ QCOMPARE(widget.pos(), expectedPos);
+ QCOMPARE(widget.geometry().topLeft(), expectedPos);
+ }
+}
+
+#ifdef Q_WS_X11
+void tst_QWidget::paintOutsidePaintEvent()
+{
+ QWidget widget;
+ widget.resize(200, 200);
+
+ QWidget child1(&widget);
+ child1.resize(100, 100);
+ child1.setPalette(Qt::red);
+ child1.setAutoFillBackground(true);
+
+ QWidget child2(&widget);
+ child2.setGeometry(50, 50, 100, 100);
+ child2.setPalette(Qt::blue);
+ child2.setAutoFillBackground(true);
+
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(60);
+
+ const QPixmap before = QPixmap::grabWindow(widget.winId());
+
+ // Child 1 should be clipped by child 2, so nothing should change.
+ child1.setAttribute(Qt::WA_PaintOutsidePaintEvent);
+ QPainter painter(&child1);
+ painter.fillRect(child1.rect(), Qt::red);
+ painter.end();
+ XSync(QX11Info::display(), false); // Flush output buffer.
+ QTest::qWait(60);
+
+ const QPixmap after = QPixmap::grabWindow(widget.winId());
+
+ QCOMPARE(before, after);
+}
+#endif
+
+class MyEvilObject : public QObject
+{
+ Q_OBJECT
+public:
+ MyEvilObject(QWidget *widgetToCrash) : QObject(), widget(widgetToCrash)
+ {
+ connect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(beEvil(QObject *)));
+ delete widget;
+ }
+ QWidget *widget;
+
+private slots:
+ void beEvil(QObject *) { widget->update(0, 0, 150, 150); }
+};
+
+void tst_QWidget::updateOnDestroyedSignal()
+{
+ QWidget widget;
+
+ QWidget *child = new QWidget(&widget);
+ child->resize(100, 100);
+ child->setAutoFillBackground(true);
+ child->setPalette(Qt::red);
+
+ widget.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&widget);
+#endif
+ QTest::qWait(200);
+
+ // Please do not crash.
+ MyEvilObject evil(child);
+ QTest::qWait(200);
+}
+
+void tst_QWidget::toplevelLineEditFocus()
+{
+ testWidget->hide();
+
+ QLineEdit w;
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QTest::qWait(20);
+
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&w);
+ QTRY_COMPARE(QApplication::focusWidget(), (QWidget*)&w);
+}
+
+void tst_QWidget::focusWidget_task254563()
+{
+ //having different visibility for widget is important
+ QWidget top;
+ top.show();
+ QWidget container(&top);
+ QWidget *widget = new QWidget(&container);
+ widget->show();
+
+ widget->setFocus(); //set focus (will set the focus widget up to the toplevel to be 'widget')
+ container.setFocus();
+ delete widget; // will call clearFocus but that doesn't help
+ QVERIFY(top.focusWidget() != widget); //dangling pointer
+}
+
+// This test case relies on developer build (AUTOTEST_EXPORT).
+#ifdef QT_BUILD_INTERNAL
+void tst_QWidget::destroyBackingStore()
+{
+ UpdateWidget w;
+ w.reset();
+ w.show();
+
+ QTest::qWaitForWindowShown(&w);
+ QApplication::processEvents();
+ QTRY_VERIFY(w.numPaintEvents > 0);
+ w.reset();
+ w.update();
+ qt_widget_private(&w)->topData()->backingStoreTracker.create(&w);
+
+ w.update();
+ QApplication::processEvents();
+#ifdef Q_WS_QWS
+ QApplication::processEvents();
+#endif
+ QCOMPARE(w.numPaintEvents, 1);
+
+ // Check one more time, because the second time around does more caching.
+ w.update();
+ QApplication::processEvents();
+ QCOMPARE(w.numPaintEvents, 2);
+}
+#endif
+
+// Helper function
+QWidgetBackingStore* backingStore(QWidget &widget)
+{
+ QWidgetBackingStore *backingStore = 0;
+#ifdef QT_BUILD_INTERNAL
+ if (QTLWExtra *topExtra = qt_widget_private(&widget)->maybeTopData())
+ backingStore = topExtra->backingStoreTracker.data();
+#endif
+ return backingStore;
+}
+
+// Tables of 5000 elements do not make sense on Windows Mobile.
+#ifndef Q_OS_WINCE_WM
+void tst_QWidget::rectOutsideCoordinatesLimit_task144779()
+{
+ QApplication::setOverrideCursor(Qt::BlankCursor); //keep the cursor out of screen grabs
+ QWidget main(0,Qt::FramelessWindowHint); //don't get confused by the size of the window frame
+ QPalette palette;
+ palette.setColor(QPalette::Window, Qt::red);
+ main.setPalette(palette);
+
+ QDesktopWidget desktop;
+ QRect desktopDimensions = desktop.availableGeometry(&main);
+ QSize mainSize(400, 400);
+ mainSize = mainSize.boundedTo(desktopDimensions.size());
+ main.resize(mainSize);
+
+ QWidget *offsetWidget = new QWidget(&main);
+ offsetWidget->setGeometry(0, -(15000 - mainSize.height()), mainSize.width(), 15000);
+
+ // big widget is too big for the coordinates, it must be limited by wrect
+ // if wrect is not at the right position because of offsetWidget, bigwidget
+ // is not painted correctly
+ QWidget *bigWidget = new QWidget(offsetWidget);
+ bigWidget->setGeometry(0, 0, mainSize.width(), 50000);
+ palette.setColor(QPalette::Window, Qt::green);
+ bigWidget->setPalette(palette);
+ bigWidget->setAutoFillBackground(true);
+
+ main.show();
+ QTest::qWaitForWindowShown(&main);
+
+ QPixmap correct(main.size());
+ correct.fill(Qt::green);
+
+ QTRY_COMPARE(QPixmap::grabWindow(main.winId()).toImage().convertToFormat(QImage::Format_RGB32),
+ correct.toImage().convertToFormat(QImage::Format_RGB32));
+ QApplication::restoreOverrideCursor();
+}
+#endif
+
+void tst_QWidget::inputFocus_task257832()
+{
+ QLineEdit *widget = new QLineEdit;
+ QInputContext *context = widget->inputContext();
+ if (!context)
+ QSKIP("No input context", SkipSingle);
+ widget->setFocus();
+ widget->winId(); // make sure, widget has been created
+ context->setFocusWidget(widget);
+ QCOMPARE(context->focusWidget(), static_cast<QWidget*>(widget));
+ widget->setReadOnly(true);
+ QVERIFY(!context->focusWidget());
+ delete widget;
+}
+
+void tst_QWidget::setGraphicsEffect()
+{
+ // Check that we don't have any effect by default.
+ QWidget *widget = new QWidget;
+ QVERIFY(!widget->graphicsEffect());
+
+ // SetGet check.
+ QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
+ widget->setGraphicsEffect(blurEffect);
+ QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
+
+ // Ensure the existing effect is deleted when setting a new one.
+ QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
+ widget->setGraphicsEffect(shadowEffect);
+ QVERIFY(!blurEffect);
+ QCOMPARE(widget->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
+ blurEffect = new QGraphicsBlurEffect;
+
+ // Ensure the effect is uninstalled when setting it on a new target.
+ QWidget *anotherWidget = new QWidget;
+ anotherWidget->setGraphicsEffect(blurEffect);
+ widget->setGraphicsEffect(blurEffect);
+ QVERIFY(!anotherWidget->graphicsEffect());
+ QVERIFY(!shadowEffect);
+
+ // Ensure the existing effect is deleted when deleting the widget.
+ delete widget;
+ QVERIFY(!blurEffect);
+ delete anotherWidget;
+
+ // Ensure the effect is uninstalled when deleting it
+ widget = new QWidget;
+ blurEffect = new QGraphicsBlurEffect;
+ widget->setGraphicsEffect(blurEffect);
+ delete blurEffect;
+ QVERIFY(!widget->graphicsEffect());
+
+ // Ensure the existing effect is uninstalled and deleted when setting a null effect
+ blurEffect = new QGraphicsBlurEffect;
+ widget->setGraphicsEffect(blurEffect);
+ widget->setGraphicsEffect(0);
+ QVERIFY(!widget->graphicsEffect());
+ QVERIFY(!blurEffect);
+
+ delete widget;
+}
+
+void tst_QWidget::activateWindow()
+{
+ // Test case for task 260685
+
+ // Create first mainwindow and set it active
+ QMainWindow* mainwindow = new QMainWindow();
+ QLabel* label = new QLabel(mainwindow);
+ mainwindow->setCentralWidget(label);
+ mainwindow->setVisible(true);
+ mainwindow->activateWindow();
+ QTest::qWaitForWindowShown(mainwindow);
+ qApp->processEvents();
+
+ QTRY_VERIFY(mainwindow->isActiveWindow());
+
+ // Create second mainwindow and set it active
+ QMainWindow* mainwindow2 = new QMainWindow();
+ QLabel* label2 = new QLabel(mainwindow2);
+ mainwindow2->setCentralWidget(label2);
+ mainwindow2->setVisible(true);
+ mainwindow2->activateWindow();
+ qApp->processEvents();
+
+ QTRY_VERIFY(!mainwindow->isActiveWindow());
+ QTRY_VERIFY(mainwindow2->isActiveWindow());
+
+ // Revert first mainwindow back to visible active
+ mainwindow->setVisible(true);
+ mainwindow->activateWindow();
+ qApp->processEvents();
+
+ QTRY_VERIFY(mainwindow->isActiveWindow());
+ QTRY_VERIFY(!mainwindow2->isActiveWindow());
+}
+
+void tst_QWidget::openModal_taskQTBUG_5804()
+{
+ class Widget : public QWidget
+ {
+ public:
+ Widget(QWidget *parent) : QWidget(parent)
+ {
+ }
+ ~Widget()
+ {
+ QMessageBox msgbox;
+ QTimer::singleShot(10, &msgbox, SLOT(accept()));
+ msgbox.exec(); //open a modal dialog
+ }
+ };
+
+ QWidget *win = new QWidget;
+ new Widget(win);
+ win->show();
+ QTest::qWaitForWindowShown(win);
+ delete win;
+}
+
+class InputContextTester : public QInputContext
+{
+ Q_OBJECT
+public:
+ QString identifierName() { return QString(); }
+ bool isComposing() const { return false; }
+ QString language() { return QString(); }
+ void reset() { ++resets; }
+ int resets;
+};
+
+void tst_QWidget::focusProxyAndInputMethods()
+{
+ InputContextTester *inputContext = new InputContextTester;
+ QWidget *toplevel = new QWidget(0, Qt::X11BypassWindowManagerHint);
+ toplevel->setAttribute(Qt::WA_InputMethodEnabled, true);
+ qApp->setInputContext(inputContext); // ownership is transferred
+
+ QWidget *child = new QWidget(toplevel);
+ child->setFocusProxy(toplevel);
+ child->setAttribute(Qt::WA_InputMethodEnabled, true);
+
+ toplevel->setFocusPolicy(Qt::WheelFocus);
+ child->setFocusPolicy(Qt::WheelFocus);
+
+ QVERIFY(!child->hasFocus());
+ QVERIFY(!toplevel->hasFocus());
+
+ toplevel->show();
+ QTest::qWaitForWindowShown(toplevel);
+ QApplication::setActiveWindow(toplevel);
+ QVERIFY(toplevel->hasFocus());
+ QVERIFY(child->hasFocus());
+
+ // verify that toggling input methods on the child widget
+ // correctly propagate to the focus proxy's input method
+ // and that the input method gets the focus proxy passed
+ // as the focus widget instead of the child widget.
+ // otherwise input method queries go to the wrong widget
+
+ QCOMPARE(inputContext->focusWidget(), toplevel);
+
+ child->setAttribute(Qt::WA_InputMethodEnabled, false);
+ QVERIFY(!inputContext->focusWidget());
+
+ child->setAttribute(Qt::WA_InputMethodEnabled, true);
+ QCOMPARE(inputContext->focusWidget(), toplevel);
+
+ child->setEnabled(false);
+ QVERIFY(!inputContext->focusWidget());
+
+ child->setEnabled(true);
+ QCOMPARE(inputContext->focusWidget(), toplevel);
+
+ delete toplevel;
+}
+
+#ifdef QT_BUILD_INTERNAL
+class scrollWidgetWBS : public QWidget
+{
+public:
+ void deleteBackingStore()
+ {
+ static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.destroy();
+ }
+ void enableBackingStore()
+ {
+ if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) {
+ static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.create(this);
+ static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBuffer(this->rect());
+ repaint();
+ }
+ }
+};
+#endif
+
+// Test case relies on developer build (AUTOTEST_EXPORT).
+#ifdef QT_BUILD_INTERNAL
+void tst_QWidget::scrollWithoutBackingStore()
+{
+ scrollWidgetWBS scrollable;
+ scrollable.resize(100,100);
+ QLabel child(QString("@"),&scrollable);
+ child.resize(50,50);
+ scrollable.show();
+ QTest::qWaitForWindowShown(&scrollable);
+ scrollable.scroll(50,50);
+ QCOMPARE(child.pos(),QPoint(50,50));
+ scrollable.deleteBackingStore();
+ scrollable.scroll(-25,-25);
+ QCOMPARE(child.pos(),QPoint(25,25));
+ scrollable.enableBackingStore();
+ QCOMPARE(child.pos(),QPoint(25,25));
+}
+#endif
+
+void tst_QWidget::taskQTBUG_7532_tabOrderWithFocusProxy()
+{
+ QWidget w;
+ w.setFocusPolicy(Qt::TabFocus);
+ QWidget *fp = new QWidget(&w);
+ fp->setFocusPolicy(Qt::TabFocus);
+ w.setFocusProxy(fp);
+ QWidget::setTabOrder(&w, fp);
+
+ // In debug mode, no assertion failure means it's alright.
+}
+
+void tst_QWidget::movedAndResizedAttributes()
+{
+#if defined (Q_OS_MAC) || defined(Q_WS_QWS)
+ QEXPECT_FAIL("", "FixMe, QTBUG-8941 and QTBUG-8977", Abort);
+ QVERIFY(false);
+#else
+ QWidget w;
+ w.show();
+
+ QVERIFY(!w.testAttribute(Qt::WA_Moved));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.setWindowState(Qt::WindowFullScreen);
+
+ QVERIFY(!w.testAttribute(Qt::WA_Moved));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.setWindowState(Qt::WindowMaximized);
+
+ QVERIFY(!w.testAttribute(Qt::WA_Moved));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.setWindowState(Qt::WindowMinimized);
+
+ QVERIFY(!w.testAttribute(Qt::WA_Moved));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.showNormal();
+
+ QVERIFY(!w.testAttribute(Qt::WA_Moved));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.showMaximized();
+
+ QVERIFY(!w.testAttribute(Qt::WA_Moved));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.showFullScreen();
+
+ QVERIFY(!w.testAttribute(Qt::WA_Moved));
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.showNormal();
+ w.move(10,10);
+ QVERIFY(w.testAttribute(Qt::WA_Moved));
+#if defined(Q_OS_WIN)
+ QEXPECT_FAIL("", "FixMe, QTBUG-8911", Abort);
+#endif
+ QVERIFY(!w.testAttribute(Qt::WA_Resized));
+
+ w.resize(100, 100);
+ QVERIFY(w.testAttribute(Qt::WA_Moved));
+ QVERIFY(w.testAttribute(Qt::WA_Resized));
+#endif
+}
+
+void tst_QWidget::childAt()
+{
+ QWidget parent(0, Qt::FramelessWindowHint);
+ parent.resize(200, 200);
+
+ QWidget *child = new QWidget(&parent);
+ child->setPalette(Qt::red);
+ child->setAutoFillBackground(true);
+ child->setGeometry(20, 20, 160, 160);
+
+ QWidget *grandChild = new QWidget(child);
+ grandChild->setPalette(Qt::blue);
+ grandChild->setAutoFillBackground(true);
+ grandChild->setGeometry(-20, -20, 220, 220);
+
+ QVERIFY(!parent.childAt(19, 19));
+ QVERIFY(!parent.childAt(180, 180));
+ QCOMPARE(parent.childAt(20, 20), grandChild);
+ QCOMPARE(parent.childAt(179, 179), grandChild);
+
+ grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
+ QCOMPARE(parent.childAt(20, 20), child);
+ QCOMPARE(parent.childAt(179, 179), child);
+ grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
+
+ child->setMask(QRect(50, 50, 60, 60));
+
+ QVERIFY(!parent.childAt(69, 69));
+ QVERIFY(!parent.childAt(130, 130));
+ QCOMPARE(parent.childAt(70, 70), grandChild);
+ QCOMPARE(parent.childAt(129, 129), grandChild);
+
+ child->setAttribute(Qt::WA_MouseNoMask);
+ QCOMPARE(parent.childAt(69, 69), grandChild);
+ QCOMPARE(parent.childAt(130, 130), grandChild);
+ child->setAttribute(Qt::WA_MouseNoMask, false);
+
+ grandChild->setAttribute(Qt::WA_TransparentForMouseEvents);
+ QCOMPARE(parent.childAt(70, 70), child);
+ QCOMPARE(parent.childAt(129, 129), child);
+ grandChild->setAttribute(Qt::WA_TransparentForMouseEvents, false);
+
+ grandChild->setMask(QRect(80, 80, 40, 40));
+
+ QCOMPARE(parent.childAt(79, 79), child);
+ QCOMPARE(parent.childAt(120, 120), child);
+ QCOMPARE(parent.childAt(80, 80), grandChild);
+ QCOMPARE(parent.childAt(119, 119), grandChild);
+
+ grandChild->setAttribute(Qt::WA_MouseNoMask);
+
+ QCOMPARE(parent.childAt(79, 79), grandChild);
+ QCOMPARE(parent.childAt(120, 120), grandChild);
+}
+
+#ifdef Q_WS_MAC
+void tst_QWidget::childAt_unifiedToolBar()
+{
+ QLabel *label = new QLabel(QLatin1String("foo"));
+ QToolBar *toolBar = new QToolBar;
+ toolBar->addWidget(new QLabel("dummy"));
+ toolBar->addWidget(label);
+
+ QMainWindow mainWindow;
+ mainWindow.addToolBar(toolBar);
+ mainWindow.show();
+
+ // Calculate the top-left corner of the tool bar and the label (in mainWindow's coordinates).
+ QPoint labelTopLeft = label->mapTo(&mainWindow, QPoint());
+ QPoint toolBarTopLeft = toolBar->mapTo(&mainWindow, QPoint());
+
+ QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
+ QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
+
+ // Enable unified tool bars.
+ mainWindow.setUnifiedTitleAndToolBarOnMac(true);
+ QTest::qWait(50);
+
+ // The tool bar is now in the "non-client" area of QMainWindow, i.e.
+ // outside the mainWindow's rect(), and since mapTo et al. doesn't work
+ // in that case (see commit 35667fd45ada49269a5987c235fdedfc43e92bb8),
+ // we use mapToGlobal/mapFromGlobal to re-calculate the corners.
+ QPoint oldToolBarTopLeft = toolBarTopLeft;
+ toolBarTopLeft = mainWindow.mapFromGlobal(toolBar->mapToGlobal(QPoint()));
+ QVERIFY(toolBarTopLeft != oldToolBarTopLeft);
+ QVERIFY(toolBarTopLeft.y() < 0);
+ labelTopLeft = mainWindow.mapFromGlobal(label->mapToGlobal(QPoint()));
+
+ QCOMPARE(mainWindow.childAt(toolBarTopLeft), static_cast<QWidget *>(toolBar));
+ QCOMPARE(mainWindow.childAt(labelTopLeft), static_cast<QWidget *>(label));
+}
+
+void tst_QWidget::taskQTBUG_11373()
+{
+ QMainWindow * myWindow = new QMainWindow();
+ QWidget * center = new QWidget();
+ myWindow -> setCentralWidget(center);
+ QWidget * drawer = new QWidget(myWindow, Qt::Drawer);
+ drawer -> hide();
+ QCOMPARE(drawer->isVisible(), false);
+ myWindow -> show();
+ myWindow -> raise();
+ // The drawer shouldn't be visible now.
+ QCOMPARE(drawer->isVisible(), false);
+ myWindow -> setWindowState(Qt::WindowFullScreen);
+ myWindow -> setWindowState(Qt::WindowNoState);
+ // The drawer should still not be visible, since we haven't shown it.
+ QCOMPARE(drawer->isVisible(), false);
+}
+#endif
+
+void tst_QWidget::taskQTBUG_17333_ResizeInfiniteRecursion()
+{
+ QTableView tb;
+ const char *s = "border: 1px solid;";
+ tb.setStyleSheet(s);
+ tb.show();
+
+ QTest::qWaitForWindowShown(&tb);
+ tb.setGeometry(QRect(100, 100, 0, 100));
+ // No crash, it works.
+}
+
+void tst_QWidget::nativeChildFocus()
+{
+ QWidget w;
+ QLayout *layout = new QVBoxLayout;
+ w.setLayout(layout);
+ QLineEdit *p1 = new QLineEdit;
+ QLineEdit *p2 = new QLineEdit;
+ layout->addWidget(p1);
+ layout->addWidget(p2);
+#if 1
+ p1->setObjectName("p1");
+ p2->setObjectName("p2");
+#endif
+ w.show();
+#if 1
+ w.activateWindow();
+ p1->setFocus();
+ p1->setAttribute(Qt::WA_NativeWindow);
+ p2->setAttribute(Qt::WA_NativeWindow);
+ QApplication::processEvents();
+ QTest::qWaitForWindowShown(&w);
+ QTest::qWait(10);
+
+ qDebug() << "checking active window:" << QApplication::activeWindow();
+ QCOMPARE(QApplication::activeWindow(), &w);
+ QCOMPARE(QApplication::focusWidget(), static_cast<QWidget*>(p1));
+#endif
+
+ QTest::qWait(1000);
+}
+
+QTEST_MAIN(tst_QWidget)
+#include "tst_qwidget.moc"
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.h b/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.h
new file mode 100644
index 0000000000..d7bc3f33c7
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtCore/QString>
+#include <QtCore/QPair>
+#include <QtGui/QWidget>
+
+#pragma once // Yeah, it's deprecated in general, but it's standard practive for Mac OS X.
+
+QString nativeWindowTitle(QWidget *widget, Qt::WindowState state);
+bool nativeWindowModified(QWidget *widget);
+
+typedef QPair<QWidget *, WId> WidgetViewPair;
+bool testAndRelease(const WId);
+WidgetViewPair createAndRetain(QWidget * const parent = 0);
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.mm b/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.mm
new file mode 100644
index 0000000000..10e137c06c
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.mm
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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 documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "tst_qwidget_mac_helpers.h"
+#include <private/qt_mac_p.h>
+#include <private/qt_cocoa_helpers_mac_p.h>
+
+
+QString nativeWindowTitle(QWidget *window, Qt::WindowState state)
+{
+ OSWindowRef windowRef = qt_mac_window_for(window);
+ QCFString macTitle;
+ if (state == Qt::WindowMinimized) {
+ macTitle = reinterpret_cast<CFStringRef>([[windowRef miniwindowTitle] retain]);
+ } else {
+ macTitle = reinterpret_cast<CFStringRef>([[windowRef title] retain]);
+ }
+ return macTitle;
+}
+
+bool nativeWindowModified(QWidget *widget)
+{
+ return [qt_mac_window_for(widget) isDocumentEdited];
+}
+
+bool testAndRelease(const WId view)
+{
+ if ([id(view) retainCount] != 2)
+ return false;
+ [id(view) release];
+ [id(view) release];
+ return true;
+}
+
+WidgetViewPair createAndRetain(QWidget * const parent)
+{
+ QWidget * const widget = new QWidget(parent);
+ const WId view = widget->winId();
+ // Retain twice so we can safely call retainCount even if the retain count
+ // is off by one because of a double release.
+ [id(view) retain];
+ [id(view) retain];
+ return qMakePair(widget, view);
+}
+
diff --git a/tests/auto/widgets/kernel/qwidget_window/.gitignore b/tests/auto/widgets/kernel/qwidget_window/.gitignore
new file mode 100644
index 0000000000..7f0bd8d631
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget_window/.gitignore
@@ -0,0 +1 @@
+tst_qwidget_window
diff --git a/tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro b/tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro
new file mode 100644
index 0000000000..dd5837012c
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget_window/qwidget_window.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qwidget_window.cpp
+
+x11 {
+ LIBS += $$QMAKE_LIBS_X11
+}
+
diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
new file mode 100644
index 0000000000..eb8b555bd6
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui/QtGui>
+#include <qeventloop.h>
+#include <qlist.h>
+
+#include <qlistwidget.h>
+
+#ifdef Q_WS_X11
+#include <X11/Xlib.h>
+#include <QX11Info>
+#endif // Q_WS_X11
+
+class tst_QWidget_window : public QWidget
+{
+ Q_OBJECT
+
+public:
+ tst_QWidget_window(){};
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+
+private slots:
+ void tst_move_show();
+ void tst_show_move();
+ void tst_show_move_hide_show();
+
+ void tst_resize_show();
+ void tst_show_resize();
+ void tst_show_resize_hide_show();
+
+ void tst_windowFilePathAndwindowTitle_data();
+ void tst_windowFilePathAndwindowTitle();
+ void tst_windowFilePath_data();
+ void tst_windowFilePath();
+
+#ifdef Q_WS_X11
+ void tst_showWithoutActivating();
+#endif
+ void tst_paintEventOnSecondShow();
+};
+
+void tst_QWidget_window::initTestCase()
+{
+}
+
+void tst_QWidget_window::cleanupTestCase()
+{
+}
+
+void tst_QWidget_window::tst_move_show()
+{
+ QWidget w;
+ w.move(100, 100);
+ w.show();
+ QCOMPARE(w.pos(), QPoint(100, 100));
+// QCoreApplication::processEvents(QEventLoop::AllEvents, 3000);
+}
+
+void tst_QWidget_window::tst_show_move()
+{
+ QWidget w;
+ w.show();
+ w.move(100, 100);
+ QCOMPARE(w.pos(), QPoint(100, 100));
+// QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+}
+
+void tst_QWidget_window::tst_show_move_hide_show()
+{
+ QWidget w;
+ w.show();
+ w.move(100, 100);
+ w.hide();
+ w.show();
+ QCOMPARE(w.pos(), QPoint(100, 100));
+// QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+}
+
+void tst_QWidget_window::tst_resize_show()
+{
+ QWidget w;
+ w.resize(200, 200);
+ w.show();
+ QCOMPARE(w.size(), QSize(200, 200));
+// QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+}
+
+void tst_QWidget_window::tst_show_resize()
+{
+ QWidget w;
+ w.show();
+ w.resize(200, 200);
+ QCOMPARE(w.size(), QSize(200, 200));
+// QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+}
+
+void tst_QWidget_window::tst_show_resize_hide_show()
+{
+ QWidget w;
+ w.show();
+ w.resize(200, 200);
+ w.hide();
+ w.show();
+ QCOMPARE(w.size(), QSize(200, 200));
+// QCoreApplication::processEvents(QEventLoop::AllEvents, 1000);
+}
+
+class TestWidget : public QWidget
+{
+public:
+ int m_first, m_next;
+ bool paintEventReceived;
+
+ void reset(){ m_first = m_next = 0; paintEventReceived = false; }
+ bool event(QEvent *event)
+ {
+ switch (event->type()) {
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate:
+ case QEvent::Hide:
+ case QEvent::Show:
+ if (m_first)
+ m_next = event->type();
+ else
+ m_first = event->type();
+ break;
+ case QEvent::Paint:
+ paintEventReceived = true;
+ break;
+ default:
+ break;
+ }
+ return QWidget::event(event);
+ }
+};
+
+void tst_QWidget_window::tst_windowFilePathAndwindowTitle_data()
+{
+ QTest::addColumn<bool>("setWindowTitleBefore");
+ QTest::addColumn<bool>("setWindowTitleAfter");
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<QString>("applicationName");
+ QTest::addColumn<QString>("indyWindowTitle");
+ QTest::addColumn<QString>("finalTitleBefore");
+ QTest::addColumn<QString>("finalTitleAfter");
+
+ QString validPath = QApplication::applicationFilePath();
+ QString appName = QLatin1String("Killer App");
+ QString fileNameOnly = QFileInfo(validPath).fileName() + QLatin1String("[*]");
+ QString fileAndApp = fileNameOnly + QLatin1String(" ") + QChar(0x2014) + QLatin1String(" ") + appName;
+ QString windowTitle = QLatin1String("Here is a Window Title");
+
+ QTest::newRow("never Set Title nor AppName") << false << false << validPath << QString() << windowTitle << fileNameOnly << fileNameOnly;
+ QTest::newRow("set title after only, but no AppName") << false << true << validPath << QString() << windowTitle << fileNameOnly << windowTitle;
+ QTest::newRow("set title before only, not AppName") << true << false << validPath << QString() << windowTitle << windowTitle << windowTitle;
+ QTest::newRow("always set title, not appName") << true << true << validPath << QString() << windowTitle << windowTitle << windowTitle;
+
+ QString platString =
+#ifdef Q_WS_MAC
+ fileNameOnly;
+#else
+ fileAndApp;
+#endif
+
+ QTest::newRow("never Set Title, yes AppName") << false << false << validPath << appName << windowTitle << platString << platString;
+ QTest::newRow("set title after only, yes AppName") << false << true << validPath << appName << windowTitle << platString << windowTitle;
+ QTest::newRow("set title before only, yes AppName") << true << false << validPath << appName << windowTitle << windowTitle << windowTitle;
+ QTest::newRow("always set title, yes appName") << true << true << validPath << appName << windowTitle << windowTitle << windowTitle;
+}
+
+void tst_QWidget_window::tst_windowFilePathAndwindowTitle()
+{
+ QFETCH(bool, setWindowTitleBefore);
+ QFETCH(bool, setWindowTitleAfter);
+ QFETCH(QString, filePath);
+ QFETCH(QString, applicationName);
+ QFETCH(QString, indyWindowTitle);
+ QFETCH(QString, finalTitleBefore);
+ QFETCH(QString, finalTitleAfter);
+
+
+ QWidget widget;
+ QCOMPARE(widget.windowFilePath(), QString());
+
+ if (!applicationName.isEmpty())
+ qApp->setApplicationName(applicationName);
+ else
+ qApp->setApplicationName(QString());
+
+ if (setWindowTitleBefore) {
+ widget.setWindowTitle(indyWindowTitle);
+ }
+ widget.setWindowFilePath(filePath);
+ QCOMPARE(finalTitleBefore, widget.windowTitle());
+ QCOMPARE(widget.windowFilePath(), filePath);
+
+ if (setWindowTitleAfter) {
+ widget.setWindowTitle(indyWindowTitle);
+ }
+ QCOMPARE(finalTitleAfter, widget.windowTitle());
+ QCOMPARE(widget.windowFilePath(), filePath);
+}
+
+void tst_QWidget_window::tst_windowFilePath_data()
+{
+ QTest::addColumn<QString>("filePath");
+ QTest::addColumn<QString>("result");
+ QTest::addColumn<bool>("again");
+ QTest::addColumn<QString>("filePath2");
+ QTest::addColumn<QString>("result2");
+
+ QString validPath = QApplication::applicationFilePath();
+ QString invalidPath = QLatin1String("::**Never a Real Path**::");
+
+ QTest::newRow("never Set Path") << QString() << QString() << false << QString() << QString();
+ QTest::newRow("never EVER Set Path") << QString() << QString() << true << QString() << QString();
+ QTest::newRow("Valid Path") << validPath << validPath << false << QString() << QString();
+ QTest::newRow("invalid Path") << invalidPath << invalidPath << false << QString() << QString();
+ QTest::newRow("Valid Path then empty") << validPath << validPath << true << QString() << QString();
+ QTest::newRow("invalid Path then empty") << invalidPath << invalidPath << true << QString() << QString();
+ QTest::newRow("invalid Path then valid") << invalidPath << invalidPath << true << validPath << validPath;
+ QTest::newRow("valid Path then invalid") << validPath << validPath << true << invalidPath << invalidPath;
+}
+
+void tst_QWidget_window::tst_windowFilePath()
+{
+ QFETCH(QString, filePath);
+ QFETCH(QString, result);
+ QFETCH(bool, again);
+ QFETCH(QString, filePath2);
+ QFETCH(QString, result2);
+
+ QWidget widget;
+ QCOMPARE(widget.windowFilePath(), QString());
+ widget.setWindowFilePath(filePath);
+ QCOMPARE(widget.windowFilePath(), result);
+ if (again) {
+ widget.setWindowFilePath(filePath2);
+ QCOMPARE(widget.windowFilePath(), result2);
+ }
+}
+
+#ifdef Q_WS_X11
+void tst_QWidget_window::tst_showWithoutActivating()
+{
+ QWidget w;
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QApplication::processEvents();
+
+ QApplication::clipboard();
+ QLineEdit *lineEdit = new QLineEdit;
+ lineEdit->setAttribute(Qt::WA_ShowWithoutActivating, true);
+ lineEdit->show();
+ lineEdit->setAttribute(Qt::WA_ShowWithoutActivating, false);
+ lineEdit->raise();
+ lineEdit->activateWindow();
+
+ Window window;
+ int revertto;
+ QTRY_COMPARE(lineEdit->winId(),
+ (XGetInputFocus(QX11Info::display(), &window, &revertto), window) );
+ // Note the use of the , before window because we want the XGetInputFocus to be re-executed
+ // in each iteration of the inside loop of the QTRY_COMPARE macro
+}
+#endif
+
+void tst_QWidget_window::tst_paintEventOnSecondShow()
+{
+ TestWidget w;
+ w.show();
+ w.hide();
+
+ w.reset();
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+ QApplication::processEvents();
+ QTRY_VERIFY(w.paintEventReceived);
+}
+
+QTEST_MAIN(tst_QWidget_window)
+#include "tst_qwidget_window.moc"
diff --git a/tests/auto/widgets/kernel/qwidgetaction/.gitignore b/tests/auto/widgets/kernel/qwidgetaction/.gitignore
new file mode 100644
index 0000000000..56d519d851
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidgetaction/.gitignore
@@ -0,0 +1 @@
+tst_qwidgetaction
diff --git a/tests/auto/widgets/kernel/qwidgetaction/qwidgetaction.pro b/tests/auto/widgets/kernel/qwidgetaction/qwidgetaction.pro
new file mode 100644
index 0000000000..3e037c2efb
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidgetaction/qwidgetaction.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qwidgetaction.cpp
+
+
diff --git a/tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp b/tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp
new file mode 100644
index 0000000000..5f51f6d316
--- /dev/null
+++ b/tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp
@@ -0,0 +1,405 @@
+/****************************************************************************
+**
+** 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$
+** GNU Lesser General Public License Usage
+** 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.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qapplication.h>
+#include <qtoolbar.h>
+#include <qcombobox.h>
+#include <qwidgetaction.h>
+#include <qlabel.h>
+#include <qmenu.h>
+#include <qmainwindow.h>
+#include <qmenubar.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QWidgetAction : public QObject
+{
+ Q_OBJECT
+private slots:
+ void defaultWidget();
+ void visibilityUpdate();
+ void customWidget();
+ void keepOwnership();
+ void visibility();
+ void setEnabled();
+ void popup();
+ void releaseWidgetCrash();
+};
+
+void tst_QWidgetAction::defaultWidget()
+{
+ {
+ QToolBar tb1;
+
+ QPointer<QComboBox> combo = new QComboBox(&tb1);
+
+ QWidgetAction *action = new QWidgetAction(0);
+ action->setDefaultWidget(combo);
+
+ QVERIFY(!combo->isVisible());
+ QVERIFY(!combo->parent());
+ QVERIFY(action->isVisible());
+
+ delete action;
+ QVERIFY(!combo);
+ }
+ {
+ QToolBar tb1;
+
+ QPointer<QComboBox> combo = new QComboBox(&tb1);
+ combo->hide();
+
+ QWidgetAction *action = new QWidgetAction(0);
+ action->setDefaultWidget(combo);
+
+ // explicitly hidden widgets should also set the action invisible
+ QVERIFY(!action->isVisible());
+
+ delete action;
+ }
+ {
+ QPointer<QComboBox> combo = new QComboBox(0);
+ combo->show();
+
+ QWidgetAction *action = new QWidgetAction(0);
+ action->setDefaultWidget(combo);
+
+ QVERIFY(action->isVisible());
+ QVERIFY(!combo->isVisible());
+
+ delete action;
+ }
+ {
+ QToolBar tb1;
+ tb1.show();
+ QToolBar tb2;
+ tb2.show();
+
+ QPointer<QComboBox> combo = new QComboBox(0);
+
+ QWidgetAction *action = new QWidgetAction(0);
+ action->setDefaultWidget(combo);
+
+ tb1.addAction(action);
+ QVERIFY(combo->parent() == &tb1);
+ qApp->processEvents();
+ qApp->processEvents();
+ QVERIFY(combo->isVisible());
+
+ // not supported, not supposed to work, hence the parent() check
+ tb2.addAction(action);
+ QVERIFY(combo->parent() == &tb1);
+
+ tb2.removeAction(action);
+ tb1.removeAction(action);
+
+ qApp->processEvents(); //the call to hide is delayd by the toolbar layout
+ QVERIFY(!combo->isVisible());
+
+ tb2.addAction(action);
+ qApp->processEvents(); //the call to hide is delayd by the toolbar layout
+ qApp->processEvents();
+ QVERIFY(combo->parent() == &tb2);
+ QVERIFY(combo->isVisible());
+
+ tb1.addAction(action);
+ QVERIFY(combo->parent() == &tb2);
+
+ delete action;
+ QVERIFY(!combo);
+ }
+ {
+ QWidgetAction *a = new QWidgetAction(0);
+ QVERIFY(!a->defaultWidget());
+
+ QPointer<QComboBox> combo1 = new QComboBox;
+ a->setDefaultWidget(combo1);
+ QVERIFY(a->defaultWidget() == combo1);
+ a->setDefaultWidget(combo1);
+ QVERIFY(combo1);
+ QVERIFY(a->defaultWidget() == combo1);
+
+ QPointer<QComboBox> combo2 = new QComboBox;
+ QVERIFY(combo1 != combo2);
+
+ a->setDefaultWidget(combo2);
+ QVERIFY(!combo1);
+ QVERIFY(a->defaultWidget() == combo2);
+
+ delete a;
+ QVERIFY(!combo2);
+ }
+}
+
+void tst_QWidgetAction::visibilityUpdate()
+{
+ // actually keeping the widget's state in sync with the
+ // action in terms of visibility is QToolBar's responsibility.
+ QToolBar tb;
+ tb.show();
+
+ QComboBox *combo = new QComboBox(0);
+ QWidgetAction *action = new QWidgetAction(0);
+ action->setDefaultWidget(combo);
+
+ tb.addAction(action);
+ //the call to show is delayed by the toolbar layout
+ QTRY_VERIFY(combo->isVisible());
+ QVERIFY(action->isVisible());
+
+ action->setVisible(false);
+ //the call to hide is delayed by the toolbar layout
+ QTRY_VERIFY(!combo->isVisible());
+
+ delete action;
+ // action also deletes combo
+}
+
+class ComboAction : public QWidgetAction
+{
+public:
+ inline ComboAction(QObject *parent) : QWidgetAction(parent) {}
+
+ QList<QWidget *> createdWidgets() const { return QWidgetAction::createdWidgets(); }
+
+protected:
+ virtual QWidget *createWidget(QWidget *parent);
+};
+
+QWidget *ComboAction::createWidget(QWidget *parent)
+{
+ return new QComboBox(parent);
+}
+
+void tst_QWidgetAction::customWidget()
+{
+ QToolBar tb1;
+ tb1.show();
+ QToolBar tb2;
+ tb2.show();
+
+ ComboAction *action = new ComboAction(0);
+
+ tb1.addAction(action);
+
+ QList<QWidget *> combos = action->createdWidgets();
+ QCOMPARE(combos.count(), 1);
+
+ QPointer<QComboBox> combo1 = qobject_cast<QComboBox *>(combos.at(0));
+ QVERIFY(combo1);
+
+ tb2.addAction(action);
+
+ combos = action->createdWidgets();
+ QCOMPARE(combos.count(), 2);
+
+ QVERIFY(combos.at(0) == combo1);
+ QPointer<QComboBox> combo2 = qobject_cast<QComboBox *>(combos.at(1));
+ QVERIFY(combo2);
+
+ tb2.removeAction(action);
+ QVERIFY(combo2);
+ // widget is deleted using deleteLater(), so process that posted event
+ QCoreApplication::sendPostedEvents(combo2, QEvent::DeferredDelete);
+ QVERIFY(!combo2);
+
+ delete action;
+ QVERIFY(!combo1);
+ QVERIFY(!combo2);
+}
+
+void tst_QWidgetAction::keepOwnership()
+{
+ QPointer<QComboBox> combo = new QComboBox;
+ QWidgetAction *action = new QWidgetAction(0);
+ action->setDefaultWidget(combo);
+
+ {
+ QToolBar *tb = new QToolBar;
+ tb->addAction(action);
+ QVERIFY(combo->parent() == tb);
+ delete tb;
+ }
+
+ QVERIFY(combo);
+ delete action;
+ QVERIFY(!combo);
+}
+
+void tst_QWidgetAction::visibility()
+{
+ {
+ QWidgetAction *a = new QWidgetAction(0);
+ QComboBox *combo = new QComboBox;
+ a->setDefaultWidget(combo);
+
+ QToolBar *tb = new QToolBar;
+ tb->addAction(a);
+ QVERIFY(!combo->isVisible());
+ tb->show();
+ QVERIFY(combo->isVisible());
+
+ delete tb;
+
+ delete a;
+ }
+ {
+ QWidgetAction *a = new QWidgetAction(0);
+ QComboBox *combo = new QComboBox;
+ a->setDefaultWidget(combo);
+
+ QToolBar *tb = new QToolBar;
+ tb->addAction(a);
+ QVERIFY(!combo->isVisible());
+
+ QToolBar *tb2 = new QToolBar;
+ tb->removeAction(a);
+ tb2->addAction(a);
+ QVERIFY(!combo->isVisible());
+ tb2->show();
+ QVERIFY(combo->isVisible());
+
+ delete tb;
+ delete tb2;
+
+ delete a;
+ }
+}
+
+void tst_QWidgetAction::setEnabled()
+{
+ QToolBar toolbar;
+ QComboBox *combobox = new QComboBox;
+ QAction *action = toolbar.addWidget(combobox);
+ toolbar.show();
+
+ QVERIFY(action->isEnabled());
+ QVERIFY(combobox->isEnabled());
+
+ action->setEnabled(false);
+ QVERIFY(!action->isEnabled());
+ QVERIFY(!combobox->isEnabled());
+
+ action->setEnabled(true);
+ QVERIFY(action->isEnabled());
+ QVERIFY(combobox->isEnabled());
+
+ combobox->setEnabled(false);
+ QVERIFY(!combobox->isEnabled());
+
+ combobox->setEnabled(true);
+ QVERIFY(action->isEnabled());
+ QVERIFY(combobox->isEnabled());
+
+
+ QWidgetAction aw(0);
+ aw.setEnabled(false);
+ QVERIFY(!aw.isEnabled());
+
+ combobox = new QComboBox;
+ aw.setDefaultWidget(combobox);
+ QVERIFY(!aw.isEnabled());
+ QVERIFY(!combobox->isEnabled());
+
+ // Make sure we don't change the default widget's Qt::WA_ForceDisabled attribute
+ // during a normal disable/enable operation (task 207433).
+ {
+ QToolBar toolBar;
+ QWidget widget;
+ toolBar.addWidget(&widget); // creates a QWidgetAction and sets 'widget' as the default widget.
+ QVERIFY(!widget.testAttribute(Qt::WA_ForceDisabled));
+
+ toolBar.setEnabled(false);
+ QVERIFY(toolBar.testAttribute(Qt::WA_ForceDisabled));
+ QVERIFY(!widget.isEnabled());
+ QVERIFY(!widget.testAttribute(Qt::WA_ForceDisabled));
+
+ toolBar.setEnabled(true);
+ QVERIFY(widget.isEnabled());
+ QVERIFY(!widget.testAttribute(Qt::WA_ForceDisabled));
+ }
+}
+
+void tst_QWidgetAction::popup()
+{
+ QPointer<QLabel> l = new QLabel("test");
+ QWidgetAction action(0);
+ action.setDefaultWidget(l);
+
+ {
+ QMenu menu;
+ menu.addAction(&action);
+ QTimer::singleShot(0, &menu, SLOT(close()));
+ menu.exec();
+ }
+
+ QVERIFY(!l.isNull());
+ delete l;
+}
+
+class CrashedAction : public QWidgetAction
+{
+public:
+ inline CrashedAction(QObject *parent) : QWidgetAction(parent) { }
+
+ virtual QWidget *createWidget(QWidget *parent) {
+ return new QWidget(parent);
+ }
+};
+
+void tst_QWidgetAction::releaseWidgetCrash()
+{
+ // this should not crash!
+ QMainWindow *w = new QMainWindow;
+ QAction *a = new CrashedAction(w);
+ QMenu *menu = w->menuBar()->addMenu("Test");
+ menu->addAction("foo");
+ menu->addAction(a);
+ menu->addAction("bar");
+ delete w;
+}
+
+QTEST_MAIN(tst_QWidgetAction)
+#include "tst_qwidgetaction.moc"