qt5base-lts/tests/auto/qmdiarea/tst_qmdiarea.cpp
Qt by Nokia 38be0d1383 Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you
want to look at revision history older than this, please refer to the
Qt Git wiki for how to use Git history grafting. At the time of
writing, this wiki is located here:

http://qt.gitorious.org/qt/pages/GitIntroductionWithQt

If you have already performed the grafting and you don't see any
history beyond this commit, try running "git log" with the "--follow"
argument.

Branched from the monolithic repo, Qt master branch, at commit
896db169ea224deb96c59ce8af800d019de63f12
2011-04-27 12:05:43 +02:00

2775 lines
90 KiB
C++

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