summaryrefslogtreecommitdiffstats
path: root/tests/auto/qmdiarea/tst_qmdiarea.cpp
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit38be0d13830efd2d98281c645c3a60afe05ffece (patch)
tree6ea73f3ec77f7d153333779883e8120f82820abe /tests/auto/qmdiarea/tst_qmdiarea.cpp
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'tests/auto/qmdiarea/tst_qmdiarea.cpp')
-rw-r--r--tests/auto/qmdiarea/tst_qmdiarea.cpp2774
1 files changed, 2774 insertions, 0 deletions
diff --git a/tests/auto/qmdiarea/tst_qmdiarea.cpp b/tests/auto/qmdiarea/tst_qmdiarea.cpp
new file mode 100644
index 0000000000..67d3d0d1fc
--- /dev/null
+++ b/tests/auto/qmdiarea/tst_qmdiarea.cpp
@@ -0,0 +1,2774 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <QMdiSubWindow>
+#include <QMdiArea>
+
+#include <QApplication>
+#include <QMainWindow>
+#include <QMenuBar>
+#include <QPushButton>
+#include <QStyle>
+#include <QStyleOption>
+#include <QVBoxLayout>
+#include <QLineEdit>
+#include <QDesktopWidget>
+#include <QDockWidget>
+#include <QScrollBar>
+#include <QTextEdit>
+#ifndef QT_NO_OPENGL
+#include <QtOpenGL>
+#endif
+#include <QMacStyle>
+
+#include "../../shared/util.h"
+#include "../platformquirks.h"
+
+static const Qt::WindowFlags DefaultWindowFlags
+ = Qt::SubWindow | Qt::WindowSystemMenuHint
+ | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint;
+
+Q_DECLARE_METATYPE(QMdiArea::WindowOrder)
+Q_DECLARE_METATYPE(QMdiSubWindow *)
+Q_DECLARE_METATYPE(QList<int>)
+Q_DECLARE_METATYPE(QTabWidget::TabPosition)
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+static bool tabBetweenSubWindowsIn(QMdiArea *mdiArea, int tabCount = -1, bool reverse = false)
+{
+ if (!mdiArea) {
+ qWarning("Null pointer to mdi area");
+ return false;
+ }
+
+ QList<QMdiSubWindow *> subWindows = mdiArea->subWindowList();
+ const bool walkThrough = tabCount == -1;
+
+ if (walkThrough) {
+ QMdiSubWindow *active = reverse ? subWindows.front() : subWindows.back();
+ mdiArea->setActiveSubWindow(active);
+ if (mdiArea->activeSubWindow() != active) {
+ qWarning("Failed to set active sub window");
+ return false;
+ }
+ tabCount = subWindows.size();
+ }
+
+ QWidget *focusWidget = qApp->focusWidget();
+ if (!focusWidget) {
+ qWarning("No focus widget");
+ return false;
+ }
+
+ Qt::KeyboardModifiers modifiers = reverse ? Qt::ShiftModifier : Qt::NoModifier;
+ Qt::Key key;
+#ifdef Q_WS_MAC
+ key = Qt::Key_Meta;
+ modifiers |= Qt::MetaModifier;
+#else
+ key = Qt::Key_Control;
+ modifiers |= Qt::ControlModifier;
+#endif
+
+ QTest::keyPress(focusWidget, key, modifiers);
+ for (int i = 0; i < tabCount; ++i) {
+ QTest::keyPress(focusWidget, reverse ? Qt::Key_Backtab : Qt::Key_Tab, modifiers);
+ if (tabCount > 1)
+ QTest::qWait(500);
+ if (walkThrough) {
+ QRubberBand *rubberBand = qFindChild<QRubberBand *>(mdiArea->viewport());
+ if (!rubberBand) {
+ qWarning("No rubber band");
+ return false;
+ }
+ QMdiSubWindow *subWindow = subWindows.at(reverse ? subWindows.size() -1 - i : i);
+ if (rubberBand->geometry() != subWindow->geometry()) {
+ qWarning("Rubber band has different geometry");
+ return false;
+ }
+ }
+ qApp->processEvents();
+ }
+ QTest::keyRelease(focusWidget, key);
+
+ return true;
+}
+
+static inline QTabBar::Shape tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position)
+{
+ const bool rounded = (shape == QTabWidget::Rounded);
+ if (position == QTabWidget::North)
+ return rounded ? QTabBar::RoundedNorth : QTabBar::TriangularNorth;
+ if (position == QTabWidget::South)
+ return rounded ? QTabBar::RoundedSouth : QTabBar::TriangularSouth;
+ if (position == QTabWidget::East)
+ return rounded ? QTabBar::RoundedEast : QTabBar::TriangularEast;
+ if (position == QTabWidget::West)
+ return rounded ? QTabBar::RoundedWest : QTabBar::TriangularWest;
+ return QTabBar::RoundedNorth;
+}
+
+enum Arrangement {
+ Tiled,
+ Cascaded
+};
+
+static bool verifyArrangement(QMdiArea *mdiArea, Arrangement arrangement, const QList<int> &expectedIndices)
+{
+ if (!mdiArea || expectedIndices.isEmpty() || mdiArea->subWindowList().isEmpty())
+ return false;
+
+ const QList<QMdiSubWindow *> subWindows = mdiArea->subWindowList();
+ const QMdiSubWindow *const firstSubWindow = subWindows.at(0);
+
+ switch (arrangement) {
+ case Tiled:
+ {
+ // Calculate the number of rows and columns.
+ const int n = subWindows.count();
+ const int numColumns = qMax(qCeil(qSqrt(qreal(n))), 1);
+ const int numRows = qMax((n % numColumns) ? (n / numColumns + 1) : (n / numColumns), 1);
+
+ // Ensure that the geometry of all the subwindows are as expected by using
+ // QWidget::childAt starting from the middle of the topleft cell and subsequently
+ // adding rowWidth and rowHeight (going from left to right).
+ const int columnWidth = mdiArea->viewport()->width() / numColumns;
+ const int rowHeight = mdiArea->viewport()->height() / numRows;
+ QPoint subWindowPos(columnWidth / 2, rowHeight / 2);
+ for (int i = 0; i < numRows; ++i) {
+ for (int j = 0; j < numColumns; ++j) {
+ const int index = expectedIndices.at(i * numColumns + j);
+ QWidget *actual = mdiArea->viewport()->childAt(subWindowPos);
+ QMdiSubWindow *expected = subWindows.at(index);
+ if (actual != expected && !expected->isAncestorOf(actual))
+ return false;
+ subWindowPos.rx() += columnWidth;
+ }
+ subWindowPos.rx() = columnWidth / 2;
+ subWindowPos.ry() += rowHeight;
+ }
+ break;
+ }
+ case Cascaded:
+ {
+ // Calculate the delta (dx, dy) between two cascaded subwindows.
+ QStyleOptionTitleBar options;
+ options.initFrom(firstSubWindow);
+ int titleBarHeight = firstSubWindow->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
+#ifdef Q_WS_MAC
+ // ### Remove this after the mac style has been fixed
+ if (qobject_cast<QMacStyle *>(firstSubWindow->style()))
+ titleBarHeight -= 4;
+#endif
+ const QFontMetrics fontMetrics = QFontMetrics(QApplication::font("QWorkspaceTitleBar"));
+ const int dy = qMax(titleBarHeight - (titleBarHeight - fontMetrics.height()) / 2, 1);
+ const int dx = 10;
+
+ // Current activation/stacking order.
+ const QList<QMdiSubWindow *> activationOrderList = mdiArea->subWindowList(QMdiArea::ActivationHistoryOrder);
+
+ // Ensure that the geometry of all the subwindows are as expected by using
+ // QWidget::childAt with the position of the first one and subsequently adding
+ // dx and dy.
+ QPoint subWindowPos(20, 5);
+ foreach (int expectedIndex, expectedIndices) {
+ QMdiSubWindow *expected = subWindows.at(expectedIndex);
+ expected->raise();
+ if (mdiArea->viewport()->childAt(subWindowPos) != expected)
+ return false;
+ expected->lower();
+ subWindowPos.rx() += dx;
+ subWindowPos.ry() += dy;
+ }
+
+ // Restore stacking order.
+ foreach (QMdiSubWindow *subWindow, activationOrderList) {
+ mdiArea->setActiveSubWindow(subWindow);
+ qApp->processEvents();
+ }
+ break;
+ }
+ default:
+ return false;
+ }
+ return true;
+}
+
+class tst_QMdiArea : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QMdiArea();
+public slots:
+ void initTestCase();
+protected slots:
+ void activeChanged(QMdiSubWindow *child);
+
+private slots:
+ // Tests from QWorkspace
+ void subWindowActivated_data();
+ void subWindowActivated();
+ void subWindowActivated2();
+ void subWindowActivatedWithMinimize();
+ void showWindows();
+ void changeWindowTitle();
+ void changeModified();
+ void childSize();
+ void fixedSize();
+ // New tests
+ void minimumSizeHint();
+ void sizeHint();
+ void setActiveSubWindow();
+ void activeSubWindow();
+ void currentSubWindow();
+ void addAndRemoveWindows();
+ void addAndRemoveWindowsWithReparenting();
+ void removeSubWindow_2();
+ void closeWindows();
+ void activateNextAndPreviousWindow();
+ void subWindowList_data();
+ void subWindowList();
+ void setBackground();
+ void setViewport();
+ void tileSubWindows();
+ void cascadeAndTileSubWindows();
+ void resizeMaximizedChildWindows_data();
+ void resizeMaximizedChildWindows();
+ void focusWidgetAfterAddSubWindow();
+ void dontMaximizeSubWindowOnActivation();
+ void delayedPlacement();
+ void iconGeometryInMenuBar();
+ void resizeTimer();
+ void updateScrollBars();
+ void setActivationOrder_data();
+ void setActivationOrder();
+ void tabBetweenSubWindows();
+ void setViewMode();
+ void setTabsClosable();
+ void setTabsMovable();
+ void setTabShape();
+ void setTabPosition_data();
+ void setTabPosition();
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+ void nativeSubWindows();
+#endif
+ void task_209615();
+ void task_236750();
+
+private:
+ QMdiSubWindow *activeWindow;
+ bool accelPressed;
+};
+
+tst_QMdiArea::tst_QMdiArea()
+ : activeWindow(0)
+{
+ qRegisterMetaType<QMdiSubWindow *>();
+}
+
+void tst_QMdiArea::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+// Old QWorkspace tests
+void tst_QMdiArea::activeChanged(QMdiSubWindow *child)
+{
+ activeWindow = child;
+}
+
+void tst_QMdiArea::subWindowActivated_data()
+{
+ // define the test elements we're going to use
+ QTest::addColumn<int>("count");
+
+ // create a first testdata instance and fill it with data
+ QTest::newRow( "data0" ) << 0;
+ QTest::newRow( "data1" ) << 1;
+ QTest::newRow( "data2" ) << 2;
+}
+
+void tst_QMdiArea::subWindowActivated()
+{
+ QMainWindow mw(0) ;
+ mw.menuBar();
+ QMdiArea *workspace = new QMdiArea(&mw);
+ workspace->setObjectName(QLatin1String("testWidget"));
+ mw.setCentralWidget(workspace);
+ QSignalSpy spy(workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+ connect( workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
+ mw.show();
+ qApp->setActiveWindow(&mw);
+
+ QFETCH( int, count );
+ int i;
+
+ for ( i = 0; i < count; ++i ) {
+ QWidget *widget = new QWidget(workspace, 0);
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ workspace->addSubWindow(widget)->show();
+ widget->show();
+ qApp->processEvents();
+ QVERIFY( activeWindow == workspace->activeSubWindow() );
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ }
+
+ QList<QMdiSubWindow *> windows = workspace->subWindowList();
+ QCOMPARE( (int)windows.count(), count );
+
+ for ( i = 0; i < count; ++i ) {
+ QMdiSubWindow *window = windows.at(i);
+ window->showMinimized();
+ qApp->processEvents();
+ QVERIFY( activeWindow == workspace->activeSubWindow() );
+ if ( i == 1 )
+ QVERIFY( activeWindow == window );
+ }
+
+ for ( i = 0; i < count; ++i ) {
+ QMdiSubWindow *window = windows.at(i);
+ window->showNormal();
+ qApp->processEvents();
+ QVERIFY( window == activeWindow );
+ QVERIFY( activeWindow == workspace->activeSubWindow() );
+ }
+ spy.clear();
+
+ while (workspace->activeSubWindow() ) {
+ workspace->activeSubWindow()->close();
+ qApp->processEvents();
+ QVERIFY(activeWindow == workspace->activeSubWindow());
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ }
+
+ QVERIFY(activeWindow == 0);
+ QVERIFY(workspace->activeSubWindow() == 0);
+ QCOMPARE(workspace->subWindowList().count(), 0);
+
+ {
+ workspace->hide();
+ QWidget *widget = new QWidget(workspace);
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ QMdiSubWindow *window = workspace->addSubWindow(widget);
+ widget->show();
+ QCOMPARE(spy.count(), 0);
+ workspace->show();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWindow == window );
+ window->close();
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWindow == 0 );
+ }
+
+ {
+ workspace->hide();
+ QWidget *widget = new QWidget(workspace);
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ QMdiSubWindow *window = workspace->addSubWindow(widget);
+ widget->showMaximized();
+ qApp->sendPostedEvents();
+ QCOMPARE(spy.count(), 0);
+ spy.clear();
+ workspace->show();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWindow == window );
+ window->close();
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWindow == 0 );
+ }
+
+ {
+ QWidget *widget = new QWidget(workspace);
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ QMdiSubWindow *window = workspace->addSubWindow(widget);
+ widget->showMinimized();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY( activeWindow == window );
+ QVERIFY(workspace->activeSubWindow() == window);
+ window->close();
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ QVERIFY(workspace->activeSubWindow() == 0);
+ QVERIFY( activeWindow == 0 );
+ }
+}
+
+#ifdef Q_WS_MAC
+#include <Security/AuthSession.h>
+bool macHasAccessToWindowsServer()
+{
+ SecuritySessionId mySession;
+ SessionAttributeBits sessionInfo;
+ SessionGetInfo(callerSecuritySession, &mySession, &sessionInfo);
+ return (sessionInfo & sessionHasGraphicAccess);
+}
+#endif
+
+
+void tst_QMdiArea::subWindowActivated2()
+{
+ QMdiArea mdiArea;
+ QSignalSpy spy(&mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+ for (int i = 0; i < 5; ++i)
+ mdiArea.addSubWindow(new QWidget);
+ QCOMPARE(spy.count(), 0);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ QTest::qWaitForWindowShown(&mdiArea);
+ mdiArea.activateWindow();
+ QTest::qWait(100);
+
+ QTRY_COMPARE(spy.count(), 5);
+ QCOMPARE(mdiArea.activeSubWindow(), mdiArea.subWindowList().back());
+ spy.clear();
+
+ // Just to make sure another widget is on top wrt. stacking order.
+ // This will typically become the active window if things are broken.
+ QMdiSubWindow *staysOnTopWindow = mdiArea.subWindowList().at(3);
+ staysOnTopWindow->setWindowFlags(Qt::WindowStaysOnTopHint);
+ mdiArea.setActiveSubWindow(staysOnTopWindow);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(mdiArea.activeSubWindow(), staysOnTopWindow);
+ spy.clear();
+
+ QMdiSubWindow *activeSubWindow = mdiArea.subWindowList().at(2);
+ mdiArea.setActiveSubWindow(activeSubWindow);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow);
+ spy.clear();
+
+ // Check that we only emit _one_ signal and the active window
+ // is unchanged after hide/show.
+ mdiArea.hide();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ QTest::qWait(100);
+ QTRY_COMPARE(spy.count(), 1);
+ QVERIFY(!mdiArea.activeSubWindow());
+ QCOMPARE(mdiArea.currentSubWindow(), activeSubWindow);
+ spy.clear();
+
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ QTest::qWait(100);
+ QTRY_COMPARE(spy.count(), 1);
+ QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow);
+ spy.clear();
+
+ if (PlatformQuirks::isAutoMaximizing())
+ QSKIP("Platform is auto maximizing, so no showMinimized()", SkipAll);
+
+ // Check that we only emit _one_ signal and the active window
+ // is unchanged after showMinimized/showNormal.
+ mdiArea.showMinimized();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#elif defined (Q_WS_MAC)
+ if (!macHasAccessToWindowsServer())
+ QEXPECT_FAIL("", "showMinimized doesn't really minimize if you don't have access to the server", Abort);
+#endif
+ QTest::qWait(10);
+#if defined(Q_WS_QWS)
+ QEXPECT_FAIL("", "task 168682", Abort);
+#endif
+#ifdef Q_OS_WINCE
+ QSKIP("Not fixed yet. See Task 197453", SkipAll);
+#endif
+ QTRY_COMPARE(spy.count(), 1);
+ QVERIFY(!mdiArea.activeSubWindow());
+ QCOMPARE(mdiArea.currentSubWindow(), activeSubWindow);
+ spy.clear();
+
+ mdiArea.showNormal();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ QTest::qWait(100);
+ QTRY_COMPARE(spy.count(), 1);
+ QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow);
+ spy.clear();
+}
+
+void tst_QMdiArea::subWindowActivatedWithMinimize()
+{
+ QMainWindow mw(0) ;
+ mw.menuBar();
+ QMdiArea *workspace = new QMdiArea(&mw);
+ workspace->setObjectName(QLatin1String("testWidget"));
+ mw.setCentralWidget(workspace);
+ QSignalSpy spy(workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+ connect( workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)) );
+ mw.show();
+ qApp->setActiveWindow(&mw);
+ QWidget *widget = new QWidget(workspace);
+ widget->setAttribute(Qt::WA_DeleteOnClose);
+ QMdiSubWindow *window1 = workspace->addSubWindow(widget);
+ QWidget *widget2 = new QWidget(workspace);
+ widget2->setAttribute(Qt::WA_DeleteOnClose);
+ QMdiSubWindow *window2 = workspace->addSubWindow(widget2);
+
+ widget->showMinimized();
+ QVERIFY( activeWindow == window1 );
+ widget2->showMinimized();
+ QVERIFY( activeWindow == window2 );
+
+ window2->close();
+ qApp->processEvents();
+ QVERIFY( activeWindow == window1 );
+
+ window1->close();
+ qApp->processEvents();
+ QVERIFY(workspace->activeSubWindow() == 0);
+ QVERIFY( activeWindow == 0 );
+
+ QVERIFY( workspace->subWindowList().count() == 0 );
+}
+
+void tst_QMdiArea::showWindows()
+{
+ QMdiArea *ws = new QMdiArea( 0 );
+
+ QWidget *widget = 0;
+ ws->show();
+
+ widget = new QWidget(ws);
+ widget->show();
+ QVERIFY( widget->isVisible() );
+
+ widget = new QWidget(ws);
+ widget->showMaximized();
+ QVERIFY( widget->isMaximized() );
+ widget->showNormal();
+ QVERIFY( !widget->isMaximized() );
+
+ widget = new QWidget(ws);
+ widget->showMinimized();
+ QVERIFY( widget->isMinimized() );
+ widget->showNormal();
+ QVERIFY( !widget->isMinimized() );
+
+ ws->hide();
+
+ widget = new QWidget(ws);
+ ws->show();
+ QVERIFY( widget->isVisible() );
+
+ ws->hide();
+
+ widget = new QWidget(ws);
+ widget->showMaximized();
+ QVERIFY( widget->isMaximized() );
+ ws->show();
+ QVERIFY( widget->isVisible() );
+ QVERIFY( widget->isMaximized() );
+ ws->hide();
+
+ widget = new QWidget(ws);
+ widget->showMinimized();
+ ws->show();
+ QVERIFY( widget->isMinimized() );
+ ws->hide();
+
+ delete ws;
+}
+
+
+//#define USE_SHOW
+
+void tst_QMdiArea::changeWindowTitle()
+{
+ const QString mwc = QString::fromLatin1("MainWindow's Caption");
+ const QString mwc2 = QString::fromLatin1("MainWindow's New Caption");
+ const QString wc = QString::fromLatin1("Widget's Caption");
+ const QString wc2 = QString::fromLatin1("Widget's New Caption");
+
+ QMainWindow *mw = new QMainWindow;
+ mw->setWindowTitle( mwc );
+ QMdiArea *ws = new QMdiArea( mw );
+ mw->setCentralWidget( ws );
+ mw->menuBar();
+ mw->show();
+ QTest::qWaitForWindowShown(mw);
+
+ QWidget *widget = new QWidget( ws );
+ widget->setWindowTitle( wc );
+ ws->addSubWindow(widget);
+
+ QCOMPARE( mw->windowTitle(), mwc );
+
+#ifdef USE_SHOW
+ widget->showMaximized();
+#else
+ widget->setWindowState(Qt::WindowMaximized);
+#endif
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QTRY_COMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc) );
+#endif
+
+ mw->hide();
+ qApp->processEvents();
+ mw->show();
+ qApp->processEvents();
+ QTest::qWaitForWindowShown(mw);
+
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QTRY_COMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc) );
+#endif
+
+#ifdef USE_SHOW
+ widget->showNormal();
+#else
+ widget->setWindowState(Qt::WindowNoState);
+#endif
+ qApp->processEvents();
+ QCOMPARE( mw->windowTitle(), mwc );
+
+#ifdef USE_SHOW
+ widget->showMaximized();
+#else
+ widget->setWindowState(Qt::WindowMaximized);
+#endif
+ qApp->processEvents();
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QTRY_COMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc) );
+ widget->setWindowTitle( wc2 );
+ QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc2) );
+ mw->setWindowTitle( mwc2 );
+ QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc2).arg(wc2) );
+#endif
+
+ mw->show();
+ qApp->setActiveWindow(mw);
+
+#ifdef USE_SHOW
+ mw->showFullScreen();
+#else
+ mw->setWindowState(Qt::WindowFullScreen);
+#endif
+
+ qApp->processEvents();
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc2).arg(wc2) );
+#endif
+#ifdef USE_SHOW
+ widget->showNormal();
+#else
+ widget->setWindowState(Qt::WindowNoState);
+#endif
+ qApp->processEvents();
+#if defined(Q_WS_MAC) || defined(Q_OS_WINCE)
+ QCOMPARE(mw->windowTitle(), mwc);
+#else
+ QCOMPARE( mw->windowTitle(), mwc2 );
+#endif
+
+#ifdef USE_SHOW
+ widget->showMaximized();
+#else
+ widget->setWindowState(Qt::WindowMaximized);
+#endif
+ qApp->processEvents();
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc2).arg(wc2) );
+#endif
+
+#ifdef USE_SHOW
+ mw->showNormal();
+#else
+ mw->setWindowState(Qt::WindowNoState);
+#endif
+ qApp->processEvents();
+#ifdef USE_SHOW
+ widget->showNormal();
+#else
+ widget->setWindowState(Qt::WindowNoState);
+#endif
+
+ delete mw;
+}
+
+void tst_QMdiArea::changeModified()
+{
+ const QString mwc = QString::fromLatin1("MainWindow's Caption");
+ const QString wc = QString::fromLatin1("Widget's Caption[*]");
+
+ QMainWindow *mw = new QMainWindow(0);
+ mw->setWindowTitle( mwc );
+ QMdiArea *ws = new QMdiArea( mw );
+ mw->setCentralWidget( ws );
+ mw->menuBar();
+ mw->show();
+
+ QWidget *widget = new QWidget( ws );
+ widget->setWindowTitle( wc );
+ ws->addSubWindow(widget);
+
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), false);
+ widget->setWindowState(Qt::WindowMaximized);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), false);
+
+ widget->setWindowState(Qt::WindowNoState);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), false);
+
+ widget->setWindowModified(true);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), true);
+ widget->setWindowState(Qt::WindowMaximized);
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QCOMPARE( mw->isWindowModified(), true);
+#endif
+ QCOMPARE( widget->isWindowModified(), true);
+
+ widget->setWindowState(Qt::WindowNoState);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), true);
+
+ widget->setWindowState(Qt::WindowMaximized);
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QCOMPARE( mw->isWindowModified(), true);
+#endif
+ QCOMPARE( widget->isWindowModified(), true);
+
+ widget->setWindowModified(false);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), false);
+
+ widget->setWindowModified(true);
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QCOMPARE( mw->isWindowModified(), true);
+#endif
+ QCOMPARE( widget->isWindowModified(), true);
+
+ widget->setWindowState(Qt::WindowNoState);
+ QCOMPARE( mw->isWindowModified(), false);
+ QCOMPARE( widget->isWindowModified(), true);
+
+ delete mw;
+}
+
+class MyChild : public QWidget
+{
+public:
+ MyChild(QWidget *parent = 0) : QWidget(parent) {}
+ QSize sizeHint() const { return QSize(234, 123); }
+};
+
+void tst_QMdiArea::childSize()
+{
+ QMdiArea ws;
+
+ MyChild *child = new MyChild(&ws);
+ child->show();
+ QCOMPARE(child->size(), child->sizeHint());
+ delete child;
+
+ child = new MyChild(&ws);
+ child->setFixedSize(200, 200);
+ child->show();
+ QCOMPARE(child->size(), child->minimumSize());
+ delete child;
+
+ child = new MyChild(&ws);
+ child->resize(150, 150);
+ child->show();
+ QCOMPARE(child->size(), QSize(150,150));
+ delete child;
+}
+
+void tst_QMdiArea::fixedSize()
+{
+ QMdiArea *ws = new QMdiArea;
+ int i;
+
+ ws->resize(500, 500);
+// ws->show();
+
+ QSize fixed(300, 300);
+ for (i = 0; i < 4; ++i) {
+ QWidget *child = new QWidget(ws);
+ child->setFixedSize(fixed);
+ child->show();
+ }
+
+ QList<QMdiSubWindow *> windows = ws->subWindowList();
+ for (i = 0; i < (int)windows.count(); ++i) {
+ QMdiSubWindow *child = windows.at(i);
+ QCOMPARE(child->size(), fixed);
+ }
+
+ ws->cascadeSubWindows();
+ ws->resize(800, 800);
+ for (i = 0; i < (int)windows.count(); ++i) {
+ QMdiSubWindow *child = windows.at(i);
+ QCOMPARE(child->size(), fixed);
+ }
+ ws->resize(500, 500);
+
+ ws->tileSubWindows();
+ ws->resize(800, 800);
+ for (i = 0; i < (int)windows.count(); ++i) {
+ QMdiSubWindow *child = windows.at(i);
+ QCOMPARE(child->size(), fixed);
+ }
+ ws->resize(500, 500);
+
+ for (i = 0; i < (int)windows.count(); ++i) {
+ QMdiSubWindow *child = windows.at(i);
+ delete child;
+ }
+
+ delete ws;
+}
+
+class LargeWidget : public QWidget
+{
+public:
+ LargeWidget(QWidget *parent = 0) : QWidget(parent) {}
+ QSize sizeHint() const { return QSize(1280, 1024); }
+ QSize minimumSizeHint() const { return QSize(300, 300); }
+};
+
+// New tests
+void tst_QMdiArea::minimumSizeHint()
+{
+ QMdiArea workspace;
+ workspace.show();
+ QSize expectedSize(workspace.style()->pixelMetric(QStyle::PM_MDIMinimizedWidth),
+ workspace.style()->pixelMetric(QStyle::PM_TitleBarHeight));
+ qApp->processEvents();
+ QAbstractScrollArea dummyScrollArea;
+ dummyScrollArea.setFrameStyle(QFrame::NoFrame);
+ expectedSize = expectedSize.expandedTo(dummyScrollArea.minimumSizeHint());
+ QCOMPARE(workspace.minimumSizeHint(), expectedSize.expandedTo(qApp->globalStrut()));
+
+ QWidget *window = workspace.addSubWindow(new QWidget);
+ qApp->processEvents();
+ window->show();
+ QCOMPARE(workspace.minimumSizeHint(), expectedSize.expandedTo(window->minimumSizeHint()));
+
+ QMdiSubWindow *subWindow = workspace.addSubWindow(new LargeWidget);
+ subWindow->show();
+ QCOMPARE(workspace.minimumSizeHint(), expectedSize.expandedTo(subWindow->minimumSizeHint()));
+
+ workspace.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ workspace.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ QCOMPARE(workspace.minimumSizeHint(), expectedSize);
+}
+
+void tst_QMdiArea::sizeHint()
+{
+ QMdiArea workspace;
+ workspace.show();
+ QSize desktopSize = QApplication::desktop()->size();
+ QSize expectedSize(desktopSize.width() * 2/3, desktopSize.height() * 2/3);
+ QCOMPARE(workspace.sizeHint(), expectedSize.expandedTo(qApp->globalStrut()));
+
+ QWidget *window = workspace.addSubWindow(new QWidget);
+ qApp->processEvents();
+ window->show();
+ QCOMPARE(workspace.sizeHint(), expectedSize.expandedTo(window->sizeHint()));
+
+ QMdiSubWindow *nested = workspace.addSubWindow(new QMdiArea);
+ expectedSize = QSize(desktopSize.width() * 2/6, desktopSize.height() * 2/6);
+ QCOMPARE(nested->widget()->sizeHint(), expectedSize);
+}
+
+void tst_QMdiArea::setActiveSubWindow()
+{
+ QMdiArea workspace;
+ workspace.show();
+
+ QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+ connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
+ qApp->setActiveWindow(&workspace);
+
+ // Activate hidden windows
+ const int windowCount = 10;
+ QMdiSubWindow *windows[windowCount];
+ for (int i = 0; i < windowCount; ++i) {
+ windows[i] = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
+ qApp->processEvents();
+ QVERIFY(windows[i]->isHidden());
+ workspace.setActiveSubWindow(windows[i]);
+ }
+ QCOMPARE(spy.count(), 0);
+ QVERIFY(!activeWindow);
+ spy.clear();
+
+ // Activate visible windows
+ for (int i = 0; i < windowCount; ++i) {
+ windows[i]->show();
+ QVERIFY(!windows[i]->isHidden());
+ workspace.setActiveSubWindow(windows[i]);
+ qApp->processEvents();
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(activeWindow, windows[i]);
+ spy.clear();
+ }
+
+ // Deactivate active window
+ QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
+ workspace.setActiveSubWindow(0);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(!activeWindow);
+ QVERIFY(!workspace.activeSubWindow());
+
+ // Activate widget which is not child of any window inside workspace
+ QMdiSubWindow fakeWindow;
+ QTest::ignoreMessage(QtWarningMsg, "QMdiArea::setActiveSubWindow: window is not inside workspace");
+ workspace.setActiveSubWindow(&fakeWindow);
+
+}
+
+void tst_QMdiArea::activeSubWindow()
+{
+ QMainWindow mainWindow;
+
+ QMdiArea *mdiArea = new QMdiArea;
+ QLineEdit *subWindowLineEdit = new QLineEdit;
+ QMdiSubWindow *subWindow = mdiArea->addSubWindow(subWindowLineEdit);
+ mainWindow.setCentralWidget(mdiArea);
+
+ QDockWidget *dockWidget = new QDockWidget(QLatin1String("Dock Widget"), &mainWindow);
+ dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea);
+ QLineEdit *dockWidgetLineEdit = new QLineEdit;
+ dockWidget->setWidget(dockWidgetLineEdit);
+ mainWindow.addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
+
+ mainWindow.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mainWindow);
+#endif
+
+ qApp->setActiveWindow(&mainWindow);
+ QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+ QCOMPARE(qApp->focusWidget(), (QWidget *)subWindowLineEdit);
+
+ dockWidgetLineEdit->setFocus();
+ QCOMPARE(qApp->focusWidget(), (QWidget *)dockWidgetLineEdit);
+ QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+
+ QEvent deactivateEvent(QEvent::WindowDeactivate);
+ qApp->sendEvent(subWindow, &deactivateEvent);
+ QVERIFY(!mdiArea->activeSubWindow());
+ QCOMPARE(qApp->focusWidget(), (QWidget *)dockWidgetLineEdit);
+
+ QEvent activateEvent(QEvent::WindowActivate);
+ qApp->sendEvent(subWindow, &activateEvent);
+ QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+ QCOMPARE(qApp->focusWidget(), (QWidget *)subWindowLineEdit);
+
+ QLineEdit dummyTopLevel;
+ dummyTopLevel.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&dummyTopLevel);
+#endif
+
+ qApp->setActiveWindow(&dummyTopLevel);
+ QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+
+ qApp->setActiveWindow(&mainWindow);
+ QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+
+#if !defined(Q_WS_MAC) && !defined(Q_WS_WIN)
+ qApp->setActiveWindow(0);
+ QVERIFY(!mdiArea->activeSubWindow());
+#endif
+
+ //task 202657
+ dockWidgetLineEdit->setFocus();
+ qApp->setActiveWindow(&mainWindow);
+ QVERIFY(dockWidgetLineEdit->hasFocus());
+}
+
+void tst_QMdiArea::currentSubWindow()
+{
+ QMdiArea mdiArea;
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ for (int i = 0; i < 5; ++i)
+ mdiArea.addSubWindow(new QLineEdit)->show();
+
+ qApp->setActiveWindow(&mdiArea);
+ QCOMPARE(qApp->activeWindow(), (QWidget *)&mdiArea);
+
+ // Check that the last added window is the active and the current.
+ QMdiSubWindow *active = mdiArea.activeSubWindow();
+ QVERIFY(active);
+ QCOMPARE(mdiArea.subWindowList().back(), active);
+ QCOMPARE(mdiArea.currentSubWindow(), active);
+
+ QLineEdit dummyTopLevel;
+ dummyTopLevel.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&dummyTopLevel);
+#endif
+
+ // Move focus to another top-level and check that we still
+ // have an active window.
+ qApp->setActiveWindow(&dummyTopLevel);
+ QCOMPARE(qApp->activeWindow(), (QWidget *)&dummyTopLevel);
+ QVERIFY(mdiArea.activeSubWindow());
+
+ delete active;
+ active = 0;
+
+ // We just deleted the current sub-window -> current should then
+ // be the next in list (which in this case is the first sub-window).
+ QVERIFY(mdiArea.currentSubWindow());
+ QCOMPARE(mdiArea.currentSubWindow(), mdiArea.subWindowList().front());
+
+ // Activate mdi area and check that active == current.
+ qApp->setActiveWindow(&mdiArea);
+ active = mdiArea.activeSubWindow();
+ QVERIFY(active);
+ QCOMPARE(mdiArea.activeSubWindow(), mdiArea.subWindowList().front());
+
+ active->hide();
+ QCOMPARE(mdiArea.activeSubWindow(), active);
+ QCOMPARE(mdiArea.currentSubWindow(), active);
+
+ qApp->setActiveWindow(&dummyTopLevel);
+ QVERIFY(mdiArea.activeSubWindow());
+ QCOMPARE(mdiArea.currentSubWindow(), active);
+
+ qApp->setActiveWindow(&mdiArea);
+ active->show();
+ QCOMPARE(mdiArea.activeSubWindow(), active);
+
+ mdiArea.setActiveSubWindow(0);
+ QVERIFY(!mdiArea.activeSubWindow());
+ QVERIFY(!mdiArea.currentSubWindow());
+
+ mdiArea.setActiveSubWindow(active);
+ QCOMPARE(mdiArea.activeSubWindow(), active);
+ QEvent windowDeactivate(QEvent::WindowDeactivate);
+ qApp->sendEvent(active, &windowDeactivate);
+ QVERIFY(!mdiArea.activeSubWindow());
+ QVERIFY(!mdiArea.currentSubWindow());
+
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(active, &windowActivate);
+ QVERIFY(mdiArea.activeSubWindow());
+ QVERIFY(mdiArea.currentSubWindow());
+
+#if !defined(Q_WS_MAC) && !defined(Q_WS_WIN)
+ qApp->setActiveWindow(0);
+ QVERIFY(!mdiArea.activeSubWindow());
+ QVERIFY(mdiArea.currentSubWindow());
+#endif
+}
+
+void tst_QMdiArea::addAndRemoveWindows()
+{
+ QWidget topLevel;
+ QMdiArea workspace(&topLevel);
+ workspace.resize(800, 600);
+ topLevel.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+ { // addSubWindow with large widget
+ QCOMPARE(workspace.subWindowList().count(), 0);
+ QWidget *window = workspace.addSubWindow(new LargeWidget);
+ QVERIFY(window);
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 1);
+ QVERIFY(window->windowFlags() == DefaultWindowFlags);
+ QCOMPARE(window->size(), workspace.viewport()->size());
+ }
+
+ { // addSubWindow, minimumSize set.
+ QMdiSubWindow *window = new QMdiSubWindow;
+ window->setMinimumSize(900, 900);
+ workspace.addSubWindow(window);
+ QVERIFY(window);
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 2);
+ QVERIFY(window->windowFlags() == DefaultWindowFlags);
+ QCOMPARE(window->size(), window->minimumSize());
+ }
+
+ { // addSubWindow, resized
+ QMdiSubWindow *window = new QMdiSubWindow;
+ window->setWidget(new QWidget);
+ window->resize(1500, 1500);
+ workspace.addSubWindow(window);
+ QVERIFY(window);
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 3);
+ QVERIFY(window->windowFlags() == DefaultWindowFlags);
+ QCOMPARE(window->size(), QSize(1500, 1500));
+ }
+
+ { // addSubWindow with 0 pointer
+ QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: null pointer to widget");
+ QWidget *window = workspace.addSubWindow(0);
+ QVERIFY(!window);
+ QCOMPARE(workspace.subWindowList().count(), 3);
+ }
+
+ { // addChildWindow
+ QMdiSubWindow *window = new QMdiSubWindow;
+ workspace.addSubWindow(window);
+ qApp->processEvents();
+ QVERIFY(window->windowFlags() == DefaultWindowFlags);
+ window->setWidget(new QWidget);
+ QCOMPARE(workspace.subWindowList().count(), 4);
+ QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: window is already added");
+ workspace.addSubWindow(window);
+ }
+
+ { // addChildWindow with 0 pointer
+ QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: null pointer to widget");
+ workspace.addSubWindow(0);
+ QCOMPARE(workspace.subWindowList().count(), 4);
+ }
+
+ // removeSubWindow
+ foreach (QWidget *window, workspace.subWindowList()) {
+ workspace.removeSubWindow(window);
+ delete window;
+ }
+ QCOMPARE(workspace.subWindowList().count(), 0);
+
+ // removeSubWindow with 0 pointer
+ QTest::ignoreMessage(QtWarningMsg, "QMdiArea::removeSubWindow: null pointer to widget");
+ workspace.removeSubWindow(0);
+
+ workspace.addSubWindow(new QPushButton(QLatin1String("Dummy to make workspace non-empty")));
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 1);
+
+ // removeSubWindow with window not inside workspace
+ QTest::ignoreMessage(QtWarningMsg,"QMdiArea::removeSubWindow: window is not inside workspace");
+ QMdiSubWindow *fakeWindow = new QMdiSubWindow;
+ workspace.removeSubWindow(fakeWindow);
+ delete fakeWindow;
+
+ // Check that newly added windows don't occupy maximized windows'
+ // restore space.
+ workspace.closeAllSubWindows();
+ workspace.setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
+ workspace.show();
+ QMdiSubWindow *window1 = workspace.addSubWindow(new QWidget);
+ window1->show();
+ const QRect window1RestoreGeometry = window1->geometry();
+ QCOMPARE(window1RestoreGeometry.topLeft(), QPoint(0, 0));
+
+ window1->showMinimized();
+
+ // Occupy space.
+ QMdiSubWindow *window2 = workspace.addSubWindow(new QWidget);
+ window2->show();
+ const QRect window2RestoreGeometry = window2->geometry();
+ QCOMPARE(window2RestoreGeometry.topLeft(), QPoint(0, 0));
+
+ window2->showMaximized();
+
+ // Don't occupy space.
+ QMdiSubWindow *window3 = workspace.addSubWindow(new QWidget);
+ window3->show();
+ QCOMPARE(window3->geometry().topLeft(), QPoint(window2RestoreGeometry.right() + 1, 0));
+}
+
+void tst_QMdiArea::addAndRemoveWindowsWithReparenting()
+{
+ QMdiArea workspace;
+ QMdiSubWindow window(&workspace);
+ QVERIFY(window.windowFlags() == DefaultWindowFlags);
+
+ // 0 because the window list contains widgets and not actual
+ // windows. Silly, but that's the behavior.
+ QCOMPARE(workspace.subWindowList().count(), 0);
+ window.setWidget(new QWidget);
+ qApp->processEvents();
+
+ QCOMPARE(workspace.subWindowList().count(), 1);
+ window.setParent(0); // Will also reset window flags
+ QCOMPARE(workspace.subWindowList().count(), 0);
+ window.setParent(&workspace);
+ QCOMPARE(workspace.subWindowList().count(), 1);
+ QVERIFY(window.windowFlags() == DefaultWindowFlags);
+
+ QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: window is already added");
+ workspace.addSubWindow(&window);
+ QCOMPARE(workspace.subWindowList().count(), 1);
+}
+
+class MySubWindow : public QMdiSubWindow
+{
+public:
+ using QObject::receivers;
+};
+
+static int numberOfConnectedSignals(MySubWindow *subWindow)
+{
+ if (!subWindow)
+ return 0;
+
+ int numConnectedSignals = 0;
+ for (int i = 0; i < subWindow->metaObject()->methodCount(); ++i) {
+ QMetaMethod method = subWindow->metaObject()->method(i);
+ if (method.methodType() == QMetaMethod::Signal) {
+ QString signature(QLatin1String("2"));
+ signature += QLatin1String(method.signature());
+ numConnectedSignals += subWindow->receivers(signature.toLatin1());
+ }
+ }
+ return numConnectedSignals;
+}
+
+void tst_QMdiArea::removeSubWindow_2()
+{
+ QMdiArea mdiArea;
+ MySubWindow *subWindow = new MySubWindow;
+ QCOMPARE(numberOfConnectedSignals(subWindow), 0);
+
+ // Connected to aboutToActivate() and windowStateChanged().
+ mdiArea.addSubWindow(subWindow);
+ QVERIFY(numberOfConnectedSignals(subWindow) >= 2);
+
+ // Ensure we disconnect from all signals.
+ mdiArea.removeSubWindow(subWindow);
+ QCOMPARE(numberOfConnectedSignals(subWindow), 0);
+
+ mdiArea.addSubWindow(subWindow);
+ QVERIFY(numberOfConnectedSignals(subWindow) >= 2);
+ subWindow->setParent(0);
+ QCOMPARE(numberOfConnectedSignals(subWindow), 0);
+}
+
+void tst_QMdiArea::closeWindows()
+{
+ QMdiArea workspace;
+ workspace.show();
+ qApp->setActiveWindow(&workspace);
+
+ // Close widget
+ QWidget *widget = new QWidget;
+ QMdiSubWindow *subWindow = workspace.addSubWindow(widget);
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 1);
+ subWindow->close();
+ QCOMPARE(workspace.subWindowList().count(), 0);
+
+ // Close window
+ QWidget *window = workspace.addSubWindow(new QWidget);
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 1);
+ window->close();
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 0);
+
+ const int windowCount = 10;
+
+ // Close active window
+ for (int i = 0; i < windowCount; ++i)
+ workspace.addSubWindow(new QWidget)->show();
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), windowCount);
+ int activeSubWindowCount = 0;
+ while (workspace.activeSubWindow()) {
+ workspace.activeSubWindow()->close();
+ qApp->processEvents();
+ ++activeSubWindowCount;
+ }
+ QCOMPARE(activeSubWindowCount, windowCount);
+ QCOMPARE(workspace.subWindowList().count(), 0);
+
+ // Close all windows
+ for (int i = 0; i < windowCount; ++i)
+ workspace.addSubWindow(new QWidget)->show();
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), windowCount);
+ QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+ connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
+ workspace.closeAllSubWindows();
+ qApp->processEvents();
+ QCOMPARE(workspace.subWindowList().count(), 0);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(!activeWindow);
+}
+
+void tst_QMdiArea::activateNextAndPreviousWindow()
+{
+ QMdiArea workspace;
+ workspace.show();
+ qApp->setActiveWindow(&workspace);
+
+ const int windowCount = 10;
+ QMdiSubWindow *windows[windowCount];
+ for (int i = 0; i < windowCount; ++i) {
+ windows[i] = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
+ windows[i]->show();
+ qApp->processEvents();
+ }
+
+ QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+ connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
+
+ // activateNextSubWindow
+ for (int i = 0; i < windowCount; ++i) {
+ workspace.activateNextSubWindow();
+ qApp->processEvents();
+ QCOMPARE(workspace.activeSubWindow(), windows[i]);
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ }
+ QVERIFY(activeWindow);
+ QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
+ QCOMPARE(workspace.activeSubWindow(), activeWindow);
+
+ // activatePreviousSubWindow
+ for (int i = windowCount - 2; i >= 0; --i) {
+ workspace.activatePreviousSubWindow();
+ qApp->processEvents();
+ QCOMPARE(workspace.activeSubWindow(), windows[i]);
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ if (i % 2 == 0)
+ windows[i]->hide(); // 10, 8, 6, 4, 2, 0
+ }
+ QVERIFY(activeWindow);
+ QCOMPARE(workspace.activeSubWindow(), windows[0]);
+ QCOMPARE(workspace.activeSubWindow(), activeWindow);
+
+ // activateNextSubWindow with every 2nd window hidden
+ for (int i = 0; i < windowCount / 2; ++i) {
+ workspace.activateNextSubWindow(); // 1, 3, 5, 7, 9
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ }
+ QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
+
+ // activatePreviousSubWindow with every 2nd window hidden
+ for (int i = 0; i < windowCount / 2; ++i) {
+ workspace.activatePreviousSubWindow(); // 7, 5, 3, 1, 9
+ QCOMPARE(spy.count(), 1);
+ spy.clear();
+ }
+ QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
+
+ workspace.setActiveSubWindow(0);
+ QVERIFY(!activeWindow);
+}
+
+void tst_QMdiArea::subWindowList_data()
+{
+ QTest::addColumn<QMdiArea::WindowOrder>("windowOrder");
+ QTest::addColumn<int>("windowCount");
+ QTest::addColumn<int>("activeSubWindow");
+ QTest::addColumn<int>("staysOnTop1");
+ QTest::addColumn<int>("staysOnTop2");
+
+ QTest::newRow("CreationOrder") << QMdiArea::CreationOrder << 10 << 4 << 8 << 5;
+ QTest::newRow("StackingOrder") << QMdiArea::StackingOrder << 10 << 6 << 3 << 9;
+ QTest::newRow("ActivationHistoryOrder") << QMdiArea::ActivationHistoryOrder << 10 << 7 << 2 << 1;
+}
+void tst_QMdiArea::subWindowList()
+{
+ QFETCH(QMdiArea::WindowOrder, windowOrder);
+ QFETCH(int, windowCount);
+ QFETCH(int, activeSubWindow);
+ QFETCH(int, staysOnTop1);
+ QFETCH(int, staysOnTop2);
+
+ QMdiArea workspace;
+ workspace.show();
+ qApp->setActiveWindow(&workspace);
+
+ QList<QMdiSubWindow *> activationOrder;
+ QVector<QMdiSubWindow *> windows;
+ for (int i = 0; i < windowCount; ++i) {
+ windows.append(qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget)));
+ windows[i]->show();
+ activationOrder.append(windows[i]);
+ }
+
+ {
+ QList<QMdiSubWindow *> widgets = workspace.subWindowList(windowOrder);
+ QCOMPARE(widgets.count(), windowCount);
+ for (int i = 0; i < widgets.count(); ++i)
+ QCOMPARE(widgets.at(i), windows[i]);
+ }
+
+ windows[staysOnTop1]->setWindowFlags(windows[staysOnTop1]->windowFlags() | Qt::WindowStaysOnTopHint);
+ workspace.setActiveSubWindow(windows[activeSubWindow]);
+ qApp->processEvents();
+ QCOMPARE(workspace.activeSubWindow(), windows[activeSubWindow]);
+ activationOrder.move(activationOrder.indexOf(windows[activeSubWindow]), windowCount - 1);
+
+ QList<QMdiSubWindow *> subWindows = workspace.subWindowList(windowOrder);
+ if (windowOrder == QMdiArea::CreationOrder) {
+ QCOMPARE(subWindows.at(activeSubWindow), windows[activeSubWindow]);
+ QCOMPARE(subWindows.at(staysOnTop1), windows[staysOnTop1]);
+ for (int i = 0; i < windowCount; ++i)
+ QCOMPARE(subWindows.at(i), windows[i]);
+ return;
+ }
+
+ if (windowOrder == QMdiArea::StackingOrder) {
+ QCOMPARE(subWindows.at(subWindows.count() - 1), windows[staysOnTop1]);
+ QCOMPARE(subWindows.at(subWindows.count() - 2), windows[activeSubWindow]);
+ QCOMPARE(subWindows.count(), windowCount);
+ } else { // ActivationHistoryOrder
+ QCOMPARE(subWindows, activationOrder);
+ }
+
+ windows[staysOnTop2]->setWindowFlags(windows[staysOnTop2]->windowFlags() | Qt::WindowStaysOnTopHint);
+ workspace.setActiveSubWindow(windows[staysOnTop2]);
+ qApp->processEvents();
+ QCOMPARE(workspace.activeSubWindow(), windows[staysOnTop2]);
+ activationOrder.move(activationOrder.indexOf(windows[staysOnTop2]), windowCount - 1);
+
+ workspace.setActiveSubWindow(windows[activeSubWindow]);
+ qApp->processEvents();
+ QCOMPARE(workspace.activeSubWindow(), windows[activeSubWindow]);
+ activationOrder.move(activationOrder.indexOf(windows[activeSubWindow]), windowCount - 1);
+
+ QList<QMdiSubWindow *> widgets = workspace.subWindowList(windowOrder);
+ QCOMPARE(widgets.count(), windowCount);
+ if (windowOrder == QMdiArea::StackingOrder) {
+ QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop2]);
+ QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]);
+ QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]);
+ } else { // ActivationHistory
+ QCOMPARE(widgets, activationOrder);
+ }
+
+ windows[activeSubWindow]->raise();
+ windows[staysOnTop2]->lower();
+
+ widgets = workspace.subWindowList(windowOrder);
+ if (windowOrder == QMdiArea::StackingOrder) {
+ QCOMPARE(widgets.at(widgets.count() - 1), windows[activeSubWindow]);
+ QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]);
+ QCOMPARE(widgets.at(0), windows[staysOnTop2]);
+ } else { // ActivationHistoryOrder
+ QCOMPARE(widgets, activationOrder);
+ }
+
+ windows[activeSubWindow]->stackUnder(windows[staysOnTop1]);
+ windows[staysOnTop2]->raise();
+
+ widgets = workspace.subWindowList(windowOrder);
+ if (windowOrder == QMdiArea::StackingOrder) {
+ QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop2]);
+ QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]);
+ QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]);
+ } else { // ActivationHistoryOrder
+ QCOMPARE(widgets, activationOrder);
+ }
+
+ workspace.setActiveSubWindow(windows[staysOnTop1]);
+ activationOrder.move(activationOrder.indexOf(windows[staysOnTop1]), windowCount - 1);
+
+ widgets = workspace.subWindowList(windowOrder);
+ if (windowOrder == QMdiArea::StackingOrder) {
+ QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop1]);
+ QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop2]);
+ QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]);
+ } else { // ActivationHistoryOrder
+ QCOMPARE(widgets, activationOrder);
+ }
+}
+
+void tst_QMdiArea::setBackground()
+{
+ QMdiArea workspace;
+ QCOMPARE(workspace.background(), workspace.palette().brush(QPalette::Dark));
+ workspace.setBackground(QBrush(Qt::green));
+ QCOMPARE(workspace.background(), QBrush(Qt::green));
+}
+
+void tst_QMdiArea::setViewport()
+{
+ QMdiArea workspace;
+ workspace.show();
+
+ QWidget *firstViewport = workspace.viewport();
+ QVERIFY(firstViewport);
+
+ const int windowCount = 10;
+ for (int i = 0; i < windowCount; ++i) {
+ QMdiSubWindow *window = workspace.addSubWindow(new QWidget);
+ window->show();
+ if (i % 2 == 0) {
+ window->showMinimized();
+ QVERIFY(window->isMinimized());
+ } else {
+ window->showMaximized();
+ QVERIFY(window->isMaximized());
+ }
+ }
+
+ qApp->processEvents();
+ QList<QMdiSubWindow *> windowsBeforeViewportChange = workspace.subWindowList();
+ QCOMPARE(windowsBeforeViewportChange.count(), windowCount);
+
+ workspace.setViewport(new QWidget);
+ qApp->processEvents();
+ QVERIFY(workspace.viewport() != firstViewport);
+
+ QList<QMdiSubWindow *> windowsAfterViewportChange = workspace.subWindowList();
+ QCOMPARE(windowsAfterViewportChange.count(), windowCount);
+ QCOMPARE(windowsAfterViewportChange, windowsBeforeViewportChange);
+
+ // for (int i = 0; i < windowCount; ++i) {
+ // QMdiSubWindow *window = windowsAfterViewportChange.at(i);
+ // if (i % 2 == 0)
+ // QVERIFY(!window->isMinimized());
+ //else
+ // QVERIFY(!window->isMaximized());
+ // }
+
+ QTest::ignoreMessage(QtWarningMsg, "QMdiArea: Deleting the view port is undefined, "
+ "use setViewport instead.");
+ delete workspace.viewport();
+ qApp->processEvents();
+
+ QCOMPARE(workspace.subWindowList().count(), 0);
+ QVERIFY(!workspace.activeSubWindow());
+}
+
+void tst_QMdiArea::tileSubWindows()
+{
+ QMdiArea workspace;
+ workspace.resize(600,480);
+ if (PlatformQuirks::isAutoMaximizing())
+ workspace.setWindowFlags(workspace.windowFlags() | Qt::X11BypassWindowManagerHint);
+ workspace.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+ const int windowCount = 10;
+ for (int i = 0; i < windowCount; ++i) {
+ QMdiSubWindow *subWindow = workspace.addSubWindow(new QWidget);
+ subWindow->setMinimumSize(50, 30);
+ subWindow->show();
+ }
+ workspace.tileSubWindows();
+ workspace.setActiveSubWindow(0);
+ QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+ QList<QMdiSubWindow *> windows = workspace.subWindowList();
+ for (int i = 0; i < windowCount; ++i) {
+ QMdiSubWindow *window = windows.at(i);
+ for (int j = 0; j < windowCount; ++j) {
+ if (i == j)
+ continue;
+ QVERIFY(!window->geometry().intersects(windows.at(j)->geometry()));
+ }
+ }
+
+ // Keep the views tiled through any subsequent resize events.
+ for (int i = 0; i < 5; ++i) {
+ workspace.resize(workspace.size() - QSize(10, 10));
+ qApp->processEvents();
+ }
+ workspace.setActiveSubWindow(0);
+#ifndef Q_OS_WINCE //See Task 197453 ToDo
+ QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+#endif
+
+ QMdiSubWindow *window = windows.at(0);
+
+ // Change the geometry of one of the children and verify
+ // that the views are not tiled anymore.
+ window->move(window->x() + 1, window->y());
+ workspace.resize(workspace.size() - QSize(10, 10));
+ workspace.setActiveSubWindow(0);
+ QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+ qApp->processEvents();
+
+ // Re-tile.
+ workspace.tileSubWindows();
+ workspace.setActiveSubWindow(0);
+ QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+ // Close one of the children and verify that the views
+ // are not tiled anymore.
+ window->close();
+ workspace.resize(workspace.size() - QSize(10, 10));
+ workspace.setActiveSubWindow(0);
+ QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+ qApp->processEvents();
+
+ // Re-tile.
+ workspace.tileSubWindows();
+ workspace.setActiveSubWindow(0);
+ QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+ window = windows.at(1);
+
+ // Maximize one of the children and verify that the views
+ // are not tiled anymore.
+ workspace.tileSubWindows();
+ window->showMaximized();
+ workspace.resize(workspace.size() - QSize(10, 10));
+ workspace.setActiveSubWindow(0);
+ QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+ qApp->processEvents();
+
+ // Re-tile.
+ workspace.tileSubWindows();
+ workspace.setActiveSubWindow(0);
+ QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+ // Minimize one of the children and verify that the views
+ // are not tiled anymore.
+ workspace.tileSubWindows();
+ window->showMinimized();
+ workspace.resize(workspace.size() - QSize(10, 10));
+ workspace.setActiveSubWindow(0);
+ QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+ qApp->processEvents();
+
+ // Re-tile.
+ workspace.tileSubWindows();
+ workspace.setActiveSubWindow(0);
+ QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+ // Active/deactivate windows and verify that the views are tiled.
+ workspace.setActiveSubWindow(windows.at(5));
+ workspace.resize(workspace.size() - QSize(10, 10));
+ workspace.setActiveSubWindow(0);
+ QTest::qWait(250); // delayed re-arrange of minimized windows
+ QTRY_COMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+ // Add another window and verify that the views are not tiled anymore.
+ workspace.addSubWindow(new QPushButton(QLatin1String("I'd like to mess up tiled views")))->show();
+ workspace.resize(workspace.size() - QSize(10, 10));
+ workspace.setActiveSubWindow(0);
+ QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+
+ // Re-tile.
+ workspace.tileSubWindows();
+ workspace.setActiveSubWindow(0);
+ QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+ // Cascade and verify that the views are not tiled anymore.
+ workspace.cascadeSubWindows();
+ workspace.resize(workspace.size() - QSize(10, 10));
+ workspace.setActiveSubWindow(0);
+ QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+
+ // Make sure the active window is placed in top left corner regardless
+ // of whether we have any windows with staysOnTopHint or not.
+ windows.at(3)->setWindowFlags(windows.at(3)->windowFlags() | Qt::WindowStaysOnTopHint);
+ QMdiSubWindow *activeSubWindow = windows.at(6);
+ workspace.setActiveSubWindow(activeSubWindow);
+ QCOMPARE(workspace.activeSubWindow(), activeSubWindow);
+ workspace.tileSubWindows();
+ QCOMPARE(activeSubWindow->geometry().topLeft(), QPoint(0, 0));
+
+ // Verify that we try to resize the area such that all sub-windows are visible.
+ // It's important that tiled windows are NOT overlapping.
+ workspace.resize(350, 150);
+ qApp->processEvents();
+ QTRY_COMPARE(workspace.size(), QSize(350, 150));
+
+ const QSize minSize(300, 100);
+ foreach (QMdiSubWindow *subWindow, workspace.subWindowList())
+ subWindow->setMinimumSize(minSize);
+
+ QCOMPARE(workspace.size(), QSize(350, 150));
+ workspace.tileSubWindows();
+ // The sub-windows are now tiled like this:
+ // | win 1 || win 2 || win 3 |
+ // +-------++-------++-------+
+ // +-------++-------++-------+
+ // | win 4 || win 5 || win 6 |
+ // +-------++-------++-------+
+ // +-------++-------++-------+
+ // | win 7 || win 8 || win 9 |
+ workspace.setActiveSubWindow(0);
+ int frameWidth = 0;
+ if (workspace.style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, 0, &workspace))
+ frameWidth = workspace.style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ const int spacing = 2 * frameWidth + 2;
+ const QSize expectedViewportSize(3 * minSize.width() + spacing, 3 * minSize.height() + spacing);
+#ifdef Q_OS_WINCE
+ QSKIP("Not fixed yet! See task 197453", SkipAll);
+#endif
+ QTRY_COMPARE(workspace.viewport()->rect().size(), expectedViewportSize);
+
+ // Not enough space for all sub-windows to be visible -> provide scroll bars.
+ workspace.resize(150, 150);
+ qApp->processEvents();
+ QTRY_COMPARE(workspace.size(), QSize(150, 150));
+
+ // Horizontal scroll bar.
+ QScrollBar *hBar = workspace.horizontalScrollBar();
+ QCOMPARE(workspace.horizontalScrollBarPolicy(), Qt::ScrollBarAsNeeded);
+ QTRY_VERIFY(hBar->isVisible());
+ QCOMPARE(hBar->value(), 0);
+ QCOMPARE(hBar->minimum(), 0);
+
+ // Vertical scroll bar.
+ QScrollBar *vBar = workspace.verticalScrollBar();
+ QCOMPARE(workspace.verticalScrollBarPolicy(), Qt::ScrollBarAsNeeded);
+ QVERIFY(vBar->isVisible());
+ QCOMPARE(vBar->value(), 0);
+ QCOMPARE(vBar->minimum(), 0);
+
+ workspace.tileSubWindows();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+ qApp->processEvents();
+
+ QTRY_VERIFY(workspace.size() != QSize(150, 150));
+ QTRY_VERIFY(!vBar->isVisible());
+ QTRY_VERIFY(!hBar->isVisible());
+}
+
+void tst_QMdiArea::cascadeAndTileSubWindows()
+{
+ QMdiArea workspace;
+ workspace.resize(400, 400);
+ workspace.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+ const int windowCount = 10;
+ QList<QMdiSubWindow *> windows;
+ for (int i = 0; i < windowCount; ++i) {
+ QMdiSubWindow *window = workspace.addSubWindow(new MyChild);
+ if (i % 3 == 0) {
+ window->showMinimized();
+ QVERIFY(window->isMinimized());
+ } else {
+ window->showMaximized();
+ QVERIFY(window->isMaximized());
+ }
+ windows.append(window);
+ }
+
+ // cascadeSubWindows
+ qApp->processEvents();
+ workspace.cascadeSubWindows();
+ qApp->processEvents();
+
+ // Check dy between two cascaded windows
+ QStyleOptionTitleBar options;
+ options.initFrom(windows.at(1));
+ int titleBarHeight = windows.at(1)->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
+ // ### Remove this after the mac style has been fixed
+ if (windows.at(1)->style()->inherits("QMacStyle"))
+ titleBarHeight -= 4;
+ const QFontMetrics fontMetrics = QFontMetrics(QApplication::font("QWorkspaceTitleBar"));
+ const int dy = qMax(titleBarHeight - (titleBarHeight - fontMetrics.height()) / 2, 1);
+ QCOMPARE(windows.at(2)->geometry().top() - windows.at(1)->geometry().top(), dy);
+
+ for (int i = 0; i < windows.count(); ++i) {
+ QMdiSubWindow *window = windows.at(i);
+ if (i % 3 == 0) {
+ QVERIFY(window->isMinimized());
+ } else {
+ QVERIFY(!window->isMaximized());
+ QCOMPARE(window->size(), window->sizeHint());
+ window->showMaximized();
+ QVERIFY(window->isMaximized());
+ }
+ }
+}
+
+void tst_QMdiArea::resizeMaximizedChildWindows_data()
+{
+ QTest::addColumn<int>("startSize");
+ QTest::addColumn<int>("increment");
+ QTest::addColumn<int>("windowCount");
+
+ QTest::newRow("multiple children") << 400 << 20 << 10;
+}
+
+void tst_QMdiArea::resizeMaximizedChildWindows()
+{
+ QFETCH(int, startSize);
+ QFETCH(int, increment);
+ QFETCH(int, windowCount);
+
+ QWidget topLevel;
+ QMdiArea workspace(&topLevel);
+ topLevel.show();
+#if defined(Q_WS_X11)
+ qt_x11_wait_for_window_manager(&workspace);
+#endif
+ QTest::qWait(100);
+ workspace.resize(startSize, startSize);
+ workspace.setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
+ QSize workspaceSize = workspace.size();
+ QVERIFY(workspaceSize.isValid());
+ QCOMPARE(workspaceSize, QSize(startSize, startSize));
+
+ QList<QMdiSubWindow *> windows;
+ for (int i = 0; i < windowCount; ++i) {
+ QMdiSubWindow *window = workspace.addSubWindow(new QWidget);
+ windows.append(window);
+ qApp->processEvents();
+ window->showMaximized();
+ QTest::qWait(100);
+ QVERIFY(window->isMaximized());
+ QSize windowSize = window->size();
+ QVERIFY(windowSize.isValid());
+ QCOMPARE(window->rect(), workspace.contentsRect());
+
+ workspace.resize(workspaceSize + QSize(increment, increment));
+ QTest::qWait(100);
+ qApp->processEvents();
+ QTRY_COMPARE(workspace.size(), workspaceSize + QSize(increment, increment));
+ QTRY_COMPARE(window->size(), windowSize + QSize(increment, increment));
+ workspaceSize = workspace.size();
+ }
+
+ int newSize = startSize + increment * windowCount;
+ QCOMPARE(workspaceSize, QSize(newSize, newSize));
+ foreach (QWidget *window, windows)
+ QCOMPARE(window->rect(), workspace.contentsRect());
+}
+
+// QWidget::setParent clears focusWidget so make sure
+// we restore it after QMdiArea::addSubWindow.
+void tst_QMdiArea::focusWidgetAfterAddSubWindow()
+{
+ QWidget *view = new QWidget;
+ view->setLayout(new QVBoxLayout);
+
+ QLineEdit *lineEdit1 = new QLineEdit;
+ QLineEdit *lineEdit2 = new QLineEdit;
+ view->layout()->addWidget(lineEdit1);
+ view->layout()->addWidget(lineEdit2);
+
+ lineEdit2->setFocus();
+ QCOMPARE(view->focusWidget(), static_cast<QWidget *>(lineEdit2));
+
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(view);
+ QCOMPARE(view->focusWidget(), static_cast<QWidget *>(lineEdit2));
+
+ mdiArea.show();
+ view->show();
+ qApp->setActiveWindow(&mdiArea);
+ QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(lineEdit2));
+}
+
+void tst_QMdiArea::dontMaximizeSubWindowOnActivation()
+{
+ QMdiArea mdiArea;
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ qApp->setActiveWindow(&mdiArea);
+
+ // Add one maximized window.
+ mdiArea.addSubWindow(new QWidget)->showMaximized();
+ QVERIFY(mdiArea.activeSubWindow());
+ QVERIFY(mdiArea.activeSubWindow()->isMaximized());
+
+ // Add few more windows and verify that they are maximized.
+ for (int i = 0; i < 5; ++i) {
+ QMdiSubWindow *window = mdiArea.addSubWindow(new QWidget);
+ window->show();
+ QVERIFY(window->isMaximized());
+ qApp->processEvents();
+ }
+
+ // Verify that activated windows still are maximized on activation.
+ QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
+ for (int i = 0; i < subWindows.count(); ++i) {
+ mdiArea.activateNextSubWindow();
+ QMdiSubWindow *window = subWindows.at(i);
+ QCOMPARE(mdiArea.activeSubWindow(), window);
+ QVERIFY(window->isMaximized());
+ qApp->processEvents();
+ }
+
+ // Restore active window and verify that other windows aren't
+ // maximized on activation.
+ mdiArea.activeSubWindow()->showNormal();
+ for (int i = 0; i < subWindows.count(); ++i) {
+ mdiArea.activateNextSubWindow();
+ QMdiSubWindow *window = subWindows.at(i);
+ QCOMPARE(mdiArea.activeSubWindow(), window);
+ QVERIFY(!window->isMaximized());
+ qApp->processEvents();
+ }
+
+ // Enable 'DontMaximizedSubWindowOnActivation' and maximize the active window.
+ mdiArea.setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
+ mdiArea.activeSubWindow()->showMaximized();
+ int indexOfMaximized = subWindows.indexOf(mdiArea.activeSubWindow());
+
+ // Verify that windows are not maximized on activation.
+ for (int i = 0; i < subWindows.count(); ++i) {
+ mdiArea.activateNextSubWindow();
+ QMdiSubWindow *window = subWindows.at(i);
+ QCOMPARE(mdiArea.activeSubWindow(), window);
+ if (indexOfMaximized != i)
+ QVERIFY(!window->isMaximized());
+ qApp->processEvents();
+ }
+ QVERIFY(mdiArea.activeSubWindow()->isMaximized());
+
+ // Minimize all windows.
+ foreach (QMdiSubWindow *window, subWindows) {
+ window->showMinimized();
+ QVERIFY(window->isMinimized());
+ qApp->processEvents();
+ }
+
+ // Disable 'DontMaximizedSubWindowOnActivation' and maximize the active window.
+ mdiArea.setOption(QMdiArea::DontMaximizeSubWindowOnActivation, false);
+ mdiArea.activeSubWindow()->showMaximized();
+
+ // Verify that minimized windows are maximized on activation.
+ for (int i = 0; i < subWindows.count(); ++i) {
+ mdiArea.activateNextSubWindow();
+ QMdiSubWindow *window = subWindows.at(i);
+ QCOMPARE(mdiArea.activeSubWindow(), window);
+ QVERIFY(window->isMaximized());
+ qApp->processEvents();
+ }
+
+ // Verify that activated windows are maximized after closing
+ // the active window
+ for (int i = 0; i < subWindows.count(); ++i) {
+ QVERIFY(mdiArea.activeSubWindow());
+ QVERIFY(mdiArea.activeSubWindow()->isMaximized());
+ mdiArea.activeSubWindow()->close();
+ qApp->processEvents();
+ }
+
+ QVERIFY(!mdiArea.activeSubWindow());
+ QCOMPARE(mdiArea.subWindowList().size(), 0);
+
+ // Verify that new windows are not maximized.
+ mdiArea.addSubWindow(new QWidget)->show();
+ QVERIFY(mdiArea.activeSubWindow());
+ QVERIFY(!mdiArea.activeSubWindow()->isMaximized());
+}
+
+void tst_QMdiArea::delayedPlacement()
+{
+ QMdiArea mdiArea;
+
+ QMdiSubWindow *window1 = mdiArea.addSubWindow(new QWidget);
+ QCOMPARE(window1->geometry().topLeft(), QPoint(0, 0));
+
+ QMdiSubWindow *window2 = mdiArea.addSubWindow(new QWidget);
+ QCOMPARE(window2->geometry().topLeft(), QPoint(0, 0));
+
+ QMdiSubWindow *window3 = mdiArea.addSubWindow(new QWidget);
+ QCOMPARE(window3->geometry().topLeft(), QPoint(0, 0));
+
+ mdiArea.resize(window3->minimumSizeHint().width() * 3, 400);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ QCOMPARE(window1->geometry().topLeft(), QPoint(0, 0));
+ QCOMPARE(window2->geometry().topLeft(), window1->geometry().topRight() + QPoint(1, 0));
+ QCOMPARE(window3->geometry().topLeft(), window2->geometry().topRight() + QPoint(1, 0));
+}
+
+void tst_QMdiArea::iconGeometryInMenuBar()
+{
+#if !defined (Q_WS_MAC) && !defined(Q_OS_WINCE)
+ QMainWindow mainWindow;
+ QMenuBar *menuBar = mainWindow.menuBar();
+ QMdiArea *mdiArea = new QMdiArea;
+ QMdiSubWindow *subWindow = mdiArea->addSubWindow(new QWidget);
+ mainWindow.setCentralWidget(mdiArea);
+ mainWindow.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mainWindow);
+#endif
+
+ subWindow->showMaximized();
+ QVERIFY(subWindow->isMaximized());
+
+ QWidget *leftCornerWidget = menuBar->cornerWidget(Qt::TopLeftCorner);
+ QVERIFY(leftCornerWidget);
+ int topMargin = (menuBar->height() - leftCornerWidget->height()) / 2;
+ int leftMargin = qApp->style()->pixelMetric(QStyle::PM_MenuBarHMargin)
+ + qApp->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth);
+ QPoint pos(leftMargin, topMargin);
+ QRect geometry = QStyle::visualRect(qApp->layoutDirection(), menuBar->rect(),
+ QRect(pos, leftCornerWidget->size()));
+ QCOMPARE(leftCornerWidget->geometry(), geometry);
+#endif
+}
+
+class EventSpy : public QObject
+{
+public:
+ EventSpy(QObject *object, QEvent::Type event)
+ : eventToSpy(event), _count(0)
+ {
+ if (object)
+ object->installEventFilter(this);
+ }
+
+ int count() const { return _count; }
+ void clear() { _count = 0; }
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event)
+ {
+ if (event->type() == eventToSpy)
+ ++_count;
+ return QObject::eventFilter(object, event);
+ }
+
+private:
+ QEvent::Type eventToSpy;
+ int _count;
+};
+
+void tst_QMdiArea::resizeTimer()
+{
+ QMdiArea mdiArea;
+ QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ QTest::qWaitForWindowShown(&mdiArea);
+
+#ifndef Q_OS_WINCE
+ int time = 250;
+#else
+ int time = 1000;
+#endif
+
+ QTest::qWait(time);
+
+ EventSpy timerEventSpy(subWindow, QEvent::Timer);
+ QCOMPARE(timerEventSpy.count(), 0);
+
+ mdiArea.tileSubWindows();
+ QTest::qWait(time); // Wait for timer events to occur.
+ QCOMPARE(timerEventSpy.count(), 1);
+ timerEventSpy.clear();
+
+ mdiArea.resize(mdiArea.size() + QSize(2, 2));
+ QTest::qWait(time); // Wait for timer events to occur.
+ QCOMPARE(timerEventSpy.count(), 1);
+ timerEventSpy.clear();
+
+ // Check that timers are killed.
+ QTest::qWait(time); // Wait for timer events to occur.
+ QCOMPARE(timerEventSpy.count(), 0);
+}
+
+void tst_QMdiArea::updateScrollBars()
+{
+ QMdiArea mdiArea;
+ mdiArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ mdiArea.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+
+ QMdiSubWindow *subWindow1 = mdiArea.addSubWindow(new QWidget);
+ QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(new QWidget);
+
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ qApp->processEvents();
+
+ QScrollBar *hbar = mdiArea.horizontalScrollBar();
+ QVERIFY(hbar);
+ QVERIFY(!hbar->isVisible());
+
+ QScrollBar *vbar = mdiArea.verticalScrollBar();
+ QVERIFY(vbar);
+ QVERIFY(!vbar->isVisible());
+
+ // Move sub-window 2 away.
+ subWindow2->move(10000, 10000);
+ qApp->processEvents();
+ QVERIFY(hbar->isVisible());
+ QVERIFY(vbar->isVisible());
+
+ for (int i = 0; i < 2; ++i) {
+ // Maximize sub-window 1 and make sure we don't have any scroll bars.
+ subWindow1->showMaximized();
+ qApp->processEvents();
+ QVERIFY(subWindow1->isMaximized());
+ QVERIFY(!hbar->isVisible());
+ QVERIFY(!vbar->isVisible());
+
+ // We still shouldn't get any scroll bars.
+ mdiArea.resize(mdiArea.size() - QSize(20, 20));
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+ qApp->processEvents();
+ QVERIFY(subWindow1->isMaximized());
+ QVERIFY(!hbar->isVisible());
+ QVERIFY(!vbar->isVisible());
+
+ // Restore sub-window 1 and make sure we have scroll bars again.
+ subWindow1->showNormal();
+ qApp->processEvents();
+ QVERIFY(!subWindow1->isMaximized());
+ QVERIFY(hbar->isVisible());
+ QVERIFY(vbar->isVisible());
+ if (i == 0) {
+ // Now, do the same when the viewport is scrolled.
+ hbar->setValue(1000);
+ vbar->setValue(1000);
+ }
+ }
+}
+
+void tst_QMdiArea::setActivationOrder_data()
+{
+ QTest::addColumn<QMdiArea::WindowOrder>("activationOrder");
+ QTest::addColumn<int>("subWindowCount");
+ QTest::addColumn<int>("staysOnTopIndex");
+ QTest::addColumn<int>("firstActiveIndex");
+ QTest::addColumn<QList<int> >("expectedActivationIndices");
+ // The order of expectedCascadeIndices:
+ // window 1 -> (index 0)
+ // window 2 -> (index 1)
+ // window 3 -> (index 2)
+ // ....
+ QTest::addColumn<QList<int> >("expectedCascadeIndices");
+
+ // The order of expectedTileIndices (the same as reading a book LTR).
+ // +--------------------+--------------------+--------------------+
+ // | window 1 (index 0) | window 2 (index 1) | window 3 (index 2) |
+ // | +--------------------+--------------------+
+ // | (index 3) | window 4 (index 4) | window 5 (index 5) |
+ // +--------------------------------------------------------------+
+ QTest::addColumn<QList<int> >("expectedTileIndices");
+
+ QList<int> list;
+ QList<int> list2;
+ QList<int> list3;
+
+ list << 2 << 1 << 0 << 1 << 2 << 3 << 4;
+ list2 << 0 << 1 << 2 << 3 << 4;
+ list3 << 1 << 4 << 3 << 1 << 2 << 0;
+ QTest::newRow("CreationOrder") << QMdiArea::CreationOrder << 5 << 3 << 1 << list << list2 << list3;
+
+ list = QList<int>();
+ list << 3 << 1 << 4 << 3 << 1 << 2 << 0;
+ list2 = QList<int>();
+ list2 << 0 << 2 << 4 << 1 << 3;
+ list3 = QList<int>();
+ list3 << 1 << 3 << 4 << 1 << 2 << 0;
+ QTest::newRow("StackingOrder") << QMdiArea::StackingOrder << 5 << 3 << 1 << list << list2 << list3;
+
+ list = QList<int>();
+ list << 0 << 1 << 0 << 1 << 4 << 3 << 2;
+ list2 = QList<int>();
+ list2 << 0 << 2 << 3 << 4 << 1;
+ list3 = QList<int>();
+ list3 << 1 << 4 << 3 << 1 << 2 << 0;
+ QTest::newRow("ActivationHistoryOrder") << QMdiArea::ActivationHistoryOrder << 5 << 3 << 1 << list << list2 << list3;
+}
+
+void tst_QMdiArea::setActivationOrder()
+{
+ QFETCH(QMdiArea::WindowOrder, activationOrder);
+ QFETCH(int, subWindowCount);
+ QFETCH(int, staysOnTopIndex);
+ QFETCH(int, firstActiveIndex);
+ QFETCH(QList<int>, expectedActivationIndices);
+ QFETCH(QList<int>, expectedCascadeIndices);
+ QFETCH(QList<int>, expectedTileIndices);
+
+ // Default order.
+ QMdiArea mdiArea;
+ QCOMPARE(mdiArea.activationOrder(), QMdiArea::CreationOrder);
+
+ // New order.
+ mdiArea.setActivationOrder(activationOrder);
+ QCOMPARE(mdiArea.activationOrder(), activationOrder);
+
+ QList<QMdiSubWindow *> subWindows;
+ for (int i = 0; i < subWindowCount; ++i)
+ subWindows << mdiArea.addSubWindow(new QPushButton(tr("%1").arg(i)));
+ QCOMPARE(mdiArea.subWindowList(activationOrder), subWindows);
+
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ for (int i = 0; i < subWindows.count(); ++i) {
+ mdiArea.activateNextSubWindow();
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(i));
+ qApp->processEvents();
+ }
+
+ QMdiSubWindow *staysOnTop = subWindows.at(staysOnTopIndex);
+ staysOnTop->setWindowFlags(staysOnTop->windowFlags() | Qt::WindowStaysOnTopHint);
+ staysOnTop->raise();
+
+ mdiArea.setActiveSubWindow(subWindows.at(firstActiveIndex));
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(firstActiveIndex));
+
+ // Verify the actual arrangement/geometry.
+ mdiArea.tileSubWindows();
+ QTest::qWait(100);
+ QVERIFY(verifyArrangement(&mdiArea, Tiled, expectedTileIndices));
+
+ mdiArea.cascadeSubWindows();
+ QVERIFY(verifyArrangement(&mdiArea, Cascaded, expectedCascadeIndices));
+ QTest::qWait(100);
+
+ mdiArea.activateNextSubWindow();
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
+
+ mdiArea.activatePreviousSubWindow();
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
+
+ mdiArea.activatePreviousSubWindow();
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
+
+ for (int i = 0; i < subWindowCount; ++i) {
+ mdiArea.closeActiveSubWindow();
+ qApp->processEvents();
+ if (i == subWindowCount - 1) { // Last window closed.
+ QVERIFY(!mdiArea.activeSubWindow());
+ break;
+ }
+ QVERIFY(mdiArea.activeSubWindow());
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
+ }
+
+ QVERIFY(mdiArea.subWindowList(activationOrder).isEmpty());
+ QVERIFY(expectedActivationIndices.isEmpty());
+}
+
+void tst_QMdiArea::tabBetweenSubWindows()
+{
+ QMdiArea mdiArea;
+ QList<QMdiSubWindow *> subWindows;
+ for (int i = 0; i < 5; ++i)
+ subWindows << mdiArea.addSubWindow(new QLineEdit);
+
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ qApp->setActiveWindow(&mdiArea);
+ QWidget *focusWidget = subWindows.back()->widget();
+ QCOMPARE(qApp->focusWidget(), focusWidget);
+
+ QSignalSpy spy(&mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+ QCOMPARE(spy.count(), 0);
+
+ // Walk through the entire list of sub windows.
+ QVERIFY(tabBetweenSubWindowsIn(&mdiArea));
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.back());
+ QCOMPARE(spy.count(), 0);
+
+ mdiArea.setActiveSubWindow(subWindows.front());
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.front());
+ spy.clear();
+
+ // Walk through the entire list of sub windows in the opposite direction (Ctrl-Shift-Tab).
+ QVERIFY(tabBetweenSubWindowsIn(&mdiArea, -1, true));
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.front());
+ QCOMPARE(spy.count(), 0);
+
+ // Ctrl-Tab-Tab-Tab
+ QVERIFY(tabBetweenSubWindowsIn(&mdiArea, 3));
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(3));
+ QCOMPARE(spy.count(), 1);
+
+ mdiArea.setActiveSubWindow(subWindows.at(1));
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(1));
+ spy.clear();
+
+ // Quick switch (Ctrl-Tab once) -> switch back to the previously active sub-window.
+ QVERIFY(tabBetweenSubWindowsIn(&mdiArea, 1));
+ QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(3));
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QMdiArea::setViewMode()
+{
+ QMdiArea mdiArea;
+
+ QPixmap iconPixmap(16, 16);
+ iconPixmap.fill(Qt::red);
+ for (int i = 0; i < 5; ++i) {
+ QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget);
+ subWindow->setWindowTitle(QString(QLatin1String("Title %1")).arg(i));
+ subWindow->setWindowIcon(iconPixmap);
+ }
+
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ QMdiSubWindow *activeSubWindow = mdiArea.activeSubWindow();
+ const QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
+
+ // Default.
+ QVERIFY(!activeSubWindow->isMaximized());
+ QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(!tabBar);
+ QCOMPARE(mdiArea.viewMode(), QMdiArea::SubWindowView);
+
+ // Tabbed view.
+ mdiArea.setViewMode(QMdiArea::TabbedView);
+ QCOMPARE(mdiArea.viewMode(), QMdiArea::TabbedView);
+ tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(tabBar);
+ QVERIFY(tabBar->isVisible());
+
+ QCOMPARE(tabBar->count(), subWindows.count());
+ QVERIFY(activeSubWindow->isMaximized());
+ QCOMPARE(tabBar->currentIndex(), subWindows.indexOf(activeSubWindow));
+
+ // Check that tabIcon and tabText are set properly.
+ for (int i = 0; i < subWindows.size(); ++i) {
+ QMdiSubWindow *subWindow = subWindows.at(i);
+ QCOMPARE(tabBar->tabText(i), subWindow->windowTitle());
+ QCOMPARE(tabBar->tabIcon(i), subWindow->windowIcon());
+ }
+
+ // Check that tabText and tabIcon are updated.
+ activeSubWindow->setWindowTitle(QLatin1String("Dude, I want another window title"));
+ QCOMPARE(tabBar->tabText(tabBar->currentIndex()), activeSubWindow->windowTitle());
+ iconPixmap.fill(Qt::green);
+ activeSubWindow->setWindowIcon(iconPixmap);
+ QCOMPARE(tabBar->tabIcon(tabBar->currentIndex()), activeSubWindow->windowIcon());
+
+ // If there's an empty window title, tabText should return "(Untitled)" (as in firefox).
+ activeSubWindow->setWindowTitle(QString());
+ QCOMPARE(tabBar->tabText(tabBar->currentIndex()), QLatin1String("(Untitled)"));
+
+ // If there's no window icon, tabIcon should return ... an empty icon :)
+ activeSubWindow->setWindowIcon(QIcon());
+ QCOMPARE(tabBar->tabIcon(tabBar->currentIndex()), QIcon());
+
+ // Check that the current tab changes when activating another sub-window.
+ for (int i = 0; i < subWindows.size(); ++i) {
+ mdiArea.activateNextSubWindow();
+ activeSubWindow = mdiArea.activeSubWindow();
+ QCOMPARE(tabBar->currentIndex(), subWindows.indexOf(activeSubWindow));
+ }
+
+ activeSubWindow = mdiArea.activeSubWindow();
+ const int tabIndex = tabBar->currentIndex();
+
+ // The current tab should not change when the sub-window is hidden.
+ activeSubWindow->hide();
+ QCOMPARE(tabBar->currentIndex(), tabIndex);
+ activeSubWindow->show();
+ QCOMPARE(tabBar->currentIndex(), tabIndex);
+
+ // Disable the tab when the sub-window is hidden and another sub-window is activated.
+ activeSubWindow->hide();
+ mdiArea.activateNextSubWindow();
+ QVERIFY(tabBar->currentIndex() != tabIndex);
+ QVERIFY(!tabBar->isTabEnabled(tabIndex));
+
+ // Enable it again.
+ activeSubWindow->show();
+ QCOMPARE(tabBar->currentIndex(), tabIndex);
+ QVERIFY(tabBar->isTabEnabled(tabIndex));
+
+ // Remove sub-windows and make sure the tab is removed.
+ foreach (QMdiSubWindow *subWindow, subWindows) {
+ if (subWindow != activeSubWindow)
+ mdiArea.removeSubWindow(subWindow);
+ }
+ QCOMPARE(tabBar->count(), 1);
+
+ // Go back to default (QMdiArea::SubWindowView).
+ mdiArea.setViewMode(QMdiArea::SubWindowView);
+ QVERIFY(!activeSubWindow->isMaximized());
+ tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(!tabBar);
+ QCOMPARE(mdiArea.viewMode(), QMdiArea::SubWindowView);
+}
+
+void tst_QMdiArea::setTabsClosable()
+{
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(new QWidget);
+
+ // test default
+ QCOMPARE(mdiArea.tabsClosable(), false);
+
+ // change value before tab bar exists
+ QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(!tabBar);
+ mdiArea.setTabsClosable(true);
+ QCOMPARE(mdiArea.tabsClosable(), true);
+
+ // force tab bar creation
+ mdiArea.setViewMode(QMdiArea::TabbedView);
+ tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(tabBar);
+
+ // value must've been propagated
+ QCOMPARE(tabBar->tabsClosable(), true);
+
+ // change value when tab bar exists
+ mdiArea.setTabsClosable(false);
+ QCOMPARE(mdiArea.tabsClosable(), false);
+ QCOMPARE(tabBar->tabsClosable(), false);
+}
+
+void tst_QMdiArea::setTabsMovable()
+{
+ QMdiArea mdiArea;
+ QMdiSubWindow *subWindow1 = mdiArea.addSubWindow(new QWidget);
+ QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(new QWidget);
+ QMdiSubWindow *subWindow3 = mdiArea.addSubWindow(new QWidget);
+
+ // test default
+ QCOMPARE(mdiArea.tabsMovable(), false);
+
+ // change value before tab bar exists
+ QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(!tabBar);
+ mdiArea.setTabsMovable(true);
+ QCOMPARE(mdiArea.tabsMovable(), true);
+
+ // force tab bar creation
+ mdiArea.setViewMode(QMdiArea::TabbedView);
+ tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(tabBar);
+
+ // value must've been propagated
+ QCOMPARE(tabBar->isMovable(), true);
+
+ // test tab moving
+ QList<QMdiSubWindow *> subWindows;
+ subWindows << subWindow1 << subWindow2 << subWindow3;
+ QCOMPARE(mdiArea.subWindowList(QMdiArea::CreationOrder), subWindows);
+ tabBar->moveTab(1, 2); // 1,3,2
+ subWindows.clear();
+ subWindows << subWindow1 << subWindow3 << subWindow2;
+ QCOMPARE(mdiArea.subWindowList(QMdiArea::CreationOrder), subWindows);
+ tabBar->moveTab(0, 2); // 3,2,1
+ subWindows.clear();
+ subWindows << subWindow3 << subWindow2 << subWindow1;
+ QCOMPARE(mdiArea.subWindowList(QMdiArea::CreationOrder), subWindows);
+
+ // change value when tab bar exists
+ mdiArea.setTabsMovable(false);
+ QCOMPARE(mdiArea.tabsMovable(), false);
+ QCOMPARE(tabBar->isMovable(), false);
+}
+
+void tst_QMdiArea::setTabShape()
+{
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ // Default.
+ QCOMPARE(mdiArea.tabShape(), QTabWidget::Rounded);
+
+ // Triangular.
+ mdiArea.setTabShape(QTabWidget::Triangular);
+ QCOMPARE(mdiArea.tabShape(), QTabWidget::Triangular);
+
+ mdiArea.setViewMode(QMdiArea::TabbedView);
+
+ QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(tabBar);
+ QCOMPARE(tabBar->shape(), QTabBar::TriangularNorth);
+
+ // Back to default (Rounded).
+ mdiArea.setTabShape(QTabWidget::Rounded);
+ QCOMPARE(mdiArea.tabShape(), QTabWidget::Rounded);
+ QCOMPARE(tabBar->shape(), QTabBar::RoundedNorth);
+}
+
+void tst_QMdiArea::setTabPosition_data()
+{
+ QTest::addColumn<QTabWidget::TabPosition>("tabPosition");
+ QTest::addColumn<bool>("hasLeftMargin");
+ QTest::addColumn<bool>("hasTopMargin");
+ QTest::addColumn<bool>("hasRightMargin");
+ QTest::addColumn<bool>("hasBottomMargin");
+
+ QTest::newRow("North") << QTabWidget::North << false << true << false << false;
+ QTest::newRow("South") << QTabWidget::South << false << false << false << true;
+ QTest::newRow("East") << QTabWidget::East << false << false << true << false;
+ QTest::newRow("West") << QTabWidget::West << true << false << false << false;
+}
+
+void tst_QMdiArea::setTabPosition()
+{
+ QFETCH(QTabWidget::TabPosition, tabPosition);
+ QFETCH(bool, hasLeftMargin);
+ QFETCH(bool, hasTopMargin);
+ QFETCH(bool, hasRightMargin);
+ QFETCH(bool, hasBottomMargin);
+
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ // Make sure there are no margins.
+ mdiArea.setContentsMargins(0, 0, 0, 0);
+
+ // Default.
+ QCOMPARE(mdiArea.tabPosition(), QTabWidget::North);
+ mdiArea.setViewMode(QMdiArea::TabbedView);
+ QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
+ QVERIFY(tabBar);
+ QCOMPARE(tabBar->shape(), QTabBar::RoundedNorth);
+
+ // New position.
+ mdiArea.setTabPosition(tabPosition);
+ QCOMPARE(mdiArea.tabPosition(), tabPosition);
+ QCOMPARE(tabBar->shape(), tabBarShapeFrom(QTabWidget::Rounded, tabPosition));
+
+ const Qt::LayoutDirection originalLayoutDirection = qApp->layoutDirection();
+
+ // Check that we have correct geometry in both RightToLeft and LeftToRight.
+ for (int i = 0; i < 2; ++i) {
+ // Check viewportMargins.
+ const QRect viewportGeometry = mdiArea.viewport()->geometry();
+ const int left = viewportGeometry.left();
+ const int top = viewportGeometry.y();
+ const int right = mdiArea.width() - viewportGeometry.width();
+ const int bottom = mdiArea.height() - viewportGeometry.height();
+
+ const QSize sizeHint = tabBar->sizeHint();
+
+ if (hasLeftMargin)
+ QCOMPARE(qApp->isLeftToRight() ? left : right, sizeHint.width());
+ if (hasRightMargin)
+ QCOMPARE(qApp->isLeftToRight() ? right : left, sizeHint.width());
+ if (hasTopMargin || hasBottomMargin)
+ QCOMPARE(hasTopMargin ? top : bottom, sizeHint.height());
+
+ // Check actual tab bar geometry.
+ const QRegion expectedTabBarGeometry = QRegion(mdiArea.rect()).subtracted(viewportGeometry);
+ QVERIFY(!expectedTabBarGeometry.isEmpty());
+ QCOMPARE(QRegion(tabBar->geometry()), expectedTabBarGeometry);
+
+ if (i == 0)
+ qApp->setLayoutDirection(originalLayoutDirection == Qt::LeftToRight ? Qt::RightToLeft : Qt::LeftToRight);
+ qApp->processEvents();
+ }
+
+ qApp->setLayoutDirection(originalLayoutDirection);
+}
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+void tst_QMdiArea::nativeSubWindows()
+{
+ { // Add native widgets after show.
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ // No native widgets.
+ QVERIFY(!mdiArea.viewport()->internalWinId());
+ foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+ QVERIFY(!subWindow->internalWinId());
+
+ QWidget *nativeWidget = new QWidget;
+ QVERIFY(nativeWidget->winId()); // enforce native window.
+ mdiArea.addSubWindow(nativeWidget);
+
+ // The viewport and all the sub-windows must be native.
+ QVERIFY(mdiArea.viewport()->internalWinId());
+ foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+ QVERIFY(subWindow->internalWinId());
+
+ // Add a non-native widget. This should become native.
+ QMdiSubWindow *subWindow = new QMdiSubWindow;
+ subWindow->setWidget(new QWidget);
+ QVERIFY(!subWindow->internalWinId());
+ mdiArea.addSubWindow(subWindow);
+ QVERIFY(subWindow->internalWinId());
+ }
+
+ { // Add native widgets before show.
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(new QWidget);
+ QWidget *nativeWidget = new QWidget;
+ (void)nativeWidget->winId();
+ mdiArea.addSubWindow(nativeWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ // The viewport and all the sub-windows must be native.
+ QVERIFY(mdiArea.viewport()->internalWinId());
+ foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+ QVERIFY(subWindow->internalWinId());
+ }
+
+ { // Make a sub-window native *after* it's added to the area.
+ QMdiArea mdiArea;
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ QMdiSubWindow *nativeSubWindow = mdiArea.subWindowList().last();
+ QVERIFY(!nativeSubWindow->internalWinId());
+ (void)nativeSubWindow->winId();
+
+ // All the sub-windows should be native at this point
+ QVERIFY(mdiArea.viewport()->internalWinId());
+ foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+ QVERIFY(subWindow->internalWinId());
+ }
+
+#ifndef QT_NO_OPENGL
+ {
+ if (!QGLFormat::hasOpenGL())
+ QSKIP("QGL not supported on this platform", SkipAll);
+
+ QMdiArea mdiArea;
+ QGLWidget *glViewport = new QGLWidget;
+ mdiArea.setViewport(glViewport);
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.addSubWindow(new QWidget);
+ mdiArea.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+ const QGLContext *context = glViewport->context();
+ if (!context || !context->isValid())
+ QSKIP("QGL is broken, cannot continue test", SkipAll);
+
+ // The viewport and all the sub-windows must be native.
+ QVERIFY(mdiArea.viewport()->internalWinId());
+ foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+ QVERIFY(subWindow->internalWinId());
+ }
+#endif
+}
+#endif
+
+void tst_QMdiArea::task_209615()
+{
+ QTabWidget tabWidget;
+ QMdiArea *mdiArea1 = new QMdiArea;
+ QMdiArea *mdiArea2 = new QMdiArea;
+ QMdiSubWindow *subWindow = mdiArea1->addSubWindow(new QLineEdit);
+
+ tabWidget.addTab(mdiArea1, QLatin1String("1"));
+ tabWidget.addTab(mdiArea2, QLatin1String("2"));
+ tabWidget.show();
+
+ mdiArea1->removeSubWindow(subWindow);
+ mdiArea2->addSubWindow(subWindow);
+
+ // Please do not assert/crash.
+ tabWidget.setCurrentIndex(1);
+}
+
+void tst_QMdiArea::task_236750()
+{
+ QMdiArea mdiArea;
+ QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QTextEdit);
+ mdiArea.show();
+
+ subWindow->setWindowFlags(subWindow->windowFlags() | Qt::FramelessWindowHint);
+ // Please do not crash (floating point exception).
+ subWindow->showMinimized();
+}
+
+QTEST_MAIN(tst_QMdiArea)
+#include "tst_qmdiarea.moc"
+