diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:18:55 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:18:55 (GMT) |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /tests/auto/qmdisubwindow | |
download | Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2 |
Long live Qt 4.5!
Diffstat (limited to 'tests/auto/qmdisubwindow')
-rw-r--r-- | tests/auto/qmdisubwindow/.gitignore | 1 | ||||
-rw-r--r-- | tests/auto/qmdisubwindow/qmdisubwindow.pro | 6 | ||||
-rw-r--r-- | tests/auto/qmdisubwindow/tst_qmdisubwindow.cpp | 2025 |
3 files changed, 2032 insertions, 0 deletions
diff --git a/tests/auto/qmdisubwindow/.gitignore b/tests/auto/qmdisubwindow/.gitignore new file mode 100644 index 0000000..f83a9b0 --- /dev/null +++ b/tests/auto/qmdisubwindow/.gitignore @@ -0,0 +1 @@ +tst_qmdisubwindow diff --git a/tests/auto/qmdisubwindow/qmdisubwindow.pro b/tests/auto/qmdisubwindow/qmdisubwindow.pro new file mode 100644 index 0000000..2b93523 --- /dev/null +++ b/tests/auto/qmdisubwindow/qmdisubwindow.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +INCLUDEPATH += . +SOURCES += tst_qmdisubwindow.cpp +DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII + + diff --git a/tests/auto/qmdisubwindow/tst_qmdisubwindow.cpp b/tests/auto/qmdisubwindow/tst_qmdisubwindow.cpp new file mode 100644 index 0000000..9249308 --- /dev/null +++ b/tests/auto/qmdisubwindow/tst_qmdisubwindow.cpp @@ -0,0 +1,2025 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> + +#include "qmdisubwindow.h" +#include "qmdiarea.h" + +#include <QLayout> +#include <QLineEdit> +#include <QMainWindow> +#include <QMenuBar> +#include <QMenu> +#include <QGroupBox> +#include <QTextEdit> +#include <QLayout> +#include <QHBoxLayout> +#include <QByteArray> +#include <QStyle> +#include <QStyleOptionTitleBar> +#include <QPushButton> +#include <QSizeGrip> +#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) +#include <QMacStyle> +#endif + +QT_BEGIN_NAMESPACE +#if defined(Q_WS_X11) +extern void qt_x11_wait_for_window_manager(QWidget *w); +#endif +#if !defined(Q_WS_WIN) +extern bool qt_tab_all_widgets; +#endif +QT_END_NAMESPACE + +static inline bool tabAllWidgets() +{ +#if !defined(Q_WS_WIN) + if (qApp->style()->inherits("QMacStyle")) + return qt_tab_all_widgets; +#endif + return true; +} + +static inline void triggerSignal(QMdiSubWindow *window, QMdiArea *workspace, + const QByteArray &signal) +{ + if (signal == SIGNAL(windowMaximized())) { + window->showMaximized(); + qApp->processEvents(); + if (window->parent()) + QVERIFY(window->isMaximized()); + } else if (signal == SIGNAL(windowMinimized())) { + window->showMinimized(); + qApp->processEvents(); + if (window->parent()) + QVERIFY(window->isMinimized()); + } else if (signal == SIGNAL(windowRestored())) { + window->showMaximized(); + qApp->processEvents(); + window->showNormal(); + qApp->processEvents(); + QVERIFY(!window->isMinimized()); + QVERIFY(!window->isMaximized()); + QVERIFY(!window->isShaded()); + } else if (signal == SIGNAL(aboutToActivate())) { + if (window->parent()) { + workspace->setActiveSubWindow(window); + qApp->processEvents(); + } + } else if (signal == SIGNAL(windowActivated())) { + if (window->parent()) { + workspace->setActiveSubWindow(window); + qApp->processEvents(); + } + } else if (signal == SIGNAL(windowDeactivated())) { + if (!window->parent()) + return; + workspace->setActiveSubWindow(window); + qApp->processEvents(); + workspace->setActiveSubWindow(0); + qApp->processEvents(); + } +} + +// --- from tst_qgraphicsview.cpp --- +static void sendMousePress(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton) +{ + QMouseEvent event(QEvent::MouseButtonPress, point, widget->mapToGlobal(point), button, 0, 0); + QApplication::sendEvent(widget, &event); +} + +static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton) +{ + QMouseEvent event(QEvent::MouseMove, point, widget->mapToGlobal(point), button, button, 0); + QApplication::sendEvent(widget, &event); +} + +static void sendMouseRelease(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton) +{ + QMouseEvent event(QEvent::MouseButtonRelease, point, widget->mapToGlobal(point), button, 0, 0); + QApplication::sendEvent(widget, &event); +} +// --- + +static void sendMouseDoubleClick(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton) +{ + sendMousePress(widget, point, button); + sendMouseRelease(widget, point, button); + QMouseEvent event(QEvent::MouseButtonDblClick, point, widget->mapToGlobal(point), button, 0, 0); + QApplication::sendEvent(widget, &event); +} + +static const Qt::WindowFlags StandardWindowFlags + = Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint; +static const Qt::WindowFlags DialogWindowFlags + = Qt::WindowTitleHint | Qt::WindowSystemMenuHint; + +Q_DECLARE_METATYPE(Qt::WindowState); +Q_DECLARE_METATYPE(Qt::WindowStates); +Q_DECLARE_METATYPE(Qt::WindowType); +Q_DECLARE_METATYPE(Qt::WindowFlags); + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QMdiSubWindow : public QObject +{ + Q_OBJECT +private slots: + void initTestCase(); + void sizeHint(); + void minimumSizeHint(); + void minimumSize(); + void setWidget(); + void setWindowState_data(); + void setWindowState(); + void mainWindowSupport(); + void emittingOfSignals_data(); + void emittingOfSignals(); + void showShaded(); + void showNormal_data(); + void showNormal(); + void setOpaqueResizeAndMove_data(); + void setOpaqueResizeAndMove(); + void setWindowFlags_data(); + void setWindowFlags(); + void mouseDoubleClick(); + void setSystemMenu(); + void restoreFocus(); + void changeFocusWithTab(); + void closeEvent(); + void setWindowTitle(); + void resizeEvents_data(); + void resizeEvents(); +#if defined(Q_WS_MAC) + void defaultSizeGrip(); +#endif + void hideAndShow(); + void keepWindowMaximizedState(); + void explicitlyHiddenWidget(); + void resizeTimer(); + void fixedMinMaxSize(); +#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE) + void replaceMenuBarWhileMaximized(); + void closeOnDoubleClick(); +#endif + void setFont(); + void task_188849(); + void mdiArea(); + void task_182852(); + void task_233197(); + void task_226929(); +}; + +void tst_QMdiSubWindow::initTestCase() +{ + qRegisterMetaType<Qt::WindowStates>("Qt::WindowStates"); +} + +void tst_QMdiSubWindow::sizeHint() +{ + QMdiSubWindow *window = new QMdiSubWindow; + QCOMPARE(window->sizeHint(), window->minimumSizeHint()); + window->show(); + QCOMPARE(window->sizeHint(), window->minimumSizeHint()); + QMdiArea workspace; + workspace.addSubWindow(window); + QCOMPARE(window->sizeHint(), window->minimumSizeHint()); +} + +void tst_QMdiSubWindow::minimumSizeHint() +{ + QMdiSubWindow window; + window.show(); + + QCOMPARE(window.minimumSizeHint(), qApp->globalStrut()); + + window.setWidget(new QWidget); + QCOMPARE(window.minimumSizeHint(), window.layout()->minimumSize() + .expandedTo(qApp->globalStrut())); + + delete window.widget(); + delete window.layout(); + window.setWidget(new QWidget); + QCOMPARE(window.minimumSizeHint(), qApp->globalStrut()); + + window.widget()->show(); + QCOMPARE(window.minimumSizeHint(), window.widget()->minimumSizeHint() + .expandedTo(qApp->globalStrut())); +} + +void tst_QMdiSubWindow::minimumSize() +{ + QMdiArea mdiArea; + mdiArea.resize(200, 200); + + // Check that we respect the minimum size set on the sub-window itself. + QMdiSubWindow *subWindow1 = mdiArea.addSubWindow(new QWidget); + subWindow1->setMinimumSize(1000, 1000); + mdiArea.show(); +#if defined(Q_WS_X11) + qt_x11_wait_for_window_manager(&mdiArea); +#endif + QCOMPARE(subWindow1->size(), QSize(1000, 1000)); + + // Check that we respect the minimum size set on the internal widget. + QWidget *widget = new QWidget; + widget->setMinimumSize(1000, 1000); + QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(widget); + QVERIFY(subWindow2->size() != mdiArea.viewport()->size()); + QCOMPARE(subWindow2->size(), subWindow2->minimumSizeHint()); +} + +void tst_QMdiSubWindow::setWidget() +{ + QMdiSubWindow window; + window.show(); + QVERIFY(window.layout()); + QVERIFY(!window.widget()); + + // QPointer so we can check if the widget is deleted + QPointer<QWidget> widget = new QWidget; + widget->setWindowTitle(QString::fromLatin1("DummyTitle")); + QCOMPARE(widget->windowTitle(), QString::fromLatin1("DummyTitle")); + window.setWidget(widget); + QCOMPARE(window.windowTitle(), window.widget()->windowTitle()); + QCOMPARE(widget->parentWidget(), static_cast<QWidget *>(&window)); + QVERIFY(!widget->isVisible()); + QCOMPARE(window.layout()->count(), 1); + + QTest::ignoreMessage(QtWarningMsg,"QMdiSubWindow::setWidget: widget is already set"); + window.setWidget(widget); + QCOMPARE(window.widget(), static_cast<QWidget *>(widget)); + QCOMPARE(widget->parentWidget(), static_cast<QWidget *>(&window)); + + window.setWidget(0); + QVERIFY(widget); + QVERIFY(!widget->parent()); + QVERIFY(!window.widget()); + QCOMPARE(window.layout()->count(), 0); + + window.setWidget(widget); + delete window.layout(); + QVERIFY(!window.layout()); + QVERIFY(window.widget()); + QCOMPARE(window.widget()->parentWidget(), static_cast<QWidget *>(&window)); + + delete window.widget(); + QVERIFY(!widget); + QVERIFY(!window.widget()); +} + +void tst_QMdiSubWindow::setWindowState_data() +{ + QTest::addColumn<Qt::WindowState>("windowState"); + + QTest::newRow("maximized") << Qt::WindowMaximized; + QTest::newRow("minimized") << Qt::WindowMinimized; + QTest::newRow("normalized") << Qt::WindowNoState; +} + +void tst_QMdiSubWindow::setWindowState() +{ + QFETCH(Qt::WindowState, windowState); + QMdiArea workspace; + QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QLineEdit)); + window->show(); + workspace.show(); +#if defined(Q_WS_X11) + qt_x11_wait_for_window_manager(&workspace); +#endif + + QWidget *testWidget = 0; + for (int iteration = 0; iteration < 2; ++iteration) { + if (iteration == 0) + testWidget = window; + else + testWidget = window->widget(); + + testWidget->setWindowState(windowState); + + Qt::WindowStates windowStateWindow = window->windowState(); + windowStateWindow &= ~Qt::WindowActive; + Qt::WindowStates windowStateWidget = window->widget()->windowState(); + windowStateWidget &= ~Qt::WindowActive; + QCOMPARE(windowStateWindow, windowStateWidget); + + switch (windowState) { + case Qt::WindowNoState: + QVERIFY(!window->widget()->isMinimized()); + QVERIFY(!window->widget()->isMaximized()); + QVERIFY(!window->isMinimized()); + QVERIFY(!window->isMaximized()); + break; + case Qt::WindowMinimized: + QVERIFY(window->widget()->isMinimized()); + QVERIFY(window->isMinimized()); + break; + case Qt::WindowMaximized: + QVERIFY(window->widget()->isMaximized()); + QVERIFY(window->isMaximized()); + break; + default: + break; + } + } +} + +void tst_QMdiSubWindow::mainWindowSupport() +{ + QList<QMdiSubWindow *> windows; + QMdiArea *workspace = new QMdiArea; + QMainWindow mainWindow; + mainWindow.setCentralWidget(workspace); + mainWindow.show(); + mainWindow.menuBar()->setVisible(true); + qApp->setActiveWindow(&mainWindow); + + // QMainWindow's window title is empty +#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE) + { + QCOMPARE(mainWindow.windowTitle(), QString()); + QMdiSubWindow *window = workspace->addSubWindow(new QPushButton(QLatin1String("Test"))); + QString expectedTitle = QLatin1String("MainWindow's title is empty"); + window->setWindowTitle(expectedTitle); + QCOMPARE(window->windowTitle(), expectedTitle); + window->showMaximized(); + QVERIFY(window->isMaximized()); + QCOMPARE(window->windowTitle(), expectedTitle); + QCOMPARE(mainWindow.windowTitle(), expectedTitle); + window->showNormal(); + QCOMPARE(window->windowTitle(), expectedTitle); + QCOMPARE(mainWindow.windowTitle(), QString()); + window->close(); + } +#endif + + QString originalWindowTitle = QString::fromLatin1("MainWindow"); + mainWindow.setWindowTitle(originalWindowTitle); + + for (int i = 0; i < 5; ++i) { + mainWindow.menuBar()->setVisible(false); + + QMdiSubWindow *window = new QMdiSubWindow; + windows.append(window); + QVERIFY(!window->maximizedButtonsWidget()); + QVERIFY(!window->maximizedSystemMenuIconWidget()); + + QMdiArea *nestedWorkspace = new QMdiArea; // :-) + window->setWidget(nestedWorkspace); + window->widget()->setWindowTitle(QString::fromLatin1("Window %1").arg(i)); + + workspace->addSubWindow(window); + QVERIFY(!window->maximizedButtonsWidget()); + QVERIFY(!window->maximizedSystemMenuIconWidget()); + window->show(); + + // mainWindow.menuBar() is not visible + window->showMaximized(); + qApp->processEvents(); + QVERIFY(window->isMaximized()); + QVERIFY(!window->maximizedButtonsWidget()); + QVERIFY(!window->maximizedSystemMenuIconWidget()); + window->showNormal(); + + // Now it is + mainWindow.menuBar()->setVisible(true); + + window->showMaximized(); + qApp->processEvents(); + QVERIFY(window->isMaximized()); +#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE) + QVERIFY(window->maximizedButtonsWidget()); + QCOMPARE(window->maximizedButtonsWidget(), mainWindow.menuBar()->cornerWidget(Qt::TopRightCorner)); + QVERIFY(window->maximizedSystemMenuIconWidget()); + QCOMPARE(window->maximizedSystemMenuIconWidget(), qobject_cast<QWidget *>(mainWindow.menuBar() + ->cornerWidget(Qt::TopLeftCorner))); + QCOMPARE(mainWindow.windowTitle(), QString::fromLatin1("%1 - [%2]") + .arg(originalWindowTitle, window->widget()->windowTitle())); +#endif + + // Check that nested child windows don't set window title + nestedWorkspace->show(); + QMdiSubWindow *nestedWindow = new QMdiSubWindow; + nestedWindow->setWidget(new QWidget); + nestedWorkspace->addSubWindow(nestedWindow); + nestedWindow->widget()->setWindowTitle(QString::fromLatin1("NestedWindow %1").arg(i)); + nestedWindow->showMaximized(); + qApp->processEvents(); + QVERIFY(nestedWindow->isMaximized()); + QVERIFY(!nestedWindow->maximizedButtonsWidget()); + QVERIFY(!nestedWindow->maximizedSystemMenuIconWidget()); + +#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE) + QCOMPARE(mainWindow.windowTitle(), QString::fromLatin1("%1 - [%2]") + .arg(originalWindowTitle, window->widget()->windowTitle())); +#endif + } + +#if defined(Q_WS_MAC) || defined(Q_OS_WINCE) + return; +#endif + + workspace->activateNextSubWindow(); + qApp->processEvents(); + foreach (QMdiSubWindow *window, windows) { + QCOMPARE(workspace->activeSubWindow(), window); + QVERIFY(window->isMaximized()); + QVERIFY(window->maximizedButtonsWidget()); + QCOMPARE(window->maximizedButtonsWidget(), mainWindow.menuBar()->cornerWidget(Qt::TopRightCorner)); + QVERIFY(window->maximizedSystemMenuIconWidget()); + QCOMPARE(window->maximizedSystemMenuIconWidget(), qobject_cast<QWidget *>(mainWindow.menuBar() + ->cornerWidget(Qt::TopLeftCorner))); + QCOMPARE(mainWindow.windowTitle(), QString::fromLatin1("%1 - [%2]") + .arg(originalWindowTitle, window->widget()->windowTitle())); + workspace->activateNextSubWindow(); + qApp->processEvents(); + } +} + +// This test was written when QMdiSubWindow emitted separate signals +void tst_QMdiSubWindow::emittingOfSignals_data() +{ + QTest::addColumn<QByteArray>("signal"); + QTest::addColumn<Qt::WindowState>("watchedState"); + + QTest::newRow("windowMaximized") << QByteArray(SIGNAL(windowMaximized())) << Qt::WindowMaximized; + QTest::newRow("windowMinimized") << QByteArray(SIGNAL(windowMinimized())) << Qt::WindowMinimized; + QTest::newRow("windowRestored") << QByteArray(SIGNAL(windowRestored())) << Qt::WindowNoState; + QTest::newRow("aboutToActivate") << QByteArray(SIGNAL(aboutToActivate())) << Qt::WindowNoState; + QTest::newRow("windowActivated") << QByteArray(SIGNAL(windowActivated())) << Qt::WindowActive; + QTest::newRow("windowDeactivated") << QByteArray(SIGNAL(windowDeactivated())) << Qt::WindowActive; +} + +void tst_QMdiSubWindow::emittingOfSignals() +{ + QFETCH(QByteArray, signal); + QFETCH(Qt::WindowState, watchedState); + QMdiArea workspace; + workspace.show(); + qApp->processEvents(); + qApp->setActiveWindow(&workspace); + QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget)); + qApp->processEvents(); + window->show(); + if (signal != SIGNAL(windowRestored())) + workspace.setActiveSubWindow(0); + qApp->processEvents(); + + QSignalSpy spy(window, signal == SIGNAL(aboutToActivate()) + ? signal.data() + : SIGNAL(windowStateChanged(Qt::WindowStates, Qt::WindowStates))); + QVERIFY(spy.isEmpty()); + triggerSignal(window, &workspace, signal); + // Unless the signal is windowRestored or windowDeactivated, + // we're already in correct state and nothing should happen. + if (signal != SIGNAL(windowRestored()) && signal != SIGNAL(windowDeactivated())) + triggerSignal(window, &workspace, signal); + + int count = 0; + if (signal == SIGNAL(aboutToActivate())) { + count += spy.count(); + } else { + for (int i = 0; i < spy.count(); ++i) { + Qt::WindowStates oldState = qvariant_cast<Qt::WindowStates>(spy.at(i).at(0)); + Qt::WindowStates newState = qvariant_cast<Qt::WindowStates>(spy.at(i).at(1)); + if (watchedState != Qt::WindowNoState) { + if (!(oldState & watchedState) && (newState & watchedState)) + ++count; + } else { + if ((oldState & (Qt::WindowMinimized | Qt::WindowMaximized)) + && (newState & (watchedState | Qt::WindowActive))) { + ++count; + } + } + } + } + QCOMPARE(count, 1); + + window->setParent(0); + window->showNormal(); +#if defined(Q_WS_X11) + qt_x11_wait_for_window_manager(window); +#endif + qApp->processEvents(); + + spy.clear(); + triggerSignal(window, &workspace, signal); + QCOMPARE(spy.count(), 0); + + delete window; + window = 0; +} + +void tst_QMdiSubWindow::showShaded() +{ + QMdiArea workspace; + QMdiSubWindow *window = workspace.addSubWindow(new QLineEdit); + window->resize(300, 300); + qApp->processEvents(); + workspace.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&workspace); +#endif + + QVERIFY(!window->isShaded()); + QVERIFY(!window->isMaximized()); + + QCOMPARE(window->size(), QSize(300, 300)); + QRect restoreGeometry = window->geometry(); + window->showShaded(); + QVERIFY(window->isShaded()); + QVERIFY(window->isMinimized()); + + window->showNormal(); + QVERIFY(!window->isShaded()); + QVERIFY(!window->isMinimized()); + QCOMPARE(window->geometry(), restoreGeometry); + window->showShaded(); + + window->showNormal(); + QVERIFY(!window->isShaded()); + QVERIFY(!window->isMinimized()); + QCOMPARE(window->geometry(), restoreGeometry); + window->showMinimized(); + window->showMaximized(); + window->showShaded(); + QCOMPARE(window->width(), workspace.contentsRect().width()); + window->showNormal(); + QCOMPARE(window->geometry(), workspace.contentsRect()); + + window->resize(300, 300); + QCOMPARE(window->size(), QSize(300, 300)); + window->showShaded(); + window->showNormal(); + QTest::qWait(250); + +#ifdef Q_OS_WINCE + QSKIP("Until we have a QEvent::WindowFlagsChange event, this will skip", SkipAll); +#endif + + const QSize minimumSizeHint = window->minimumSizeHint(); + QVERIFY(minimumSizeHint.height() < 300); + const int maxHeightDiff = 300 - minimumSizeHint.height(); + + // Calculate mouse position for bottom right corner and simulate a + // vertical resize with the mouse. + int offset = window->style()->pixelMetric(QStyle::PM_MDIFrameWidth) / 2; + QPoint mousePosition(window->width() - qMax(offset, 2), window->height() - qMax(offset, 2)); + QWidget *mouseReceiver = 0; +#ifdef Q_WS_MAC + if (qobject_cast<QMacStyle*>(window->style())) + mouseReceiver = qFindChild<QSizeGrip *>(window); + else +#endif + mouseReceiver = window; + QVERIFY(mouseReceiver); + sendMouseMove(mouseReceiver, mousePosition, Qt::NoButton); + sendMousePress(mouseReceiver, mousePosition); + + for (int i = 0; i < maxHeightDiff + 20; ++i) { + --mousePosition.ry(); + sendMouseMove(mouseReceiver, mousePosition); + } + + sendMouseRelease(mouseReceiver, mousePosition); + // Make sure we respect the minimumSizeHint! + QCOMPARE(window->height(), minimumSizeHint.height()); + + window->showShaded(); + window->setParent(0); + window->show(); + QVERIFY(!window->isShaded()); + + delete window; +} + +void tst_QMdiSubWindow::showNormal_data() +{ + QTest::addColumn<QByteArray>("slot"); + + QTest::newRow("showMinimized") << QByteArray("showMinimized"); + QTest::newRow("showMaximized") << QByteArray("showMaximized"); + QTest::newRow("showShaded") << QByteArray("showShaded"); +} + +void tst_QMdiSubWindow::showNormal() +{ + QFETCH(QByteArray, slot); + + QMdiArea workspace; + QWidget *window = workspace.addSubWindow(new QWidget); + qApp->processEvents(); + workspace.show(); + window->show(); +#if defined(Q_WS_X11) + qt_x11_wait_for_window_manager(&workspace); +#endif + + QRect originalGeometry = window->geometry(); + QVERIFY(QMetaObject::invokeMethod(window, slot.data())); + qApp->processEvents(); + window->showNormal(); + qApp->processEvents(); + QCOMPARE(window->geometry(), originalGeometry); +} + +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_QMdiSubWindow::setOpaqueResizeAndMove_data() +{ + QTest::addColumn<bool>("opaqueMode"); + QTest::addColumn<int>("geometryCount"); + QTest::addColumn<int>("expectedGeometryCount"); + QTest::addColumn<QSize>("workspaceSize"); + QTest::addColumn<QSize>("windowSize"); + + QTest::newRow("normal mode") << true<< 20 << 20 << QSize(400, 400) << QSize(200, 200); + QTest::newRow("rubberband mode") << false << 20 << 1 << QSize(400, 400) << QSize(200, 200); +} + +void tst_QMdiSubWindow::setOpaqueResizeAndMove() +{ +#if defined (QT_NO_CURSOR) || defined (Q_OS_WINCE_WM) //For Windows CE we will set QT_NO_CURSOR if there is no cursor support + QSKIP("No cursor available", SkipAll); +#endif + QFETCH(bool, opaqueMode); + QFETCH(int, geometryCount); + QFETCH(int, expectedGeometryCount); + QFETCH(QSize, workspaceSize); + QFETCH(QSize, windowSize); + + QMdiArea workspace; + QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget)); + qApp->processEvents(); + workspace.resize(workspaceSize); + workspace.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&workspace); +#endif + + QWidget *mouseReceiver = 0; + if (window->style()->inherits("QMacStyle")) + mouseReceiver = qFindChild<QSizeGrip *>(window); + else + mouseReceiver = window; + QVERIFY(mouseReceiver); + + // ----------------------------- resize ----------------------------- + { + // setOpaqueResize + window->setOption(QMdiSubWindow::RubberBandResize, !opaqueMode); + QCOMPARE(window->testOption(QMdiSubWindow::RubberBandResize), !opaqueMode); + + // Check that the event spy actually works + EventSpy resizeSpy(window, QEvent::Resize); + QCOMPARE(resizeSpy.count(), 0); + window->resize(windowSize); + QCOMPARE(window->size(), windowSize); + QCOMPARE(resizeSpy.count(), 1); + resizeSpy.clear(); + QCOMPARE(resizeSpy.count(), 0); + + QTest::qWait(250); // delayed update of dirty regions + + // Enter resize mode. + int offset = window->style()->pixelMetric(QStyle::PM_MDIFrameWidth) / 2; + QPoint mousePosition(mouseReceiver->width() - qMax(offset, 2), mouseReceiver->height() - qMax(offset, 2)); + sendMouseMove(mouseReceiver, mousePosition, Qt::NoButton); + sendMousePress(mouseReceiver, mousePosition); + + // The window itself is the grabber in rubberband mode + if (!opaqueMode) { + mouseReceiver = window; + mousePosition = QPoint(window->width() - qMax(offset, 2), window->height() - qMax(offset, 2)); + } + + // Trigger resize events + for (int i = 0; i < geometryCount; ++i) { + if (mouseReceiver == window) { + ++mousePosition.rx(); + ++mousePosition.ry(); + sendMouseMove(mouseReceiver, mousePosition); + } else { + sendMouseMove(mouseReceiver, mousePosition + QPoint(1, 1)); + } + } + + // Leave resize mode + sendMouseRelease(mouseReceiver, mousePosition); + QCOMPARE(resizeSpy.count(), expectedGeometryCount); + QCOMPARE(window->size(), windowSize + QSize(geometryCount, geometryCount)); + } + + // ------------------------------ move ------------------------------ + { + // setOpaqueMove + window->setOption(QMdiSubWindow::RubberBandMove, !opaqueMode); + QCOMPARE(window->testOption(QMdiSubWindow::RubberBandMove), !opaqueMode); + + EventSpy moveSpy(window, QEvent::Move); + QCOMPARE(moveSpy.count(), 0); + window->move(30, 30); + QCOMPARE(moveSpy.count(), 1); + moveSpy.clear(); + + // Enter move mode + QStyleOptionTitleBar options; + options.initFrom(window); + int height = window->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options); +#if defined(Q_WS_MAC) + // ### Remove this after mac style has been fixed + height -= 4; +#endif + QPoint mousePosition(window->width() / 2, height - 1); + sendMouseMove(window, mousePosition, Qt::NoButton); + sendMousePress(window, mousePosition); + + // Trigger move events + for (int i = 0; i < geometryCount; ++i) { + ++mousePosition.rx(); + ++mousePosition.ry(); + sendMouseMove(window, mousePosition); + } + + // Leave move mode + sendMouseRelease(window, mousePosition); + QCOMPARE(moveSpy.count(), expectedGeometryCount); + QCOMPARE(window->size(), windowSize + QSize(geometryCount, geometryCount)); + } +} + +void tst_QMdiSubWindow::setWindowFlags_data() +{ + QTest::addColumn<Qt::WindowType>("windowType"); + QTest::addColumn<Qt::WindowType>("expectedWindowType"); + QTest::addColumn<Qt::WindowFlags>("customFlags"); + QTest::addColumn<Qt::WindowFlags>("expectedCustomFlags"); + + // NB! If 'expectedCustomFlags' is set to 'Qt::WindowFlags(0)' + // and nothing else, it means we're expecting the same as customFlags. + + // Standard window types with no custom flags set. + QTest::newRow("Qt::Widget") << Qt::Widget << Qt::SubWindow + << Qt::WindowFlags(0) << StandardWindowFlags; + QTest::newRow("Qt::Window") << Qt::Window << Qt::SubWindow + << Qt::WindowFlags(0) << StandardWindowFlags; + QTest::newRow("Qt::Dialog") << Qt::Dialog << Qt::SubWindow + << Qt::WindowFlags(0) << DialogWindowFlags; + QTest::newRow("Qt::Sheet") << Qt::Sheet << Qt::SubWindow + << Qt::WindowFlags(0) << StandardWindowFlags; + QTest::newRow("Qt::Drawer") << Qt::Drawer << Qt::SubWindow + << Qt::WindowFlags(0) << StandardWindowFlags; + QTest::newRow("Qt::Popup") << Qt::Popup << Qt::SubWindow + << Qt::WindowFlags(0) << StandardWindowFlags; + QTest::newRow("Qt::Tool") << Qt::Tool << Qt::SubWindow + << Qt::WindowFlags(0) << StandardWindowFlags; + QTest::newRow("Qt::ToolTip") << Qt::ToolTip << Qt::SubWindow + << Qt::WindowFlags(0) << StandardWindowFlags; + QTest::newRow("Qt::SplashScreen") << Qt::SplashScreen << Qt::SubWindow + << Qt::WindowFlags(0) << StandardWindowFlags; + QTest::newRow("Qt::Desktop") << Qt::Desktop << Qt::SubWindow + << Qt::WindowFlags(0) << StandardWindowFlags; + QTest::newRow("Qt::SubWindow") << Qt::SubWindow << Qt::SubWindow + << Qt::WindowFlags(0) << StandardWindowFlags; + + // Custom flags + QTest::newRow("Title") << Qt::SubWindow << Qt::SubWindow + << (Qt::WindowTitleHint | Qt::WindowFlags(0)) + << Qt::WindowFlags(0); + QTest::newRow("TitleAndMin") << Qt::SubWindow << Qt::SubWindow + << (Qt::WindowTitleHint | Qt::WindowMinimizeButtonHint) + << Qt::WindowFlags(0); + QTest::newRow("TitleAndMax") << Qt::SubWindow << Qt::SubWindow + << (Qt::WindowTitleHint | Qt::WindowMaximizeButtonHint) + << Qt::WindowFlags(0); + QTest::newRow("TitleAndMinMax") << Qt::SubWindow << Qt::SubWindow + << (Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint) + << Qt::WindowFlags(0); + QTest::newRow("Standard") << Qt::SubWindow << Qt::SubWindow + << StandardWindowFlags + << Qt::WindowFlags(0); + QTest::newRow("StandardAndShade") << Qt::SubWindow << Qt::SubWindow + << (StandardWindowFlags | Qt::WindowShadeButtonHint) + << Qt::WindowFlags(0); + QTest::newRow("StandardAndContext") << Qt::SubWindow << Qt::SubWindow + << (StandardWindowFlags | Qt::WindowContextHelpButtonHint) + << Qt::WindowFlags(0); + QTest::newRow("StandardAndStaysOnTop") << Qt::SubWindow << Qt::SubWindow + << (StandardWindowFlags | Qt::WindowStaysOnTopHint) + << Qt::WindowFlags(0); + QTest::newRow("StandardAndFrameless") << Qt::SubWindow << Qt::SubWindow + << (StandardWindowFlags | Qt::FramelessWindowHint) + << (Qt::FramelessWindowHint | Qt::WindowFlags(0)); + QTest::newRow("StandardAndFramelessAndStaysOnTop") << Qt::SubWindow << Qt::SubWindow + << (StandardWindowFlags | Qt::FramelessWindowHint + | Qt::WindowStaysOnTopHint) + << (Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); + QTest::newRow("Shade") << Qt::SubWindow << Qt::SubWindow + << (Qt::WindowShadeButtonHint | Qt::WindowFlags(0)) + << (StandardWindowFlags | Qt::WindowShadeButtonHint); + QTest::newRow("ShadeAndCustomize") << Qt::SubWindow << Qt::SubWindow + << (Qt::WindowShadeButtonHint | Qt::CustomizeWindowHint) + << Qt::WindowFlags(0); + QTest::newRow("Context") << Qt::SubWindow << Qt::SubWindow + << (Qt::WindowContextHelpButtonHint | Qt::WindowFlags(0)) + << (StandardWindowFlags | Qt::WindowContextHelpButtonHint); + QTest::newRow("ContextAndCustomize") << Qt::SubWindow << Qt::SubWindow + << (Qt::WindowContextHelpButtonHint | Qt::CustomizeWindowHint) + << Qt::WindowFlags(0); + QTest::newRow("ShadeAndContext") << Qt::SubWindow << Qt::SubWindow + << (Qt::WindowShadeButtonHint | Qt::WindowContextHelpButtonHint) + << (StandardWindowFlags | Qt::WindowShadeButtonHint | Qt::WindowContextHelpButtonHint); + QTest::newRow("ShadeAndContextAndCustomize") << Qt::SubWindow << Qt::SubWindow + << (Qt::WindowShadeButtonHint | Qt::WindowContextHelpButtonHint | Qt::CustomizeWindowHint) + << Qt::WindowFlags(0); + QTest::newRow("OnlyCustomize") << Qt::SubWindow << Qt::SubWindow + << (Qt::CustomizeWindowHint | Qt::WindowFlags(0)) + << Qt::WindowFlags(0); +} + +void tst_QMdiSubWindow::setWindowFlags() +{ + QSKIP("Until we have a QEvent::WindowFlagsChange event, this will skip", SkipAll); + QFETCH(Qt::WindowType, windowType); + QFETCH(Qt::WindowType, expectedWindowType); + QFETCH(Qt::WindowFlags, customFlags); + QFETCH(Qt::WindowFlags, expectedCustomFlags); + + QMdiArea workspace; + QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget)); + qApp->processEvents(); + workspace.show(); + window->show(); +#if defined(Q_WS_X11) + qt_x11_wait_for_window_manager(&workspace); +#endif + + window->setWindowFlags(windowType | customFlags); + QCOMPARE(window->windowType(), expectedWindowType); + if (!expectedCustomFlags) // We expect the same as 'customFlags' + QCOMPARE(window->windowFlags() & ~expectedWindowType, customFlags); + else + QCOMPARE(window->windowFlags() & ~expectedWindowType, expectedCustomFlags); + +} + +void tst_QMdiSubWindow::mouseDoubleClick() +{ + QMdiArea workspace; + QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget)); + qApp->processEvents(); + workspace.show(); + window->show(); + + QVERIFY(!window->isMaximized()); + QVERIFY(!window->isShaded()); + + QRect originalGeometry = window->geometry(); + + // Calculate mouse position + QStyleOptionTitleBar options; + options.initFrom(window); + int height = window->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options); + // ### Remove this after mac style has been fixed + if (window->style()->inherits("QMacStyle")) + height -= 4; + // has border + if (!window->style()->styleHint(QStyle::SH_TitleBar_NoBorder, &options, window)) + height += window->isMinimized() ? 8 : 4; + QPoint mousePosition(window->width() / 2, height - 1); + sendMouseMove(window, mousePosition, Qt::NoButton); + + // Without Qt::WindowShadeButtonHint flag set + sendMouseDoubleClick(window, mousePosition); + qApp->processEvents(); + QVERIFY(window->isMaximized()); + + sendMouseDoubleClick(window, mousePosition); + qApp->processEvents(); + QVERIFY(!window->isMaximized()); + QCOMPARE(window->geometry(), originalGeometry); + + // With Qt::WindowShadeButtonHint flag set + QSKIP("Until we have a QEvent::WindowFlagsChange event, this will skip", SkipAll); + window->setWindowFlags(window->windowFlags() | Qt::WindowShadeButtonHint); + QVERIFY(window->windowFlags() & Qt::WindowShadeButtonHint); + originalGeometry = window->geometry(); + sendMouseDoubleClick(window, mousePosition); + qApp->processEvents(); + QVERIFY(window->isShaded()); + + sendMouseDoubleClick(window, mousePosition); + qApp->processEvents(); + QVERIFY(!window->isShaded()); + QCOMPARE(window->geometry(), originalGeometry); + + window->showMinimized(); + QVERIFY(window->isMinimized()); + sendMouseDoubleClick(window, mousePosition); + QVERIFY(!window->isMinimized()); + QCOMPARE(window->geometry(), originalGeometry); +} + +void tst_QMdiSubWindow::setSystemMenu() +{ + QMdiSubWindow *subWindow = new QMdiSubWindow; + subWindow->resize(200, 50); + QPointer<QMenu>systemMenu = subWindow->systemMenu(); + QVERIFY(systemMenu); + QCOMPARE(subWindow->actions(), systemMenu->actions()); + + QMainWindow mainWindow; + QMdiArea *mdiArea = new QMdiArea; + mdiArea->addSubWindow(subWindow); + mainWindow.setCentralWidget(mdiArea); + mainWindow.menuBar(); + mainWindow.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&mainWindow); +#endif + + QVERIFY(subWindow->isVisible()); + QPoint globalPopupPos = subWindow->mapToGlobal(subWindow->contentsRect().topLeft()); + + // Show system menu + QVERIFY(!qApp->activePopupWidget()); + subWindow->showSystemMenu(); + QTest::qWait(250); + QCOMPARE(qApp->activePopupWidget(), qobject_cast<QWidget *>(systemMenu)); + QCOMPARE(systemMenu->mapToGlobal(QPoint(0, 0)), globalPopupPos); + + systemMenu->hide(); + QVERIFY(!qApp->activePopupWidget()); + + QTest::ignoreMessage(QtWarningMsg, "QMdiSubWindow::setSystemMenu: system menu is already set"); + subWindow->setSystemMenu(systemMenu); + + subWindow->setSystemMenu(0); + QVERIFY(!systemMenu); // systemMenu is QPointer + + systemMenu = new QMenu(subWindow); + systemMenu->addAction(QIcon(subWindow->style()->standardIcon(QStyle::SP_TitleBarCloseButton)), + QObject::tr("&Close"), subWindow, SLOT(close())); + subWindow->setSystemMenu(systemMenu); + QCOMPARE(subWindow->systemMenu(), qobject_cast<QMenu *>(systemMenu)); + QCOMPARE(subWindow->systemMenu()->parentWidget(), static_cast<QWidget *>(subWindow)); + QCOMPARE(subWindow->systemMenu()->actions().count(), 1); + + // Show the new system menu + QVERIFY(!qApp->activePopupWidget()); + subWindow->showSystemMenu(); + QTest::qWait(250); + QCOMPARE(qApp->activePopupWidget(), qobject_cast<QWidget *>(systemMenu)); + QCOMPARE(systemMenu->mapToGlobal(QPoint(0, 0)), globalPopupPos); + + systemMenu->hide(); + QVERIFY(!qApp->activePopupWidget()); + +#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE) + // System menu in menu bar. + subWindow->showMaximized(); + QVERIFY(subWindow->isMaximized()); + QWidget *menuLabel = subWindow->maximizedSystemMenuIconWidget(); + QVERIFY(menuLabel); + subWindow->showSystemMenu(); + QTest::qWait(250); + QCOMPARE(qApp->activePopupWidget(), qobject_cast<QWidget *>(systemMenu)); + globalPopupPos = menuLabel->mapToGlobal(QPoint(0, menuLabel->y() + menuLabel->height())); + QCOMPARE(systemMenu->mapToGlobal(QPoint(0, 0)), globalPopupPos); + systemMenu->hide(); + QVERIFY(!qApp->activePopupWidget()); + subWindow->showNormal(); +#endif + + // Reverse + qApp->setLayoutDirection(Qt::RightToLeft); + qApp->processEvents(); + mainWindow.updateGeometry(); + + subWindow->showSystemMenu(); + QTest::qWait(250); + QCOMPARE(qApp->activePopupWidget(), qobject_cast<QWidget *>(systemMenu)); + // + QPoint(1, 0) because topRight() == QPoint(left() + width() -1, top()) + globalPopupPos = subWindow->mapToGlobal(subWindow->contentsRect().topRight()) + QPoint(1, 0); + globalPopupPos -= QPoint(systemMenu->sizeHint().width(), 0); + QCOMPARE(systemMenu->mapToGlobal(QPoint(0, 0)), globalPopupPos); + + systemMenu->hide(); + QVERIFY(!qApp->activePopupWidget()); + +#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE) + // System menu in menu bar in reverse mode. + subWindow->showMaximized(); + QVERIFY(subWindow->isMaximized()); + menuLabel = subWindow->maximizedSystemMenuIconWidget(); + QVERIFY(menuLabel); + subWindow->showSystemMenu(); + QTest::qWait(250); + QCOMPARE(qApp->activePopupWidget(), qobject_cast<QWidget *>(systemMenu)); + globalPopupPos = menuLabel->mapToGlobal(QPoint(menuLabel->width(), menuLabel->y() + menuLabel->height())); + globalPopupPos -= QPoint(systemMenu->sizeHint().width(), 0); + QCOMPARE(systemMenu->mapToGlobal(QPoint(0, 0)), globalPopupPos); +#endif + + delete systemMenu; + QVERIFY(!qApp->activePopupWidget()); + QVERIFY(!subWindow->systemMenu()); + + // Restore layout direction. + qApp->setLayoutDirection(Qt::LeftToRight); +} + +void tst_QMdiSubWindow::restoreFocus() +{ + // Create complex layout. + QGroupBox *box = new QGroupBox(tr("GroupBox")); + box->setCheckable(true); + + QGroupBox *box1 = new QGroupBox(tr("&TopLeft")); + box1->setLayout(new QHBoxLayout); + box1->layout()->addWidget(new QTextEdit); + + QGroupBox *box2 = new QGroupBox(tr("&TopRight")); + box2->setLayout(new QHBoxLayout); + box2->layout()->addWidget(new QTextEdit); + + QGroupBox *box3 = new QGroupBox(tr("&BottomLeft")); + box3->setLayout(new QHBoxLayout); + box3->layout()->addWidget(new QTextEdit); + + QGroupBox *box4 = new QGroupBox(tr("&BottomRight")); + box4->setLayout(new QHBoxLayout); + QMdiArea *nestedWorkspace = new QMdiArea; + for (int i = 0; i < 4; ++i) + nestedWorkspace->addSubWindow(new QTextEdit)->show(); + qApp->processEvents(); + nestedWorkspace->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + nestedWorkspace->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + box4->layout()->addWidget(nestedWorkspace); + + QGridLayout *layout = new QGridLayout; + layout->addWidget(box1, 0, 0); + layout->addWidget(box2, 0, 1); + layout->addWidget(box3, 1, 0); + layout->addWidget(box4, 1, 1); + + box->setLayout(layout); + + // Add complex widget to workspace. + QMdiArea topArea; + QMdiSubWindow *complexWindow = topArea.addSubWindow(box); + topArea.show(); + box->show(); + + qApp->setActiveWindow(&topArea); + QMdiSubWindow *expectedFocusWindow = nestedWorkspace->subWindowList().last(); + QVERIFY(expectedFocusWindow); + QVERIFY(expectedFocusWindow->widget()); + QCOMPARE(qApp->focusWidget(), expectedFocusWindow->widget()); + + // Normal -> minimized + expectedFocusWindow->showMinimized(); + qApp->processEvents(); + QVERIFY(expectedFocusWindow->isMinimized()); + QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(expectedFocusWindow)); + + // Minimized -> normal + expectedFocusWindow->showNormal(); + qApp->processEvents(); + QVERIFY(!expectedFocusWindow->isMinimized()); + QCOMPARE(qApp->focusWidget(), expectedFocusWindow->widget()); + + // Normal -> maximized + expectedFocusWindow->showMaximized(); + qApp->processEvents(); + QVERIFY(expectedFocusWindow->isMaximized()); + QCOMPARE(qApp->focusWidget(), expectedFocusWindow->widget()); + + // Maximized -> normal + expectedFocusWindow->showNormal(); + qApp->processEvents(); + QVERIFY(!expectedFocusWindow->isMaximized()); + QCOMPARE(qApp->focusWidget(), expectedFocusWindow->widget()); + + // Minimized -> maximized + expectedFocusWindow->showMinimized(); + qApp->processEvents(); + QVERIFY(expectedFocusWindow->isMinimized()); + expectedFocusWindow->showMaximized(); + qApp->processEvents(); + QVERIFY(expectedFocusWindow->isMaximized()); + QCOMPARE(qApp->focusWidget(), expectedFocusWindow->widget()); + + // Maximized -> minimized + expectedFocusWindow->showNormal(); + qApp->processEvents(); + QVERIFY(!expectedFocusWindow->isMaximized()); + expectedFocusWindow->showMaximized(); + qApp->processEvents(); + QVERIFY(expectedFocusWindow->isMaximized()); + expectedFocusWindow->showMinimized(); + qApp->processEvents(); + QVERIFY(expectedFocusWindow->isMinimized()); + QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(expectedFocusWindow)); + + complexWindow->showMinimized(); + qApp->processEvents(); + QVERIFY(complexWindow->isMinimized()); + QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(complexWindow)); + + complexWindow->showNormal(); + qApp->processEvents(); + QVERIFY(!complexWindow->isMinimized()); + QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(expectedFocusWindow)); +} + +void tst_QMdiSubWindow::changeFocusWithTab() +{ + QWidget *widget = new QWidget; + widget->setLayout(new QVBoxLayout); + + QLineEdit *firstLineEdit = new QLineEdit; + widget->layout()->addWidget(firstLineEdit); + QLineEdit *secondLineEdit = new QLineEdit; + widget->layout()->addWidget(secondLineEdit); + QLineEdit *thirdLineEdit = new QLineEdit; + widget->layout()->addWidget(thirdLineEdit); + + QMdiArea mdiArea; + mdiArea.addSubWindow(widget); + mdiArea.show(); + QCOMPARE(mdiArea.subWindowList().count(), 1); + + qApp->setActiveWindow(&mdiArea); + QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(firstLineEdit)); + + // Next + QTest::keyPress(widget, Qt::Key_Tab); + QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(secondLineEdit)); + + // Next + QTest::keyPress(widget, Qt::Key_Tab); + QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(thirdLineEdit)); + + // Previous + QTest::keyPress(widget, Qt::Key_Backtab); + QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(secondLineEdit)); + + // Previous + QTest::keyPress(widget, Qt::Key_Backtab); + QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(firstLineEdit)); + + QMdiSubWindow *window = mdiArea.addSubWindow(new QPushButton); + window->show(); + QCOMPARE(mdiArea.activeSubWindow(), window); + + // Check that we don't give away focus to another window by + // just hitting tab if the child widget does not accept + // focus (which is the case for a QPushButton). + QTest::keyPress(window, Qt::Key_Tab); + QCOMPARE(mdiArea.activeSubWindow(), window); + QCOMPARE(qApp->focusWidget(), tabAllWidgets() ? window->widget() : window); + QTest::keyPress(window, Qt::Key_Tab); + QCOMPARE(mdiArea.activeSubWindow(), window); + QCOMPARE(qApp->focusWidget(), tabAllWidgets() ? window->widget() : window); +} + +class MyTextEdit : public QTextEdit +{ +public: + MyTextEdit(QWidget *parent = 0) : QTextEdit(parent), acceptClose(false) {} + void setAcceptClose(bool enable = true) { acceptClose = enable; } +protected: + void closeEvent(QCloseEvent *closeEvent) + { + if (!acceptClose) + closeEvent->ignore(); + } + +private: + bool acceptClose; +}; + +void tst_QMdiSubWindow::closeEvent() +{ + QMdiArea mdiArea; + mdiArea.show(); + + MyTextEdit *textEdit = new MyTextEdit; + textEdit->setAcceptClose(false); + QMdiSubWindow *window = mdiArea.addSubWindow(textEdit); + EventSpy closeSpy(window->widget(), QEvent::Close); + window->show(); + + QCOMPARE(closeSpy.count(), 0); + QVERIFY(window->isVisible()); + QVERIFY(textEdit->isVisible()); + + QVERIFY(!window->close()); + QCOMPARE(closeSpy.count(), 1); + QVERIFY(window->isVisible()); + QVERIFY(textEdit->isVisible()); + + QVERIFY(!textEdit->close()); + QCOMPARE(closeSpy.count(), 2); + QVERIFY(window->isVisible()); + QVERIFY(textEdit->isVisible()); + + textEdit->setAcceptClose(true); + + QVERIFY(window->close()); + QCOMPARE(closeSpy.count(), 3); + QCOMPARE(mdiArea.subWindowList().count(), 0); +} + +// There exists more tests in QMdiArea which covers window title support +// related to QMainWindow. This test is specific for QMdiSubWindow and its +// widget. +void tst_QMdiSubWindow::setWindowTitle() +{ + QString expectedWindowTitle = QLatin1String("This is teh shit[*]"); + QTextEdit *textEdit = new QTextEdit; + textEdit->setWindowTitle(expectedWindowTitle); + QCOMPARE(textEdit->windowTitle(), expectedWindowTitle); + textEdit->setWindowModified(true); + QCOMPARE(textEdit->isWindowModified(), true); + + QMdiArea mdiArea; + QMdiSubWindow *window = new QMdiSubWindow; + mdiArea.addSubWindow(window); + QCOMPARE(window->windowTitle(), QString()); + QVERIFY(!window->isWindowModified()); + + window->setWidget(textEdit); + QVERIFY(window->isWindowModified()); + QCOMPARE(textEdit->windowTitle(), expectedWindowTitle); + QCOMPARE(window->windowTitle(), window->widget()->windowTitle()); + + textEdit->setWindowModified(false); + QVERIFY(!textEdit->isWindowModified()); + QVERIFY(!window->isWindowModified()); + // This will return the title including the astrix, but the + // actual window title does not contain the astrix. This behavior + // seems a bit odd, but is equal to e.g. QTextEdit (and probably all + // other widgets which are not real top-level widgets). + QCOMPARE(window->windowTitle(), expectedWindowTitle); + + textEdit->setWindowModified(true);; + expectedWindowTitle = QLatin1String("Override child title"); + window->setWindowTitle(expectedWindowTitle); + QVERIFY(window->isWindowModified()); + QCOMPARE(window->windowTitle(), expectedWindowTitle); + + textEdit->setWindowTitle(QLatin1String("My parent overrides me")); + QCOMPARE(window->windowTitle(), expectedWindowTitle); + + textEdit->setWindowModified(false); + QVERIFY(window->isWindowModified()); + QCOMPARE(window->windowTitle(), expectedWindowTitle); + + window->setWindowModified(false); + QVERIFY(!window->isWindowModified()); + window->setWindowTitle(QString()); + QCOMPARE(window->windowTitle(), QString()); + + expectedWindowTitle = QLatin1String("My parent doesn't have any title so now I can set one[*]"); + textEdit->setWindowTitle(expectedWindowTitle); + QCOMPARE(window->windowTitle(), expectedWindowTitle); + textEdit->setWindowModified(true); + QVERIFY(window->isWindowModified()); + + window->setWidget(0); + QCOMPARE(window->windowTitle(), QString()); + QVERIFY(!window->isWindowModified()); + delete textEdit; +} + +void tst_QMdiSubWindow::resizeEvents_data() +{ + QTest::addColumn<Qt::WindowState>("windowState"); + QTest::addColumn<int>("expectedWindowResizeEvents"); + QTest::addColumn<int>("expectedWidgetResizeEvents"); + QTest::addColumn<bool>("isShadeMode"); + + QTest::newRow("minimized") << Qt::WindowMinimized << 1 << 0 << false; + QTest::newRow("maximized") << Qt::WindowMaximized << 1 << 1 << false; + QTest::newRow("shaded") << Qt::WindowMinimized << 1 << 0 << true; +} + +void tst_QMdiSubWindow::resizeEvents() +{ + QFETCH(Qt::WindowState, windowState); + QFETCH(int, expectedWindowResizeEvents); + QFETCH(int, expectedWidgetResizeEvents); + QFETCH(bool, isShadeMode); + + QMainWindow mainWindow; + QMdiArea *mdiArea = new QMdiArea; + mainWindow.setCentralWidget(mdiArea); + mainWindow.show(); +#if defined(Q_WS_X11) + qt_x11_wait_for_window_manager(&mainWindow); +#endif + + QMdiSubWindow *window = mdiArea->addSubWindow(new QTextEdit); + window->show(); + + EventSpy windowResizeEventSpy(window, QEvent::Resize); + QCOMPARE(windowResizeEventSpy.count(), 0); + EventSpy widgetResizeEventSpy(window->widget(), QEvent::Resize); + QCOMPARE(widgetResizeEventSpy.count(), 0); + + // Set the window state. + if (!isShadeMode) + window->setWindowState(windowState); + else + window->showShaded(); + + // Check that the window state is correct. + QCOMPARE(window->windowState(), windowState | Qt::WindowActive); + QCOMPARE(window->widget()->windowState(), windowState); + + // Make sure we got as many resize events as expected. + QCOMPARE(windowResizeEventSpy.count(), expectedWindowResizeEvents); + QCOMPARE(widgetResizeEventSpy.count(), expectedWidgetResizeEvents); + windowResizeEventSpy.clear(); + widgetResizeEventSpy.clear(); + + // Normalize. + window->showNormal(); + + // Check that the window state is correct. + QCOMPARE(window->windowState(), Qt::WindowNoState | Qt::WindowActive); + QCOMPARE(window->widget()->windowState(), Qt::WindowNoState); + + // Make sure we got as many resize events as expected. + QCOMPARE(windowResizeEventSpy.count(), expectedWindowResizeEvents); + QCOMPARE(widgetResizeEventSpy.count(), expectedWidgetResizeEvents); +} + +#if defined(Q_WS_MAC) +void tst_QMdiSubWindow::defaultSizeGrip() +{ + if (!qApp->style()->inherits("QMacStyle")) + return; + QMdiArea mdiArea; + mdiArea.show(); + + // QSizeGrip on windows with decoration. + QMdiSubWindow *windowWithDecoration = mdiArea.addSubWindow(new QWidget); + windowWithDecoration->show(); + QVERIFY(qFindChild<QSizeGrip *>(windowWithDecoration)); + + // ...but not on windows without decoration (Qt::FramelessWindowHint). + QMdiSubWindow *windowWithoutDecoration = mdiArea.addSubWindow(new QWidget, Qt::FramelessWindowHint); + windowWithoutDecoration->show(); + QVERIFY(!qFindChild<QSizeGrip *>(windowWithoutDecoration)); +} +#endif + +void tst_QMdiSubWindow::hideAndShow() +{ + // Create a QTabWidget with two tabs; QMdiArea and QTextEdit. + QTabWidget *tabWidget = new QTabWidget; + QMdiArea *mdiArea = new QMdiArea; + tabWidget->addTab(mdiArea, QLatin1String("QMdiArea")); + tabWidget->addTab(new QTextEdit, QLatin1String("Dummy")); + + // Set the tab widget as the central widget in QMainWindow. + QMainWindow mainWindow; + mainWindow.setGeometry(0, 0, 640, 480); + QMenuBar *menuBar = mainWindow.menuBar(); + mainWindow.setCentralWidget(tabWidget); + mainWindow.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&mainWindow); +#endif + + QVERIFY(!menuBar->cornerWidget(Qt::TopRightCorner)); + QMdiSubWindow *subWindow = mdiArea->addSubWindow(new QTextEdit); + subWindow->showMaximized(); +#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE) + QVERIFY(menuBar->cornerWidget(Qt::TopRightCorner)); + QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget()); +#endif + + // Hide QMdiArea. + tabWidget->setCurrentIndex(1); + + QVERIFY(!menuBar->cornerWidget(Qt::TopRightCorner)); + QVERIFY(!subWindow->maximizedButtonsWidget()); + QVERIFY(!subWindow->maximizedSystemMenuIconWidget()); + + // Show QMdiArea. + tabWidget->setCurrentIndex(0); + +#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE) + QVERIFY(menuBar->cornerWidget(Qt::TopRightCorner)); + QVERIFY(subWindow->maximizedButtonsWidget()); + QVERIFY(subWindow->maximizedSystemMenuIconWidget()); + QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget()); +#endif + + // Hide QMdiArea. + tabWidget->setCurrentIndex(1); + + // Add few more windows. + for (int i = 0; i < 5; ++i) + mdiArea->addSubWindow(new QTextEdit); + + // Show QMdiArea. + tabWidget->setCurrentIndex(0); + qApp->processEvents(); + + subWindow = mdiArea->subWindowList().back(); + QVERIFY(subWindow); + QCOMPARE(mdiArea->activeSubWindow(), subWindow); + +#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE) + QVERIFY(menuBar->cornerWidget(Qt::TopRightCorner)); + QVERIFY(subWindow->maximizedButtonsWidget()); + QVERIFY(subWindow->maximizedSystemMenuIconWidget()); + QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget()); +#endif + + subWindow->showNormal(); + QVERIFY(!menuBar->cornerWidget(Qt::TopRightCorner)); + + // Check that newly added windows got right sizes. + foreach (QMdiSubWindow *window, mdiArea->subWindowList()) + QCOMPARE(window->size(), window->sizeHint()); + + subWindow->showMaximized(); +#ifndef Q_WS_MAC + QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget()); +#endif + + subWindow->hide(); + QVERIFY(!subWindow->maximizedButtonsWidget()); + QVERIFY(!subWindow->maximizedSystemMenuIconWidget()); + QVERIFY(!menuBar->cornerWidget(Qt::TopRightCorner)); + + subWindow->show(); +#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE) + QVERIFY(subWindow->maximizedButtonsWidget()); + QVERIFY(subWindow->maximizedSystemMenuIconWidget()); + QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget()); +#endif + + // Hide QMainWindow. + mainWindow.hide(); + QVERIFY(!subWindow->maximizedButtonsWidget()); + QVERIFY(!subWindow->maximizedSystemMenuIconWidget()); + QVERIFY(!menuBar->cornerWidget(Qt::TopRightCorner)); + + // Show QMainWindow. + mainWindow.show(); +#if !defined (Q_WS_MAC) && !defined (Q_OS_WINCE) + QVERIFY(subWindow->maximizedButtonsWidget()); + QVERIFY(subWindow->maximizedSystemMenuIconWidget()); + QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget()); +#endif +} + +void tst_QMdiSubWindow::keepWindowMaximizedState() +{ + QMdiArea mdiArea; + QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QTextEdit); + mdiArea.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&mdiArea); +#endif + + subWindow->showMaximized(); + QVERIFY(subWindow->isMaximized()); + + // move + const QPoint newPosition = subWindow->pos() + QPoint(10, 10); + subWindow->move(newPosition); + QCOMPARE(subWindow->pos(), newPosition); + QVERIFY(subWindow->isMaximized()); + + // resize + const QSize newSize = subWindow->size() - QSize(10, 10); + subWindow->resize(newSize); + QCOMPARE(subWindow->size(), newSize); + QVERIFY(subWindow->isMaximized()); + + // setGeometry + const QRect newGeometry = QRect(newPosition - QPoint(10, 10), newSize + QSize(10, 10)); + subWindow->setGeometry(newGeometry); + QCOMPARE(subWindow->geometry(), newGeometry); + QVERIFY(subWindow->isMaximized()); + + subWindow->showNormal(); + + // Verify that we don't force Qt::WindowMaximized. + QVERIFY(!subWindow->isMaximized()); + subWindow->setGeometry(QRect(newPosition, newSize)); + QCOMPARE(subWindow->geometry(), QRect(newPosition, newSize)); + QVERIFY(!subWindow->isMaximized()); +} + +void tst_QMdiSubWindow::explicitlyHiddenWidget() +{ + QMdiArea mdiArea; + QTextEdit *textEdit = new QTextEdit; + textEdit->hide(); + QMdiSubWindow *subWindow = mdiArea.addSubWindow(textEdit); + mdiArea.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&mdiArea); +#endif + + QVERIFY(subWindow->isVisible()); + QVERIFY(!textEdit->isVisible()); + + textEdit->show(); + QVERIFY(textEdit->isVisible()); + + // normal -> minimized + subWindow->showMinimized(); + QVERIFY(subWindow->isVisible()); + QVERIFY(!textEdit->isVisible()); + + // minimized -> normal + subWindow->showNormal(); + QVERIFY(subWindow->isVisible()); + QVERIFY(textEdit->isVisible()); + + // minimized -> maximized + subWindow->showMinimized(); + subWindow->showMaximized(); + QVERIFY(subWindow->isVisible()); + QVERIFY(textEdit->isVisible()); + + textEdit->hide(); + + // maximized -> normal + subWindow->showNormal(); + QVERIFY(subWindow->isVisible()); + QVERIFY(!textEdit->isVisible()); + + textEdit->show(); + + subWindow->showMinimized(); + subWindow->setWidget(0); + delete textEdit; + textEdit = new QTextEdit; + textEdit->hide(); + subWindow->setWidget(textEdit); + subWindow->showNormal(); + QVERIFY(subWindow->isVisible()); + QVERIFY(!textEdit->isVisible()); +} + +void tst_QMdiSubWindow::resizeTimer() +{ + QMdiArea mdiArea; + QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget); + mdiArea.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&mdiArea); +#endif + + EventSpy timerEventSpy(subWindow, QEvent::Timer); + QCOMPARE(timerEventSpy.count(), 0); + + for (int i = 0; i < 20; ++i) { + subWindow->resize(subWindow->size() + QSize(2, 2)); + qApp->processEvents(); + } + + QTest::qWait(500); // Wait for timer events to occur. + + QVERIFY(timerEventSpy.count() > 0); +} + +void tst_QMdiSubWindow::fixedMinMaxSize() +{ + QMdiArea mdiArea; + mdiArea.setGeometry(0, 0, 640, 480); + mdiArea.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&mdiArea); +#endif + + const QSize minimumSize = QSize(250, 150); + const QSize maximumSize = QSize(300, 200); + + // Add the sub window to QMdiArea and set min/max size. + QMdiSubWindow *subWindow = new QMdiSubWindow; + subWindow->setMinimumSize(minimumSize); + QCOMPARE(subWindow->minimumSize(), minimumSize); + subWindow->setMaximumSize(maximumSize); + QCOMPARE(subWindow->maximumSize(), maximumSize); + mdiArea.addSubWindow(subWindow); + subWindow->show(); + QCOMPARE(subWindow->size(), minimumSize); + + // Calculate the size of a minimized sub window. + QStyleOptionTitleBar options; + options.initFrom(subWindow); + int minimizedHeight = subWindow->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options); +#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) + // ### Remove this after mac style has been fixed + if (qobject_cast<QMacStyle *>(subWindow->style())) + minimizedHeight -= 4; +#endif + if (!subWindow->style()->styleHint(QStyle::SH_TitleBar_NoBorder, &options, subWindow)) + minimizedHeight += 8; + int minimizedWidth = subWindow->style()->pixelMetric(QStyle::PM_MDIMinimizedWidth, &options); + const QSize minimizedSize = QSize(minimizedWidth, minimizedHeight); + + // Even though the sub window has a minimum size set, it should be possible + // to minimize the window. + subWindow->showMinimized(); + QVERIFY(subWindow->isMinimized()); + QCOMPARE(subWindow->size(), minimizedSize); + QCOMPARE(subWindow->minimumSize(), minimizedSize); + + // Restore minimum size. + subWindow->showNormal(); + QVERIFY(!subWindow->isMinimized()); + QCOMPARE(subWindow->size(), minimumSize); + QCOMPARE(subWindow->minimumSize(), minimumSize); + + // Well, the logic here is of course broken (calling showMaximized on a window with + // maximum size set), but we should handle it :) + subWindow->showMaximized(); + QVERIFY(subWindow->isMaximized()); + QCOMPARE(subWindow->size(), maximumSize); + + subWindow->showNormal(); + QVERIFY(!subWindow->isMaximized()); + QCOMPARE(subWindow->size(), minimumSize); +} + +#if !defined( Q_WS_MAC) && !defined( Q_OS_WINCE) +void tst_QMdiSubWindow::replaceMenuBarWhileMaximized() +{ + + QMainWindow mainWindow; + + QMdiArea *mdiArea = new QMdiArea; + QMdiSubWindow *subWindow = mdiArea->addSubWindow(new QTextEdit); + subWindow->showMaximized(); + + mainWindow.setCentralWidget(mdiArea); + QMenuBar *menuBar = mainWindow.menuBar(); + mainWindow.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&mainWindow); +#endif + + qApp->processEvents(); + + QVERIFY(subWindow->maximizedButtonsWidget()); + QVERIFY(subWindow->maximizedSystemMenuIconWidget()); + QCOMPARE(menuBar->cornerWidget(Qt::TopLeftCorner), subWindow->maximizedSystemMenuIconWidget()); + QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget()); + + // Replace. + mainWindow.setMenuBar(new QMenuBar); + menuBar = mainWindow.menuBar(); + qApp->processEvents(); + + QVERIFY(subWindow->maximizedButtonsWidget()); + QVERIFY(subWindow->maximizedSystemMenuIconWidget()); + QCOMPARE(menuBar->cornerWidget(Qt::TopLeftCorner), subWindow->maximizedSystemMenuIconWidget()); + QCOMPARE(menuBar->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget()); + + subWindow->showNormal(); + QVERIFY(!subWindow->maximizedButtonsWidget()); + QVERIFY(!subWindow->maximizedSystemMenuIconWidget()); + QVERIFY(!menuBar->cornerWidget(Qt::TopLeftCorner)); + QVERIFY(!menuBar->cornerWidget(Qt::TopRightCorner)); + + // Delete and replace. + subWindow->showMaximized(); + delete menuBar; + mainWindow.setMenuBar(new QMenuBar); + qApp->processEvents(); + + QVERIFY(!subWindow->maximizedButtonsWidget()); + QVERIFY(!subWindow->maximizedSystemMenuIconWidget()); + + subWindow->showNormal(); + QVERIFY(!subWindow->maximizedButtonsWidget()); + QVERIFY(!subWindow->maximizedSystemMenuIconWidget()); + + // Delete. + subWindow->showMaximized(); + mainWindow.setMenuBar(0); + qApp->processEvents(); + QVERIFY(!mainWindow.menuWidget()); + + QVERIFY(!subWindow->maximizedButtonsWidget()); + QVERIFY(!subWindow->maximizedSystemMenuIconWidget()); + + subWindow->showNormal(); + QVERIFY(!subWindow->maximizedButtonsWidget()); + QVERIFY(!subWindow->maximizedSystemMenuIconWidget()); +} + +void tst_QMdiSubWindow::closeOnDoubleClick() +{ + QMdiArea mdiArea; + QPointer<QMdiSubWindow> subWindow = mdiArea.addSubWindow(new QWidget); + mdiArea.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&mdiArea); +#endif + + subWindow->showSystemMenu(); + QTest::qWait(200); + + QPointer<QMenu> systemMenu = subWindow->systemMenu(); + QVERIFY(systemMenu); + QVERIFY(systemMenu->isVisible()); + + sendMouseDoubleClick(systemMenu, QPoint(10, 10)); + if (qApp->activePopupWidget() == static_cast<QWidget *>(systemMenu)) + systemMenu->hide(); + qApp->processEvents(); + QVERIFY(!subWindow || !subWindow->isVisible()); + QVERIFY(!systemMenu || !systemMenu->isVisible()); +} +#endif + +void tst_QMdiSubWindow::setFont() +{ + QMdiArea mdiArea; + QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QPushButton(QLatin1String("test"))); + subWindow->resize(300, 100); + subWindow->setWindowTitle(QLatin1String("Window title")); + mdiArea.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&mdiArea); +#endif + + const QFont originalFont = QApplication::font("QWorkspaceTitleBar"); + QStyleOptionTitleBar opt; + opt.initFrom(subWindow); + const int titleBarHeight = subWindow->style()->pixelMetric(QStyle::PM_TitleBarHeight, &opt); + const QRect titleBarRect = QRect(0, 0, subWindow->width(), titleBarHeight); + const QImage originalTitleBar = QPixmap::grabWidget(subWindow, titleBarRect).toImage(); + + QFont newFont(QLatin1String("Helvetica"), 16); + newFont.setBold(true); + subWindow->setFont(newFont); + qApp->processEvents(); + QCOMPARE(subWindow->font(), newFont); + QImage newTitleBar = QPixmap::grabWidget(subWindow, titleBarRect).toImage(); + QVERIFY(newTitleBar != originalTitleBar); + + subWindow->setFont(originalFont); + qApp->processEvents(); + QCOMPARE(subWindow->font(), originalFont); + newTitleBar = QPixmap::grabWidget(subWindow, titleBarRect).toImage(); + QCOMPARE(newTitleBar, originalTitleBar); +} + +void tst_QMdiSubWindow::task_188849() +{ + QMainWindow mainWindow; + // Sets a regular QWidget (and NOT a QMenuBar) as the menu bar. + mainWindow.setMenuWidget(new QWidget); + + QMdiArea *mdiArea = new QMdiArea; + QMdiSubWindow *subWindow = mdiArea->addSubWindow(new QWidget); + mainWindow.setCentralWidget(mdiArea); + mainWindow.show(); +#if defined(Q_WS_X11) + qt_x11_wait_for_window_manager(&mainWindow); +#endif + + // QMdiSubWindow will now try to show its buttons in the menu bar. + // Without checking that the menu bar is actually a QMenuBar + // and not a regular QWidget, this will crash. + subWindow->showMaximized(); +} + +void tst_QMdiSubWindow::mdiArea() +{ + QMdiArea mdiArea; + QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget); + QCOMPARE(subWindow->mdiArea(), &mdiArea); + + subWindow->setParent(0); + QVERIFY(!subWindow->mdiArea()); + + // Child of the area's corner widget. + mdiArea.setCornerWidget(new QWidget); + subWindow->setParent(mdiArea.cornerWidget()); + QVERIFY(!subWindow->mdiArea()); + + // Nested mdi area. + QMdiArea *nestedArea = new QMdiArea; + mdiArea.addSubWindow(nestedArea); + nestedArea->addSubWindow(subWindow); + QCOMPARE(subWindow->mdiArea(), nestedArea); + nestedArea->setViewport(new QWidget); + QCOMPARE(subWindow->mdiArea(), nestedArea); +} + +void tst_QMdiSubWindow::task_182852() +{ +#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE) + + QMdiArea *workspace = new QMdiArea; + QMainWindow mainWindow; + mainWindow.setCentralWidget(workspace); + mainWindow.show(); + mainWindow.menuBar()->setVisible(true); + qApp->setActiveWindow(&mainWindow); + + QString originalWindowTitle = QString::fromLatin1("MainWindow - [foo]"); + mainWindow.setWindowTitle(originalWindowTitle); + + QMdiSubWindow *window = new QMdiSubWindow; + + QMdiArea *nestedWorkspace = new QMdiArea; // :-) + window->setWidget(nestedWorkspace); + window->widget()->setWindowTitle(QString::fromLatin1("Window")); + + workspace->addSubWindow(window); + + window->showMaximized(); + qApp->processEvents(); + QVERIFY(window->isMaximized()); + + QCOMPARE(mainWindow.windowTitle(), QString::fromLatin1("%1 - [%2]") + .arg(originalWindowTitle, window->widget()->windowTitle())); + + window->showNormal(); + QCOMPARE(mainWindow.windowTitle(), originalWindowTitle); + + window->widget()->setWindowTitle(QString::fromLatin1("foo")); + window->showMaximized(); + + QCOMPARE(mainWindow.windowTitle(), originalWindowTitle); + + window->showNormal(); + QCOMPARE(mainWindow.windowTitle(), originalWindowTitle); + + window->widget()->setWindowTitle(QString::fromLatin1("bar")); + window->showMaximized(); + + QCOMPARE(mainWindow.windowTitle(), QString::fromLatin1("%1 - [%2]") + .arg(originalWindowTitle, window->widget()->windowTitle())); + + +#endif +} + +void tst_QMdiSubWindow::task_233197() +{ + QMainWindow *mainWindow = new QMainWindow; + mainWindow->setAttribute(Qt::WA_DeleteOnClose); + mainWindow->resize(500, 200); + mainWindow->show(); + + QMdiArea *mdiArea = new QMdiArea(mainWindow); + mdiArea->setOption(QMdiArea::DontMaximizeSubWindowOnActivation, true); + mainWindow->setCentralWidget(mdiArea); + + QMdiSubWindow *subWindow1 = new QMdiSubWindow(); + mdiArea->addSubWindow(subWindow1); + subWindow1->showMaximized(); + + QMdiSubWindow *subWindow2 = new QMdiSubWindow(); + mdiArea->addSubWindow(subWindow2); + subWindow2->showMaximized(); + + QMdiSubWindow *subWindow3 = new QMdiSubWindow(); + mdiArea->addSubWindow(subWindow3); + subWindow3->showMaximized(); + + QMenuBar *menuBar = mainWindow->menuBar(); // force creation of a menubar + Q_UNUSED(menuBar); + + QPushButton *focus1 = new QPushButton(QLatin1String("Focus 1"), mainWindow); + QObject::connect(focus1, SIGNAL(clicked()), subWindow1, SLOT(setFocus())); + focus1->move(5, 30); + focus1->show(); + + QPushButton *focus2 = new QPushButton(QLatin1String("Focus 2"), mainWindow); + QObject::connect(focus2, SIGNAL(clicked()), subWindow2, SLOT(setFocus())); + focus2->move(5, 60); + focus2->show(); + + QPushButton *close = new QPushButton(QLatin1String("Close"), mainWindow); + QObject::connect(close, SIGNAL(clicked()), mainWindow, SLOT(close())); + close->move(5, 90); + close->show(); + + QTest::qWait(200); + + sendMousePress(focus2, QPoint()); + sendMouseRelease(focus2, QPoint()); + + sendMousePress(focus1, QPoint()); + sendMouseRelease(focus1, QPoint()); + + sendMousePress(focus2, QPoint()); + sendMouseRelease(focus2, QPoint()); + + sendMousePress(close, QPoint()); + sendMouseRelease(close, QPoint()); + + QTest::qWait(200); +} + +void tst_QMdiSubWindow::task_226929() +{ + QMdiArea mdiArea; + mdiArea.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&mdiArea); +#endif + + QMdiSubWindow *sub1 = mdiArea.addSubWindow(new QTextEdit); + sub1->showMinimized(); + + QMdiSubWindow *sub2 = mdiArea.addSubWindow(new QTextEdit); + sub2->showMaximized(); + + QTest::qWait(100); + + // Do not assert. + // This window will now be activated and automatically maximized + // (if not QMdiArea::DontMaximizeSubWindowOnActionvation is set). + sub1->showNormal(); + QVERIFY(sub1->isMaximized()); +} + +QTEST_MAIN(tst_QMdiSubWindow) +#include "tst_qmdisubwindow.moc" + |