1 /****************************************************************************
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
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
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.
40 ****************************************************************************/
43 #include <QtTest/QtTest>
45 #include <QMdiSubWindow>
48 #include <QApplication>
49 #include <QMainWindow>
51 #include <QPushButton>
53 #include <QStyleOption>
54 #include <QVBoxLayout>
56 #include <QDesktopWidget>
57 #include <QDockWidget>
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
)
79 static bool tabBetweenSubWindowsIn(QMdiArea
*mdiArea
, int tabCount
= -1, bool reverse
= false)
82 qWarning("Null pointer to mdi area");
86 QList
<QMdiSubWindow
*> subWindows
= mdiArea
->subWindowList();
87 const bool walkThrough
= tabCount
== -1;
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");
96 tabCount
= subWindows
.size();
99 QWidget
*focusWidget
= qApp
->focusWidget();
101 qWarning("No focus widget");
105 Qt::KeyboardModifiers modifiers
= reverse
? Qt::ShiftModifier
: Qt::NoModifier
;
109 modifiers
|= Qt::MetaModifier
;
111 key
= Qt::Key_Control
;
112 modifiers
|= Qt::ControlModifier
;
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
);
121 QRubberBand
*rubberBand
= qFindChild
<QRubberBand
*>(mdiArea
->viewport());
123 qWarning("No rubber band");
126 QMdiSubWindow
*subWindow
= subWindows
.at(reverse
? subWindows
.size() -1 - i
: i
);
127 if (rubberBand
->geometry() != subWindow
->geometry()) {
128 qWarning("Rubber band has different geometry");
132 qApp
->processEvents();
134 QTest::keyRelease(focusWidget
, key
);
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
;
158 static bool verifyArrangement(QMdiArea
*mdiArea
, Arrangement arrangement
, const QList
<int> &expectedIndices
)
160 if (!mdiArea
|| expectedIndices
.isEmpty() || mdiArea
->subWindowList().isEmpty())
163 const QList
<QMdiSubWindow
*> subWindows
= mdiArea
->subWindowList();
164 const QMdiSubWindow
*const firstSubWindow
= subWindows
.at(0);
166 switch (arrangement
) {
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
))
187 subWindowPos
.rx() += columnWidth
;
189 subWindowPos
.rx() = columnWidth
/ 2;
190 subWindowPos
.ry() += rowHeight
;
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
);
201 // ### Remove this after the mac style has been fixed
202 if (qobject_cast
<QMacStyle
*>(firstSubWindow
->style()))
205 const QFontMetrics fontMetrics
= QFontMetrics(QApplication::font("QWorkspaceTitleBar"));
206 const int dy
= qMax(titleBarHeight
- (titleBarHeight
- fontMetrics
.height()) / 2, 1);
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
215 QPoint
subWindowPos(20, 5);
216 foreach (int expectedIndex
, expectedIndices
) {
217 QMdiSubWindow
*expected
= subWindows
.at(expectedIndex
);
219 if (mdiArea
->viewport()->childAt(subWindowPos
) != expected
)
222 subWindowPos
.rx() += dx
;
223 subWindowPos
.ry() += dy
;
226 // Restore stacking order.
227 foreach (QMdiSubWindow
*subWindow
, activationOrderList
) {
228 mdiArea
->setActiveSubWindow(subWindow
);
229 qApp
->processEvents();
239 class tst_QMdiArea
: public QObject
247 void activeChanged(QMdiSubWindow
*child
);
250 // Tests from QWorkspace
251 void subWindowActivated_data();
252 void subWindowActivated();
253 void subWindowActivated2();
254 void subWindowActivatedWithMinimize();
256 void changeWindowTitle();
257 void changeModified();
261 void minimumSizeHint();
263 void setActiveSubWindow();
264 void activeSubWindow();
265 void currentSubWindow();
266 void addAndRemoveWindows();
267 void addAndRemoveWindowsWithReparenting();
268 void removeSubWindow_2();
270 void activateNextAndPreviousWindow();
271 void subWindowList_data();
272 void subWindowList();
273 void setBackground();
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();
284 void updateScrollBars();
285 void setActivationOrder_data();
286 void setActivationOrder();
287 void tabBetweenSubWindows();
290 void setTabPosition_data();
291 void setTabPosition();
292 #if defined(Q_WS_WIN) || defined(Q_WS_X11)
293 void nativeSubWindows();
299 QMdiSubWindow
*activeWindow
;
303 tst_QMdiArea::tst_QMdiArea()
306 qRegisterMetaType
<QMdiSubWindow
*>();
309 void tst_QMdiArea::initTestCase()
311 #ifdef Q_OS_WINCE //disable magic for WindowsCE
312 qApp
->setAutoMaximizeThreshold(-1);
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()
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
*)));
343 qApp
->setActiveWindow(&mw
);
345 QFETCH( int, count
);
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();
353 qApp
->processEvents();
354 QVERIFY( activeWindow
== workspace
->activeSubWindow() );
355 QCOMPARE(spy
.count(), 1);
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() );
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() );
380 while (workspace
->activeSubWindow() ) {
381 workspace
->activeSubWindow()->close();
382 qApp
->processEvents();
383 QVERIFY(activeWindow
== workspace
->activeSubWindow());
384 QCOMPARE(spy
.count(), 1);
388 QVERIFY(activeWindow
== 0);
389 QVERIFY(workspace
->activeSubWindow() == 0);
390 QCOMPARE(workspace
->subWindowList().count(), 0);
394 QWidget
*widget
= new QWidget(workspace
);
395 widget
->setAttribute(Qt::WA_DeleteOnClose
);
396 QMdiSubWindow
*window
= workspace
->addSubWindow(widget
);
398 QCOMPARE(spy
.count(), 0);
400 QCOMPARE(spy
.count(), 1);
402 QVERIFY( activeWindow
== window
);
404 qApp
->processEvents();
405 QCOMPARE(spy
.count(), 1);
407 QVERIFY( activeWindow
== 0 );
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);
420 QCOMPARE(spy
.count(), 1);
422 QVERIFY( activeWindow
== window
);
424 qApp
->processEvents();
425 QCOMPARE(spy
.count(), 1);
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);
437 QVERIFY( activeWindow
== window
);
438 QVERIFY(workspace
->activeSubWindow() == window
);
440 qApp
->processEvents();
441 QCOMPARE(spy
.count(), 1);
443 QVERIFY(workspace
->activeSubWindow() == 0);
444 QVERIFY( activeWindow
== 0 );
449 #include <Security/AuthSession.h>
450 bool macHasAccessToWindowsServer()
452 SecuritySessionId mySession
;
453 SessionAttributeBits sessionInfo
;
454 SessionGetInfo(callerSecuritySession
, &mySession
, &sessionInfo
);
455 return (sessionInfo
& sessionHasGraphicAccess
);
460 void tst_QMdiArea::subWindowActivated2()
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);
469 qt_x11_wait_for_window_manager(&mdiArea
);
473 QTRY_COMPARE(spy
.count(), 5);
474 QCOMPARE(mdiArea
.activeSubWindow(), mdiArea
.subWindowList().back());
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
);
486 QMdiSubWindow
*activeSubWindow
= mdiArea
.subWindowList().at(2);
487 mdiArea
.setActiveSubWindow(activeSubWindow
);
488 QCOMPARE(spy
.count(), 1);
489 QCOMPARE(mdiArea
.activeSubWindow(), activeSubWindow
);
492 // Check that we only emit _one_ signal and the active window
493 // is unchanged after hide/show.
496 qt_x11_wait_for_window_manager(&mdiArea
);
499 QTRY_COMPARE(spy
.count(), 1);
500 QVERIFY(!mdiArea
.activeSubWindow());
501 QCOMPARE(mdiArea
.currentSubWindow(), activeSubWindow
);
506 qt_x11_wait_for_window_manager(&mdiArea
);
509 QTRY_COMPARE(spy
.count(), 1);
510 QCOMPARE(mdiArea
.activeSubWindow(), activeSubWindow
);
513 // Check that we only emit _one_ signal and the active window
514 // is unchanged after showMinimized/showNormal.
515 mdiArea
.showMinimized();
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
);
523 #if defined(Q_WS_QWS)
524 QEXPECT_FAIL("", "task 168682", Abort
);
527 QSKIP("Not fixed yet. See Task 197453", SkipAll
);
529 QTRY_COMPARE(spy
.count(), 1);
530 QVERIFY(!mdiArea
.activeSubWindow());
531 QCOMPARE(mdiArea
.currentSubWindow(), activeSubWindow
);
534 mdiArea
.showNormal();
536 qt_x11_wait_for_window_manager(&mdiArea
);
539 QTRY_COMPARE(spy
.count(), 1);
540 QCOMPARE(mdiArea
.activeSubWindow(), activeSubWindow
);
544 void tst_QMdiArea::subWindowActivatedWithMinimize()
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
*)) );
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
);
568 qApp
->processEvents();
569 QVERIFY( activeWindow
== window1
);
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 );
586 widget
= new QWidget(ws
);
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() );
604 widget
= new QWidget(ws
);
606 QVERIFY( widget
->isVisible() );
610 widget
= new QWidget(ws
);
611 widget
->showMaximized();
612 QVERIFY( widget
->isMaximized() );
614 QVERIFY( widget
->isVisible() );
615 QVERIFY( widget
->isMaximized() );
618 widget
= new QWidget(ws
);
619 widget
->showMinimized();
621 QVERIFY( widget
->isMinimized() );
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
);
643 QTest::qWaitForWindowShown(mw
);
645 QWidget
*widget
= new QWidget( ws
);
646 widget
->setWindowTitle( wc
);
647 ws
->addSubWindow(widget
);
649 QCOMPARE( mw
->windowTitle(), mwc
);
652 widget
->showMaximized();
654 widget
->setWindowState(Qt::WindowMaximized
);
656 #if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
657 QTRY_COMPARE( mw
->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc
).arg(wc
) );
661 qApp
->processEvents();
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
) );
671 widget
->showNormal();
673 widget
->setWindowState(Qt::WindowNoState
);
675 qApp
->processEvents();
676 QCOMPARE( mw
->windowTitle(), mwc
);
679 widget
->showMaximized();
681 widget
->setWindowState(Qt::WindowMaximized
);
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
) );
693 qApp
->setActiveWindow(mw
);
696 mw
->showFullScreen();
698 mw
->setWindowState(Qt::WindowFullScreen
);
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
) );
706 widget
->showNormal();
708 widget
->setWindowState(Qt::WindowNoState
);
710 qApp
->processEvents();
711 #if defined(Q_WS_MAC) || defined(Q_OS_WINCE)
712 QCOMPARE(mw
->windowTitle(), mwc
);
714 QCOMPARE( mw
->windowTitle(), mwc2
);
718 widget
->showMaximized();
720 widget
->setWindowState(Qt::WindowMaximized
);
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
) );
730 mw
->setWindowState(Qt::WindowNoState
);
732 qApp
->processEvents();
734 widget
->showNormal();
736 widget
->setWindowState(Qt::WindowNoState
);
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
);
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);
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);
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);
795 QCOMPARE( widget
->isWindowModified(), true);
797 widget
->setWindowState(Qt::WindowNoState
);
798 QCOMPARE( mw
->isWindowModified(), false);
799 QCOMPARE( widget
->isWindowModified(), true);
804 class MyChild
: public QWidget
807 MyChild(QWidget
*parent
= 0) : QWidget(parent
) {}
808 QSize
sizeHint() const { return QSize(234, 123); }
811 void tst_QMdiArea::childSize()
815 MyChild
*child
= new MyChild(&ws
);
817 QCOMPARE(child
->size(), child
->sizeHint());
820 child
= new MyChild(&ws
);
821 child
->setFixedSize(200, 200);
823 QCOMPARE(child
->size(), child
->minimumSize());
826 child
= new MyChild(&ws
);
827 child
->resize(150, 150);
829 QCOMPARE(child
->size(), QSize(150,150));
833 void tst_QMdiArea::fixedSize()
835 QMdiArea
*ws
= new QMdiArea
;
838 ws
->resize(500, 500);
841 QSize
fixed(300, 300);
842 for (i
= 0; i
< 4; ++i
) {
843 QWidget
*child
= new QWidget(ws
);
844 child
->setFixedSize(fixed
);
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
);
878 class LargeWidget
: public QWidget
881 LargeWidget(QWidget
*parent
= 0) : QWidget(parent
) {}
882 QSize
sizeHint() const { return QSize(1280, 1024); }
883 QSize
minimumSizeHint() const { return QSize(300, 300); }
887 void tst_QMdiArea::minimumSizeHint()
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();
902 QCOMPARE(workspace
.minimumSizeHint(), expectedSize
.expandedTo(window
->minimumSizeHint()));
904 QMdiSubWindow
*subWindow
= workspace
.addSubWindow(new LargeWidget
);
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()
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();
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()
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
);
953 // Activate visible windows
954 for (int i
= 0; i
< windowCount
; ++i
) {
956 QVERIFY(!windows
[i
]->isHidden());
957 workspace
.setActiveSubWindow(windows
[i
]);
958 qApp
->processEvents();
959 QCOMPARE(spy
.count(), 1);
960 QCOMPARE(activeWindow
, windows
[i
]);
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
);
995 qt_x11_wait_for_window_manager(&mainWindow
);
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();
1019 qt_x11_wait_for_window_manager(&dummyTopLevel
);
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());
1034 dockWidgetLineEdit
->setFocus();
1035 qApp
->setActiveWindow(&mainWindow
);
1036 QVERIFY(dockWidgetLineEdit
->hasFocus());
1039 void tst_QMdiArea::currentSubWindow()
1044 qt_x11_wait_for_window_manager(&mdiArea
);
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();
1056 QCOMPARE(mdiArea
.subWindowList().back(), active
);
1057 QCOMPARE(mdiArea
.currentSubWindow(), active
);
1059 QLineEdit dummyTopLevel
;
1060 dummyTopLevel
.show();
1062 qt_x11_wait_for_window_manager(&dummyTopLevel
);
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());
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();
1083 QCOMPARE(mdiArea
.activeSubWindow(), mdiArea
.subWindowList().front());
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
);
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());
1120 void tst_QMdiArea::addAndRemoveWindows()
1123 workspace
.resize(800, 600);
1126 qt_x11_wait_for_window_manager(&workspace
);
1129 { // addSubWindow with large widget
1130 QCOMPARE(workspace
.subWindowList().count(), 0);
1131 QWidget
*window
= workspace
.addSubWindow(new LargeWidget
);
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
);
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
);
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);
1166 QCOMPARE(workspace
.subWindowList().count(), 3);
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);
1187 foreach (QWidget
*window
, workspace
.subWindowList()) {
1188 workspace
.removeSubWindow(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
);
1207 // Check that newly added windows don't occupy maximized windows'
1209 workspace
.closeAllSubWindows();
1210 workspace
.setOption(QMdiArea::DontMaximizeSubWindowOnActivation
);
1212 QMdiSubWindow
*window1
= workspace
.addSubWindow(new QWidget
);
1214 const QRect window1RestoreGeometry
= window1
->geometry();
1215 QCOMPARE(window1RestoreGeometry
.topLeft(), QPoint(0, 0));
1217 window1
->showMinimized();
1220 QMdiSubWindow
*window2
= workspace
.addSubWindow(new QWidget
);
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
);
1230 QCOMPARE(window3
->geometry().topLeft(), QPoint(window2RestoreGeometry
.right() + 1, 0));
1233 void tst_QMdiArea::addAndRemoveWindowsWithReparenting()
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
1260 using QObject::receivers
;
1263 static int numberOfConnectedSignals(MySubWindow
*subWindow
)
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()
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()
1304 qApp
->setActiveWindow(&workspace
);
1307 QWidget
*widget
= new QWidget
;
1308 QMdiSubWindow
*subWindow
= workspace
.addSubWindow(widget
);
1309 qApp
->processEvents();
1310 QCOMPARE(workspace
.subWindowList().count(), 1);
1312 QCOMPARE(workspace
.subWindowList().count(), 0);
1315 QWidget
*window
= workspace
.addSubWindow(new QWidget
);
1316 qApp
->processEvents();
1317 QCOMPARE(workspace
.subWindowList().count(), 1);
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()
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
));
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);
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);
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);
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);
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
);
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
)));
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
]);
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()
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()
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
);
1556 window
->showMinimized();
1557 QVERIFY(window
->isMinimized());
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);
1579 // QVERIFY(!window->isMinimized());
1581 // QVERIFY(!window->isMaximized());
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()
1596 workspace
.resize(600,480);
1599 qt_x11_wait_for_window_manager(&workspace
);
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);
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
) {
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());
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();
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.
1650 workspace
.resize(workspace
.size() - QSize(10, 10));
1651 workspace
.setActiveSubWindow(0);
1652 QVERIFY(workspace
.viewport()->childrenRect() != workspace
.viewport()->rect());
1653 qApp
->processEvents();
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();
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();
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());
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);
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
);
1750 QSKIP("Not fixed yet! See task 197453", SkipAll
);
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();
1775 qt_x11_wait_for_window_manager(&workspace
);
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()
1787 workspace
.resize(400, 400);
1790 qt_x11_wait_for_window_manager(&workspace
);
1793 const int windowCount
= 10;
1794 QList
<QMdiSubWindow
*> windows
;
1795 for (int i
= 0; i
< windowCount
; ++i
) {
1796 QMdiSubWindow
*window
= workspace
.addSubWindow(new MyChild
);
1798 window
->showMinimized();
1799 QVERIFY(window
->isMinimized());
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
);
1826 QVERIFY(window
->isMinimized());
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
);
1853 #if defined(Q_WS_X11)
1854 qt_x11_wait_for_window_manager(&workspace
);
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();
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
));
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
));
1905 mdiArea
.addSubWindow(view
);
1906 QCOMPARE(view
->focusWidget(), static_cast<QWidget
*>(lineEdit2
));
1910 qApp
->setActiveWindow(&mdiArea
);
1911 QCOMPARE(qApp
->focusWidget(), static_cast<QWidget
*>(lineEdit2
));
1914 void tst_QMdiArea::dontMaximizeSubWindowOnActivation()
1919 qt_x11_wait_for_window_manager(&mdiArea
);
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
);
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()
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);
2027 qt_x11_wait_for_window_manager(&mdiArea
);
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
);
2045 qt_x11_wait_for_window_manager(&mainWindow
);
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
);
2063 class EventSpy
: public QObject
2066 EventSpy(QObject
*object
, QEvent::Type event
)
2067 : eventToSpy(event
), _count(0)
2070 object
->installEventFilter(this);
2073 int count() const { return _count
; }
2074 void clear() { _count
= 0; }
2077 bool eventFilter(QObject
*object
, QEvent
*event
)
2079 if (event
->type() == eventToSpy
)
2081 return QObject::eventFilter(object
, event
);
2085 QEvent::Type eventToSpy
;
2089 void tst_QMdiArea::resizeTimer()
2092 QMdiSubWindow
*subWindow
= mdiArea
.addSubWindow(new QWidget
);
2095 qt_x11_wait_for_window_manager(&mdiArea
);
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()
2127 mdiArea
.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded
);
2128 mdiArea
.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded
);
2130 QMdiSubWindow
*subWindow1
= mdiArea
.addSubWindow(new QWidget
);
2131 QMdiSubWindow
*subWindow2
= mdiArea
.addSubWindow(new QWidget
);
2135 qt_x11_wait_for_window_manager(&mdiArea
);
2137 qApp
->processEvents();
2139 QScrollBar
*hbar
= mdiArea
.horizontalScrollBar();
2141 QVERIFY(!hbar
->isVisible());
2143 QScrollBar
*vbar
= mdiArea
.verticalScrollBar();
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));
2164 qt_x11_wait_for_window_manager(&mdiArea
);
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());
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)
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");
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
);
2245 QCOMPARE(mdiArea
.activationOrder(), QMdiArea::CreationOrder
);
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
);
2258 qt_x11_wait_for_window_manager(&mdiArea
);
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();
2277 QVERIFY(verifyArrangement(&mdiArea
, Tiled
, expectedTileIndices
));
2279 mdiArea
.cascadeSubWindows();
2280 QVERIFY(verifyArrangement(&mdiArea
, Cascaded
, expectedCascadeIndices
));
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());
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()
2310 QList
<QMdiSubWindow
*> subWindows
;
2311 for (int i
= 0; i
< 5; ++i
)
2312 subWindows
<< mdiArea
.addSubWindow(new QLineEdit
);
2316 qt_x11_wait_for_window_manager(&mdiArea
);
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());
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);
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));
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()
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
);
2369 qt_x11_wait_for_window_manager(&mdiArea
);
2372 QMdiSubWindow
*activeSubWindow
= mdiArea
.activeSubWindow();
2373 const QList
<QMdiSubWindow
*> subWindows
= mdiArea
.subWindowList();
2376 QVERIFY(!activeSubWindow
->isMaximized());
2377 QTabBar
*tabBar
= qFindChild
<QTabBar
*>(&mdiArea
);
2379 QCOMPARE(mdiArea
.viewMode(), QMdiArea::SubWindowView
);
2382 mdiArea
.setViewMode(QMdiArea::TabbedView
);
2383 QCOMPARE(mdiArea
.viewMode(), QMdiArea::TabbedView
);
2384 tabBar
= qFindChild
<QTabBar
*>(&mdiArea
);
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
));
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
);
2453 QCOMPARE(mdiArea
.viewMode(), QMdiArea::SubWindowView
);
2456 void tst_QMdiArea::setTabShape()
2459 mdiArea
.addSubWindow(new QWidget
);
2462 qt_x11_wait_for_window_manager(&mdiArea
);
2466 QCOMPARE(mdiArea
.tabShape(), QTabWidget::Rounded
);
2469 mdiArea
.setTabShape(QTabWidget::Triangular
);
2470 QCOMPARE(mdiArea
.tabShape(), QTabWidget::Triangular
);
2472 mdiArea
.setViewMode(QMdiArea::TabbedView
);
2474 QTabBar
*tabBar
= qFindChild
<QTabBar
*>(&mdiArea
);
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
);
2507 mdiArea
.addSubWindow(new QWidget
);
2510 qt_x11_wait_for_window_manager(&mdiArea
);
2513 // Make sure there are no margins.
2514 mdiArea
.setContentsMargins(0, 0, 0, 0);
2517 QCOMPARE(mdiArea
.tabPosition(), QTabWidget::North
);
2518 mdiArea
.setViewMode(QMdiArea::TabbedView
);
2519 QTabBar
*tabBar
= qFindChild
<QTabBar
*>(&mdiArea
);
2521 QCOMPARE(tabBar
->shape(), QTabBar::RoundedNorth
);
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();
2542 QCOMPARE(qApp
->isLeftToRight() ? left
: right
, sizeHint
.width());
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
);
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.
2566 mdiArea
.addSubWindow(new QWidget
);
2567 mdiArea
.addSubWindow(new QWidget
);
2570 qt_x11_wait_for_window_manager(&mdiArea
);
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.
2597 mdiArea
.addSubWindow(new QWidget
);
2598 QWidget
*nativeWidget
= new QWidget
;
2599 (void)nativeWidget
->winId();
2600 mdiArea
.addSubWindow(nativeWidget
);
2603 qt_x11_wait_for_window_manager(&mdiArea
);
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.
2614 mdiArea
.addSubWindow(new QWidget
);
2615 mdiArea
.addSubWindow(new QWidget
);
2618 qt_x11_wait_for_window_manager(&mdiArea
);
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
);
2637 QGLWidget
*glViewport
= new QGLWidget
;
2638 mdiArea
.setViewport(glViewport
);
2639 mdiArea
.addSubWindow(new QWidget
);
2640 mdiArea
.addSubWindow(new QWidget
);
2643 qt_x11_wait_for_window_manager(&mdiArea
);
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());
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"));
2670 mdiArea1
->removeSubWindow(subWindow
);
2671 mdiArea2
->addSubWindow(subWindow
);
2673 // Please do not assert/crash.
2674 tabWidget
.setCurrentIndex(1);
2677 void tst_QMdiArea::task_236750()
2680 QMdiSubWindow
*subWindow
= mdiArea
.addSubWindow(new QTextEdit
);
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"