tests/auto/qmdiarea/tst_qmdiarea.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #include <QtTest/QtTest>
       
    44 
       
    45 #include <QMdiSubWindow>
       
    46 #include <QMdiArea>
       
    47 
       
    48 #include <QApplication>
       
    49 #include <QMainWindow>
       
    50 #include <QMenuBar>
       
    51 #include <QPushButton>
       
    52 #include <QStyle>
       
    53 #include <QStyleOption>
       
    54 #include <QVBoxLayout>
       
    55 #include <QLineEdit>
       
    56 #include <QDesktopWidget>
       
    57 #include <QDockWidget>
       
    58 #include <QScrollBar>
       
    59 #include <QTextEdit>
       
    60 #ifndef QT_NO_OPENGL
       
    61 #include <QtOpenGL>
       
    62 #endif
       
    63 #include <QMacStyle>
       
    64 
       
    65 #include "../../shared/util.h"
       
    66 
       
    67 static const Qt::WindowFlags DefaultWindowFlags
       
    68     = Qt::SubWindow | Qt::WindowSystemMenuHint
       
    69       | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint;
       
    70 
       
    71 Q_DECLARE_METATYPE(QMdiArea::WindowOrder)
       
    72 Q_DECLARE_METATYPE(QMdiSubWindow *)
       
    73 Q_DECLARE_METATYPE(QList<int>)
       
    74 Q_DECLARE_METATYPE(QTabWidget::TabPosition)
       
    75 
       
    76 //TESTED_CLASS=
       
    77 //TESTED_FILES=
       
    78 
       
    79 static bool tabBetweenSubWindowsIn(QMdiArea *mdiArea, int tabCount = -1, bool reverse = false)
       
    80 {
       
    81     if (!mdiArea) {
       
    82         qWarning("Null pointer to mdi area");
       
    83         return false;
       
    84     }
       
    85 
       
    86     QList<QMdiSubWindow *> subWindows = mdiArea->subWindowList();
       
    87     const bool walkThrough = tabCount == -1;
       
    88 
       
    89     if (walkThrough) {
       
    90         QMdiSubWindow *active = reverse ? subWindows.front() : subWindows.back();
       
    91         mdiArea->setActiveSubWindow(active);
       
    92         if (mdiArea->activeSubWindow() != active) {
       
    93             qWarning("Failed to set active sub window");
       
    94             return false;
       
    95         }
       
    96         tabCount = subWindows.size();
       
    97     }
       
    98 
       
    99     QWidget *focusWidget = qApp->focusWidget();
       
   100     if (!focusWidget) {
       
   101         qWarning("No focus widget");
       
   102         return false;
       
   103     }
       
   104 
       
   105     Qt::KeyboardModifiers modifiers = reverse ? Qt::ShiftModifier : Qt::NoModifier;
       
   106     Qt::Key key;
       
   107 #ifdef Q_WS_MAC
       
   108     key = Qt::Key_Meta;
       
   109     modifiers |= Qt::MetaModifier;
       
   110 #else
       
   111     key = Qt::Key_Control;
       
   112     modifiers |= Qt::ControlModifier;
       
   113 #endif
       
   114 
       
   115     QTest::keyPress(focusWidget, key, modifiers);
       
   116     for (int i = 0; i < tabCount; ++i) {
       
   117         QTest::keyPress(focusWidget, reverse ? Qt::Key_Backtab : Qt::Key_Tab, modifiers);
       
   118         if (tabCount > 1)
       
   119             QTest::qWait(500);
       
   120         if (walkThrough) {
       
   121             QRubberBand *rubberBand = qFindChild<QRubberBand *>(mdiArea->viewport());
       
   122             if (!rubberBand) {
       
   123                 qWarning("No rubber band");
       
   124                 return false;
       
   125             }
       
   126             QMdiSubWindow *subWindow = subWindows.at(reverse ? subWindows.size() -1 - i : i);
       
   127             if (rubberBand->geometry() != subWindow->geometry()) {
       
   128                 qWarning("Rubber band has different geometry");
       
   129                 return false;
       
   130             }
       
   131         }
       
   132         qApp->processEvents();
       
   133     }
       
   134     QTest::keyRelease(focusWidget, key);
       
   135 
       
   136     return true;
       
   137 }
       
   138 
       
   139 static inline QTabBar::Shape tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position)
       
   140 {
       
   141     const bool rounded = (shape == QTabWidget::Rounded);
       
   142     if (position == QTabWidget::North)
       
   143         return rounded ? QTabBar::RoundedNorth : QTabBar::TriangularNorth;
       
   144     if (position == QTabWidget::South)
       
   145         return rounded ? QTabBar::RoundedSouth : QTabBar::TriangularSouth;
       
   146     if (position == QTabWidget::East)
       
   147         return rounded ? QTabBar::RoundedEast : QTabBar::TriangularEast;
       
   148     if (position == QTabWidget::West)
       
   149         return rounded ? QTabBar::RoundedWest : QTabBar::TriangularWest;
       
   150     return QTabBar::RoundedNorth;
       
   151 }
       
   152 
       
   153 enum Arrangement {
       
   154     Tiled,
       
   155     Cascaded
       
   156 };
       
   157 
       
   158 static bool verifyArrangement(QMdiArea *mdiArea, Arrangement arrangement, const QList<int> &expectedIndices)
       
   159 {
       
   160     if (!mdiArea || expectedIndices.isEmpty() || mdiArea->subWindowList().isEmpty())
       
   161         return false;
       
   162 
       
   163     const QList<QMdiSubWindow *> subWindows = mdiArea->subWindowList();
       
   164     const QMdiSubWindow *const firstSubWindow = subWindows.at(0);
       
   165 
       
   166     switch (arrangement) {
       
   167     case Tiled:
       
   168     {
       
   169         // Calculate the number of rows and columns.
       
   170         const int n = subWindows.count();
       
   171         const int numColumns = qMax(qCeil(qSqrt(qreal(n))), 1);
       
   172         const int numRows = qMax((n % numColumns) ? (n / numColumns + 1) : (n / numColumns), 1);
       
   173 
       
   174         // Ensure that the geometry of all the subwindows are as expected by using
       
   175         // QWidget::childAt starting from the middle of the topleft cell and subsequently
       
   176         // adding rowWidth and rowHeight (going from left to right).
       
   177         const int columnWidth = mdiArea->viewport()->width() / numColumns;
       
   178         const int rowHeight = mdiArea->viewport()->height() / numRows;
       
   179         QPoint subWindowPos(columnWidth / 2, rowHeight / 2);
       
   180         for (int i = 0; i < numRows; ++i) {
       
   181             for (int j = 0; j < numColumns; ++j) {
       
   182                 const int index = expectedIndices.at(i * numColumns + j);
       
   183                 QWidget *actual = mdiArea->viewport()->childAt(subWindowPos);
       
   184                 QMdiSubWindow *expected = subWindows.at(index);
       
   185                 if (actual != expected && !expected->isAncestorOf(actual))
       
   186                     return false;
       
   187                 subWindowPos.rx() += columnWidth;
       
   188             }
       
   189             subWindowPos.rx() = columnWidth / 2;
       
   190             subWindowPos.ry() += rowHeight;
       
   191         }
       
   192         break;
       
   193     }
       
   194     case Cascaded:
       
   195     {
       
   196         // Calculate the delta (dx, dy) between two cascaded subwindows.
       
   197         QStyleOptionTitleBar options;
       
   198         options.initFrom(firstSubWindow);
       
   199         int titleBarHeight = firstSubWindow->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
       
   200 #ifdef Q_WS_MAC
       
   201         // ### Remove this after the mac style has been fixed
       
   202         if (qobject_cast<QMacStyle *>(firstSubWindow->style()))
       
   203             titleBarHeight -= 4;
       
   204 #endif
       
   205         const QFontMetrics fontMetrics = QFontMetrics(QApplication::font("QWorkspaceTitleBar"));
       
   206         const int dy = qMax(titleBarHeight - (titleBarHeight - fontMetrics.height()) / 2, 1);
       
   207         const int dx = 10;
       
   208 
       
   209         // Current activation/stacking order.
       
   210         const QList<QMdiSubWindow *> activationOrderList = mdiArea->subWindowList(QMdiArea::ActivationHistoryOrder);
       
   211 
       
   212         // Ensure that the geometry of all the subwindows are as expected by using
       
   213         // QWidget::childAt with the position of the first one and subsequently adding
       
   214         // dx and dy.
       
   215         QPoint subWindowPos(20, 5);
       
   216         foreach (int expectedIndex, expectedIndices) {
       
   217             QMdiSubWindow *expected = subWindows.at(expectedIndex);
       
   218             expected->raise();
       
   219             if (mdiArea->viewport()->childAt(subWindowPos) != expected)
       
   220                 return false;
       
   221             expected->lower();
       
   222             subWindowPos.rx() += dx;
       
   223             subWindowPos.ry() += dy;
       
   224         }
       
   225 
       
   226         // Restore stacking order.
       
   227         foreach (QMdiSubWindow *subWindow, activationOrderList) {
       
   228             mdiArea->setActiveSubWindow(subWindow);
       
   229             qApp->processEvents();
       
   230         }
       
   231         break;
       
   232     }
       
   233     default:
       
   234         return false;
       
   235     }
       
   236     return true;
       
   237 }
       
   238 
       
   239 class tst_QMdiArea : public QObject
       
   240 {
       
   241     Q_OBJECT
       
   242 public:
       
   243     tst_QMdiArea();
       
   244 public slots:
       
   245     void initTestCase();
       
   246 protected slots:
       
   247     void activeChanged(QMdiSubWindow *child);
       
   248 
       
   249 private slots:
       
   250     // Tests from QWorkspace
       
   251     void subWindowActivated_data();
       
   252     void subWindowActivated();
       
   253     void subWindowActivated2();
       
   254     void subWindowActivatedWithMinimize();
       
   255     void showWindows();
       
   256     void changeWindowTitle();
       
   257     void changeModified();
       
   258     void childSize();
       
   259     void fixedSize();
       
   260     // New tests
       
   261     void minimumSizeHint();
       
   262     void sizeHint();
       
   263     void setActiveSubWindow();
       
   264     void activeSubWindow();
       
   265     void currentSubWindow();
       
   266     void addAndRemoveWindows();
       
   267     void addAndRemoveWindowsWithReparenting();
       
   268     void removeSubWindow_2();
       
   269     void closeWindows();
       
   270     void activateNextAndPreviousWindow();
       
   271     void subWindowList_data();
       
   272     void subWindowList();
       
   273     void setBackground();
       
   274     void setViewport();
       
   275     void tileSubWindows();
       
   276     void cascadeAndTileSubWindows();
       
   277     void resizeMaximizedChildWindows_data();
       
   278     void resizeMaximizedChildWindows();
       
   279     void focusWidgetAfterAddSubWindow();
       
   280     void dontMaximizeSubWindowOnActivation();
       
   281     void delayedPlacement();
       
   282     void iconGeometryInMenuBar();
       
   283     void resizeTimer();
       
   284     void updateScrollBars();
       
   285     void setActivationOrder_data();
       
   286     void setActivationOrder();
       
   287     void tabBetweenSubWindows();
       
   288     void setViewMode();
       
   289     void setTabShape();
       
   290     void setTabPosition_data();
       
   291     void setTabPosition();
       
   292 #if defined(Q_WS_WIN) || defined(Q_WS_X11)
       
   293     void nativeSubWindows();
       
   294 #endif
       
   295     void task_209615();
       
   296     void task_236750();
       
   297 
       
   298 private:
       
   299     QMdiSubWindow *activeWindow;
       
   300     bool accelPressed;
       
   301 };
       
   302 
       
   303 tst_QMdiArea::tst_QMdiArea()
       
   304     : activeWindow(0)
       
   305 {
       
   306     qRegisterMetaType<QMdiSubWindow *>();
       
   307 }
       
   308 
       
   309 void tst_QMdiArea::initTestCase()
       
   310 {
       
   311 #ifdef Q_OS_WINCE //disable magic for WindowsCE
       
   312     qApp->setAutoMaximizeThreshold(-1);
       
   313 #endif
       
   314 }
       
   315 
       
   316 // Old QWorkspace tests
       
   317 void tst_QMdiArea::activeChanged(QMdiSubWindow *child)
       
   318 {
       
   319     activeWindow = child;
       
   320 }
       
   321 
       
   322 void tst_QMdiArea::subWindowActivated_data()
       
   323 {
       
   324     // define the test elements we're going to use
       
   325     QTest::addColumn<int>("count");
       
   326 
       
   327     // create a first testdata instance and fill it with data
       
   328     QTest::newRow( "data0" ) << 0;
       
   329     QTest::newRow( "data1" ) << 1;
       
   330     QTest::newRow( "data2" ) << 2;
       
   331 }
       
   332 
       
   333 void tst_QMdiArea::subWindowActivated()
       
   334 {
       
   335     QMainWindow mw(0) ;
       
   336     mw.menuBar();
       
   337     QMdiArea *workspace = new QMdiArea(&mw);
       
   338     workspace->setObjectName(QLatin1String("testWidget"));
       
   339     mw.setCentralWidget(workspace);
       
   340     QSignalSpy spy(workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
       
   341     connect( workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
       
   342     mw.show();
       
   343     qApp->setActiveWindow(&mw);
       
   344 
       
   345     QFETCH( int, count );
       
   346     int i;
       
   347 
       
   348     for ( i = 0; i < count; ++i ) {
       
   349         QWidget *widget = new QWidget(workspace, 0);
       
   350         widget->setAttribute(Qt::WA_DeleteOnClose);
       
   351         workspace->addSubWindow(widget)->show();
       
   352         widget->show();
       
   353         qApp->processEvents();
       
   354         QVERIFY( activeWindow == workspace->activeSubWindow() );
       
   355         QCOMPARE(spy.count(), 1);
       
   356         spy.clear();
       
   357     }
       
   358 
       
   359     QList<QMdiSubWindow *> windows = workspace->subWindowList();
       
   360     QCOMPARE( (int)windows.count(), count );
       
   361 
       
   362     for ( i = 0; i < count; ++i ) {
       
   363         QMdiSubWindow *window = windows.at(i);
       
   364         window->showMinimized();
       
   365         qApp->processEvents();
       
   366         QVERIFY( activeWindow == workspace->activeSubWindow() );
       
   367         if ( i == 1 )
       
   368             QVERIFY( activeWindow == window );
       
   369     }
       
   370 
       
   371     for ( i = 0; i < count; ++i ) {
       
   372         QMdiSubWindow *window = windows.at(i);
       
   373         window->showNormal();
       
   374         qApp->processEvents();
       
   375         QVERIFY( window == activeWindow );
       
   376         QVERIFY( activeWindow == workspace->activeSubWindow() );
       
   377     }
       
   378     spy.clear();
       
   379 
       
   380     while (workspace->activeSubWindow() ) {
       
   381         workspace->activeSubWindow()->close();
       
   382         qApp->processEvents();
       
   383         QVERIFY(activeWindow == workspace->activeSubWindow());
       
   384         QCOMPARE(spy.count(), 1);
       
   385         spy.clear();
       
   386     }
       
   387 
       
   388     QVERIFY(activeWindow == 0);
       
   389     QVERIFY(workspace->activeSubWindow() == 0);
       
   390     QCOMPARE(workspace->subWindowList().count(), 0);
       
   391 
       
   392     {
       
   393         workspace->hide();
       
   394         QWidget *widget = new QWidget(workspace);
       
   395         widget->setAttribute(Qt::WA_DeleteOnClose);
       
   396         QMdiSubWindow *window = workspace->addSubWindow(widget);
       
   397         widget->show();
       
   398         QCOMPARE(spy.count(), 0);
       
   399         workspace->show();
       
   400         QCOMPARE(spy.count(), 1);
       
   401         spy.clear();
       
   402         QVERIFY( activeWindow == window );
       
   403         window->close();
       
   404         qApp->processEvents();
       
   405         QCOMPARE(spy.count(), 1);
       
   406         spy.clear();
       
   407         QVERIFY( activeWindow == 0 );
       
   408     }
       
   409 
       
   410     {
       
   411         workspace->hide();
       
   412         QWidget *widget = new QWidget(workspace);
       
   413         widget->setAttribute(Qt::WA_DeleteOnClose);
       
   414         QMdiSubWindow *window = workspace->addSubWindow(widget);
       
   415         widget->showMaximized();
       
   416         qApp->sendPostedEvents();
       
   417         QCOMPARE(spy.count(), 0);
       
   418         spy.clear();
       
   419         workspace->show();
       
   420         QCOMPARE(spy.count(), 1);
       
   421         spy.clear();
       
   422         QVERIFY( activeWindow == window );
       
   423         window->close();
       
   424         qApp->processEvents();
       
   425         QCOMPARE(spy.count(), 1);
       
   426         spy.clear();
       
   427         QVERIFY( activeWindow == 0 );
       
   428     }
       
   429 
       
   430     {
       
   431         QWidget *widget = new QWidget(workspace);
       
   432         widget->setAttribute(Qt::WA_DeleteOnClose);
       
   433         QMdiSubWindow *window = workspace->addSubWindow(widget);
       
   434         widget->showMinimized();
       
   435         QCOMPARE(spy.count(), 1);
       
   436         spy.clear();
       
   437         QVERIFY( activeWindow == window );
       
   438         QVERIFY(workspace->activeSubWindow() == window);
       
   439         window->close();
       
   440         qApp->processEvents();
       
   441         QCOMPARE(spy.count(), 1);
       
   442         spy.clear();
       
   443         QVERIFY(workspace->activeSubWindow() == 0);
       
   444         QVERIFY( activeWindow == 0 );
       
   445     }
       
   446 }
       
   447 
       
   448 #ifdef Q_WS_MAC
       
   449 #include <Security/AuthSession.h>
       
   450 bool macHasAccessToWindowsServer()
       
   451 {
       
   452     SecuritySessionId mySession;
       
   453     SessionAttributeBits sessionInfo;
       
   454     SessionGetInfo(callerSecuritySession, &mySession, &sessionInfo);
       
   455     return (sessionInfo & sessionHasGraphicAccess);
       
   456 }
       
   457 #endif
       
   458 
       
   459 
       
   460 void tst_QMdiArea::subWindowActivated2()
       
   461 {
       
   462     QMdiArea mdiArea;
       
   463     QSignalSpy spy(&mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)));
       
   464     for (int i = 0; i < 5; ++i)
       
   465         mdiArea.addSubWindow(new QWidget);
       
   466     QCOMPARE(spy.count(), 0);
       
   467     mdiArea.show();
       
   468 #ifdef Q_WS_X11
       
   469     qt_x11_wait_for_window_manager(&mdiArea);
       
   470 #endif
       
   471     QTest::qWait(100);
       
   472 
       
   473     QTRY_COMPARE(spy.count(), 5);
       
   474     QCOMPARE(mdiArea.activeSubWindow(), mdiArea.subWindowList().back());
       
   475     spy.clear();
       
   476 
       
   477     // Just to make sure another widget is on top wrt. stacking order.
       
   478     // This will typically become the active window if things are broken.
       
   479     QMdiSubWindow *staysOnTopWindow = mdiArea.subWindowList().at(3);
       
   480     staysOnTopWindow->setWindowFlags(Qt::WindowStaysOnTopHint);
       
   481     mdiArea.setActiveSubWindow(staysOnTopWindow);
       
   482     QCOMPARE(spy.count(), 1);
       
   483     QCOMPARE(mdiArea.activeSubWindow(), staysOnTopWindow);
       
   484     spy.clear();
       
   485 
       
   486     QMdiSubWindow *activeSubWindow = mdiArea.subWindowList().at(2);
       
   487     mdiArea.setActiveSubWindow(activeSubWindow);
       
   488     QCOMPARE(spy.count(), 1);
       
   489     QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow);
       
   490     spy.clear();
       
   491 
       
   492     // Check that we only emit _one_ signal and the active window
       
   493     // is unchanged after hide/show.
       
   494     mdiArea.hide();
       
   495 #ifdef Q_WS_X11
       
   496     qt_x11_wait_for_window_manager(&mdiArea);
       
   497 #endif
       
   498     QTest::qWait(100);
       
   499     QTRY_COMPARE(spy.count(), 1);
       
   500     QVERIFY(!mdiArea.activeSubWindow());
       
   501     QCOMPARE(mdiArea.currentSubWindow(), activeSubWindow);
       
   502     spy.clear();
       
   503 
       
   504     mdiArea.show();
       
   505 #ifdef Q_WS_X11
       
   506     qt_x11_wait_for_window_manager(&mdiArea);
       
   507 #endif
       
   508     QTest::qWait(100);
       
   509     QTRY_COMPARE(spy.count(), 1);
       
   510     QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow);
       
   511     spy.clear();
       
   512 
       
   513     // Check that we only emit _one_ signal and the active window
       
   514     // is unchanged after showMinimized/showNormal.
       
   515     mdiArea.showMinimized();
       
   516 #ifdef Q_WS_X11
       
   517     qt_x11_wait_for_window_manager(&mdiArea);
       
   518 #elif defined (Q_WS_MAC)
       
   519     if (!macHasAccessToWindowsServer())
       
   520         QEXPECT_FAIL("", "showMinimized doesn't really minimize if you don't have access to the server", Abort);
       
   521 #endif
       
   522     QTest::qWait(10);
       
   523 #if defined(Q_WS_QWS)
       
   524     QEXPECT_FAIL("", "task 168682", Abort);
       
   525 #endif
       
   526 #ifdef Q_OS_WINCE
       
   527     QSKIP("Not fixed yet. See Task 197453", SkipAll);
       
   528 #endif
       
   529     QTRY_COMPARE(spy.count(), 1);
       
   530     QVERIFY(!mdiArea.activeSubWindow());
       
   531     QCOMPARE(mdiArea.currentSubWindow(), activeSubWindow);
       
   532     spy.clear();
       
   533 
       
   534     mdiArea.showNormal();
       
   535 #ifdef Q_WS_X11
       
   536     qt_x11_wait_for_window_manager(&mdiArea);
       
   537 #endif
       
   538     QTest::qWait(100);
       
   539     QTRY_COMPARE(spy.count(), 1);
       
   540     QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow);
       
   541     spy.clear();
       
   542 }
       
   543 
       
   544 void tst_QMdiArea::subWindowActivatedWithMinimize()
       
   545 {
       
   546     QMainWindow mw(0) ;
       
   547     mw.menuBar();
       
   548     QMdiArea *workspace = new QMdiArea(&mw);
       
   549     workspace->setObjectName(QLatin1String("testWidget"));
       
   550     mw.setCentralWidget(workspace);
       
   551     QSignalSpy spy(workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
       
   552     connect( workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)) );
       
   553     mw.show();
       
   554     qApp->setActiveWindow(&mw);
       
   555     QWidget *widget = new QWidget(workspace);
       
   556     widget->setAttribute(Qt::WA_DeleteOnClose);
       
   557     QMdiSubWindow *window1 = workspace->addSubWindow(widget);
       
   558     QWidget *widget2 = new QWidget(workspace);
       
   559     widget2->setAttribute(Qt::WA_DeleteOnClose);
       
   560     QMdiSubWindow *window2 = workspace->addSubWindow(widget2);
       
   561 
       
   562     widget->showMinimized();
       
   563     QVERIFY( activeWindow == window1 );
       
   564     widget2->showMinimized();
       
   565     QVERIFY( activeWindow == window2 );
       
   566 
       
   567     window2->close();
       
   568     qApp->processEvents();
       
   569     QVERIFY( activeWindow == window1 );
       
   570 
       
   571     window1->close();
       
   572     qApp->processEvents();
       
   573     QVERIFY(workspace->activeSubWindow() == 0);
       
   574     QVERIFY( activeWindow == 0 );
       
   575 
       
   576     QVERIFY( workspace->subWindowList().count() == 0 );
       
   577 }
       
   578 
       
   579 void tst_QMdiArea::showWindows()
       
   580 {
       
   581     QMdiArea *ws = new QMdiArea( 0 );
       
   582 
       
   583     QWidget *widget = 0;
       
   584     ws->show();
       
   585 
       
   586     widget = new QWidget(ws);
       
   587     widget->show();
       
   588     QVERIFY( widget->isVisible() );
       
   589 
       
   590     widget = new QWidget(ws);
       
   591     widget->showMaximized();
       
   592     QVERIFY( widget->isMaximized() );
       
   593     widget->showNormal();
       
   594     QVERIFY( !widget->isMaximized() );
       
   595 
       
   596     widget = new QWidget(ws);
       
   597     widget->showMinimized();
       
   598     QVERIFY( widget->isMinimized() );
       
   599     widget->showNormal();
       
   600     QVERIFY( !widget->isMinimized() );
       
   601 
       
   602     ws->hide();
       
   603 
       
   604     widget = new QWidget(ws);
       
   605     ws->show();
       
   606     QVERIFY( widget->isVisible() );
       
   607 
       
   608     ws->hide();
       
   609 
       
   610     widget = new QWidget(ws);
       
   611     widget->showMaximized();
       
   612     QVERIFY( widget->isMaximized() );
       
   613     ws->show();
       
   614     QVERIFY( widget->isVisible() );
       
   615     QVERIFY( widget->isMaximized() );
       
   616     ws->hide();
       
   617 
       
   618     widget = new QWidget(ws);
       
   619     widget->showMinimized();
       
   620     ws->show();
       
   621     QVERIFY( widget->isMinimized() );
       
   622     ws->hide();
       
   623 
       
   624     delete ws;
       
   625 }
       
   626 
       
   627 
       
   628 //#define USE_SHOW
       
   629 
       
   630 void tst_QMdiArea::changeWindowTitle()
       
   631 {
       
   632     const QString mwc = QString::fromLatin1("MainWindow's Caption");
       
   633     const QString mwc2 = QString::fromLatin1("MainWindow's New Caption");
       
   634     const QString wc = QString::fromLatin1("Widget's Caption");
       
   635     const QString wc2 = QString::fromLatin1("Widget's New Caption");
       
   636 
       
   637     QMainWindow *mw = new QMainWindow;
       
   638     mw->setWindowTitle( mwc );
       
   639     QMdiArea *ws = new QMdiArea( mw );
       
   640     mw->setCentralWidget( ws );
       
   641     mw->menuBar();
       
   642     mw->show();
       
   643     QTest::qWaitForWindowShown(mw);
       
   644 
       
   645     QWidget *widget = new QWidget( ws );
       
   646     widget->setWindowTitle( wc );
       
   647     ws->addSubWindow(widget);
       
   648 
       
   649     QCOMPARE( mw->windowTitle(), mwc );
       
   650 
       
   651 #ifdef USE_SHOW
       
   652     widget->showMaximized();
       
   653 #else
       
   654     widget->setWindowState(Qt::WindowMaximized);
       
   655 #endif
       
   656 #if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
       
   657     QTRY_COMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc) );
       
   658 #endif
       
   659 
       
   660     mw->hide();
       
   661     qApp->processEvents();
       
   662     mw->show();
       
   663     qApp->processEvents();
       
   664     QTest::qWaitForWindowShown(mw);
       
   665 
       
   666 #if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
       
   667     QTRY_COMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc) );
       
   668 #endif
       
   669 
       
   670 #ifdef USE_SHOW
       
   671     widget->showNormal();
       
   672 #else
       
   673     widget->setWindowState(Qt::WindowNoState);
       
   674 #endif
       
   675     qApp->processEvents();
       
   676     QCOMPARE( mw->windowTitle(), mwc );
       
   677 
       
   678 #ifdef USE_SHOW
       
   679     widget->showMaximized();
       
   680 #else
       
   681     widget->setWindowState(Qt::WindowMaximized);
       
   682 #endif
       
   683     qApp->processEvents();
       
   684 #if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
       
   685     QTRY_COMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc) );
       
   686     widget->setWindowTitle( wc2 );
       
   687     QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc2) );
       
   688     mw->setWindowTitle( mwc2 );
       
   689     QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc2).arg(wc2) );
       
   690 #endif
       
   691 
       
   692     mw->show();
       
   693     qApp->setActiveWindow(mw);
       
   694 
       
   695 #ifdef USE_SHOW
       
   696     mw->showFullScreen();
       
   697 #else
       
   698     mw->setWindowState(Qt::WindowFullScreen);
       
   699 #endif
       
   700 
       
   701     qApp->processEvents();
       
   702 #if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
       
   703     QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc2).arg(wc2) );
       
   704 #endif
       
   705 #ifdef USE_SHOW
       
   706     widget->showNormal();
       
   707 #else
       
   708     widget->setWindowState(Qt::WindowNoState);
       
   709 #endif
       
   710     qApp->processEvents();
       
   711 #if defined(Q_WS_MAC) || defined(Q_OS_WINCE)
       
   712     QCOMPARE(mw->windowTitle(), mwc);
       
   713 #else
       
   714     QCOMPARE( mw->windowTitle(), mwc2 );
       
   715 #endif
       
   716 
       
   717 #ifdef USE_SHOW
       
   718     widget->showMaximized();
       
   719 #else
       
   720     widget->setWindowState(Qt::WindowMaximized);
       
   721 #endif
       
   722     qApp->processEvents();
       
   723 #if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
       
   724     QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc2).arg(wc2) );
       
   725 #endif
       
   726 
       
   727 #ifdef USE_SHOW
       
   728     mw->showNormal();
       
   729 #else
       
   730     mw->setWindowState(Qt::WindowNoState);
       
   731 #endif
       
   732     qApp->processEvents();
       
   733 #ifdef USE_SHOW
       
   734     widget->showNormal();
       
   735 #else
       
   736     widget->setWindowState(Qt::WindowNoState);
       
   737 #endif
       
   738 
       
   739     delete mw;
       
   740 }
       
   741 
       
   742 void tst_QMdiArea::changeModified()
       
   743 {
       
   744     const QString mwc = QString::fromLatin1("MainWindow's Caption");
       
   745     const QString wc = QString::fromLatin1("Widget's Caption[*]");
       
   746 
       
   747     QMainWindow *mw = new QMainWindow(0);
       
   748     mw->setWindowTitle( mwc );
       
   749     QMdiArea *ws = new QMdiArea( mw );
       
   750     mw->setCentralWidget( ws );
       
   751     mw->menuBar();
       
   752     mw->show();
       
   753 
       
   754     QWidget *widget = new QWidget( ws );
       
   755     widget->setWindowTitle( wc );
       
   756     ws->addSubWindow(widget);
       
   757 
       
   758     QCOMPARE( mw->isWindowModified(), false);
       
   759     QCOMPARE( widget->isWindowModified(), false);
       
   760     widget->setWindowState(Qt::WindowMaximized);
       
   761     QCOMPARE( mw->isWindowModified(), false);
       
   762     QCOMPARE( widget->isWindowModified(), false);
       
   763 
       
   764     widget->setWindowState(Qt::WindowNoState);
       
   765     QCOMPARE( mw->isWindowModified(), false);
       
   766     QCOMPARE( widget->isWindowModified(), false);
       
   767 
       
   768     widget->setWindowModified(true);
       
   769     QCOMPARE( mw->isWindowModified(), false);
       
   770     QCOMPARE( widget->isWindowModified(), true);
       
   771     widget->setWindowState(Qt::WindowMaximized);
       
   772 #if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
       
   773     QCOMPARE( mw->isWindowModified(), true);
       
   774 #endif
       
   775     QCOMPARE( widget->isWindowModified(), true);
       
   776 
       
   777     widget->setWindowState(Qt::WindowNoState);
       
   778     QCOMPARE( mw->isWindowModified(), false);
       
   779     QCOMPARE( widget->isWindowModified(), true);
       
   780 
       
   781     widget->setWindowState(Qt::WindowMaximized);
       
   782 #if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
       
   783     QCOMPARE( mw->isWindowModified(), true);
       
   784 #endif
       
   785     QCOMPARE( widget->isWindowModified(), true);
       
   786 
       
   787     widget->setWindowModified(false);
       
   788     QCOMPARE( mw->isWindowModified(), false);
       
   789     QCOMPARE( widget->isWindowModified(), false);
       
   790 
       
   791     widget->setWindowModified(true);
       
   792 #if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
       
   793     QCOMPARE( mw->isWindowModified(), true);
       
   794 #endif
       
   795     QCOMPARE( widget->isWindowModified(), true);
       
   796 
       
   797     widget->setWindowState(Qt::WindowNoState);
       
   798     QCOMPARE( mw->isWindowModified(), false);
       
   799     QCOMPARE( widget->isWindowModified(), true);
       
   800 
       
   801     delete mw;
       
   802 }
       
   803 
       
   804 class MyChild : public QWidget
       
   805 {
       
   806 public:
       
   807     MyChild(QWidget *parent = 0) : QWidget(parent) {}
       
   808     QSize sizeHint() const { return QSize(234, 123); }
       
   809 };
       
   810 
       
   811 void tst_QMdiArea::childSize()
       
   812 {
       
   813     QMdiArea ws;
       
   814 
       
   815     MyChild *child = new MyChild(&ws);
       
   816     child->show();
       
   817     QCOMPARE(child->size(), child->sizeHint());
       
   818     delete child;
       
   819 
       
   820     child = new MyChild(&ws);
       
   821     child->setFixedSize(200, 200);
       
   822     child->show();
       
   823     QCOMPARE(child->size(), child->minimumSize());
       
   824     delete child;
       
   825 
       
   826     child = new MyChild(&ws);
       
   827     child->resize(150, 150);
       
   828     child->show();
       
   829     QCOMPARE(child->size(), QSize(150,150));
       
   830     delete child;
       
   831 }
       
   832 
       
   833 void tst_QMdiArea::fixedSize()
       
   834 {
       
   835     QMdiArea *ws = new QMdiArea;
       
   836     int i;
       
   837 
       
   838     ws->resize(500, 500);
       
   839 //     ws->show();
       
   840 
       
   841     QSize fixed(300, 300);
       
   842     for (i = 0; i < 4; ++i) {
       
   843         QWidget *child = new QWidget(ws);
       
   844         child->setFixedSize(fixed);
       
   845         child->show();
       
   846     }
       
   847 
       
   848     QList<QMdiSubWindow *> windows = ws->subWindowList();
       
   849     for (i = 0; i < (int)windows.count(); ++i) {
       
   850         QMdiSubWindow *child = windows.at(i);
       
   851         QCOMPARE(child->size(), fixed);
       
   852     }
       
   853 
       
   854     ws->cascadeSubWindows();
       
   855     ws->resize(800, 800);
       
   856     for (i = 0; i < (int)windows.count(); ++i) {
       
   857         QMdiSubWindow *child = windows.at(i);
       
   858         QCOMPARE(child->size(), fixed);
       
   859     }
       
   860     ws->resize(500, 500);
       
   861 
       
   862     ws->tileSubWindows();
       
   863     ws->resize(800, 800);
       
   864     for (i = 0; i < (int)windows.count(); ++i) {
       
   865         QMdiSubWindow *child = windows.at(i);
       
   866         QCOMPARE(child->size(), fixed);
       
   867     }
       
   868     ws->resize(500, 500);
       
   869 
       
   870     for (i = 0; i < (int)windows.count(); ++i) {
       
   871         QMdiSubWindow *child = windows.at(i);
       
   872         delete child;
       
   873     }
       
   874 
       
   875     delete ws;
       
   876 }
       
   877 
       
   878 class LargeWidget : public QWidget
       
   879 {
       
   880 public:
       
   881     LargeWidget(QWidget *parent = 0) : QWidget(parent) {}
       
   882     QSize sizeHint() const { return QSize(1280, 1024); }
       
   883     QSize minimumSizeHint() const { return QSize(300, 300); }
       
   884 };
       
   885 
       
   886 // New tests
       
   887 void tst_QMdiArea::minimumSizeHint()
       
   888 {
       
   889     QMdiArea workspace;
       
   890     workspace.show();
       
   891     QSize expectedSize(workspace.style()->pixelMetric(QStyle::PM_MDIMinimizedWidth),
       
   892                        workspace.style()->pixelMetric(QStyle::PM_TitleBarHeight));
       
   893     qApp->processEvents();
       
   894     QAbstractScrollArea dummyScrollArea;
       
   895     dummyScrollArea.setFrameStyle(QFrame::NoFrame);
       
   896     expectedSize = expectedSize.expandedTo(dummyScrollArea.minimumSizeHint());
       
   897     QCOMPARE(workspace.minimumSizeHint(), expectedSize.expandedTo(qApp->globalStrut()));
       
   898 
       
   899     QWidget *window = workspace.addSubWindow(new QWidget);
       
   900     qApp->processEvents();
       
   901     window->show();
       
   902     QCOMPARE(workspace.minimumSizeHint(), expectedSize.expandedTo(window->minimumSizeHint()));
       
   903 
       
   904     QMdiSubWindow *subWindow = workspace.addSubWindow(new LargeWidget);
       
   905     subWindow->show();
       
   906     QCOMPARE(workspace.minimumSizeHint(), expectedSize.expandedTo(subWindow->minimumSizeHint()));
       
   907 
       
   908     workspace.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
       
   909     workspace.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
       
   910     QCOMPARE(workspace.minimumSizeHint(), expectedSize);
       
   911 }
       
   912 
       
   913 void tst_QMdiArea::sizeHint()
       
   914 {
       
   915     QMdiArea workspace;
       
   916     workspace.show();
       
   917     QSize desktopSize = QApplication::desktop()->size();
       
   918     QSize expectedSize(desktopSize.width() * 2/3, desktopSize.height() * 2/3);
       
   919     QCOMPARE(workspace.sizeHint(), expectedSize.expandedTo(qApp->globalStrut()));
       
   920 
       
   921     QWidget *window = workspace.addSubWindow(new QWidget);
       
   922     qApp->processEvents();
       
   923     window->show();
       
   924     QCOMPARE(workspace.sizeHint(), expectedSize.expandedTo(window->sizeHint()));
       
   925 
       
   926     QMdiSubWindow *nested = workspace.addSubWindow(new QMdiArea);
       
   927     expectedSize = QSize(desktopSize.width() * 2/6, desktopSize.height() * 2/6);
       
   928     QCOMPARE(nested->widget()->sizeHint(), expectedSize);
       
   929 }
       
   930 
       
   931 void tst_QMdiArea::setActiveSubWindow()
       
   932 {
       
   933     QMdiArea workspace;
       
   934     workspace.show();
       
   935 
       
   936     QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
       
   937     connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
       
   938     qApp->setActiveWindow(&workspace);
       
   939 
       
   940     // Activate hidden windows
       
   941     const int windowCount = 10;
       
   942     QMdiSubWindow *windows[windowCount];
       
   943     for (int i = 0; i < windowCount; ++i) {
       
   944         windows[i] = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
       
   945         qApp->processEvents();
       
   946         QVERIFY(windows[i]->isHidden());
       
   947         workspace.setActiveSubWindow(windows[i]);
       
   948     }
       
   949     QCOMPARE(spy.count(), 0);
       
   950     QVERIFY(!activeWindow);
       
   951     spy.clear();
       
   952 
       
   953     // Activate visible windows
       
   954     for (int i = 0; i < windowCount; ++i) {
       
   955         windows[i]->show();
       
   956         QVERIFY(!windows[i]->isHidden());
       
   957         workspace.setActiveSubWindow(windows[i]);
       
   958         qApp->processEvents();
       
   959         QCOMPARE(spy.count(), 1);
       
   960         QCOMPARE(activeWindow, windows[i]);
       
   961         spy.clear();
       
   962     }
       
   963 
       
   964     // Deactivate active window
       
   965     QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
       
   966     workspace.setActiveSubWindow(0);
       
   967     QCOMPARE(spy.count(), 1);
       
   968     QVERIFY(!activeWindow);
       
   969     QVERIFY(!workspace.activeSubWindow());
       
   970 
       
   971     // Activate widget which is not child of any window inside workspace
       
   972     QMdiSubWindow fakeWindow;
       
   973     QTest::ignoreMessage(QtWarningMsg, "QMdiArea::setActiveSubWindow: window is not inside workspace");
       
   974     workspace.setActiveSubWindow(&fakeWindow);
       
   975 
       
   976 }
       
   977 
       
   978 void tst_QMdiArea::activeSubWindow()
       
   979 {
       
   980     QMainWindow mainWindow;
       
   981 
       
   982     QMdiArea *mdiArea = new QMdiArea;
       
   983     QLineEdit *subWindowLineEdit = new QLineEdit;
       
   984     QMdiSubWindow *subWindow = mdiArea->addSubWindow(subWindowLineEdit);
       
   985     mainWindow.setCentralWidget(mdiArea);
       
   986 
       
   987     QDockWidget *dockWidget = new QDockWidget(QLatin1String("Dock Widget"), &mainWindow);
       
   988     dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea);
       
   989     QLineEdit *dockWidgetLineEdit = new QLineEdit;
       
   990     dockWidget->setWidget(dockWidgetLineEdit);
       
   991     mainWindow.addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
       
   992 
       
   993     mainWindow.show();
       
   994 #ifdef Q_WS_X11
       
   995     qt_x11_wait_for_window_manager(&mainWindow);
       
   996 #endif
       
   997 
       
   998     qApp->setActiveWindow(&mainWindow);
       
   999     QCOMPARE(mdiArea->activeSubWindow(), subWindow);
       
  1000     QCOMPARE(qApp->focusWidget(), (QWidget *)subWindowLineEdit);
       
  1001 
       
  1002     dockWidgetLineEdit->setFocus();
       
  1003     QCOMPARE(qApp->focusWidget(), (QWidget *)dockWidgetLineEdit);
       
  1004     QCOMPARE(mdiArea->activeSubWindow(), subWindow);
       
  1005 
       
  1006     QEvent deactivateEvent(QEvent::WindowDeactivate);
       
  1007     qApp->sendEvent(subWindow, &deactivateEvent);
       
  1008     QVERIFY(!mdiArea->activeSubWindow());
       
  1009     QCOMPARE(qApp->focusWidget(), (QWidget *)dockWidgetLineEdit);
       
  1010 
       
  1011     QEvent activateEvent(QEvent::WindowActivate);
       
  1012     qApp->sendEvent(subWindow, &activateEvent);
       
  1013     QCOMPARE(mdiArea->activeSubWindow(), subWindow);
       
  1014     QCOMPARE(qApp->focusWidget(), (QWidget *)subWindowLineEdit);
       
  1015 
       
  1016     QLineEdit dummyTopLevel;
       
  1017     dummyTopLevel.show();
       
  1018 #ifdef Q_WS_X11
       
  1019     qt_x11_wait_for_window_manager(&dummyTopLevel);
       
  1020 #endif
       
  1021 
       
  1022     qApp->setActiveWindow(&dummyTopLevel);
       
  1023     QCOMPARE(mdiArea->activeSubWindow(), subWindow);
       
  1024 
       
  1025     qApp->setActiveWindow(&mainWindow);
       
  1026     QCOMPARE(mdiArea->activeSubWindow(), subWindow);
       
  1027 
       
  1028 #if !defined(Q_WS_MAC) && !defined(Q_WS_WIN)
       
  1029     qApp->setActiveWindow(0);
       
  1030     QVERIFY(!mdiArea->activeSubWindow());
       
  1031 #endif
       
  1032 
       
  1033     //task 202657
       
  1034     dockWidgetLineEdit->setFocus();
       
  1035     qApp->setActiveWindow(&mainWindow);
       
  1036     QVERIFY(dockWidgetLineEdit->hasFocus());
       
  1037 }
       
  1038 
       
  1039 void tst_QMdiArea::currentSubWindow()
       
  1040 {
       
  1041     QMdiArea mdiArea;
       
  1042     mdiArea.show();
       
  1043 #ifdef Q_WS_X11
       
  1044     qt_x11_wait_for_window_manager(&mdiArea);
       
  1045 #endif
       
  1046 
       
  1047     for (int i = 0; i < 5; ++i)
       
  1048         mdiArea.addSubWindow(new QLineEdit)->show();
       
  1049 
       
  1050     qApp->setActiveWindow(&mdiArea);
       
  1051     QCOMPARE(qApp->activeWindow(), (QWidget *)&mdiArea);
       
  1052 
       
  1053     // Check that the last added window is the active and the current.
       
  1054     QMdiSubWindow *active = mdiArea.activeSubWindow();
       
  1055     QVERIFY(active);
       
  1056     QCOMPARE(mdiArea.subWindowList().back(), active);
       
  1057     QCOMPARE(mdiArea.currentSubWindow(), active);
       
  1058 
       
  1059     QLineEdit dummyTopLevel;
       
  1060     dummyTopLevel.show();
       
  1061 #ifdef Q_WS_X11
       
  1062     qt_x11_wait_for_window_manager(&dummyTopLevel);
       
  1063 #endif
       
  1064 
       
  1065     // Move focus to another top-level and check that we still
       
  1066     // have an active window.
       
  1067     qApp->setActiveWindow(&dummyTopLevel);
       
  1068     QCOMPARE(qApp->activeWindow(), (QWidget *)&dummyTopLevel);
       
  1069     QVERIFY(mdiArea.activeSubWindow());
       
  1070 
       
  1071     delete active;
       
  1072     active = 0;
       
  1073 
       
  1074     // We just deleted the current sub-window -> current should then
       
  1075     // be the next in list (which in this case is the first sub-window).
       
  1076     QVERIFY(mdiArea.currentSubWindow());
       
  1077     QCOMPARE(mdiArea.currentSubWindow(), mdiArea.subWindowList().front());
       
  1078 
       
  1079     // Activate mdi area and check that active == current.
       
  1080     qApp->setActiveWindow(&mdiArea);
       
  1081     active = mdiArea.activeSubWindow();
       
  1082     QVERIFY(active);
       
  1083     QCOMPARE(mdiArea.activeSubWindow(), mdiArea.subWindowList().front());
       
  1084 
       
  1085     active->hide();
       
  1086     QCOMPARE(mdiArea.activeSubWindow(), active);
       
  1087     QCOMPARE(mdiArea.currentSubWindow(), active);
       
  1088 
       
  1089     qApp->setActiveWindow(&dummyTopLevel);
       
  1090     QVERIFY(mdiArea.activeSubWindow());
       
  1091     QCOMPARE(mdiArea.currentSubWindow(), active);
       
  1092 
       
  1093     qApp->setActiveWindow(&mdiArea);
       
  1094     active->show();
       
  1095     QCOMPARE(mdiArea.activeSubWindow(), active);
       
  1096 
       
  1097     mdiArea.setActiveSubWindow(0);
       
  1098     QVERIFY(!mdiArea.activeSubWindow());
       
  1099     QVERIFY(!mdiArea.currentSubWindow());
       
  1100 
       
  1101     mdiArea.setActiveSubWindow(active);
       
  1102     QCOMPARE(mdiArea.activeSubWindow(), active);
       
  1103     QEvent windowDeactivate(QEvent::WindowDeactivate);
       
  1104     qApp->sendEvent(active, &windowDeactivate);
       
  1105     QVERIFY(!mdiArea.activeSubWindow());
       
  1106     QVERIFY(!mdiArea.currentSubWindow());
       
  1107 
       
  1108     QEvent windowActivate(QEvent::WindowActivate);
       
  1109     qApp->sendEvent(active, &windowActivate);
       
  1110     QVERIFY(mdiArea.activeSubWindow());
       
  1111     QVERIFY(mdiArea.currentSubWindow());
       
  1112 
       
  1113 #if !defined(Q_WS_MAC) && !defined(Q_WS_WIN)
       
  1114     qApp->setActiveWindow(0);
       
  1115     QVERIFY(!mdiArea.activeSubWindow());
       
  1116     QVERIFY(mdiArea.currentSubWindow());
       
  1117 #endif
       
  1118 }
       
  1119 
       
  1120 void tst_QMdiArea::addAndRemoveWindows()
       
  1121 {
       
  1122     QMdiArea workspace;
       
  1123     workspace.resize(800, 600);
       
  1124     workspace.show();
       
  1125 #ifdef Q_WS_X11
       
  1126     qt_x11_wait_for_window_manager(&workspace);
       
  1127 #endif
       
  1128 
       
  1129     { // addSubWindow with large widget
       
  1130     QCOMPARE(workspace.subWindowList().count(), 0);
       
  1131     QWidget *window = workspace.addSubWindow(new LargeWidget);
       
  1132     QVERIFY(window);
       
  1133     qApp->processEvents();
       
  1134     QCOMPARE(workspace.subWindowList().count(), 1);
       
  1135     QVERIFY(window->windowFlags() == DefaultWindowFlags);
       
  1136     QCOMPARE(window->size(), workspace.viewport()->size());
       
  1137     }
       
  1138 
       
  1139     { // addSubWindow, minimumSize set.
       
  1140     QMdiSubWindow *window = new QMdiSubWindow;
       
  1141     window->setMinimumSize(900, 900);
       
  1142     workspace.addSubWindow(window);
       
  1143     QVERIFY(window);
       
  1144     qApp->processEvents();
       
  1145     QCOMPARE(workspace.subWindowList().count(), 2);
       
  1146     QVERIFY(window->windowFlags() == DefaultWindowFlags);
       
  1147     QCOMPARE(window->size(), window->minimumSize());
       
  1148     }
       
  1149 
       
  1150     { // addSubWindow, resized
       
  1151     QMdiSubWindow *window = new QMdiSubWindow;
       
  1152     window->setWidget(new QWidget);
       
  1153     window->resize(1500, 1500);
       
  1154     workspace.addSubWindow(window);
       
  1155     QVERIFY(window);
       
  1156     qApp->processEvents();
       
  1157     QCOMPARE(workspace.subWindowList().count(), 3);
       
  1158     QVERIFY(window->windowFlags() == DefaultWindowFlags);
       
  1159     QCOMPARE(window->size(), QSize(1500, 1500));
       
  1160     }
       
  1161 
       
  1162     { // addSubWindow with 0 pointer
       
  1163     QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: null pointer to widget");
       
  1164     QWidget *window = workspace.addSubWindow(0);
       
  1165     QVERIFY(!window);
       
  1166     QCOMPARE(workspace.subWindowList().count(), 3);
       
  1167     }
       
  1168 
       
  1169     { // addChildWindow
       
  1170     QMdiSubWindow *window = new QMdiSubWindow;
       
  1171     workspace.addSubWindow(window);
       
  1172     qApp->processEvents();
       
  1173     QVERIFY(window->windowFlags() == DefaultWindowFlags);
       
  1174     window->setWidget(new QWidget);
       
  1175     QCOMPARE(workspace.subWindowList().count(), 4);
       
  1176     QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: window is already added");
       
  1177     workspace.addSubWindow(window);
       
  1178     }
       
  1179 
       
  1180     { // addChildWindow with 0 pointer
       
  1181     QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: null pointer to widget");
       
  1182     workspace.addSubWindow(0);
       
  1183     QCOMPARE(workspace.subWindowList().count(), 4);
       
  1184     }
       
  1185 
       
  1186     // removeSubWindow
       
  1187     foreach (QWidget *window, workspace.subWindowList()) {
       
  1188         workspace.removeSubWindow(window);
       
  1189         delete window;
       
  1190     }
       
  1191     QCOMPARE(workspace.subWindowList().count(), 0);
       
  1192 
       
  1193     // removeSubWindow with 0 pointer
       
  1194     QTest::ignoreMessage(QtWarningMsg, "QMdiArea::removeSubWindow: null pointer to widget");
       
  1195     workspace.removeSubWindow(0);
       
  1196 
       
  1197     workspace.addSubWindow(new QPushButton(QLatin1String("Dummy to make workspace non-empty")));
       
  1198     qApp->processEvents();
       
  1199     QCOMPARE(workspace.subWindowList().count(), 1);
       
  1200 
       
  1201     // removeSubWindow with window not inside workspace
       
  1202     QTest::ignoreMessage(QtWarningMsg,"QMdiArea::removeSubWindow: window is not inside workspace");
       
  1203     QMdiSubWindow *fakeWindow = new QMdiSubWindow;
       
  1204     workspace.removeSubWindow(fakeWindow);
       
  1205     delete fakeWindow;
       
  1206 
       
  1207     // Check that newly added windows don't occupy maximized windows'
       
  1208     // restore space.
       
  1209     workspace.closeAllSubWindows();
       
  1210     workspace.setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
       
  1211     workspace.show();
       
  1212     QMdiSubWindow *window1 = workspace.addSubWindow(new QWidget);
       
  1213     window1->show();
       
  1214     const QRect window1RestoreGeometry = window1->geometry();
       
  1215     QCOMPARE(window1RestoreGeometry.topLeft(), QPoint(0, 0));
       
  1216 
       
  1217     window1->showMinimized();
       
  1218 
       
  1219     // Occupy space.
       
  1220     QMdiSubWindow *window2 = workspace.addSubWindow(new QWidget);
       
  1221     window2->show();
       
  1222     const QRect window2RestoreGeometry = window2->geometry();
       
  1223     QCOMPARE(window2RestoreGeometry.topLeft(), QPoint(0, 0));
       
  1224 
       
  1225     window2->showMaximized();
       
  1226 
       
  1227     // Don't occupy space.
       
  1228     QMdiSubWindow *window3 = workspace.addSubWindow(new QWidget);
       
  1229     window3->show();
       
  1230     QCOMPARE(window3->geometry().topLeft(), QPoint(window2RestoreGeometry.right() + 1, 0));
       
  1231 }
       
  1232 
       
  1233 void tst_QMdiArea::addAndRemoveWindowsWithReparenting()
       
  1234 {
       
  1235     QMdiArea workspace;
       
  1236     QMdiSubWindow window(&workspace);
       
  1237     QVERIFY(window.windowFlags() == DefaultWindowFlags);
       
  1238 
       
  1239     // 0 because the window list contains widgets and not actual
       
  1240     // windows. Silly, but that's the behavior.
       
  1241     QCOMPARE(workspace.subWindowList().count(), 0);
       
  1242     window.setWidget(new QWidget);
       
  1243     qApp->processEvents();
       
  1244 
       
  1245     QCOMPARE(workspace.subWindowList().count(), 1);
       
  1246     window.setParent(0); // Will also reset window flags
       
  1247     QCOMPARE(workspace.subWindowList().count(), 0);
       
  1248     window.setParent(&workspace);
       
  1249     QCOMPARE(workspace.subWindowList().count(), 1);
       
  1250     QVERIFY(window.windowFlags() == DefaultWindowFlags);
       
  1251 
       
  1252     QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: window is already added");
       
  1253     workspace.addSubWindow(&window);
       
  1254     QCOMPARE(workspace.subWindowList().count(), 1);
       
  1255 }
       
  1256 
       
  1257 class MySubWindow : public QMdiSubWindow
       
  1258 {
       
  1259 public:
       
  1260     using QObject::receivers;
       
  1261 };
       
  1262 
       
  1263 static int numberOfConnectedSignals(MySubWindow *subWindow)
       
  1264 {
       
  1265     if (!subWindow)
       
  1266         return 0;
       
  1267 
       
  1268     int numConnectedSignals = 0;
       
  1269     for (int i = 0; i < subWindow->metaObject()->methodCount(); ++i) {
       
  1270         QMetaMethod method = subWindow->metaObject()->method(i);
       
  1271         if (method.methodType() == QMetaMethod::Signal) {
       
  1272             QString signature(QLatin1String("2"));
       
  1273             signature += QLatin1String(method.signature());
       
  1274             numConnectedSignals += subWindow->receivers(signature.toLatin1());
       
  1275         }
       
  1276     }
       
  1277     return numConnectedSignals;
       
  1278 }
       
  1279 
       
  1280 void tst_QMdiArea::removeSubWindow_2()
       
  1281 {
       
  1282     QMdiArea mdiArea;
       
  1283     MySubWindow *subWindow = new MySubWindow;
       
  1284     QCOMPARE(numberOfConnectedSignals(subWindow), 0);
       
  1285 
       
  1286     // Connected to aboutToActivate() and windowStateChanged().
       
  1287     mdiArea.addSubWindow(subWindow);
       
  1288     QVERIFY(numberOfConnectedSignals(subWindow) >= 2);
       
  1289 
       
  1290     // Ensure we disconnect from all signals.
       
  1291     mdiArea.removeSubWindow(subWindow);
       
  1292     QCOMPARE(numberOfConnectedSignals(subWindow), 0);
       
  1293 
       
  1294     mdiArea.addSubWindow(subWindow);
       
  1295     QVERIFY(numberOfConnectedSignals(subWindow) >= 2);
       
  1296     subWindow->setParent(0);
       
  1297     QCOMPARE(numberOfConnectedSignals(subWindow), 0);
       
  1298 }
       
  1299 
       
  1300 void tst_QMdiArea::closeWindows()
       
  1301 {
       
  1302     QMdiArea workspace;
       
  1303     workspace.show();
       
  1304     qApp->setActiveWindow(&workspace);
       
  1305 
       
  1306     // Close widget
       
  1307     QWidget *widget = new QWidget;
       
  1308     QMdiSubWindow *subWindow = workspace.addSubWindow(widget);
       
  1309     qApp->processEvents();
       
  1310     QCOMPARE(workspace.subWindowList().count(), 1);
       
  1311     subWindow->close();
       
  1312     QCOMPARE(workspace.subWindowList().count(), 0);
       
  1313 
       
  1314     // Close window
       
  1315     QWidget *window = workspace.addSubWindow(new QWidget);
       
  1316     qApp->processEvents();
       
  1317     QCOMPARE(workspace.subWindowList().count(), 1);
       
  1318     window->close();
       
  1319     qApp->processEvents();
       
  1320     QCOMPARE(workspace.subWindowList().count(), 0);
       
  1321 
       
  1322     const int windowCount = 10;
       
  1323 
       
  1324     // Close active window
       
  1325     for (int i = 0; i < windowCount; ++i)
       
  1326         workspace.addSubWindow(new QWidget)->show();
       
  1327     qApp->processEvents();
       
  1328     QCOMPARE(workspace.subWindowList().count(), windowCount);
       
  1329     int activeSubWindowCount = 0;
       
  1330     while (workspace.activeSubWindow()) {
       
  1331         workspace.activeSubWindow()->close();
       
  1332         qApp->processEvents();
       
  1333         ++activeSubWindowCount;
       
  1334     }
       
  1335     QCOMPARE(activeSubWindowCount, windowCount);
       
  1336     QCOMPARE(workspace.subWindowList().count(), 0);
       
  1337 
       
  1338     // Close all windows
       
  1339     for (int i = 0; i < windowCount; ++i)
       
  1340         workspace.addSubWindow(new QWidget)->show();
       
  1341     qApp->processEvents();
       
  1342     QCOMPARE(workspace.subWindowList().count(), windowCount);
       
  1343     QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
       
  1344     connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
       
  1345     workspace.closeAllSubWindows();
       
  1346     qApp->processEvents();
       
  1347     QCOMPARE(workspace.subWindowList().count(), 0);
       
  1348     QCOMPARE(spy.count(), 1);
       
  1349     QVERIFY(!activeWindow);
       
  1350 }
       
  1351 
       
  1352 void tst_QMdiArea::activateNextAndPreviousWindow()
       
  1353 {
       
  1354     QMdiArea workspace;
       
  1355     workspace.show();
       
  1356     qApp->setActiveWindow(&workspace);
       
  1357 
       
  1358     const int windowCount = 10;
       
  1359     QMdiSubWindow *windows[windowCount];
       
  1360     for (int i = 0; i < windowCount; ++i) {
       
  1361         windows[i] = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
       
  1362         windows[i]->show();
       
  1363         qApp->processEvents();
       
  1364     }
       
  1365 
       
  1366     QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
       
  1367     connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
       
  1368 
       
  1369     // activateNextSubWindow
       
  1370     for (int i = 0; i < windowCount; ++i) {
       
  1371         workspace.activateNextSubWindow();
       
  1372         qApp->processEvents();
       
  1373         QCOMPARE(workspace.activeSubWindow(), windows[i]);
       
  1374         QCOMPARE(spy.count(), 1);
       
  1375         spy.clear();
       
  1376     }
       
  1377     QVERIFY(activeWindow);
       
  1378     QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
       
  1379     QCOMPARE(workspace.activeSubWindow(), activeWindow);
       
  1380 
       
  1381     // activatePreviousSubWindow
       
  1382     for (int i = windowCount - 2; i >= 0; --i) {
       
  1383         workspace.activatePreviousSubWindow();
       
  1384         qApp->processEvents();
       
  1385         QCOMPARE(workspace.activeSubWindow(), windows[i]);
       
  1386         QCOMPARE(spy.count(), 1);
       
  1387         spy.clear();
       
  1388         if (i % 2 == 0)
       
  1389             windows[i]->hide(); // 10, 8, 6, 4, 2, 0
       
  1390     }
       
  1391     QVERIFY(activeWindow);
       
  1392     QCOMPARE(workspace.activeSubWindow(), windows[0]);
       
  1393     QCOMPARE(workspace.activeSubWindow(), activeWindow);
       
  1394 
       
  1395     // activateNextSubWindow with every 2nd window hidden
       
  1396     for (int i = 0; i < windowCount / 2; ++i) {
       
  1397         workspace.activateNextSubWindow(); // 1, 3, 5, 7, 9
       
  1398         QCOMPARE(spy.count(), 1);
       
  1399         spy.clear();
       
  1400     }
       
  1401     QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
       
  1402 
       
  1403     // activatePreviousSubWindow with every 2nd window hidden
       
  1404     for (int i = 0; i < windowCount / 2; ++i) {
       
  1405         workspace.activatePreviousSubWindow(); // 7, 5, 3, 1, 9
       
  1406         QCOMPARE(spy.count(), 1);
       
  1407         spy.clear();
       
  1408     }
       
  1409     QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
       
  1410 
       
  1411     workspace.setActiveSubWindow(0);
       
  1412     QVERIFY(!activeWindow);
       
  1413 }
       
  1414 
       
  1415 void tst_QMdiArea::subWindowList_data()
       
  1416 {
       
  1417     QTest::addColumn<QMdiArea::WindowOrder>("windowOrder");
       
  1418     QTest::addColumn<int>("windowCount");
       
  1419     QTest::addColumn<int>("activeSubWindow");
       
  1420     QTest::addColumn<int>("staysOnTop1");
       
  1421     QTest::addColumn<int>("staysOnTop2");
       
  1422 
       
  1423     QTest::newRow("CreationOrder") << QMdiArea::CreationOrder << 10 << 4 << 8 << 5;
       
  1424     QTest::newRow("StackingOrder") << QMdiArea::StackingOrder << 10 << 6 << 3 << 9;
       
  1425     QTest::newRow("ActivationHistoryOrder") << QMdiArea::ActivationHistoryOrder << 10 << 7 << 2 << 1;
       
  1426 }
       
  1427 void tst_QMdiArea::subWindowList()
       
  1428 {
       
  1429     QFETCH(QMdiArea::WindowOrder, windowOrder);
       
  1430     QFETCH(int, windowCount);
       
  1431     QFETCH(int, activeSubWindow);
       
  1432     QFETCH(int, staysOnTop1);
       
  1433     QFETCH(int, staysOnTop2);
       
  1434 
       
  1435     QMdiArea workspace;
       
  1436     workspace.show();
       
  1437     qApp->setActiveWindow(&workspace);
       
  1438 
       
  1439     QList<QMdiSubWindow *> activationOrder;
       
  1440     QVector<QMdiSubWindow *> windows;
       
  1441     for (int i = 0; i < windowCount; ++i) {
       
  1442         windows.append(qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget)));
       
  1443         windows[i]->show();
       
  1444         activationOrder.append(windows[i]);
       
  1445     }
       
  1446 
       
  1447     {
       
  1448     QList<QMdiSubWindow *> widgets = workspace.subWindowList(windowOrder);
       
  1449     QCOMPARE(widgets.count(), windowCount);
       
  1450     for (int i = 0; i < widgets.count(); ++i)
       
  1451         QCOMPARE(widgets.at(i), windows[i]);
       
  1452     }
       
  1453 
       
  1454     windows[staysOnTop1]->setWindowFlags(windows[staysOnTop1]->windowFlags() | Qt::WindowStaysOnTopHint);
       
  1455     workspace.setActiveSubWindow(windows[activeSubWindow]);
       
  1456     qApp->processEvents();
       
  1457     QCOMPARE(workspace.activeSubWindow(), windows[activeSubWindow]);
       
  1458     activationOrder.move(activationOrder.indexOf(windows[activeSubWindow]), windowCount - 1);
       
  1459 
       
  1460     QList<QMdiSubWindow *> subWindows = workspace.subWindowList(windowOrder);
       
  1461     if (windowOrder == QMdiArea::CreationOrder) {
       
  1462         QCOMPARE(subWindows.at(activeSubWindow), windows[activeSubWindow]);
       
  1463         QCOMPARE(subWindows.at(staysOnTop1), windows[staysOnTop1]);
       
  1464         for (int i = 0; i < windowCount; ++i)
       
  1465             QCOMPARE(subWindows.at(i), windows[i]);
       
  1466         return;
       
  1467     }
       
  1468 
       
  1469     if (windowOrder == QMdiArea::StackingOrder) {
       
  1470         QCOMPARE(subWindows.at(subWindows.count() - 1), windows[staysOnTop1]);
       
  1471         QCOMPARE(subWindows.at(subWindows.count() - 2), windows[activeSubWindow]);
       
  1472         QCOMPARE(subWindows.count(), windowCount);
       
  1473     } else { // ActivationHistoryOrder
       
  1474         QCOMPARE(subWindows, activationOrder);
       
  1475     }
       
  1476 
       
  1477     windows[staysOnTop2]->setWindowFlags(windows[staysOnTop2]->windowFlags() | Qt::WindowStaysOnTopHint);
       
  1478     workspace.setActiveSubWindow(windows[staysOnTop2]);
       
  1479     qApp->processEvents();
       
  1480     QCOMPARE(workspace.activeSubWindow(), windows[staysOnTop2]);
       
  1481     activationOrder.move(activationOrder.indexOf(windows[staysOnTop2]), windowCount - 1);
       
  1482 
       
  1483     workspace.setActiveSubWindow(windows[activeSubWindow]);
       
  1484     qApp->processEvents();
       
  1485     QCOMPARE(workspace.activeSubWindow(), windows[activeSubWindow]);
       
  1486     activationOrder.move(activationOrder.indexOf(windows[activeSubWindow]), windowCount - 1);
       
  1487 
       
  1488     QList<QMdiSubWindow *> widgets = workspace.subWindowList(windowOrder);
       
  1489     QCOMPARE(widgets.count(), windowCount);
       
  1490     if (windowOrder == QMdiArea::StackingOrder) {
       
  1491         QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop2]);
       
  1492         QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]);
       
  1493         QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]);
       
  1494     } else { // ActivationHistory
       
  1495         QCOMPARE(widgets, activationOrder);
       
  1496     }
       
  1497 
       
  1498     windows[activeSubWindow]->raise();
       
  1499     windows[staysOnTop2]->lower();
       
  1500 
       
  1501     widgets = workspace.subWindowList(windowOrder);
       
  1502     if (windowOrder == QMdiArea::StackingOrder) {
       
  1503         QCOMPARE(widgets.at(widgets.count() - 1), windows[activeSubWindow]);
       
  1504         QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]);
       
  1505         QCOMPARE(widgets.at(0), windows[staysOnTop2]);
       
  1506     } else { // ActivationHistoryOrder
       
  1507         QCOMPARE(widgets, activationOrder);
       
  1508     }
       
  1509 
       
  1510     windows[activeSubWindow]->stackUnder(windows[staysOnTop1]);
       
  1511     windows[staysOnTop2]->raise();
       
  1512 
       
  1513     widgets = workspace.subWindowList(windowOrder);
       
  1514     if (windowOrder == QMdiArea::StackingOrder) {
       
  1515         QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop2]);
       
  1516         QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]);
       
  1517         QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]);
       
  1518     } else { // ActivationHistoryOrder
       
  1519         QCOMPARE(widgets, activationOrder);
       
  1520     }
       
  1521 
       
  1522     workspace.setActiveSubWindow(windows[staysOnTop1]);
       
  1523     activationOrder.move(activationOrder.indexOf(windows[staysOnTop1]), windowCount - 1);
       
  1524 
       
  1525     widgets = workspace.subWindowList(windowOrder);
       
  1526     if (windowOrder == QMdiArea::StackingOrder) {
       
  1527         QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop1]);
       
  1528         QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop2]);
       
  1529         QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]);
       
  1530     } else { // ActivationHistoryOrder
       
  1531         QCOMPARE(widgets, activationOrder);
       
  1532     }
       
  1533 }
       
  1534 
       
  1535 void tst_QMdiArea::setBackground()
       
  1536 {
       
  1537     QMdiArea workspace;
       
  1538     QCOMPARE(workspace.background(), workspace.palette().brush(QPalette::Dark));
       
  1539     workspace.setBackground(QBrush(Qt::green));
       
  1540     QCOMPARE(workspace.background(), QBrush(Qt::green));
       
  1541 }
       
  1542 
       
  1543 void tst_QMdiArea::setViewport()
       
  1544 {
       
  1545     QMdiArea workspace;
       
  1546     workspace.show();
       
  1547 
       
  1548     QWidget *firstViewport = workspace.viewport();
       
  1549     QVERIFY(firstViewport);
       
  1550 
       
  1551     const int windowCount = 10;
       
  1552     for (int i = 0; i < windowCount; ++i) {
       
  1553         QMdiSubWindow *window = workspace.addSubWindow(new QWidget);
       
  1554         window->show();
       
  1555         if (i % 2 == 0) {
       
  1556             window->showMinimized();
       
  1557             QVERIFY(window->isMinimized());
       
  1558         } else {
       
  1559             window->showMaximized();
       
  1560             QVERIFY(window->isMaximized());
       
  1561         }
       
  1562     }
       
  1563 
       
  1564     qApp->processEvents();
       
  1565     QList<QMdiSubWindow *> windowsBeforeViewportChange = workspace.subWindowList();
       
  1566     QCOMPARE(windowsBeforeViewportChange.count(), windowCount);
       
  1567 
       
  1568     workspace.setViewport(new QWidget);
       
  1569     qApp->processEvents();
       
  1570     QVERIFY(workspace.viewport() != firstViewport);
       
  1571 
       
  1572     QList<QMdiSubWindow *> windowsAfterViewportChange = workspace.subWindowList();
       
  1573     QCOMPARE(windowsAfterViewportChange.count(), windowCount);
       
  1574     QCOMPARE(windowsAfterViewportChange, windowsBeforeViewportChange);
       
  1575 
       
  1576     //    for (int i = 0; i < windowCount; ++i) {
       
  1577     //        QMdiSubWindow *window = windowsAfterViewportChange.at(i);
       
  1578     //        if (i % 2 == 0)
       
  1579     //            QVERIFY(!window->isMinimized());
       
  1580     //else
       
  1581     //    QVERIFY(!window->isMaximized());
       
  1582     //    }
       
  1583 
       
  1584     QTest::ignoreMessage(QtWarningMsg, "QMdiArea: Deleting the view port is undefined, "
       
  1585                                        "use setViewport instead.");
       
  1586     delete workspace.viewport();
       
  1587     qApp->processEvents();
       
  1588 
       
  1589     QCOMPARE(workspace.subWindowList().count(), 0);
       
  1590     QVERIFY(!workspace.activeSubWindow());
       
  1591 }
       
  1592 
       
  1593 void tst_QMdiArea::tileSubWindows()
       
  1594 {
       
  1595     QMdiArea workspace;
       
  1596     workspace.resize(600,480);
       
  1597     workspace.show();
       
  1598 #ifdef Q_WS_X11
       
  1599     qt_x11_wait_for_window_manager(&workspace);
       
  1600 #endif
       
  1601 
       
  1602     const int windowCount = 10;
       
  1603     for (int i = 0; i < windowCount; ++i) {
       
  1604         QMdiSubWindow *subWindow = workspace.addSubWindow(new QWidget);
       
  1605         subWindow->setMinimumSize(50, 30);
       
  1606         subWindow->show();
       
  1607     }
       
  1608     workspace.tileSubWindows();
       
  1609     workspace.setActiveSubWindow(0);
       
  1610     QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
       
  1611 
       
  1612     QList<QMdiSubWindow *> windows = workspace.subWindowList();
       
  1613     for (int i = 0; i < windowCount; ++i) {
       
  1614         QMdiSubWindow *window = windows.at(i);
       
  1615         for (int j = 0; j < windowCount; ++j) {
       
  1616             if (i == j)
       
  1617                 continue;
       
  1618             QVERIFY(!window->geometry().intersects(windows.at(j)->geometry()));
       
  1619         }
       
  1620     }
       
  1621 
       
  1622     // Keep the views tiled through any subsequent resize events.
       
  1623     for (int i = 0; i < 5; ++i) {
       
  1624         workspace.resize(workspace.size() - QSize(10, 10));
       
  1625         qApp->processEvents();
       
  1626     }
       
  1627     workspace.setActiveSubWindow(0);
       
  1628 #ifndef Q_OS_WINCE //See Task 197453 ToDo
       
  1629     QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
       
  1630 #endif
       
  1631 
       
  1632     QMdiSubWindow *window = windows.at(0);
       
  1633 
       
  1634     // Change the geometry of one of the children and verify
       
  1635     // that the views are not tiled anymore.
       
  1636     window->move(window->x() + 1, window->y());
       
  1637     workspace.resize(workspace.size() - QSize(10, 10));
       
  1638     workspace.setActiveSubWindow(0);
       
  1639     QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
       
  1640     qApp->processEvents();
       
  1641 
       
  1642     // Re-tile.
       
  1643     workspace.tileSubWindows();
       
  1644     workspace.setActiveSubWindow(0);
       
  1645     QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
       
  1646 
       
  1647     // Close one of the children and verify that the views
       
  1648     // are not tiled anymore.
       
  1649     window->close();
       
  1650     workspace.resize(workspace.size() - QSize(10, 10));
       
  1651     workspace.setActiveSubWindow(0);
       
  1652     QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
       
  1653     qApp->processEvents();
       
  1654 
       
  1655     // Re-tile.
       
  1656     workspace.tileSubWindows();
       
  1657     workspace.setActiveSubWindow(0);
       
  1658     QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
       
  1659 
       
  1660     window = windows.at(1);
       
  1661 
       
  1662     // Maximize one of the children and verify that the views
       
  1663     // are not tiled anymore.
       
  1664     workspace.tileSubWindows();
       
  1665     window->showMaximized();
       
  1666     workspace.resize(workspace.size() - QSize(10, 10));
       
  1667     workspace.setActiveSubWindow(0);
       
  1668     QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
       
  1669     qApp->processEvents();
       
  1670 
       
  1671     // Re-tile.
       
  1672     workspace.tileSubWindows();
       
  1673     workspace.setActiveSubWindow(0);
       
  1674     QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
       
  1675 
       
  1676     // Minimize one of the children and verify that the views
       
  1677     // are not tiled anymore.
       
  1678     workspace.tileSubWindows();
       
  1679     window->showMinimized();
       
  1680     workspace.resize(workspace.size() - QSize(10, 10));
       
  1681     workspace.setActiveSubWindow(0);
       
  1682     QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
       
  1683     qApp->processEvents();
       
  1684 
       
  1685     // Re-tile.
       
  1686     workspace.tileSubWindows();
       
  1687     workspace.setActiveSubWindow(0);
       
  1688     QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
       
  1689 
       
  1690     // Active/deactivate windows and verify that the views are tiled.
       
  1691     workspace.setActiveSubWindow(windows.at(5));
       
  1692     workspace.resize(workspace.size() - QSize(10, 10));
       
  1693     workspace.setActiveSubWindow(0);
       
  1694     QTest::qWait(250); // delayed re-arrange of minimized windows
       
  1695     QTRY_COMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
       
  1696 
       
  1697     // Add another window and verify that the views are not tiled anymore.
       
  1698     workspace.addSubWindow(new QPushButton(QLatin1String("I'd like to mess up tiled views")))->show();
       
  1699     workspace.resize(workspace.size() - QSize(10, 10));
       
  1700     workspace.setActiveSubWindow(0);
       
  1701     QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
       
  1702 
       
  1703     // Re-tile.
       
  1704     workspace.tileSubWindows();
       
  1705     workspace.setActiveSubWindow(0);
       
  1706     QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
       
  1707 
       
  1708     // Cascade and verify that the views are not tiled anymore.
       
  1709     workspace.cascadeSubWindows();
       
  1710     workspace.resize(workspace.size() - QSize(10, 10));
       
  1711     workspace.setActiveSubWindow(0);
       
  1712     QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
       
  1713 
       
  1714     // Make sure the active window is placed in top left corner regardless
       
  1715     // of whether we have any windows with staysOnTopHint or not.
       
  1716     windows.at(3)->setWindowFlags(windows.at(3)->windowFlags() | Qt::WindowStaysOnTopHint);
       
  1717     QMdiSubWindow *activeSubWindow = windows.at(6);
       
  1718     workspace.setActiveSubWindow(activeSubWindow);
       
  1719     QCOMPARE(workspace.activeSubWindow(), activeSubWindow);
       
  1720     workspace.tileSubWindows();
       
  1721     QCOMPARE(activeSubWindow->geometry().topLeft(), QPoint(0, 0));
       
  1722 
       
  1723     // Verify that we try to resize the area such that all sub-windows are visible.
       
  1724     // It's important that tiled windows are NOT overlapping.
       
  1725     workspace.resize(350, 150);
       
  1726     qApp->processEvents();
       
  1727     QTRY_COMPARE(workspace.size(), QSize(350, 150));
       
  1728 
       
  1729     const QSize minSize(300, 100);
       
  1730     foreach (QMdiSubWindow *subWindow, workspace.subWindowList())
       
  1731         subWindow->setMinimumSize(minSize);
       
  1732 
       
  1733     QCOMPARE(workspace.size(), QSize(350, 150));
       
  1734     workspace.tileSubWindows();
       
  1735     // The sub-windows are now tiled like this:
       
  1736     // | win 1 || win 2 || win 3 |
       
  1737     // +-------++-------++-------+
       
  1738     // +-------++-------++-------+
       
  1739     // | win 4 || win 5 || win 6 |
       
  1740     // +-------++-------++-------+
       
  1741     // +-------++-------++-------+
       
  1742     // | win 7 || win 8 || win 9 |
       
  1743     workspace.setActiveSubWindow(0);
       
  1744     int frameWidth = 0;
       
  1745     if (workspace.style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, 0, &workspace))
       
  1746         frameWidth = workspace.style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
       
  1747     const int spacing = 2 * frameWidth + 2;
       
  1748     const QSize expectedViewportSize(3 * minSize.width() + spacing, 3 * minSize.height() + spacing);
       
  1749 #ifdef Q_OS_WINCE
       
  1750     QSKIP("Not fixed yet! See task 197453", SkipAll);
       
  1751 #endif
       
  1752     QTRY_COMPARE(workspace.viewport()->rect().size(), expectedViewportSize);
       
  1753 
       
  1754     // Not enough space for all sub-windows to be visible -> provide scroll bars.
       
  1755     workspace.resize(150, 150);
       
  1756     qApp->processEvents();
       
  1757     QTRY_COMPARE(workspace.size(), QSize(150, 150));
       
  1758 
       
  1759     // Horizontal scroll bar.
       
  1760     QScrollBar *hBar = workspace.horizontalScrollBar();
       
  1761     QCOMPARE(workspace.horizontalScrollBarPolicy(), Qt::ScrollBarAsNeeded);
       
  1762     QTRY_VERIFY(hBar->isVisible());
       
  1763     QCOMPARE(hBar->value(), 0);
       
  1764     QCOMPARE(hBar->minimum(), 0);
       
  1765 
       
  1766     // Vertical scroll bar.
       
  1767     QScrollBar *vBar = workspace.verticalScrollBar();
       
  1768     QCOMPARE(workspace.verticalScrollBarPolicy(), Qt::ScrollBarAsNeeded);
       
  1769     QVERIFY(vBar->isVisible());
       
  1770     QCOMPARE(vBar->value(), 0);
       
  1771     QCOMPARE(vBar->minimum(), 0);
       
  1772 
       
  1773     workspace.tileSubWindows();
       
  1774 #ifdef Q_WS_X11
       
  1775     qt_x11_wait_for_window_manager(&workspace);
       
  1776 #endif
       
  1777     qApp->processEvents();
       
  1778 
       
  1779     QTRY_VERIFY(workspace.size() != QSize(150, 150));
       
  1780     QTRY_VERIFY(!vBar->isVisible());
       
  1781     QTRY_VERIFY(!hBar->isVisible());
       
  1782 }
       
  1783 
       
  1784 void tst_QMdiArea::cascadeAndTileSubWindows()
       
  1785 {
       
  1786     QMdiArea workspace;
       
  1787     workspace.resize(400, 400);
       
  1788     workspace.show();
       
  1789 #ifdef Q_WS_X11
       
  1790     qt_x11_wait_for_window_manager(&workspace);
       
  1791 #endif
       
  1792 
       
  1793     const int windowCount = 10;
       
  1794     QList<QMdiSubWindow *> windows;
       
  1795     for (int i = 0; i < windowCount; ++i) {
       
  1796         QMdiSubWindow *window = workspace.addSubWindow(new MyChild);
       
  1797         if (i % 3 == 0) {
       
  1798             window->showMinimized();
       
  1799             QVERIFY(window->isMinimized());
       
  1800         } else {
       
  1801             window->showMaximized();
       
  1802             QVERIFY(window->isMaximized());
       
  1803         }
       
  1804         windows.append(window);
       
  1805     }
       
  1806 
       
  1807     // cascadeSubWindows
       
  1808     qApp->processEvents();
       
  1809     workspace.cascadeSubWindows();
       
  1810     qApp->processEvents();
       
  1811 
       
  1812     // Check dy between two cascaded windows
       
  1813     QStyleOptionTitleBar options;
       
  1814     options.initFrom(windows.at(1));
       
  1815     int titleBarHeight = windows.at(1)->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
       
  1816     // ### Remove this after the mac style has been fixed
       
  1817     if (windows.at(1)->style()->inherits("QMacStyle"))
       
  1818         titleBarHeight -= 4;
       
  1819     const QFontMetrics fontMetrics = QFontMetrics(QApplication::font("QWorkspaceTitleBar"));
       
  1820     const int dy = qMax(titleBarHeight - (titleBarHeight - fontMetrics.height()) / 2, 1);
       
  1821     QCOMPARE(windows.at(2)->geometry().top() - windows.at(1)->geometry().top(), dy);
       
  1822 
       
  1823     for (int i = 0; i < windows.count(); ++i) {
       
  1824         QMdiSubWindow *window = windows.at(i);
       
  1825         if (i % 3 == 0) {
       
  1826             QVERIFY(window->isMinimized());
       
  1827         } else {
       
  1828             QVERIFY(!window->isMaximized());
       
  1829             QCOMPARE(window->size(), window->sizeHint());
       
  1830             window->showMaximized();
       
  1831             QVERIFY(window->isMaximized());
       
  1832         }
       
  1833     }
       
  1834 }
       
  1835 
       
  1836 void tst_QMdiArea::resizeMaximizedChildWindows_data()
       
  1837 {
       
  1838     QTest::addColumn<int>("startSize");
       
  1839     QTest::addColumn<int>("increment");
       
  1840     QTest::addColumn<int>("windowCount");
       
  1841 
       
  1842     QTest::newRow("multiple children") << 400 << 20 << 10;
       
  1843 }
       
  1844 
       
  1845 void tst_QMdiArea::resizeMaximizedChildWindows()
       
  1846 {
       
  1847     QFETCH(int, startSize);
       
  1848     QFETCH(int, increment);
       
  1849     QFETCH(int, windowCount);
       
  1850 
       
  1851     QMdiArea workspace;
       
  1852     workspace.show();
       
  1853 #if defined(Q_WS_X11)
       
  1854     qt_x11_wait_for_window_manager(&workspace);
       
  1855 #endif
       
  1856     QTest::qWait(100);
       
  1857     workspace.resize(startSize, startSize);
       
  1858     workspace.setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
       
  1859     QSize workspaceSize = workspace.size();
       
  1860     QVERIFY(workspaceSize.isValid());
       
  1861     QCOMPARE(workspaceSize, QSize(startSize, startSize));
       
  1862 
       
  1863     QList<QMdiSubWindow *> windows;
       
  1864     for (int i = 0; i < windowCount; ++i) {
       
  1865         QMdiSubWindow *window = workspace.addSubWindow(new QWidget);
       
  1866         windows.append(window);
       
  1867         qApp->processEvents();
       
  1868         window->showMaximized();
       
  1869         QTest::qWait(100);
       
  1870         QVERIFY(window->isMaximized());
       
  1871         QSize windowSize = window->size();
       
  1872         QVERIFY(windowSize.isValid());
       
  1873         QCOMPARE(window->rect(), workspace.contentsRect());
       
  1874 
       
  1875         workspace.resize(workspaceSize + QSize(increment, increment));
       
  1876         QTest::qWait(100);
       
  1877         qApp->processEvents();
       
  1878         QTRY_COMPARE(workspace.size(), workspaceSize + QSize(increment, increment));
       
  1879         QTRY_COMPARE(window->size(), windowSize + QSize(increment, increment));
       
  1880         workspaceSize = workspace.size();
       
  1881     }
       
  1882 
       
  1883     int newSize = startSize + increment * windowCount;
       
  1884     QCOMPARE(workspaceSize, QSize(newSize, newSize));
       
  1885     foreach (QWidget *window, windows)
       
  1886         QCOMPARE(window->rect(), workspace.contentsRect());
       
  1887 }
       
  1888 
       
  1889 // QWidget::setParent clears focusWidget so make sure
       
  1890 // we restore it after QMdiArea::addSubWindow.
       
  1891 void tst_QMdiArea::focusWidgetAfterAddSubWindow()
       
  1892 {
       
  1893     QWidget *view = new QWidget;
       
  1894     view->setLayout(new QVBoxLayout);
       
  1895 
       
  1896     QLineEdit *lineEdit1 = new QLineEdit;
       
  1897     QLineEdit *lineEdit2 = new QLineEdit;
       
  1898     view->layout()->addWidget(lineEdit1);
       
  1899     view->layout()->addWidget(lineEdit2);
       
  1900 
       
  1901     lineEdit2->setFocus();
       
  1902     QCOMPARE(view->focusWidget(), static_cast<QWidget *>(lineEdit2));
       
  1903 
       
  1904     QMdiArea mdiArea;
       
  1905     mdiArea.addSubWindow(view);
       
  1906     QCOMPARE(view->focusWidget(), static_cast<QWidget *>(lineEdit2));
       
  1907 
       
  1908     mdiArea.show();
       
  1909     view->show();
       
  1910     qApp->setActiveWindow(&mdiArea);
       
  1911     QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(lineEdit2));
       
  1912 }
       
  1913 
       
  1914 void tst_QMdiArea::dontMaximizeSubWindowOnActivation()
       
  1915 {
       
  1916     QMdiArea mdiArea;
       
  1917     mdiArea.show();
       
  1918 #ifdef Q_WS_X11
       
  1919     qt_x11_wait_for_window_manager(&mdiArea);
       
  1920 #endif
       
  1921     qApp->setActiveWindow(&mdiArea);
       
  1922 
       
  1923     // Add one maximized window.
       
  1924     mdiArea.addSubWindow(new QWidget)->showMaximized();
       
  1925     QVERIFY(mdiArea.activeSubWindow());
       
  1926     QVERIFY(mdiArea.activeSubWindow()->isMaximized());
       
  1927 
       
  1928     // Add few more windows and verify that they are maximized.
       
  1929     for (int i = 0; i < 5; ++i) {
       
  1930         QMdiSubWindow *window = mdiArea.addSubWindow(new QWidget);
       
  1931         window->show();
       
  1932         QVERIFY(window->isMaximized());
       
  1933         qApp->processEvents();
       
  1934     }
       
  1935 
       
  1936     // Verify that activated windows still are maximized on activation.
       
  1937     QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
       
  1938     for (int i = 0; i < subWindows.count(); ++i) {
       
  1939         mdiArea.activateNextSubWindow();
       
  1940         QMdiSubWindow *window = subWindows.at(i);
       
  1941         QCOMPARE(mdiArea.activeSubWindow(), window);
       
  1942         QVERIFY(window->isMaximized());
       
  1943         qApp->processEvents();
       
  1944     }
       
  1945 
       
  1946     // Restore active window and verify that other windows aren't
       
  1947     // maximized on activation.
       
  1948     mdiArea.activeSubWindow()->showNormal();
       
  1949     for (int i = 0; i < subWindows.count(); ++i) {
       
  1950         mdiArea.activateNextSubWindow();
       
  1951         QMdiSubWindow *window = subWindows.at(i);
       
  1952         QCOMPARE(mdiArea.activeSubWindow(), window);
       
  1953         QVERIFY(!window->isMaximized());
       
  1954         qApp->processEvents();
       
  1955     }
       
  1956 
       
  1957     // Enable 'DontMaximizedSubWindowOnActivation' and maximize the active window.
       
  1958     mdiArea.setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
       
  1959     mdiArea.activeSubWindow()->showMaximized();
       
  1960     int indexOfMaximized = subWindows.indexOf(mdiArea.activeSubWindow());
       
  1961 
       
  1962     // Verify that windows are not maximized on activation.
       
  1963     for (int i = 0; i < subWindows.count(); ++i) {
       
  1964         mdiArea.activateNextSubWindow();
       
  1965         QMdiSubWindow *window = subWindows.at(i);
       
  1966         QCOMPARE(mdiArea.activeSubWindow(), window);
       
  1967         if (indexOfMaximized != i)
       
  1968             QVERIFY(!window->isMaximized());
       
  1969         qApp->processEvents();
       
  1970     }
       
  1971     QVERIFY(mdiArea.activeSubWindow()->isMaximized());
       
  1972 
       
  1973     // Minimize all windows.
       
  1974     foreach (QMdiSubWindow *window, subWindows) {
       
  1975         window->showMinimized();
       
  1976         QVERIFY(window->isMinimized());
       
  1977         qApp->processEvents();
       
  1978     }
       
  1979 
       
  1980     // Disable 'DontMaximizedSubWindowOnActivation' and maximize the active window.
       
  1981     mdiArea.setOption(QMdiArea::DontMaximizeSubWindowOnActivation, false);
       
  1982     mdiArea.activeSubWindow()->showMaximized();
       
  1983 
       
  1984     // Verify that minimized windows are maximized on activation.
       
  1985     for (int i = 0; i < subWindows.count(); ++i) {
       
  1986         mdiArea.activateNextSubWindow();
       
  1987         QMdiSubWindow *window = subWindows.at(i);
       
  1988         QCOMPARE(mdiArea.activeSubWindow(), window);
       
  1989         QVERIFY(window->isMaximized());
       
  1990         qApp->processEvents();
       
  1991     }
       
  1992 
       
  1993     // Verify that activated windows are maximized after closing
       
  1994     // the active window
       
  1995     for (int i = 0; i < subWindows.count(); ++i) {
       
  1996         QVERIFY(mdiArea.activeSubWindow());
       
  1997         QVERIFY(mdiArea.activeSubWindow()->isMaximized());
       
  1998         mdiArea.activeSubWindow()->close();
       
  1999         qApp->processEvents();
       
  2000     }
       
  2001 
       
  2002     QVERIFY(!mdiArea.activeSubWindow());
       
  2003     QCOMPARE(mdiArea.subWindowList().size(), 0);
       
  2004 
       
  2005     // Verify that new windows are not maximized.
       
  2006     mdiArea.addSubWindow(new QWidget)->show();
       
  2007     QVERIFY(mdiArea.activeSubWindow());
       
  2008     QVERIFY(!mdiArea.activeSubWindow()->isMaximized());
       
  2009 }
       
  2010 
       
  2011 void tst_QMdiArea::delayedPlacement()
       
  2012 {
       
  2013     QMdiArea mdiArea;
       
  2014 
       
  2015     QMdiSubWindow *window1 = mdiArea.addSubWindow(new QWidget);
       
  2016     QCOMPARE(window1->geometry().topLeft(), QPoint(0, 0));
       
  2017 
       
  2018     QMdiSubWindow *window2 = mdiArea.addSubWindow(new QWidget);
       
  2019     QCOMPARE(window2->geometry().topLeft(), QPoint(0, 0));
       
  2020 
       
  2021     QMdiSubWindow *window3 = mdiArea.addSubWindow(new QWidget);
       
  2022     QCOMPARE(window3->geometry().topLeft(), QPoint(0, 0));
       
  2023 
       
  2024     mdiArea.resize(window3->minimumSizeHint().width() * 3, 400);
       
  2025     mdiArea.show();
       
  2026 #ifdef Q_WS_X11
       
  2027     qt_x11_wait_for_window_manager(&mdiArea);
       
  2028 #endif
       
  2029 
       
  2030     QCOMPARE(window1->geometry().topLeft(), QPoint(0, 0));
       
  2031     QCOMPARE(window2->geometry().topLeft(), window1->geometry().topRight() + QPoint(1, 0));
       
  2032     QCOMPARE(window3->geometry().topLeft(), window2->geometry().topRight() + QPoint(1, 0));
       
  2033 }
       
  2034 
       
  2035 void tst_QMdiArea::iconGeometryInMenuBar()
       
  2036 {
       
  2037 #if !defined (Q_WS_MAC) && !defined(Q_OS_WINCE)
       
  2038     QMainWindow mainWindow;
       
  2039     QMenuBar *menuBar = mainWindow.menuBar();
       
  2040     QMdiArea *mdiArea = new QMdiArea;
       
  2041     QMdiSubWindow *subWindow = mdiArea->addSubWindow(new QWidget);
       
  2042     mainWindow.setCentralWidget(mdiArea);
       
  2043     mainWindow.show();
       
  2044 #ifdef Q_WS_X11
       
  2045     qt_x11_wait_for_window_manager(&mainWindow);
       
  2046 #endif
       
  2047 
       
  2048     subWindow->showMaximized();
       
  2049     QVERIFY(subWindow->isMaximized());
       
  2050 
       
  2051     QWidget *leftCornerWidget = menuBar->cornerWidget(Qt::TopLeftCorner);
       
  2052     QVERIFY(leftCornerWidget);
       
  2053     int topMargin = (menuBar->height() - leftCornerWidget->height()) / 2;
       
  2054     int leftMargin = qApp->style()->pixelMetric(QStyle::PM_MenuBarHMargin)
       
  2055                    + qApp->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth);
       
  2056     QPoint pos(leftMargin, topMargin);
       
  2057     QRect geometry = QStyle::visualRect(qApp->layoutDirection(), menuBar->rect(),
       
  2058                                         QRect(pos, leftCornerWidget->size()));
       
  2059     QCOMPARE(leftCornerWidget->geometry(), geometry);
       
  2060 #endif
       
  2061 }
       
  2062 
       
  2063 class EventSpy : public QObject
       
  2064 {
       
  2065 public:
       
  2066     EventSpy(QObject *object, QEvent::Type event)
       
  2067         : eventToSpy(event), _count(0)
       
  2068     {
       
  2069         if (object)
       
  2070             object->installEventFilter(this);
       
  2071     }
       
  2072 
       
  2073     int count() const { return _count; }
       
  2074     void clear() { _count = 0; }
       
  2075 
       
  2076 protected:
       
  2077     bool eventFilter(QObject *object, QEvent *event)
       
  2078     {
       
  2079         if (event->type() == eventToSpy)
       
  2080             ++_count;
       
  2081         return  QObject::eventFilter(object, event);
       
  2082     }
       
  2083 
       
  2084 private:
       
  2085     QEvent::Type eventToSpy;
       
  2086     int _count;
       
  2087 };
       
  2088 
       
  2089 void tst_QMdiArea::resizeTimer()
       
  2090 {
       
  2091     QMdiArea mdiArea;
       
  2092     QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget);
       
  2093     mdiArea.show();
       
  2094 #ifdef Q_WS_X11
       
  2095     qt_x11_wait_for_window_manager(&mdiArea);
       
  2096 #endif
       
  2097 
       
  2098 #ifndef Q_OS_WINCE
       
  2099     int time = 250;
       
  2100 #else
       
  2101     int time = 1000;
       
  2102 #endif
       
  2103 
       
  2104     QTest::qWait(time);
       
  2105 
       
  2106     EventSpy timerEventSpy(subWindow, QEvent::Timer);
       
  2107     QCOMPARE(timerEventSpy.count(), 0);
       
  2108 
       
  2109     mdiArea.tileSubWindows();
       
  2110     QTest::qWait(time); // Wait for timer events to occur.
       
  2111     QCOMPARE(timerEventSpy.count(), 1);
       
  2112     timerEventSpy.clear();
       
  2113 
       
  2114     mdiArea.resize(mdiArea.size() + QSize(2, 2));
       
  2115     QTest::qWait(time); // Wait for timer events to occur.
       
  2116     QCOMPARE(timerEventSpy.count(), 1);
       
  2117     timerEventSpy.clear();
       
  2118 
       
  2119     // Check that timers are killed.
       
  2120     QTest::qWait(time); // Wait for timer events to occur.
       
  2121     QCOMPARE(timerEventSpy.count(), 0);
       
  2122 }
       
  2123 
       
  2124 void tst_QMdiArea::updateScrollBars()
       
  2125 {
       
  2126     QMdiArea mdiArea;
       
  2127     mdiArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
       
  2128     mdiArea.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
       
  2129 
       
  2130     QMdiSubWindow *subWindow1 = mdiArea.addSubWindow(new QWidget);
       
  2131     QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(new QWidget);
       
  2132 
       
  2133     mdiArea.show();
       
  2134 #ifdef Q_WS_X11
       
  2135     qt_x11_wait_for_window_manager(&mdiArea);
       
  2136 #endif
       
  2137     qApp->processEvents();
       
  2138 
       
  2139     QScrollBar *hbar = mdiArea.horizontalScrollBar();
       
  2140     QVERIFY(hbar);
       
  2141     QVERIFY(!hbar->isVisible());
       
  2142 
       
  2143     QScrollBar *vbar = mdiArea.verticalScrollBar();
       
  2144     QVERIFY(vbar);
       
  2145     QVERIFY(!vbar->isVisible());
       
  2146 
       
  2147     // Move sub-window 2 away.
       
  2148     subWindow2->move(10000, 10000);
       
  2149     qApp->processEvents();
       
  2150     QVERIFY(hbar->isVisible());
       
  2151     QVERIFY(vbar->isVisible());
       
  2152 
       
  2153     for (int i = 0; i < 2; ++i) {
       
  2154     // Maximize sub-window 1 and make sure we don't have any scroll bars.
       
  2155     subWindow1->showMaximized();
       
  2156     qApp->processEvents();
       
  2157     QVERIFY(subWindow1->isMaximized());
       
  2158     QVERIFY(!hbar->isVisible());
       
  2159     QVERIFY(!vbar->isVisible());
       
  2160 
       
  2161     // We still shouldn't get any scroll bars.
       
  2162     mdiArea.resize(mdiArea.size() - QSize(20, 20));
       
  2163 #ifdef Q_WS_X11
       
  2164     qt_x11_wait_for_window_manager(&mdiArea);
       
  2165 #endif
       
  2166     qApp->processEvents();
       
  2167     QVERIFY(subWindow1->isMaximized());
       
  2168     QVERIFY(!hbar->isVisible());
       
  2169     QVERIFY(!vbar->isVisible());
       
  2170 
       
  2171     // Restore sub-window 1 and make sure we have scroll bars again.
       
  2172     subWindow1->showNormal();
       
  2173     qApp->processEvents();
       
  2174     QVERIFY(!subWindow1->isMaximized());
       
  2175     QVERIFY(hbar->isVisible());
       
  2176     QVERIFY(vbar->isVisible());
       
  2177         if (i == 0) {
       
  2178             // Now, do the same when the viewport is scrolled.
       
  2179             hbar->setValue(1000);
       
  2180             vbar->setValue(1000);
       
  2181         }
       
  2182     }
       
  2183 }
       
  2184 
       
  2185 void tst_QMdiArea::setActivationOrder_data()
       
  2186 {
       
  2187     QTest::addColumn<QMdiArea::WindowOrder>("activationOrder");
       
  2188     QTest::addColumn<int>("subWindowCount");
       
  2189     QTest::addColumn<int>("staysOnTopIndex");
       
  2190     QTest::addColumn<int>("firstActiveIndex");
       
  2191     QTest::addColumn<QList<int> >("expectedActivationIndices");
       
  2192     // The order of expectedCascadeIndices:
       
  2193     // window 1 -> (index 0)
       
  2194     //   window 2 -> (index 1)
       
  2195     //     window 3 -> (index 2)
       
  2196     // ....
       
  2197     QTest::addColumn<QList<int> >("expectedCascadeIndices");
       
  2198 
       
  2199     // The order of expectedTileIndices (the same as reading a book LTR).
       
  2200     // +--------------------+--------------------+--------------------+
       
  2201     // | window 1 (index 0) | window 2 (index 1) | window 3 (index 2) |
       
  2202     // |                    +--------------------+--------------------+
       
  2203     // |          (index 3) | window 4 (index 4) | window 5 (index 5) |
       
  2204     // +--------------------------------------------------------------+
       
  2205     QTest::addColumn<QList<int> >("expectedTileIndices");
       
  2206 
       
  2207     QList<int> list;
       
  2208     QList<int> list2;
       
  2209     QList<int> list3;
       
  2210 
       
  2211     list << 2 << 1 << 0 << 1 << 2 << 3 << 4;
       
  2212     list2 << 0 << 1 << 2 << 3 << 4;
       
  2213     list3 << 1 << 4 << 3 << 1 << 2 << 0;
       
  2214     QTest::newRow("CreationOrder") << QMdiArea::CreationOrder << 5 << 3 << 1 << list << list2 << list3;
       
  2215 
       
  2216     list = QList<int>();
       
  2217     list << 3 << 1 << 4 << 3 << 1 << 2 << 0;
       
  2218     list2 = QList<int>();
       
  2219     list2 << 0 << 2 << 4 << 1 << 3;
       
  2220     list3 = QList<int>();
       
  2221     list3 << 1 << 3 << 4 << 1 << 2 << 0;
       
  2222     QTest::newRow("StackingOrder") << QMdiArea::StackingOrder << 5 << 3 << 1 << list << list2 << list3;
       
  2223 
       
  2224     list = QList<int>();
       
  2225     list << 0 << 1 << 0 << 1 << 4 << 3 << 2;
       
  2226     list2 = QList<int>();
       
  2227     list2 << 0 << 2 << 3 << 4 << 1;
       
  2228     list3 = QList<int>();
       
  2229     list3 << 1 << 4 << 3 << 1 << 2 << 0;
       
  2230     QTest::newRow("ActivationHistoryOrder") << QMdiArea::ActivationHistoryOrder << 5 << 3 << 1 << list << list2 << list3;
       
  2231 }
       
  2232 
       
  2233 void tst_QMdiArea::setActivationOrder()
       
  2234 {
       
  2235     QFETCH(QMdiArea::WindowOrder, activationOrder);
       
  2236     QFETCH(int, subWindowCount);
       
  2237     QFETCH(int, staysOnTopIndex);
       
  2238     QFETCH(int, firstActiveIndex);
       
  2239     QFETCH(QList<int>, expectedActivationIndices);
       
  2240     QFETCH(QList<int>, expectedCascadeIndices);
       
  2241     QFETCH(QList<int>, expectedTileIndices);
       
  2242 
       
  2243     // Default order.
       
  2244     QMdiArea mdiArea;
       
  2245     QCOMPARE(mdiArea.activationOrder(), QMdiArea::CreationOrder);
       
  2246 
       
  2247     // New order.
       
  2248     mdiArea.setActivationOrder(activationOrder);
       
  2249     QCOMPARE(mdiArea.activationOrder(), activationOrder);
       
  2250 
       
  2251     QList<QMdiSubWindow *> subWindows;
       
  2252     for (int i = 0; i < subWindowCount; ++i)
       
  2253         subWindows << mdiArea.addSubWindow(new QPushButton(tr("%1").arg(i)));
       
  2254     QCOMPARE(mdiArea.subWindowList(activationOrder), subWindows);
       
  2255 
       
  2256     mdiArea.show();
       
  2257 #ifdef Q_WS_X11
       
  2258     qt_x11_wait_for_window_manager(&mdiArea);
       
  2259 #endif
       
  2260 
       
  2261     for (int i = 0; i < subWindows.count(); ++i) {
       
  2262         mdiArea.activateNextSubWindow();
       
  2263         QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(i));
       
  2264         qApp->processEvents();
       
  2265     }
       
  2266 
       
  2267     QMdiSubWindow *staysOnTop = subWindows.at(staysOnTopIndex);
       
  2268     staysOnTop->setWindowFlags(staysOnTop->windowFlags() | Qt::WindowStaysOnTopHint);
       
  2269     staysOnTop->raise();
       
  2270 
       
  2271     mdiArea.setActiveSubWindow(subWindows.at(firstActiveIndex));
       
  2272     QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(firstActiveIndex));
       
  2273 
       
  2274     // Verify the actual arrangement/geometry.
       
  2275     mdiArea.tileSubWindows();
       
  2276     QTest::qWait(100);
       
  2277     QVERIFY(verifyArrangement(&mdiArea, Tiled, expectedTileIndices));
       
  2278 
       
  2279     mdiArea.cascadeSubWindows();
       
  2280     QVERIFY(verifyArrangement(&mdiArea, Cascaded, expectedCascadeIndices));
       
  2281     QTest::qWait(100);
       
  2282 
       
  2283     mdiArea.activateNextSubWindow();
       
  2284     QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
       
  2285 
       
  2286     mdiArea.activatePreviousSubWindow();
       
  2287     QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
       
  2288 
       
  2289     mdiArea.activatePreviousSubWindow();
       
  2290     QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
       
  2291 
       
  2292     for (int i = 0; i < subWindowCount; ++i) {
       
  2293         mdiArea.closeActiveSubWindow();
       
  2294         qApp->processEvents();
       
  2295         if (i == subWindowCount - 1) { // Last window closed.
       
  2296             QVERIFY(!mdiArea.activeSubWindow());
       
  2297             break;
       
  2298         }
       
  2299         QVERIFY(mdiArea.activeSubWindow());
       
  2300         QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
       
  2301     }
       
  2302 
       
  2303     QVERIFY(mdiArea.subWindowList(activationOrder).isEmpty());
       
  2304     QVERIFY(expectedActivationIndices.isEmpty());
       
  2305 }
       
  2306 
       
  2307 void tst_QMdiArea::tabBetweenSubWindows()
       
  2308 {
       
  2309     QMdiArea mdiArea;
       
  2310     QList<QMdiSubWindow *> subWindows;
       
  2311     for (int i = 0; i < 5; ++i)
       
  2312         subWindows << mdiArea.addSubWindow(new QLineEdit);
       
  2313 
       
  2314     mdiArea.show();
       
  2315 #ifdef Q_WS_X11
       
  2316     qt_x11_wait_for_window_manager(&mdiArea);
       
  2317 #endif
       
  2318 
       
  2319     qApp->setActiveWindow(&mdiArea);
       
  2320     QWidget *focusWidget = subWindows.back()->widget();
       
  2321     QCOMPARE(qApp->focusWidget(), focusWidget);
       
  2322 
       
  2323     QSignalSpy spy(&mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)));
       
  2324     QCOMPARE(spy.count(), 0);
       
  2325 
       
  2326     // Walk through the entire list of sub windows.
       
  2327     QVERIFY(tabBetweenSubWindowsIn(&mdiArea));
       
  2328     QCOMPARE(mdiArea.activeSubWindow(), subWindows.back());
       
  2329     QCOMPARE(spy.count(), 0);
       
  2330 
       
  2331     mdiArea.setActiveSubWindow(subWindows.front());
       
  2332     QCOMPARE(mdiArea.activeSubWindow(), subWindows.front());
       
  2333     spy.clear();
       
  2334 
       
  2335     // Walk through the entire list of sub windows in the opposite direction (Ctrl-Shift-Tab).
       
  2336     QVERIFY(tabBetweenSubWindowsIn(&mdiArea, -1, true));
       
  2337     QCOMPARE(mdiArea.activeSubWindow(), subWindows.front());
       
  2338     QCOMPARE(spy.count(), 0);
       
  2339 
       
  2340     // Ctrl-Tab-Tab-Tab
       
  2341     QVERIFY(tabBetweenSubWindowsIn(&mdiArea, 3));
       
  2342     QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(3));
       
  2343     QCOMPARE(spy.count(), 1);
       
  2344 
       
  2345     mdiArea.setActiveSubWindow(subWindows.at(1));
       
  2346     QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(1));
       
  2347     spy.clear();
       
  2348 
       
  2349     // Quick switch (Ctrl-Tab once) -> switch back to the previously active sub-window.
       
  2350     QVERIFY(tabBetweenSubWindowsIn(&mdiArea, 1));
       
  2351     QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(3));
       
  2352     QCOMPARE(spy.count(), 1);
       
  2353 }
       
  2354 
       
  2355 void tst_QMdiArea::setViewMode()
       
  2356 {
       
  2357     QMdiArea mdiArea;
       
  2358 
       
  2359     QPixmap iconPixmap(16, 16);
       
  2360     iconPixmap.fill(Qt::red);
       
  2361     for (int i = 0; i < 5; ++i) {
       
  2362         QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget);
       
  2363         subWindow->setWindowTitle(QString(QLatin1String("Title %1")).arg(i));
       
  2364         subWindow->setWindowIcon(iconPixmap);
       
  2365     }
       
  2366 
       
  2367     mdiArea.show();
       
  2368 #ifdef Q_WS_X11
       
  2369     qt_x11_wait_for_window_manager(&mdiArea);
       
  2370 #endif
       
  2371 
       
  2372     QMdiSubWindow *activeSubWindow = mdiArea.activeSubWindow();
       
  2373     const QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
       
  2374 
       
  2375     // Default.
       
  2376     QVERIFY(!activeSubWindow->isMaximized());
       
  2377     QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
       
  2378     QVERIFY(!tabBar);
       
  2379     QCOMPARE(mdiArea.viewMode(), QMdiArea::SubWindowView);
       
  2380 
       
  2381     // Tabbed view.
       
  2382     mdiArea.setViewMode(QMdiArea::TabbedView);
       
  2383     QCOMPARE(mdiArea.viewMode(), QMdiArea::TabbedView);
       
  2384     tabBar = qFindChild<QTabBar *>(&mdiArea);
       
  2385     QVERIFY(tabBar);
       
  2386     QVERIFY(tabBar->isVisible());
       
  2387 
       
  2388     QCOMPARE(tabBar->count(), subWindows.count());
       
  2389     QVERIFY(activeSubWindow->isMaximized());
       
  2390     QCOMPARE(tabBar->currentIndex(), subWindows.indexOf(activeSubWindow));
       
  2391 
       
  2392     // Check that tabIcon and tabText are set properly.
       
  2393     for (int i = 0; i < subWindows.size(); ++i) {
       
  2394         QMdiSubWindow *subWindow = subWindows.at(i);
       
  2395         QCOMPARE(tabBar->tabText(i), subWindow->windowTitle());
       
  2396         QCOMPARE(tabBar->tabIcon(i), subWindow->windowIcon());
       
  2397     }
       
  2398 
       
  2399     // Check that tabText and tabIcon are updated.
       
  2400     activeSubWindow->setWindowTitle(QLatin1String("Dude, I want another window title"));
       
  2401     QCOMPARE(tabBar->tabText(tabBar->currentIndex()), activeSubWindow->windowTitle());
       
  2402     iconPixmap.fill(Qt::green);
       
  2403     activeSubWindow->setWindowIcon(iconPixmap);
       
  2404     QCOMPARE(tabBar->tabIcon(tabBar->currentIndex()), activeSubWindow->windowIcon());
       
  2405 
       
  2406     // If there's an empty window title, tabText should return "(Untitled)" (as in firefox).
       
  2407     activeSubWindow->setWindowTitle(QString());
       
  2408     QCOMPARE(tabBar->tabText(tabBar->currentIndex()), QLatin1String("(Untitled)"));
       
  2409 
       
  2410     // If there's no window icon, tabIcon should return ... an empty icon :)
       
  2411     activeSubWindow->setWindowIcon(QIcon());
       
  2412     QCOMPARE(tabBar->tabIcon(tabBar->currentIndex()), QIcon());
       
  2413 
       
  2414     // Check that the current tab changes when activating another sub-window.
       
  2415     for (int i = 0; i < subWindows.size(); ++i) {
       
  2416         mdiArea.activateNextSubWindow();
       
  2417         activeSubWindow = mdiArea.activeSubWindow();
       
  2418         QCOMPARE(tabBar->currentIndex(), subWindows.indexOf(activeSubWindow));
       
  2419     }
       
  2420 
       
  2421     activeSubWindow = mdiArea.activeSubWindow();
       
  2422     const int tabIndex = tabBar->currentIndex();
       
  2423 
       
  2424     // The current tab should not change when the sub-window is hidden.
       
  2425     activeSubWindow->hide();
       
  2426     QCOMPARE(tabBar->currentIndex(), tabIndex);
       
  2427     activeSubWindow->show();
       
  2428     QCOMPARE(tabBar->currentIndex(), tabIndex);
       
  2429 
       
  2430     // Disable the tab when the sub-window is hidden and another sub-window is activated.
       
  2431     activeSubWindow->hide();
       
  2432     mdiArea.activateNextSubWindow();
       
  2433     QVERIFY(tabBar->currentIndex() != tabIndex);
       
  2434     QVERIFY(!tabBar->isTabEnabled(tabIndex));
       
  2435 
       
  2436     // Enable it again.
       
  2437     activeSubWindow->show();
       
  2438     QCOMPARE(tabBar->currentIndex(), tabIndex);
       
  2439     QVERIFY(tabBar->isTabEnabled(tabIndex));
       
  2440 
       
  2441     // Remove sub-windows and make sure the tab is removed.
       
  2442     foreach (QMdiSubWindow *subWindow, subWindows) {
       
  2443         if (subWindow != activeSubWindow)
       
  2444             mdiArea.removeSubWindow(subWindow);
       
  2445     }
       
  2446     QCOMPARE(tabBar->count(), 1);
       
  2447 
       
  2448     // Go back to default (QMdiArea::SubWindowView).
       
  2449     mdiArea.setViewMode(QMdiArea::SubWindowView);
       
  2450     QVERIFY(!activeSubWindow->isMaximized());
       
  2451     tabBar = qFindChild<QTabBar *>(&mdiArea);
       
  2452     QVERIFY(!tabBar);
       
  2453     QCOMPARE(mdiArea.viewMode(), QMdiArea::SubWindowView);
       
  2454 }
       
  2455 
       
  2456 void tst_QMdiArea::setTabShape()
       
  2457 {
       
  2458     QMdiArea mdiArea;
       
  2459     mdiArea.addSubWindow(new QWidget);
       
  2460     mdiArea.show();
       
  2461 #ifdef Q_WS_X11
       
  2462     qt_x11_wait_for_window_manager(&mdiArea);
       
  2463 #endif
       
  2464 
       
  2465     // Default.
       
  2466     QCOMPARE(mdiArea.tabShape(), QTabWidget::Rounded);
       
  2467 
       
  2468     // Triangular.
       
  2469     mdiArea.setTabShape(QTabWidget::Triangular);
       
  2470     QCOMPARE(mdiArea.tabShape(), QTabWidget::Triangular);
       
  2471 
       
  2472     mdiArea.setViewMode(QMdiArea::TabbedView);
       
  2473 
       
  2474     QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
       
  2475     QVERIFY(tabBar);
       
  2476     QCOMPARE(tabBar->shape(), QTabBar::TriangularNorth);
       
  2477 
       
  2478     // Back to default (Rounded).
       
  2479     mdiArea.setTabShape(QTabWidget::Rounded);
       
  2480     QCOMPARE(mdiArea.tabShape(), QTabWidget::Rounded);
       
  2481     QCOMPARE(tabBar->shape(), QTabBar::RoundedNorth);
       
  2482 }
       
  2483 
       
  2484 void tst_QMdiArea::setTabPosition_data()
       
  2485 {
       
  2486     QTest::addColumn<QTabWidget::TabPosition>("tabPosition");
       
  2487     QTest::addColumn<bool>("hasLeftMargin");
       
  2488     QTest::addColumn<bool>("hasTopMargin");
       
  2489     QTest::addColumn<bool>("hasRightMargin");
       
  2490     QTest::addColumn<bool>("hasBottomMargin");
       
  2491 
       
  2492     QTest::newRow("North") << QTabWidget::North << false << true << false << false;
       
  2493     QTest::newRow("South") << QTabWidget::South << false << false << false << true;
       
  2494     QTest::newRow("East") << QTabWidget::East << false << false << true << false;
       
  2495     QTest::newRow("West") << QTabWidget::West << true << false << false << false;
       
  2496 }
       
  2497 
       
  2498 void tst_QMdiArea::setTabPosition()
       
  2499 {
       
  2500     QFETCH(QTabWidget::TabPosition, tabPosition);
       
  2501     QFETCH(bool, hasLeftMargin);
       
  2502     QFETCH(bool, hasTopMargin);
       
  2503     QFETCH(bool, hasRightMargin);
       
  2504     QFETCH(bool, hasBottomMargin);
       
  2505 
       
  2506     QMdiArea mdiArea;
       
  2507     mdiArea.addSubWindow(new QWidget);
       
  2508     mdiArea.show();
       
  2509 #ifdef Q_WS_X11
       
  2510     qt_x11_wait_for_window_manager(&mdiArea);
       
  2511 #endif
       
  2512 
       
  2513     // Make sure there are no margins.
       
  2514     mdiArea.setContentsMargins(0, 0, 0, 0);
       
  2515 
       
  2516     // Default.
       
  2517     QCOMPARE(mdiArea.tabPosition(), QTabWidget::North);
       
  2518     mdiArea.setViewMode(QMdiArea::TabbedView);
       
  2519     QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
       
  2520     QVERIFY(tabBar);
       
  2521     QCOMPARE(tabBar->shape(), QTabBar::RoundedNorth);
       
  2522 
       
  2523     // New position.
       
  2524     mdiArea.setTabPosition(tabPosition);
       
  2525     QCOMPARE(mdiArea.tabPosition(), tabPosition);
       
  2526     QCOMPARE(tabBar->shape(), tabBarShapeFrom(QTabWidget::Rounded, tabPosition));
       
  2527 
       
  2528     const Qt::LayoutDirection originalLayoutDirection = qApp->layoutDirection();
       
  2529 
       
  2530     // Check that we have correct geometry in both RightToLeft and LeftToRight.
       
  2531     for (int i = 0; i < 2; ++i) {
       
  2532         // Check viewportMargins.
       
  2533         const QRect viewportGeometry = mdiArea.viewport()->geometry();
       
  2534         const int left = viewportGeometry.left();
       
  2535         const int top = viewportGeometry.y();
       
  2536         const int right = mdiArea.width() - viewportGeometry.width();
       
  2537         const int bottom = mdiArea.height() - viewportGeometry.height();
       
  2538 
       
  2539         const QSize sizeHint = tabBar->sizeHint();
       
  2540 
       
  2541         if (hasLeftMargin)
       
  2542             QCOMPARE(qApp->isLeftToRight() ? left : right, sizeHint.width());
       
  2543         if (hasRightMargin)
       
  2544             QCOMPARE(qApp->isLeftToRight() ? right : left, sizeHint.width());
       
  2545         if (hasTopMargin || hasBottomMargin)
       
  2546             QCOMPARE(hasTopMargin ? top : bottom, sizeHint.height());
       
  2547 
       
  2548         // Check actual tab bar geometry.
       
  2549         const QRegion expectedTabBarGeometry = QRegion(mdiArea.rect()).subtracted(viewportGeometry);
       
  2550         QVERIFY(!expectedTabBarGeometry.isEmpty());
       
  2551         QCOMPARE(QRegion(tabBar->geometry()), expectedTabBarGeometry);
       
  2552 
       
  2553         if (i == 0)
       
  2554             qApp->setLayoutDirection(originalLayoutDirection == Qt::LeftToRight ? Qt::RightToLeft : Qt::LeftToRight);
       
  2555         qApp->processEvents();
       
  2556     }
       
  2557 
       
  2558     qApp->setLayoutDirection(originalLayoutDirection);
       
  2559 }
       
  2560 
       
  2561 #if defined(Q_WS_WIN) || defined(Q_WS_X11)
       
  2562 void tst_QMdiArea::nativeSubWindows()
       
  2563 {
       
  2564     { // Add native widgets after show.
       
  2565     QMdiArea mdiArea;
       
  2566     mdiArea.addSubWindow(new QWidget);
       
  2567     mdiArea.addSubWindow(new QWidget);
       
  2568     mdiArea.show();
       
  2569 #ifdef Q_WS_X11
       
  2570     qt_x11_wait_for_window_manager(&mdiArea);
       
  2571 #endif
       
  2572 
       
  2573     // No native widgets.
       
  2574     QVERIFY(!mdiArea.viewport()->internalWinId());
       
  2575     foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
       
  2576         QVERIFY(!subWindow->internalWinId());
       
  2577 
       
  2578     QWidget *nativeWidget = new QWidget;
       
  2579     QVERIFY(nativeWidget->winId()); // enforce native window.
       
  2580     mdiArea.addSubWindow(nativeWidget);
       
  2581 
       
  2582     // The viewport and all the sub-windows must be native.
       
  2583     QVERIFY(mdiArea.viewport()->internalWinId());
       
  2584     foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
       
  2585         QVERIFY(subWindow->internalWinId());
       
  2586 
       
  2587     // Add a non-native widget. This should become native.
       
  2588     QMdiSubWindow *subWindow = new QMdiSubWindow;
       
  2589     subWindow->setWidget(new QWidget);
       
  2590     QVERIFY(!subWindow->internalWinId());
       
  2591     mdiArea.addSubWindow(subWindow);
       
  2592     QVERIFY(subWindow->internalWinId());
       
  2593     }
       
  2594 
       
  2595     { // Add native widgets before show.
       
  2596     QMdiArea mdiArea;
       
  2597     mdiArea.addSubWindow(new QWidget);
       
  2598     QWidget *nativeWidget = new QWidget;
       
  2599     (void)nativeWidget->winId();
       
  2600     mdiArea.addSubWindow(nativeWidget);
       
  2601     mdiArea.show();
       
  2602 #ifdef Q_WS_X11
       
  2603     qt_x11_wait_for_window_manager(&mdiArea);
       
  2604 #endif
       
  2605 
       
  2606     // The viewport and all the sub-windows must be native.
       
  2607     QVERIFY(mdiArea.viewport()->internalWinId());
       
  2608     foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
       
  2609         QVERIFY(subWindow->internalWinId());
       
  2610     }
       
  2611 
       
  2612     { // Make a sub-window native *after* it's added to the area.
       
  2613     QMdiArea mdiArea;
       
  2614     mdiArea.addSubWindow(new QWidget);
       
  2615     mdiArea.addSubWindow(new QWidget);
       
  2616     mdiArea.show();
       
  2617 #ifdef Q_WS_X11
       
  2618     qt_x11_wait_for_window_manager(&mdiArea);
       
  2619 #endif
       
  2620 
       
  2621     QMdiSubWindow *nativeSubWindow = mdiArea.subWindowList().last();
       
  2622     QVERIFY(!nativeSubWindow->internalWinId());
       
  2623     (void)nativeSubWindow->winId();
       
  2624 
       
  2625     // All the sub-windows should be native at this point
       
  2626     QVERIFY(mdiArea.viewport()->internalWinId());
       
  2627     foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
       
  2628             QVERIFY(subWindow->internalWinId());
       
  2629     }
       
  2630 
       
  2631 #ifndef QT_NO_OPENGL
       
  2632     {
       
  2633     if (!QGLFormat::hasOpenGL())
       
  2634         QSKIP("QGL not supported on this platform", SkipAll);
       
  2635 
       
  2636     QMdiArea mdiArea;
       
  2637     QGLWidget *glViewport = new QGLWidget;
       
  2638     mdiArea.setViewport(glViewport);
       
  2639     mdiArea.addSubWindow(new QWidget);
       
  2640     mdiArea.addSubWindow(new QWidget);
       
  2641     mdiArea.show();
       
  2642 #ifdef Q_WS_X11
       
  2643     qt_x11_wait_for_window_manager(&mdiArea);
       
  2644 #endif
       
  2645 
       
  2646     const QGLContext *context = glViewport->context();
       
  2647     if (!context || !context->isValid())
       
  2648         QSKIP("QGL is broken, cannot continue test", SkipAll);
       
  2649 
       
  2650     // The viewport and all the sub-windows must be native.
       
  2651     QVERIFY(mdiArea.viewport()->internalWinId());
       
  2652     foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
       
  2653         QVERIFY(subWindow->internalWinId());
       
  2654     }
       
  2655 #endif
       
  2656 }
       
  2657 #endif
       
  2658 
       
  2659 void tst_QMdiArea::task_209615()
       
  2660 {
       
  2661     QTabWidget tabWidget;
       
  2662     QMdiArea *mdiArea1 = new QMdiArea;
       
  2663     QMdiArea *mdiArea2 = new QMdiArea;
       
  2664     QMdiSubWindow *subWindow = mdiArea1->addSubWindow(new QLineEdit);
       
  2665 
       
  2666     tabWidget.addTab(mdiArea1, QLatin1String("1"));
       
  2667     tabWidget.addTab(mdiArea2, QLatin1String("2"));
       
  2668     tabWidget.show();
       
  2669 
       
  2670     mdiArea1->removeSubWindow(subWindow);
       
  2671     mdiArea2->addSubWindow(subWindow);
       
  2672 
       
  2673     // Please do not assert/crash.
       
  2674     tabWidget.setCurrentIndex(1);
       
  2675 }
       
  2676 
       
  2677 void tst_QMdiArea::task_236750()
       
  2678 {
       
  2679     QMdiArea mdiArea;
       
  2680     QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QTextEdit);
       
  2681     mdiArea.show();
       
  2682 
       
  2683     subWindow->setWindowFlags(subWindow->windowFlags() | Qt::FramelessWindowHint);
       
  2684     // Please do not crash (floating point exception).
       
  2685     subWindow->showMinimized();
       
  2686 }
       
  2687 
       
  2688 QTEST_MAIN(tst_QMdiArea)
       
  2689 #include "tst_qmdiarea.moc"
       
  2690