QtBase  v6.3.1
tst_qmdisubwindow.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #include "qmdisubwindow.h"
30 #include "private/qmdisubwindow_p.h"
31 #include "qmdiarea.h"
32 
33 #include <QTest>
34 #include <QLayout>
35 #include <QLineEdit>
36 #include <QMainWindow>
37 #include <QMenuBar>
38 #include <QMenu>
39 #include <QGroupBox>
40 #include <QTextEdit>
41 #include <QLayout>
42 #include <QHBoxLayout>
43 #include <QByteArray>
44 #include <QStyle>
45 #include <QStyleOptionTitleBar>
46 #include <QPushButton>
47 #include <QScreen>
48 #include <QSizeGrip>
49 #include <QSignalSpy>
50 #include <QList>
51 
53 extern bool qt_tab_all_widgets();
55 
56 static inline bool tabAllWidgets()
57 {
58 #if !defined(Q_OS_WIN)
59  if (QApplication::style()->inherits("QMacStyle"))
60  return qt_tab_all_widgets();
61 #endif
62  return true;
63 }
64 
65 static inline void triggerSignal(QMdiSubWindow *window, QMdiArea *workspace,
66  const QByteArray &signal)
67 {
68  if (signal == SIGNAL(windowMaximized())) {
69  window->showMaximized();
71  if (window->parent())
72  QVERIFY(window->isMaximized());
73  } else if (signal == SIGNAL(windowMinimized())) {
74  window->showMinimized();
76  if (window->parent())
77  QVERIFY(window->isMinimized());
78  } else if (signal == SIGNAL(windowRestored())) {
79  window->showMaximized();
81  window->showNormal();
82  QTRY_VERIFY(!window->isMinimized());
83  QTRY_VERIFY(!window->isMaximized());
84  QTRY_VERIFY(!window->isShaded());
85  } else if (signal == SIGNAL(aboutToActivate())) {
86  if (window->parent()) {
87  workspace->setActiveSubWindow(window);
89  }
90  } else if (signal == SIGNAL(windowActivated())) {
91  if (window->parent()) {
92  workspace->setActiveSubWindow(window);
94  }
95  } else if (signal == SIGNAL(windowDeactivated())) {
96  if (!window->parent())
97  return;
98  workspace->setActiveSubWindow(window);
100  workspace->setActiveSubWindow(nullptr);
102  }
103 }
104 
105 // --- from tst_qgraphicsview.cpp ---
106 static void sendMousePress(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton)
107 {
110 }
111 
112 static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton)
113 {
116 }
117 
118 static void sendMouseRelease(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton)
119 {
122 }
123 // ---
124 
125 static void sendMouseDoubleClick(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton)
126 {
127  sendMousePress(widget, point, button);
128  sendMouseRelease(widget, point, button);
131 }
132 
133 static const Qt::WindowFlags StandardWindowFlags
135 static const Qt::WindowFlags DialogWindowFlags
137 
139 {
140 public:
142 
143  LayoutDirectionGuard() = default;
145 };
146 
148 Q_DECLARE_METATYPE(Qt::WindowStates);
150 Q_DECLARE_METATYPE(Qt::WindowFlags);
152 
153 class TestPushButton : public QPushButton
154 {
155 public:
158  {
159  }
160 
161 protected:
162  // don't rely on style-specific button behavior in test
163  bool hitButton(const QPoint &point) const override
164  {
165  return rect().contains(point);
166  }
167 };
168 
170 {
171  Q_OBJECT
172 private slots:
173  void initTestCase();
174  void cleanup();
175  void sizeHint();
176  void minimumSizeHint();
177  void minimumSize();
178  void setWidget();
179  void setWindowState_data();
180  void setWindowState();
181  void mainWindowSupport();
182  void emittingOfSignals_data();
183  void emittingOfSignals();
184  void showShaded();
185  void showNormal_data();
186  void showNormal();
187 #ifndef QT_NO_CURSOR
188  void setOpaqueResizeAndMove_data();
189  void setOpaqueResizeAndMove();
190 #endif
191  void setWindowFlags_data();
192  void setWindowFlags();
193  void mouseDoubleClick();
194  void setSystemMenu();
195  void restoreFocus();
196  void restoreFocusOverCreation();
197  void changeFocusWithTab();
198  void closeEvent();
199  void setWindowTitle();
200  void resizeEvents_data();
201  void resizeEvents();
202 #if defined(Q_OS_MAC)
203  void defaultSizeGrip();
204 #endif
205  void hideAndShow();
206  void keepWindowMaximizedState();
207  void explicitlyHiddenWidget();
208  void resizeTimer();
209  void fixedMinMaxSize();
210 #if !defined (Q_OS_DARWIN)
211  void replaceMenuBarWhileMaximized();
212  void closeOnDoubleClick_data();
213  void closeOnDoubleClick();
214 #endif
215  void setFont();
216  void task_188849();
217  void mdiArea();
218  void task_182852();
219  void task_233197();
220  void task_226929();
221  void styleChange();
222  void testFullScreenState();
223  void testRemoveBaseWidget();
224 };
225 
226 void tst_QMdiSubWindow::initTestCase()
227 {
229  QSKIP("Wayland: Almost all of these fail. Figure out why.");
230 
231  qRegisterMetaType<Qt::WindowStates>("Qt::WindowStates");
232  // Avoid unnecessary waits for empty top level widget lists when
233  // testing menus.
235 }
236 
237 void tst_QMdiSubWindow::cleanup()
238 {
240 }
241 
242 void tst_QMdiSubWindow::sizeHint()
243 {
245  QCOMPARE(window->sizeHint(), window->minimumSizeHint());
246  window->show();
247  QCOMPARE(window->sizeHint(), window->minimumSizeHint());
250  workspace.addSubWindow(window);
251  QCOMPARE(window->sizeHint(), window->minimumSizeHint());
252 }
253 
254 void tst_QMdiSubWindow::minimumSizeHint()
255 {
256  class Widget : public QWidget
257  {
258  public:
259  Widget() = default;
260 
261  QSize minimumSizeHint() const override
262  {
263  return QSize(100, 100);
264  }
265 
266  };
269  window.show();
270 
271  QCOMPARE(window.minimumSizeHint(), QSize(0, 0));
272 
273  window.setWidget(new QWidget);
274  QCOMPARE(window.minimumSizeHint(), window.layout()->minimumSize());
275 
276  delete window.widget();
277  delete window.layout();
278  window.setWidget(new Widget);
279  QCOMPARE(window.minimumSizeHint(), QSize(0, 0));
280 
281  window.widget()->show();
282  QCOMPARE(window.minimumSizeHint(), window.widget()->minimumSizeHint());
283 }
284 
285 void tst_QMdiSubWindow::minimumSize()
286 {
287  QMdiArea mdiArea;
288  mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
289  mdiArea.resize(200, 200);
290 
291  // Check that we respect the minimum size set on the sub-window itself.
292  QMdiSubWindow *subWindow1 = mdiArea.addSubWindow(new QWidget);
293  subWindow1->setMinimumSize(1000, 1000);
294  mdiArea.show();
296  QCOMPARE(subWindow1->size(), QSize(1000, 1000));
297 
298  // Check that we respect the minimum size set on the internal widget.
299  QWidget *widget = new QWidget;
300  widget->setMinimumSize(1000, 1000);
301  QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(widget);
302  QVERIFY(subWindow2->size() != mdiArea.viewport()->size());
303  QCOMPARE(subWindow2->size(), subWindow2->minimumSizeHint());
304 }
305 
306 void tst_QMdiSubWindow::setWidget()
307 {
309  window.show();
310  QVERIFY(window.layout());
311  QVERIFY(!window.widget());
312 
313  // QPointer so we can check if the widget is deleted
315  widget->setWindowTitle(QString::fromLatin1("DummyTitle"));
316  QCOMPARE(widget->windowTitle(), QString::fromLatin1("DummyTitle"));
317  window.setWidget(widget);
318  QCOMPARE(window.windowTitle(), window.widget()->windowTitle());
319  QCOMPARE(widget->parentWidget(), static_cast<QWidget *>(&window));
320  QVERIFY(!widget->isVisible());
321  QCOMPARE(window.layout()->count(), 1);
322 
323  QTest::ignoreMessage(QtWarningMsg,"QMdiSubWindow::setWidget: widget is already set");
324  window.setWidget(widget);
325  QCOMPARE(window.widget(), static_cast<QWidget *>(widget));
326  QCOMPARE(widget->parentWidget(), static_cast<QWidget *>(&window));
327 
328  window.setWidget(nullptr);
329  QVERIFY(widget);
330  QVERIFY(!widget->parent());
331  QVERIFY(!window.widget());
332  QCOMPARE(window.layout()->count(), 0);
333 
334  window.setWidget(widget);
335  delete window.layout();
336  QVERIFY(!window.layout());
337  QVERIFY(window.widget());
338  QCOMPARE(window.widget()->parentWidget(), static_cast<QWidget *>(&window));
339 
340  delete window.widget();
341  QVERIFY(!widget);
342  QVERIFY(!window.widget());
343 }
344 
345 void tst_QMdiSubWindow::setWindowState_data()
346 {
347  QTest::addColumn<Qt::WindowState>("windowState");
348 
349  QTest::newRow("maximized") << Qt::WindowMaximized;
350  QTest::newRow("minimized") << Qt::WindowMinimized;
351  QTest::newRow("normalized") << Qt::WindowNoState;
352 }
353 
354 void tst_QMdiSubWindow::setWindowState()
355 {
356  QFETCH(Qt::WindowState, windowState);
359  QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QLineEdit));
360  window->show();
361  workspace.show();
363 
364  QWidget *testWidget = nullptr;
365  for (int iteration = 0; iteration < 2; ++iteration) {
366  if (iteration == 0)
367  testWidget = window;
368  else
369  testWidget = window->widget();
370 
371  testWidget->setWindowState(windowState);
372 
373  Qt::WindowStates windowStateWindow = window->windowState();
374  windowStateWindow &= ~Qt::WindowActive;
375  Qt::WindowStates windowStateWidget = window->widget()->windowState();
376  windowStateWidget &= ~Qt::WindowActive;
377  QCOMPARE(windowStateWindow, windowStateWidget);
378 
379  switch (windowState) {
380  case Qt::WindowNoState:
381  QVERIFY(!window->widget()->isMinimized());
382  QVERIFY(!window->widget()->isMaximized());
383  QVERIFY(!window->isMinimized());
384  QVERIFY(!window->isMaximized());
385  break;
386  case Qt::WindowMinimized:
387  QVERIFY(window->widget()->isMinimized());
388  QVERIFY(window->isMinimized());
389  break;
390  case Qt::WindowMaximized:
391  QVERIFY(window->widget()->isMaximized());
392  QVERIFY(window->isMaximized());
393  break;
394  default:
395  break;
396  }
397  }
398 }
399 
400 void tst_QMdiSubWindow::mainWindowSupport()
401 {
403  QMdiArea *workspace = new QMdiArea;
405  mainWindow.setCentralWidget(workspace);
406  mainWindow.show();
407  mainWindow.menuBar()->setVisible(true);
409  bool nativeMenuBar = mainWindow.menuBar()->isNativeMenuBar();
410 
411  // QMainWindow's window title is empty, so on a platform which does NOT have a native menubar,
412  // the maximized subwindow's title is imposed onto the main window's titlebar.
413  if (!nativeMenuBar) {
415  QMdiSubWindow *window = workspace->addSubWindow(new TestPushButton(QLatin1String("Test")));
416  QString expectedTitle = QLatin1String("MainWindow's title is empty");
417  window->setWindowTitle(expectedTitle);
418  QCOMPARE(window->windowTitle(), expectedTitle);
419  window->showMaximized();
420  QVERIFY(window->isMaximized());
421  QCOMPARE(window->windowTitle(), expectedTitle);
422  QCOMPARE(mainWindow.windowTitle(), expectedTitle);
423  window->showNormal();
424  QCOMPARE(window->windowTitle(), expectedTitle);
426  window->close();
427  }
428 
429  QString originalWindowTitle = QString::fromLatin1("MainWindow");
430  mainWindow.setWindowTitle(originalWindowTitle);
431 
432  for (int i = 0; i < 5; ++i) {
433  mainWindow.menuBar()->setVisible(false);
434 
437  QVERIFY(!window->maximizedButtonsWidget());
438  QVERIFY(!window->maximizedSystemMenuIconWidget());
439 
440  QMdiArea *nestedWorkspace = new QMdiArea; // :-)
441  window->setWidget(nestedWorkspace);
442  window->widget()->setWindowTitle(QLatin1String("Window ") + QString::number(i));
443 
444  workspace->addSubWindow(window);
445  QVERIFY(!window->maximizedButtonsWidget());
446  QVERIFY(!window->maximizedSystemMenuIconWidget());
447  window->show();
448 
449  // mainWindow.menuBar() is not visible
450  window->showMaximized();
452  QVERIFY(window->isMaximized());
453  QVERIFY(!window->maximizedButtonsWidget());
454  QVERIFY(!window->maximizedSystemMenuIconWidget());
455  window->showNormal();
456 
457  // Now it is
458  mainWindow.menuBar()->setVisible(true);
459 
460  window->showMaximized();
462  QVERIFY(window->isMaximized());
463  if (!nativeMenuBar) {
464  QVERIFY(window->maximizedButtonsWidget());
465  QCOMPARE(window->maximizedButtonsWidget(), mainWindow.menuBar()->cornerWidget(Qt::TopRightCorner));
466  QVERIFY(window->maximizedSystemMenuIconWidget());
467  QCOMPARE(window->maximizedSystemMenuIconWidget(),
468  qobject_cast<QWidget *>(mainWindow.menuBar()->cornerWidget(Qt::TopLeftCorner)));
469  const QString expectedTitle = originalWindowTitle + QLatin1String(" - [")
470  + window->widget()->windowTitle() + QLatin1Char(']');
471  QCOMPARE(mainWindow.windowTitle(), expectedTitle);
472  }
473 
474  // Check that nested child windows don't set window title
475  nestedWorkspace->show();
476  QMdiSubWindow *nestedWindow = new QMdiSubWindow;
477  nestedWindow->setWidget(new QWidget);
478  nestedWorkspace->addSubWindow(nestedWindow);
479  nestedWindow->widget()->setWindowTitle(QLatin1String("NestedWindow ") + QString::number(i));
480  nestedWindow->showMaximized();
482  QVERIFY(nestedWindow->isMaximized());
483  QVERIFY(!nestedWindow->maximizedButtonsWidget());
484  QVERIFY(!nestedWindow->maximizedSystemMenuIconWidget());
485 
486  if (!nativeMenuBar) {
488  .arg(originalWindowTitle, window->widget()->windowTitle()));
489  }
490  }
491 
492  if (nativeMenuBar)
493  return;
494 
495  workspace->activateNextSubWindow();
497  for (QMdiSubWindow *window : qAsConst(windows)) {
498  QCOMPARE(workspace->activeSubWindow(), window);
499  QVERIFY(window->isMaximized());
500  QVERIFY(window->maximizedButtonsWidget());
501  QCOMPARE(window->maximizedButtonsWidget(), mainWindow.menuBar()->cornerWidget(Qt::TopRightCorner));
502  QVERIFY(window->maximizedSystemMenuIconWidget());
503  QCOMPARE(window->maximizedSystemMenuIconWidget(), qobject_cast<QWidget *>(mainWindow.menuBar()
504  ->cornerWidget(Qt::TopLeftCorner)));
506  .arg(originalWindowTitle, window->widget()->windowTitle()));
507  workspace->activateNextSubWindow();
509  }
510 }
511 
512 // This test was written when QMdiSubWindow emitted separate signals
513 void tst_QMdiSubWindow::emittingOfSignals_data()
514 {
515  QTest::addColumn<QByteArray>("signal");
516  QTest::addColumn<Qt::WindowState>("watchedState");
517 
518  QTest::newRow("windowMaximized") << QByteArray(SIGNAL(windowMaximized())) << Qt::WindowMaximized;
519  QTest::newRow("windowMinimized") << QByteArray(SIGNAL(windowMinimized())) << Qt::WindowMinimized;
520  QTest::newRow("windowRestored") << QByteArray(SIGNAL(windowRestored())) << Qt::WindowNoState;
521  QTest::newRow("aboutToActivate") << QByteArray(SIGNAL(aboutToActivate())) << Qt::WindowNoState;
522  QTest::newRow("windowActivated") << QByteArray(SIGNAL(windowActivated())) << Qt::WindowActive;
523  QTest::newRow("windowDeactivated") << QByteArray(SIGNAL(windowDeactivated())) << Qt::WindowActive;
524 }
525 
526 void tst_QMdiSubWindow::emittingOfSignals()
527 {
529  QFETCH(Qt::WindowState, watchedState);
532  workspace.show();
535  QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
537  window->show();
538  if (signal != SIGNAL(windowRestored()))
539  workspace.setActiveSubWindow(nullptr);
541 
542  QSignalSpy spy(window, signal == SIGNAL(aboutToActivate())
543  ? signal.data()
544  : SIGNAL(windowStateChanged(Qt::WindowStates,Qt::WindowStates)));
545  QVERIFY(spy.isEmpty());
546  triggerSignal(window, &workspace, signal);
547  // Unless the signal is windowRestored or windowDeactivated,
548  // we're already in correct state and nothing should happen.
549  if (signal != SIGNAL(windowRestored()) && signal != SIGNAL(windowDeactivated()))
550  triggerSignal(window, &workspace, signal);
551 
552  int count = 0;
553  if (signal == SIGNAL(aboutToActivate())) {
554  count += spy.count();
555  } else {
556  for (int i = 0; i < spy.count(); ++i) {
557  Qt::WindowStates oldState = qvariant_cast<Qt::WindowStates>(spy.at(i).at(0));
558  Qt::WindowStates newState = qvariant_cast<Qt::WindowStates>(spy.at(i).at(1));
559  if (watchedState != Qt::WindowNoState) {
560  if (!(oldState & watchedState) && (newState & watchedState))
561  ++count;
562  } else {
563  if ((oldState & (Qt::WindowMinimized | Qt::WindowMaximized))
564  && (newState & (watchedState | Qt::WindowActive))) {
565  ++count;
566  }
567  }
568  }
569  }
570  QCOMPARE(count, 1);
571 
572  window->setParent(nullptr);
573  window->showNormal();
576 
577  spy.clear();
578  triggerSignal(window, &workspace, signal);
579  QCOMPARE(spy.count(), 0);
580 
581  delete window;
582  window = nullptr;
583 }
584 
585 void tst_QMdiSubWindow::showShaded()
586 {
589  QMdiSubWindow *window = workspace.addSubWindow(new QLineEdit);
590  window->resize(300, 300);
592  workspace.show();
594 
595  QVERIFY(!window->isShaded());
596  QVERIFY(!window->isMaximized());
597 
598  QCOMPARE(window->size(), QSize(300, 300));
599  QRect restoreGeometry = window->geometry();
600  window->showShaded();
601  QVERIFY(window->isShaded());
602  QVERIFY(window->isMinimized());
603 
604  window->showNormal();
605  QVERIFY(!window->isShaded());
606  QVERIFY(!window->isMinimized());
607  QCOMPARE(window->geometry(), restoreGeometry);
608  window->showShaded();
609 
610  window->showNormal();
611  QVERIFY(!window->isShaded());
612  QVERIFY(!window->isMinimized());
613  QCOMPARE(window->geometry(), restoreGeometry);
614  window->showMinimized();
615  window->showMaximized();
616  window->showShaded();
617  QCOMPARE(window->width(), workspace.contentsRect().width());
618  window->showNormal();
619  QCOMPARE(window->geometry(), workspace.contentsRect());
620 
621  window->resize(300, 300);
622  QCOMPARE(window->size(), QSize(300, 300));
623  window->showShaded();
624  window->showNormal();
625  QTest::qWait(250);
626 
627  const QSize minimumSizeHint = window->minimumSizeHint();
628  QVERIFY(minimumSizeHint.height() < 300);
629  const int maxHeightDiff = 300 - minimumSizeHint.height();
630 
631  // Calculate mouse position for bottom right corner and simulate a
632  // vertical resize with the mouse.
633  int offset = window->style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth) / 2;
634  QPoint mousePosition(window->width() - qMax(offset, 2), window->height() - qMax(offset, 2));
635  QWidget *mouseReceiver = nullptr;
636 #ifdef Q_OS_MAC
637  if (window->style()->inherits("QMacStyle"))
638  mouseReceiver = window->findChild<QSizeGrip *>();
639  else
640 #endif
641  mouseReceiver = window;
642  QVERIFY(mouseReceiver);
643  sendMouseMove(mouseReceiver, mousePosition, Qt::NoButton);
644  sendMousePress(mouseReceiver, mousePosition);
645 
646  for (int i = 0; i < maxHeightDiff + 20; ++i) {
647  --mousePosition.ry();
648  sendMouseMove(mouseReceiver, mousePosition);
649  }
650 
651  sendMouseRelease(mouseReceiver, mousePosition);
652  // Make sure we respect the minimumSizeHint!
653  QCOMPARE(window->height(), minimumSizeHint.height());
654 
655  window->showShaded();
656  window->setParent(nullptr);
657  window->show();
658  QVERIFY(!window->isShaded());
659 
660  delete window;
661 }
662 
663 void tst_QMdiSubWindow::showNormal_data()
664 {
665  QTest::addColumn<QByteArray>("slot");
666 
667  QTest::newRow("showMinimized") << QByteArray("showMinimized");
668  QTest::newRow("showMaximized") << QByteArray("showMaximized");
669  QTest::newRow("showShaded") << QByteArray("showShaded");
670 }
671 
672 void tst_QMdiSubWindow::showNormal()
673 {
674  QFETCH(QByteArray, slot);
675 
678  QWidget *window = workspace.addSubWindow(new QWidget);
680  workspace.show();
681  window->show();
683 
684  QRect originalGeometry = window->geometry();
687  window->showNormal();
689  QCOMPARE(window->geometry(), originalGeometry);
690 }
691 
692 class EventSpy : public QObject
693 {
694 public:
695  explicit EventSpy(QObject *object, QEvent::Type event)
696  : eventToSpy(event)
697  {
698  if (object)
699  object->installEventFilter(this);
700  }
701 
702  int count() const { return _count; }
703  void clear() { _count = 0; }
704 
705 protected:
706  bool eventFilter(QObject *object, QEvent *event) override
707  {
708  if (event->type() == eventToSpy)
709  ++_count;
710  return QObject::eventFilter(object, event);
711  }
712 
713 private:
714  const QEvent::Type eventToSpy;
715  int _count = 0;
716 };
717 
718 #ifndef QT_NO_CURSOR
719 void tst_QMdiSubWindow::setOpaqueResizeAndMove_data()
720 {
721  QTest::addColumn<bool>("opaqueMode");
722  QTest::addColumn<int>("geometryCount");
723  QTest::addColumn<int>("expectedGeometryCount");
724  QTest::addColumn<QSize>("workspaceSize");
725  QTest::addColumn<QSize>("windowSize");
726 
727  QTest::newRow("normal mode") << true<< 20 << 20 << QSize(400, 400) << QSize(240, 200);
728  QTest::newRow("rubberband mode") << false << 20 << 1 << QSize(400, 400) << QSize(240, 200);
729 }
730 
731 void tst_QMdiSubWindow::setOpaqueResizeAndMove()
732 {
733  QFETCH(bool, opaqueMode);
734  QFETCH(int, geometryCount);
735  QFETCH(int, expectedGeometryCount);
736  QFETCH(QSize, workspaceSize);
738 
742  QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
744  workspace.resize(workspaceSize);
745  workspace.show();
747 
748  QWidget *mouseReceiver = nullptr;
749  if (window->style()->inherits("QMacStyle"))
750  mouseReceiver = window->findChild<QSizeGrip *>();
751  else
752  mouseReceiver = window;
753  QVERIFY(mouseReceiver);
754 
755  // ----------------------------- resize -----------------------------
756  {
757  // setOpaqueResize
758  window->setOption(QMdiSubWindow::RubberBandResize, !opaqueMode);
759  QCOMPARE(window->testOption(QMdiSubWindow::RubberBandResize), !opaqueMode);
760 
761  // Check that the event spy actually works
762  EventSpy resizeSpy(window, QEvent::Resize);
763  QCOMPARE(resizeSpy.count(), 0);
764  window->resize(windowSize);
765  QCOMPARE(window->size(), windowSize);
766  QCOMPARE(resizeSpy.count(), 1);
767  resizeSpy.clear();
768  QCOMPARE(resizeSpy.count(), 0);
769 
770  // we need to wait for the resizeTimer to make sure updateDirtyRegions is called
771  auto priv = static_cast<QMdiSubWindowPrivate*>(qt_widget_private(window));
772  QTRY_COMPARE(priv->resizeTimerId, -1);
773 
774  // Enter resize mode.
775  int offset = window->style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth) / 2;
776  QPoint mousePosition(mouseReceiver->width() - qMax(offset, 2), mouseReceiver->height() - qMax(offset, 2));
777  sendMouseMove(mouseReceiver, mousePosition, Qt::NoButton);
778  sendMousePress(mouseReceiver, mousePosition);
779 
780  // The window itself is the grabber in rubberband mode
781  if (!opaqueMode) {
782  mouseReceiver = window;
783  mousePosition = QPoint(window->width() - qMax(offset, 2), window->height() - qMax(offset, 2));
784  }
785 
786  // Trigger resize events
787  for (int i = 0; i < geometryCount; ++i) {
788  if (mouseReceiver == window) {
789  ++mousePosition.rx();
790  ++mousePosition.ry();
791  sendMouseMove(mouseReceiver, mousePosition);
792  } else {
793  sendMouseMove(mouseReceiver, mousePosition + QPoint(1, 1));
794  }
795  }
796 
797  // Leave resize mode
798  sendMouseRelease(mouseReceiver, mousePosition);
799  QCOMPARE(resizeSpy.count(), expectedGeometryCount);
800  QCOMPARE(window->size(), windowSize + QSize(geometryCount, geometryCount));
801  }
802 
803  // ------------------------------ move ------------------------------
804  {
805  // setOpaqueMove
806  window->setOption(QMdiSubWindow::RubberBandMove, !opaqueMode);
807  QCOMPARE(window->testOption(QMdiSubWindow::RubberBandMove), !opaqueMode);
808 
809  EventSpy moveSpy(window, QEvent::Move);
810  QCOMPARE(moveSpy.count(), 0);
811  window->move(30, 30);
812  QCOMPARE(moveSpy.count(), 1);
813  moveSpy.clear();
814 
815  // Enter move mode
816  QStyleOptionTitleBar options;
817  options.initFrom(window);
818  int height = window->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
819 #if defined(Q_OS_MAC)
820  // ### Remove this after mac style has been fixed
821  height -= 4;
822 #endif
823  QPoint mousePosition(window->width() / 3, height - 1);
824  sendMouseMove(window, mousePosition, Qt::NoButton);
825  sendMousePress(window, mousePosition);
826 
827  // Trigger move events
828  for (int i = 0; i < geometryCount; ++i) {
829  ++mousePosition.rx();
830  ++mousePosition.ry();
831  sendMouseMove(window, mousePosition);
832  }
833 
834  // Leave move mode
835  sendMouseRelease(window, mousePosition);
836  QCOMPARE(moveSpy.count(), expectedGeometryCount);
837  QCOMPARE(window->size(), windowSize + QSize(geometryCount, geometryCount));
838  }
839 }
840 #endif
841 
842 void tst_QMdiSubWindow::setWindowFlags_data()
843 {
844  QTest::addColumn<Qt::WindowType>("windowType");
845  QTest::addColumn<Qt::WindowType>("expectedWindowType");
846  QTest::addColumn<Qt::WindowFlags>("customFlags");
847  QTest::addColumn<Qt::WindowFlags>("expectedCustomFlags");
848 
849  // NB! If 'expectedCustomFlags' is set to 'Qt::WindowFlags(0)'
850  // and nothing else, it means we're expecting the same as customFlags.
851 
852  // Standard window types with no custom flags set.
853  QTest::newRow("Qt::Widget") << Qt::Widget << Qt::SubWindow
854  << Qt::WindowFlags{} << StandardWindowFlags;
855  QTest::newRow("Qt::Window") << Qt::Window << Qt::SubWindow
856  << Qt::WindowFlags{} << StandardWindowFlags;
857  QTest::newRow("Qt::Dialog") << Qt::Dialog << Qt::SubWindow
858  << Qt::WindowFlags{} << DialogWindowFlags;
859  QTest::newRow("Qt::Sheet") << Qt::Sheet << Qt::SubWindow
860  << Qt::WindowFlags{} << StandardWindowFlags;
861  QTest::newRow("Qt::Drawer") << Qt::Drawer << Qt::SubWindow
862  << Qt::WindowFlags{} << StandardWindowFlags;
863  QTest::newRow("Qt::Popup") << Qt::Popup << Qt::SubWindow
864  << Qt::WindowFlags{} << StandardWindowFlags;
865  QTest::newRow("Qt::Tool") << Qt::Tool << Qt::SubWindow
866  << Qt::WindowFlags{} << StandardWindowFlags;
867  QTest::newRow("Qt::ToolTip") << Qt::ToolTip << Qt::SubWindow
868  << Qt::WindowFlags{} << StandardWindowFlags;
869  QTest::newRow("Qt::SplashScreen") << Qt::SplashScreen << Qt::SubWindow
870  << Qt::WindowFlags{} << StandardWindowFlags;
871  QTest::newRow("Qt::Desktop") << Qt::Desktop << Qt::SubWindow
872  << Qt::WindowFlags{} << StandardWindowFlags;
873  QTest::newRow("Qt::SubWindow") << Qt::SubWindow << Qt::SubWindow
874  << Qt::WindowFlags{} << StandardWindowFlags;
875 
876  // Custom flags
878  << (Qt::WindowTitleHint | Qt::WindowFlags{})
879  << Qt::WindowFlags{};
880  QTest::newRow("TitleAndMin") << Qt::SubWindow << Qt::SubWindow
882  << Qt::WindowFlags{};
883  QTest::newRow("TitleAndMax") << Qt::SubWindow << Qt::SubWindow
885  << Qt::WindowFlags{};
886  QTest::newRow("TitleAndMinMax") << Qt::SubWindow << Qt::SubWindow
888  << Qt::WindowFlags{};
889  QTest::newRow("Standard") << Qt::SubWindow << Qt::SubWindow
890  << StandardWindowFlags
891  << Qt::WindowFlags{};
892  QTest::newRow("StandardAndShade") << Qt::SubWindow << Qt::SubWindow
893  << (StandardWindowFlags | Qt::WindowShadeButtonHint)
894  << Qt::WindowFlags{};
895  QTest::newRow("StandardAndContext") << Qt::SubWindow << Qt::SubWindow
896  << (StandardWindowFlags | Qt::WindowContextHelpButtonHint)
897  << Qt::WindowFlags{};
898  QTest::newRow("StandardAndStaysOnTop") << Qt::SubWindow << Qt::SubWindow
899  << (StandardWindowFlags | Qt::WindowStaysOnTopHint)
900  << Qt::WindowFlags{};
901  QTest::newRow("StandardAndFrameless") << Qt::SubWindow << Qt::SubWindow
902  << (StandardWindowFlags | Qt::FramelessWindowHint)
903  << Qt::WindowFlags(Qt::FramelessWindowHint);
904  QTest::newRow("StandardAndFramelessAndStaysOnTop") << Qt::SubWindow << Qt::SubWindow
905  << (StandardWindowFlags | Qt::FramelessWindowHint
909  << (Qt::WindowShadeButtonHint | Qt::WindowFlags{})
910  << (StandardWindowFlags | Qt::WindowShadeButtonHint);
911  QTest::newRow("ShadeAndCustomize") << Qt::SubWindow << Qt::SubWindow
913  << Qt::WindowFlags{};
914  QTest::newRow("Context") << Qt::SubWindow << Qt::SubWindow
915  << (Qt::WindowContextHelpButtonHint | Qt::WindowFlags{})
916  << (StandardWindowFlags | Qt::WindowContextHelpButtonHint);
917  QTest::newRow("ContextAndCustomize") << Qt::SubWindow << Qt::SubWindow
919  << Qt::WindowFlags{};
920  QTest::newRow("ShadeAndContext") << Qt::SubWindow << Qt::SubWindow
922  << (StandardWindowFlags | Qt::WindowShadeButtonHint | Qt::WindowContextHelpButtonHint);
923  QTest::newRow("ShadeAndContextAndCustomize") << Qt::SubWindow << Qt::SubWindow
925  << Qt::WindowFlags{};
926  QTest::newRow("OnlyCustomize") << Qt::SubWindow << Qt::SubWindow
927  << (Qt::CustomizeWindowHint | Qt::WindowFlags{})
928  << Qt::WindowFlags{};
929 }
930 
931 void tst_QMdiSubWindow::setWindowFlags()
932 {
933  QFETCH(Qt::WindowType, windowType);
934  QFETCH(Qt::WindowType, expectedWindowType);
935  QFETCH(Qt::WindowFlags, customFlags);
936  QFETCH(Qt::WindowFlags, expectedCustomFlags);
937 
941  QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
943  workspace.show();
944  window->show();
946 
947  window->setWindowFlags(windowType | customFlags);
948  QCOMPARE(window->windowType(), expectedWindowType);
949 
950  if (!expectedCustomFlags) // We expect the same as 'customFlags'
951  QCOMPARE(window->windowFlags() & ~expectedWindowType, customFlags);
952  else
953  QCOMPARE(window->windowFlags() & ~expectedWindowType, expectedCustomFlags);
954 }
955 
956 void tst_QMdiSubWindow::mouseDoubleClick()
957 {
960  QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
962  workspace.show();
963  window->show();
964 
965  QVERIFY(!window->isMaximized());
966  QVERIFY(!window->isShaded());
967 
968  QRect originalGeometry = window->geometry();
969 
970  // Calculate mouse position
971  QStyleOptionTitleBar options;
972  options.initFrom(window);
973  int height = window->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
974  // has border
975  if (!window->style()->styleHint(QStyle::SH_TitleBar_NoBorder, &options, window))
976  height += window->isMinimized() ? 8 : 4;
977  QPoint mousePosition(window->width() / 2, height - 1);
978  sendMouseMove(window, mousePosition, Qt::NoButton);
979 
980  // Without Qt::WindowShadeButtonHint flag set
981  sendMouseDoubleClick(window, mousePosition);
983  QVERIFY(window->isMaximized());
984 
985  sendMouseDoubleClick(window, mousePosition);
987  QVERIFY(!window->isMaximized());
988  QCOMPARE(window->geometry(), originalGeometry);
989 
990  // With Qt::WindowShadeButtonHint flag set
991  window->setWindowFlags(window->windowFlags() | Qt::WindowShadeButtonHint);
992  QVERIFY(window->windowFlags() & Qt::WindowShadeButtonHint);
993  originalGeometry = window->geometry();
994  sendMouseDoubleClick(window, mousePosition);
996  QVERIFY(window->isShaded());
997 
998  sendMouseDoubleClick(window, mousePosition);
1000  QVERIFY(!window->isShaded());
1001  QCOMPARE(window->geometry(), originalGeometry);
1002 
1003  window->showMinimized();
1004  QVERIFY(window->isMinimized());
1005  sendMouseDoubleClick(window, mousePosition);
1006  QVERIFY(!window->isMinimized());
1007  QCOMPARE(window->geometry(), originalGeometry);
1008 }
1009 
1010 void tst_QMdiSubWindow::setSystemMenu()
1011 {
1012  QMdiSubWindow *subWindow = new QMdiSubWindow;
1013  subWindow->resize(200, 50);
1014  QPointer<QMenu>systemMenu = subWindow->systemMenu();
1015  QVERIFY(systemMenu);
1016  QCOMPARE(subWindow->actions(), systemMenu->actions());
1017 
1020  QMdiArea *mdiArea = new QMdiArea;
1021  mdiArea->addSubWindow(subWindow);
1022  mainWindow.setCentralWidget(mdiArea);
1023  mainWindow.menuBar()->setNativeMenuBar(false);
1024  // Prevent the window from spanning screens
1025  if (QGuiApplication::screens().size() > 1)
1027  else
1028  mainWindow.show();
1030 
1031  QTRY_VERIFY(subWindow->isVisible());
1032  QPoint globalPopupPos;
1033 
1034  // Show system menu
1036  subWindow->showSystemMenu();
1038  QTRY_COMPARE(systemMenu->mapToGlobal(QPoint(0, 0)),
1039  (globalPopupPos = subWindow->mapToGlobal(subWindow->contentsRect().topLeft())) );
1040 
1041  systemMenu->hide();
1043 
1044  QTest::ignoreMessage(QtWarningMsg, "QMdiSubWindow::setSystemMenu: system menu is already set");
1045  subWindow->setSystemMenu(systemMenu);
1046 
1047  subWindow->setSystemMenu(nullptr);
1048  QVERIFY(!systemMenu); // systemMenu is QPointer
1049 
1050  systemMenu = new QMenu(subWindow);
1051  systemMenu->addAction(QIcon(subWindow->style()->standardIcon(QStyle::SP_TitleBarCloseButton)),
1052  QObject::tr("&Close"), subWindow, SLOT(close()));
1053  subWindow->setSystemMenu(systemMenu);
1054  QCOMPARE(subWindow->systemMenu(), qobject_cast<QMenu *>(systemMenu));
1055  QCOMPARE(subWindow->systemMenu()->parentWidget(), static_cast<QWidget *>(subWindow));
1056  QCOMPARE(subWindow->systemMenu()->actions().count(), 1);
1057 
1058  // Show the new system menu
1060  subWindow->showSystemMenu();
1062  QTRY_COMPARE(systemMenu->mapToGlobal(QPoint(0, 0)), globalPopupPos);
1063 
1064  systemMenu->hide();
1066 
1067 #if !defined (Q_OS_DARWIN)
1068  // System menu in menu bar.
1069  subWindow->showMaximized();
1070  QVERIFY(subWindow->isMaximized());
1071  QWidget *menuLabel = subWindow->maximizedSystemMenuIconWidget();
1072  QVERIFY(menuLabel);
1073  subWindow->showSystemMenu();
1075  QCOMPARE(systemMenu->mapToGlobal(QPoint(0, 0)),
1076  (globalPopupPos = menuLabel->mapToGlobal(QPoint(0, menuLabel->y() + menuLabel->height()))));
1077  systemMenu->hide();
1079  subWindow->showNormal();
1080 #endif
1081 
1082  // Reverse
1083  LayoutDirectionGuard guard;
1087  QTest::qWait(150);
1088 
1089  subWindow->showSystemMenu();
1091  // + QPoint(1, 0) because topRight() == QPoint(left() + width() -1, top())
1092  globalPopupPos = subWindow->mapToGlobal(subWindow->contentsRect().topRight()) + QPoint(1, 0);
1093  globalPopupPos -= QPoint(systemMenu->sizeHint().width(), 0);
1094  QTRY_COMPARE(systemMenu->mapToGlobal(QPoint(0, 0)), globalPopupPos);
1095 
1096  systemMenu->hide();
1098 
1099 #if !defined (Q_OS_DARWIN)
1100  // System menu in menu bar in reverse mode.
1101  subWindow->showMaximized();
1102  QVERIFY(subWindow->isMaximized());
1103  menuLabel = subWindow->maximizedSystemMenuIconWidget();
1104  QVERIFY(menuLabel);
1105  subWindow->showSystemMenu();
1107  globalPopupPos = menuLabel->mapToGlobal(QPoint(menuLabel->width(), menuLabel->y() + menuLabel->height()));
1108  globalPopupPos -= QPoint(systemMenu->sizeHint().width(), 0);
1109  QTRY_COMPARE(systemMenu->mapToGlobal(QPoint(0, 0)), globalPopupPos);
1110 #endif
1111 
1112  delete systemMenu;
1114  QVERIFY(!subWindow->systemMenu());
1115 }
1116 
1117 void tst_QMdiSubWindow::restoreFocus()
1118 {
1119  // Create complex layout.
1120  QGroupBox *box = new QGroupBox(tr("GroupBox"));
1121  box->setCheckable(true);
1122 
1123  QGroupBox *box1 = new QGroupBox(tr("&TopLeft"));
1124  box1->setLayout(new QHBoxLayout);
1125  box1->layout()->addWidget(new QTextEdit);
1126 
1127  QGroupBox *box2 = new QGroupBox(tr("&TopRight"));
1128  box2->setLayout(new QHBoxLayout);
1129  box2->layout()->addWidget(new QTextEdit);
1130 
1131  QGroupBox *box3 = new QGroupBox(tr("&BottomLeft"));
1132  box3->setLayout(new QHBoxLayout);
1133  box3->layout()->addWidget(new QTextEdit);
1134 
1135  QGroupBox *box4 = new QGroupBox(tr("&BottomRight"));
1136  box4->setLayout(new QHBoxLayout);
1137  QMdiArea *nestedWorkspace = new QMdiArea;
1138  for (int i = 0; i < 4; ++i)
1139  nestedWorkspace->addSubWindow(new QTextEdit)->show();
1141  nestedWorkspace->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
1142  nestedWorkspace->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
1143  box4->layout()->addWidget(nestedWorkspace);
1144 
1146  layout->addWidget(box1, 0, 0);
1147  layout->addWidget(box2, 0, 1);
1148  layout->addWidget(box3, 1, 0);
1149  layout->addWidget(box4, 1, 1);
1150 
1151  box->setLayout(layout);
1152 
1153  // Add complex widget to workspace.
1154  QMdiArea topArea;
1155  topArea.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
1156  QMdiSubWindow *complexWindow = topArea.addSubWindow(box);
1157  topArea.show();
1158  box->show();
1159 
1161  QMdiSubWindow *expectedFocusWindow = nestedWorkspace->subWindowList().last();
1162  QVERIFY(expectedFocusWindow);
1163  QVERIFY(expectedFocusWindow->widget());
1164  QCOMPARE(QApplication::focusWidget(), expectedFocusWindow->widget());
1165 
1166  // Normal -> minimized
1167  expectedFocusWindow->showMinimized();
1169  QVERIFY(expectedFocusWindow->isMinimized());
1170  QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(expectedFocusWindow));
1171 
1172  // Minimized -> normal
1173  expectedFocusWindow->showNormal();
1175  QVERIFY(!expectedFocusWindow->isMinimized());
1176  QCOMPARE(QApplication::focusWidget(), expectedFocusWindow->widget());
1177 
1178  // Normal -> maximized
1179  expectedFocusWindow->showMaximized();
1181  QVERIFY(expectedFocusWindow->isMaximized());
1182  QCOMPARE(QApplication::focusWidget(), expectedFocusWindow->widget());
1183 
1184  // Maximized -> normal
1185  expectedFocusWindow->showNormal();
1187  QVERIFY(!expectedFocusWindow->isMaximized());
1188  QCOMPARE(QApplication::focusWidget(), expectedFocusWindow->widget());
1189 
1190  // Minimized -> maximized
1191  expectedFocusWindow->showMinimized();
1193  QVERIFY(expectedFocusWindow->isMinimized());
1194  expectedFocusWindow->showMaximized();
1196  QVERIFY(expectedFocusWindow->isMaximized());
1197  QCOMPARE(QApplication::focusWidget(), expectedFocusWindow->widget());
1198 
1199  // Maximized -> minimized
1200  expectedFocusWindow->showNormal();
1202  QVERIFY(!expectedFocusWindow->isMaximized());
1203  expectedFocusWindow->showMaximized();
1205  QVERIFY(expectedFocusWindow->isMaximized());
1206  expectedFocusWindow->showMinimized();
1208  QVERIFY(expectedFocusWindow->isMinimized());
1209  QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(expectedFocusWindow));
1210 
1211  complexWindow->showMinimized();
1213  QVERIFY(complexWindow->isMinimized());
1214  QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(complexWindow));
1215 
1216  complexWindow->showNormal();
1218  QVERIFY(!complexWindow->isMinimized());
1219  QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(expectedFocusWindow));
1220 }
1221 
1222 class MultiWidget : public QWidget {
1223 public:
1224  explicit MultiWidget(QWidget *parent = nullptr) : QWidget(parent)
1226  {
1227  QVBoxLayout *lt = new QVBoxLayout(this);
1228  lt->addWidget(m_lineEdit1);
1229  lt->addWidget(m_lineEdit2);
1230  }
1231 
1234 };
1235 
1236 void tst_QMdiSubWindow::restoreFocusOverCreation()
1237 {
1238  // QTBUG-38378, verify that the focus child of a subwindow
1239  // is not "forgotten" when adding yet another subwindow.
1240  QMdiArea mdiArea;
1241  mdiArea.resize(800, 800);
1242  mdiArea.move(QGuiApplication::primaryScreen()->availableGeometry().center() - QPoint(400, 400));
1243  mdiArea.setWindowTitle(QStringLiteral("restoreFocusOverCreation"));
1244 
1245  MultiWidget *subWidget1 = new MultiWidget;
1246  MultiWidget *subWidget2 = new MultiWidget;
1247 
1248  QMdiSubWindow *subWindow1 = mdiArea.addSubWindow(subWidget1);
1249  subWidget1->m_lineEdit2->setFocus();
1250  subWindow1->show();
1251  mdiArea.show();
1255 
1256  QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(subWidget2);
1257  subWindow2->show();
1259 
1260  mdiArea.setActiveSubWindow(subWindow1);
1262 }
1263 
1264 void tst_QMdiSubWindow::changeFocusWithTab()
1265 {
1266  QWidget *widget = new QWidget;
1268 
1269  QLineEdit *firstLineEdit = new QLineEdit;
1270  widget->layout()->addWidget(firstLineEdit);
1271  QLineEdit *secondLineEdit = new QLineEdit;
1272  widget->layout()->addWidget(secondLineEdit);
1273  QLineEdit *thirdLineEdit = new QLineEdit;
1274  widget->layout()->addWidget(thirdLineEdit);
1275 
1276  QMdiArea mdiArea;
1277  mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
1278  mdiArea.addSubWindow(widget);
1279  mdiArea.show();
1280  QCOMPARE(mdiArea.subWindowList().count(), 1);
1281 
1283  QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(firstLineEdit));
1284 
1285  // Next
1286  QTest::keyPress(widget, Qt::Key_Tab);
1287  QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(secondLineEdit));
1288 
1289  // Next
1290  QTest::keyPress(widget, Qt::Key_Tab);
1291  QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(thirdLineEdit));
1292 
1293  // Previous
1294  QTest::keyPress(widget, Qt::Key_Backtab);
1295  QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(secondLineEdit));
1296 
1297  // Previous
1298  QTest::keyPress(widget, Qt::Key_Backtab);
1299  QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(firstLineEdit));
1300 
1302  window->show();
1303  QCOMPARE(mdiArea.activeSubWindow(), window);
1304 
1305  // Check that we don't give away focus to another window by
1306  // just hitting tab if the child widget does not accept
1307  // focus (which is the case for a QPushButton).
1308  QTest::keyPress(window, Qt::Key_Tab);
1309  QCOMPARE(mdiArea.activeSubWindow(), window);
1310  QCOMPARE(QApplication::focusWidget(), tabAllWidgets() ? window->widget() : window);
1311  QTest::keyPress(window, Qt::Key_Tab);
1312  QCOMPARE(mdiArea.activeSubWindow(), window);
1313  QCOMPARE(QApplication::focusWidget(), tabAllWidgets() ? window->widget() : window);
1314 }
1315 
1316 class MyTextEdit : public QTextEdit
1317 {
1318 public:
1319  using QTextEdit::QTextEdit;
1320  void setAcceptClose(bool enable = true) { acceptClose = enable; }
1321 protected:
1323  {
1324  if (!acceptClose)
1325  closeEvent->ignore();
1326  }
1327 
1328 private:
1329  bool acceptClose = false;
1330 };
1331 
1332 void tst_QMdiSubWindow::closeEvent()
1333 {
1334  QMdiArea mdiArea;
1335  mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
1336  mdiArea.show();
1337 
1339  textEdit->setAcceptClose(false);
1341  EventSpy closeSpy(window->widget(), QEvent::Close);
1342  window->show();
1343 
1344  QCOMPARE(closeSpy.count(), 0);
1345  QVERIFY(window->isVisible());
1347 
1348  QVERIFY(!window->close());
1349  QCOMPARE(closeSpy.count(), 1);
1350  QVERIFY(window->isVisible());
1352 
1353  QVERIFY(!textEdit->close());
1354  QCOMPARE(closeSpy.count(), 2);
1355  QVERIFY(window->isVisible());
1357 
1358  textEdit->setAcceptClose(true);
1359 
1360  QVERIFY(window->close());
1361  QCOMPARE(closeSpy.count(), 3);
1362  QCOMPARE(mdiArea.subWindowList().count(), 0);
1363 }
1364 
1365 // There exists more tests in QMdiArea which covers window title support
1366 // related to QMainWindow. This test is specific for QMdiSubWindow and its
1367 // widget.
1368 void tst_QMdiSubWindow::setWindowTitle()
1369 {
1370  QString expectedWindowTitle = QLatin1String("This is teh shit[*]");
1371  QTextEdit *textEdit = new QTextEdit;
1372  textEdit->setWindowTitle(expectedWindowTitle);
1373  QCOMPARE(textEdit->windowTitle(), expectedWindowTitle);
1374  textEdit->setWindowModified(true);
1375  QCOMPARE(textEdit->isWindowModified(), true);
1376 
1377  QMdiArea mdiArea;
1379  mdiArea.addSubWindow(window);
1380  QCOMPARE(window->windowTitle(), QString());
1381  QVERIFY(!window->isWindowModified());
1382 
1383  window->setWidget(textEdit);
1384  QVERIFY(window->isWindowModified());
1385  QCOMPARE(textEdit->windowTitle(), expectedWindowTitle);
1386  QCOMPARE(window->windowTitle(), window->widget()->windowTitle());
1387 
1388  textEdit->setWindowModified(false);
1389  QVERIFY(!textEdit->isWindowModified());
1390  QVERIFY(!window->isWindowModified());
1391  // This will return the title including the astrix, but the
1392  // actual window title does not contain the astrix. This behavior
1393  // seems a bit odd, but is equal to e.g. QTextEdit (and probably all
1394  // other widgets which are not real top-level widgets).
1395  QCOMPARE(window->windowTitle(), expectedWindowTitle);
1396 
1397  textEdit->setWindowModified(true);;
1398  expectedWindowTitle = QLatin1String("Override child title");
1399  window->setWindowTitle(expectedWindowTitle);
1400  QVERIFY(window->isWindowModified());
1401  QCOMPARE(window->windowTitle(), expectedWindowTitle);
1402 
1403  textEdit->setWindowTitle(QLatin1String("My parent overrides me"));
1404  QCOMPARE(window->windowTitle(), expectedWindowTitle);
1405 
1406  textEdit->setWindowModified(false);
1407  QVERIFY(window->isWindowModified());
1408  QCOMPARE(window->windowTitle(), expectedWindowTitle);
1409 
1410  window->setWindowModified(false);
1411  QVERIFY(!window->isWindowModified());
1412  window->setWindowTitle(QString());
1413  QCOMPARE(window->windowTitle(), QString());
1414 
1415  expectedWindowTitle = QLatin1String("My parent doesn't have any title so now I can set one[*]");
1416  textEdit->setWindowTitle(expectedWindowTitle);
1417  QCOMPARE(window->windowTitle(), expectedWindowTitle);
1418  textEdit->setWindowModified(true);
1419  QVERIFY(window->isWindowModified());
1420 
1421  window->setWidget(nullptr);
1422  QCOMPARE(window->windowTitle(), QString());
1423  QVERIFY(!window->isWindowModified());
1424  delete textEdit;
1425 }
1426 
1427 void tst_QMdiSubWindow::resizeEvents_data()
1428 {
1429  QTest::addColumn<Qt::WindowState>("windowState");
1430  QTest::addColumn<int>("expectedWindowResizeEvents");
1431  QTest::addColumn<int>("expectedWidgetResizeEvents");
1432  QTest::addColumn<bool>("isShadeMode");
1433 
1434  QTest::newRow("minimized") << Qt::WindowMinimized << 1 << 0 << false;
1435  QTest::newRow("maximized") << Qt::WindowMaximized << 1 << 1 << false;
1436  QTest::newRow("shaded") << Qt::WindowMinimized << 1 << 0 << true;
1437 }
1438 
1439 void tst_QMdiSubWindow::resizeEvents()
1440 {
1441  QFETCH(Qt::WindowState, windowState);
1442  QFETCH(int, expectedWindowResizeEvents);
1443  QFETCH(int, expectedWidgetResizeEvents);
1444  QFETCH(bool, isShadeMode);
1445 
1449  QMdiArea *mdiArea = new QMdiArea;
1450  mainWindow.setCentralWidget(mdiArea);
1451  mainWindow.show();
1453 
1454  QMdiSubWindow *window = mdiArea->addSubWindow(new QTextEdit);
1455  window->show();
1456 
1457  EventSpy windowResizeEventSpy(window, QEvent::Resize);
1458  QCOMPARE(windowResizeEventSpy.count(), 0);
1459  EventSpy widgetResizeEventSpy(window->widget(), QEvent::Resize);
1460  QCOMPARE(widgetResizeEventSpy.count(), 0);
1461 
1462  // Set the window state.
1463  if (!isShadeMode)
1464  window->setWindowState(windowState);
1465  else
1466  window->showShaded();
1467 
1468  // Check that the window state is correct.
1469  QCOMPARE(window->windowState(), windowState | Qt::WindowActive);
1470  QCOMPARE(window->widget()->windowState(), windowState);
1471 
1472  // Make sure we got as many resize events as expected.
1473  QCOMPARE(windowResizeEventSpy.count(), expectedWindowResizeEvents);
1474  QCOMPARE(widgetResizeEventSpy.count(), expectedWidgetResizeEvents);
1475  windowResizeEventSpy.clear();
1476  widgetResizeEventSpy.clear();
1477 
1478  // Normalize.
1479  window->showNormal();
1480 
1481  // Check that the window state is correct.
1483  QCOMPARE(window->widget()->windowState(), Qt::WindowNoState);
1484 
1485  // Make sure we got as many resize events as expected.
1486  QCOMPARE(windowResizeEventSpy.count(), expectedWindowResizeEvents);
1487  QCOMPARE(widgetResizeEventSpy.count(), expectedWidgetResizeEvents);
1488 }
1489 
1490 #if defined(Q_OS_MAC)
1491 void tst_QMdiSubWindow::defaultSizeGrip()
1492 {
1493  if (!qApp->style()->inherits("QMacStyle"))
1494  return;
1495  QMdiArea mdiArea;
1496  mdiArea.show();
1497 
1498  // QSizeGrip on windows with decoration.
1499  QMdiSubWindow *windowWithDecoration = mdiArea.addSubWindow(new QWidget);
1500  windowWithDecoration->show();
1501  QVERIFY(windowWithDecoration->findChild<QSizeGrip *>());
1502 
1503  // ...but not on windows without decoration (Qt::FramelessWindowHint).
1504  QMdiSubWindow *windowWithoutDecoration = mdiArea.addSubWindow(new QWidget, Qt::FramelessWindowHint);
1505  windowWithoutDecoration->show();
1506  QVERIFY(!windowWithoutDecoration->findChild<QSizeGrip *>());
1507 }
1508 #endif
1509 
1510 void tst_QMdiSubWindow::hideAndShow()
1511 {
1512  // Create a QTabWidget with two tabs; QMdiArea and QTextEdit.
1513  QTabWidget *tabWidget = new QTabWidget;
1514  QMdiArea *mdiArea = new QMdiArea;
1515  tabWidget->addTab(mdiArea, QLatin1String("QMdiArea"));
1516  tabWidget->addTab(new QTextEdit, QLatin1String("Dummy"));
1517 
1518  // Set the tab widget as the central widget in QMainWindow.
1521  mainWindow.setGeometry(0, 0, 640, 480);
1522  QMenuBar *menuBar = mainWindow.menuBar();
1523  menuBar->setNativeMenuBar(false);
1524  mainWindow.setCentralWidget(tabWidget);
1525  mainWindow.show();
1527 
1529  QMdiSubWindow *subWindow = mdiArea->addSubWindow(new QTextEdit);
1530  subWindow->showMaximized();
1531 #if !defined (Q_OS_DARWIN)
1534 #endif
1535 
1536  // Hide QMdiArea.
1537  tabWidget->setCurrentIndex(1);
1538 
1540  QVERIFY(!subWindow->maximizedButtonsWidget());
1541  QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
1542 
1543  // Show QMdiArea.
1544  tabWidget->setCurrentIndex(0);
1545 
1546 #if !defined (Q_OS_DARWIN)
1548  QVERIFY(subWindow->maximizedButtonsWidget());
1549  QVERIFY(subWindow->maximizedSystemMenuIconWidget());
1551 #endif
1552 
1553  // Hide QMdiArea.
1554  tabWidget->setCurrentIndex(1);
1555 
1556  // Add few more windows.
1557  for (int i = 0; i < 5; ++i)
1558  mdiArea->addSubWindow(new QTextEdit);
1559 
1560  // Show QMdiArea.
1561  tabWidget->setCurrentIndex(0);
1563 
1564  subWindow = mdiArea->subWindowList().back();
1565  QVERIFY(subWindow);
1566  QCOMPARE(mdiArea->activeSubWindow(), subWindow);
1567 
1568 #if !defined (Q_OS_DARWIN)
1570  QVERIFY(subWindow->maximizedButtonsWidget());
1571  QVERIFY(subWindow->maximizedSystemMenuIconWidget());
1573 #endif
1574 
1575  subWindow->showNormal();
1577 
1578  // Check that newly added windows got right sizes.
1579  const auto subWindowList = mdiArea->subWindowList();
1580  for (QMdiSubWindow *window : subWindowList)
1581  QCOMPARE(window->size(), window->sizeHint());
1582 
1583  subWindow->showMaximized();
1584 #ifndef Q_OS_MAC
1586 #endif
1587 
1588  subWindow->hide();
1589  QVERIFY(!subWindow->maximizedButtonsWidget());
1590  QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
1592 
1593  subWindow->show();
1594 #if !defined (Q_OS_DARWIN)
1595  QVERIFY(subWindow->maximizedButtonsWidget());
1596  QVERIFY(subWindow->maximizedSystemMenuIconWidget());
1598 #endif
1599 
1600  // Hide QMainWindow.
1601  mainWindow.hide();
1602  QVERIFY(!subWindow->maximizedButtonsWidget());
1603  QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
1605 
1606  // Show QMainWindow.
1607  mainWindow.show();
1608 #if !defined (Q_OS_DARWIN)
1609  QVERIFY(subWindow->maximizedButtonsWidget());
1610  QVERIFY(subWindow->maximizedSystemMenuIconWidget());
1612 #endif
1613 }
1614 
1615 void tst_QMdiSubWindow::keepWindowMaximizedState()
1616 {
1617  QMdiArea mdiArea;
1618  mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
1619  QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QTextEdit);
1620  mdiArea.show();
1622 
1623  subWindow->showMaximized();
1624  QVERIFY(subWindow->isMaximized());
1625 
1626  // move
1627  const QPoint newPosition = subWindow->pos() + QPoint(10, 10);
1628  subWindow->move(newPosition);
1629  QCOMPARE(subWindow->pos(), newPosition);
1630  QVERIFY(subWindow->isMaximized());
1631 
1632  // resize
1633  const QSize newSize = subWindow->size() - QSize(10, 10);
1634  subWindow->resize(newSize);
1635  QCOMPARE(subWindow->size(), newSize);
1636  QVERIFY(subWindow->isMaximized());
1637 
1638  // setGeometry
1639  const QRect newGeometry = QRect(newPosition - QPoint(10, 10), newSize + QSize(10, 10));
1640  subWindow->setGeometry(newGeometry);
1641  QCOMPARE(subWindow->geometry(), newGeometry);
1642  QVERIFY(subWindow->isMaximized());
1643 
1644  subWindow->showNormal();
1645 
1646  // Verify that we don't force Qt::WindowMaximized.
1647  QVERIFY(!subWindow->isMaximized());
1648  subWindow->setGeometry(QRect(newPosition, newSize));
1649  QCOMPARE(subWindow->geometry(), QRect(newPosition, newSize));
1650  QVERIFY(!subWindow->isMaximized());
1651 }
1652 
1653 void tst_QMdiSubWindow::explicitlyHiddenWidget()
1654 {
1655  QMdiArea mdiArea;
1656  mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
1657  QTextEdit *textEdit = new QTextEdit;
1658  textEdit->hide();
1659  QMdiSubWindow *subWindow = mdiArea.addSubWindow(textEdit);
1660  mdiArea.show();
1662 
1663  QVERIFY(subWindow->isVisible());
1664  QVERIFY(!textEdit->isVisible());
1665 
1666  textEdit->show();
1668 
1669  // normal -> minimized
1670  subWindow->showMinimized();
1671  QVERIFY(subWindow->isVisible());
1672  QVERIFY(!textEdit->isVisible());
1673 
1674  // minimized -> normal
1675  subWindow->showNormal();
1676  QVERIFY(subWindow->isVisible());
1678 
1679  // minimized -> maximized
1680  subWindow->showMinimized();
1681  subWindow->showMaximized();
1682  QVERIFY(subWindow->isVisible());
1684 
1685  textEdit->hide();
1686 
1687  // maximized -> normal
1688  subWindow->showNormal();
1689  QVERIFY(subWindow->isVisible());
1690  QVERIFY(!textEdit->isVisible());
1691 
1692  textEdit->show();
1693 
1694  subWindow->showMinimized();
1695  subWindow->setWidget(nullptr);
1696  delete textEdit;
1697  textEdit = new QTextEdit;
1698  textEdit->hide();
1699  subWindow->setWidget(textEdit);
1700  subWindow->showNormal();
1701  QVERIFY(subWindow->isVisible());
1702  QVERIFY(!textEdit->isVisible());
1703 }
1704 
1705 void tst_QMdiSubWindow::resizeTimer()
1706 {
1707  QMdiArea mdiArea;
1708  mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
1709  QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget);
1710  mdiArea.show();
1712 
1713  EventSpy timerEventSpy(subWindow, QEvent::Timer);
1714  QCOMPARE(timerEventSpy.count(), 0);
1715 
1716  for (int i = 0; i < 20; ++i) {
1717  subWindow->resize(subWindow->size() + QSize(2, 2));
1719  }
1720 
1721  QTest::qWait(500); // Wait for timer events to occur.
1722 
1723  QTRY_VERIFY(timerEventSpy.count() > 0);
1724 }
1725 
1726 void tst_QMdiSubWindow::fixedMinMaxSize()
1727 {
1728  QMdiArea mdiArea;
1729  mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
1730  mdiArea.setGeometry(0, 0, 640, 480);
1731  mdiArea.show();
1733 
1734  const QSize minimumSize = QSize(250, 150);
1735  const QSize maximumSize = QSize(300, 200);
1736 
1737  // Add the sub window to QMdiArea and set min/max size.
1738  QMdiSubWindow *subWindow = new QMdiSubWindow;
1739  subWindow->setMinimumSize(minimumSize);
1740  QCOMPARE(subWindow->minimumSize(), minimumSize);
1741  subWindow->setMaximumSize(maximumSize);
1742  QCOMPARE(subWindow->maximumSize(), maximumSize);
1743  mdiArea.addSubWindow(subWindow);
1744  subWindow->show();
1745  QCOMPARE(subWindow->size(), minimumSize);
1746 
1747  // Calculate the size of a minimized sub window.
1748  QStyleOptionTitleBar options;
1749  options.initFrom(subWindow);
1750  int minimizedHeight = subWindow->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
1751  if (!subWindow->style()->styleHint(QStyle::SH_TitleBar_NoBorder, &options, subWindow))
1752  minimizedHeight += 8;
1753  int minimizedWidth = subWindow->style()->pixelMetric(QStyle::PM_MdiSubWindowMinimizedWidth,
1754  &options);
1755  const QSize minimizedSize = QSize(minimizedWidth, minimizedHeight);
1756 
1757  // Even though the sub window has a minimum size set, it should be possible
1758  // to minimize the window.
1759  subWindow->showMinimized();
1760  QVERIFY(subWindow->isMinimized());
1761  QCOMPARE(subWindow->size(), minimizedSize);
1762  QCOMPARE(subWindow->minimumSize(), minimizedSize);
1763 
1764  // Restore minimum size.
1765  subWindow->showNormal();
1766  QVERIFY(!subWindow->isMinimized());
1767  QCOMPARE(subWindow->size(), minimumSize);
1768  QCOMPARE(subWindow->minimumSize(), minimumSize);
1769 
1770  // Well, the logic here is of course broken (calling showMaximized on a window with
1771  // maximum size set), but we should handle it :)
1772  subWindow->showMaximized();
1773  QVERIFY(subWindow->isMaximized());
1774  QCOMPARE(subWindow->size(), maximumSize);
1775 
1776  subWindow->showNormal();
1777  QVERIFY(!subWindow->isMaximized());
1778  QCOMPARE(subWindow->size(), minimumSize);
1779 }
1780 
1781 #if !defined( Q_OS_DARWIN)
1782 void tst_QMdiSubWindow::replaceMenuBarWhileMaximized()
1783 {
1784 
1787 
1788  QMdiArea *mdiArea = new QMdiArea;
1789  QMdiSubWindow *subWindow = mdiArea->addSubWindow(new QTextEdit);
1790  subWindow->showMaximized();
1791 
1792  mainWindow.setCentralWidget(mdiArea);
1793  QMenuBar *menuBar1 = mainWindow.menuBar();
1794  menuBar1->setNativeMenuBar(false);
1795  mainWindow.show();
1797 
1799 
1800  QVERIFY(subWindow->maximizedButtonsWidget());
1801  QVERIFY(subWindow->maximizedSystemMenuIconWidget());
1804 
1805  // Replace.
1806  auto menuBar2 = new QMenuBar;
1807  mainWindow.setMenuBar(menuBar2);
1808  menuBar2->setNativeMenuBar(false);
1810 
1811  QVERIFY(subWindow->maximizedButtonsWidget());
1812  QVERIFY(subWindow->maximizedSystemMenuIconWidget());
1813  QCOMPARE(menuBar2->cornerWidget(Qt::TopLeftCorner), subWindow->maximizedSystemMenuIconWidget());
1814  QCOMPARE(menuBar2->cornerWidget(Qt::TopRightCorner), subWindow->maximizedButtonsWidget());
1815 
1816  subWindow->showNormal();
1817  QVERIFY(!subWindow->maximizedButtonsWidget());
1818  QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
1819  QVERIFY(!menuBar2->cornerWidget(Qt::TopLeftCorner));
1820  QVERIFY(!menuBar2->cornerWidget(Qt::TopRightCorner));
1821 
1822  // Delete and replace.
1823  subWindow->showMaximized();
1824  delete menuBar2;
1825  auto menuBar3 = new QMenuBar;
1826  mainWindow.setMenuBar(menuBar3);
1828 
1829  QVERIFY(!subWindow->maximizedButtonsWidget());
1830  QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
1831 
1832  subWindow->showNormal();
1833  QVERIFY(!subWindow->maximizedButtonsWidget());
1834  QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
1835 
1836  // Delete.
1837  subWindow->showMaximized();
1838  mainWindow.setMenuBar(nullptr);
1840  QVERIFY(!mainWindow.menuWidget());
1841 
1842  QVERIFY(!subWindow->maximizedButtonsWidget());
1843  QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
1844 
1845  subWindow->showNormal();
1846  QVERIFY(!subWindow->maximizedButtonsWidget());
1847  QVERIFY(!subWindow->maximizedSystemMenuIconWidget());
1848  delete menuBar1;
1849  delete menuBar3;
1850 }
1851 
1852 void tst_QMdiSubWindow::closeOnDoubleClick_data()
1853 {
1854  QTest::addColumn<int>("actionIndex");
1855  QTest::addColumn<bool>("expectClosed");
1856 
1857  QTest::newRow("close") << 1 << true;
1858  QTest::newRow("disabled-restore-action") << 0 << false; // QTBUG-48493
1859 }
1860 
1861 void tst_QMdiSubWindow::closeOnDoubleClick()
1862 {
1863  QFETCH(int, actionIndex);
1864  QFETCH(bool, expectClosed);
1865 
1866  QMdiArea mdiArea;
1867  mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction())
1869  QPointer<QMdiSubWindow> subWindow = mdiArea.addSubWindow(new QWidget);
1870  mdiArea.show();
1872 
1873  subWindow->showSystemMenu();
1874 
1875  QPointer<QMenu> systemMenu;
1876  QTRY_VERIFY( (systemMenu = subWindow->systemMenu()) );
1877  QVERIFY(systemMenu->isVisible());
1878 
1879  const QRect actionGeometry = systemMenu->actionGeometry(systemMenu->actions().at(actionIndex));
1880  sendMouseDoubleClick(systemMenu, actionGeometry.center());
1881  if (QApplication::activePopupWidget() == static_cast<QWidget *>(systemMenu))
1882  systemMenu->hide();
1884  QVERIFY(!systemMenu || !systemMenu->isVisible());
1885  QCOMPARE(subWindow.isNull() || !subWindow->isVisible(), expectClosed);
1886 }
1887 #endif
1888 
1889 void tst_QMdiSubWindow::setFont()
1890 {
1891  QSKIP("This test function is unstable in CI, please see QTBUG-22544");
1892  QMdiArea mdiArea;
1893  mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
1894  QMdiSubWindow *subWindow = mdiArea.addSubWindow(new TestPushButton(QLatin1String("test")));
1895  subWindow->resize(300, 100);
1896  subWindow->setWindowTitle(QLatin1String("Window title"));
1897  mdiArea.show();
1899 
1900 
1901  const QFont originalFont = QApplication::font("QMdiSubWindowTitleBar");
1903  opt.initFrom(subWindow);
1904  const int titleBarHeight = subWindow->style()->pixelMetric(QStyle::PM_TitleBarHeight, &opt);
1905  const QRect titleBarRect = QRect(0, 0, subWindow->width(), titleBarHeight);
1906  const QImage originalTitleBar = subWindow->grab(titleBarRect).toImage();
1907 
1908  QFont newFont(QLatin1String("Helvetica"), 16);
1909  newFont.setBold(true);
1910  subWindow->setFont(newFont);
1912  const QFont &swFont = subWindow->font();
1913  QCOMPARE(swFont.family(), newFont.family());
1914  QCOMPARE(swFont.pointSize(), newFont.pointSize());
1915  QCOMPARE(swFont.weight(), newFont.weight());
1916  QImage newTitleBar = subWindow->grab(titleBarRect).toImage();
1917  QVERIFY(newTitleBar != originalTitleBar);
1918 
1919  subWindow->setFont(originalFont);
1921  QCOMPARE(subWindow->font(), originalFont);
1922  newTitleBar = subWindow->grab(titleBarRect).toImage();
1923  QCOMPARE(newTitleBar, originalTitleBar);
1924 }
1925 
1926 void tst_QMdiSubWindow::task_188849()
1927 {
1930  // Sets a regular QWidget (and NOT a QMenuBar) as the menu bar.
1931  mainWindow.setMenuWidget(new QWidget);
1932 
1933  QMdiArea *mdiArea = new QMdiArea;
1934  QMdiSubWindow *subWindow = mdiArea->addSubWindow(new QWidget);
1935  mainWindow.setCentralWidget(mdiArea);
1936  mainWindow.show();
1938 
1939  // QMdiSubWindow will now try to show its buttons in the menu bar.
1940  // Without checking that the menu bar is actually a QMenuBar
1941  // and not a regular QWidget, this will crash.
1942  subWindow->showMaximized();
1943 }
1944 
1945 void tst_QMdiSubWindow::mdiArea()
1946 {
1947  QMdiArea mdiArea;
1948  mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
1949  QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget);
1950  QCOMPARE(subWindow->mdiArea(), &mdiArea);
1951 
1952  subWindow->setParent(nullptr);
1953  QVERIFY(!subWindow->mdiArea());
1954 
1955  // Child of the area's corner widget.
1956  mdiArea.setCornerWidget(new QWidget);
1957  subWindow->setParent(mdiArea.cornerWidget());
1958  QVERIFY(!subWindow->mdiArea());
1959 
1960  // Nested mdi area.
1961  QMdiArea *nestedArea = new QMdiArea;
1962  mdiArea.addSubWindow(nestedArea);
1963  nestedArea->addSubWindow(subWindow);
1964  QCOMPARE(subWindow->mdiArea(), nestedArea);
1965  nestedArea->setViewport(new QWidget);
1966  QCOMPARE(subWindow->mdiArea(), nestedArea);
1967 }
1968 
1969 void tst_QMdiSubWindow::task_182852()
1970 {
1971  QMdiArea *workspace = new QMdiArea;
1974  mainWindow.setCentralWidget(workspace);
1975  mainWindow.show();
1976  mainWindow.menuBar()->setVisible(true);
1978  if (mainWindow.menuBar()->isNativeMenuBar())
1979  return; // The main window's title is not overwritten if we have a native menubar (macOS, Unity etc.)
1980 
1981  QString originalWindowTitle = QString::fromLatin1("MainWindow - [foo]");
1982  mainWindow.setWindowTitle(originalWindowTitle);
1983 
1985 
1986  QMdiArea *nestedWorkspace = new QMdiArea; // :-)
1987  window->setWidget(nestedWorkspace);
1988  window->widget()->setWindowTitle(QString::fromLatin1("Window"));
1989 
1990  workspace->addSubWindow(window);
1991 
1992  window->showMaximized();
1994  QVERIFY(window->isMaximized());
1995 
1997  .arg(originalWindowTitle, window->widget()->windowTitle()));
1998 
1999  window->showNormal();
2000  QCOMPARE(mainWindow.windowTitle(), originalWindowTitle);
2001 
2002  window->widget()->setWindowTitle(QString::fromLatin1("foo"));
2003  window->showMaximized();
2004 
2005  QCOMPARE(mainWindow.windowTitle(), originalWindowTitle);
2006 
2007  window->showNormal();
2008  QCOMPARE(mainWindow.windowTitle(), originalWindowTitle);
2009 
2010  window->widget()->setWindowTitle(QString::fromLatin1("bar"));
2011  window->showMaximized();
2012 
2014  .arg(originalWindowTitle, window->widget()->windowTitle()));
2015 }
2016 
2017 void tst_QMdiSubWindow::task_233197()
2018 {
2022  mainWindow->resize(500, 200);
2023  mainWindow->show();
2024 
2025  QMdiArea *mdiArea = new QMdiArea(mainWindow);
2027  mainWindow->setCentralWidget(mdiArea);
2028 
2029  QMdiSubWindow *subWindow1 = new QMdiSubWindow();
2030  mdiArea->addSubWindow(subWindow1);
2031  subWindow1->showMaximized();
2032 
2033  QMdiSubWindow *subWindow2 = new QMdiSubWindow();
2034  mdiArea->addSubWindow(subWindow2);
2035  subWindow2->showMaximized();
2036 
2037  QMdiSubWindow *subWindow3 = new QMdiSubWindow();
2038  mdiArea->addSubWindow(subWindow3);
2039  subWindow3->showMaximized();
2040 
2041  QMenuBar *menuBar = mainWindow->menuBar(); // force creation of a menubar
2042  Q_UNUSED(menuBar);
2043 
2044  QPushButton *focus1 = new TestPushButton(QLatin1String("Focus 1"), mainWindow);
2045  QObject::connect(focus1, &QAbstractButton::clicked, subWindow1,
2046  QOverload<>::of(&QWidget::setFocus));
2047  focus1->move(5, 30);
2048  focus1->show();
2049 
2050  QPushButton *focus2 = new TestPushButton(QLatin1String("Focus 2"), mainWindow);
2051  QObject::connect(focus2, &QAbstractButton::clicked, subWindow2,
2052  QOverload<>::of(&QWidget::setFocus));
2053  focus2->move(5, 60);
2054  focus2->show();
2055 
2056  QPushButton *close = new TestPushButton(QLatin1String("Close"), mainWindow);
2058  close->move(5, 90);
2059  close->show();
2060 
2061  QTest::qWait(200);
2062 
2063  sendMousePress(focus2, QPoint());
2064  sendMouseRelease(focus2, QPoint());
2065 
2066  sendMousePress(focus1, QPoint());
2067  sendMouseRelease(focus1, QPoint());
2068 
2069  sendMousePress(focus2, QPoint());
2070  sendMouseRelease(focus2, QPoint());
2071 
2072  sendMousePress(close, QPoint());
2073  sendMouseRelease(close, QPoint());
2074 
2075  QTest::qWait(200);
2076 }
2077 
2078 void tst_QMdiSubWindow::task_226929()
2079 {
2080  QMdiArea mdiArea;
2081  mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
2082  mdiArea.show();
2084 
2085  QMdiSubWindow *sub1 = mdiArea.addSubWindow(new QTextEdit);
2086  sub1->showMinimized();
2087 
2088  QMdiSubWindow *sub2 = mdiArea.addSubWindow(new QTextEdit);
2089  sub2->showMaximized();
2090 
2091  QTest::qWait(100);
2092 
2093  // Do not assert.
2094  // This window will now be activated and automatically maximized
2095  // (if not QMdiArea::DontMaximizeSubWindowOnActionvation is set).
2096  sub1->showNormal();
2097  QVERIFY(sub1->isMaximized());
2098 }
2099 
2100 void tst_QMdiSubWindow::styleChange()
2101 {
2102  QMdiArea mdiArea;
2103  mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
2104  mdiArea.show();
2106 
2107  QMdiSubWindow *sub1 = mdiArea.addSubWindow(new QTextEdit);
2108  sub1->showMaximized();
2109 
2110  QMdiSubWindow *sub2 = mdiArea.addSubWindow(new QTextEdit);
2111  sub2->showMinimized();
2112 
2113  mdiArea.setActiveSubWindow(sub1);
2114 
2115  QTest::qWait(100);
2116 
2117  qRegisterMetaType<QMdiSubWindow *>();
2119  QVERIFY(spy.isValid());
2120 
2124 
2125  // subWindowActivated should NOT be activated by a style change,
2126  // even if internally QMdiSubWindow un-minimizes subwindows temporarily.
2127  QCOMPARE(spy.count(), 0);
2128 }
2129 
2130 void tst_QMdiSubWindow::testFullScreenState()
2131 {
2132  QMdiArea mdiArea;
2133  mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
2134  mdiArea.showMaximized();
2135 
2136  QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget);
2137  subWindow->setGeometry(0, 0, 300, 300);
2138  subWindow->showFullScreen(); // QMdiSubWindow does not support the fullscreen state. This call
2139  // should be equivalent to setVisible(true) (and not showNormal())
2141  QCOMPARE(subWindow->size(), QSize(300, 300));
2142 }
2143 
2144 void tst_QMdiSubWindow::testRemoveBaseWidget()
2145 {
2146  QMdiArea mdiArea;
2147  mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
2148  mdiArea.show();
2149 
2150  QWidget *widget1 = new QWidget;
2151  mdiArea.addSubWindow(widget1);
2152 
2153  QWidget *widget2 = new QWidget;
2154  mdiArea.addSubWindow(widget2);
2155 
2156  mdiArea.removeSubWindow(widget1);
2157  QVERIFY(!widget1->parent());
2158 
2159  widget2->setParent(widget1);
2160  mdiArea.removeSubWindow(widget2);
2161  QCOMPARE(widget2->parent(), widget1);
2162 
2163  delete widget1;
2164 }
2165 
2167 #include "tst_qmdisubwindow.moc"
2168 
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
EventSpy(QObject *object, QEvent::Type event)
bool eventFilter(QObject *object, QEvent *event) override
int count() const
Q_DISABLE_COPY(LayoutDirectionGuard)
LayoutDirectionGuard()=default
MultiWidget(QWidget *parent=nullptr)
QLineEdit * m_lineEdit1
QLineEdit * m_lineEdit2
A simple QTextEdit which can switch between two different size states.
void closeEvent(QCloseEvent *closeEvent) override
void setAcceptClose(bool enable=true)
void clicked(bool checked=false)
static QStyle * style()
static QWidget * focusWidget()
static QWidgetList topLevelWidgets()
static QFont font()
static void setEffectEnabled(Qt::UIEffect, bool enable=true)
static QWidget * activePopupWidget()
static void setActiveWindow(QWidget *act)
void addWidget(QWidget *, int stretch=0, Qt::Alignment alignment=Qt::Alignment())
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
The QCloseEvent class contains parameters that describe a close event.
Definition: qevent.h:629
static bool sendEvent(QObject *receiver, QEvent *event)
static void processEvents(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
The QEvent class is the base class of all event classes. Event objects contain event parameters.
Definition: qcoreevent.h:58
@ Close
Definition: qcoreevent.h:91
@ StyleChange
Definition: qcoreevent.h:149
@ MouseMove
Definition: qcoreevent.h:76
@ Resize
Definition: qcoreevent.h:86
@ MouseButtonPress
Definition: qcoreevent.h:73
@ Timer
Definition: qcoreevent.h:72
@ MouseButtonDblClick
Definition: qcoreevent.h:75
@ Move
Definition: qcoreevent.h:85
@ MouseButtonRelease
Definition: qcoreevent.h:74
The QFont class specifies a query for a font used for drawing text.
Definition: qfont.h:56
QString family() const
Definition: qfont.cpp:821
Weight weight() const
Definition: qfont.cpp:1153
int pointSize() const
Definition: qfont.cpp:899
bool isVisible() const
void setWindowTitle(const QString &title)
QString windowTitle
This property holds the window title (caption).
The QGridLayout class lays out widgets in a grid.
Definition: qgridlayout.h:57
The QGroupBox widget provides a group box frame with a title.
Definition: qgroupbox.h:53
QScreen * primaryScreen
the primary (or default) screen of the application.
static void setLayoutDirection(Qt::LayoutDirection direction)
QString platformName
The name of the underlying platform plugin.
static QList< QScreen * > screens()
The QHBoxLayout class lines up widgets horizontally.
Definition: qboxlayout.h:114
The QIcon class provides scalable icons in different modes and states.
Definition: qicon.h:56
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:73
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
void addWidget(QWidget *w)
Definition: qlayout.cpp:223
The QLineEdit widget is a one-line text editor.
Definition: qlineedit.h:64
Definition: qlist.h:108
bool isEmpty() const noexcept
Definition: qlist.h:418
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
qsizetype count() const noexcept
Definition: qlist.h:415
void append(parameter_type t)
Definition: qlist.h:469
void clear()
Definition: qlist.h:445
The QMainWindow class provides a main application window.\inmodule QtWidgets.
Definition: qmainwindow.h:61
The QMdiArea widget provides an area in which MDI windows are displayed.
Definition: qmdiarea.h:57
QMdiSubWindow * addSubWindow(QWidget *widget, Qt::WindowFlags flags=Qt::WindowFlags())
Definition: qmdiarea.cpp:1966
QMdiSubWindow * activeSubWindow() const
Definition: qmdiarea.cpp:1819
void setOption(AreaOption option, bool on=true)
Definition: qmdiarea.cpp:2106
void subWindowActivated(QMdiSubWindow *)
void removeSubWindow(QWidget *widget)
Definition: qmdiarea.cpp:2011
QList< QMdiSubWindow * > subWindowList(WindowOrder order=CreationOrder) const
Definition: qmdiarea.cpp:1875
@ DontMaximizeSubWindowOnActivation
Definition: qmdiarea.h:73
void setActiveSubWindow(QMdiSubWindow *window)
Definition: qmdiarea.cpp:1831
The QMdiSubWindow class provides a subwindow class for QMdiArea.
Definition: qmdisubwindow.h:56
QSize minimumSizeHint() const override
QWidget * maximizedSystemMenuIconWidget() const
QWidget * maximizedButtonsWidget() const
QWidget * widget() const
QMdiArea * mdiArea() const
void setWidget(QWidget *widget)
The QMenuBar class provides a horizontal menu bar.
Definition: qmenubar.h:56
QWidget * cornerWidget(Qt::Corner corner=Qt::TopRightCorner) const
Definition: qmenubar.cpp:1766
void setNativeMenuBar(bool nativeMenuBar)
Definition: qmenubar.cpp:1802
The QMenu class provides a menu widget for use in menu bars, context menus, and other popup menus.
Definition: qmenu.h:62
QSize sizeHint() const override
Definition: qmenu.cpp:2263
QRect actionGeometry(QAction *) const
Definition: qmenu.cpp:2255
void addAction(QAction *action)
Definition: qwidget.cpp:3129
The QMouseEvent class contains parameters that describe a mouse event.
Definition: qevent.h:231
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
T findChild(const QString &aName=QString(), Qt::FindChildOptions options=Qt::FindChildrenRecursively) const
Definition: qobject.h:168
QObject * parent() const
Definition: qobject.h:409
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Definition: qobject.cpp:2772
virtual bool event(QEvent *event)
Definition: qobject.cpp:1329
virtual bool eventFilter(QObject *watched, QEvent *event)
Definition: qobject.cpp:1484
friend class QWidget
Definition: qobject.h:445
QImage toImage() const
Definition: qpixmap.cpp:443
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:52
bool isNull() const
Definition: qpointer.h:87
The QPushButton widget provides a command button.
Definition: qpushbutton.h:56
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:59
constexpr QPoint topLeft() const noexcept
Definition: qrect.h:248
constexpr QPoint topRight() const noexcept
Definition: qrect.h:254
bool contains(const QRect &r, bool proper=false) const noexcept
Definition: qrect.cpp:887
constexpr QPoint center() const noexcept
Definition: qrect.h:260
bool isValid() const
Definition: qsignalspy.h:130
The QSizeGrip class provides a resize handle for resizing top-level windows.
Definition: qsizegrip.h:52
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:55
constexpr int height() const noexcept
Definition: qsize.h:160
constexpr int width() const noexcept
Definition: qsize.h:157
The QString class provides a Unicode character string.
Definition: qstring.h:388
static QString fromLatin1(QByteArrayView ba)
Definition: qstring.cpp:5488
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=QLatin1Char(' ')) const
Definition: qstring.cpp:8318
static QString number(int, int base=10)
Definition: qstring.cpp:7538
virtual QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option=nullptr, const QWidget *widget=nullptr) const =0
@ SH_TitleBar_NoBorder
Definition: qstyle.h:645
virtual int styleHint(StyleHint stylehint, const QStyleOption *opt=nullptr, const QWidget *widget=nullptr, QStyleHintReturn *returnData=nullptr) const =0
@ SP_TitleBarCloseButton
Definition: qstyle.h:754
@ PM_TitleBarHeight
Definition: qstyle.h:484
@ PM_MdiSubWindowFrameWidth
Definition: qstyle.h:507
@ PM_MdiSubWindowMinimizedWidth
Definition: qstyle.h:508
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option=nullptr, const QWidget *widget=nullptr) const =0
void initFrom(const QWidget *w)
the position of the selected tab in relation to this tab
Definition: qstyleoption.h:630
The QTabWidget class provides a stack of tabbed widgets.
Definition: qtabwidget.h:56
void setCurrentIndex(int index)
Definition: qtabwidget.cpp:711
int addTab(QWidget *widget, const QString &)
Definition: qtabwidget.cpp:395
The QTextEdit class provides a widget that is used to edit and display both plain and rich text.
Definition: qtextedit.h:63
QTextEdit(QWidget *parent=nullptr)
Definition: qtextedit.cpp:637
The QVBoxLayout class lines up widgets vertically.
Definition: qboxlayout.h:127
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:133
void setLayout(QLayout *)
Definition: qwidget.cpp:10146
void setAttribute(Qt::WidgetAttribute, bool on=true)
Definition: qwidget.cpp:11088
void setGeometry(int x, int y, int w, int h)
Definition: qwidget.h:919
Q_INVOKABLE QPixmap grab(const QRect &rectangle=QRect(QPoint(0, 0), QSize(-1, -1)))
Definition: qwidget.cpp:5218
void setParent(QWidget *parent)
Definition: qwidget.cpp:10512
void setMinimumSize(const QSize &)
Definition: qwidget.h:865
void updateGeometry()
Definition: qwidget.cpp:10386
bool isMinimized() const
Definition: qwidget.cpp:2848
QSize size
the size of the widget excluding any window frame
Definition: qwidget.h:147
QSize minimumSize
the widget's minimum size
Definition: qwidget.h:154
QPointF mapToGlobal(const QPointF &) const
QRect geometry
the geometry of the widget relative to its parent and excluding the window frame
Definition: qwidget.h:140
QLayout * layout() const
Definition: qwidget.cpp:10115
int width
the width of the widget excluding any window frame
Definition: qwidget.h:148
void showMinimized()
Definition: qwidget.cpp:2859
QSize maximumSize
the widget's maximum size in pixels
Definition: qwidget.h:155
QPoint pos
the position of the widget within its parent widget
Definition: qwidget.h:145
bool isMaximized() const
Definition: qwidget.cpp:2888
QRect contentsRect() const
Definition: qwidget.cpp:7622
bool close()
Definition: qwidget.cpp:8468
void move(int x, int y)
Definition: qwidget.h:913
void showFullScreen()
Definition: qwidget.cpp:3033
void hide()
Definition: qwidget.cpp:8078
int height
the height of the widget excluding any window frame
Definition: qwidget.h:149
QList< QAction * > actions() const
Definition: qwidget.cpp:3219
QRect rect
the internal geometry of the widget excluding any window frame
Definition: qwidget.h:150
void setWindowState(Qt::WindowStates state)
Definition: qwidget.cpp:2949
void setFocus()
Definition: qwidget.h:454
int y
the y coordinate of the widget relative to its parent and including any window frame
Definition: qwidget.h:144
void show()
Definition: qwidget.cpp:7825
virtual void setVisible(bool visible)
Definition: qwidget.cpp:8198
void setMaximumSize(const QSize &)
Definition: qwidget.h:868
void showMaximized()
Definition: qwidget.cpp:3056
void setWindowTitle(const QString &)
Definition: qwidget.cpp:6119
QStyle * style() const
Definition: qwidget.cpp:2612
void setFont(const QFont &)
Definition: qwidget.cpp:4673
QFont font
the font currently set for the widget
Definition: qwidget.h:167
void resize(int w, int h)
Definition: qwidget.h:916
QString windowTitle
the window title (caption)
Definition: qwidget.h:185
QWidget * parentWidget() const
Definition: qwidget.h:937
void showNormal()
Definition: qwidget.cpp:3072
bool isVisible() const
Definition: qwidget.h:907
TestPushButton(const QString &title, QWidget *parent=nullptr)
bool hitButton(const QPoint &point) const override
Definition: widget.h:60
#define this
Definition: dialogs.cpp:56
QOpenGLWidget * widget
[1]
QPushButton * button
[2]
auto signal
QSignalSpy spy(myCustomObject, SIGNAL(mySignal(int, QString, double)))
[0]
QCOMPARE(spy.count(), 1)
QStyleOptionButton opt
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
JDIMENSION DCTELEM * workspace
Definition: jsimddct.h:16
QList< QWindow * > windows
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Definition: qtestcase.cpp:2658
Q_TESTLIB_EXPORT const char * currentTestFunction()
Definition: qtestcase.cpp:2749
Q_GUI_EXPORT bool qWaitForWindowActive(QWindow *window, int timeout=5000)
Q_GUI_EXPORT bool qWaitForWindowExposed(QWindow *window, int timeout=5000)
Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const char *message)
Definition: qtestcase.cpp:2292
Q_TESTLIB_EXPORT const char * currentDataTag()
Definition: qtestcase.cpp:2758
Q_CORE_EXPORT void qWait(int ms)
Definition: qnamespace.h:55
WindowState
Definition: qnamespace.h:276
@ WindowNoState
Definition: qnamespace.h:277
@ WindowMinimized
Definition: qnamespace.h:278
@ WindowMaximized
Definition: qnamespace.h:279
@ WindowActive
Definition: qnamespace.h:281
@ TopRightCorner
Definition: qnamespace.h:1289
@ TopLeftCorner
Definition: qnamespace.h:1288
MouseButton
Definition: qnamespace.h:81
@ LeftButton
Definition: qnamespace.h:83
@ NoButton
Definition: qnamespace.h:82
@ WA_DeleteOnClose
Definition: qnamespace.h:346
@ LeftToRight
Definition: qnamespace.h:1463
@ RightToLeft
Definition: qnamespace.h:1464
@ UI_AnimateMenu
Definition: qnamespace.h:1168
@ Key_Tab
Definition: qnamespace.h:685
@ Key_Backtab
Definition: qnamespace.h:686
@ ScrollBarAsNeeded
Definition: qnamespace.h:1277
@ CaseInsensitive
Definition: qnamespace.h:1283
QTextStream & center(QTextStream &stream)
WindowType
Definition: qnamespace.h:230
@ CustomizeWindowHint
Definition: qnamespace.h:264
@ Desktop
Definition: qnamespace.h:240
@ Widget
Definition: qnamespace.h:231
@ FramelessWindowHint
Definition: qnamespace.h:250
@ WindowContextHelpButtonHint
Definition: qnamespace.h:256
@ ToolTip
Definition: qnamespace.h:238
@ Drawer
Definition: qnamespace.h:235
@ Popup
Definition: qnamespace.h:236
@ Window
Definition: qnamespace.h:232
@ SplashScreen
Definition: qnamespace.h:239
@ WindowStaysOnTopHint
Definition: qnamespace.h:258
@ WindowMaximizeButtonHint
Definition: qnamespace.h:254
@ WindowMinimizeButtonHint
Definition: qnamespace.h:253
@ Dialog
Definition: qnamespace.h:233
@ WindowShadeButtonHint
Definition: qnamespace.h:257
@ WindowMinMaxButtonsHint
Definition: qnamespace.h:255
@ Sheet
Definition: qnamespace.h:234
@ SubWindow
Definition: qnamespace.h:241
@ Tool
Definition: qnamespace.h:237
@ WindowTitleHint
Definition: qnamespace.h:251
@ WindowSystemMenuHint
Definition: qnamespace.h:252
@ WindowCloseButtonHint
Definition: qnamespace.h:266
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool startsWith(QByteArrayView haystack, QByteArrayView needle) noexcept
#define QString()
Definition: parse-defines.h:51
#define qApp
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
@ QtWarningMsg
Definition: qlogging.h:62
#define SLOT(a)
Definition: qobjectdefs.h:87
#define SIGNAL(a)
Definition: qobjectdefs.h:88
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLboolean enable
GLenum GLuint GLintptr offset
struct _cl_event * event
Definition: qopenglext.h:2998
#define QStringLiteral(str)
#define tr(X)
#define QTEST_MAIN(TestObject)
Definition: qtest.h:664
#define QSKIP(statement,...)
Definition: qtestcase.h:222
#define QFETCH(Type, name)
Definition: qtestcase.h:230
#define QTRY_COMPARE(expr, expected)
Definition: qtestcase.h:214
#define QVERIFY(statement)
Definition: qtestcase.h:64
#define QTRY_VERIFY(expr)
Definition: qtestcase.h:196
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define slots
Definition: qtmetamacros.h:76
Q_WIDGETS_EXPORT QWidgetPrivate * qt_widget_private(QWidget *widget)
Definition: qwidget.cpp:12216
QWidget * qobject_cast< QWidget * >(QObject *o)
Definition: qwidget.h:819
Q_UNUSED(salary)
[21]
QVBoxLayout * layout
QString title
[35]
timer inherits("QTimer")
QGraphicsWidget * textEdit
myWidget restoreGeometry(settings.value("myWidget/geometry").toByteArray())
aWidget window() -> setWindowTitle("New Window Title")
[2]
QMenuBar * menuBar
[0]
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:53
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
Definition: jquant2.c:237
@ windowSize
QT_BEGIN_NAMESPACE bool qt_tab_all_widgets()
Q_DECLARE_METATYPE(Qt::WindowState)