Fix QIODevice::getChar optimization
[qt-netbsd.git] / tests / auto / qmdiarea / tst_qmdiarea.cpp
blob068d1faa39f013071ca6059b271c3b1704cb1297
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.
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.
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.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
38 ** $QT_END_LICENSE$
40 ****************************************************************************/
43 #include <QtTest/QtTest>
45 #include <QMdiSubWindow>
46 #include <QMdiArea>
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>
65 #include "../../shared/util.h"
67 static const Qt::WindowFlags DefaultWindowFlags
68 = Qt::SubWindow | Qt::WindowSystemMenuHint
69 | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint;
71 Q_DECLARE_METATYPE(QMdiArea::WindowOrder)
72 Q_DECLARE_METATYPE(QMdiSubWindow *)
73 Q_DECLARE_METATYPE(QList<int>)
74 Q_DECLARE_METATYPE(QTabWidget::TabPosition)
76 //TESTED_CLASS=
77 //TESTED_FILES=
79 static bool tabBetweenSubWindowsIn(QMdiArea *mdiArea, int tabCount = -1, bool reverse = false)
81 if (!mdiArea) {
82 qWarning("Null pointer to mdi area");
83 return false;
86 QList<QMdiSubWindow *> subWindows = mdiArea->subWindowList();
87 const bool walkThrough = tabCount == -1;
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;
96 tabCount = subWindows.size();
99 QWidget *focusWidget = qApp->focusWidget();
100 if (!focusWidget) {
101 qWarning("No focus widget");
102 return false;
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
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;
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;
132 qApp->processEvents();
134 QTest::keyRelease(focusWidget, key);
136 return true;
139 static inline QTabBar::Shape tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position)
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;
153 enum Arrangement {
154 Tiled,
155 Cascaded
158 static bool verifyArrangement(QMdiArea *mdiArea, Arrangement arrangement, const QList<int> &expectedIndices)
160 if (!mdiArea || expectedIndices.isEmpty() || mdiArea->subWindowList().isEmpty())
161 return false;
163 const QList<QMdiSubWindow *> subWindows = mdiArea->subWindowList();
164 const QMdiSubWindow *const firstSubWindow = subWindows.at(0);
166 switch (arrangement) {
167 case Tiled:
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);
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;
189 subWindowPos.rx() = columnWidth / 2;
190 subWindowPos.ry() += rowHeight;
192 break;
194 case Cascaded:
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;
209 // Current activation/stacking order.
210 const QList<QMdiSubWindow *> activationOrderList = mdiArea->subWindowList(QMdiArea::ActivationHistoryOrder);
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;
226 // Restore stacking order.
227 foreach (QMdiSubWindow *subWindow, activationOrderList) {
228 mdiArea->setActiveSubWindow(subWindow);
229 qApp->processEvents();
231 break;
233 default:
234 return false;
236 return true;
239 class tst_QMdiArea : public QObject
241 Q_OBJECT
242 public:
243 tst_QMdiArea();
244 public slots:
245 void initTestCase();
246 protected slots:
247 void activeChanged(QMdiSubWindow *child);
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();
298 private:
299 QMdiSubWindow *activeWindow;
300 bool accelPressed;
303 tst_QMdiArea::tst_QMdiArea()
304 : activeWindow(0)
306 qRegisterMetaType<QMdiSubWindow *>();
309 void tst_QMdiArea::initTestCase()
311 #ifdef Q_OS_WINCE //disable magic for WindowsCE
312 qApp->setAutoMaximizeThreshold(-1);
313 #endif
316 // Old QWorkspace tests
317 void tst_QMdiArea::activeChanged(QMdiSubWindow *child)
319 activeWindow = child;
322 void tst_QMdiArea::subWindowActivated_data()
324 // define the test elements we're going to use
325 QTest::addColumn<int>("count");
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;
333 void tst_QMdiArea::subWindowActivated()
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);
345 QFETCH( int, count );
346 int i;
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();
359 QList<QMdiSubWindow *> windows = workspace->subWindowList();
360 QCOMPARE( (int)windows.count(), count );
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 );
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() );
378 spy.clear();
380 while (workspace->activeSubWindow() ) {
381 workspace->activeSubWindow()->close();
382 qApp->processEvents();
383 QVERIFY(activeWindow == workspace->activeSubWindow());
384 QCOMPARE(spy.count(), 1);
385 spy.clear();
388 QVERIFY(activeWindow == 0);
389 QVERIFY(workspace->activeSubWindow() == 0);
390 QCOMPARE(workspace->subWindowList().count(), 0);
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 );
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 );
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 );
448 #ifdef Q_WS_MAC
449 #include <Security/AuthSession.h>
450 bool macHasAccessToWindowsServer()
452 SecuritySessionId mySession;
453 SessionAttributeBits sessionInfo;
454 SessionGetInfo(callerSecuritySession, &mySession, &sessionInfo);
455 return (sessionInfo & sessionHasGraphicAccess);
457 #endif
460 void tst_QMdiArea::subWindowActivated2()
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);
473 QTRY_COMPARE(spy.count(), 5);
474 QCOMPARE(mdiArea.activeSubWindow(), mdiArea.subWindowList().back());
475 spy.clear();
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();
486 QMdiSubWindow *activeSubWindow = mdiArea.subWindowList().at(2);
487 mdiArea.setActiveSubWindow(activeSubWindow);
488 QCOMPARE(spy.count(), 1);
489 QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow);
490 spy.clear();
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();
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();
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();
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();
544 void tst_QMdiArea::subWindowActivatedWithMinimize()
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);
562 widget->showMinimized();
563 QVERIFY( activeWindow == window1 );
564 widget2->showMinimized();
565 QVERIFY( activeWindow == window2 );
567 window2->close();
568 qApp->processEvents();
569 QVERIFY( activeWindow == window1 );
571 window1->close();
572 qApp->processEvents();
573 QVERIFY(workspace->activeSubWindow() == 0);
574 QVERIFY( activeWindow == 0 );
576 QVERIFY( workspace->subWindowList().count() == 0 );
579 void tst_QMdiArea::showWindows()
581 QMdiArea *ws = new QMdiArea( 0 );
583 QWidget *widget = 0;
584 ws->show();
586 widget = new QWidget(ws);
587 widget->show();
588 QVERIFY( widget->isVisible() );
590 widget = new QWidget(ws);
591 widget->showMaximized();
592 QVERIFY( widget->isMaximized() );
593 widget->showNormal();
594 QVERIFY( !widget->isMaximized() );
596 widget = new QWidget(ws);
597 widget->showMinimized();
598 QVERIFY( widget->isMinimized() );
599 widget->showNormal();
600 QVERIFY( !widget->isMinimized() );
602 ws->hide();
604 widget = new QWidget(ws);
605 ws->show();
606 QVERIFY( widget->isVisible() );
608 ws->hide();
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();
618 widget = new QWidget(ws);
619 widget->showMinimized();
620 ws->show();
621 QVERIFY( widget->isMinimized() );
622 ws->hide();
624 delete ws;
628 //#define USE_SHOW
630 void tst_QMdiArea::changeWindowTitle()
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");
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);
645 QWidget *widget = new QWidget( ws );
646 widget->setWindowTitle( wc );
647 ws->addSubWindow(widget);
649 QCOMPARE( mw->windowTitle(), mwc );
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
660 mw->hide();
661 qApp->processEvents();
662 mw->show();
663 qApp->processEvents();
664 QTest::qWaitForWindowShown(mw);
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
670 #ifdef USE_SHOW
671 widget->showNormal();
672 #else
673 widget->setWindowState(Qt::WindowNoState);
674 #endif
675 qApp->processEvents();
676 QCOMPARE( mw->windowTitle(), mwc );
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
692 mw->show();
693 qApp->setActiveWindow(mw);
695 #ifdef USE_SHOW
696 mw->showFullScreen();
697 #else
698 mw->setWindowState(Qt::WindowFullScreen);
699 #endif
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
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
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
739 delete mw;
742 void tst_QMdiArea::changeModified()
744 const QString mwc = QString::fromLatin1("MainWindow's Caption");
745 const QString wc = QString::fromLatin1("Widget's Caption[*]");
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();
754 QWidget *widget = new QWidget( ws );
755 widget->setWindowTitle( wc );
756 ws->addSubWindow(widget);
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);
764 widget->setWindowState(Qt::WindowNoState);
765 QCOMPARE( mw->isWindowModified(), false);
766 QCOMPARE( widget->isWindowModified(), false);
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);
777 widget->setWindowState(Qt::WindowNoState);
778 QCOMPARE( mw->isWindowModified(), false);
779 QCOMPARE( widget->isWindowModified(), true);
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);
787 widget->setWindowModified(false);
788 QCOMPARE( mw->isWindowModified(), false);
789 QCOMPARE( widget->isWindowModified(), false);
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);
797 widget->setWindowState(Qt::WindowNoState);
798 QCOMPARE( mw->isWindowModified(), false);
799 QCOMPARE( widget->isWindowModified(), true);
801 delete mw;
804 class MyChild : public QWidget
806 public:
807 MyChild(QWidget *parent = 0) : QWidget(parent) {}
808 QSize sizeHint() const { return QSize(234, 123); }
811 void tst_QMdiArea::childSize()
813 QMdiArea ws;
815 MyChild *child = new MyChild(&ws);
816 child->show();
817 QCOMPARE(child->size(), child->sizeHint());
818 delete child;
820 child = new MyChild(&ws);
821 child->setFixedSize(200, 200);
822 child->show();
823 QCOMPARE(child->size(), child->minimumSize());
824 delete child;
826 child = new MyChild(&ws);
827 child->resize(150, 150);
828 child->show();
829 QCOMPARE(child->size(), QSize(150,150));
830 delete child;
833 void tst_QMdiArea::fixedSize()
835 QMdiArea *ws = new QMdiArea;
836 int i;
838 ws->resize(500, 500);
839 // ws->show();
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();
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);
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);
860 ws->resize(500, 500);
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);
868 ws->resize(500, 500);
870 for (i = 0; i < (int)windows.count(); ++i) {
871 QMdiSubWindow *child = windows.at(i);
872 delete child;
875 delete ws;
878 class LargeWidget : public QWidget
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); }
886 // New tests
887 void tst_QMdiArea::minimumSizeHint()
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()));
899 QWidget *window = workspace.addSubWindow(new QWidget);
900 qApp->processEvents();
901 window->show();
902 QCOMPARE(workspace.minimumSizeHint(), expectedSize.expandedTo(window->minimumSizeHint()));
904 QMdiSubWindow *subWindow = workspace.addSubWindow(new LargeWidget);
905 subWindow->show();
906 QCOMPARE(workspace.minimumSizeHint(), expectedSize.expandedTo(subWindow->minimumSizeHint()));
908 workspace.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
909 workspace.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
910 QCOMPARE(workspace.minimumSizeHint(), expectedSize);
913 void tst_QMdiArea::sizeHint()
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()));
921 QWidget *window = workspace.addSubWindow(new QWidget);
922 qApp->processEvents();
923 window->show();
924 QCOMPARE(workspace.sizeHint(), expectedSize.expandedTo(window->sizeHint()));
926 QMdiSubWindow *nested = workspace.addSubWindow(new QMdiArea);
927 expectedSize = QSize(desktopSize.width() * 2/6, desktopSize.height() * 2/6);
928 QCOMPARE(nested->widget()->sizeHint(), expectedSize);
931 void tst_QMdiArea::setActiveSubWindow()
933 QMdiArea workspace;
934 workspace.show();
936 QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
937 connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
938 qApp->setActiveWindow(&workspace);
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]);
949 QCOMPARE(spy.count(), 0);
950 QVERIFY(!activeWindow);
951 spy.clear();
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();
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());
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);
978 void tst_QMdiArea::activeSubWindow()
980 QMainWindow mainWindow;
982 QMdiArea *mdiArea = new QMdiArea;
983 QLineEdit *subWindowLineEdit = new QLineEdit;
984 QMdiSubWindow *subWindow = mdiArea->addSubWindow(subWindowLineEdit);
985 mainWindow.setCentralWidget(mdiArea);
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);
993 mainWindow.show();
994 #ifdef Q_WS_X11
995 qt_x11_wait_for_window_manager(&mainWindow);
996 #endif
998 qApp->setActiveWindow(&mainWindow);
999 QCOMPARE(mdiArea->activeSubWindow(), subWindow);
1000 QCOMPARE(qApp->focusWidget(), (QWidget *)subWindowLineEdit);
1002 dockWidgetLineEdit->setFocus();
1003 QCOMPARE(qApp->focusWidget(), (QWidget *)dockWidgetLineEdit);
1004 QCOMPARE(mdiArea->activeSubWindow(), subWindow);
1006 QEvent deactivateEvent(QEvent::WindowDeactivate);
1007 qApp->sendEvent(subWindow, &deactivateEvent);
1008 QVERIFY(!mdiArea->activeSubWindow());
1009 QCOMPARE(qApp->focusWidget(), (QWidget *)dockWidgetLineEdit);
1011 QEvent activateEvent(QEvent::WindowActivate);
1012 qApp->sendEvent(subWindow, &activateEvent);
1013 QCOMPARE(mdiArea->activeSubWindow(), subWindow);
1014 QCOMPARE(qApp->focusWidget(), (QWidget *)subWindowLineEdit);
1016 QLineEdit dummyTopLevel;
1017 dummyTopLevel.show();
1018 #ifdef Q_WS_X11
1019 qt_x11_wait_for_window_manager(&dummyTopLevel);
1020 #endif
1022 qApp->setActiveWindow(&dummyTopLevel);
1023 QCOMPARE(mdiArea->activeSubWindow(), subWindow);
1025 qApp->setActiveWindow(&mainWindow);
1026 QCOMPARE(mdiArea->activeSubWindow(), subWindow);
1028 #if !defined(Q_WS_MAC) && !defined(Q_WS_WIN)
1029 qApp->setActiveWindow(0);
1030 QVERIFY(!mdiArea->activeSubWindow());
1031 #endif
1033 //task 202657
1034 dockWidgetLineEdit->setFocus();
1035 qApp->setActiveWindow(&mainWindow);
1036 QVERIFY(dockWidgetLineEdit->hasFocus());
1039 void tst_QMdiArea::currentSubWindow()
1041 QMdiArea mdiArea;
1042 mdiArea.show();
1043 #ifdef Q_WS_X11
1044 qt_x11_wait_for_window_manager(&mdiArea);
1045 #endif
1047 for (int i = 0; i < 5; ++i)
1048 mdiArea.addSubWindow(new QLineEdit)->show();
1050 qApp->setActiveWindow(&mdiArea);
1051 QCOMPARE(qApp->activeWindow(), (QWidget *)&mdiArea);
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);
1059 QLineEdit dummyTopLevel;
1060 dummyTopLevel.show();
1061 #ifdef Q_WS_X11
1062 qt_x11_wait_for_window_manager(&dummyTopLevel);
1063 #endif
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());
1071 delete active;
1072 active = 0;
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());
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());
1085 active->hide();
1086 QCOMPARE(mdiArea.activeSubWindow(), active);
1087 QCOMPARE(mdiArea.currentSubWindow(), active);
1089 qApp->setActiveWindow(&dummyTopLevel);
1090 QVERIFY(mdiArea.activeSubWindow());
1091 QCOMPARE(mdiArea.currentSubWindow(), active);
1093 qApp->setActiveWindow(&mdiArea);
1094 active->show();
1095 QCOMPARE(mdiArea.activeSubWindow(), active);
1097 mdiArea.setActiveSubWindow(0);
1098 QVERIFY(!mdiArea.activeSubWindow());
1099 QVERIFY(!mdiArea.currentSubWindow());
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());
1108 QEvent windowActivate(QEvent::WindowActivate);
1109 qApp->sendEvent(active, &windowActivate);
1110 QVERIFY(mdiArea.activeSubWindow());
1111 QVERIFY(mdiArea.currentSubWindow());
1113 #if !defined(Q_WS_MAC) && !defined(Q_WS_WIN)
1114 qApp->setActiveWindow(0);
1115 QVERIFY(!mdiArea.activeSubWindow());
1116 QVERIFY(mdiArea.currentSubWindow());
1117 #endif
1120 void tst_QMdiArea::addAndRemoveWindows()
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
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());
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());
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));
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);
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);
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);
1186 // removeSubWindow
1187 foreach (QWidget *window, workspace.subWindowList()) {
1188 workspace.removeSubWindow(window);
1189 delete window;
1191 QCOMPARE(workspace.subWindowList().count(), 0);
1193 // removeSubWindow with 0 pointer
1194 QTest::ignoreMessage(QtWarningMsg, "QMdiArea::removeSubWindow: null pointer to widget");
1195 workspace.removeSubWindow(0);
1197 workspace.addSubWindow(new QPushButton(QLatin1String("Dummy to make workspace non-empty")));
1198 qApp->processEvents();
1199 QCOMPARE(workspace.subWindowList().count(), 1);
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;
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));
1217 window1->showMinimized();
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));
1225 window2->showMaximized();
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));
1233 void tst_QMdiArea::addAndRemoveWindowsWithReparenting()
1235 QMdiArea workspace;
1236 QMdiSubWindow window(&workspace);
1237 QVERIFY(window.windowFlags() == DefaultWindowFlags);
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();
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);
1252 QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: window is already added");
1253 workspace.addSubWindow(&window);
1254 QCOMPARE(workspace.subWindowList().count(), 1);
1257 class MySubWindow : public QMdiSubWindow
1259 public:
1260 using QObject::receivers;
1263 static int numberOfConnectedSignals(MySubWindow *subWindow)
1265 if (!subWindow)
1266 return 0;
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());
1277 return numConnectedSignals;
1280 void tst_QMdiArea::removeSubWindow_2()
1282 QMdiArea mdiArea;
1283 MySubWindow *subWindow = new MySubWindow;
1284 QCOMPARE(numberOfConnectedSignals(subWindow), 0);
1286 // Connected to aboutToActivate() and windowStateChanged().
1287 mdiArea.addSubWindow(subWindow);
1288 QVERIFY(numberOfConnectedSignals(subWindow) >= 2);
1290 // Ensure we disconnect from all signals.
1291 mdiArea.removeSubWindow(subWindow);
1292 QCOMPARE(numberOfConnectedSignals(subWindow), 0);
1294 mdiArea.addSubWindow(subWindow);
1295 QVERIFY(numberOfConnectedSignals(subWindow) >= 2);
1296 subWindow->setParent(0);
1297 QCOMPARE(numberOfConnectedSignals(subWindow), 0);
1300 void tst_QMdiArea::closeWindows()
1302 QMdiArea workspace;
1303 workspace.show();
1304 qApp->setActiveWindow(&workspace);
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);
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);
1322 const int windowCount = 10;
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;
1335 QCOMPARE(activeSubWindowCount, windowCount);
1336 QCOMPARE(workspace.subWindowList().count(), 0);
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);
1352 void tst_QMdiArea::activateNextAndPreviousWindow()
1354 QMdiArea workspace;
1355 workspace.show();
1356 qApp->setActiveWindow(&workspace);
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();
1366 QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
1367 connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
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();
1377 QVERIFY(activeWindow);
1378 QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
1379 QCOMPARE(workspace.activeSubWindow(), activeWindow);
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
1391 QVERIFY(activeWindow);
1392 QCOMPARE(workspace.activeSubWindow(), windows[0]);
1393 QCOMPARE(workspace.activeSubWindow(), activeWindow);
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();
1401 QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
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();
1409 QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
1411 workspace.setActiveSubWindow(0);
1412 QVERIFY(!activeWindow);
1415 void tst_QMdiArea::subWindowList_data()
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");
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;
1427 void tst_QMdiArea::subWindowList()
1429 QFETCH(QMdiArea::WindowOrder, windowOrder);
1430 QFETCH(int, windowCount);
1431 QFETCH(int, activeSubWindow);
1432 QFETCH(int, staysOnTop1);
1433 QFETCH(int, staysOnTop2);
1435 QMdiArea workspace;
1436 workspace.show();
1437 qApp->setActiveWindow(&workspace);
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]);
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]);
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);
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;
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);
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);
1483 workspace.setActiveSubWindow(windows[activeSubWindow]);
1484 qApp->processEvents();
1485 QCOMPARE(workspace.activeSubWindow(), windows[activeSubWindow]);
1486 activationOrder.move(activationOrder.indexOf(windows[activeSubWindow]), windowCount - 1);
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);
1498 windows[activeSubWindow]->raise();
1499 windows[staysOnTop2]->lower();
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);
1510 windows[activeSubWindow]->stackUnder(windows[staysOnTop1]);
1511 windows[staysOnTop2]->raise();
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);
1522 workspace.setActiveSubWindow(windows[staysOnTop1]);
1523 activationOrder.move(activationOrder.indexOf(windows[staysOnTop1]), windowCount - 1);
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);
1535 void tst_QMdiArea::setBackground()
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));
1543 void tst_QMdiArea::setViewport()
1545 QMdiArea workspace;
1546 workspace.show();
1548 QWidget *firstViewport = workspace.viewport();
1549 QVERIFY(firstViewport);
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());
1564 qApp->processEvents();
1565 QList<QMdiSubWindow *> windowsBeforeViewportChange = workspace.subWindowList();
1566 QCOMPARE(windowsBeforeViewportChange.count(), windowCount);
1568 workspace.setViewport(new QWidget);
1569 qApp->processEvents();
1570 QVERIFY(workspace.viewport() != firstViewport);
1572 QList<QMdiSubWindow *> windowsAfterViewportChange = workspace.subWindowList();
1573 QCOMPARE(windowsAfterViewportChange.count(), windowCount);
1574 QCOMPARE(windowsAfterViewportChange, windowsBeforeViewportChange);
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 // }
1584 QTest::ignoreMessage(QtWarningMsg, "QMdiArea: Deleting the view port is undefined, "
1585 "use setViewport instead.");
1586 delete workspace.viewport();
1587 qApp->processEvents();
1589 QCOMPARE(workspace.subWindowList().count(), 0);
1590 QVERIFY(!workspace.activeSubWindow());
1593 void tst_QMdiArea::tileSubWindows()
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
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();
1608 workspace.tileSubWindows();
1609 workspace.setActiveSubWindow(0);
1610 QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
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()));
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();
1627 workspace.setActiveSubWindow(0);
1628 #ifndef Q_OS_WINCE //See Task 197453 ToDo
1629 QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
1630 #endif
1632 QMdiSubWindow *window = windows.at(0);
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();
1642 // Re-tile.
1643 workspace.tileSubWindows();
1644 workspace.setActiveSubWindow(0);
1645 QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
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();
1655 // Re-tile.
1656 workspace.tileSubWindows();
1657 workspace.setActiveSubWindow(0);
1658 QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
1660 window = windows.at(1);
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();
1671 // Re-tile.
1672 workspace.tileSubWindows();
1673 workspace.setActiveSubWindow(0);
1674 QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
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();
1685 // Re-tile.
1686 workspace.tileSubWindows();
1687 workspace.setActiveSubWindow(0);
1688 QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
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());
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());
1703 // Re-tile.
1704 workspace.tileSubWindows();
1705 workspace.setActiveSubWindow(0);
1706 QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
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());
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));
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));
1729 const QSize minSize(300, 100);
1730 foreach (QMdiSubWindow *subWindow, workspace.subWindowList())
1731 subWindow->setMinimumSize(minSize);
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);
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));
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);
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);
1773 workspace.tileSubWindows();
1774 #ifdef Q_WS_X11
1775 qt_x11_wait_for_window_manager(&workspace);
1776 #endif
1777 qApp->processEvents();
1779 QTRY_VERIFY(workspace.size() != QSize(150, 150));
1780 QTRY_VERIFY(!vBar->isVisible());
1781 QTRY_VERIFY(!hBar->isVisible());
1784 void tst_QMdiArea::cascadeAndTileSubWindows()
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
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());
1804 windows.append(window);
1807 // cascadeSubWindows
1808 qApp->processEvents();
1809 workspace.cascadeSubWindows();
1810 qApp->processEvents();
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);
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());
1836 void tst_QMdiArea::resizeMaximizedChildWindows_data()
1838 QTest::addColumn<int>("startSize");
1839 QTest::addColumn<int>("increment");
1840 QTest::addColumn<int>("windowCount");
1842 QTest::newRow("multiple children") << 400 << 20 << 10;
1845 void tst_QMdiArea::resizeMaximizedChildWindows()
1847 QFETCH(int, startSize);
1848 QFETCH(int, increment);
1849 QFETCH(int, windowCount);
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));
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());
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();
1883 int newSize = startSize + increment * windowCount;
1884 QCOMPARE(workspaceSize, QSize(newSize, newSize));
1885 foreach (QWidget *window, windows)
1886 QCOMPARE(window->rect(), workspace.contentsRect());
1889 // QWidget::setParent clears focusWidget so make sure
1890 // we restore it after QMdiArea::addSubWindow.
1891 void tst_QMdiArea::focusWidgetAfterAddSubWindow()
1893 QWidget *view = new QWidget;
1894 view->setLayout(new QVBoxLayout);
1896 QLineEdit *lineEdit1 = new QLineEdit;
1897 QLineEdit *lineEdit2 = new QLineEdit;
1898 view->layout()->addWidget(lineEdit1);
1899 view->layout()->addWidget(lineEdit2);
1901 lineEdit2->setFocus();
1902 QCOMPARE(view->focusWidget(), static_cast<QWidget *>(lineEdit2));
1904 QMdiArea mdiArea;
1905 mdiArea.addSubWindow(view);
1906 QCOMPARE(view->focusWidget(), static_cast<QWidget *>(lineEdit2));
1908 mdiArea.show();
1909 view->show();
1910 qApp->setActiveWindow(&mdiArea);
1911 QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(lineEdit2));
1914 void tst_QMdiArea::dontMaximizeSubWindowOnActivation()
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);
1923 // Add one maximized window.
1924 mdiArea.addSubWindow(new QWidget)->showMaximized();
1925 QVERIFY(mdiArea.activeSubWindow());
1926 QVERIFY(mdiArea.activeSubWindow()->isMaximized());
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();
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();
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();
1957 // Enable 'DontMaximizedSubWindowOnActivation' and maximize the active window.
1958 mdiArea.setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
1959 mdiArea.activeSubWindow()->showMaximized();
1960 int indexOfMaximized = subWindows.indexOf(mdiArea.activeSubWindow());
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();
1971 QVERIFY(mdiArea.activeSubWindow()->isMaximized());
1973 // Minimize all windows.
1974 foreach (QMdiSubWindow *window, subWindows) {
1975 window->showMinimized();
1976 QVERIFY(window->isMinimized());
1977 qApp->processEvents();
1980 // Disable 'DontMaximizedSubWindowOnActivation' and maximize the active window.
1981 mdiArea.setOption(QMdiArea::DontMaximizeSubWindowOnActivation, false);
1982 mdiArea.activeSubWindow()->showMaximized();
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();
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();
2002 QVERIFY(!mdiArea.activeSubWindow());
2003 QCOMPARE(mdiArea.subWindowList().size(), 0);
2005 // Verify that new windows are not maximized.
2006 mdiArea.addSubWindow(new QWidget)->show();
2007 QVERIFY(mdiArea.activeSubWindow());
2008 QVERIFY(!mdiArea.activeSubWindow()->isMaximized());
2011 void tst_QMdiArea::delayedPlacement()
2013 QMdiArea mdiArea;
2015 QMdiSubWindow *window1 = mdiArea.addSubWindow(new QWidget);
2016 QCOMPARE(window1->geometry().topLeft(), QPoint(0, 0));
2018 QMdiSubWindow *window2 = mdiArea.addSubWindow(new QWidget);
2019 QCOMPARE(window2->geometry().topLeft(), QPoint(0, 0));
2021 QMdiSubWindow *window3 = mdiArea.addSubWindow(new QWidget);
2022 QCOMPARE(window3->geometry().topLeft(), QPoint(0, 0));
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
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));
2035 void tst_QMdiArea::iconGeometryInMenuBar()
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
2048 subWindow->showMaximized();
2049 QVERIFY(subWindow->isMaximized());
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
2063 class EventSpy : public QObject
2065 public:
2066 EventSpy(QObject *object, QEvent::Type event)
2067 : eventToSpy(event), _count(0)
2069 if (object)
2070 object->installEventFilter(this);
2073 int count() const { return _count; }
2074 void clear() { _count = 0; }
2076 protected:
2077 bool eventFilter(QObject *object, QEvent *event)
2079 if (event->type() == eventToSpy)
2080 ++_count;
2081 return QObject::eventFilter(object, event);
2084 private:
2085 QEvent::Type eventToSpy;
2086 int _count;
2089 void tst_QMdiArea::resizeTimer()
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
2098 #ifndef Q_OS_WINCE
2099 int time = 250;
2100 #else
2101 int time = 1000;
2102 #endif
2104 QTest::qWait(time);
2106 EventSpy timerEventSpy(subWindow, QEvent::Timer);
2107 QCOMPARE(timerEventSpy.count(), 0);
2109 mdiArea.tileSubWindows();
2110 QTest::qWait(time); // Wait for timer events to occur.
2111 QCOMPARE(timerEventSpy.count(), 1);
2112 timerEventSpy.clear();
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();
2119 // Check that timers are killed.
2120 QTest::qWait(time); // Wait for timer events to occur.
2121 QCOMPARE(timerEventSpy.count(), 0);
2124 void tst_QMdiArea::updateScrollBars()
2126 QMdiArea mdiArea;
2127 mdiArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
2128 mdiArea.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
2130 QMdiSubWindow *subWindow1 = mdiArea.addSubWindow(new QWidget);
2131 QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(new QWidget);
2133 mdiArea.show();
2134 #ifdef Q_WS_X11
2135 qt_x11_wait_for_window_manager(&mdiArea);
2136 #endif
2137 qApp->processEvents();
2139 QScrollBar *hbar = mdiArea.horizontalScrollBar();
2140 QVERIFY(hbar);
2141 QVERIFY(!hbar->isVisible());
2143 QScrollBar *vbar = mdiArea.verticalScrollBar();
2144 QVERIFY(vbar);
2145 QVERIFY(!vbar->isVisible());
2147 // Move sub-window 2 away.
2148 subWindow2->move(10000, 10000);
2149 qApp->processEvents();
2150 QVERIFY(hbar->isVisible());
2151 QVERIFY(vbar->isVisible());
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());
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());
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);
2185 void tst_QMdiArea::setActivationOrder_data()
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");
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");
2207 QList<int> list;
2208 QList<int> list2;
2209 QList<int> list3;
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;
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;
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;
2233 void tst_QMdiArea::setActivationOrder()
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);
2243 // Default order.
2244 QMdiArea mdiArea;
2245 QCOMPARE(mdiArea.activationOrder(), QMdiArea::CreationOrder);
2247 // New order.
2248 mdiArea.setActivationOrder(activationOrder);
2249 QCOMPARE(mdiArea.activationOrder(), activationOrder);
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);
2256 mdiArea.show();
2257 #ifdef Q_WS_X11
2258 qt_x11_wait_for_window_manager(&mdiArea);
2259 #endif
2261 for (int i = 0; i < subWindows.count(); ++i) {
2262 mdiArea.activateNextSubWindow();
2263 QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(i));
2264 qApp->processEvents();
2267 QMdiSubWindow *staysOnTop = subWindows.at(staysOnTopIndex);
2268 staysOnTop->setWindowFlags(staysOnTop->windowFlags() | Qt::WindowStaysOnTopHint);
2269 staysOnTop->raise();
2271 mdiArea.setActiveSubWindow(subWindows.at(firstActiveIndex));
2272 QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(firstActiveIndex));
2274 // Verify the actual arrangement/geometry.
2275 mdiArea.tileSubWindows();
2276 QTest::qWait(100);
2277 QVERIFY(verifyArrangement(&mdiArea, Tiled, expectedTileIndices));
2279 mdiArea.cascadeSubWindows();
2280 QVERIFY(verifyArrangement(&mdiArea, Cascaded, expectedCascadeIndices));
2281 QTest::qWait(100);
2283 mdiArea.activateNextSubWindow();
2284 QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
2286 mdiArea.activatePreviousSubWindow();
2287 QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
2289 mdiArea.activatePreviousSubWindow();
2290 QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
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;
2299 QVERIFY(mdiArea.activeSubWindow());
2300 QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
2303 QVERIFY(mdiArea.subWindowList(activationOrder).isEmpty());
2304 QVERIFY(expectedActivationIndices.isEmpty());
2307 void tst_QMdiArea::tabBetweenSubWindows()
2309 QMdiArea mdiArea;
2310 QList<QMdiSubWindow *> subWindows;
2311 for (int i = 0; i < 5; ++i)
2312 subWindows << mdiArea.addSubWindow(new QLineEdit);
2314 mdiArea.show();
2315 #ifdef Q_WS_X11
2316 qt_x11_wait_for_window_manager(&mdiArea);
2317 #endif
2319 qApp->setActiveWindow(&mdiArea);
2320 QWidget *focusWidget = subWindows.back()->widget();
2321 QCOMPARE(qApp->focusWidget(), focusWidget);
2323 QSignalSpy spy(&mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)));
2324 QCOMPARE(spy.count(), 0);
2326 // Walk through the entire list of sub windows.
2327 QVERIFY(tabBetweenSubWindowsIn(&mdiArea));
2328 QCOMPARE(mdiArea.activeSubWindow(), subWindows.back());
2329 QCOMPARE(spy.count(), 0);
2331 mdiArea.setActiveSubWindow(subWindows.front());
2332 QCOMPARE(mdiArea.activeSubWindow(), subWindows.front());
2333 spy.clear();
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);
2340 // Ctrl-Tab-Tab-Tab
2341 QVERIFY(tabBetweenSubWindowsIn(&mdiArea, 3));
2342 QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(3));
2343 QCOMPARE(spy.count(), 1);
2345 mdiArea.setActiveSubWindow(subWindows.at(1));
2346 QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(1));
2347 spy.clear();
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);
2355 void tst_QMdiArea::setViewMode()
2357 QMdiArea mdiArea;
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);
2367 mdiArea.show();
2368 #ifdef Q_WS_X11
2369 qt_x11_wait_for_window_manager(&mdiArea);
2370 #endif
2372 QMdiSubWindow *activeSubWindow = mdiArea.activeSubWindow();
2373 const QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
2375 // Default.
2376 QVERIFY(!activeSubWindow->isMaximized());
2377 QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
2378 QVERIFY(!tabBar);
2379 QCOMPARE(mdiArea.viewMode(), QMdiArea::SubWindowView);
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());
2388 QCOMPARE(tabBar->count(), subWindows.count());
2389 QVERIFY(activeSubWindow->isMaximized());
2390 QCOMPARE(tabBar->currentIndex(), subWindows.indexOf(activeSubWindow));
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());
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());
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)"));
2410 // If there's no window icon, tabIcon should return ... an empty icon :)
2411 activeSubWindow->setWindowIcon(QIcon());
2412 QCOMPARE(tabBar->tabIcon(tabBar->currentIndex()), QIcon());
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));
2421 activeSubWindow = mdiArea.activeSubWindow();
2422 const int tabIndex = tabBar->currentIndex();
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);
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));
2436 // Enable it again.
2437 activeSubWindow->show();
2438 QCOMPARE(tabBar->currentIndex(), tabIndex);
2439 QVERIFY(tabBar->isTabEnabled(tabIndex));
2441 // Remove sub-windows and make sure the tab is removed.
2442 foreach (QMdiSubWindow *subWindow, subWindows) {
2443 if (subWindow != activeSubWindow)
2444 mdiArea.removeSubWindow(subWindow);
2446 QCOMPARE(tabBar->count(), 1);
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);
2456 void tst_QMdiArea::setTabShape()
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
2465 // Default.
2466 QCOMPARE(mdiArea.tabShape(), QTabWidget::Rounded);
2468 // Triangular.
2469 mdiArea.setTabShape(QTabWidget::Triangular);
2470 QCOMPARE(mdiArea.tabShape(), QTabWidget::Triangular);
2472 mdiArea.setViewMode(QMdiArea::TabbedView);
2474 QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
2475 QVERIFY(tabBar);
2476 QCOMPARE(tabBar->shape(), QTabBar::TriangularNorth);
2478 // Back to default (Rounded).
2479 mdiArea.setTabShape(QTabWidget::Rounded);
2480 QCOMPARE(mdiArea.tabShape(), QTabWidget::Rounded);
2481 QCOMPARE(tabBar->shape(), QTabBar::RoundedNorth);
2484 void tst_QMdiArea::setTabPosition_data()
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");
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;
2498 void tst_QMdiArea::setTabPosition()
2500 QFETCH(QTabWidget::TabPosition, tabPosition);
2501 QFETCH(bool, hasLeftMargin);
2502 QFETCH(bool, hasTopMargin);
2503 QFETCH(bool, hasRightMargin);
2504 QFETCH(bool, hasBottomMargin);
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
2513 // Make sure there are no margins.
2514 mdiArea.setContentsMargins(0, 0, 0, 0);
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);
2523 // New position.
2524 mdiArea.setTabPosition(tabPosition);
2525 QCOMPARE(mdiArea.tabPosition(), tabPosition);
2526 QCOMPARE(tabBar->shape(), tabBarShapeFrom(QTabWidget::Rounded, tabPosition));
2528 const Qt::LayoutDirection originalLayoutDirection = qApp->layoutDirection();
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();
2539 const QSize sizeHint = tabBar->sizeHint();
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());
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);
2553 if (i == 0)
2554 qApp->setLayoutDirection(originalLayoutDirection == Qt::LeftToRight ? Qt::RightToLeft : Qt::LeftToRight);
2555 qApp->processEvents();
2558 qApp->setLayoutDirection(originalLayoutDirection);
2561 #if defined(Q_WS_WIN) || defined(Q_WS_X11)
2562 void tst_QMdiArea::nativeSubWindows()
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
2573 // No native widgets.
2574 QVERIFY(!mdiArea.viewport()->internalWinId());
2575 foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
2576 QVERIFY(!subWindow->internalWinId());
2578 QWidget *nativeWidget = new QWidget;
2579 QVERIFY(nativeWidget->winId()); // enforce native window.
2580 mdiArea.addSubWindow(nativeWidget);
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());
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());
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
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());
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
2621 QMdiSubWindow *nativeSubWindow = mdiArea.subWindowList().last();
2622 QVERIFY(!nativeSubWindow->internalWinId());
2623 (void)nativeSubWindow->winId();
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());
2631 #ifndef QT_NO_OPENGL
2633 if (!QGLFormat::hasOpenGL())
2634 QSKIP("QGL not supported on this platform", SkipAll);
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
2646 const QGLContext *context = glViewport->context();
2647 if (!context || !context->isValid())
2648 QSKIP("QGL is broken, cannot continue test", SkipAll);
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());
2655 #endif
2657 #endif
2659 void tst_QMdiArea::task_209615()
2661 QTabWidget tabWidget;
2662 QMdiArea *mdiArea1 = new QMdiArea;
2663 QMdiArea *mdiArea2 = new QMdiArea;
2664 QMdiSubWindow *subWindow = mdiArea1->addSubWindow(new QLineEdit);
2666 tabWidget.addTab(mdiArea1, QLatin1String("1"));
2667 tabWidget.addTab(mdiArea2, QLatin1String("2"));
2668 tabWidget.show();
2670 mdiArea1->removeSubWindow(subWindow);
2671 mdiArea2->addSubWindow(subWindow);
2673 // Please do not assert/crash.
2674 tabWidget.setCurrentIndex(1);
2677 void tst_QMdiArea::task_236750()
2679 QMdiArea mdiArea;
2680 QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QTextEdit);
2681 mdiArea.show();
2683 subWindow->setWindowFlags(subWindow->windowFlags() | Qt::FramelessWindowHint);
2684 // Please do not crash (floating point exception).
2685 subWindow->showMinimized();
2688 QTEST_MAIN(tst_QMdiArea)
2689 #include "tst_qmdiarea.moc"