diff options
Diffstat (limited to 'tests/auto/widgets')
294 files changed, 10726 insertions, 3976 deletions
diff --git a/tests/auto/widgets/CMakeLists.txt b/tests/auto/widgets/CMakeLists.txt index 883824d8f0..5ffacc9f18 100644 --- a/tests/auto/widgets/CMakeLists.txt +++ b/tests/auto/widgets/CMakeLists.txt @@ -1,7 +1,5 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from widgets.pro. +# SPDX-License-Identifier: BSD-3-Clause add_subdirectory(dialogs) add_subdirectory(effects) diff --git a/tests/auto/widgets/dialogs/CMakeLists.txt b/tests/auto/widgets/dialogs/CMakeLists.txt index 6e9c1f343b..f46950b6bf 100644 --- a/tests/auto/widgets/dialogs/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/CMakeLists.txt @@ -1,7 +1,5 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from dialogs.pro. +# SPDX-License-Identifier: BSD-3-Clause add_subdirectory(qcolordialog) add_subdirectory(qdialog) diff --git a/tests/auto/widgets/dialogs/qcolordialog/CMakeLists.txt b/tests/auto/widgets/dialogs/qcolordialog/CMakeLists.txt index 9b7bcce02d..2cba18c0f0 100644 --- a/tests/auto/widgets/dialogs/qcolordialog/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qcolordialog/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qcolordialog.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qcolordialog Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qcolordialog LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qcolordialog SOURCES tst_qcolordialog.cpp diff --git a/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp b/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp index 7d2f59dc83..5ae8eaf30d 100644 --- a/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp +++ b/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp @@ -1,10 +1,12 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QtGui/QtGui> #include <QtWidgets/QColorDialog> +#include <QtWidgets/QLineEdit> +#include <QSignalSpy> QT_FORWARD_DECLARE_CLASS(QtTestEventThread) @@ -25,6 +27,10 @@ private slots: void native_activeModalWidget(); void task247349_alpha(); void QTBUG_43548_initialColor(); + void hexColor_data(); + void hexColor(); + + void hideNativeByDestruction(); }; class TestNativeDialog : public QColorDialog @@ -77,7 +83,7 @@ void tst_QColorDialog::native_activeModalWidget() void tst_QColorDialog::postKeyReturn() { QWidgetList list = QApplication::topLevelWidgets(); - for (int i=0; i<list.count(); ++i) { + for (int i=0; i<list.size(); ++i) { QColorDialog *dialog = qobject_cast<QColorDialog *>(list[i]); if (dialog) { QTest::keyClick( list[i], Qt::Key_Return, Qt::NoModifier ); @@ -126,5 +132,81 @@ void tst_QColorDialog::QTBUG_43548_initialColor() QCOMPARE(a, dialog.currentColor()); } +void tst_QColorDialog::hexColor_data() +{ + QTest::addColumn<const QString>("colorString"); + QTest::addColumn<const QString>("expectedHexColor"); + QTest::addColumn<const int>("expectedSignalCount"); + + QTest::newRow("White-#") << "#FFFFFE" << "#FFFFFE" << 1; + QTest::newRow("White") << "FFFFFD" << "#FFFFFD" << 1; + QTest::newRow("Blue-#") << "#77fffb" << "#77fffb" << 2; + QTest::newRow("Blue") << "77fffa" << "#77fffa" << 2; +} + +void tst_QColorDialog::hexColor() +{ + QColorDialog dialog; + dialog.setOption(QColorDialog::DontUseNativeDialog); + dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + + QLineEdit *lineEdit = dialog.findChild<QLineEdit *>("qt_colorname_lineedit", + Qt::FindChildrenRecursively); + QVERIFY2(lineEdit, "QLineEdit for color not found. Adapt this test."); + QVERIFY(lineEdit); // eliminate compiler warning + + QFETCH(const QString, colorString); + QFETCH(const QString, expectedHexColor); + QFETCH(const int, expectedSignalCount); + + QSignalSpy spy(&dialog, &QColorDialog::currentColorChanged); + + // Delete existing color + lineEdit->activateWindow(); + QVERIFY(QTest::qWaitForWindowActive(lineEdit)); + for (int i = 0; i < 8; ++i) + QTest::keyEvent(QTest::KeyAction::Click, lineEdit, Qt::Key_Backspace); + QVERIFY(lineEdit->text().isEmpty()); + + // Enter new color + for (const QChar &key : colorString) + QTest::keyEvent(QTest::KeyAction::Click, lineEdit, key.toLatin1()); + QCOMPARE(lineEdit->text().toLower(), expectedHexColor.toLower()); + + // Consume all color change signals + QTRY_COMPARE(spy.count(), expectedSignalCount); + + const QColor color = qvariant_cast<QColor>(spy.last().at(0)); + QCOMPARE(color.name(QColor::HexRgb), expectedHexColor.toLower()); +} + +void tst_QColorDialog::hideNativeByDestruction() +{ + QWidget window; + QWidget *child = new QWidget(&window); + QPointer<QColorDialog> dialog = new QColorDialog(child); + // Make it application modal so that we don't end up with a sheet on macOS + dialog->setWindowModality(Qt::ApplicationModal); + window.show(); + QVERIFY(QTest::qWaitForWindowActive(&window)); + dialog->open(); + + // We test that the dialog opens and closes by watching the activation of the + // transient parent window. If it doesn't deactivate, then we have to skip. + const auto windowActive = [&window]{ return window.isActiveWindow(); }; + const auto windowInactive = [&window]{ return !window.isActiveWindow(); }; + if (!QTest::qWaitFor(windowInactive, 2000)) + QSKIP("Dialog didn't activate"); + + // This should destroy the dialog and close the native window + child->deleteLater(); + QTRY_VERIFY(!dialog); + // If the native window is still open, then the transient parent can't become + // active + window.activateWindow(); + QVERIFY(QTest::qWaitFor(windowActive)); +} + QTEST_MAIN(tst_QColorDialog) #include "tst_qcolordialog.moc" diff --git a/tests/auto/widgets/dialogs/qdialog/CMakeLists.txt b/tests/auto/widgets/dialogs/qdialog/CMakeLists.txt index 61ec486cea..d69310541d 100644 --- a/tests/auto/widgets/dialogs/qdialog/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qdialog/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qdialog.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qdialog Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qdialog LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qdialog SOURCES tst_qdialog.cpp @@ -15,4 +19,5 @@ qt_internal_add_test(tst_qdialog Qt::Gui Qt::GuiPrivate Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp index b18a5c9d12..13f971f5f0 100644 --- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp +++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "../../../shared/highdpi.h" @@ -22,6 +22,8 @@ #include <qpa/qplatformtheme.h> #include <qpa/qplatformtheme_p.h> +#include <QtWidgets/private/qapplication_p.h> + QT_FORWARD_DECLARE_CLASS(QDialog) // work around function being protected @@ -133,7 +135,7 @@ void tst_QDialog::defaultButtons() pushThree->setAutoDefault(false); testWidget.show(); - QApplication::setActiveWindow(&testWidget); + QApplicationPrivate::setActiveWindow(&testWidget); QVERIFY(QTest::qWaitForWindowExposed(&testWidget)); push->setDefault(true); @@ -284,6 +286,10 @@ void tst_QDialog::showAsTool() { if (QStringList{"xcb", "offscreen"}.contains(QGuiApplication::platformName())) QSKIP("activeWindow() is not respected by all Xcb window managers and the offscreen plugin"); + + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + DummyDialog testWidget; testWidget.resize(200, 200); testWidget.setWindowTitle(QTest::currentTestFunction()); @@ -689,7 +695,7 @@ void tst_QDialog::virtualsOnClose() // Qt doesn't deliver events to QWidgets closed during destruction QCOMPARE(filter.closeEventCount, 0); // QDialog doesn't emit signals when closed by destruction - QCOMPARE(rejectedSpy.count(), 0); + QCOMPARE(rejectedSpy.size(), 0); } } @@ -742,7 +748,7 @@ void tst_QDialog::quitOnDone() // also quit with a timer in case the test fails QTimer::singleShot(1000, QApplication::instance(), &QApplication::quit); QApplication::exec(); - QCOMPARE(quitSpy.count(), 1); + QCOMPARE(quitSpy.size(), 1); } void tst_QDialog::focusWidgetAfterOpen() diff --git a/tests/auto/widgets/dialogs/qerrormessage/CMakeLists.txt b/tests/auto/widgets/dialogs/qerrormessage/CMakeLists.txt index fb84e0833e..a26401c417 100644 --- a/tests/auto/widgets/dialogs/qerrormessage/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qerrormessage/CMakeLists.txt @@ -1,19 +1,21 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qerrormessage.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qerrormessage Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qerrormessage LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qerrormessage SOURCES tst_qerrormessage.cpp LIBRARIES Qt::Gui + Qt::GuiPrivate Qt::Widgets ) - -#### Keys ignored in scope 1:.:.:qerrormessage.pro:<TRUE>: -# TEMPLATE = "app" diff --git a/tests/auto/widgets/dialogs/qerrormessage/tst_qerrormessage.cpp b/tests/auto/widgets/dialogs/qerrormessage/tst_qerrormessage.cpp index 97dad396e5..53ade3cbc6 100644 --- a/tests/auto/widgets/dialogs/qerrormessage/tst_qerrormessage.cpp +++ b/tests/auto/widgets/dialogs/qerrormessage/tst_qerrormessage.cpp @@ -1,20 +1,43 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QErrorMessage> #include <QDebug> #include <QCheckBox> +#include <qpa/qplatformtheme.h> +#include <private/qguiapplication_p.h> + class tst_QErrorMessage : public QObject { Q_OBJECT private slots: + void initTestCase_data(); + void init(); + void dontShowAgain(); void dontShowCategoryAgain(); + void baseClassSetVisible(); }; +void tst_QErrorMessage::initTestCase_data() +{ + QTest::addColumn<bool>("useNativeDialog"); + QTest::newRow("widget") << false; + if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { + if (theme->usePlatformNativeDialog(QPlatformTheme::MessageDialog)) + QTest::newRow("native") << true; + } +} + +void tst_QErrorMessage::init() +{ + QFETCH_GLOBAL(bool, useNativeDialog); + qApp->setAttribute(Qt::AA_DontUseNativeDialogs, !useNativeDialog); +} + void tst_QErrorMessage::dontShowAgain() { QString plainString = QLatin1String("foo"); @@ -47,8 +70,7 @@ void tst_QErrorMessage::dontShowAgain() QVERIFY(errorMessageDialog.isVisible()); checkBox = errorMessageDialog.findChild<QCheckBox*>(); QVERIFY(checkBox); - QVERIFY(!checkBox->isChecked()); - checkBox->setChecked(true); + QVERIFY(checkBox->isChecked()); errorMessageDialog.close(); errorMessageDialog.showMessage(htmlString); @@ -116,5 +138,13 @@ void tst_QErrorMessage::dontShowCategoryAgain() QVERIFY(errorMessageDialog.isVisible()); } +void tst_QErrorMessage::baseClassSetVisible() +{ + QErrorMessage errorMessage; + errorMessage.QDialog::setVisible(true); + QCOMPARE(errorMessage.isVisible(), true); + errorMessage.close(); +} + QTEST_MAIN(tst_QErrorMessage) #include "tst_qerrormessage.moc" diff --git a/tests/auto/widgets/dialogs/qfiledialog/BLACKLIST b/tests/auto/widgets/dialogs/qfiledialog/BLACKLIST index 38c40c6211..38aa416115 100644 --- a/tests/auto/widgets/dialogs/qfiledialog/BLACKLIST +++ b/tests/auto/widgets/dialogs/qfiledialog/BLACKLIST @@ -4,5 +4,7 @@ android # QTBUG-101194 android # QTBUG-101194 [historyBack] android # QTBUG-101194 +[completer_data] +android # QTBUG-108329 [completer] android # QTBUG-101194 diff --git a/tests/auto/widgets/dialogs/qfiledialog/CMakeLists.txt b/tests/auto/widgets/dialogs/qfiledialog/CMakeLists.txt index ff5c125af8..000d99cdcf 100644 --- a/tests/auto/widgets/dialogs/qfiledialog/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qfiledialog/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qfiledialog.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qfiledialog Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qfiledialog LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qfiledialog SOURCES tst_qfiledialog.cpp diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp index e0d091c3bd..6ebf255f31 100644 --- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -13,7 +13,7 @@ #include <qsharedpointer.h> #include <qfiledialog.h> #include <qabstractitemdelegate.h> -#include <qitemdelegate.h> +#include <qstyleditemdelegate.h> #include <qlistview.h> #include <qcombobox.h> #include <qpushbutton.h> @@ -38,6 +38,8 @@ #include <QFileDialog> #include <QFileSystemModel> +#include <QtWidgets/private/qapplication_p.h> + #if defined(Q_OS_UNIX) #include <unistd.h> // for pathconf() on OS X #ifdef QT_BUILD_INTERNAL @@ -126,9 +128,10 @@ private slots: void QTBUG49600_nativeIconProviderCrash(); void focusObjectDuringDestruction(); - // NOTE: Please keep widgetlessNativeDialog() as the LAST test! + // NOTE: Please keep widgetlessNativeDialog() and + // hideNativeByDestruction() as the LAST tests! // - // widgetlessNativeDialog() is the only test function that creates + // widgetlessNativeDialog() are the only test functions that create // a native file dialog instance. GTK+ versions prior 3.15.5 have // a nasty bug (https://bugzilla.gnome.org/show_bug.cgi?id=725164) // in GtkFileChooserWidget, which makes it leak its folder change @@ -139,6 +142,7 @@ private slots: // The crash has been fixed in GTK+ 3.15.5, but the RHEL 7.2 CI has // GTK+ 3.14.13 installed (QTBUG-55276). void widgetlessNativeDialog(); + void hideNativeByDestruction(); private: void cleanupSettingsFile(); @@ -206,7 +210,7 @@ void tst_QFiledialog::currentChangedSignal() QVERIFY(listView->model()->hasChildren(folder)); listView->setCurrentIndex(folder); - QCOMPARE(spyCurrentChanged.count(), 1); + QCOMPARE(spyCurrentChanged.size(), 1); } // only emitted from the views, sidebar, or lookin combo @@ -228,7 +232,7 @@ void tst_QFiledialog::directoryEnteredSignal() QVERIFY(secondItem.isValid()); sidebar->setCurrentIndex(secondItem); QTest::keyPress(sidebar->viewport(), Qt::Key_Return); - QCOMPARE(spyDirectoryEntered.count(), 1); + QCOMPARE(spyDirectoryEntered.size(), 1); spyDirectoryEntered.clear(); // lookInCombo @@ -237,7 +241,7 @@ void tst_QFiledialog::directoryEnteredSignal() QVERIFY(comboBox->view()->model()->index(1, 0).isValid()); comboBox->view()->setCurrentIndex(comboBox->view()->model()->index(1, 0)); QTest::keyPress(comboBox->view()->viewport(), Qt::Key_Return); - QCOMPARE(spyDirectoryEntered.count(), 1); + QCOMPARE(spyDirectoryEntered.size(), 1); spyDirectoryEntered.clear(); // view @@ -314,7 +318,7 @@ void tst_QFiledialog::filesSelectedSignal() QVERIFY(button->isEnabled()); button->animateClick(); QTRY_COMPARE(fd.isVisible(), false); - QCOMPARE(spyFilesSelected.count(), 1); + QCOMPARE(spyFilesSelected.size(), 1); } // only emitted when the combo box is activated @@ -339,7 +343,7 @@ void tst_QFiledialog::filterSelectedSignal() QTest::keyPress(filters, Qt::Key_Down); - QCOMPARE(spyFilterSelected.count(), 1); + QCOMPARE(spyFilterSelected.size(), 1); } void tst_QFiledialog::args() @@ -380,14 +384,14 @@ void tst_QFiledialog::directory() #ifndef Q_OS_WIN QCOMPARE(tempPath, fd.directory().absolutePath()); #endif - QCOMPARE(spyCurrentChanged.count(), 0); - QCOMPARE(spyDirectoryEntered.count(), 0); - QCOMPARE(spyFilesSelected.count(), 0); - QCOMPARE(spyFilterSelected.count(), 0); + QCOMPARE(spyCurrentChanged.size(), 0); + QCOMPARE(spyDirectoryEntered.size(), 0); + QCOMPARE(spyFilesSelected.size(), 0); + QCOMPARE(spyFilterSelected.size(), 0); // Check my way QList<QListView*> list = fd.findChildren<QListView*>("listView"); - QVERIFY(list.count() > 0); + QVERIFY(list.size() > 0); #ifdef Q_OS_WIN QCOMPARE(list.at(0)->rootIndex().data().toString().toLower(), temp.dirName().toLower()); #else @@ -420,13 +424,9 @@ void tst_QFiledialog::completer_data() QDir dir = QDir::root(); #ifdef Q_OS_ANDROID - // Android 11 and above doesn't allow accessing root filesystem as before, - // so let's opt int for the app's home. - if (QNativeInterface::QAndroidApplication::sdkVersion() >= 30) { - const auto homePaths = QStandardPaths::standardLocations(QStandardPaths::HomeLocation); - QVERIFY(!homePaths.isEmpty()); - dir = QDir(homePaths.first()); - } + const auto homePaths = QStandardPaths::standardLocations(QStandardPaths::HomeLocation); + QVERIFY(!homePaths.isEmpty()); + dir = QDir(homePaths.first()); #endif QFileInfoList list = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); @@ -519,7 +519,6 @@ void tst_QFiledialog::completer() for (int i = 0; i < input.size(); ++i) QTest::keyPress(lineEdit, input[i].toLatin1()); - QStringList expectedFiles; if (expected == -1) { QString fullPath = startPath; if (!fullPath.endsWith(QLatin1Char('/'))) @@ -532,11 +531,11 @@ void tst_QFiledialog::completer() QFileInfo fi(fullPath); QDir x(fi.absolutePath()); - expectedFiles = x.entryList(model->filter()); + const QStringList expectedFiles = x.entryList(model->filter()); expected = 0; if (input.startsWith("..")) input.clear(); - foreach (const QString &expectedFile, expectedFiles) { + for (const QString &expectedFile : expectedFiles) { if (expectedFile.startsWith(input, caseSensitivity)) ++expected; } @@ -572,16 +571,16 @@ void tst_QFiledialog::completer_up() fd.show(); QLineEdit *lineEdit = fd.findChild<QLineEdit*>("fileNameEdit"); QVERIFY(lineEdit); - QCOMPARE(spyFilesSelected.count(), 0); - int depth = QDir::currentPath().split('/').count(); + QCOMPARE(spyFilesSelected.size(), 0); + int depth = QDir::currentPath().split('/').size(); for (int i = 0; i <= depth * 3 + 1; ++i) { lineEdit->insert("../"); qApp->processEvents(); } - QCOMPARE(spyCurrentChanged.count(), 0); - QCOMPARE(spyDirectoryEntered.count(), 0); - QCOMPARE(spyFilesSelected.count(), 0); - QCOMPARE(spyFilterSelected.count(), 0); + QCOMPARE(spyCurrentChanged.size(), 0); + QCOMPARE(spyDirectoryEntered.size(), 0); + QCOMPARE(spyFilesSelected.size(), 0); + QCOMPARE(spyFilterSelected.size(), 0); } void tst_QFiledialog::acceptMode() @@ -661,7 +660,7 @@ void tst_QFiledialog::filters() // effects QList<QComboBox*> views = fd.findChildren<QComboBox*>("fileTypeCombo"); - QCOMPARE(views.count(), 1); + QCOMPARE(views.size(), 1); QCOMPARE(views.at(0)->isVisible(), false); QStringList filters; @@ -676,15 +675,15 @@ void tst_QFiledialog::filters() QCOMPARE(fd.nameFilters(), filters); fd.setNameFilter("Image files (*.png *.xpm *.jpg);;Text files (*.txt);;Any files (*.*)"); QCOMPARE(fd.nameFilters(), filters); - QCOMPARE(spyCurrentChanged.count(), 0); - QCOMPARE(spyDirectoryEntered.count(), 0); - QCOMPARE(spyFilesSelected.count(), 0); - QCOMPARE(spyFilterSelected.count(), 0); + QCOMPARE(spyCurrentChanged.size(), 0); + QCOMPARE(spyDirectoryEntered.size(), 0); + QCOMPARE(spyFilesSelected.size(), 0); + QCOMPARE(spyFilterSelected.size(), 0); // setting shouldn't emit any signals for (int i = views.at(0)->currentIndex(); i < views.at(0)->count(); ++i) views.at(0)->setCurrentIndex(i); - QCOMPARE(spyFilterSelected.count(), 0); + QCOMPARE(spyFilterSelected.size(), 0); //Let check if filters with whitespaces QFileDialog fd2; @@ -723,7 +722,7 @@ void tst_QFiledialog::selectFilter() QCOMPARE(fd.selectedNameFilter(), filters.at(2)); fd.selectNameFilter(""); QCOMPARE(fd.selectedNameFilter(), filters.at(2)); - QCOMPARE(spyFilterSelected.count(), 0); + QCOMPARE(spyFilterSelected.size(), 0); } void tst_QFiledialog::history() @@ -762,10 +761,10 @@ void tst_QFiledialog::history() badHistory << QDir::toNativeSeparators(QDir::current().absolutePath()); QCOMPARE(fd.history(), badHistory); - QCOMPARE(spyCurrentChanged.count(), 0); - QCOMPARE(spyDirectoryEntered.count(), 0); - QCOMPARE(spyFilesSelected.count(), 0); - QCOMPARE(spyFilterSelected.count(), 0); + QCOMPARE(spyCurrentChanged.size(), 0); + QCOMPARE(spyDirectoryEntered.size(), 0); + QCOMPARE(spyFilesSelected.size(), 0); + QCOMPARE(spyFilterSelected.size(), 0); } void tst_QFiledialog::iconProvider() @@ -807,7 +806,7 @@ void tst_QFiledialog::itemDelegate() { QFileDialog fd; QVERIFY(fd.itemDelegate() != 0); - QItemDelegate *id = new QItemDelegate(&fd); + QStyledItemDelegate *id = new QStyledItemDelegate(&fd); fd.setItemDelegate(id); QCOMPARE(fd.itemDelegate(), (QAbstractItemDelegate *)id); } @@ -868,7 +867,7 @@ void tst_QFiledialog::selectFile() QVERIFY(model); fd->setDirectory(QDir::currentPath()); // default value - QCOMPARE(fd->selectedFiles().count(), 1); + QCOMPARE(fd->selectedFiles().size(), 1); QScopedPointer<QTemporaryFile> tempFile; if (file == QLatin1String("temp")) { @@ -878,7 +877,7 @@ void tst_QFiledialog::selectFile() } fd->selectFile(file); - QCOMPARE(fd->selectedFiles().count(), count); + QCOMPARE(fd->selectedFiles().size(), count); if (tempFile.isNull()) { QCOMPARE(model->index(fd->directory().path()), model->index(QDir::currentPath())); } else { @@ -926,7 +925,7 @@ void tst_QFiledialog::selectFiles() QString filesPath = fd.directory().absolutePath(); for (int i=0; i < 5; ++i) { QFile file(filesPath + QLatin1String("/qfiledialog_auto_test_not_pres_") + QString::number(i)); - file.open(QIODevice::WriteOnly); + QVERIFY(file.open(QIODevice::WriteOnly)); file.resize(1024); file.flush(); file.close(); @@ -935,29 +934,29 @@ void tst_QFiledialog::selectFiles() // Get a list of files in the view and then get the corresponding index's QStringList list = fd.directory().entryList(QDir::Files); QModelIndexList toSelect; - QVERIFY(list.count() > 1); + QVERIFY(list.size() > 1); QListView* listView = fd.findChild<QListView*>("listView"); QVERIFY(listView); - for (int i = 0; i < list.count(); ++i) { + for (int i = 0; i < list.size(); ++i) { fd.selectFile(fd.directory().path() + QLatin1Char('/') + list.at(i)); QTRY_VERIFY(!listView->selectionModel()->selectedRows().isEmpty()); toSelect.append(listView->selectionModel()->selectedRows().last()); } - QCOMPARE(spyFilesSelected.count(), 0); + QCOMPARE(spyFilesSelected.size(), 0); listView->selectionModel()->clear(); - QCOMPARE(spyFilesSelected.count(), 0); + QCOMPARE(spyFilesSelected.size(), 0); // select the indexes - for (int i = 0; i < toSelect.count(); ++i) { + for (int i = 0; i < toSelect.size(); ++i) { listView->selectionModel()->select(toSelect.at(i), QItemSelectionModel::Select | QItemSelectionModel::Rows); } - QCOMPARE(fd.selectedFiles().count(), toSelect.count()); - QCOMPARE(spyCurrentChanged.count(), 0); - QCOMPARE(spyDirectoryEntered.count(), 0); - QCOMPARE(spyFilesSelected.count(), 0); - QCOMPARE(spyFilterSelected.count(), 0); + QCOMPARE(fd.selectedFiles().size(), toSelect.size()); + QCOMPARE(spyCurrentChanged.size(), 0); + QCOMPARE(spyDirectoryEntered.size(), 0); + QCOMPARE(spyFilesSelected.size(), 0); + QCOMPARE(spyFilterSelected.size(), 0); } @@ -983,13 +982,13 @@ void tst_QFiledialog::viewMode() // find widgets QList<QTreeView*> treeView = fd.findChildren<QTreeView*>("treeView"); - QCOMPARE(treeView.count(), 1); + QCOMPARE(treeView.size(), 1); QList<QListView*> listView = fd.findChildren<QListView*>("listView"); - QCOMPARE(listView.count(), 1); + QCOMPARE(listView.size(), 1); QList<QToolButton*> listButton = fd.findChildren<QToolButton*>("listModeButton"); - QCOMPARE(listButton.count(), 1); + QCOMPARE(listButton.size(), 1); QList<QToolButton*> treeButton = fd.findChildren<QToolButton*>("detailModeButton"); - QCOMPARE(treeButton.count(), 1); + QCOMPARE(treeButton.size(), 1); // default value QCOMPARE(fd.viewMode(), QFileDialog::List); @@ -1118,7 +1117,6 @@ void tst_QFiledialog::focus() QFileDialog fd; fd.setDirectory(QDir::currentPath()); fd.show(); - QApplication::setActiveWindow(&fd); QVERIFY(QTest::qWaitForWindowActive(&fd)); QCOMPARE(fd.isVisible(), true); QCOMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd)); @@ -1128,7 +1126,7 @@ void tst_QFiledialog::focus() QCursor::setPos(fd.geometry().center()); QList<QWidget*> treeView = fd.findChildren<QWidget*>("fileNameEdit"); - QCOMPARE(treeView.count(), 1); + QCOMPARE(treeView.size(), 1); QVERIFY(treeView.at(0)); QTRY_COMPARE(treeView.at(0)->hasFocus(), true); QCOMPARE(treeView.at(0)->hasFocus(), true); @@ -1158,13 +1156,13 @@ void tst_QFiledialog::historyBack() QCOMPARE(backButton->isEnabled(), true); QCOMPARE(forwardButton->isEnabled(), false); fd.setDirectory(desktop); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); backButton->click(); qApp->processEvents(); QCOMPARE(backButton->isEnabled(), true); QCOMPARE(forwardButton->isEnabled(), true); - QCOMPARE(spy.count(), 3); + QCOMPARE(spy.size(), 3); QString currentPath = qvariant_cast<QString>(spy.last().first()); QCOMPARE(model->index(currentPath), model->index(temp)); @@ -1173,11 +1171,11 @@ void tst_QFiledialog::historyBack() QCOMPARE(currentPath, home); QCOMPARE(backButton->isEnabled(), false); QCOMPARE(forwardButton->isEnabled(), true); - QCOMPARE(spy.count(), 4); + QCOMPARE(spy.size(), 4); // nothing should change at this point backButton->click(); - QCOMPARE(spy.count(), 4); + QCOMPARE(spy.size(), 4); QCOMPARE(backButton->isEnabled(), false); QCOMPARE(forwardButton->isEnabled(), true); } @@ -1211,7 +1209,7 @@ void tst_QFiledialog::historyForward() QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(desktop)); QCOMPARE(backButton->isEnabled(), true); QCOMPARE(forwardButton->isEnabled(), false); - QCOMPARE(spy.count(), 4); + QCOMPARE(spy.size(), 4); backButton->click(); QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(temp)); @@ -1221,13 +1219,13 @@ void tst_QFiledialog::historyForward() QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(home)); QCOMPARE(backButton->isEnabled(), false); QCOMPARE(forwardButton->isEnabled(), true); - QCOMPARE(spy.count(), 6); + QCOMPARE(spy.size(), 6); forwardButton->click(); QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(temp)); backButton->click(); QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(home)); - QCOMPARE(spy.count(), 8); + QCOMPARE(spy.size(), 8); forwardButton->click(); QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(temp)); @@ -1440,7 +1438,7 @@ void tst_QFiledialog::widgetlessNativeDialog() QSKIP("This platform always uses widgets to realize its QFileDialog, instead of the native file dialog."); #ifdef Q_OS_ANDROID // QTBUG-101194 - QSKIP("Android: This keeeps the window open. Figure out why."); + QSKIP("Android: This keeps the window open. Figure out why."); #endif QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, false); QFileDialog fd; @@ -1454,6 +1452,46 @@ void tst_QFiledialog::widgetlessNativeDialog() QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, true); } +void tst_QFiledialog::hideNativeByDestruction() +{ + if (!QGuiApplicationPrivate::platformTheme()->usePlatformNativeDialog(QPlatformTheme::FileDialog)) + QSKIP("This platform always uses widgets to realize its QFileDialog, instead of the native file dialog."); + +#ifdef Q_OS_ANDROID + // QTBUG-101194 + QSKIP("Android: This keeps the native window open. Figure out why."); +#endif + + QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, false); + auto resetAttribute = qScopeGuard([]{ + QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, true); + }); + + QWidget window; + QWidget *child = new QWidget(&window); + QPointer<QFileDialog> dialog = new QFileDialog(child); + // Make it application modal so that we don't end up with a sheet on macOS + dialog->setWindowModality(Qt::ApplicationModal); + window.show(); + QVERIFY(QTest::qWaitForWindowActive(&window)); + dialog->open(); + + // We test that the dialog opens and closes by watching the activation of the + // transient parent window. If it doesn't deactivate, then we have to skip. + const auto windowActive = [&window]{ return window.isActiveWindow(); }; + const auto windowInactive = [&window]{ return !window.isActiveWindow(); }; + if (!QTest::qWaitFor(windowInactive, 2000)) + QSKIP("Dialog didn't activate"); + + // This should destroy the dialog and close the native window + child->deleteLater(); + QTRY_VERIFY(!dialog); + // If the native window is still open, then the transient parent can't become + // active + window.activateWindow(); + QVERIFY(QTest::qWaitFor(windowActive, 2000)); +} + void tst_QFiledialog::selectedFilesWithoutWidgets() { // Test for a crash when widgets are not instantiated yet. diff --git a/tests/auto/widgets/dialogs/qfiledialog2/CMakeLists.txt b/tests/auto/widgets/dialogs/qfiledialog2/CMakeLists.txt index 5b9e95a440..7db2168a20 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qfiledialog2/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qfiledialog2.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qfiledialog2 Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qfiledialog2 LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qfiledialog2 SOURCES tst_qfiledialog2.cpp diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp index 4ef1a0e36e..c34c8559da 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -11,7 +11,6 @@ #include <qdebug.h> #include <qfiledialog.h> #include <qabstractitemdelegate.h> -#include <qitemdelegate.h> #include <qlistview.h> #include <qcombobox.h> #include <qpushbutton.h> @@ -37,6 +36,8 @@ #include "../../../../shared/filesystem.h" +#include <QtWidgets/private/qapplication_p.h> + #if defined QT_BUILD_INTERNAL QT_BEGIN_NAMESPACE Q_GUI_EXPORT bool qt_test_isFetchedRoot(); @@ -106,6 +107,10 @@ private slots: void dontShowCompleterOnRoot(); void nameFilterParsing_data(); void nameFilterParsing(); +#if QT_CONFIG(settings) + void settingsCompatibility_data(); + void settingsCompatibility(); +#endif private: void cleanupSettingsFile(); @@ -446,6 +451,44 @@ void tst_QFileDialog2::task180459_lastDirectory() delete dlg; } +#if QT_CONFIG(settings) +void tst_QFileDialog2::settingsCompatibility_data() +{ + QTest::addColumn<QString>("qtVersion"); + QTest::addColumn<QDataStream::Version>("dsVersion"); + QTest::newRow("6.2.3") << "6.2.3" << QDataStream::Qt_6_0; + QTest::newRow("6.5") << "6.5" << QDataStream::Qt_5_0; + QTest::newRow("15.5.2") << "5.15.2" << QDataStream::Qt_5_15; + QTest::newRow("15.5.9") << "5.15.9" << QDataStream::Qt_5_15; +} + +void tst_QFileDialog2::settingsCompatibility() +{ + static const QByteArray ba32 = QByteArrayLiteral("\x00\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xF7\x00\x00\x00\x04\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00""d\xFF\xFF\xFF\xFF\x00\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x01\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00>\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00""B\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00n\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\xE8\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00"); + static const QByteArray ba64 = QByteArrayLiteral("\x00\x00\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xF7\x00\x00\x00\x04\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00""d\xFF\xFF\xFF\xFF\x00\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x01\t\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00>\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00""B\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00n\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\xE8\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00"); + QFETCH(QString, qtVersion); + QFETCH(QDataStream::Version, dsVersion); + // Create a header view, convert template to target format and store it in settings + { + QSettings settings(QSettings::UserScope, "QtProject"); + settings.beginGroup("FileDialog"); + settings.setValue("sidebarWidth", 93); // random value + settings.setValue("shortcuts", QStringList({settings.fileName(), "/tmp"})); + settings.setValue("qtVersion", qtVersion); + settings.setValue("treeViewHeader", dsVersion < QDataStream::Qt_6_0 ? ba32 : ba64); + settings.endGroup(); + } + // Create a file dialog, read settings write them back + { + QFileDialog fd; + } + // Read back settings and compare byte array + QSettings settings(QSettings::UserScope, "QtProject"); + settings.beginGroup("FileDialog"); + const QByteArray savedState = settings.value("treeViewHeader").toByteArray(); + QCOMPARE(savedState, ba32); +} +#endif class FilterDirModel : public QSortFilterProxyModel @@ -638,13 +681,13 @@ void tst_QFileDialog2::completionOnLevelAfterRoot() #if defined(Q_OS_WIN) fd.setDirectory("C:/"); QDir current = fd.directory(); - QStringList entryList = current.entryList(QStringList(), QDir::Dirs); + const QStringList entryList = current.entryList(QStringList(), QDir::Dirs); // Find a suitable test dir under c:-root: // - At least 6 characters long // - Ascii, letters only // - No another dir with same start QString testDir; - foreach (const QString &entry, entryList) { + for (const QString &entry : entryList) { if (entry.size() > 5 && QString(entry.toLatin1()).compare(entry) == 0) { bool invalid = false; for (int i = 0; i < 5; i++) { @@ -654,7 +697,7 @@ void tst_QFileDialog2::completionOnLevelAfterRoot() } } if (!invalid) { - foreach (const QString &check, entryList) { + for (const QString &check : entryList) { if (check.startsWith(entry.left(5), Qt::CaseInsensitive) && check != entry) { invalid = true; break; @@ -761,8 +804,8 @@ void tst_QFileDialog2::task235069_hideOnEscape() child->setFocus(); QTest::keyClick(child, Qt::Key_Escape); QCOMPARE(fd.isVisible(), false); - QCOMPARE(spyFinished.count(), 1); // QTBUG-7690 - QCOMPARE(spyRejected.count(), 1); // reject(), don't hide() + QCOMPARE(spyFinished.size(), 1); // QTBUG-7690 + QCOMPARE(spyRejected.size(), 1); // reject(), don't hide() } #ifdef QT_BUILD_INTERNAL @@ -904,9 +947,9 @@ void tst_QFileDialog2::task239706_editableFilterCombo() d.show(); QVERIFY(QTest::qWaitForWindowExposed(&d)); - QList<QComboBox *> comboList = d.findChildren<QComboBox *>(); + const QList<QComboBox *> comboList = d.findChildren<QComboBox *>(); QComboBox *filterCombo = nullptr; - foreach (QComboBox *combo, comboList) { + for (QComboBox *combo : comboList) { if (combo->objectName() == QString("fileTypeCombo")) { filterCombo = combo; break; @@ -984,10 +1027,10 @@ public : void removeSelection() { QList<QModelIndex> idxs = selectionModel()->selectedIndexes(); QList<QPersistentModelIndex> indexes; - for (int i = 0; i < idxs.count(); i++) + for (int i = 0; i < idxs.size(); i++) indexes.append(idxs.at(i)); - for (int i = 0; i < indexes.count(); ++i) + for (int i = 0; i < indexes.size(); ++i) if (!indexes.at(i).data(Qt::UserRole + 1).toUrl().path().isEmpty()) model()->removeRow(indexes.at(i).row()); } @@ -1067,7 +1110,6 @@ void tst_QFileDialog2::task254490_selectFileMultipleTimes() QTemporaryFile *t; t = new QTemporaryFile; QVERIFY2(t->open(), qPrintable(t->errorString())); - t->open(); QFileDialog fd(0, "TestFileDialog"); fd.setDirectory(tempPath); @@ -1089,7 +1131,7 @@ void tst_QFileDialog2::task254490_selectFileMultipleTimes() QCOMPARE(lineEdit->text(),QLatin1String("new_file.txt")); QListView *list = fd.findChild<QListView*>("listView"); QVERIFY(list); - QCOMPARE(list->selectionModel()->selectedRows(0).count(), 0); + QCOMPARE(list->selectionModel()->selectedRows(0).size(), 0); t->deleteLater(); } @@ -1105,7 +1147,7 @@ void tst_QFileDialog2::task257579_sideBarWithNonCleanUrls() QFileDialog fd; fd.setSidebarUrls(QList<QUrl>() << QUrl::fromLocalFile(url)); QSidebar *sidebar = fd.findChild<QSidebar*>("sidebar"); - QCOMPARE(sidebar->urls().count(), 1); + QCOMPARE(sidebar->urls().size(), 1); QVERIFY(sidebar->urls().first().toLocalFile() != url); QCOMPARE(sidebar->urls().first().toLocalFile(), QDir::cleanPath(url)); @@ -1210,7 +1252,7 @@ void tst_QFileDialog2::QTBUG6558_showDirsOnly() //Create a file QFile tempFile(dirPath + "/plop.txt"); - tempFile.open(QIODevice::WriteOnly | QIODevice::Text); + QVERIFY(tempFile.open(QIODevice::WriteOnly | QIODevice::Text)); QTextStream out(&tempFile); out << "The magic number is: " << 49 << "\n"; tempFile.close(); @@ -1223,7 +1265,6 @@ void tst_QFileDialog2::QTBUG6558_showDirsOnly() fd.setOption(QFileDialog::ShowDirsOnly, true); fd.show(); - QApplication::setActiveWindow(&fd); QVERIFY(QTest::qWaitForWindowActive(&fd)); QCOMPARE(fd.isVisible(), true); QCOMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd)); @@ -1267,7 +1308,6 @@ void tst_QFileDialog2::QTBUG4842_selectFilterWithHideNameFilterDetails() fd.selectNameFilter(chosenFilterString); fd.show(); - QApplication::setActiveWindow(&fd); QVERIFY(QTest::qWaitForWindowActive(&fd)); QCOMPARE(fd.isVisible(), true); QCOMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd)); @@ -1283,7 +1323,6 @@ void tst_QFileDialog2::QTBUG4842_selectFilterWithHideNameFilterDetails() fd2.selectNameFilter(chosenFilterString); fd2.show(); - QApplication::setActiveWindow(&fd2); QVERIFY(QTest::qWaitForWindowActive(&fd2)); QCOMPARE(fd2.isVisible(), true); QCOMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd2)); @@ -1303,7 +1342,6 @@ void tst_QFileDialog2::dontShowCompleterOnRoot() fd.setAcceptMode(QFileDialog::AcceptSave); fd.show(); - QApplication::setActiveWindow(&fd); QVERIFY(QTest::qWaitForWindowActive(&fd)); QCOMPARE(fd.isVisible(), true); QCOMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd)); diff --git a/tests/auto/widgets/dialogs/qfontdialog/CMakeLists.txt b/tests/auto/widgets/dialogs/qfontdialog/CMakeLists.txt index 93e0dd31f0..b1bbf62cc7 100644 --- a/tests/auto/widgets/dialogs/qfontdialog/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qfontdialog/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qfontdialog.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qfontdialog Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qfontdialog LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Resources: set_source_files_properties("../../../shared/resources/test.ttf" PROPERTIES QT_RESOURCE_ALIAS "test.ttf" diff --git a/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp b/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp index 828eaa7214..01f3e7ec95 100644 --- a/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp +++ b/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -45,6 +45,7 @@ private slots: void qtbug_41513_stylesheetStyle(); #endif + void hideNativeByDestruction(); private: void runSlotWithFailsafeTimer(const char *member); @@ -76,7 +77,7 @@ void tst_QFontDialog::cleanup() void tst_QFontDialog::postKeyReturn() { QWidgetList list = QApplication::topLevelWidgets(); - for (int i=0; i<list.count(); ++i) { + for (int i=0; i<list.size(); ++i) { QFontDialog *dialog = qobject_cast<QFontDialog*>(list[i]); if (dialog) { QTest::keyClick( list[i], Qt::Key_Return, Qt::NoModifier ); @@ -215,7 +216,7 @@ void tst_QFontDialog::testNonStandardFontSize() QList<int> standardSizesList = QFontDatabase::standardSizes(); int nonStandardFontSize; if (!standardSizesList.isEmpty()) { - nonStandardFontSize = standardSizesList.at(standardSizesList.count()-1); // get the maximum standard size. + nonStandardFontSize = standardSizesList.at(standardSizesList.size()-1); // get the maximum standard size. nonStandardFontSize += 1; // the increment of 1 to mock a non-standard font size. } else { QSKIP("QFontDatabase::standardSizes() is empty."); @@ -238,5 +239,32 @@ void tst_QFontDialog::testNonStandardFontSize() qWarning("Fail using a non-standard font size."); } +void tst_QFontDialog::hideNativeByDestruction() +{ + QWidget window; + QWidget *child = new QWidget(&window); + QPointer<QFontDialog> dialog = new QFontDialog(child); + // Make it application modal so that we don't end up with a sheet on macOS + dialog->setWindowModality(Qt::ApplicationModal); + window.show(); + QVERIFY(QTest::qWaitForWindowActive(&window)); + dialog->open(); + + // We test that the dialog opens and closes by watching the activation of the + // transient parent window. If it doesn't deactivate, then we have to skip. + const auto windowActive = [&window]{ return window.isActiveWindow(); }; + const auto windowInactive = [&window]{ return !window.isActiveWindow(); }; + if (!QTest::qWaitFor(windowInactive, 2000)) + QSKIP("Dialog didn't activate"); + + // This should destroy the dialog and close the native window + child->deleteLater(); + QTRY_VERIFY(!dialog); + // If the native window is still open, then the transient parent can't become + // active + window.activateWindow(); + QVERIFY(QTest::qWaitFor(windowActive)); +} + QTEST_MAIN(tst_QFontDialog) #include "tst_qfontdialog.moc" diff --git a/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog_mac_helpers.mm b/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog_mac_helpers.mm deleted file mode 100644 index f035888f6c..0000000000 --- a/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog_mac_helpers.mm +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include <AppKit/AppKit.h> - -void click_cocoa_button() -{ - QMacAutoReleasePool pool; - NSArray *windows = [NSApp windows]; - for (NSWindow *window in windows) { - // This is NOT how one should do RTTI, but since I don't want to leak the class too much... - if ([[window delegate] respondsToSelector:@selector(qtFont)]) { - NSArray *subviews = [[window contentView] subviews]; - for (NSView *view in subviews) { - if ([view isKindOfClass:[NSButton class]] - && [[static_cast<NSButton *>(view) title] isEqualTo:@"OK"]) { - [static_cast<NSButton *>(view) performClick:view]; - [NSApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined location:NSZeroPoint - modifierFlags:0 timestamp:0. windowNumber:0 context:0 - subtype:SHRT_MAX data1:0 data2:0] atStart:NO]; - - break; - } - } - break; - } - } -} diff --git a/tests/auto/widgets/dialogs/qinputdialog/CMakeLists.txt b/tests/auto/widgets/dialogs/qinputdialog/CMakeLists.txt index 53b80d043a..528493a66b 100644 --- a/tests/auto/widgets/dialogs/qinputdialog/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qinputdialog/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qinputdialog.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qinputdialog Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qinputdialog LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qinputdialog SOURCES tst_qinputdialog.cpp diff --git a/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp b/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp index 357bb4b6ad..136c789abd 100644 --- a/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp +++ b/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST b/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST +++ /dev/null diff --git a/tests/auto/widgets/dialogs/qmessagebox/CMakeLists.txt b/tests/auto/widgets/dialogs/qmessagebox/CMakeLists.txt index 3edcb3c04a..53fd8a61c6 100644 --- a/tests/auto/widgets/dialogs/qmessagebox/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qmessagebox/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qmessagebox.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qmessagebox Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmessagebox LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qmessagebox SOURCES tst_qmessagebox.cpp @@ -16,6 +20,3 @@ qt_internal_add_test(tst_qmessagebox Qt::GuiPrivate Qt::Widgets ) - -#### Keys ignored in scope 1:.:.:qmessagebox.pro:<TRUE>: -# TEMPLATE = "app" diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp index 5dbb47ce59..26a6245164 100644 --- a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp +++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp @@ -1,11 +1,10 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QMessageBox> #include <QDebug> -#include <QPair> #include <QSet> #include <QList> #include <QPointer> @@ -23,7 +22,11 @@ class tst_QMessageBox : public QObject Q_OBJECT private slots: + void initTestCase_data(); + void init(); + void sanityTest(); + void baseClassSetVisible(); void defaultButton(); void escapeButton(); void clickedButton(); @@ -34,6 +37,9 @@ private slots: void detailsButtonText(); void expandDetailsWithoutMoving(); + void optionsEmptyByDefault(); + void changeNativeOption(); + #ifndef Q_OS_MAC void shortcut(); #endif @@ -51,6 +57,14 @@ private slots: void acceptedRejectedSignals(); void acceptedRejectedSignals_data(); + void overrideDone_data(); + void overrideDone(); + + void hideNativeByDestruction(); + + void explicitDoneAfterButtonClicked(); + void legacyApiReturnValue(); + void cleanup(); }; @@ -129,6 +143,60 @@ void ExecCloseHelper::timerEvent(QTimerEvent *te) } } +void tst_QMessageBox::initTestCase_data() +{ + QTest::addColumn<bool>("useNativeDialog"); + QTest::newRow("widget") << false; + if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { + if (theme->usePlatformNativeDialog(QPlatformTheme::MessageDialog)) + QTest::newRow("native") << true; + } +} + +void tst_QMessageBox::init() +{ + QFETCH_GLOBAL(bool, useNativeDialog); + qApp->setAttribute(Qt::AA_DontUseNativeDialogs, !useNativeDialog); +} + +class OverridingMessageBox : public QMessageBox +{ +public: + void done(int result) override { + doneResult = result; + QMessageBox::done(result); + } + std::optional<int> doneResult; +}; + +void tst_QMessageBox::overrideDone_data() +{ + QTest::addColumn<QMessageBox::StandardButton>("button"); + QTest::addColumn<int>("closeAction"); + QTest::addColumn<int>("result"); + + QTest::newRow("close") << QMessageBox::Help << int(ExecCloseHelper::CloseWindow) << 0; + QTest::newRow("yes") << QMessageBox::Yes << int(Qt::Key_Enter) << int(QMessageBox::Yes); + QTest::newRow("no") << QMessageBox::No << int(Qt::Key_Enter) << int(QMessageBox::No); +} + +void tst_QMessageBox::overrideDone() +{ + QFETCH(QMessageBox::StandardButton, button); + QFETCH(int, closeAction); + QFETCH(int, result); + + OverridingMessageBox messageBox; + messageBox.addButton(button); + messageBox.setDefaultButton(button); + ExecCloseHelper closeHelper; + closeHelper.start(closeAction, &messageBox); + messageBox.exec(); + QVERIFY(messageBox.doneResult.has_value()); + QCOMPARE(*messageBox.doneResult, result); + +} + void tst_QMessageBox::cleanup() { QTRY_VERIFY(QApplication::topLevelWidgets().isEmpty()); // OS X requires TRY @@ -155,6 +223,15 @@ void tst_QMessageBox::sanityTest() msgBox.exec(); } +void tst_QMessageBox::baseClassSetVisible() +{ + QMessageBox msgBox; + msgBox.setText("Hello World"); + msgBox.QDialog::setVisible(true); + QCOMPARE(msgBox.isVisible(), true); + msgBox.close(); +} + void tst_QMessageBox::button() { QMessageBox msgBox; @@ -363,7 +440,7 @@ void tst_QMessageBox::shortcut() msgBox.addButton("&Maybe", QMessageBox::YesRole); ExecCloseHelper closeHelper; closeHelper.start(Qt::Key_M, &msgBox); - QCOMPARE(msgBox.exec(), 2); + QCOMPARE(msgBox.exec(), 4); } #endif @@ -398,72 +475,61 @@ void tst_QMessageBox::staticSourceCompat() // source compat tests for < 4.2 QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED +#define COMPARE(real, exp) do {\ + const auto pressed = static_cast<QMessageBox::StandardButton>(real);\ + const auto expected = static_cast<QMessageBox::StandardButton>(exp);\ + if (!QTest::qCompare(pressed, expected, #real, #exp, __FILE__, __LINE__)) \ + return; } while (false) + ExecCloseHelper closeHelper; closeHelper.start(Qt::Key_Enter); ret = QMessageBox::information(nullptr, "title", "text", QMessageBox::Yes, QMessageBox::No); - int expectedButton = int(QMessageBox::Yes); - if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { - const int dialogButtonBoxLayout = theme->themeHint(QPlatformTheme::DialogButtonBoxLayout).toInt(); - if (dialogButtonBoxLayout == QDialogButtonBox::MacLayout - || dialogButtonBoxLayout == QDialogButtonBox::GnomeLayout) - expectedButton = int(QMessageBox::No); - } - QCOMPARE(ret, expectedButton); + COMPARE(ret, QMessageBox::No); QVERIFY(closeHelper.done()); closeHelper.start(Qt::Key_Enter); ret = QMessageBox::information(nullptr, "title", "text", QMessageBox::Yes | QMessageBox::Default, QMessageBox::No); - QCOMPARE(ret, int(QMessageBox::Yes)); + COMPARE(ret, int(QMessageBox::Yes)); QVERIFY(closeHelper.done()); +#if QT_DEPRECATED_SINCE(6, 2) + // The overloads below are valid only before 6.2 closeHelper.start(Qt::Key_Enter); ret = QMessageBox::information(nullptr, "title", "text", QMessageBox::Yes, QMessageBox::No | QMessageBox::Default); - QCOMPARE(ret, int(QMessageBox::No)); + COMPARE(ret, int(QMessageBox::No)); QVERIFY(closeHelper.done()); closeHelper.start(Qt::Key_Enter); ret = QMessageBox::information(nullptr, "title", "text", QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape); - QCOMPARE(ret, int(QMessageBox::Yes)); + COMPARE(ret, int(QMessageBox::Yes)); QVERIFY(closeHelper.done()); closeHelper.start(Qt::Key_Enter); ret = QMessageBox::information(nullptr, "title", "text", QMessageBox::Yes | QMessageBox::Escape, QMessageBox::No | QMessageBox::Default); - QCOMPARE(ret, int(QMessageBox::No)); + COMPARE(ret, int(QMessageBox::No)); QVERIFY(closeHelper.done()); // the button text versions closeHelper.start(Qt::Key_Enter); ret = QMessageBox::information(nullptr, "title", "text", "Yes", "No", QString(), 1); - QCOMPARE(ret, 1); + COMPARE(ret, 1); QVERIFY(closeHelper.done()); - - if (0) { // don't run these tests since the dialog won't close! - closeHelper.start(Qt::Key_Escape); - ret = QMessageBox::information(nullptr, "title", "text", "Yes", "No", QString(), 1); - QCOMPARE(ret, -1); - QVERIFY(closeHelper.done()); - - closeHelper.start(Qt::Key_Escape); - ret = QMessageBox::information(nullptr, "title", "text", "Yes", "No", QString(), 0, 1); - QCOMPARE(ret, 1); - QVERIFY(closeHelper.done()); - } +#endif // QT_DEPRECATED_SINCE(6, 2) +#undef COMPARE QT_WARNING_POP } void tst_QMessageBox::instanceSourceCompat() { -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED - QMessageBox mb("Application name here", - "Saving the file will overwrite the original file on the disk.\n" - "Do you really want to save?", - QMessageBox::Information, - QMessageBox::Yes | QMessageBox::Default, - QMessageBox::No, - QMessageBox::Cancel | QMessageBox::Escape); - mb.setButtonText(QMessageBox::Yes, "Save"); - mb.setButtonText(QMessageBox::No, "Discard"); + QMessageBox mb(QMessageBox::Information, + "Application name here", + "Saving the file will overwrite the original file on the disk.\n" + "Do you really want to save?", + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + mb.setDefaultButton(QMessageBox::Yes); + mb.setEscapeButton(QMessageBox::Cancel); + mb.button(QMessageBox::Yes)->setText("Save"); + mb.button(QMessageBox::No)->setText("Discard"); mb.addButton("&Revert", QMessageBox::RejectRole); mb.addButton("&Zoo", QMessageBox::ActionRole); @@ -475,15 +541,18 @@ QT_WARNING_DISABLE_DEPRECATED #ifndef Q_OS_MAC // mnemonics are not used on OS X closeHelper.start(QKeyCombination(Qt::ALT | Qt::Key_R).toCombined(), &mb); - QCOMPARE(mb.exec(), 0); + QCOMPARE(mb.exec(), 2); closeHelper.start(QKeyCombination(Qt::ALT | Qt::Key_Z).toCombined(), &mb); - QCOMPARE(mb.exec(), 1); + QCOMPARE(mb.exec(), 3); #endif -QT_WARNING_POP } void tst_QMessageBox::detailsText() { + QFETCH_GLOBAL(bool, useNativeDialog); + if (useNativeDialog) + QSKIP("Native dialogs do not propagate expose events"); + QMessageBox box; QString text("This is the details text."); box.setDetailedText(text); @@ -497,6 +566,10 @@ void tst_QMessageBox::detailsText() void tst_QMessageBox::detailsButtonText() { + QFETCH_GLOBAL(bool, useNativeDialog); + if (useNativeDialog) + QSKIP("Native dialogs do not propagate expose events"); + QMessageBox box; box.setDetailedText("bla"); box.open(); @@ -518,6 +591,10 @@ void tst_QMessageBox::detailsButtonText() void tst_QMessageBox::expandDetailsWithoutMoving() // QTBUG-32473 { + QFETCH_GLOBAL(bool, useNativeDialog); + if (useNativeDialog) + QSKIP("Native dialogs do not propagate expose events"); + tst_ResizingMessageBox box; box.setDetailedText("bla"); box.show(); @@ -543,6 +620,20 @@ void tst_QMessageBox::expandDetailsWithoutMoving() // QTBUG-32473 QCOMPARE(box.geometry().topLeft(), geom.topLeft()); } +void tst_QMessageBox::optionsEmptyByDefault() +{ + QMessageBox b; + QCOMPARE(b.options(), QMessageBox::Options()); + QVERIFY(!b.testOption(QMessageBox::Option::DontUseNativeDialog)); +} + +void tst_QMessageBox::changeNativeOption() +{ + QMessageBox b; + b.setOption(QMessageBox::Option::DontUseNativeDialog); + QCOMPARE(b.options(), QMessageBox::Options(QMessageBox::Option::DontUseNativeDialog)); +} + void tst_QMessageBox::incorrectDefaultButton() { ExecCloseHelper closeHelper; @@ -557,6 +648,7 @@ void tst_QMessageBox::incorrectDefaultButton() QMessageBox::question(nullptr, "", "I've been hit!",QFlag(QMessageBox::Ok | QMessageBox::Cancel),QMessageBox::Save); QVERIFY(closeHelper.done()); +#if QT_DEPRECATED_SINCE(6, 2) closeHelper.start(Qt::Key_Escape); QTest::ignoreMessage(QtWarningMsg, "QDialogButtonBox::createButton: Invalid ButtonRole, button not added"); QTest::ignoreMessage(QtWarningMsg, "QDialogButtonBox::createButton: Invalid ButtonRole, button not added"); @@ -566,6 +658,7 @@ QT_WARNING_DISABLE_DEPRECATED QMessageBox::question(nullptr, "", "I've been hit!",QMessageBox::Ok | QMessageBox::Cancel,QMessageBox::Save | QMessageBox::Cancel,QMessageBox::Ok); QT_WARNING_POP QVERIFY(closeHelper.done()); +#endif } void tst_QMessageBox::updateSize() @@ -615,6 +708,10 @@ Q_DECLARE_METATYPE(RoleSet); void tst_QMessageBox::acceptedRejectedSignals() { + QFETCH_GLOBAL(bool, useNativeDialog); + if (useNativeDialog) + QSKIP("Native dialogs do not propagate expose events"); + QMessageBox messageBox(QMessageBox::Information, "Test window", "Test text"); QFETCH(ButtonsCreator, buttonsCreator); @@ -636,7 +733,7 @@ void tst_QMessageBox::acceptedRejectedSignals() button->click(); if (roles.contains(messageBox.buttonRole(button))) - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); else QVERIFY(spy.isEmpty()); } @@ -694,5 +791,94 @@ void tst_QMessageBox::acceptedRejectedSignals_data() addCustomButtonsData(); } +void tst_QMessageBox::hideNativeByDestruction() +{ + QWidget window; + QWidget *child = new QWidget(&window); + QPointer<QMessageBox> dialog = new QMessageBox(child); + // Make it application modal so that we don't end up with a sheet on macOS + dialog->setWindowModality(Qt::ApplicationModal); + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + dialog->open(); + + // We test that the dialog opens and closes by watching the activation of the + // transient parent window. If it doesn't deactivate, then we have to skip. + const auto windowActive = [&window]{ return window.isActiveWindow(); }; + const auto windowInactive = [&window]{ return !window.isActiveWindow(); }; + if (!QTest::qWaitFor(windowInactive, 2000)) + QSKIP("Dialog didn't activate"); + + // This should destroy the dialog and close the native window + child->deleteLater(); + QTRY_VERIFY(!dialog); + // If the native window is still open, then the transient parent can't become + // active + window.activateWindow(); + QVERIFY(QTest::qWaitFor(windowActive)); +} + +void tst_QMessageBox::explicitDoneAfterButtonClicked() +{ + QMessageBox msgBox; + auto *standardButton = msgBox.addButton(QMessageBox::Ok); + auto *customButton = msgBox.addButton("Custom", QMessageBox::RejectRole); + + QSignalSpy acceptedSpy(&msgBox, &QDialog::accepted); + QSignalSpy rejectedSpy(&msgBox, &QDialog::rejected); + + msgBox.setDefaultButton(standardButton); + ExecCloseHelper closeHelper; + closeHelper.start(Qt::Key_Enter, &msgBox); + msgBox.exec(); + QCOMPARE(msgBox.clickedButton(), standardButton); + QCOMPARE(msgBox.result(), QMessageBox::Ok); + QCOMPARE(acceptedSpy.size(), 1); + QCOMPARE(rejectedSpy.size(), 0); + + msgBox.accept(); + QCOMPARE(msgBox.result(), QDialog::Accepted); + QCOMPARE(acceptedSpy.size(), 2); + QCOMPARE(rejectedSpy.size(), 0); + msgBox.reject(); + QCOMPARE(msgBox.result(), QDialog::Rejected); + QCOMPARE(acceptedSpy.size(), 2); + QCOMPARE(rejectedSpy.size(), 1); + + msgBox.setDefaultButton(customButton); + closeHelper.start(Qt::Key_Enter, &msgBox); + msgBox.exec(); + QCOMPARE(msgBox.clickedButton(), customButton); + QVERIFY(msgBox.result() != QDialog::Accepted); + QVERIFY(msgBox.result() != QDialog::Rejected); + QCOMPARE(acceptedSpy.size(), 2); + QCOMPARE(rejectedSpy.size(), 2); + + msgBox.accept(); + QCOMPARE(msgBox.result(), QDialog::Accepted); + QCOMPARE(acceptedSpy.size(), 3); + QCOMPARE(rejectedSpy.size(), 2); + msgBox.reject(); + QCOMPARE(msgBox.result(), QDialog::Rejected); + QCOMPARE(acceptedSpy.size(), 3); + QCOMPARE(rejectedSpy.size(), 3); +} + +void tst_QMessageBox::legacyApiReturnValue() +{ + ExecCloseHelper closeHelper; + for (int i = 0; i < 3; ++i) { + closeHelper.start(Qt::Key_Enter); +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED + QCOMPARE(QMessageBox::warning(nullptr, "Title", "Text", + "Button 0", "Button 1", "Button 2", i), i); + closeHelper.start(Qt::Key_Escape); + QCOMPARE(QMessageBox::warning(nullptr, "Title", "Text", + "Button 0", "Button 1", "Button 2", 0, i), i); +QT_WARNING_POP + } +} + QTEST_MAIN(tst_QMessageBox) #include "tst_qmessagebox.moc" diff --git a/tests/auto/widgets/dialogs/qprogressdialog/CMakeLists.txt b/tests/auto/widgets/dialogs/qprogressdialog/CMakeLists.txt index 429dc4c85b..4861f3af25 100644 --- a/tests/auto/widgets/dialogs/qprogressdialog/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qprogressdialog/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qprogressdialog.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qprogressdialog Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qprogressdialog LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qprogressdialog SOURCES tst_qprogressdialog.cpp diff --git a/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp b/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp index 12ab1201ee..baf727d766 100644 --- a/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp +++ b/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -84,7 +84,7 @@ void tst_QProgressDialog::autoShow() // in order to test for the setValue() behavior instead // See autoShowCtor() for the ctor timer check dlg.setValue(value); - QThread::msleep(delay); + QThread::sleep(std::chrono::milliseconds{delay}); dlg.setValue(min+1); QCOMPARE(dlg.isVisible(), expectedAutoShow); } @@ -93,7 +93,7 @@ void tst_QProgressDialog::autoShowCtor() { QProgressDialog dlg; QVERIFY(!dlg.isVisible()); - QThread::msleep(dlg.minimumDuration()); + QThread::sleep(std::chrono::milliseconds{dlg.minimumDuration()}); QTRY_VERIFY(dlg.isVisible()); } @@ -181,7 +181,7 @@ void tst_QProgressDialog::QTBUG_31046() { QProgressDialog dlg("", "", 50, 60); dlg.setValue(0); - QThread::msleep(200); + QThread::sleep(std::chrono::milliseconds{200}); dlg.setValue(50); QCOMPARE(50, dlg.value()); } diff --git a/tests/auto/widgets/dialogs/qsidebar/CMakeLists.txt b/tests/auto/widgets/dialogs/qsidebar/CMakeLists.txt index 413be3a5dc..bf9513bb69 100644 --- a/tests/auto/widgets/dialogs/qsidebar/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qsidebar/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qsidebar.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qsidebar Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsidebar LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qsidebar SOURCES tst_qsidebar.cpp diff --git a/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp b/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp index c4a2ffa2fd..cdbf2011a4 100644 --- a/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp +++ b/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -38,9 +38,9 @@ void tst_QSidebar::setUrls() QCOMPARE(model->rowCount(), 0); qsidebar.setUrls(urls); QCOMPARE(qsidebar.urls(), urls); - QCOMPARE(model->rowCount(), urls.count()); + QCOMPARE(model->rowCount(), urls.size()); qsidebar.setUrls(urls); - QCOMPARE(model->rowCount(), urls.count()); + QCOMPARE(model->rowCount(), urls.size()); } void tst_QSidebar::selectUrls() @@ -55,7 +55,7 @@ void tst_QSidebar::selectUrls() QSignalSpy spy(&qsidebar, SIGNAL(goToUrl(QUrl))); qsidebar.selectUrl(urls.at(0)); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QSidebar::addUrls() @@ -171,7 +171,7 @@ void tst_QSidebar::goToUrl() QSignalSpy spy(&qsidebar, SIGNAL(goToUrl(QUrl))); QTest::mousePress(qsidebar.viewport(), Qt::LeftButton, {}, qsidebar.visualRect(qsidebar.model()->index(0, 0)).center()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE((spy.value(0)).at(0).toUrl(), urls.first()); } diff --git a/tests/auto/widgets/dialogs/qwizard/CMakeLists.txt b/tests/auto/widgets/dialogs/qwizard/CMakeLists.txt index 1497dd8078..d863126560 100644 --- a/tests/auto/widgets/dialogs/qwizard/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qwizard/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qwizard.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qwizard Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qwizard LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Resources: set(qwizard_resource_files "images/background.png" @@ -22,6 +26,7 @@ qt_internal_add_test(tst_qwizard LIBRARIES Qt::Gui Qt::Widgets + Qt::WidgetsPrivate TESTDATA ${qwizard_resource_files} BUILTIN_TESTDATA ) diff --git a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp index 2a0ba93803..c0afed6919 100644 --- a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp +++ b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QFont> @@ -17,6 +17,10 @@ #include <QSignalSpy> #include <QOperatingSystemVersion> +#include <QtWidgets/private/qapplication_p.h> + +#include <memory> + Q_DECLARE_METATYPE(QWizard::WizardButton); static QImage grabWidget(QWidget *window) @@ -396,7 +400,7 @@ void tst_QWizard::setPixmap() QVERIFY(wizard.pixmap(QWizard::BannerPixmap).isNull()); QVERIFY(wizard.pixmap(QWizard::LogoPixmap).isNull()); QVERIFY(wizard.pixmap(QWizard::WatermarkPixmap).isNull()); - if (QOperatingSystemVersion::current() <= QOperatingSystemVersion::MacOSHighSierra) + if (QOperatingSystemVersion::currentType() == QOperatingSystemVersion::MacOS) QVERIFY(!wizard.pixmap(QWizard::BackgroundPixmap).isNull()); else QVERIFY(wizard.pixmap(QWizard::BackgroundPixmap).isNull()); @@ -404,7 +408,7 @@ void tst_QWizard::setPixmap() QVERIFY(page->pixmap(QWizard::BannerPixmap).isNull()); QVERIFY(page->pixmap(QWizard::LogoPixmap).isNull()); QVERIFY(page->pixmap(QWizard::WatermarkPixmap).isNull()); - if (QOperatingSystemVersion::current() <= QOperatingSystemVersion::MacOSHighSierra) + if (QOperatingSystemVersion::currentType() == QOperatingSystemVersion::MacOS) QVERIFY(!wizard.pixmap(QWizard::BackgroundPixmap).isNull()); else QVERIFY(page->pixmap(QWizard::BackgroundPixmap).isNull()); @@ -522,7 +526,7 @@ void tst_QWizard::addPage() QCOMPARE(wizard.addPage(pages[i]), i); QCOMPARE(pages[i]->window(), (QWidget *)&wizard); QCOMPARE(wizard.startId(), 0); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QList<QVariant> arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), i); } @@ -535,37 +539,37 @@ void tst_QWizard::addPage() QVERIFY(!wizard.page(N + 1)); wizard.setPage(N + 50, new QWizardPage); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QList<QVariant> arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), N + 50); wizard.setPage(-3000, new QWizardPage); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), -3000); QWizardPage *pageX = new QWizardPage; QCOMPARE(wizard.addPage(pageX), N + 51); QCOMPARE(wizard.page(N + 51), pageX); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), N + 51); QCOMPARE(wizard.addPage(new QWizardPage), N + 52); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), N + 52); QTest::ignoreMessage(QtWarningMsg,"QWizard::setPage: Cannot insert null page"); wizard.addPage(0); // generates a warning - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); delete parent; } #define CHECK_VISITED(wizard, list) \ do { \ - QList<int> myList = list; \ + const QList<int> myList = list; \ QCOMPARE((wizard).visitedIds(), myList); \ - Q_FOREACH(int id, myList) \ + for (int id : myList) \ QVERIFY((wizard).hasVisitedPage(id)); \ } while (0) @@ -584,7 +588,7 @@ void tst_QWizard::setPage() page = new QWizardPage(parent); QTest::ignoreMessage(QtWarningMsg,"QWizard::setPage: Cannot insert page with ID -1"); wizard.setPage(-1, page); // gives a warning and does nothing - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QVERIFY(!wizard.page(-2)); QVERIFY(!wizard.page(-1)); QVERIFY(!wizard.page(0)); @@ -596,7 +600,7 @@ void tst_QWizard::setPage() page = new QWizardPage(parent); wizard.setPage(0, page); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QList<QVariant> arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), 0); QCOMPARE(page->window(), (QWidget *)&wizard); @@ -609,7 +613,7 @@ void tst_QWizard::setPage() page = new QWizardPage(parent); wizard.setPage(-2, page); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), -2); QCOMPARE(page->window(), (QWidget *)&wizard); @@ -630,7 +634,7 @@ void tst_QWizard::setPage() page = new QWizardPage(parent); wizard.setPage(2, page); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), 2); QCOMPARE(wizard.page(2), page); @@ -649,7 +653,7 @@ void tst_QWizard::setPage() page = new QWizardPage(parent); wizard.setPage(-3, page); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), -3); QCOMPARE(wizard.page(-3), page); @@ -720,7 +724,7 @@ void tst_QWizard::setPage() QCOMPARE(wizard.nextId(), -2); CHECK_VISITED(wizard, QList<int>() << -3); } - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); delete parent; } @@ -978,7 +982,7 @@ void tst_QWizard::setOption_IgnoreSubTitles() // Check that subtitles are shown when they should (i.e., // they're set and IgnoreSubTitles is off). - qApp->setActiveWindow(0); // ensure no focus rectangle around cancel button + QApplicationPrivate::setActiveWindow(0); // ensure no focus rectangle around cancel button QImage i11 = grabWidget(&wizard1); QImage i21 = grabWidget(&wizard2); QVERIFY(i11 != i21); @@ -1579,9 +1583,9 @@ class SetPage : public Operation QString describe() const override { return QLatin1String("set page ") + QString::number(page); } int page; public: - static QSharedPointer<SetPage> create(int page) + static std::shared_ptr<SetPage> create(int page) { - QSharedPointer<SetPage> o = QSharedPointer<SetPage>::create(); + std::shared_ptr<SetPage> o = std::make_shared<SetPage>(); o->page = page; return o; } @@ -1593,9 +1597,9 @@ class SetStyle : public Operation QString describe() const override { return QLatin1String("set style ") + QString::number(style); } QWizard::WizardStyle style; public: - static QSharedPointer<SetStyle> create(QWizard::WizardStyle style) + static std::shared_ptr<SetStyle> create(QWizard::WizardStyle style) { - QSharedPointer<SetStyle> o = QSharedPointer<SetStyle>::create(); + std::shared_ptr<SetStyle> o = std::make_shared<SetStyle>(); o->style = style; return o; } @@ -1608,9 +1612,9 @@ class SetOption : public Operation QWizard::WizardOption option; bool on; public: - static QSharedPointer<SetOption> create(QWizard::WizardOption option, bool on) + static std::shared_ptr<SetOption> create(QWizard::WizardOption option, bool on) { - QSharedPointer<SetOption> o = QSharedPointer<SetOption>::create(); + std::shared_ptr<SetOption> o = std::make_shared<SetOption>(); o->option = option; o->on = on; return o; @@ -1639,8 +1643,8 @@ class OptionInfo tags[QWizard::HaveCustomButton3] = "15/CB3"; for (int i = 0; i < 2; ++i) { - QMap<QWizard::WizardOption, QSharedPointer<Operation> > operations_; - foreach (QWizard::WizardOption option, tags.keys()) + QMap<QWizard::WizardOption, std::shared_ptr<Operation> > operations_; + for (const auto &[option, _] : std::as_const(tags).asKeyValueRange()) operations_[option] = SetOption::create(option, i == 1); operations << operations_; } @@ -1648,7 +1652,7 @@ class OptionInfo OptionInfo(OptionInfo const&); OptionInfo& operator=(OptionInfo const&); QMap<QWizard::WizardOption, QString> tags; - QList<QMap<QWizard::WizardOption, QSharedPointer<Operation> > > operations; + QList<QMap<QWizard::WizardOption, std::shared_ptr<Operation> > > operations; public: static OptionInfo &instance() { @@ -1657,7 +1661,7 @@ public: } QString tag(QWizard::WizardOption option) const { return tags.value(option); } - QSharedPointer<Operation> operation(QWizard::WizardOption option, bool on) const + std::shared_ptr<Operation> operation(QWizard::WizardOption option, bool on) const { return operations.at(on).value(option); } QList<QWizard::WizardOption> options() const { return tags.keys(); } }; @@ -1668,7 +1672,7 @@ QString SetOption::describe() const + QLatin1Char(on ? '1' : '0'); } -Q_DECLARE_METATYPE(QList<QSharedPointer<Operation>>) +Q_DECLARE_METATYPE(QList<std::shared_ptr<Operation>>) class TestGroup { @@ -1685,7 +1689,7 @@ public: combinations.clear(); } - QList<QSharedPointer<Operation>> &add() + QList<std::shared_ptr<Operation>> &add() { combinations.resize(combinations.size() + 1); return combinations.last(); @@ -1693,7 +1697,7 @@ public: void createTestRows() { - for (int i = 0; i < combinations.count(); ++i) { + for (int i = 0; i < combinations.size(); ++i) { QTest::newRow((name.toLatin1() + ", row " + QByteArray::number(i)).constData()) << (i == 0) << (type == Equality) << combinations.at(i); ++nRows_; @@ -1706,7 +1710,7 @@ private: QString name; Type type; int nRows_; - QList<QList<QSharedPointer<Operation>>> combinations; + QList<QList<std::shared_ptr<Operation>>> combinations; }; class IntroPage : public QWizardPage @@ -1783,16 +1787,16 @@ public: ~TestWizard() { - foreach (int id, pageIds) { + for (int id : std::as_const(pageIds)) { QWizardPage *page_to_delete = page(id); removePage(id); delete page_to_delete; } } - void applyOperations(const QList<QSharedPointer<Operation>> &operations) + void applyOperations(const QList<std::shared_ptr<Operation>> &operations) { - foreach (const QSharedPointer<Operation> &op, operations) { + for (const std::shared_ptr<Operation> &op : operations) { if (op) { op->apply(this); opsDescr += QLatin1Char('(') + op->describe() + QLatin1String(") "); @@ -1812,25 +1816,31 @@ public: class CombinationsTestData { TestGroup testGroup; - QList<QSharedPointer<Operation>> pageOps; - QList<QSharedPointer<Operation>> styleOps; - QMap<bool, QList<QSharedPointer<Operation>>> setAllOptions; + const std::shared_ptr<Operation> pageOps[3] = { + SetPage::create(0), + SetPage::create(1), + SetPage::create(2), + }; + const std::shared_ptr<Operation> styleOps[3] = { + SetStyle::create(QWizard::ClassicStyle), + SetStyle::create(QWizard::ModernStyle), + SetStyle::create(QWizard::MacStyle), + }; + QMap<bool, QList<std::shared_ptr<Operation>>> setAllOptions; public: CombinationsTestData() { QTest::addColumn<bool>("ref"); QTest::addColumn<bool>("testEquality"); - QTest::addColumn<QList<QSharedPointer<Operation>>>("operations"); - pageOps << SetPage::create(0) << SetPage::create(1) << SetPage::create(2); - styleOps << SetStyle::create(QWizard::ClassicStyle) << SetStyle::create(QWizard::ModernStyle) - << SetStyle::create(QWizard::MacStyle); -#define SETPAGE(page) pageOps.at(page) -#define SETSTYLE(style) styleOps.at(style) + QTest::addColumn<QList<std::shared_ptr<Operation>>>("operations"); +#define SETPAGE(page) pageOps[page] +#define SETSTYLE(style) styleOps[style] #define OPT(option, on) OptionInfo::instance().operation(option, on) #define CLROPT(option) OPT(option, false) #define SETOPT(option) OPT(option, true) - foreach (QWizard::WizardOption option, OptionInfo::instance().options()) { + const auto options = OptionInfo::instance().options(); + for (QWizard::WizardOption option : options) { setAllOptions[false] << CLROPT(option); setAllOptions[true] << SETOPT(option); } @@ -1887,7 +1897,7 @@ public: testGroup.createTestRows(); for (int i = 0; i < 2; ++i) { - QList<QSharedPointer<Operation>> setOptions = setAllOptions.value(i == 1); + QList<std::shared_ptr<Operation>> setOptions = setAllOptions.value(i == 1); testGroup.reset("testAll 3.1"); testGroup.add() << setOptions; @@ -1904,21 +1914,22 @@ public: testGroup.createTestRows(); } - foreach (const QSharedPointer<Operation> &pageOp, pageOps) { + for (const std::shared_ptr<Operation> &pageOp : pageOps) { testGroup.reset("testAll 4.1"); testGroup.add() << pageOp; testGroup.add() << pageOp << pageOp; testGroup.createTestRows(); for (int i = 0; i < 2; ++i) { - QList<QSharedPointer<Operation>> optionOps = setAllOptions.value(i == 1); + QList<std::shared_ptr<Operation>> optionOps = setAllOptions.value(i == 1); testGroup.reset("testAll 4.2"); testGroup.add() << optionOps << pageOp; testGroup.add() << pageOp << optionOps; testGroup.createTestRows(); - foreach (QWizard::WizardOption option, OptionInfo::instance().options()) { - QSharedPointer<Operation> optionOp = OPT(option, i == 1); + const auto options = OptionInfo::instance().options(); + for (QWizard::WizardOption option : options) { + std::shared_ptr<Operation> optionOp = OPT(option, i == 1); testGroup.reset("testAll 4.3"); testGroup.add() << optionOp << pageOp; testGroup.add() << pageOp << optionOp; @@ -1927,21 +1938,22 @@ public: } } - foreach (const QSharedPointer<Operation> &styleOp, styleOps) { + for (const std::shared_ptr<Operation> &styleOp : styleOps) { testGroup.reset("testAll 5.1"); testGroup.add() << styleOp; testGroup.add() << styleOp << styleOp; testGroup.createTestRows(); for (int i = 0; i < 2; ++i) { - QList<QSharedPointer<Operation>> optionOps = setAllOptions.value(i == 1); + QList<std::shared_ptr<Operation>> optionOps = setAllOptions.value(i == 1); testGroup.reset("testAll 5.2"); testGroup.add() << optionOps << styleOp; testGroup.add() << styleOp << optionOps; testGroup.createTestRows(); - foreach (QWizard::WizardOption option, OptionInfo::instance().options()) { - QSharedPointer<Operation> optionOp = OPT(option, i == 1); + const auto options = OptionInfo::instance().options(); + for (QWizard::WizardOption option : options) { + std::shared_ptr<Operation> optionOp = OPT(option, i == 1); testGroup.reset("testAll 5.3"); testGroup.add() << optionOp << styleOp; testGroup.add() << styleOp << optionOp; @@ -1950,8 +1962,8 @@ public: } } - foreach (const QSharedPointer<Operation> &pageOp, pageOps) { - foreach (const QSharedPointer<Operation> &styleOp, styleOps) { + for (const std::shared_ptr<Operation> &pageOp : pageOps) { + for (const std::shared_ptr<Operation> &styleOp : styleOps) { testGroup.reset("testAll 6.1"); testGroup.add() << pageOp; @@ -1969,7 +1981,7 @@ public: testGroup.createTestRows(); for (int i = 0; i < 2; ++i) { - QList<QSharedPointer<Operation>> optionOps = setAllOptions.value(i == 1); + QList<std::shared_ptr<Operation>> optionOps = setAllOptions.value(i == 1); testGroup.reset("testAll 6.4"); testGroup.add() << optionOps << pageOp << styleOp; testGroup.add() << pageOp << optionOps << styleOp; @@ -1979,8 +1991,9 @@ public: testGroup.add() << styleOp << pageOp << optionOps; testGroup.createTestRows(); - foreach (QWizard::WizardOption option, OptionInfo::instance().options()) { - QSharedPointer<Operation> optionOp = OPT(option, i == 1); + const auto options = OptionInfo::instance().options(); + for (QWizard::WizardOption option : options) { + std::shared_ptr<Operation> optionOp = OPT(option, i == 1); testGroup.reset("testAll 6.5"); testGroup.add() << optionOp << pageOp << styleOp; testGroup.add() << pageOp << optionOp << styleOp; @@ -2042,7 +2055,7 @@ void tst_QWizard::combinations() { QFETCH(bool, ref); QFETCH(bool, testEquality); - QFETCH(QList<QSharedPointer<Operation>>, operations); + QFETCH(const QList<std::shared_ptr<Operation>>, operations); TestWizard wizard; #if !defined(QT_NO_STYLE_WINDOWSVISTA) @@ -2111,7 +2124,7 @@ public: QList<WizardPage *> shown() const { QList<WizardPage *> result; - foreach (WizardPage *page, pages) + for (WizardPage *page : pages) if (page->shown()) result << page; return result; @@ -2129,19 +2142,19 @@ void tst_QWizard::showCurrentPageOnly() wizard.show(); - QCOMPARE(pages.shown().count(), 1); + QCOMPARE(pages.shown().size(), 1); QCOMPARE(pages.shown().first(), pages.all().first()); const int steps = 2; for (int i = 0; i < steps; ++i) wizard.next(); - QCOMPARE(pages.shown().count(), 1); + QCOMPARE(pages.shown().size(), 1); QCOMPARE(pages.shown().first(), pages.all().at(steps)); wizard.restart(); - QCOMPARE(pages.shown().count(), 1); + QCOMPARE(pages.shown().size(), 1); QCOMPARE(pages.shown().first(), pages.all().first()); } @@ -2273,36 +2286,36 @@ void tst_QWizard::removePage() wizard.restart(); QCOMPARE(wizard.pageIds().size(), 4); QCOMPARE(wizard.visitedIds().size(), 1); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); // Removing a non-existent page wizard.removePage(4); QCOMPARE(wizard.pageIds().size(), 4); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); // Removing and then reinserting a page QCOMPARE(wizard.pageIds().size(), 4); QVERIFY(wizard.pageIds().contains(2)); wizard.removePage(2); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QList<QVariant> arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), 2); QCOMPARE(wizard.pageIds().size(), 3); QVERIFY(!wizard.pageIds().contains(2)); wizard.setPage(2, page2); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QCOMPARE(wizard.pageIds().size(), 4); QVERIFY(wizard.pageIds().contains(2)); // Removing the same page twice wizard.removePage(2); // restore - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), 2); QCOMPARE(wizard.pageIds().size(), 3); QVERIFY(!wizard.pageIds().contains(2)); wizard.removePage(2); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QCOMPARE(wizard.pageIds().size(), 3); QVERIFY(!wizard.pageIds().contains(2)); @@ -2312,9 +2325,9 @@ void tst_QWizard::removePage() wizard.next(); QCOMPARE(wizard.visitedIds().size(), 2); QCOMPARE(wizard.currentPage(), page1); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); wizard.removePage(2); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), 2); QCOMPARE(wizard.visitedIds().size(), 2); @@ -2325,11 +2338,11 @@ void tst_QWizard::removePage() wizard.setPage(2, page2); // restore wizard.restart(); wizard.next(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QCOMPARE(wizard.visitedIds().size(), 2); QCOMPARE(wizard.currentPage(), page1); wizard.removePage(0); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), 0); QCOMPARE(wizard.visitedIds().size(), 1); @@ -2341,11 +2354,11 @@ void tst_QWizard::removePage() wizard.setPage(0, page0); // restore wizard.restart(); wizard.next(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QCOMPARE(wizard.visitedIds().size(), 2); QCOMPARE(wizard.currentPage(), page1); wizard.removePage(1); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), 1); QCOMPARE(wizard.visitedIds().size(), 1); @@ -2355,7 +2368,7 @@ void tst_QWizard::removePage() // Remove the current page which is the first (and only) one in the history wizard.removePage(0); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), 0); QCOMPARE(wizard.visitedIds().size(), 1); @@ -2365,7 +2378,7 @@ void tst_QWizard::removePage() QCOMPARE(wizard.currentPage(), page2); // wizard.removePage(2); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), 2); QCOMPARE(wizard.visitedIds().size(), 1); @@ -2375,7 +2388,7 @@ void tst_QWizard::removePage() QCOMPARE(wizard.currentPage(), page3); // wizard.removePage(3); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), 3); QVERIFY(wizard.visitedIds().empty()); @@ -2563,7 +2576,8 @@ void tst_QWizard::task161658_alignments() wizard.show(); QVERIFY(QTest::qWaitForWindowExposed(&wizard)); - foreach (QLabel *subtitleLabel, wizard.findChildren<QLabel *>()) { + const auto subtitleLabels = wizard.findChildren<QLabel *>(); + for (QLabel *subtitleLabel : subtitleLabels) { if (subtitleLabel->text().startsWith("SUBTITLE#")) { QCOMPARE(lineEdit1.mapToGlobal(lineEdit1.contentsRect().bottomRight()).x(), subtitleLabel->mapToGlobal(subtitleLabel->contentsRect().bottomRight()).x()); diff --git a/tests/auto/widgets/dialogs/qwizard/tst_qwizard_2.cpp b/tests/auto/widgets/dialogs/qwizard/tst_qwizard_2.cpp index 042ef983c3..8eef99ff38 100644 --- a/tests/auto/widgets/dialogs/qwizard/tst_qwizard_2.cpp +++ b/tests/auto/widgets/dialogs/qwizard/tst_qwizard_2.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QComboBox> diff --git a/tests/auto/widgets/effects/CMakeLists.txt b/tests/auto/widgets/effects/CMakeLists.txt index efb93154b5..fdc82023fb 100644 --- a/tests/auto/widgets/effects/CMakeLists.txt +++ b/tests/auto/widgets/effects/CMakeLists.txt @@ -1,7 +1,5 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from effects.pro. +# SPDX-License-Identifier: BSD-3-Clause add_subdirectory(qgraphicseffect) add_subdirectory(qpixmapfilter) diff --git a/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST b/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST index e69de29bb2..69367f06fd 100644 --- a/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST +++ b/tests/auto/widgets/effects/qgraphicseffect/BLACKLIST @@ -0,0 +1,2 @@ +[draw] +wayland diff --git a/tests/auto/widgets/effects/qgraphicseffect/CMakeLists.txt b/tests/auto/widgets/effects/qgraphicseffect/CMakeLists.txt index f58d1c364e..e9d32b1a8d 100644 --- a/tests/auto/widgets/effects/qgraphicseffect/CMakeLists.txt +++ b/tests/auto/widgets/effects/qgraphicseffect/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicseffect.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicseffect Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicseffect LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicseffect SOURCES tst_qgraphicseffect.cpp diff --git a/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp index fc7205faf6..3d1988e5da 100644 --- a/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp +++ b/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtTest/QtTestWidgets> @@ -354,7 +354,9 @@ void tst_QGraphicsEffect::draw() // Effect is already enabled; nothing should happen. effect->setEnabled(true); - QTest::qWait(50); + // Send only posted events, not window system events, + // so that we don't get any spontaneous paint events. + QCoreApplication::sendPostedEvents(); QCOMPARE(effect->numRepaints, 0); QCOMPARE(item->numRepaints, 0); diff --git a/tests/auto/widgets/effects/qpixmapfilter/CMakeLists.txt b/tests/auto/widgets/effects/qpixmapfilter/CMakeLists.txt index e09646d5fc..c19e6c7cfd 100644 --- a/tests/auto/widgets/effects/qpixmapfilter/CMakeLists.txt +++ b/tests/auto/widgets/effects/qpixmapfilter/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qpixmapfilter.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qpixmapfilter Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qpixmapfilter LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qpixmapfilter SOURCES tst_qpixmapfilter.cpp diff --git a/tests/auto/widgets/effects/qpixmapfilter/tst_qpixmapfilter.cpp b/tests/auto/widgets/effects/qpixmapfilter/tst_qpixmapfilter.cpp index 804c3389df..39087aeaaf 100644 --- a/tests/auto/widgets/effects/qpixmapfilter/tst_qpixmapfilter.cpp +++ b/tests/auto/widgets/effects/qpixmapfilter/tst_qpixmapfilter.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/graphicsview/CMakeLists.txt b/tests/auto/widgets/graphicsview/CMakeLists.txt index 0a524cbcbf..b0ea73b65e 100644 --- a/tests/auto/widgets/graphicsview/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/CMakeLists.txt @@ -1,7 +1,5 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from graphicsview.pro. +# SPDX-License-Identifier: BSD-3-Clause if(QT_FEATURE_private_tests) add_subdirectory(qgraphicsanchorlayout) diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/BLACKLIST index ce0e42b3c7..fde971443d 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/BLACKLIST +++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/BLACKLIST @@ -1,2 +1,2 @@ [layoutDirection] -ubuntu-20.04 +ubuntu-22.04 diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/CMakeLists.txt index ad921ef4a4..2b530d39f3 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicsanchorlayout.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicsanchorlayout Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicsanchorlayout LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicsanchorlayout SOURCES tst_qgraphicsanchorlayout.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp index d8fa17280a..cf37aa5639 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QtWidgets/qgraphicsanchorlayout.h> diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/CMakeLists.txt index 499705213e..62235c8d1b 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicsanchorlayout1.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicsanchorlayout1 Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicsanchorlayout1 LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicsanchorlayout1 SOURCES tst_qgraphicsanchorlayout1.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp index 8b4d8b0b68..9a047b876d 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtGui> #include <QTest> @@ -1663,7 +1663,7 @@ void tst_QGraphicsAnchorLayout1::testBasicLayout() // Determine amount of widgets to add. int widgetCount = -1; - for (int i = 0; i < data.count(); ++i) { + for (int i = 0; i < data.size(); ++i) { const BasicLayoutTestData item = data[i]; widgetCount = qMax(widgetCount, item.firstIndex); widgetCount = qMax(widgetCount, item.secondIndex); @@ -1678,7 +1678,7 @@ void tst_QGraphicsAnchorLayout1::testBasicLayout() // Setup anchor layout TheAnchorLayout *layout = new TheAnchorLayout; - for (int i = 0; i < data.count(); ++i) { + for (int i = 0; i < data.size(); ++i) { const BasicLayoutTestData item = data[i]; layout->setAnchor( getItem(item.firstIndex, widgets, layout), @@ -1695,7 +1695,7 @@ void tst_QGraphicsAnchorLayout1::testBasicLayout() QCOMPARE(widget->size(), size); // Validate - for (int i = 0; i < result.count(); ++i) { + for (int i = 0; i < result.size(); ++i) { const BasicLayoutTestResult item = result[i]; QRectF expected = item.rect; QRectF actual = widgets[item.index]->geometry(); @@ -1707,7 +1707,7 @@ void tst_QGraphicsAnchorLayout1::testBasicLayout() widget->setLayoutDirection(Qt::RightToLeft); layout->activate(); // Validate - for (int j = 0; j < result.count(); ++j) { + for (int j = 0; j < result.size(); ++j) { const BasicLayoutTestResult item = result[j]; QRectF mirroredRect(item.rect); // only valid cases are mirrored @@ -2168,7 +2168,7 @@ void tst_QGraphicsAnchorLayout1::testRemoveCenterAnchor() // Determine amount of widgets to add. int widgetCount = -1; - for (int i = 0; i < data.count(); ++i) { + for (int i = 0; i < data.size(); ++i) { const BasicLayoutTestData item = data[i]; widgetCount = qMax(widgetCount, item.firstIndex); widgetCount = qMax(widgetCount, item.secondIndex); @@ -2185,7 +2185,7 @@ void tst_QGraphicsAnchorLayout1::testRemoveCenterAnchor() // Setup anchor layout TheAnchorLayout *layout = new TheAnchorLayout; - for (int i = 0; i < data.count(); ++i) { + for (int i = 0; i < data.size(); ++i) { const BasicLayoutTestData item = data[i]; layout->setAnchor( getItem(item.firstIndex, widgets, layout), @@ -2195,7 +2195,7 @@ void tst_QGraphicsAnchorLayout1::testRemoveCenterAnchor() item.spacing ); } - for (int i = 0; i < removeData.count(); ++i) { + for (int i = 0; i < removeData.size(); ++i) { const BasicLayoutTestData item = removeData[i]; layout->removeAnchor( getItem(item.firstIndex, widgets, layout), @@ -2211,7 +2211,7 @@ void tst_QGraphicsAnchorLayout1::testRemoveCenterAnchor() QCOMPARE(widget->size(), size); // Validate - for (int i = 0; i < result.count(); ++i) { + for (int i = 0; i < result.size(); ++i) { const BasicLayoutTestResult item = result[i]; QCOMPARE(widgets[item.index]->geometry(), item.rect); @@ -2999,7 +2999,7 @@ void tst_QGraphicsAnchorLayout1::testComplexCases() // Determine amount of widgets to add. int widgetCount = -1; - for (int i = 0; i < data.count(); ++i) { + for (int i = 0; i < data.size(); ++i) { const BasicLayoutTestData item = data[i]; widgetCount = qMax(widgetCount, item.firstIndex); widgetCount = qMax(widgetCount, item.secondIndex); @@ -3025,7 +3025,7 @@ void tst_QGraphicsAnchorLayout1::testComplexCases() // Setup anchor layout TheAnchorLayout *layout = new TheAnchorLayout; - for (int i = 0; i < data.count(); ++i) { + for (int i = 0; i < data.size(); ++i) { const BasicLayoutTestData item = data[i]; layout->setAnchor( getItem(item.firstIndex, widgets, layout), @@ -3042,7 +3042,7 @@ void tst_QGraphicsAnchorLayout1::testComplexCases() QCOMPARE(widget->size(), size); // Validate - for (int i = 0; i < result.count(); ++i) { + for (int i = 0; i < result.size(); ++i) { const BasicLayoutTestResult item = result[i]; QCOMPARE(widgets[item.index]->geometry(), item.rect); } @@ -3051,7 +3051,7 @@ void tst_QGraphicsAnchorLayout1::testComplexCases() widget->setLayoutDirection(Qt::RightToLeft); layout->activate(); // Validate - for (int j = 0; j < result.count(); ++j) { + for (int j = 0; j < result.size(); ++j) { const BasicLayoutTestResult item = result[j]; QRectF mirroredRect(item.rect); // only valid cases are mirrored diff --git a/tests/auto/widgets/graphicsview/qgraphicseffectsource/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicseffectsource/CMakeLists.txt index c48f507eb5..1e198d7baa 100644 --- a/tests/auto/widgets/graphicsview/qgraphicseffectsource/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicseffectsource/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicseffectsource.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicseffectsource Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicseffectsource LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicseffectsource SOURCES tst_qgraphicseffectsource.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp b/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp index 10c550efc0..28c439dbcd 100644 --- a/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QtWidgets/qgraphicseffect.h> @@ -154,11 +154,11 @@ void tst_QGraphicsEffectSource::init() QVERIFY(effect); QVERIFY(item); QVERIFY(effect->source()); - effect->reset(); effect->storeDeviceDependentStuff = false; effect->doNothingInDraw = false; - item->reset(); QCoreApplication::processEvents(); // Process all queued paint events + effect->reset(); + item->reset(); } void tst_QGraphicsEffectSource::graphicsItem() diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/CMakeLists.txt index 423a2a8209..c4ffe216f5 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicsgridlayout.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicsgridlayout Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicsgridlayout LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicsgridlayout SOURCES tst_qgraphicsgridlayout.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp index f4b3a5ef99..fad75ec045 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -1658,7 +1658,7 @@ void tst_QGraphicsGridLayout::sizeHint() widget->setContentsMargins(0, 0, 0, 0); int i; - for (i = 0; i < itemDescriptions.count(); ++i) { + for (i = 0; i < itemDescriptions.size(); ++i) { ItemDesc desc = itemDescriptions.at(i); RectWidget *item = new RectWidget(widget); desc.apply(layout, item); @@ -2159,7 +2159,7 @@ void tst_QGraphicsGridLayout::defaultStretchFactors() widget->setContentsMargins(0, 0, 0, 0); int i; - for (i = 0; i < itemDescriptions.count(); ++i) { + for (i = 0; i < itemDescriptions.size(); ++i) { ItemDesc desc = itemDescriptions.at(i); RectWidget *item = new RectWidget(widget); desc.apply(layout, item); @@ -2174,7 +2174,7 @@ void tst_QGraphicsGridLayout::defaultStretchFactors() widget->resize(newSize); QApplication::sendPostedEvents(0, 0); - for (i = 0; i < expectedSizes.count(); ++i) { + for (i = 0; i < expectedSizes.size(); ++i) { QSizeF itemSize = layout->itemAt(i)->geometry().size(); QCOMPARE(itemSize, expectedSizes.at(i)); } @@ -2318,7 +2318,7 @@ void tst_QGraphicsGridLayout::alignment2() widget->setContentsMargins(0, 0, 0, 0); int i; - for (i = 0; i < itemDescriptions.count(); ++i) { + for (i = 0; i < itemDescriptions.size(); ++i) { ItemDesc desc = itemDescriptions.at(i); RectWidget *item = new RectWidget(widget); desc.apply(layout, item); @@ -2333,7 +2333,7 @@ void tst_QGraphicsGridLayout::alignment2() widget->resize(newSize); QApplication::sendPostedEvents(0, 0); - for (i = 0; i < expectedGeometries.count(); ++i) { + for (i = 0; i < expectedGeometries.size(); ++i) { QRectF itemRect = layout->itemAt(i)->geometry(); QCOMPARE(itemRect, expectedGeometries.at(i)); } @@ -2896,7 +2896,7 @@ void tst_QGraphicsGridLayout::geometries() widget->setContentsMargins(0, 0, 0, 0); int i; - for (i = 0; i < itemDescriptions.count(); ++i) { + for (i = 0; i < itemDescriptions.size(); ++i) { ItemDesc desc = itemDescriptions.at(i); RectWidget *item = new RectWidget(widget); desc.apply(layout, item); @@ -2911,7 +2911,7 @@ void tst_QGraphicsGridLayout::geometries() widget->resize(newSize); QApplication::processEvents(); - for (i = 0; i < expectedGeometries.count(); ++i) { + for (i = 0; i < expectedGeometries.size(); ++i) { QRectF itemRect = layout->itemAt(i)->geometry(); QCOMPARE(itemRect, expectedGeometries.at(i)); } @@ -2976,11 +2976,6 @@ static QSizeF wfh(Qt::SizeHint /*which*/, const QSizeF &constraint) return result; } -bool qFuzzyCompare(const QSizeF &a, const QSizeF &b) -{ - return qFuzzyCompare(a.width(), b.width()) && qFuzzyCompare(a.height(), b.height()); -} - void tst_QGraphicsGridLayout::heightForWidth() { QGraphicsWidget *widget = new QGraphicsWidget; diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST index e942520ed7..c3de568a24 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/BLACKLIST @@ -1,3 +1,6 @@ # QTBUG-74760 [sorting] osx +# QTBUG-115293 +[itemUsesExtendedStyleOption] +wayland diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicsitem/CMakeLists.txt index f9c59d2d8f..3ee507cd46 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicsitem.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicsitem Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicsitem LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicsitem SOURCES tst_qgraphicsitem.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp index 5c07f8d046..35356adcfc 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -40,6 +40,8 @@ #include <QtGui/private/qeventpoint_p.h> +#include <QtWidgets/private/qapplication_p.h> + using AbstractGraphicsShapeItemPtr = QSharedPointer<QAbstractGraphicsShapeItem>; using GraphicsItems = QList<QGraphicsItem *>; using GraphicsItemsList = QList<QGraphicsItem *>; @@ -991,7 +993,6 @@ void tst_QGraphicsItem::inputMethodHints() scene.addItem(item); scene.addItem(item2); QGraphicsView view(&scene); - QApplication::setActiveWindow(&view); view.setWindowTitle(QLatin1String(QTest::currentTestFunction())); view.show(); QVERIFY(QTest::qWaitForWindowExposed(&view)); @@ -1048,7 +1049,6 @@ void tst_QGraphicsItem::toolTip() view.setWindowTitle(QLatin1String(QTest::currentTestFunction())); view.setFixedSize(200, 200); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); QVERIFY(QTest::qWaitForWindowActive(&view)); { @@ -2206,7 +2206,7 @@ void tst_QGraphicsItem::setTransform() scene.update(scene.sceneRect()); QCoreApplication::processEvents(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); item.setTransform(QTransform().rotate(qreal(12.34))); QRectF rotatedRect = scene.sceneRect(); @@ -2214,14 +2214,14 @@ void tst_QGraphicsItem::setTransform() scene.update(scene.sceneRect()); QCoreApplication::processEvents(); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); item.setTransform(QTransform()); scene.update(scene.sceneRect()); QCoreApplication::processEvents(); - QCOMPARE(spy.count(), 3); + QCOMPARE(spy.size(), 3); QList<QRectF> rlist = qvariant_cast<QList<QRectF> >(spy.last().at(0)); QCOMPARE(rlist.size(), 2); @@ -3374,7 +3374,7 @@ void tst_QGraphicsItem::childrenBoundingRect() childChild->setPos(500, 500); child->setTransform(QTransform().rotate(90), true); - scene.addPolygon(parent->mapToScene(parent->boundingRect() | parent->childrenBoundingRect()))->setPen(QPen(Qt::red));; + scene.addPolygon(parent->mapToScene(parent->boundingRect() | parent->childrenBoundingRect()))->setPen(QPen(Qt::red)); QGraphicsView view(&scene); view.setWindowTitle(QLatin1String(QTest::currentTestFunction())); @@ -3601,7 +3601,7 @@ void tst_QGraphicsItem::group() view.fitInView(scene.itemsBoundingRect()); - for (QGraphicsItem *item : qAsConst(newItems)) { + for (QGraphicsItem *item : std::as_const(newItems)) { group->addToGroup(item); QCOMPARE(item->group(), group); } @@ -4944,7 +4944,6 @@ void tst_QGraphicsItem::sceneEventFilter() QGraphicsView view(&scene); view.setWindowTitle(QLatin1String(QTest::currentTestFunction())); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); QVERIFY(QTest::qWaitForWindowActive(&view)); @@ -5565,7 +5564,6 @@ void tst_QGraphicsItem::itemClipsChildrenToShape4() scene.addEllipse( 100, 100, 100, 50 ); // <-- this is important to trigger the right codepath* //now the label is shown outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false ); - QApplication::setActiveWindow(&view); view.setWindowTitle(QLatin1String(QTest::currentTestFunction())); view.show(); QTRY_COMPARE(QApplication::activeWindow(), &view); @@ -5681,7 +5679,7 @@ void tst_QGraphicsItem::itemClipsChildrenToShape5() } const QList<QGraphicsItem *> children = parent->childItems(); - const int childrenCount = children.count(); + const int childrenCount = children.size(); for (int i = 0; i < 5; ++i) { QString clipString; @@ -8226,7 +8224,7 @@ void tst_QGraphicsItem::sorting() QVERIFY(QTest::qWaitForWindowActive(&view)); } QVERIFY(QTest::qWaitForWindowExposed(&view)); - QTRY_VERIFY(_paintedItems.count() > 0); + QTRY_VERIFY(_paintedItems.size() > 0); _paintedItems.clear(); @@ -10929,7 +10927,6 @@ void tst_QGraphicsItem::focusHandling() view.show(); QVERIFY(QTest::qWaitForWindowExposed(&view)); - QApplication::setActiveWindow(&view); QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); QVERIFY(itemWithFocus->hasFocus()); @@ -11445,7 +11442,7 @@ void tst_QGraphicsItem::QTBUG_7714_fullUpdateDiscardingOpacityUpdate2() view.show(); if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) { - qApp->setActiveWindow(&view); + QApplicationPrivate::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); } QVERIFY(QTest::qWaitForWindowExposed(&view)); @@ -11702,7 +11699,7 @@ public: QLatin1String wiseWords("AZ BUKI VEDI"); QString sentence(wiseWords); QStringList words = sentence.split(QLatin1Char(' '), Qt::SkipEmptyParts); - for (int i = 0; i < words.count(); ++i) { + for (int i = 0; i < words.size(); ++i) { QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(this); QLabel *label = new QLabel(words.at(i)); proxy->setWidget(label); diff --git a/tests/auto/widgets/graphicsview/qgraphicsitemanimation/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/CMakeLists.txt index 89422caf92..04bfb3f54a 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitemanimation/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicsitemanimation.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicsitemanimation Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicsitemanimation LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicsitemanimation SOURCES tst_qgraphicsitemanimation.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp index 5f86ee4149..9cf74c23fe 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/graphicsview/qgraphicslayout/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicslayout/CMakeLists.txt index 8ac2a15abd..4951558423 100644 --- a/tests/auto/widgets/graphicsview/qgraphicslayout/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicslayout/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicslayout.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicslayout Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicslayout LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicslayout SOURCES tst_qgraphicslayout.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp b/tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp index b5ba1d8787..268195d7d3 100644 --- a/tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -670,7 +670,7 @@ public: private slots: void valueChanged(qreal value) { - for (int i = 0; i < fromGeoms.count(); ++i) { + for (int i = 0; i < fromGeoms.size(); ++i) { QGraphicsLayoutItem *li = itemAt(i); QRectF from = fromGeoms.at(i); QRectF to = toGeoms.at(i); @@ -825,7 +825,7 @@ CustomLayout(QGraphicsLayoutItem *parent) int count() const override { - return items.count(); + return items.size(); } QGraphicsLayoutItem* itemAt(int index) const override @@ -841,12 +841,12 @@ void removeAt(int index) override void addItem(QGraphicsLayoutItem *item) { - insertItem(items.count(), item); + insertItem(items.size(), item); } void insertItem(int index, QGraphicsLayoutItem *item) { - index = qBound(0, index, items.count()); + index = qBound(0, index, items.size()); item->setParentLayoutItem(this); @@ -854,7 +854,7 @@ void insertItem(int index, QGraphicsLayoutItem *item) updateParentWidget(widget); - if (index == items.count()) { + if (index == items.size()) { items.append(item); } else { items.insert(index, item); @@ -922,7 +922,7 @@ void tst_QGraphicsLayout::ownership() destructedSet.clear(); window->setLayout(0); - QCOMPARE(destructedSet.count(), 0); + QCOMPARE(destructedSet.size(), 0); delete window; } diff --git a/tests/auto/widgets/graphicsview/qgraphicslayoutitem/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/CMakeLists.txt index e1a7e7b36e..7bd25cecf2 100644 --- a/tests/auto/widgets/graphicsview/qgraphicslayoutitem/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicslayoutitem.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicslayoutitem Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicslayoutitem LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicslayoutitem SOURCES tst_qgraphicslayoutitem.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp index 2389d7668b..87b703a286 100644 --- a/tests/auto/widgets/graphicsview/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/CMakeLists.txt index 9bfad231b2..b63bbb6f33 100644 --- a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicslinearlayout.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicslinearlayout Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicslinearlayout LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicslinearlayout SOURCES tst_qgraphicslinearlayout.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp index ff625dbc00..65212e94cc 100644 --- a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -723,7 +723,7 @@ void tst_QGraphicsLinearLayout::orientation() // important to resize to preferredsize when orientation is switched widget->resize(widget->effectiveSizeHint(Qt::PreferredSize)); qApp->processEvents(); - for (i = 0; i < positions.count(); ++i) { + for (i = 0; i < positions.size(); ++i) { QGraphicsWidget *item = static_cast<QGraphicsWidget*>(layout.itemAt(i)); if (initialOrientation == Qt::Horizontal) QCOMPARE(item->pos().y(), positions.at(i)); @@ -1121,7 +1121,7 @@ void tst_QGraphicsLinearLayout::setStretchFactor() int i; - for (i = 0; i < stretches.count(); ++i) { + for (i = 0; i < stretches.size(); ++i) { QGraphicsWidget *item = new RectWidget(widget); item->setMinimumSize(5,5); item->setPreferredSize(10,5); @@ -1139,7 +1139,7 @@ void tst_QGraphicsLinearLayout::setStretchFactor() qreal firstStretch = -1; qreal firstExtent = -1.; qreal sumExtent = 0; - for (i = 0; i < stretches.count(); ++i) { + for (i = 0; i < stretches.size(); ++i) { QGraphicsWidget *item = static_cast<QGraphicsWidget*>(layout.itemAt(i)); qreal extent = item->size().width(); qreal stretch = (qreal)stretches.at(i); @@ -1297,7 +1297,7 @@ void tst_QGraphicsLinearLayout::defaultStretchFactors() QSizeF itemSize = layout->itemAt(i)->geometry().size(); if (orientation == Qt::Vertical) itemSize.transpose(); - if (i < expectedSizes.count()) + if (i < expectedSizes.size()) QCOMPARE(itemSize.width(), qreal(expectedSizes.at(i))); } diff --git a/tests/auto/widgets/graphicsview/qgraphicsobject/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicsobject/CMakeLists.txt index 35ad56d21b..0c21d9febc 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsobject/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicsobject/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicsobject.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicsobject Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicsobject LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicsobject SOURCES tst_qgraphicsobject.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicsobject/tst_qgraphicsobject.cpp b/tests/auto/widgets/graphicsview/qgraphicsobject/tst_qgraphicsobject.cpp index 849ac19d25..674a7f73d5 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsobject/tst_qgraphicsobject.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsobject/tst_qgraphicsobject.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -41,28 +41,28 @@ void tst_QGraphicsObject::pos() QSignalSpy ySpy(&object, SIGNAL(yChanged())); QVERIFY(object.pos() == QPointF(0, 0)); object.setPos(10, 10); - QCOMPARE(xSpy.count(), 1); - QCOMPARE(ySpy.count(), 1); + QCOMPARE(xSpy.size(), 1); + QCOMPARE(ySpy.size(), 1); QCOMPARE(object.pos(), QPointF(10,10)); object.setPos(10, 10); - QCOMPARE(xSpy.count(), 1); - QCOMPARE(ySpy.count(), 1); + QCOMPARE(xSpy.size(), 1); + QCOMPARE(ySpy.size(), 1); object.setProperty("pos", QPointF(0, 0)); - QCOMPARE(xSpy.count(), 2); - QCOMPARE(ySpy.count(), 2); + QCOMPARE(xSpy.size(), 2); + QCOMPARE(ySpy.size(), 2); QCOMPARE(object.property("pos").toPointF(), QPointF(0,0)); object.setProperty("pos", QPointF(10, 0)); - QCOMPARE(xSpy.count(), 3); - QCOMPARE(ySpy.count(), 2); + QCOMPARE(xSpy.size(), 3); + QCOMPARE(ySpy.size(), 2); QCOMPARE(object.property("pos").toPointF(), QPointF(10,0)); object.setProperty("pos", QPointF(10, 10)); - QCOMPARE(xSpy.count(), 3); - QCOMPARE(ySpy.count(), 3); + QCOMPARE(xSpy.size(), 3); + QCOMPARE(ySpy.size(), 3); QVERIFY(object.property("pos") == QPointF(10, 10)); } @@ -73,19 +73,19 @@ void tst_QGraphicsObject::x() QSignalSpy ySpy(&object, SIGNAL(yChanged())); QVERIFY(object.pos() == QPointF(0, 0)); object.setX(10); - QCOMPARE(xSpy.count(), 1); - QCOMPARE(ySpy.count(), 0); + QCOMPARE(xSpy.size(), 1); + QCOMPARE(ySpy.size(), 0); QVERIFY(object.pos() == QPointF(10, 0)); QCOMPARE(object.x(), qreal(10)); object.setX(10); - QCOMPARE(xSpy.count(), 1); - QCOMPARE(ySpy.count(), 0); + QCOMPARE(xSpy.size(), 1); + QCOMPARE(ySpy.size(), 0); object.setProperty("x", 0); - QCOMPARE(xSpy.count(), 2); - QCOMPARE(ySpy.count(), 0); + QCOMPARE(xSpy.size(), 2); + QCOMPARE(ySpy.size(), 0); QCOMPARE(object.property("x").toDouble(), double(0)); } @@ -96,19 +96,19 @@ void tst_QGraphicsObject::y() QSignalSpy ySpy(&object, SIGNAL(yChanged())); QVERIFY(object.pos() == QPointF(0, 0)); object.setY(10); - QCOMPARE(xSpy.count(), 0); - QCOMPARE(ySpy.count(), 1); + QCOMPARE(xSpy.size(), 0); + QCOMPARE(ySpy.size(), 1); QVERIFY(object.pos() == QPointF(0, 10)); QCOMPARE(object.y(), qreal(10)); object.setY(10); - QCOMPARE(xSpy.count(), 0); - QCOMPARE(ySpy.count(), 1); + QCOMPARE(xSpy.size(), 0); + QCOMPARE(ySpy.size(), 1); object.setProperty("y", 0); - QCOMPARE(xSpy.count(), 0); - QCOMPARE(ySpy.count(), 2); + QCOMPARE(xSpy.size(), 0); + QCOMPARE(ySpy.size(), 2); QCOMPARE(object.property("y").toDouble(), qreal(0)); } @@ -118,15 +118,15 @@ void tst_QGraphicsObject::z() QSignalSpy zSpy(&object, SIGNAL(zChanged())); QCOMPARE(object.zValue(), qreal(0)); object.setZValue(10); - QCOMPARE(zSpy.count(), 1); + QCOMPARE(zSpy.size(), 1); QCOMPARE(object.zValue(), qreal(10)); object.setZValue(10); - QCOMPARE(zSpy.count(), 1); + QCOMPARE(zSpy.size(), 1); object.setProperty("z", 0); - QCOMPARE(zSpy.count(), 2); + QCOMPARE(zSpy.size(), 2); QCOMPARE(object.property("z").toDouble(), double(0)); } @@ -136,15 +136,15 @@ void tst_QGraphicsObject::opacity() QSignalSpy spy(&object, SIGNAL(opacityChanged())); QCOMPARE(object.opacity(), 1.); object.setOpacity(0); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(object.opacity(), 0.); object.setOpacity(0); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); object.setProperty("opacity", .5); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); QCOMPARE(object.property("opacity").toDouble(), .5); } @@ -154,15 +154,15 @@ void tst_QGraphicsObject::enabled() QSignalSpy spy(&object, SIGNAL(enabledChanged())); QVERIFY(object.isEnabled()); object.setEnabled(false); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QVERIFY(!object.isEnabled()); object.setEnabled(false); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); object.setProperty("enabled", true); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); QVERIFY(object.property("enabled").toBool()); } @@ -172,15 +172,15 @@ void tst_QGraphicsObject::visible() QSignalSpy spy(&object, SIGNAL(visibleChanged())); QVERIFY(object.isVisible()); object.setVisible(false); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QVERIFY(!object.isVisible()); object.setVisible(false); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); object.setProperty("visible", true); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); QVERIFY(object.property("visible").toBool()); } diff --git a/tests/auto/widgets/graphicsview/qgraphicspixmapitem/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/CMakeLists.txt index 40cc03504e..b60958f4f1 100644 --- a/tests/auto/widgets/graphicsview/qgraphicspixmapitem/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicspixmapitem.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicspixmapitem Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicspixmapitem LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicspixmapitem SOURCES tst_qgraphicspixmapitem.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp index 44d38f0172..fd8f8bd37d 100644 --- a/tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/graphicsview/qgraphicspolygonitem/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/CMakeLists.txt index bdb00e149c..116378decb 100644 --- a/tests/auto/widgets/graphicsview/qgraphicspolygonitem/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicspolygonitem.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicspolygonitem Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicspolygonitem LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicspolygonitem SOURCES tst_qgraphicspolygonitem.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp index 5360249186..9412fab0ee 100644 --- a/tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/CMakeLists.txt index abcde4407d..f28ff74cfa 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicsproxywidget.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicsproxywidget Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicsproxywidget LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicsproxywidget SOURCES tst_qgraphicsproxywidget.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index a73a736e5b..ee1a8c530a 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -9,6 +9,8 @@ #include <private/qgraphicsproxywidget_p.h> #include <private/qlayoutengine_p.h> // qSmartMin functions... +#include <QtWidgets/private/qapplication_p.h> + Q_LOGGING_CATEGORY(lcTests, "qt.widgets.tests") /* @@ -333,7 +335,7 @@ void tst_QGraphicsProxyWidget::setWidget() widget->setStyle(style.data()); widget->setFont(QFont("Times")); widget->setVisible(true); - QApplication::setActiveWindow(widget); + QApplicationPrivate::setActiveWindow(widget); widget->activateWindow(); widget->setEnabled(true); widget->resize(325, 241); @@ -707,7 +709,6 @@ void tst_QGraphicsProxyWidget::focusNextPrevChild() QGraphicsScene scene; QGraphicsView view(&scene); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); if (hasScene) { scene.addItem(proxyGuard.release()); @@ -749,7 +750,6 @@ void tst_QGraphicsProxyWidget::focusOutEvent() SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget; scene.addItem(proxy); view.show(); - QApplication::setActiveWindow(&view); view.activateWindow(); view.setFocus(); QVERIFY(QTest::qWaitForWindowActive(&view)); @@ -782,6 +782,9 @@ void tst_QGraphicsProxyWidget::focusOutEvent() void tst_QGraphicsProxyWidget::focusProxy_QTBUG_51856() { +#ifdef ANDROID + QSKIP("This test leads to failures on subsequent test cases, QTBUG-119574"); +#endif // QSpinBox has an internal QLineEdit; this QLineEdit has the spinbox // as its focus proxy. struct FocusedSpinBox : QSpinBox @@ -804,6 +807,9 @@ void tst_QGraphicsProxyWidget::focusProxy_QTBUG_51856() } }; + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QGraphicsScene scene; QGraphicsView view(&scene); SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget; @@ -925,7 +931,6 @@ void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent() QGraphicsScene scene; QGraphicsView view(&scene); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget; @@ -940,7 +945,7 @@ void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent() proxy->setPos(50, 0); QSignalSpy sceneChangedSpy(&scene, &QGraphicsScene::changed); scene.addItem(proxy); - QTRY_VERIFY(sceneChangedSpy.count() > 0); + QTRY_VERIFY(sceneChangedSpy.size() > 0); // outside graphics item QTest::mouseMove(&view, QPoint(10, 10)); @@ -979,7 +984,6 @@ void tst_QGraphicsProxyWidget::keyPressEvent() QGraphicsView view(&scene); view.show(); view.viewport()->setFocus(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(QApplication::activeWindow(), (QWidget*)&view); @@ -1018,7 +1022,6 @@ void tst_QGraphicsProxyWidget::keyReleaseEvent() QGraphicsScene scene; QGraphicsView view(&scene); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(QApplication::activeWindow(), (QWidget*)&view); @@ -1038,9 +1041,9 @@ void tst_QGraphicsProxyWidget::keyReleaseEvent() proxy->setFocus(); QTest::keyPress(view.viewport(), Qt::Key_Space); - QTRY_COMPARE(spy.count(), 0); + QTRY_COMPARE(spy.size(), 0); QTest::keyRelease(view.viewport(), Qt::Key_Space); - QTRY_COMPARE(spy.count(), hasWidget ? 1 : 0); + QTRY_COMPARE(spy.size(), hasWidget ? 1 : 0); } // protected void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) @@ -1064,11 +1067,10 @@ void tst_QGraphicsProxyWidget::mouseDoubleClickEvent() view.resize(100, 100); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(QApplication::activeWindow(), (QWidget*)&view); // wait for scene to be updated before doing any coordinate mappings on it - QTRY_VERIFY(sceneChangedSpy.count() > 0); + QTRY_VERIFY(sceneChangedSpy.size() > 0); QPoint pointInLineEdit = view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())); QTest::mousePress(view.viewport(), Qt::LeftButton, {}, pointInLineEdit); @@ -1109,13 +1111,13 @@ void tst_QGraphicsProxyWidget::mousePressReleaseEvent() proxy->setFocus(); // wait for scene to be updated before doing any coordinate mappings on it - QTRY_VERIFY(sceneChangedSpy.count() > 0); + QTRY_VERIFY(sceneChangedSpy.size() > 0); QPoint buttonCenter = view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())); QTest::mousePress(view.viewport(), Qt::LeftButton, {}, buttonCenter); - QTRY_COMPARE(spy.count(), 0); + QTRY_COMPARE(spy.size(), 0); QTest::mouseRelease(view.viewport(), Qt::LeftButton, {}, buttonCenter); - QTRY_COMPARE(spy.count(), hasWidget ? 1 : 0); + QTRY_COMPARE(spy.size(), hasWidget ? 1 : 0); } void tst_QGraphicsProxyWidget::resizeEvent_data() @@ -1150,7 +1152,6 @@ void tst_QGraphicsProxyWidget::paintEvent() QGraphicsScene scene; QGraphicsView view(&scene); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QVERIFY(view.isActiveWindow()); @@ -1166,7 +1167,7 @@ void tst_QGraphicsProxyWidget::paintEvent() QSignalSpy sceneChangedSpy(&scene, &QGraphicsScene::changed); scene.addItem(&proxy); - QTRY_VERIFY(sceneChangedSpy.count() > 0); // make sure the scene is ready + QTRY_VERIFY(sceneChangedSpy.size() > 0); // make sure the scene is ready proxy.paintCount = 0; w->update(); @@ -1321,6 +1322,9 @@ static QList<QRect> rects(const QRegion ®ion) void tst_QGraphicsProxyWidget::scrollUpdate() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + ScrollWidget *widget = new ScrollWidget; QGraphicsScene scene; @@ -1534,7 +1538,6 @@ void tst_QGraphicsProxyWidget::tabFocus_simpleWidget() window.setLayout(layout); window.show(); - QApplication::setActiveWindow(&window); window.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&window)); @@ -1618,7 +1621,6 @@ void tst_QGraphicsProxyWidget::tabFocus_simpleTwoWidgets() window.setLayout(layout); window.show(); - QApplication::setActiveWindow(&window); window.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&window)); @@ -1751,7 +1753,6 @@ void tst_QGraphicsProxyWidget::tabFocus_complexWidget() window.setLayout(layout); window.show(); - QApplication::setActiveWindow(&window); window.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&window)); @@ -1888,7 +1889,6 @@ void tst_QGraphicsProxyWidget::tabFocus_complexTwoWidgets() window.setLayout(layout); window.show(); - QApplication::setActiveWindow(&window); window.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&window)); @@ -2062,7 +2062,6 @@ void tst_QGraphicsProxyWidget::setFocus_simpleWidget() window.setLayout(layout); window.show(); - QApplication::setActiveWindow(&window); window.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&window)); QCOMPARE(QApplication::activeWindow(), &window); @@ -2134,7 +2133,6 @@ void tst_QGraphicsProxyWidget::setFocus_simpleTwoWidgets() window.setLayout(layout); window.show(); - QApplication::setActiveWindow(&window); window.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&window)); QCOMPARE(QApplication::activeWindow(), &window); @@ -2213,7 +2211,6 @@ void tst_QGraphicsProxyWidget::setFocus_complexTwoWidgets() window.setLayout(layout); window.show(); - QApplication::setActiveWindow(&window); window.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&window)); QCOMPARE(QApplication::activeWindow(), &window); @@ -2305,7 +2302,7 @@ void tst_QGraphicsProxyWidget::popup_basic() box->setGeometry(0, 0, 320, 40); box->addItems(QStringList() << "monday" << "tuesday" << "wednesday" << "thursday" << "saturday" << "sunday"); - QCOMPARE(proxy->childItems().count(), 0); + QCOMPARE(proxy->childItems().size(), 0); proxy->setWidget(boxGuard.release()); proxy->show(); scene.addItem(proxy); @@ -2322,7 +2319,7 @@ void tst_QGraphicsProxyWidget::popup_basic() QTRY_COMPARE(box->pos(), QPoint()); - QCOMPARE(proxy->childItems().count(), 1); + QCOMPARE(proxy->childItems().size(), 1); QGraphicsProxyWidget *child = (QGraphicsProxyWidget*)(proxy->childItems())[0]; QVERIFY(child->isWidget()); QVERIFY(child->widget()); @@ -2402,7 +2399,7 @@ void tst_QGraphicsProxyWidget::changingCursor_basic() proxy->setWidget(widget); QSignalSpy sceneChangedSpy(&scene, &QGraphicsScene::changed); scene.addItem(proxy); - QTRY_VERIFY(sceneChangedSpy.count() > 0); // make sure the scene is ready + QTRY_VERIFY(sceneChangedSpy.size() > 0); // make sure the scene is ready // in QTest::mouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center()))); @@ -2458,7 +2455,6 @@ void tst_QGraphicsProxyWidget::tooltip_basic() QGraphicsView view(&scene); view.setFixedSize(200, 200); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); { QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(), @@ -2468,7 +2464,8 @@ void tst_QGraphicsProxyWidget::tooltip_basic() bool foundView = false; bool foundTipLabel = false; - foreach (QWidget *widget, QApplication::topLevelWidgets()) { + const auto widgets = QApplication::topLevelWidgets(); + for (QWidget *widget : widgets) { if (widget == &view) foundView = true; if (widget->inherits("QTipLabel")) @@ -2595,7 +2592,7 @@ void tst_QGraphicsProxyWidget::windowOpacity() QGraphicsProxyWidget *proxy = scene.addWidget(widget); proxy->setCacheMode(QGraphicsItem::ItemCoordinateCache); - QApplication::setActiveWindow(&view); + QApplicationPrivate::setActiveWindow(&view); view.show(); QVERIFY(QTest::qWaitForWindowActive(&view)); QVERIFY(view.isActiveWindow()); @@ -2620,7 +2617,7 @@ void tst_QGraphicsProxyWidget::windowOpacity() QTRY_COMPARE(eventSpy.counts[QEvent::UpdateRequest], 0); QTRY_COMPARE(eventSpy.counts[QEvent::Paint], paints); - QTRY_COMPARE(signalSpy.count(), 1); + QTRY_COMPARE(signalSpy.size(), 1); const QList<QVariant> arguments = signalSpy.takeFirst(); const QList<QRectF> updateRects = qvariant_cast<QList<QRectF> >(arguments.at(0)); QCOMPARE(updateRects.size(), 1); @@ -2895,10 +2892,10 @@ void tst_QGraphicsProxyWidget::createProxyForChildWidget() QTest::mousePress(view.viewport(), Qt::LeftButton, {}, view.mapFromScene(checkboxProxy->mapToScene(QPointF(8,8)))); - QTRY_COMPARE(spy.count(), 0); + QTRY_COMPARE(spy.size(), 0); QTest::mouseRelease(view.viewport(), Qt::LeftButton, {}, view.mapFromScene(checkboxProxy->mapToScene(QPointF(8,8)))); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); @@ -2993,7 +2990,6 @@ void tst_QGraphicsProxyWidget::actionsContextMenu() view.resize(200, 200); view.move(QGuiApplication::primaryScreen()->geometry().center() - QPoint(100, 100)); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); view.setFocus(); QTRY_VERIFY(view.hasFocus()); @@ -3063,6 +3059,9 @@ void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget_data() void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QFETCH(bool, bypass); std::unique_ptr<QWidget> widgetGuard(new QWidget); @@ -3072,7 +3071,6 @@ void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget() QGraphicsScene scene; QGraphicsView view(&scene); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QGraphicsProxyWidget *proxy = scene.addWidget(widgetGuard.release()); @@ -3276,6 +3274,9 @@ public: void tst_QGraphicsProxyWidget::inputMethod() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QGraphicsScene scene; // check that the proxy is initialized with the correct input method sensitivity @@ -3335,7 +3336,6 @@ void tst_QGraphicsProxyWidget::clickFocus() view.setFrameStyle(0); view.resize(300, 300); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QVERIFY(!proxy->hasFocus()); @@ -3479,7 +3479,6 @@ void tst_QGraphicsProxyWidget::QTBUG_6986_sendMouseEventToAlienWidget() QGraphicsView view(&scene); view.resize(600, 600); - QApplication::setActiveWindow(&view); view.show(); QVERIFY(QTest::qWaitForWindowActive(&view)); @@ -3523,7 +3522,6 @@ void tst_QGraphicsProxyWidget::mapToGlobal() // QTBUG-41135 childWidget->resize(embeddedWidget->size() / 2); childWidget->move(embeddedWidget->width() / 4, embeddedWidget->height() / 4); // center in embeddedWidget scene.addWidget(embeddedWidget); - QApplication::setActiveWindow(&view); view.show(); QVERIFY(QTest::qWaitForWindowExposed(&view)); const QPoint embeddedCenter = embeddedWidget->rect().center(); @@ -3688,27 +3686,27 @@ void tst_QGraphicsProxyWidget::wheelEventPropagation() // accepted by the embedded widget QCOMPARE(view.itemAt(wheelPosition), nullptr); wheelUp(Qt::NoScrollPhase); - QCOMPARE(scrollSpy.count(), ++scrollCount); + QCOMPARE(scrollSpy.size(), ++scrollCount); // wheeling on the label, which ignores the event, should scroll the view QCOMPARE(view.itemAt(wheelPosition), labelProxy); wheelUp(Qt::NoScrollPhase); - QCOMPARE(scrollSpy.count(), ++scrollCount); + QCOMPARE(scrollSpy.size(), ++scrollCount); QCOMPARE(view.itemAt(wheelPosition), labelProxy); wheelUp(Qt::NoScrollPhase); - QCOMPARE(scrollSpy.count(), ++scrollCount); + QCOMPARE(scrollSpy.size(), ++scrollCount); // left the widget QCOMPARE(view.itemAt(wheelPosition), nullptr); wheelUp(Qt::NoScrollPhase); - QCOMPARE(scrollSpy.count(), ++scrollCount); + QCOMPARE(scrollSpy.size(), ++scrollCount); // reached the nested widget, which accepts the wheel event, so no more scrolling QCOMPARE(view.itemAt(wheelPosition), nestedProxy); // remember this position for later const int scrollBarValueOnNestedProxy = view.verticalScrollBar()->value(); wheelUp(Qt::NoScrollPhase); - QCOMPARE(scrollSpy.count(), scrollCount); + QCOMPARE(scrollSpy.size(), scrollCount); QCOMPARE(nestedWidget->wheelEventCount, 1); // reset, try with kinetic events @@ -3719,41 +3717,41 @@ void tst_QGraphicsProxyWidget::wheelEventPropagation() // no matter if the widget accepts wheel events - the view has the grab QCOMPARE(view.itemAt(wheelPosition), nullptr); wheelUp(Qt::ScrollBegin); - QCOMPARE(scrollSpy.count(), ++scrollCount); + QCOMPARE(scrollSpy.size(), ++scrollCount); for (int i = 0; i < 5; ++i) { wheelUp(Qt::ScrollUpdate); - QCOMPARE(scrollSpy.count(), ++scrollCount); + QCOMPARE(scrollSpy.size(), ++scrollCount); } wheelUp(Qt::ScrollEnd); - QCOMPARE(scrollSpy.count(), ++scrollCount); + QCOMPARE(scrollSpy.size(), ++scrollCount); // reset view.verticalScrollBar()->setValue(0); - scrollCount = scrollSpy.count(); + scrollCount = scrollSpy.size(); // starting a scroll on a widget that doesn't accept wheel events // should also scroll the view, which still gets the grab wheelUp(Qt::NoScrollPhase); - scrollCount = scrollSpy.count(); + scrollCount = scrollSpy.size(); QCOMPARE(view.itemAt(wheelPosition), labelProxy); wheelUp(Qt::ScrollBegin); - QCOMPARE(scrollSpy.count(), ++scrollCount); + QCOMPARE(scrollSpy.size(), ++scrollCount); for (int i = 0; i < 5; ++i) { wheelUp(Qt::ScrollUpdate); - QCOMPARE(scrollSpy.count(), ++scrollCount); + QCOMPARE(scrollSpy.size(), ++scrollCount); } wheelUp(Qt::ScrollEnd); - QCOMPARE(scrollSpy.count(), ++scrollCount); + QCOMPARE(scrollSpy.size(), ++scrollCount); // starting a scroll on a widget that does accept wheel events // should not scroll the view view.verticalScrollBar()->setValue(scrollBarValueOnNestedProxy); - scrollCount = scrollSpy.count(); + scrollCount = scrollSpy.size(); QCOMPARE(view.itemAt(wheelPosition), nestedProxy); wheelUp(Qt::ScrollBegin); - QCOMPARE(scrollSpy.count(), scrollCount); + QCOMPARE(scrollSpy.size(), scrollCount); } #endif // QT_CONFIG(wheelevent) @@ -3851,7 +3849,7 @@ void tst_QGraphicsProxyWidget::touchEventPropagation() QHash<int, QList<TouchRecord>> records; QWidget *mousePressReceiver = nullptr; - int count(int id = 0) const { return records.value(id).count(); } + int count(int id = 0) const { return records.value(id).size(); } TouchRecord at(int i, int id = 0) const { return records.value(id).at(i); } void clear() { @@ -3955,7 +3953,7 @@ void tst_QGraphicsProxyWidget::touchEventPropagation() QCOMPARE(record.receiver, view.windowHandle()); QCOMPARE(record.eventType, QEvent::TouchEnd); QCOMPARE(eventSpy.mousePressReceiver, pushButton1); - QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.size(), 1); eventSpy.clear(); clickedSpy.clear(); @@ -4023,7 +4021,7 @@ void tst_QGraphicsProxyWidget::touchEventPropagation() QCOMPARE(eventSpy.at(0, 3).receiver, touchWidget2); QCOMPARE(eventSpy.at(1, 3).receiver, touchWidget2); QCOMPARE(eventSpy.at(2, 3).receiver, touchWidget2); - QCOMPARE(clickedSpy.count(), 0); // multi-touch event does not synthesize a mouse event + QCOMPARE(clickedSpy.size(), 0); // multi-touch event does not synthesize a mouse event } QTEST_MAIN(tst_QGraphicsProxyWidget) diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST b/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/auto/widgets/graphicsview/qgraphicsscene/BLACKLIST +++ /dev/null diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicsscene/CMakeLists.txt index 2b459890b8..c0dd8995b8 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsscene/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicsscene/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicsscene.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicsscene Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicsscene LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Resources: set(testdata_resource_files @@ -42,7 +46,7 @@ set(testdata_resource_files ) qt_internal_add_test(tst_qgraphicsscene - LOWDPI # special case + LOWDPI SOURCES tst_qgraphicsscene.cpp DEFINES diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp index 8389d8eab7..515ba80bbe 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtWidgets/QApplication> #include <QtWidgets/QDial> @@ -31,6 +31,8 @@ #include "../../../shared/platforminputcontext.h" #include <private/qinputmethod_p.h> +#include <QtWidgets/private/qapplication_p.h> + #if defined(Q_OS_WIN) #include <QtCore/qt_windows.h> #define Q_CHECK_PAINTEVENTS \ @@ -319,27 +321,27 @@ void tst_QGraphicsScene::sceneRect() QGraphicsScene scene; QSignalSpy sceneRectChanged(&scene, &QGraphicsScene::sceneRectChanged); QCOMPARE(scene.sceneRect(), QRectF()); - QCOMPARE(sceneRectChanged.count(), 0); + QCOMPARE(sceneRectChanged.size(), 0); QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 10, 10)); item->setPen(QPen(Qt::black, 0)); item->setPos(-5, -5); - QCOMPARE(sceneRectChanged.count(), 0); + QCOMPARE(sceneRectChanged.size(), 0); QCOMPARE(itemAt(scene, 0, 0), item); QVERIFY(scene.items(QPointF(10, 10)).isEmpty()); - QCOMPARE(sceneRectChanged.count(), 0); + QCOMPARE(sceneRectChanged.size(), 0); QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 10, 10)); - QCOMPARE(sceneRectChanged.count(), 1); + QCOMPARE(sceneRectChanged.size(), 1); QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); item->setPos(0, 0); QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 15, 15)); - QCOMPARE(sceneRectChanged.count(), 2); + QCOMPARE(sceneRectChanged.size(), 2); QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); scene.setSceneRect(-100, -100, 10, 10); - QCOMPARE(sceneRectChanged.count(), 3); + QCOMPARE(sceneRectChanged.size(), 3); QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); QCOMPARE(itemAt(scene, 0, 0), item); @@ -347,16 +349,16 @@ void tst_QGraphicsScene::sceneRect() QCOMPARE(scene.sceneRect(), QRectF(-100, -100, 10, 10)); item->setPos(10, 10); QCOMPARE(scene.sceneRect(), QRectF(-100, -100, 10, 10)); - QCOMPARE(sceneRectChanged.count(), 3); + QCOMPARE(sceneRectChanged.size(), 3); QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); scene.setSceneRect(QRectF()); QCOMPARE(itemAt(scene, 10, 10), item); QVERIFY(scene.items(QPointF(20, 20)).isEmpty()); - QCOMPARE(sceneRectChanged.count(), 4); + QCOMPARE(sceneRectChanged.size(), 4); QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 25, 25)); - QCOMPARE(sceneRectChanged.count(), 5); + QCOMPARE(sceneRectChanged.size(), 5); QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); } @@ -532,7 +534,7 @@ void tst_QGraphicsScene::itemsBoundingRect() QGraphicsScene scene; - for (const auto &rect : qAsConst(rects)) { + for (const auto &rect : std::as_const(rects)) { QPainterPath path; path.addRect(rect); QGraphicsPathItem *item = scene.addPath(path); @@ -597,7 +599,7 @@ void tst_QGraphicsScene::items_QPointF() int n = 0; QList<QGraphicsItem *> addedItems; - for (const auto &rect : qAsConst(items)) { + for (const auto &rect : std::as_const(items)) { QPainterPath path; path.addRect(0, 0, rect.width(), rect.height()); @@ -944,32 +946,32 @@ void tst_QGraphicsScene::selectionChanged() { QGraphicsScene scene(0, 0, 1000, 1000); QSignalSpy spy(&scene, &QGraphicsScene::selectionChanged); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QPainterPath path; path.addRect(scene.sceneRect()); QCOMPARE(scene.selectionArea(), QPainterPath()); scene.setSelectionArea(path); QCOMPARE(scene.selectionArea(), path); - QCOMPARE(spy.count(), 0); // selection didn't change + QCOMPARE(spy.size(), 0); // selection didn't change QVERIFY(scene.selectedItems().isEmpty()); QGraphicsItem *rect = scene.addRect(QRectF(0, 0, 100, 100)); - QCOMPARE(spy.count(), 0); // selection didn't change + QCOMPARE(spy.size(), 0); // selection didn't change rect->setSelected(true); QVERIFY(!rect->isSelected()); - QCOMPARE(spy.count(), 0); // selection didn't change, item isn't selectable + QCOMPARE(spy.size(), 0); // selection didn't change, item isn't selectable rect->setFlag(QGraphicsItem::ItemIsSelectable); rect->setSelected(true); QVERIFY(rect->isSelected()); - QCOMPARE(spy.count(), 1); // selection changed + QCOMPARE(spy.size(), 1); // selection changed QCOMPARE(scene.selectedItems(), {rect}); rect->setSelected(false); QVERIFY(!rect->isSelected()); - QCOMPARE(spy.count(), 2); // selection changed + QCOMPARE(spy.size(), 2); // selection changed QVERIFY(scene.selectedItems().isEmpty()); QGraphicsEllipseItem *parentItem = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100)); @@ -981,33 +983,33 @@ void tst_QGraphicsScene::selectionChanged() grandChildItem->setSelected(true); scene.addItem(parentItem); - QCOMPARE(spy.count(), 3); // the grandchild was added, so the selection changed once + QCOMPARE(spy.size(), 3); // the grandchild was added, so the selection changed once scene.removeItem(parentItem); - QCOMPARE(spy.count(), 4); // the grandchild was removed, so the selection changed + QCOMPARE(spy.size(), 4); // the grandchild was removed, so the selection changed rect->setSelected(true); - QCOMPARE(spy.count(), 5); // the rect was reselected, so the selection changed + QCOMPARE(spy.size(), 5); // the rect was reselected, so the selection changed scene.clearSelection(); - QCOMPARE(spy.count(), 6); // the scene selection was cleared + QCOMPARE(spy.size(), 6); // the scene selection was cleared rect->setSelected(true); - QCOMPARE(spy.count(), 7); // the rect was reselected, so the selection changed + QCOMPARE(spy.size(), 7); // the rect was reselected, so the selection changed rect->setFlag(QGraphicsItem::ItemIsSelectable, false); - QCOMPARE(spy.count(), 8); // the rect was unselected, so the selection changed + QCOMPARE(spy.size(), 8); // the rect was unselected, so the selection changed rect->setSelected(true); - QCOMPARE(spy.count(), 8); // the rect is not longer selectable, so the selection does not change + QCOMPARE(spy.size(), 8); // the rect is not longer selectable, so the selection does not change rect->setFlag(QGraphicsItem::ItemIsSelectable, true); rect->setSelected(true); - QCOMPARE(spy.count(), 9); // the rect is again selectable, so the selection changed + QCOMPARE(spy.size(), 9); // the rect is again selectable, so the selection changed delete rect; - QCOMPARE(spy.count(), 10); // a selected item was deleted; selection changed + QCOMPARE(spy.size(), 10); // a selected item was deleted; selection changed } void tst_QGraphicsScene::selectionChanged2() @@ -1020,7 +1022,7 @@ void tst_QGraphicsScene::selectionChanged2() item1->setFlag(QGraphicsItem::ItemIsSelectable); item2->setFlag(QGraphicsItem::ItemIsSelectable); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); { QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress); event.setScenePos(QPointF(50, 50)); @@ -1035,7 +1037,7 @@ void tst_QGraphicsScene::selectionChanged2() } QVERIFY(item1->isSelected()); QVERIFY(!item2->isSelected()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); { QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress); event.setScenePos(QPointF(150, 150)); @@ -1050,7 +1052,7 @@ void tst_QGraphicsScene::selectionChanged2() } QVERIFY(!item1->isSelected()); QVERIFY(item2->isSelected()); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); { QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress); event.setScenePos(QPointF(50, 50)); @@ -1060,7 +1062,7 @@ void tst_QGraphicsScene::selectionChanged2() } QVERIFY(!item1->isSelected()); QVERIFY(item2->isSelected()); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); { QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease); event.setScenePos(QPointF(50, 50)); @@ -1069,7 +1071,7 @@ void tst_QGraphicsScene::selectionChanged2() } QVERIFY(item1->isSelected()); QVERIFY(!item2->isSelected()); - QCOMPARE(spy.count(), 3); + QCOMPARE(spy.size(), 3); } void tst_QGraphicsScene::addItem() @@ -1292,7 +1294,6 @@ void tst_QGraphicsScene::removeItem() view.setWindowTitle(QTest::currentTestFunction()); view.setFixedSize(150, 150); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QTest::mouseMove(view.windowHandle(), view.mapFromScene(hoverItem->scenePos() + QPointF(20, 20))); QTRY_VERIFY(!hoverItem->isHovered); @@ -1600,7 +1601,6 @@ void tst_QGraphicsScene::hoverEvents_siblings() view.rotate(10); view.scale(1.7, 1.7); view.show(); - QApplication::setActiveWindow(&view); view.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&view)); @@ -1670,7 +1670,6 @@ void tst_QGraphicsScene::hoverEvents_parentChild() view.rotate(10); view.scale(1.7, 1.7); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove); @@ -1732,7 +1731,7 @@ void tst_QGraphicsScene::createItemGroup() // All items in children1 are children of parent1 QGraphicsItem *parent1 = scene.addRect(QRectF(-10, -10, 20, 20)); - for (QGraphicsItem *item : qAsConst(children1)) + for (QGraphicsItem *item : std::as_const(children1)) item->setParentItem(parent1); QGraphicsItemGroup *group = scene.createItemGroup(children1); @@ -1748,7 +1747,7 @@ void tst_QGraphicsScene::createItemGroup() // All items in children2 are children of parent2 QGraphicsItem *parent2 = scene.addRect(QRectF(-10, -10, 20, 20)); - for (QGraphicsItem *item : qAsConst(children2)) + for (QGraphicsItem *item : std::as_const(children2)) item->setParentItem(parent2); // Now make parent2 a child of parent1, so all children2 are also children @@ -1772,7 +1771,7 @@ void tst_QGraphicsScene::createItemGroup() QCOMPARE(children2.first()->parentItem(), parent1); // Fixup the parent-child chain - for (QGraphicsItem *item : qAsConst(children2)) + for (QGraphicsItem *item : std::as_const(children2)) item->setParentItem(parent2); // These share no common parent @@ -1782,7 +1781,7 @@ void tst_QGraphicsScene::createItemGroup() // Make children3 children of parent3 QGraphicsItem *parent3 = scene.addRect(QRectF(-10, -10, 20, 20)); - for (QGraphicsItem *item : qAsConst(children3)) + for (QGraphicsItem *item : std::as_const(children3)) item->setParentItem(parent3); // These should have parent3 as a parent @@ -2678,6 +2677,9 @@ void tst_QGraphicsScene::renderItemsWithNegativeWidthOrHeight() #ifdef Q_OS_ANDROID QSKIP("Test only works on platforms with resizable windows"); #endif + if (QGuiApplication::platformName().startsWith(QLatin1String("eglfs"), Qt::CaseInsensitive)) + QSKIP("EGLFS does not allow resizing on top window"); + QGraphicsScene scene(0, 0, m_testSize.width(), m_testSize.height()); // Add item with negative width. @@ -2832,7 +2834,7 @@ void tst_QGraphicsScene::update() QCoreApplication::processEvents(); // Check that the update region is correct - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QRectF region; const auto &rects = qvariant_cast<QList<QRectF> >(spy.at(0).at(0)); for (const auto &rectF : rects) @@ -2849,7 +2851,6 @@ void tst_QGraphicsScene::update2() view.resize(m_testSize); view.setScene(&scene); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QTRY_VERIFY(view.repaints >= 1); view.repaints = 0; @@ -3039,7 +3040,6 @@ void tst_QGraphicsScene::tabFocus_emptyScene() widget.setLayout(layout); widget.setWindowTitle(QTest::currentTestFunction()); widget.show(); - QApplication::setActiveWindow(&widget); widget.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&widget)); @@ -3091,7 +3091,6 @@ void tst_QGraphicsScene::tabFocus_sceneWithFocusableItems() widget.setWindowTitle(QTest::currentTestFunction()); widget.setLayout(layout); widget.show(); - QApplication::setActiveWindow(&widget); widget.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&widget)); @@ -3145,7 +3144,7 @@ void tst_QGraphicsScene::tabFocus_sceneWithFocusableItems() // Check that the correct item regains focus. widget.show(); - QApplication::setActiveWindow(&widget); + QApplicationPrivate::setActiveWindow(&widget); widget.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&widget)); QVERIFY(view->hasFocus()); @@ -3229,7 +3228,7 @@ void tst_QGraphicsScene::tabFocus_sceneWithFocusWidgets() widget.setWindowTitle(QTest::currentTestFunction()); widget.setLayout(layout); widget.show(); - QApplication::setActiveWindow(&widget); + QApplicationPrivate::setActiveWindow(&widget); widget.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&widget)); @@ -3268,7 +3267,7 @@ void tst_QGraphicsScene::tabFocus_sceneWithFocusWidgets() widget.hide(); QTest::qWait(15); widget.show(); - QApplication::setActiveWindow(&widget); + QApplicationPrivate::setActiveWindow(&widget); widget.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&widget)); QTRY_VERIFY(widget1->hasFocus()); @@ -3317,7 +3316,7 @@ void tst_QGraphicsScene::tabFocus_sceneWithNestedFocusWidgets() widget.setWindowTitle(QTest::currentTestFunction()); widget.setLayout(layout); widget.show(); - QApplication::setActiveWindow(&widget); + QApplicationPrivate::setActiveWindow(&widget); widget.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&widget)); @@ -3402,7 +3401,7 @@ void tst_QGraphicsScene::tabFocus_sceneWithNestedFocusWidgets() widget.hide(); QTest::qWait(12); widget.show(); - QApplication::setActiveWindow(&widget); + QApplicationPrivate::setActiveWindow(&widget); widget.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&widget)); QTRY_VERIFY(widget1->hasFocus()); @@ -3531,7 +3530,7 @@ void tst_QGraphicsScene::task160653_selectionChanged() QVERIFY(QTest::qWaitForWindowActive(&view)); QTest::mouseClick( view.viewport(), Qt::LeftButton, {}, view.mapFromScene(scene.items().first()->scenePos())); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } void tst_QGraphicsScene::task250680_childClip() @@ -3662,8 +3661,8 @@ void tst_QGraphicsScene::insertionOrder() { QList<QGraphicsItem*> itemList = scene.items(); - QCOMPARE(itemList.count(), numItems); - for (int i = 0; i < itemList.count(); ++i) { + QCOMPARE(itemList.size(), numItems); + for (int i = 0; i < itemList.size(); ++i) { QCOMPARE(numItems-1-i, itemList.at(i)->data(0).toInt()); } } @@ -3676,8 +3675,8 @@ void tst_QGraphicsScene::insertionOrder() { QList<QGraphicsItem*> itemList = scene.items(); - QCOMPARE(itemList.count(), numItems); - for (int i = 0; i < itemList.count(); ++i) { + QCOMPARE(itemList.size(), numItems); + for (int i = 0; i < itemList.size(); ++i) { QCOMPARE(numItems-1-i, itemList.at(i)->data(0).toInt()); } } @@ -3820,7 +3819,6 @@ void tst_QGraphicsScene::inputMethod() view.resize(m_testSize); view.show(); view.setWindowTitle(QTest::currentTestFunction()); - QApplication::setActiveWindow(&view); view.setFocus(); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(QApplication::activeWindow(), &view); @@ -4025,7 +4023,7 @@ void tst_QGraphicsScene::polishItems2() // added 10 new children. These should be polished in the next // event loop iteration. const QList<QGraphicsItem *> children = item->childItems(); - QCOMPARE(children.count(), 10); + QCOMPARE(children.size(), 10); for (QGraphicsItem *child : children) QVERIFY(!static_cast<PolishItem *>(child)->polished); @@ -4064,7 +4062,6 @@ void tst_QGraphicsScene::isActive() view1->setVisible(false); toplevel1.show(); - QApplication::setActiveWindow(&toplevel1); QVERIFY(QTest::qWaitForWindowActive(&toplevel1)); QCOMPARE(QApplication::activeWindow(), &toplevel1); @@ -4093,7 +4090,7 @@ void tst_QGraphicsScene::isActive() QVERIFY(!scene2.hasFocus()); toplevel1.show(); - QApplication::setActiveWindow(&toplevel1); + QApplicationPrivate::setActiveWindow(&toplevel1); QVERIFY(QTest::qWaitForWindowActive(&toplevel1)); QCOMPARE(QApplication::activeWindow(), &toplevel1); @@ -4133,7 +4130,7 @@ void tst_QGraphicsScene::isActive() toplevel2.move(m_availableGeometry.topLeft() + QPoint(50, 50)); toplevel2.show(); - QApplication::setActiveWindow(&toplevel2); + QApplicationPrivate::setActiveWindow(&toplevel2); QVERIFY(QTest::qWaitForWindowActive(&toplevel2)); QCOMPARE(QApplication::activeWindow(), &toplevel2); @@ -4183,7 +4180,7 @@ void tst_QGraphicsScene::isActive() topLevelView.move(toplevel2.geometry().topRight() + QPoint(100, 50)); topLevelView.resize(m_testSize); topLevelView.show(); - QApplication::setActiveWindow(&topLevelView); + QApplicationPrivate::setActiveWindow(&topLevelView); topLevelView.setFocus(); QVERIFY(QTest::qWaitForWindowActive(&topLevelView)); QCOMPARE(QApplication::activeWindow(), &topLevelView); @@ -4211,7 +4208,7 @@ void tst_QGraphicsScene::isActive() QVERIFY(scene1.hasFocus()); QVERIFY(!scene2.hasFocus()); - QApplication::setActiveWindow(&toplevel2); + QApplicationPrivate::setActiveWindow(&toplevel2); QVERIFY(QTest::qWaitForWindowActive(&toplevel2)); QVERIFY(!scene1.isActive()); @@ -4241,7 +4238,6 @@ void tst_QGraphicsScene::isActive() toplevel3.show(); - QApplication::setActiveWindow(&toplevel3); QVERIFY(QTest::qWaitForWindowActive(&toplevel3)); QCOMPARE(QApplication::activeWindow(), &toplevel3); @@ -4354,7 +4350,6 @@ void tst_QGraphicsScene::removeFullyTransparentItem() view.resize(m_testSize); view.setScene(&scene); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCoreApplication::processEvents(); // Process all queued paint events @@ -4604,13 +4599,13 @@ void tst_QGraphicsScene::zeroScale() rect1->setScale(0.00000001); QApplication::processEvents(); - QTRY_COMPARE(cl.changes.count(), 1); + QTRY_COMPARE(cl.changes.size(), 1); QGraphicsRectItem *rect2 = new QGraphicsRectItem(-0.0000001, -0.0000001, 0.0000001, 0.0000001); rect2->setScale(0.00000001); scene.addItem(rect2); rect1->setPos(20,20); QApplication::processEvents(); - QTRY_COMPARE(cl.changes.count(), 2); + QTRY_COMPARE(cl.changes.size(), 2); } void tst_QGraphicsScene::focusItemChangedSignal() @@ -4621,17 +4616,17 @@ void tst_QGraphicsScene::focusItemChangedSignal() QGraphicsScene scene; QSignalSpy spy(&scene, &QGraphicsScene::focusItemChanged); QVERIFY(spy.isValid()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); scene.setFocus(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QEvent activateEvent(QEvent::WindowActivate); QCoreApplication::sendEvent(&scene, &activateEvent); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QGraphicsRectItem *topLevelItem1 = new QGraphicsRectItem; topLevelItem1->setFlag(QGraphicsItem::ItemIsFocusable); scene.addItem(topLevelItem1); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QVERIFY(!topLevelItem1->hasFocus()); QGraphicsRectItem *topLevelItem2 = new QGraphicsRectItem; @@ -4639,7 +4634,7 @@ void tst_QGraphicsScene::focusItemChangedSignal() topLevelItem2->setFocus(); QVERIFY(!topLevelItem2->hasFocus()); scene.addItem(topLevelItem2); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QList<QVariant> arguments = spy.takeFirst(); QCOMPARE(arguments.size(), 3); QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), topLevelItem2); @@ -4648,7 +4643,7 @@ void tst_QGraphicsScene::focusItemChangedSignal() QVERIFY(topLevelItem2->hasFocus()); scene.clearFocus(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.size(), 3); QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), nullptr); @@ -4656,7 +4651,7 @@ void tst_QGraphicsScene::focusItemChangedSignal() QCOMPARE(qvariant_cast<Qt::FocusReason>(arguments.at(2)), Qt::OtherFocusReason); scene.setFocus(Qt::MenuBarFocusReason); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.size(), 3); QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), topLevelItem2); @@ -4685,16 +4680,16 @@ void tst_QGraphicsScene::focusItemChangedSignal() QEvent deactivateEvent(QEvent::WindowDeactivate); QCoreApplication::sendEvent(&scene, &deactivateEvent); QEXPECT_FAIL("", "QTBUG-28346", Continue); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCoreApplication::sendEvent(&scene, &activateEvent); QEXPECT_FAIL("", "QTBUG-28346", Continue); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QGraphicsRectItem *panel1 = new QGraphicsRectItem; panel1->setFlags(QGraphicsItem::ItemIsPanel | QGraphicsItem::ItemIsFocusable); panel1->setFocus(); scene.addItem(panel1); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.size(), 3); QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), panel1); @@ -4704,11 +4699,11 @@ void tst_QGraphicsScene::focusItemChangedSignal() QGraphicsRectItem *panel2 = new QGraphicsRectItem; panel2->setFlags(QGraphicsItem::ItemIsPanel | QGraphicsItem::ItemIsFocusable); scene.addItem(panel2); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); for (int i = 0; i < 3; ++i) { scene.setActivePanel(panel2); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.size(), 3); QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), panel2); @@ -4716,7 +4711,7 @@ void tst_QGraphicsScene::focusItemChangedSignal() QCOMPARE(qvariant_cast<Qt::FocusReason>(arguments.at(2)), Qt::ActiveWindowFocusReason); scene.setActivePanel(panel1); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.size(), 3); QCOMPARE(qvariant_cast<QGraphicsItem *>(arguments.at(0)), panel1); @@ -4812,7 +4807,6 @@ void tst_QGraphicsScene::focusOnTouch() rect->setFlag(QGraphicsItem::ItemIsFocusable, true); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QVERIFY(!rect->hasFocus()); @@ -4863,23 +4857,23 @@ void tst_QGraphicsScene::clearSelection() scene.addItem(regularRect); scene.addItem(selectedRect); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); - QCOMPARE(scene.selectedItems().count(), 2); + QCOMPARE(scene.selectedItems().size(), 2); scene.clearSelection(); QVERIFY(!regularRect->isSelected()); QVERIFY(selectedRect->isSelected()); - QCOMPARE(scene.selectedItems().count(), 1); - QCOMPARE(spy.count(), 3); + QCOMPARE(scene.selectedItems().size(), 1); + QCOMPARE(spy.size(), 3); delete regularRect; - QCOMPARE(spy.count(), 3); + QCOMPARE(spy.size(), 3); scene.clearSelection(); - QCOMPARE(spy.count(), 3); + QCOMPARE(spy.size(), 3); delete selectedRect; - QCOMPARE(spy.count(), 4); + QCOMPARE(spy.size(), 4); } void tst_QGraphicsScene::taskQTBUG_15977_renderWithDeviceCoordinateCache() @@ -4913,7 +4907,6 @@ void tst_QGraphicsScene::taskQTBUG_16401_focusItem() rect->setFlag(QGraphicsItem::ItemIsFocusable); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QVERIFY(!scene.focusItem()); @@ -4955,7 +4948,6 @@ void tst_QGraphicsScene::taskQTBUG_42915_focusNextPrevChild() widget2->setFocusPolicy(Qt::NoFocus); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QTest::keyEvent(QTest::Click, &view, Qt::Key_Tab); diff --git a/tests/auto/widgets/graphicsview/qgraphicssceneindex/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicssceneindex/CMakeLists.txt index 45fef2616e..867831d898 100644 --- a/tests/auto/widgets/graphicsview/qgraphicssceneindex/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicssceneindex/CMakeLists.txt @@ -1,7 +1,11 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +# SPDX-License-Identifier: BSD-3-Clause -# Generated from qgraphicssceneindex.pro. +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicssceneindex LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() if(NOT QT_FEATURE_private_tests) return() @@ -21,6 +25,3 @@ qt_internal_add_test(tst_qgraphicssceneindex Qt::Widgets Qt::WidgetsPrivate ) - -#### Keys ignored in scope 1:.:.:qgraphicssceneindex.pro:<TRUE>: -# _REQUIREMENTS = "qtConfig(private_tests)" diff --git a/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index 4cad9906bb..b6d48b52d5 100644 --- a/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -8,6 +8,7 @@ #include <private/qgraphicsscenebsptreeindex_p.h> #include <private/qgraphicssceneindex_p.h> #include <private/qgraphicsscenelinearindex_p.h> +#include <QtWidgets/private/qapplication_p.h> class tst_QGraphicsSceneIndex : public QObject { @@ -74,13 +75,13 @@ void tst_QGraphicsSceneIndex::scatteredItems() for (int i = 0; i < 10; ++i) scene.addRect(i*50, i*50, 40, 35); - QCOMPARE(scene.items(QPointF(5, 5)).count(), 1); - QCOMPARE(scene.items(QPointF(55, 55)).count(), 1); - QCOMPARE(scene.items(QPointF(-100, -100)).count(), 0); + QCOMPARE(scene.items(QPointF(5, 5)).size(), 1); + QCOMPARE(scene.items(QPointF(55, 55)).size(), 1); + QCOMPARE(scene.items(QPointF(-100, -100)).size(), 0); - QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1); - QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 10); - QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0); + QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).size(), 1); + QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).size(), 10); + QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).size(), 0); } void tst_QGraphicsSceneIndex::overlappedItems_data() @@ -99,17 +100,17 @@ void tst_QGraphicsSceneIndex::overlappedItems() for (int j = 0; j < 10; ++j) scene.addRect(i*50, j*50, 200, 200)->setPen(QPen(Qt::black, 0)); - QCOMPARE(scene.items(QPointF(5, 5)).count(), 1); - QCOMPARE(scene.items(QPointF(55, 55)).count(), 4); - QCOMPARE(scene.items(QPointF(105, 105)).count(), 9); - QCOMPARE(scene.items(QPointF(-100, -100)).count(), 0); - - QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 100); - QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0); - QCOMPARE(scene.items(QRectF(0, 0, 200, 200)).count(), 16); - QCOMPARE(scene.items(QRectF(0, 0, 100, 100)).count(), 4); - QCOMPARE(scene.items(QRectF(0, 0, 1, 100)).count(), 2); - QCOMPARE(scene.items(QRectF(0, 0, 1, 1000)).count(), 10); + QCOMPARE(scene.items(QPointF(5, 5)).size(), 1); + QCOMPARE(scene.items(QPointF(55, 55)).size(), 4); + QCOMPARE(scene.items(QPointF(105, 105)).size(), 9); + QCOMPARE(scene.items(QPointF(-100, -100)).size(), 0); + + QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).size(), 100); + QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).size(), 0); + QCOMPARE(scene.items(QRectF(0, 0, 200, 200)).size(), 16); + QCOMPARE(scene.items(QRectF(0, 0, 100, 100)).size(), 4); + QCOMPARE(scene.items(QRectF(0, 0, 1, 100)).size(), 2); + QCOMPARE(scene.items(QRectF(0, 0, 1, 1000)).size(), 10); } void tst_QGraphicsSceneIndex::movingItems_data() @@ -128,20 +129,20 @@ void tst_QGraphicsSceneIndex::movingItems() scene.addRect(i*50, i*50, 40, 35); QGraphicsRectItem *box = scene.addRect(0, 0, 10, 10); - QCOMPARE(scene.items(QPointF(5, 5)).count(), 2); - QCOMPARE(scene.items(QPointF(-1, -1)).count(), 0); - QCOMPARE(scene.items(QRectF(0, 0, 5, 5)).count(), 2); + QCOMPARE(scene.items(QPointF(5, 5)).size(), 2); + QCOMPARE(scene.items(QPointF(-1, -1)).size(), 0); + QCOMPARE(scene.items(QRectF(0, 0, 5, 5)).size(), 2); box->setPos(10, 10); - QCOMPARE(scene.items(QPointF(9, 9)).count(), 1); - QCOMPARE(scene.items(QPointF(15, 15)).count(), 2); - QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).count(), 1); + QCOMPARE(scene.items(QPointF(9, 9)).size(), 1); + QCOMPARE(scene.items(QPointF(15, 15)).size(), 2); + QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).size(), 1); box->setPos(-5, -5); - QCOMPARE(scene.items(QPointF(-1, -1)).count(), 1); - QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).count(), 2); + QCOMPARE(scene.items(QPointF(-1, -1)).size(), 1); + QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).size(), 2); - QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 11); + QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).size(), 11); } void tst_QGraphicsSceneIndex::connectedToSceneRectChanged() @@ -290,7 +291,6 @@ void tst_QGraphicsSceneIndex::removeItems() QGraphicsView view(&scene); view.resize(600, 600); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); scene.removeItem(widgetChild1); @@ -322,7 +322,6 @@ void tst_QGraphicsSceneIndex::clear() QGraphicsView view(&scene); view.show(); - qApp->setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); scene.clear(); diff --git a/tests/auto/widgets/graphicsview/qgraphicstransform/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicstransform/CMakeLists.txt index 472392a731..a11036b30f 100644 --- a/tests/auto/widgets/graphicsview/qgraphicstransform/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicstransform/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicstransform.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicstransform Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicstransform LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicstransform SOURCES tst_qgraphicstransform.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp b/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp index 114444ebb9..3ee63d288b 100644 --- a/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicsview/CMakeLists.txt index fb82b2acb7..cf33de0b33 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicsview/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicsview.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicsview Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicsview LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicsview SOURCES tst_qgraphicsview.cpp tst_qgraphicsview.h @@ -22,9 +26,6 @@ qt_internal_add_test(tst_qgraphicsview Qt::WidgetsPrivate ) -#### Keys ignored in scope 1:.:.:qgraphicsview.pro:<TRUE>: -# testcase.timeout = "500" - ## Scopes: ##################################################################### diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index 849e290351..7ed1f28b0a 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -40,6 +40,8 @@ #include <QtTest/private/qtesthelpers_p.h> +#include <QtWidgets/private/qapplication_p.h> + using namespace QTestPrivate; Q_DECLARE_METATYPE(ExpectedValueDescription) @@ -77,6 +79,12 @@ static void sendMouseRelease(QWidget *widget, const QPoint &point, Qt::MouseButt QApplication::sendEvent(widget, &event); } +static bool isPlatformEGLFS() +{ + static const bool isEGLFS = !QGuiApplication::platformName().compare(QLatin1String("eglfs"), Qt::CaseInsensitive); + return isEGLFS; +} + class EventSpy : public QObject { Q_OBJECT @@ -246,6 +254,8 @@ private slots: #ifndef QT_NO_CURSOR void QTBUG_7438_cursor(); #endif + void resizeContentsOnItemDrag_data(); + void resizeContentsOnItemDrag(); public slots: void dummySlot() {} @@ -644,6 +654,8 @@ void tst_QGraphicsView::openGLViewport() { if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) QSKIP("QOpenGL is not supported on this platform."); + if (isPlatformEGLFS()) + QSKIP("", "Resizing does not work on EGLFS on top level window", Continue); QGraphicsScene scene; scene.setBackgroundBrush(Qt::white); @@ -665,16 +677,16 @@ void tst_QGraphicsView::openGLViewport() view.show(); QVERIFY(QTest::qWaitForWindowExposed(&view)); - QTRY_VERIFY(spy1.count() > 0); - QTRY_VERIFY(spy2.count() >= spy1.count()); + QTRY_VERIFY(spy1.size() > 0); + QTRY_VERIFY(spy2.size() >= spy1.size()); spy1.clear(); spy2.clear(); // Now test for resize (QTBUG-52419). This is special when the viewport is // a QOpenGLWidget since the underlying FBO must also be maintained. view.resize(300, 300); - QTRY_VERIFY(spy1.count() > 0); - QTRY_VERIFY(spy2.count() >= spy1.count()); + QTRY_VERIFY(spy1.size() > 0); + QTRY_VERIFY(spy2.size() >= spy1.size()); // There is no sane way to check if the framebuffer contents got updated // (grabFramebuffer is no good for the viewport case as that does not go // through paintGL). So skip the actual verification. @@ -1044,10 +1056,10 @@ void tst_QGraphicsView::rotated_rubberBand() sendMousePress(view.viewport(), QPoint(midWidth - 2, 0), Qt::LeftButton); sendMouseMove(view.viewport(), QPoint(midWidth + 2, view.viewport()->height()), Qt::LeftButton, Qt::LeftButton); - QCOMPARE(scene.selectedItems().count(), dim); - foreach (const QGraphicsItem *item, scene.items()) { + QCOMPARE(scene.selectedItems().size(), dim); + const auto items = scene.items(); + for (const QGraphicsItem *item : items) QCOMPARE(item->isSelected(), item->data(0).toBool()); - } sendMouseRelease(view.viewport(), QPoint(), Qt::LeftButton); } @@ -1625,6 +1637,9 @@ void tst_QGraphicsView::itemsInRect_cosmeticAdjust_data() void tst_QGraphicsView::itemsInRect_cosmeticAdjust() { + if (isPlatformEGLFS()) + QSKIP("", "Resizing does not work on EGLFS on top level window", Continue); + QFETCH(QRect, updateRect); QFETCH(int, numPaints); QFETCH(bool, adjustForAntialiasing); @@ -1918,6 +1933,9 @@ void tst_QGraphicsView::mapToSceneRect_data() void tst_QGraphicsView::mapToSceneRect() { + if (isPlatformEGLFS()) + QSKIP("", "Resizing does not work on EGLFS on top level window", Continue); + QFETCH(QRect, viewRect); QFETCH(QPolygonF, scenePoly); QFETCH(qreal, rotation); @@ -2135,7 +2153,6 @@ void tst_QGraphicsView::sendEvent() QGraphicsView view(&scene); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); @@ -2203,7 +2220,6 @@ void tst_QGraphicsView::wheelEvent() // Assign a view. QGraphicsView view(&scene); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); @@ -2440,7 +2456,6 @@ void tst_QGraphicsView::viewportUpdateMode() // Show the view, and initialize our test. view.show(); - qApp->setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); QVERIFY(QTest::qWaitForWindowActive(&view)); QTRY_VERIFY(!view.lastUpdateRegions.isEmpty()); @@ -2523,7 +2538,6 @@ void tst_QGraphicsView::viewportUpdateMode2() const QMargins margins = view.contentsMargins(); view.resize(200 + margins.left() + margins.right(), 200 + margins.top() + margins.bottom()); toplevel.show(); - qApp->setActiveWindow(&toplevel); QVERIFY(QTest::qWaitForWindowExposed(&toplevel)); QVERIFY(QTest::qWaitForWindowActive(&toplevel)); QTRY_VERIFY(view.painted); @@ -2735,7 +2749,8 @@ void tst_QGraphicsView::optimizationFlags_dontSavePainterState2() rectB->setTransform(QTransform::fromTranslate(200, 200)); rectB->setPen(QPen(Qt::black, 0)); - foreach (QGraphicsItem *item, scene.items()) + const auto items = scene.items(); + for (QGraphicsItem *item : items) item->setOpacity(0.6); CustomView view(&scene); @@ -2872,6 +2887,9 @@ public: void tst_QGraphicsView::scrollBarRanges() { + if (isPlatformEGLFS()) + QSKIP("", "Resizing does not work on EGLFS on top level window", Continue); + QFETCH(QByteArray, style); QFETCH(QSize, viewportSize); QFETCH(QRectF, sceneRect); @@ -3167,7 +3185,6 @@ void tst_QGraphicsView::task172231_untransformableItems() view.scale(2, 1); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); @@ -3229,7 +3246,6 @@ void tst_QGraphicsView::task187791_setSceneCausesUpdate() QGraphicsScene scene(0, 0, 200, 200); QGraphicsView view(&scene); view.show(); - qApp->setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); EventSpy updateSpy(view.viewport(), QEvent::Paint); @@ -3254,7 +3270,8 @@ protected: { ++mouseMoves; QGraphicsView::mouseMoveEvent(event); - foreach (QGraphicsItem *item, scene()->items()) { + const auto items = scene()->items(); + for (QGraphicsItem *item : items) { scene()->removeItem(item); delete item; } @@ -3315,7 +3332,6 @@ void tst_QGraphicsView::task207546_focusCrash() widget.layout()->addWidget(gr2); widget.show(); widget.activateWindow(); - QApplication::setActiveWindow(&widget); QVERIFY(QTest::qWaitForWindowActive(&widget)); QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&widget)); widget.focusNextPrevChild(true); @@ -3407,7 +3423,6 @@ void tst_QGraphicsView::task239729_noViewUpdate() QCOMPARE(spy.count(), 0); view->show(); - qApp->setActiveWindow(view); QVERIFY(QTest::qWaitForWindowActive(view)); QTRY_VERIFY(spy.count() >= 1); @@ -3539,6 +3554,9 @@ void tst_QGraphicsView::embeddedViewsWithFocus() void focusOutEvent(QFocusEvent *) override { --focusCount; } }; + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QGraphicsScene innerScene; FocusWidget *innerWidget = new FocusWidget; innerScene.addWidget(innerWidget); @@ -3640,6 +3658,9 @@ void tst_QGraphicsView::moveItemWhileScrolling_data() void tst_QGraphicsView::moveItemWhileScrolling() { + if (isPlatformEGLFS()) + QSKIP("", "Resizing does not work on EGLFS on top level window", Continue); + QFETCH(bool, adjustForAntialiasing); QFETCH(bool, changedConnected); @@ -4032,7 +4053,7 @@ void tst_QGraphicsView::exposeRegion() CustomView view; view.setScene(&scene); view.show(); - qApp->setActiveWindow(&view); + QApplicationPrivate::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); QVERIFY(QTest::qWaitForWindowActive(&view)); @@ -4106,7 +4127,6 @@ void tst_QGraphicsView::update() QVERIFY(QTest::qWaitForWindowExposed(&toplevel)); - QApplication::setActiveWindow(&toplevel); QApplication::processEvents(); QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&toplevel)); @@ -4163,6 +4183,9 @@ void tst_QGraphicsView::update2_data() void tst_QGraphicsView::update2() { + if (isPlatformEGLFS()) + QSKIP("", "Resizing does not work on EGLFS on top level window", Continue); + QFETCH(qreal, penWidth); QFETCH(bool, antialiasing); QFETCH(bool, changedConnected); @@ -4188,7 +4211,7 @@ void tst_QGraphicsView::update2() view.setFrameStyle(0); view.resize(200, 200); view.show(); - qApp->setActiveWindow(&view); + QApplicationPrivate::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); QVERIFY(QTest::qWaitForWindowActive(&view)); QTRY_VERIFY(rect->numPaints > 0); @@ -4258,7 +4281,7 @@ void tst_QGraphicsView::update_ancestorClipsChildrenToShape() CustomView view(&scene); view.show(); - qApp->setActiveWindow(&view); + QApplicationPrivate::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); QVERIFY(QTest::qWaitForWindowActive(&view)); QTRY_VERIFY(view.painted); @@ -4312,7 +4335,7 @@ void tst_QGraphicsView::update_ancestorClipsChildrenToShape2() CustomView view(&scene); view.show(); - qApp->setActiveWindow(&view); + QApplicationPrivate::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); QVERIFY(QTest::qWaitForWindowActive(&view)); QTRY_VERIFY(view.painted); @@ -4373,7 +4396,6 @@ void tst_QGraphicsView::inputMethodSensitivity() QGraphicsScene scene; QGraphicsView view(&scene); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); @@ -4471,7 +4493,6 @@ void tst_QGraphicsView::inputContextReset() QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled)); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view)); @@ -4619,7 +4640,6 @@ void tst_QGraphicsView::task255529_transformationAnchorMouseAndViewportMargins() VpGraphicsView view(&scene); view.setWindowFlags(Qt::X11BypassWindowManagerHint); view.show(); - qApp->setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); const bool isActiveWindow = QTest::qWaitForWindowActive(&view); if (!isActiveWindow) @@ -4762,6 +4782,9 @@ void tst_QGraphicsView::QTBUG_4151_clipAndIgnore() void tst_QGraphicsView::QTBUG_5859_exposedRect() { + if (isPlatformEGLFS()) + QSKIP("", "Resizing does not work on EGLFS on top level window", Continue); + class CustomScene : public QGraphicsScene { public: @@ -4790,7 +4813,6 @@ void tst_QGraphicsView::QTBUG_5859_exposedRect() QGraphicsView view(&scene); view.scale(4.15, 4.15); view.showNormal(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); QVERIFY(QTest::qWaitForWindowActive(&view)); @@ -4862,7 +4884,6 @@ void tst_QGraphicsView::hoverLeave() scene.addItem(item); view.showNormal(); - qApp->setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); QWindow *viewWindow = view.window()->windowHandle(); @@ -4941,7 +4962,6 @@ void tst_QGraphicsView::QTBUG_70255_scrollTo() view.centerOn(0, 0); view.show(); - QApplication::setActiveWindow(&view); if (!QTest::qWaitForWindowExposed(&view) || !QTest::qWaitForWindowActive(&view)) QSKIP("Failed to show and activate window"); @@ -4955,5 +4975,111 @@ void tst_QGraphicsView::QTBUG_70255_scrollTo() QCOMPARE(point, QPoint(0, -500)); } +void tst_QGraphicsView::resizeContentsOnItemDrag_data() +{ + QTest::addColumn<Qt::Alignment>("alignment"); + QTest::addColumn<Qt::Orientation>("orientation"); + QTest::addRow("Center right") << Qt::Alignment(Qt::AlignCenter) << Qt::Horizontal; + QTest::addRow("Center down") << Qt::Alignment(Qt::AlignCenter) << Qt::Vertical; + QTest::addRow("BottomLeft right") << (Qt::AlignBottom | Qt::AlignLeft) << Qt::Horizontal; + QTest::addRow("TopRight down") << (Qt::AlignTop | Qt::AlignRight) << Qt::Vertical; +} + +void tst_QGraphicsView::resizeContentsOnItemDrag() +{ + QFETCH(Qt::Alignment, alignment); + QFETCH(Qt::Orientation, orientation); + + QGraphicsView view; + QGraphicsScene scene; + view.setFixedSize(200, 200); + view.setScene(&scene); + + view.setAlignment(alignment); + + class MovableItem : public QGraphicsEllipseItem + { + public: + using QGraphicsEllipseItem::QGraphicsEllipseItem; + + QList<QPointF> scenePositions; + + protected: + void mousePressEvent(QGraphicsSceneMouseEvent *event) override + { + scenePositions << event->scenePos(); + } + void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override + { + scenePositions << event->scenePos(); + QGraphicsEllipseItem::mouseMoveEvent(event); + } + }; + + MovableItem item(-10, -10, 20, 20); + item.setFlags(QGraphicsItem::ItemIsMovable); + scene.addItem(&item); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + // Position the item near the relevant edge of the view, with a few pixels + // to go until the scrollbars should be showing. + if (orientation == Qt::Horizontal) + item.setPos(view.width() - item.rect().width() - 5, 0); + else + item.setPos(0, view.height() - item.rect().height() - 5); + QApplication::processEvents(); // queued connection used to trigger recalculateContentSize + QPoint mousePos = view.mapFromScene(item.pos()); + + QTest::mousePress(view.viewport(), Qt::LeftButton, {}, mousePos); + QCOMPARE(item.scenePositions.count(), 1); + QCOMPARE(item.scenePositions.takeLast(), view.mapToScene(mousePos)); + + auto lastItemPos = item.pos(); + auto lastScenePos = view.mapToScene(mousePos); + int overshoot = 0; + const QScrollBar *scrollBar = orientation == Qt::Horizontal + ? view.horizontalScrollBar() + : view.verticalScrollBar(); + // Drag the item until the scroll bars become visible, and then for a few more pixels. + // Verify that the item doesn't jump when the scrollbar shows. + while (overshoot < 10) { + if (orientation == Qt::Horizontal) + mousePos.rx() += 1; + else + mousePos.ry() += 1; + QTest::mouseMove(view.viewport(), mousePos); + QApplication::processEvents(); // queued connection used to trigger recalculateContentSize + const bool scrollbarAvailable = scrollBar->maximum() > scrollBar->minimum(); + bool allowMoreEvents = false; + if (scrollbarAvailable) { + if (!overshoot) { + QTRY_VERIFY(scrollBar->isVisible()); + // scrollbar becoming visible triggers event replay, so we get more than one + allowMoreEvents = true; + } + ++overshoot; + } + if (allowMoreEvents) + QCOMPARE_GE(item.scenePositions.count(), 1); + else + QCOMPARE(item.scenePositions.count(), 1); + const auto scenePos = item.scenePositions.takeLast(); + item.scenePositions.clear(); + + const auto same = orientation == Qt::Horizontal ? &QPointF::y : &QPointF::x; + const auto moved = orientation == Qt::Horizontal ? &QPointF::x : &QPointF::y; + QCOMPARE((item.pos().*same)(), (lastItemPos.*same)()); + QCOMPARE_GE((item.pos().*moved)() - (lastItemPos.*moved)(), 1); + QCOMPARE_LE((item.pos().*moved)() - (lastItemPos.*moved)(), 2); + lastItemPos = item.pos(); + + QCOMPARE((scenePos.*same)(), (lastScenePos.*same)()); + QCOMPARE_GE((scenePos.*moved)() - (lastScenePos.*moved)(), 1); + QCOMPARE_LE((scenePos.*moved)() - (lastScenePos.*moved)(), 2); + lastScenePos = scenePos; + } +} + QTEST_MAIN(tst_QGraphicsView) #include "tst_qgraphicsview.moc" diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.h b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.h index 9fd35b325b..2fb5ed638c 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.h +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef TST_QGRAPHICSVIEW_H #define TST_QGRAPHICSVIEW_H diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp index 9e9a4093ba..1380e007e7 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QtCore/QSize> #include <QtCore/QRectF> diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/CMakeLists.txt b/tests/auto/widgets/graphicsview/qgraphicswidget/CMakeLists.txt index 45c7c09f63..42e30e4f5d 100644 --- a/tests/auto/widgets/graphicsview/qgraphicswidget/CMakeLists.txt +++ b/tests/auto/widgets/graphicsview/qgraphicswidget/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgraphicswidget.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgraphicswidget Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgraphicswidget LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgraphicswidget SOURCES tst_qgraphicswidget.cpp diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp index fedb82e641..9fd93ca91d 100644 --- a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -18,6 +18,8 @@ #include <qscreen.h> #include <qsignalspy.h> +#include <QtWidgets/private/qapplication_p.h> + typedef QList<QGraphicsItem *> QGraphicsItemList; class EventSpy : public QObject @@ -144,8 +146,16 @@ private slots: void QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems(); void QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems(); void QTBUG_45867_send_itemChildAddedChange_to_parent(); + +private: + static bool hasWindowActivation(); }; +bool tst_QGraphicsWidget::hasWindowActivation() +{ + return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)); +} + // Subclass that exposes the protected functions. class SubQGraphicsWidget : public QGraphicsWidget { public: @@ -940,9 +950,9 @@ void tst_QGraphicsWidget::geometry() widget.setPos(pos); widget.resize(size); if (!size.isNull() && !pos.isNull()) - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); if (!size.isNull() && pos.isNull()) - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(widget.geometry(), QRectF(pos, size)); } @@ -953,10 +963,10 @@ void tst_QGraphicsWidget::geometryChanged() QCOMPARE(w.geometry(), QRectF(0, 0, 200, 200)); QSignalSpy spy(&w, SIGNAL(geometryChanged())); w.setGeometry(0, 0, 100, 100); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(w.geometry(), QRectF(0, 0, 100, 100)); w.setPos(10, 10); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); QCOMPARE(w.geometry(), QRectF(10, 10, 100, 100)); } @@ -968,10 +978,10 @@ void tst_QGraphicsWidget::width() QSignalSpy spy(&w, SIGNAL(widthChanged())); w.setProperty("width", qreal(50)); QCOMPARE(w.property("width").toReal(), qreal(50)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); //calling old school setGeometry should work too w.setGeometry(0, 0, 200, 200); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); } void tst_QGraphicsWidget::height() @@ -981,10 +991,10 @@ void tst_QGraphicsWidget::height() QSignalSpy spy(&w, SIGNAL(heightChanged())); w.setProperty("height", qreal(50)); QCOMPARE(w.property("height").toReal(), qreal(50)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); //calling old school setGeometry should work too w.setGeometry(0, 0, 200, 200); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); } void tst_QGraphicsWidget::getContentsMargins_data() @@ -1049,7 +1059,10 @@ void tst_QGraphicsWidget::initStyleOption() QGraphicsView view(&scene); view.resize(300, 300); view.show(); - QVERIFY(QTest::qWaitForWindowActive(&view)); + if (hasWindowActivation()) + QVERIFY(QTest::qWaitForWindowActive(&view)); + else + QVERIFY(QTest::qWaitForWindowExposed(&view)); view.setAlignment(Qt::AlignTop | Qt::AlignLeft); SubQGraphicsWidget *widget = new SubQGraphicsWidget; @@ -1063,10 +1076,12 @@ void tst_QGraphicsWidget::initStyleOption() QFETCH(bool, enabled); widget->setEnabled(enabled); QFETCH(bool, focus); - if (focus) { - widget->setFlag(QGraphicsItem::ItemIsFocusable, true); - widget->setFocus(); - QVERIFY(widget->hasFocus()); + if (hasWindowActivation()) { + if (focus) { + widget->setFlag(QGraphicsItem::ItemIsFocusable, true); + widget->setFocus(); + QVERIFY(widget->hasFocus()); + } } QFETCH(bool, underMouse); if (underMouse) { @@ -1085,8 +1100,10 @@ void tst_QGraphicsWidget::initStyleOption() bool isEnabled = option.state & QStyle::State_Enabled; QCOMPARE(isEnabled, enabled); - bool hasFocus = option.state & QStyle::State_HasFocus; - QCOMPARE(hasFocus, focus); + if (hasWindowActivation()) { + bool hasFocus = option.state & QStyle::State_HasFocus; + QCOMPARE(hasFocus, focus); + } bool isUnderMouse = option.state & QStyle::State_MouseOver; QCOMPARE(isUnderMouse, underMouse); // if (layoutDirection != Qt::LeftToRight) @@ -1123,12 +1140,12 @@ void tst_QGraphicsWidget::layout() widget.setLayout(layout); QTRY_COMPARE(widget.layout(), static_cast<QGraphicsLayout*>(layout)); - for (int i = 0; i < children.count(); ++i) { + for (int i = 0; i < children.size(); ++i) { SubQGraphicsWidget *item = children[i]; QCOMPARE(item->parentWidget(), (QGraphicsWidget *)&widget); QVERIFY(item->geometry() != QRectF(0, 0, -1, -1)); } - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); // don't crash widget.setLayout(0); } @@ -1161,7 +1178,7 @@ void tst_QGraphicsWidget::layoutDirection() QCOMPARE(widget.testAttribute(Qt::WA_SetLayoutDirection), true); view->show(); QVERIFY(QTest::qWaitForWindowExposed(view.data())); - for (int i = 0; i < children.count(); ++i) { + for (int i = 0; i < children.size(); ++i) { QTRY_COMPARE(children[i]->layoutDirection(), layoutDirection); QTRY_COMPARE(children[i]->testAttribute(Qt::WA_SetLayoutDirection), false); view->update(); @@ -1371,7 +1388,6 @@ void tst_QGraphicsWidget::setTabOrder() QGraphicsScene scene; QGraphicsView view(&scene); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QGraphicsWidget *lastItem = nullptr; @@ -1399,7 +1415,7 @@ void tst_QGraphicsWidget::setTabOrder() QVERIFY(view.viewport()->hasFocus()); int currentItem = 0; - while (currentItem < children.count() - 1) { + while (currentItem < children.size() - 1) { QTest::keyPress(view.viewport(), Qt::Key_Tab); ++currentItem; QVERIFY(children[currentItem % children.size()]->hasFocus()); @@ -1443,7 +1459,6 @@ void tst_QGraphicsWidget::setTabOrderAndReparent() QGraphicsScene scene; QGraphicsView view(&scene); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(QApplication::activeWindow(), (QWidget*)&view); @@ -1548,7 +1563,7 @@ void tst_QGraphicsWidget::unsetLayoutDirection() widget.setLayoutDirection(layoutDirection); widget.unsetLayoutDirection(); QCOMPARE(widget.testAttribute(Qt::WA_SetLayoutDirection), false); - for (int i = 0; i < children.count(); ++i) { + for (int i = 0; i < children.size(); ++i) { QCOMPARE(children[i]->layoutDirection(), Qt::LeftToRight); } } @@ -1573,7 +1588,6 @@ void tst_QGraphicsWidget::verifyFocusChain() QGraphicsScene scene; QGraphicsView view(&scene); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); { @@ -1665,7 +1679,6 @@ void tst_QGraphicsWidget::verifyFocusChain() w1_2->setFocusPolicy(Qt::StrongFocus); scene.addItem(w1_2); window->show(); - QApplication::setActiveWindow(window.data()); QVERIFY(QTest::qWaitForWindowActive(window.data())); lineEdit->setFocus(); @@ -1713,13 +1726,16 @@ void tst_QGraphicsWidget::verifyFocusChain() void tst_QGraphicsWidget::updateFocusChainWhenChildDie() { + if (!hasWindowActivation()) + QSKIP("Window activation is not supported"); + const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry(); QGraphicsScene scene; QGraphicsView view(&scene); view.resize(200, 150); view.move(availableGeometry.topLeft() + QPoint(50, 50)); view.show(); - QApplication::setActiveWindow(&view); + view.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&view)); // delete item in focus chain with no focus and verify chain @@ -1748,13 +1764,8 @@ void tst_QGraphicsWidget::updateFocusChainWhenChildDie() w->setParentItem(parent); //We don't crash perfect QVERIFY(w); - const QPoint center(view.viewport()->width() / 2, view.viewport()->height() / 2); - QTest::mouseMove(view.viewport(), center); - QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, center); -#ifdef Q_OS_MAC - QEXPECT_FAIL("", "QTBUG-23699", Continue); -#endif - QTRY_COMPARE(qApp->activeWindow(), static_cast<QWidget *>(&view)); + view.activateWindow(); + QVERIFY(QTest::qWaitForWindowActive(&view)); QTRY_COMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(w)); } @@ -1840,7 +1851,7 @@ enum WhichSize { MinimumSizeHint, PreferredSizeHint, MaximumSizeHint, - Size, + WidgetSize, None, }; @@ -1855,48 +1866,48 @@ void tst_QGraphicsWidget::setSizes_data() QTest::addColumn<QList<Inst>>("compareInstructions"); QTest::newRow("minSize1") << (QList<Inst>() - << Inst(Size, QSize(25, 25)) << Inst(MinimumSize, QSize(10, 10))) - << (QList<Inst>() << Inst(Size, QSize(25, 25))); - QTest::newRow("minSize2") << (QList<Inst>() << Inst(Size, QSizeF(20, 20)) + << Inst(WidgetSize, QSize(25, 25)) << Inst(MinimumSize, QSize(10, 10))) + << (QList<Inst>() << Inst(WidgetSize, QSize(25, 25))); + QTest::newRow("minSize2") << (QList<Inst>() << Inst(WidgetSize, QSizeF(20, 20)) << Inst(MinimumSize, QSizeF(25, 25))) - << (QList<Inst>() << Inst(Size, QSizeF(25, 25))); + << (QList<Inst>() << Inst(WidgetSize, QSizeF(25, 25))); QTest::newRow("minWidth1") << (QList<Inst>() - << Inst(Size, QSizeF(20, 20)) << Inst(MinimumWidth, 5.0)) - << (QList<Inst>() << Inst(Size, QSizeF(20, 20))); + << Inst(WidgetSize, QSizeF(20, 20)) << Inst(MinimumWidth, 5.0)) + << (QList<Inst>() << Inst(WidgetSize, QSizeF(20, 20))); QTest::newRow("minWidth2") << (QList<Inst>() - << Inst(Size, QSizeF(20, 20)) << Inst(MinimumWidth, 25.0)) - << (QList<Inst>() << Inst(Size, QSizeF(25, 20))); + << Inst(WidgetSize, QSizeF(20, 20)) << Inst(MinimumWidth, 25.0)) + << (QList<Inst>() << Inst(WidgetSize, QSizeF(25, 20))); QTest::newRow("minHeight1") << (QList<Inst>() - << Inst(Size, QSizeF(20, 20)) << Inst(MinimumHeight, 5.0)) - << (QList<Inst>() << Inst(Size, QSizeF(20, 20))); + << Inst(WidgetSize, QSizeF(20, 20)) << Inst(MinimumHeight, 5.0)) + << (QList<Inst>() << Inst(WidgetSize, QSizeF(20, 20))); QTest::newRow("minHeight2") << (QList<Inst>() - << Inst(Size, QSizeF(20, 20)) << Inst(MinimumHeight, 25.0)) - << (QList<Inst>() << Inst(Size, QSizeF(20, 25))); - QTest::newRow("maxSize1") << (QList<Inst>() << Inst(Size, QSizeF(40, 40)) + << Inst(WidgetSize, QSizeF(20, 20)) << Inst(MinimumHeight, 25.0)) + << (QList<Inst>() << Inst(WidgetSize, QSizeF(20, 25))); + QTest::newRow("maxSize1") << (QList<Inst>() << Inst(WidgetSize, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(30, 30))) - << (QList<Inst>() << Inst(Size, QSizeF(30, 30))); - QTest::newRow("maxSize2") << (QList<Inst>() << Inst(Size, QSizeF(40, 40)) + << (QList<Inst>() << Inst(WidgetSize, QSizeF(30, 30))); + QTest::newRow("maxSize2") << (QList<Inst>() << Inst(WidgetSize, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(30, -1))) - << (QList<Inst>() << Inst(Size, QSizeF(30, 40))); - QTest::newRow("maxSize3") << (QList<Inst>() << Inst(Size, QSizeF(40, 40)) + << (QList<Inst>() << Inst(WidgetSize, QSizeF(30, 40))); + QTest::newRow("maxSize3") << (QList<Inst>() << Inst(WidgetSize, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(-1, 30))) - << (QList<Inst>() << Inst(Size, QSizeF(40, 30))); + << (QList<Inst>() << Inst(WidgetSize, QSizeF(40, 30))); QTest::newRow("maxWidth1") << (QList<Inst>() - << Inst(Size, QSizeF(40, 40)) << Inst(MaximumWidth, 30)) - << (QList<Inst>() << Inst(Size, QSizeF(30, 40))); + << Inst(WidgetSize, QSizeF(40, 40)) << Inst(MaximumWidth, 30)) + << (QList<Inst>() << Inst(WidgetSize, QSizeF(30, 40))); QTest::newRow("maxHeight") << (QList<Inst>() - << Inst(Size, QSizeF(40, 40)) << Inst(MaximumHeight, 20)) - << (QList<Inst>() << Inst(Size, QSizeF(40, 20))); - QTest::newRow("unsetMinSize") << (QList<Inst>() << Inst(Size, QSizeF(40, 40)) + << Inst(WidgetSize, QSizeF(40, 40)) << Inst(MaximumHeight, 20)) + << (QList<Inst>() << Inst(WidgetSize, QSizeF(40, 20))); + QTest::newRow("unsetMinSize") << (QList<Inst>() << Inst(WidgetSize, QSizeF(40, 40)) << Inst(MinimumSize, QSizeF(-1, -1))) << (QList<Inst>() << Inst(MinimumSize, QSizeF(5, 5))); - QTest::newRow("unsetMaxSize") << (QList<Inst>() << Inst(Size, QSizeF(40, 40)) + QTest::newRow("unsetMaxSize") << (QList<Inst>() << Inst(WidgetSize, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(-1, -1))) << (QList<Inst>() << Inst(MaximumSize, QSizeF(500, 500))); QTest::newRow("unsetMinSize, expand size to minimumSizeHint") - << (QList<Inst>() << Inst(MinimumSize, QSize(0, 0)) << Inst(Size, QSize(1, 1)) + << (QList<Inst>() << Inst(MinimumSize, QSize(0, 0)) << Inst(WidgetSize, QSize(1, 1)) << Inst(MinimumSize, QSize(-1.0, -1.0))) - << (QList<Inst>() << Inst(Size, QSize(5, 5)) << Inst(MinimumSize, QSize(5, 5))); + << (QList<Inst>() << Inst(WidgetSize, QSize(5, 5)) << Inst(MinimumSize, QSize(5, 5))); } void tst_QGraphicsWidget::setSizes() @@ -1912,7 +1923,7 @@ void tst_QGraphicsWidget::setSizes() QSizeF max = QSizeF(50, 50); int i; - for (i = 0; i < inputInstructions.count(); ++i) { + for (i = 0; i < inputInstructions.size(); ++i) { Inst input = inputInstructions.at(i); // defaults @@ -1926,7 +1937,7 @@ void tst_QGraphicsWidget::setSizes() case MaximumSize: max = input.second.toSizeF(); break; - case Size: + case WidgetSize : widget->resize(input.second.toSizeF()); break; case MinimumWidth: @@ -1966,7 +1977,7 @@ void tst_QGraphicsWidget::setSizes() widget->setPreferredSize(pref); widget->setMaximumSize(max); - for (i = 0; i < compareInstructions.count(); ++i) { + for (i = 0; i < compareInstructions.size(); ++i) { Inst input = compareInstructions.at(i); switch (input.first) { case MinimumSize: @@ -1978,7 +1989,7 @@ void tst_QGraphicsWidget::setSizes() case MaximumSize: QTRY_COMPARE(widget->maximumSize(), input.second.toSizeF()); break; - case Size: + case WidgetSize: QTRY_COMPARE(widget->size(), input.second.toSizeF()); break; case MinimumWidth: @@ -2679,7 +2690,6 @@ void tst_QGraphicsWidget::task250119_shortcutContext() QGraphicsView view; view.setScene(&scene); view.show(); - QApplication::setActiveWindow(&view); QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view); @@ -2716,11 +2726,11 @@ void tst_QGraphicsWidget::task250119_shortcutContext() w_signal.setFocus(); QTest::keyPress(&view, Qt::Key_B); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); w_signal.clearFocus(); QTest::keyPress(&view, Qt::Key_B); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); scene.removeItem(&w_signal); } diff --git a/tests/auto/widgets/itemviews/CMakeLists.txt b/tests/auto/widgets/itemviews/CMakeLists.txt index 2ea705c922..60e05fadb4 100644 --- a/tests/auto/widgets/itemviews/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/CMakeLists.txt @@ -1,7 +1,5 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from itemviews.pro. +# SPDX-License-Identifier: BSD-3-Clause add_subdirectory(qabstractitemview) add_subdirectory(qdatawidgetmapper) diff --git a/tests/auto/widgets/itemviews/qabstractitemview/BLACKLIST b/tests/auto/widgets/itemviews/qabstractitemview/BLACKLIST index e69de29bb2..778a25b2e4 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/BLACKLIST +++ b/tests/auto/widgets/itemviews/qabstractitemview/BLACKLIST @@ -0,0 +1,4 @@ +[focusNextOnHide] +wayland +[selectionAutoScrolling] +wayland diff --git a/tests/auto/widgets/itemviews/qabstractitemview/CMakeLists.txt b/tests/auto/widgets/itemviews/qabstractitemview/CMakeLists.txt index 00f3ccb690..ca39501a95 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qabstractitemview/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qabstractitemview.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qabstractitemview Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qabstractitemview LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qabstractitemview SOURCES tst_qabstractitemview.cpp diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index 6a99772c53..4f2495375d 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <private/qguiapplication_p.h> @@ -30,6 +30,7 @@ #include <QVBoxLayout> #include <QtTest/private/qtesthelpers_p.h> #include <private/qabstractitemview_p.h> +#include <QtWidgets/private/qapplication_p.h> Q_DECLARE_METATYPE(Qt::ItemFlags); @@ -108,6 +109,7 @@ private slots: void QTBUG6407_extendedSelection(); void QTBUG6753_selectOnSelection(); void testDelegateDestroyEditor(); + void testDelegateDestroyEditorChild(); void testClickedSignal(); void testChangeEditorState(); void deselectInSingleSelection(); @@ -140,11 +142,16 @@ private slots: void selectionCommand(); void mouseSelection_data(); void mouseSelection(); + void keepSingleSelectionOnEmptyAreaClick(); void scrollerSmoothScroll(); void inputMethodOpensEditor_data(); void inputMethodOpensEditor(); void selectionAutoScrolling_data(); void selectionAutoScrolling(); + void testSpinBoxAsEditor_data(); + void testSpinBoxAsEditor(); + void removeIndexWhileEditing(); + void focusNextOnHide(); private: static QAbstractItemView *viewFromString(const QByteArray &viewType, QWidget *parent = nullptr) @@ -171,17 +178,19 @@ public: QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const override { openedEditor = new QWidget(parent); + virtualCtorCallCount++; return openedEditor; } void destroyEditor(QWidget *editor, const QModelIndex &) const override { - calledVirtualDtor = true; + virtualDtorCallCount++; editor->deleteLater(); } void changeSize() { size = QSize(50, 50); emit sizeHintChanged(QModelIndex()); } mutable QWidget *openedEditor = nullptr; QSize size; - mutable bool calledVirtualDtor = false; + mutable int virtualCtorCallCount = 0; + mutable int virtualDtorCallCount = 0; }; class DialogItemDelegate : public QStyledItemDelegate @@ -424,12 +433,12 @@ void tst_QAbstractItemView::basic_tests(QAbstractItemView *view) QVERIFY(spy.isValid()); view->setIconSize(QSize(32, 32)); QCOMPARE(view->iconSize(), QSize(32, 32)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).value<QSize>(), QSize(32, 32)); // Should this happen? view->setIconSize(QSize(-1, -1)); QCOMPARE(view->iconSize(), QSize(-1, -1)); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); QCOMPARE(view->currentIndex(), QModelIndex()); QCOMPARE(view->rootIndex(), QModelIndex()); @@ -663,9 +672,9 @@ void tst_QAbstractItemView::selectAll() GeometriesTestView view; view.setModel(&model); - QCOMPARE(view.selectedIndexes().count(), 0); + QCOMPARE(view.selectedIndexes().size(), 0); view.selectAll(); - QCOMPARE(view.selectedIndexes().count(), 4 * 4); + QCOMPARE(view.selectedIndexes().size(), 4 * 4); } void tst_QAbstractItemView::ctrlA() @@ -674,9 +683,9 @@ void tst_QAbstractItemView::ctrlA() GeometriesTestView view; view.setModel(&model); - QCOMPARE(view.selectedIndexes().count(), 0); + QCOMPARE(view.selectedIndexes().size(), 0); QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier); - QCOMPARE(view.selectedIndexes().count(), 4 * 4); + QCOMPARE(view.selectedIndexes().size(), 4 * 4); } void tst_QAbstractItemView::persistentEditorFocus() @@ -693,7 +702,7 @@ void tst_QAbstractItemView::persistentEditorFocus() //these are spinboxes because we put numbers inside const QList<QSpinBox*> list = view.viewport()->findChildren<QSpinBox*>(); - QCOMPARE(list.count(), 2); //these should be the 2 editors + QCOMPARE(list.size(), 2); //these should be the 2 editors view.setCurrentIndex(model.index(0, 0)); QCOMPARE(view.currentIndex(), model.index(0, 0)); @@ -753,22 +762,6 @@ void tst_QAbstractItemView::pressClosesReleaseDoesntOpenEditor() QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, inChildOutsideEditor); // should not reopen editor QTest::qWait(QApplication::doubleClickInterval() * 2); QCOMPARE(view.state(), QAbstractItemView::NoState); - - // with multiple items selected, clicking from the currently edited item into another - // selected item closes the current and reopens a new editor - view.setSelectionMode(QAbstractItemView::ExtendedSelection); - const QRect child2Rect = view.visualRect(model.indexFromItem(parent->child(1))); - QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, child2Rect.center()); // select - QVERIFY(view.selectionModel()->selectedIndexes().contains(model.indexFromItem(parent->child(0)))); - QVERIFY(view.selectionModel()->selectedIndexes().contains(model.indexFromItem(parent->child(1)))); - QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, child2Rect.center()); // edit - QTRY_COMPARE(view.state(), QAbstractItemView::EditingState); - QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, inChildOutsideEditor); // editor closes - QCOMPARE(view.state(), QAbstractItemView::NoState); - QTest::qWait(10); // process some events, let the internal timer time out - QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, inChildOutsideEditor); // should open editor - QTest::qWait(QApplication::doubleClickInterval() * 2); - QCOMPARE(view.state(), QAbstractItemView::EditingState); } @@ -1058,7 +1051,6 @@ void tst_QAbstractItemView::setItemDelegate() centerOnScreen(&v); moveCursorAway(&v); v.show(); - QApplication::setActiveWindow(&v); QVERIFY(QTest::qWaitForWindowActive(&v)); QModelIndex index = model.index(cellToEdit.y(), cellToEdit.x()); @@ -1267,7 +1259,6 @@ void tst_QAbstractItemView::task221955_selectedEditor() tree.show(); tree.setFocus(); tree.setCurrentIndex(tree.model()->index(1,0)); - QApplication::setActiveWindow(&tree); QVERIFY(QTest::qWaitForWindowActive(&tree)); QVERIFY(! tree.selectionModel()->selectedIndexes().contains(tree.model()->index(3,0))); @@ -1354,7 +1345,7 @@ void tst_QAbstractItemView::task200665_itemEntered() QSignalSpy spy(&view, &QAbstractItemView::entered); view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum()); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); } void tst_QAbstractItemView::task257481_emptyEditor() @@ -1377,17 +1368,17 @@ void tst_QAbstractItemView::task257481_emptyEditor() treeView.edit(model.index(0, 0)); QList<QLineEdit *> lineEditors = treeView.viewport()->findChildren<QLineEdit *>(); - QCOMPARE(lineEditors.count(), 1); + QCOMPARE(lineEditors.size(), 1); QVERIFY(!lineEditors.constFirst()->size().isEmpty()); treeView.edit(model.index(1, 0)); lineEditors = treeView.viewport()->findChildren<QLineEdit *>(); - QCOMPARE(lineEditors.count(), 1); + QCOMPARE(lineEditors.size(), 1); QVERIFY(!lineEditors.constFirst()->size().isEmpty()); treeView.edit(model.index(2, 0)); lineEditors = treeView.viewport()->findChildren<QLineEdit *>(); - QCOMPARE(lineEditors.count(), 1); + QCOMPARE(lineEditors.size(), 1); QVERIFY(!lineEditors.constFirst()->size().isEmpty()); } @@ -1421,7 +1412,7 @@ void tst_QAbstractItemView::shiftArrowSelectionAfterScrolling() QCOMPARE(view.currentIndex(), index1); QModelIndexList selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 2); + QCOMPARE(selected.size(), 2); QVERIFY(selected.contains(index0)); QVERIFY(selected.contains(index1)); } @@ -1475,7 +1466,7 @@ void tst_QAbstractItemView::shiftSelectionAfterRubberbandSelection() // Verify that the selection worked OK QModelIndexList selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 2); + QCOMPARE(selected.size(), 2); QVERIFY(selected.contains(index1)); QVERIFY(selected.contains(index2)); @@ -1498,7 +1489,7 @@ void tst_QAbstractItemView::shiftSelectionAfterRubberbandSelection() // Verify that the selection worked OK selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 2); + QCOMPARE(selected.size(), 2); QVERIFY(selected.contains(index1)); QVERIFY(selected.contains(index2)); } @@ -1527,7 +1518,7 @@ void tst_QAbstractItemView::ctrlRubberbandSelection() // Select item 1 view.setCurrentIndex(index1); QModelIndexList selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 1); + QCOMPARE(selected.size(), 1); QVERIFY(selected.contains(index1)); // Now press control and draw a rubberband around items 1 and 2. @@ -1544,7 +1535,7 @@ void tst_QAbstractItemView::ctrlRubberbandSelection() // Verify that item 2 is selected now selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 1); + QCOMPARE(selected.size(), 1); QVERIFY(selected.contains(index2)); } @@ -1566,7 +1557,6 @@ void tst_QAbstractItemView::QTBUG6407_extendedSelection() moveCursorAway(&view); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(&view, QApplication::activeWindow()); @@ -1577,21 +1567,21 @@ void tst_QAbstractItemView::QTBUG6407_extendedSelection() QVERIFY(view.viewport()->rect().contains(p)); QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, p); QCOMPARE(view.currentIndex(), index49); - QCOMPARE(view.selectedItems().count(), 1); + QCOMPARE(view.selectedItems().size(), 1); QModelIndex index47 = view.model()->index(47,0); p = view.visualRect(index47).center(); QVERIFY(view.viewport()->rect().contains(p)); QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, p); QCOMPARE(view.currentIndex(), index47); - QCOMPARE(view.selectedItems().count(), 3); //49, 48, 47; + QCOMPARE(view.selectedItems().size(), 3); //49, 48, 47; QModelIndex index44 = view.model()->index(44,0); p = view.visualRect(index44).center(); QVERIFY(view.viewport()->rect().contains(p)); QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, p); QCOMPARE(view.currentIndex(), index44); - QCOMPARE(view.selectedItems().count(), 6); //49 .. 44; + QCOMPARE(view.selectedItems().size(), 6); //49 .. 44; } @@ -1616,7 +1606,7 @@ void tst_QAbstractItemView::QTBUG6753_selectOnSelection() QTest::mouseMove(table.viewport(), itemRect.center()); QTest::mouseClick(table.viewport(), Qt::LeftButton, Qt::NoModifier, itemRect.center()); - QCOMPARE(table.selectedItems().count(), 1); + QCOMPARE(table.selectedItems().size(), 1); QCOMPARE(table.selectedItems().first(), table.item(item.row(), item.column())); } @@ -1627,9 +1617,31 @@ void tst_QAbstractItemView::testDelegateDestroyEditor() table.setItemDelegate(&delegate); table.edit(table.model()->index(1, 1)); QAbstractItemView *tv = &table; - QVERIFY(!delegate.calledVirtualDtor); + QCOMPARE(delegate.virtualDtorCallCount, 0); tv->closeEditor(delegate.openedEditor, QAbstractItemDelegate::NoHint); - QVERIFY(delegate.calledVirtualDtor); + QCOMPARE(delegate.virtualDtorCallCount, 1); +} + +void tst_QAbstractItemView::testDelegateDestroyEditorChild() +{ + QTreeWidget tree; + MyAbstractItemDelegate delegate; + tree.setItemDelegate(&delegate); + QTreeWidgetItem *topLevel = new QTreeWidgetItem; + QTreeWidgetItem *levelOne1 = new QTreeWidgetItem(topLevel); + QTreeWidgetItem *levelTwo1 = new QTreeWidgetItem(levelOne1); + QTreeWidgetItem *levelOne2 = new QTreeWidgetItem(topLevel); + QTreeWidgetItem *levelTwo2 = new QTreeWidgetItem(levelOne2); + tree.insertTopLevelItem(0, topLevel); + tree.openPersistentEditor(levelOne1); + tree.openPersistentEditor(levelTwo1); + tree.openPersistentEditor(levelOne2); + tree.openPersistentEditor(levelTwo2); + QCOMPARE(delegate.virtualCtorCallCount, 4); + levelOne1->removeChild(levelTwo1); + QCOMPARE(delegate.virtualDtorCallCount, 1); + topLevel->removeChild(levelOne2); + QCOMPARE(delegate.virtualDtorCallCount, 3); } void tst_QAbstractItemView::testClickedSignal() @@ -1642,7 +1654,6 @@ void tst_QAbstractItemView::testClickedSignal() centerOnScreen(&view); moveCursorAway(&view); view.showNormal(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(&view, QApplication::activeWindow()); @@ -1653,12 +1664,12 @@ void tst_QAbstractItemView::testClickedSignal() QSignalSpy clickedSpy(&view, &QTableWidget::clicked); QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, p); - QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.size(), 1); QTest::mouseClick(view.viewport(), Qt::RightButton, {}, p); // We expect that right-clicks do not cause the clicked() signal to // be emitted. - QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.size(), 1); } @@ -1693,7 +1704,6 @@ void tst_QAbstractItemView::testChangeEditorState() centerOnScreen(&view); moveCursorAway(&view); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(&view, QApplication::activeWindow()); @@ -1714,7 +1724,6 @@ void tst_QAbstractItemView::deselectInSingleSelection() QVERIFY(QTest::qWaitForWindowExposed(&view)); view.setSelectionMode(QAbstractItemView::SingleSelection); view.setEditTriggers(QAbstractItemView::NoEditTriggers); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowExposed(&view)); // mouse QModelIndex index22 = s.index(2, 2); @@ -1722,28 +1731,28 @@ void tst_QAbstractItemView::deselectInSingleSelection() QPoint clickpos = rect22.center(); QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, clickpos); QCOMPARE(view.currentIndex(), index22); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, clickpos); QCOMPARE(view.currentIndex(), index22); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 0); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 0); // second click with modifier however does select QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, clickpos); QCOMPARE(view.currentIndex(), index22); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); // keyboard QTest::keyClick(&view, Qt::Key_Space, Qt::NoModifier); QCOMPARE(view.currentIndex(), index22); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); QTest::keyClick(&view, Qt::Key_Space, Qt::ControlModifier); QCOMPARE(view.currentIndex(), index22); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 0); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 0); // second keypress with modifier however does select QTest::keyClick(&view, Qt::Key_Space, Qt::ControlModifier); QCOMPARE(view.currentIndex(), index22); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); } void tst_QAbstractItemView::testNoActivateOnDisabledItem() @@ -1761,7 +1770,6 @@ void tst_QAbstractItemView::testNoActivateOnDisabledItem() moveCursorAway(&treeView); treeView.show(); - QApplication::setActiveWindow(&treeView); QVERIFY(QTest::qWaitForWindowActive(&treeView)); QSignalSpy activatedSpy(&treeView, &QAbstractItemView::activated); @@ -1771,7 +1779,7 @@ void tst_QAbstractItemView::testNoActivateOnDisabledItem() QPoint clickPos = treeView.visualRect(itemIndex).center(); QTest::mouseClick(treeView.viewport(), Qt::LeftButton, {}, clickPos); - QCOMPARE(activatedSpy.count(), 0); + QCOMPARE(activatedSpy.size(), 0); } void tst_QAbstractItemView::testFocusPolicy_data() @@ -1808,7 +1816,6 @@ void tst_QAbstractItemView::testFocusPolicy() moveCursorAway(&window); window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); // itemview accepts focus => editor is closed => return focus to the itemview @@ -1846,7 +1853,6 @@ void tst_QAbstractItemView::QTBUG31411_noSelection() moveCursorAway(&window); window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); qRegisterMetaType<QItemSelection>(); @@ -1865,7 +1871,7 @@ void tst_QAbstractItemView::QTBUG31411_noSelection() QVERIFY(editor2); QTest::keyClick(editor2, Qt::Key_Escape, Qt::NoModifier); - QCOMPARE(selectionChangeSpy.count(), 0); + QCOMPARE(selectionChangeSpy.size(), 0); } void tst_QAbstractItemView::QTBUG39324_settingSameInstanceOfIndexWidget() @@ -1907,7 +1913,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() // Click "C" QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(indexC).center()); QModelIndexList selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 1); + QCOMPARE(selected.size(), 1); QVERIFY(selected.contains(indexC)); // Insert new item "B1" @@ -1917,14 +1923,14 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() // Shift-click "D" -> we expect that "C" and "D" are selected QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, view.visualRect(indexD).center()); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 2); + QCOMPARE(selected.size(), 2); QVERIFY(selected.contains(indexC)); QVERIFY(selected.contains(indexD)); // Click "D" QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(indexD).center()); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 1); + QCOMPARE(selected.size(), 1); QVERIFY(selected.contains(indexD)); // Remove items "B" and "C" @@ -1936,7 +1942,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() // Shift-click "F" -> we expect that "D", "E", and "F" are selected QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, view.visualRect(indexF).center()); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 3); + QCOMPARE(selected.size(), 3); QVERIFY(selected.contains(indexD)); QVERIFY(selected.contains(indexE)); QVERIFY(selected.contains(indexF)); @@ -1945,7 +1951,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() while (view.currentIndex() != indexA) QTest::keyClick(&view, Qt::Key_Up); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 1); + QCOMPARE(selected.size(), 1); QVERIFY(selected.contains(indexA)); // Change the sort order @@ -1954,7 +1960,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() // Shift-click "F" -> All items should be selected QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, view.visualRect(indexF).center()); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), model.rowCount()); + QCOMPARE(selected.size(), model.rowCount()); // Restore the old sort order proxyModel.sort(0, Qt::AscendingOrder); @@ -1962,7 +1968,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() // Click "D" QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(indexD).center()); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 1); + QCOMPARE(selected.size(), 1); QVERIFY(selected.contains(indexD)); // Insert new item "B2" @@ -1972,7 +1978,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() // Press Shift+Down -> "D" and "E" should be selected. QTest::keyClick(&view, Qt::Key_Down, Qt::ShiftModifier); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 2); + QCOMPARE(selected.size(), 2); QVERIFY(selected.contains(indexD)); QVERIFY(selected.contains(indexE)); @@ -1981,7 +1987,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, view.visualRect(indexA).center()); view.setCurrentIndex(indexD); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 1); + QCOMPARE(selected.size(), 1); QVERIFY(selected.contains(indexD)); // Insert new item "B3" @@ -1991,7 +1997,7 @@ void tst_QAbstractItemView::shiftSelectionAfterChangingModelContents() // Press Shift+Down -> "D" and "E" should be selected. QTest::keyClick(&view, Qt::Key_Down, Qt::ShiftModifier); selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 2); + QCOMPARE(selected.size(), 2); QVERIFY(selected.contains(indexD)); QVERIFY(selected.contains(indexE)); } @@ -2269,14 +2275,14 @@ void tst_QAbstractItemView::testClickToSelect() // Click the center of the visualRect of item "A" QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, centerA); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.back().front().value<QRect>(), QRect(centerA, QSize(1, 1))); // Click a point slightly away from the center const QPoint nearCenterA = centerA + QPoint(1, 1); QVERIFY(visualRectA.contains(nearCenterA)); QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, nearCenterA); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); QCOMPARE(spy.back().front().value<QRect>(), QRect(nearCenterA, QSize(1, 1))); } @@ -2446,15 +2452,11 @@ void tst_QAbstractItemView::inputMethodEnabled() // Check focus by switching the activation of the window to force a focus in view->setCurrentIndex(model->index(1, 0)); - QApplication::setActiveWindow(nullptr); - QApplication::setActiveWindow(view.data()); QVERIFY(QTest::qWaitForWindowActive(view.data())); QCOMPARE(view->testAttribute(Qt::WA_InputMethodEnabled), result); view->setCurrentIndex(QModelIndex()); QVERIFY(!view->testAttribute(Qt::WA_InputMethodEnabled)); - QApplication::setActiveWindow(nullptr); - QApplication::setActiveWindow(view.data()); QVERIFY(QTest::qWaitForWindowActive(view.data())); QModelIndex index = model->index(1, 0); QPoint p = view->visualRect(index).center(); @@ -2464,8 +2466,6 @@ void tst_QAbstractItemView::inputMethodEnabled() QCOMPARE(view->testAttribute(Qt::WA_InputMethodEnabled), result); index = model->index(0, 0); - QApplication::setActiveWindow(nullptr); - QApplication::setActiveWindow(view.data()); QVERIFY(QTest::qWaitForWindowActive(view.data())); p = view->visualRect(index).center(); QTest::mouseClick(view->viewport(), Qt::LeftButton, Qt::NoModifier, p); @@ -2475,11 +2475,11 @@ void tst_QAbstractItemView::inputMethodEnabled() // There is a case when it goes to the first visible item so we // make the flags of the first item match the ones we are testing // to check the attribute correctly - QApplication::setActiveWindow(nullptr); + QApplicationPrivate::setActiveWindow(nullptr); view->setCurrentIndex(QModelIndex()); view->reset(); item->setFlags(Qt::ItemFlags(itemFlags)); - QApplication::setActiveWindow(view.data()); + QApplicationPrivate::setActiveWindow(view.data()); QVERIFY(QTest::qWaitForWindowActive(view.data())); QCOMPARE(view->testAttribute(Qt::WA_InputMethodEnabled), result); } @@ -2590,11 +2590,11 @@ void tst_QAbstractItemView::checkFocusAfterActivationChanges() QVERIFY(QTest::qWaitForWindowExposed(delegate.openedEditor)); QVERIFY(delegate.openedEditor->hasFocus()); - QApplication::setActiveWindow(&otherTopLevel); + QApplicationPrivate::setActiveWindow(&otherTopLevel); otherTopLevel.setFocus(); QTRY_VERIFY(!delegate.openedEditor); - QApplication::setActiveWindow(&w); + QApplicationPrivate::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); QVERIFY(view->hasFocus()); } @@ -2634,7 +2634,7 @@ void tst_QAbstractItemView::dragSelectAfterNewPress() // Verify that the selection worked OK QModelIndexList selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 3); + QCOMPARE(selected.size(), 3); for (int i = 0; i < 2; ++i) QVERIFY(selected.contains(model.index(i, 0))); @@ -2651,18 +2651,19 @@ void tst_QAbstractItemView::dragSelectAfterNewPress() // Verify that the selection worked OK selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 6); + QCOMPARE(selected.size(), 6); for (int i = 0; i < 5; ++i) QVERIFY(selected.contains(model.index(i, 0))); } void tst_QAbstractItemView::dragWithSecondClick_data() { - QTest::addColumn<QString>("viewClass"); + QTest::addColumn<QByteArray>("viewClass"); QTest::addColumn<bool>("doubleClick"); - for (QString viewClass : {"QListView", "QTreeView"}) { - QTest::addRow("DoubleClick") << viewClass << true; - QTest::addRow("Two Single Clicks") << viewClass << false; + const QList<QByteArray> widgets { "QListView", "QTreeView" }; + for (const QByteArray &widget : widgets) { + QTest::newRow(widget + ": DoubleClick") << widget << true; + QTest::newRow(widget + ": Two Single Clicks") << widget << false; } } @@ -2691,7 +2692,7 @@ protected: void tst_QAbstractItemView::dragWithSecondClick() { - QFETCH(QString, viewClass); + QFETCH(QByteArray, viewClass); QFETCH(bool, doubleClick); QStandardItemModel model; @@ -2846,32 +2847,40 @@ void tst_QAbstractItemView::mouseSelection_data() { QTest::addColumn<QAbstractItemView::SelectionMode>("selectionMode"); QTest::addColumn<bool>("dragEnabled"); + QTest::addColumn<QAbstractItemView::EditTrigger>("editTrigger"); QTest::addColumn<QList<SelectionEvent>>("selectionEvents"); QTest::addColumn<QList<int>>("selectedRows"); // single selection mode - always one row selected, modifiers ignored QTest::addRow("Single:Press") << QAbstractItemView::SingleSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1)} << QList{1}; QTest::addRow("Single:Click") << QAbstractItemView::SingleSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent{SelectionEvent::Click, 1}} << QList{1}; QTest::addRow("Single:Press+Drag") << QAbstractItemView::SingleSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent{SelectionEvent::Move, 2}, SelectionEvent{SelectionEvent::Release}} << QList{2}; QTest::addRow("Single:Shift+Click") << QAbstractItemView::SingleSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent{SelectionEvent::Click, Qt::ShiftModifier, 2}} << QList{2}; QTest::addRow("Single:Press;Ctrl+Press") << QAbstractItemView::SingleSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent{SelectionEvent::Press, 3}, SelectionEvent{SelectionEvent::Press, Qt::ControlModifier, 3}} << QList{3}; QTest::addRow("Single:Ctrl+Click") << QAbstractItemView::SingleSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent{SelectionEvent::Click, Qt::ControlModifier, 3}} << QList{3}; QTest::addRow("Single:Click;Ctrl+Click") << QAbstractItemView::SingleSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent{SelectionEvent::Click, 3}, SelectionEvent{SelectionEvent::Click, Qt::ControlModifier, 3}} << QList<int>{}; @@ -2879,30 +2888,37 @@ void tst_QAbstractItemView::mouseSelection_data() // multi selection mode - selection toggles on press, selection can be drag-extended // modifiers ignored QTest::addRow("Multi:Press") << QAbstractItemView::MultiSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1)} << QList{1}; QTest::addRow("Multi:Press twice") << QAbstractItemView::MultiSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent(SelectionEvent::Press, 1)} << QList<int>{}; QTest::addRow("Multi:Press twice with drag enabled") << QAbstractItemView::MultiSelection << true + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Click, 1), SelectionEvent(SelectionEvent::Press, 1)} << QList{1}; QTest::addRow("Multi:Press and click with drag enabled") << QAbstractItemView::MultiSelection << true + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent(SelectionEvent::Click, 1)} << QList<int>{}; QTest::addRow("Multi:Press,Press") << QAbstractItemView::MultiSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 2), SelectionEvent(SelectionEvent::Press, 3)} << QList{2, 3}; QTest::addRow("Multi:Press,Drag") << QAbstractItemView::MultiSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent(SelectionEvent::Move, 5), SelectionEvent(SelectionEvent::Release)} << QList{1, 2, 3, 4, 5}; QTest::addRow("Multi:Press,Drag,Deselect") << QAbstractItemView::MultiSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent(SelectionEvent::Move, 5), SelectionEvent(SelectionEvent::Release), @@ -2910,6 +2926,7 @@ void tst_QAbstractItemView::mouseSelection_data() << QList{1, 2, 4, 5}; // drag-select a few indices; then drag-select a larger area that includes the first QTest::addRow("Multi:Press,Drag;Surround") << QAbstractItemView::MultiSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 3), SelectionEvent(SelectionEvent::Move, 5), SelectionEvent(SelectionEvent::Release), @@ -2919,6 +2936,7 @@ void tst_QAbstractItemView::mouseSelection_data() << QList{1, 2, 3, 4, 5, 6, 7, 8}; // drag-select a few indices; then try to select more starting with the last -> not working QTest::addRow("Multi:Press,Drag;Expand") << QAbstractItemView::MultiSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 3), SelectionEvent(SelectionEvent::Move, 5), SelectionEvent(SelectionEvent::Release), @@ -2929,6 +2947,7 @@ void tst_QAbstractItemView::mouseSelection_data() // Multi: Press-dragging a selection should not deselect #QTBUG-59888 QTest::addRow("Multi:Press-Drag selection") << QAbstractItemView::MultiSelection << true // with drag'n'drop enabled, we cannot drag a selection + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Click, 2), SelectionEvent(SelectionEvent::Click, 3), SelectionEvent(SelectionEvent::Click, 4), @@ -2941,42 +2960,51 @@ void tst_QAbstractItemView::mouseSelection_data() // Extended selection: Press selects a single item QTest::addRow("Extended:Press") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 3)} << QList{3}; QTest::addRow("Extended:Press twice") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 3), SelectionEvent(SelectionEvent::Press, 3)} << QList{3}; QTest::addRow("Extended:Press,Press") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 2), SelectionEvent(SelectionEvent::Press, 3)} << QList{3}; // Extended selection: press with Ctrl toggles item QTest::addRow("Extended:Press,Toggle") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 3), SelectionEvent(SelectionEvent::Click, Qt::ControlModifier, 3)} << QList<int>{}; QTest::addRow("Extended:Press,Add") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent(SelectionEvent::Click, Qt::ControlModifier, 3)} << QList{1, 3}; // Extended selection: Shift creates a range between first and last pressed QTest::addRow("Extended:Press,Range") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent(SelectionEvent::Press, Qt::ShiftModifier, 5)} << QList{1, 2, 3, 4, 5}; QTest::addRow("Extended:Press,Range,Fix Range") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 1), SelectionEvent(SelectionEvent::Press, Qt::ShiftModifier, 5), SelectionEvent(SelectionEvent::Press, Qt::ShiftModifier, 3)} << QList{1, 2, 3}; // Extended: dragging extends the selection QTest::addRow("Extended:Press,Drag") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 2), SelectionEvent(SelectionEvent::Move, 5)} << QList{2, 3, 4, 5}; // Extended: Ctrl+Press-dragging extends the selection QTest::addRow("Extended:Press,Drag;Ctrl-Press,Drag") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Press, 2), SelectionEvent(SelectionEvent::Move, 5), SelectionEvent(SelectionEvent::Release), @@ -2985,7 +3013,8 @@ void tst_QAbstractItemView::mouseSelection_data() SelectionEvent(SelectionEvent::Release, Qt::ControlModifier, 8)} << QList{2, 3, 4, 5, 6, 7, 8}; // Extended: Ctrl+Press-dragging in a selection should not deselect #QTBUG-59888 - QTest::addRow("Extended:Ctrl-Drag selection") << QAbstractItemView::ExtendedSelection << true + QTest::addRow("Extended:Ctrl-Drag selection,no deselect") << QAbstractItemView::ExtendedSelection << true + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Click, 2), SelectionEvent(SelectionEvent::Click, Qt::ShiftModifier, 5), SelectionEvent(SelectionEvent::Press, Qt::ControlModifier, 3), @@ -2995,6 +3024,7 @@ void tst_QAbstractItemView::mouseSelection_data() << QList{2, 3, 4, 5}; // Extended: Ctrl+Press-dragging with a selection extends, then drags #QTBUG-59888 QTest::addRow("Extended:Ctrl-Drag selection") << QAbstractItemView::ExtendedSelection << true + << QAbstractItemView::NoEditTriggers << QList{SelectionEvent(SelectionEvent::Click, 2), SelectionEvent(SelectionEvent::Click, Qt::ShiftModifier, 5), SelectionEvent(SelectionEvent::Press, Qt::ControlModifier, 6), @@ -3002,12 +3032,37 @@ void tst_QAbstractItemView::mouseSelection_data() // two moves needed because of distance and state logic in 7QAbstractItemView SelectionEvent(SelectionEvent::Move, Qt::ControlModifier, 8)} << QList{2, 3, 4, 5, 6}; + // Extended: when drag is enabled, click with Ctrl toggles item instead of editing # QTBUG-111131 + QTest::addRow("Extended:Click,Toggle,editable") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::SelectedClicked + << QList{SelectionEvent(SelectionEvent::Click, 3), + SelectionEvent(SelectionEvent::Click, Qt::ControlModifier, 3)} + << QList<int>{}; + QTest::addRow("Extended:Click,Toggle,dragable,editable") << QAbstractItemView::ExtendedSelection << true + << QAbstractItemView::SelectedClicked + << QList{SelectionEvent(SelectionEvent::Click, 3), + SelectionEvent(SelectionEvent::Click, Qt::ControlModifier, 3)} + << QList<int>{}; + // Extended: when drag is enabled, click on selected without Ctrl clears before editing + QTest::addRow("Extended:Range,Click,editable") << QAbstractItemView::ExtendedSelection << false + << QAbstractItemView::SelectedClicked + << QList{SelectionEvent(SelectionEvent::Click, 1), + SelectionEvent(SelectionEvent::Click, Qt::ShiftModifier, 3), + SelectionEvent(SelectionEvent::Click, 2)} + << QList<int>{2}; + QTest::addRow("Extended:Range,Click,dragable,editable") << QAbstractItemView::ExtendedSelection << true + << QAbstractItemView::SelectedClicked + << QList{SelectionEvent(SelectionEvent::Click, 1), + SelectionEvent(SelectionEvent::Click, Qt::ShiftModifier, 3), + SelectionEvent(SelectionEvent::Click, 2)} + << QList<int>{2}; } void tst_QAbstractItemView::mouseSelection() { QFETCH(QAbstractItemView::SelectionMode, selectionMode); QFETCH(bool, dragEnabled); + QFETCH(QAbstractItemView::EditTrigger, editTrigger); QFETCH(QList<SelectionEvent>, selectionEvents); QFETCH(QList<int>, selectedRows); @@ -3016,7 +3071,7 @@ void tst_QAbstractItemView::mouseSelection() for (int i = 0; i < 10; ++i) { QStandardItem *item = new QStandardItem(QString("item %0").arg(i)); item->setDragEnabled(dragEnabled); - item->setEditable(false); + item->setEditable(editTrigger != QAbstractItemView::NoEditTriggers); parentItem->appendRow(item); } @@ -3026,13 +3081,14 @@ void tst_QAbstractItemView::mouseSelection() view->setModel(&model); view->setDragEnabled(dragEnabled); view->setSelectionMode(selectionMode); + view->setEditTriggers(editTrigger); view->show(); QVERIFY(QTest::qWaitForWindowActive(view)); Qt::MouseButton buttonDown = Qt::NoButton; int targetRow = -1; QModelIndex pressedIndex; - for (const auto &event : qAsConst(selectionEvents)) { + for (const auto &event : std::as_const(selectionEvents)) { if (event.row != -1) targetRow = event.row; const QModelIndex targetIndex = model.index(targetRow, 0); @@ -3077,6 +3133,37 @@ void tst_QAbstractItemView::mouseSelection() } /*! + Make sure that when clicking on empty space in the view, we don't + unselect the current row. + QTBUG-105870 +*/ +void tst_QAbstractItemView::keepSingleSelectionOnEmptyAreaClick() +{ + QListWidget view; + view.setSelectionMode(QAbstractItemView::SingleSelection); + QListWidgetItem *lastItem; + for (int i = 0; i < 5; i++) + lastItem = new QListWidgetItem("item " + QString::number(i), &view); + + // Make widget large enough so that there is empty area below the last item + view.setFixedSize(300, 500); + view.show(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + // Select third row + view.setCurrentRow(2); + + // Click below the last row + QPoint targetPoint = view.visualItemRect(lastItem).bottomLeft(); + targetPoint += QPoint(10, 10); + + QTest::mouseClick(view.viewport(), Qt::MouseButton::LeftButton, Qt::NoModifier, targetPoint); + + QCOMPARE(view.currentRow(), 2); + QVERIFY(view.currentItem()->isSelected()); +} + +/*! Verify that scrolling an autoScroll enabled itemview with a QScroller produces a continuous, smooth scroll without any jumping around due to the currentItem negotiation between QAbstractItemView and QScroller. @@ -3084,6 +3171,9 @@ void tst_QAbstractItemView::mouseSelection() */ void tst_QAbstractItemView::scrollerSmoothScroll() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QListWidget view; view.setAutoScroll(true); view.setVerticalScrollMode(QListView::ScrollPerPixel); @@ -3153,6 +3243,9 @@ void tst_QAbstractItemView::inputMethodOpensEditor_data() void tst_QAbstractItemView::inputMethodOpensEditor() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QTableWidget tableWidget(50, 50); tableWidget.setEditTriggers(QAbstractItemView::AnyKeyPressed); for (int r = 0; r < 50; ++r) { @@ -3321,10 +3414,152 @@ void tst_QAbstractItemView::selectionAutoScrolling() QTRY_COMPARE(scrollBar->value(), 0); else QTRY_COMPARE(scrollBar->value(), scrollBar->maximum()); - QVERIFY(listview.selectionModel()->selectedIndexes().count() > 0); + QVERIFY(listview.selectionModel()->selectedIndexes().size() > 0); QTest::mouseRelease(listview.viewport(), Qt::LeftButton, Qt::NoModifier, dragPoint); } +class SpinBoxDelegate : public QStyledItemDelegate +{ +public: + using QStyledItemDelegate::QStyledItemDelegate; + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const override + { + QSpinBox *spinboxEditor = new QSpinBox(parent); + return spinboxEditor; + } + + void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override + { + if (QSpinBox *spin = qobject_cast<QSpinBox *>(editor)) { + model->setData(index, spin->value()); + } + } +}; + +void tst_QAbstractItemView::testSpinBoxAsEditor_data() +{ + QTest::addColumn<bool>("keyboardTracking"); + QTest::newRow("true") << true; + QTest::newRow("false")<< false; +} + +void tst_QAbstractItemView::testSpinBoxAsEditor() +{ + QFETCH(bool, keyboardTracking); + + QStandardItemModel model(2, 2); + SpinBoxDelegate delegate; + + QTableView view; + view.setModel(&model); + view.setItemDelegate(&delegate); + + view.setCurrentIndex(model.index(0, 1)); + view.openPersistentEditor(model.index(0, 1)); + const QList<QSpinBox *> list = view.viewport()->findChildren<QSpinBox *>(); + QCOMPARE(list.size(), 1); + QSpinBox *sb = list.first(); + QVERIFY(sb); + + sb->setKeyboardTracking(keyboardTracking); + + centerOnScreen(&view); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + QTRY_COMPARE(QApplication::focusWidget(), sb); + + QTest::keyClick(sb, Qt::Key_1, Qt::NoModifier); + QPoint clickpos = view.visualRect(model.index(0, 0)).center(); + QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, clickpos); + + QCOMPARE(model.data(model.index(0, 1)).toInt(), 1); +} + +void tst_QAbstractItemView::removeIndexWhileEditing() +{ + QTreeView view; + QStandardItemModel treeModel; + auto editableItem1 = new QStandardItem("aa"); + auto editableItem2 = new QStandardItem("ab"); + auto editableItem3 = new QStandardItem("ac"); + auto item = new QStandardItem("a"); + item->appendRow(editableItem1); + item->appendRow(editableItem2); + item->appendRow(editableItem3); + treeModel.setItem(0, 0, item); + QSortFilterProxyModel filterModel; + filterModel.setSourceModel(&treeModel); + view.setModel(&filterModel); + view.show(); + + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + view.setExpanded(item->index(), true); + + filterModel.setFilterRegularExpression("a.*"); + + QTest::failOnWarning(QRegularExpression("QAbstractItemView::closeEditor called with an editor " + "that does not belong to this view")); + + // Verify that we shut editing down cleanly if the index we are editing is + // filtered out after committing + { + const QModelIndex filteredIndex = filterModel.mapFromSource(editableItem1->index()); + QVERIFY(filteredIndex.isValid()); + view.edit(filteredIndex); + QCOMPARE(view.state(), QAbstractItemView::EditingState); + QTRY_VERIFY(QApplication::focusWidget()); + QPointer<QLineEdit> lineEdit = qobject_cast<QLineEdit *>(QApplication::focusWidget()); + QVERIFY(lineEdit); + lineEdit->setText("c"); + QTest::keyClick(lineEdit, Qt::Key_Enter); + QTRY_VERIFY(!lineEdit); + QCOMPARE(editableItem1->data(Qt::DisplayRole), "c"); + QCOMPARE(view.state(), QAbstractItemView::NoState); + } + + // If we change the filter while we edit, then we should clean up state as well + { + const QModelIndex filteredIndex = filterModel.mapFromSource(editableItem2->index()); + QVERIFY(filteredIndex.isValid()); + view.edit(filteredIndex); + QCOMPARE(view.state(), QAbstractItemView::EditingState); + QTRY_VERIFY(QApplication::focusWidget()); + QPointer<QLineEdit> lineEdit = qobject_cast<QLineEdit *>(QApplication::focusWidget()); + QVERIFY(lineEdit); + filterModel.setFilterFixedString("c"); + QVERIFY(!filterModel.mapFromSource(editableItem2->index()).isValid()); + QTRY_VERIFY(!lineEdit); + QCOMPARE(view.state(), QAbstractItemView::NoState); + } +} + +void tst_QAbstractItemView::focusNextOnHide() +{ + QWidget widget; + QTableWidget table(10, 10); + table.setTabKeyNavigation(true); + QLineEdit lineEdit; + + QHBoxLayout layout; + layout.addWidget(&table); + layout.addWidget(&lineEdit); + widget.setLayout(&layout); + + widget.setTabOrder({&table, &lineEdit}); + + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + QVERIFY(table.hasFocus()); + QCOMPARE(table.currentIndex(), table.model()->index(0, 0)); + QTest::keyPress(&table, Qt::Key_Tab); + QCOMPARE(table.currentIndex(), table.model()->index(0, 1)); + + table.hide(); + QCOMPARE(table.currentIndex(), table.model()->index(0, 1)); + QVERIFY(lineEdit.hasFocus()); +} QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc" diff --git a/tests/auto/widgets/itemviews/qcolumnview/CMakeLists.txt b/tests/auto/widgets/itemviews/qcolumnview/CMakeLists.txt index 4ca68de8c9..8cf19c703e 100644 --- a/tests/auto/widgets/itemviews/qcolumnview/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qcolumnview/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qcolumnview.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qcolumnview Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qcolumnview LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qcolumnview SOURCES ../../../../shared/fakedirmodel.h diff --git a/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp b/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp index 9c37e0af6d..1ff9973e00 100644 --- a/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp +++ b/tests/auto/widgets/itemviews/qcolumnview/tst_qcolumnview.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QColumnView> #include <QScrollBar> @@ -497,11 +497,11 @@ void tst_QColumnView::selectAll() view.setModel(&m_fakeDirModel); view.selectAll(); - QVERIFY(view.selectionModel()->selectedIndexes().count() >= 0); + QVERIFY(view.selectionModel()->selectedIndexes().size() >= 0); view.setCurrentIndex(m_fakeDirHomeIndex); view.selectAll(); - QVERIFY(view.selectionModel()->selectedIndexes().count() > 0); + QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); QModelIndex file; for (int i = 0; i < m_fakeDirModel.rowCount(m_fakeDirHomeIndex); ++i) { @@ -512,10 +512,10 @@ void tst_QColumnView::selectAll() } view.setCurrentIndex(file); view.selectAll(); - QVERIFY(view.selectionModel()->selectedIndexes().count() > 0); + QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); view.setCurrentIndex(QModelIndex()); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 0); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 0); } void tst_QColumnView::clicked() @@ -536,13 +536,13 @@ void tst_QColumnView::clicked() QPoint localPoint = view.visualRect(m_fakeDirHomeIndex).center(); QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, localPoint); - QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedSpy.size(), 1); QCoreApplication::processEvents(); if (sizeof(qreal) != sizeof(double)) QSKIP("Skipped due to rounding errors"); - for (int i = 0; i < view.createdColumns.count(); ++i) { + for (int i = 0; i < view.createdColumns.size(); ++i) { QAbstractItemView *column = view.createdColumns.at(i); if (column && column->selectionModel() && (column->rootIndex() == m_fakeDirHomeIndex)) QVERIFY(column->selectionModel()->selectedIndexes().isEmpty()); @@ -560,7 +560,7 @@ void tst_QColumnView::selectedColumns() QTest::qWait(ANIMATION_DELAY); - for (int i = 0; i < view.createdColumns.count(); ++i) { + for (int i = 0; i < view.createdColumns.size(); ++i) { QAbstractItemView *column = view.createdColumns.at(i); if (!column) continue; @@ -591,7 +591,7 @@ void tst_QColumnView::setSelectionModel() view.setSelectionModel(selectionModel); bool found = false; - for (int i = 0; i < view.createdColumns.count(); ++i) { + for (int i = 0; i < view.createdColumns.size(); ++i) { if (view.createdColumns.at(i)->selectionModel() == selectionModel) { found = true; break; @@ -631,7 +631,7 @@ void tst_QColumnView::moveGrip_basic() view.setMinimumWidth(200); grip->moveGrip(-800); QCOMPARE(view.width(), 200); - QCOMPARE(spy.count(), 5); + QCOMPARE(spy.size(), 5); } void tst_QColumnView::moveGrip_data() @@ -659,7 +659,7 @@ void tst_QColumnView::moveGrip() topLevel.show(); QVERIFY(QTest::qWaitForWindowActive(&topLevel)); - int columnNum = view.createdColumns.count() - 2; + int columnNum = view.createdColumns.size() - 2; QVERIFY(columnNum >= 0); const QObjectList list = view.createdColumns[columnNum]->children(); QColumnViewGrip *grip = nullptr; @@ -687,7 +687,7 @@ void tst_QColumnView::doubleClick() QCOMPARE(view.width(), 200); QTest::mouseDClick(grip, Qt::LeftButton); QCOMPARE(view.width(), view.sizeHint().width()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } void tst_QColumnView::gripMoved() @@ -711,7 +711,7 @@ void tst_QColumnView::gripMoved() QCoreApplication::processEvents(); QTest::mouseRelease(grip, Qt::LeftButton); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); QCOMPARE(view.width(), oldWidth + 65); } @@ -776,7 +776,7 @@ void tst_QColumnView::setPreviewWidget() void tst_QColumnView::sizes() { QColumnView view; - QCOMPARE(view.columnWidths().count(), 0); + QCOMPARE(view.columnWidths().size(), 0); const QList<int> newSizes{ 10, 4, 50, 6 }; @@ -787,16 +787,16 @@ void tst_QColumnView::sizes() view.setModel(&m_fakeDirModel); view.setCurrentIndex(m_fakeDirHomeIndex); - QList<int> postSizes = view.columnWidths().mid(0, newSizes.count()); - QCOMPARE(postSizes, newSizes.mid(0, postSizes.count())); + QList<int> postSizes = view.columnWidths().mid(0, newSizes.size()); + QCOMPARE(postSizes, newSizes.mid(0, postSizes.size())); - QVERIFY(view.columnWidths().count() > 1); + QVERIFY(view.columnWidths().size() > 1); QList<int> smallerSizes{ 6 }; view.setColumnWidths(smallerSizes); QList<int> expectedSizes = newSizes; expectedSizes[0] = 6; - postSizes = view.columnWidths().mid(0, newSizes.count()); - QCOMPARE(postSizes, expectedSizes.mid(0, postSizes.count())); + postSizes = view.columnWidths().mid(0, newSizes.size()); + QCOMPARE(postSizes, expectedSizes.mid(0, postSizes.size())); } void tst_QColumnView::rowDelegate() @@ -806,7 +806,7 @@ void tst_QColumnView::rowDelegate() view.setItemDelegateForRow(3, d); view.setModel(&m_fakeDirModel); - for (int i = 0; i < view.createdColumns.count(); ++i) { + for (int i = 0; i < view.createdColumns.size(); ++i) { QAbstractItemView *column = view.createdColumns.at(i); QCOMPARE(column->itemDelegateForRow(3), d); } @@ -956,7 +956,7 @@ void tst_QColumnView::dynamicModelChanges() model.appendRow(item); QVERIFY(QTest::qWaitForWindowExposed(&view)); //let the time for painting to occur - QTRY_COMPARE(delegate.paintedIndexes.count(), 1); + QTRY_COMPARE(delegate.paintedIndexes.size(), 1); QCOMPARE(*delegate.paintedIndexes.begin(), model.index(0,0)); } diff --git a/tests/auto/widgets/itemviews/qdatawidgetmapper/CMakeLists.txt b/tests/auto/widgets/itemviews/qdatawidgetmapper/CMakeLists.txt index bae69c5d76..e4b2c52fb2 100644 --- a/tests/auto/widgets/itemviews/qdatawidgetmapper/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qdatawidgetmapper/CMakeLists.txt @@ -1,16 +1,21 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qdatawidgetmapper.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qdatawidgetmapper Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qdatawidgetmapper LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qdatawidgetmapper SOURCES tst_qdatawidgetmapper.cpp LIBRARIES Qt::Gui Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/itemviews/qdatawidgetmapper/tst_qdatawidgetmapper.cpp b/tests/auto/widgets/itemviews/qdatawidgetmapper/tst_qdatawidgetmapper.cpp index 41db835f0f..c3527e4215 100644 --- a/tests/auto/widgets/itemviews/qdatawidgetmapper/tst_qdatawidgetmapper.cpp +++ b/tests/auto/widgets/itemviews/qdatawidgetmapper/tst_qdatawidgetmapper.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QComboBox> #include <QDataWidgetMapper> @@ -11,6 +11,8 @@ #include <QTextEdit> #include <QVBoxLayout> +#include <QtWidgets/private/qapplication_p.h> + class tst_QDataWidgetMapper: public QObject { Q_OBJECT @@ -252,22 +254,22 @@ void tst_QDataWidgetMapper::currentIndexChanged() QSignalSpy spy(&mapper, &QDataWidgetMapper::currentIndexChanged); mapper.toFirst(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.takeFirst().at(0).toInt(), 0); mapper.toNext(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.takeFirst().at(0).toInt(), 1); mapper.setCurrentIndex(7); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.takeFirst().at(0).toInt(), 7); mapper.setCurrentIndex(-1); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); mapper.setCurrentIndex(42); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QDataWidgetMapper::changingValues() @@ -418,27 +420,26 @@ void tst_QDataWidgetMapper::textEditDoesntChangeFocusOnTab_qtbug3305() container.show(); - QApplication::setActiveWindow(&container); QVERIFY(QTest::qWaitForWindowActive(&container)); int closeEditorSpyCount = 0; const QString textEditContents = textEdit->toPlainText(); - QCOMPARE(closeEditorSpy.count(), closeEditorSpyCount); + QCOMPARE(closeEditorSpy.size(), closeEditorSpyCount); QVERIFY(lineEdit->hasFocus()); QVERIFY(!textEdit->hasFocus()); // this will generate a closeEditor for the tab key, and another for the focus out QTest::keyClick(QApplication::focusWidget(), Qt::Key_Tab); closeEditorSpyCount += 2; - QTRY_COMPARE(closeEditorSpy.count(), closeEditorSpyCount); + QTRY_COMPARE(closeEditorSpy.size(), closeEditorSpyCount); QTRY_VERIFY(textEdit->hasFocus()); QVERIFY(!lineEdit->hasFocus()); // now that the text edit is focused, a tab keypress will insert a tab, not change focus QTest::keyClick(QApplication::focusWidget(), Qt::Key_Tab); - QTRY_COMPARE(closeEditorSpy.count(), closeEditorSpyCount); + QTRY_COMPARE(closeEditorSpy.size(), closeEditorSpyCount); QVERIFY(!lineEdit->hasFocus()); QVERIFY(textEdit->hasFocus()); @@ -449,7 +450,7 @@ void tst_QDataWidgetMapper::textEditDoesntChangeFocusOnTab_qtbug3305() QTRY_VERIFY(lineEdit->hasFocus()); QVERIFY(!textEdit->hasFocus()); ++closeEditorSpyCount; - QCOMPARE(closeEditorSpy.count(), closeEditorSpyCount); + QCOMPARE(closeEditorSpy.size(), closeEditorSpyCount); } QTEST_MAIN(tst_QDataWidgetMapper) diff --git a/tests/auto/widgets/itemviews/qfileiconprovider/CMakeLists.txt b/tests/auto/widgets/itemviews/qfileiconprovider/CMakeLists.txt index f4830e5011..88ded71aac 100644 --- a/tests/auto/widgets/itemviews/qfileiconprovider/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qfileiconprovider/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qfileiconprovider.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qfileiconprovider Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qfileiconprovider LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qfileiconprovider SOURCES tst_qfileiconprovider.cpp diff --git a/tests/auto/widgets/itemviews/qfileiconprovider/tst_qfileiconprovider.cpp b/tests/auto/widgets/itemviews/qfileiconprovider/tst_qfileiconprovider.cpp index 6b1decf7fd..3cba6dbf8b 100644 --- a/tests/auto/widgets/itemviews/qfileiconprovider/tst_qfileiconprovider.cpp +++ b/tests/auto/widgets/itemviews/qfileiconprovider/tst_qfileiconprovider.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QFileIconProvider> @@ -48,6 +48,7 @@ void tst_QFileIconProvider::iconType_data() // public QIcon icon(QFileIconProvider::IconType const& type) const void tst_QFileIconProvider::iconType() { + QGuiApplication::setDesktopSettingsAware(false); QFETCH(QFileIconProvider::IconType, type); QFileIconProvider provider; QVERIFY(!provider.icon(type).isNull()); diff --git a/tests/auto/widgets/itemviews/qheaderview/CMakeLists.txt b/tests/auto/widgets/itemviews/qheaderview/CMakeLists.txt index 0cf172a9cc..a13454085c 100644 --- a/tests/auto/widgets/itemviews/qheaderview/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qheaderview/CMakeLists.txt @@ -1,17 +1,19 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qheaderview.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qheaderview Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qheaderview LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qheaderview SOURCES tst_qheaderview.cpp - DEFINES - QT_DISABLE_DEPRECATED_UP_TO=0 LIBRARIES Qt::CorePrivate Qt::Gui diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp index f748f53f37..57efa3e349 100644 --- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp +++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp @@ -1,6 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2012 Thorbjørn Lund Martsum - tmartsum[at]gmail.com -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QHeaderView> #include <QProxyStyle> @@ -12,6 +12,7 @@ #include <QTest> #include <QTreeWidget> #include <QtWidgets/private/qheaderview_p.h> +#include <QtWidgets/private/qapplication_p.h> using BoolList = QList<bool>; using IntList = QList<int>; @@ -226,6 +227,7 @@ private slots: void statusTips(); void testRemovingColumnsViaLayoutChanged(); void testModelMovingColumns(); + void testModelMovingRows(); protected: void setupTestData(bool use_reset_model = false); @@ -306,6 +308,12 @@ public: endRemoveRows(); } + void moveRow(int from, int to) + { + beginMoveRows(QModelIndex(), from, from, QModelIndex(), to); + endMoveRows(); + } + void removeOneColumn(int col) { beginRemoveColumns(QModelIndex(), col, col); @@ -474,7 +482,7 @@ void tst_QHeaderView::init() QSignalSpy spy(view, &QHeaderView::sectionCountChanged); view->setModel(model); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); view->resize(200,200); } @@ -795,10 +803,10 @@ void tst_QHeaderView::visualIndexAt() for (int i : hidden) view->setSectionHidden(i, true); - for (int j = 0; j < from.count(); ++j) + for (int j = 0; j < from.size(); ++j) view->moveSection(from.at(j), to.at(j)); - for (int k = 0; k < coordinate.count(); ++k) + for (int k = 0; k < coordinate.size(); ++k) QTRY_COMPARE(view->visualIndexAt(coordinate.at(k)), visual.at(k)); } @@ -910,14 +918,14 @@ void tst_QHeaderView::swapSections() QCOMPARE(view->sectionsMoved(), true); for (int i = 0; i < view->count(); ++i) QCOMPARE(view->logicalIndex(i), logical.at(i)); - QCOMPARE(spy1.count(), 4); + QCOMPARE(spy1.size(), 4); logical = { 3, 1, 2, 0 }; view->swapSections(3, 0); QCOMPARE(view->sectionsMoved(), true); for (int j = 0; j < view->count(); ++j) QCOMPARE(view->logicalIndex(j), logical.at(j)); - QCOMPARE(spy1.count(), 6); + QCOMPARE(spy1.size(), 6); } void tst_QHeaderView::moveSection_data() @@ -963,9 +971,9 @@ void tst_QHeaderView::moveSection() QFETCH(const IntList, logical); QFETCH(int, count); - QCOMPARE(from.count(), to.count()); - QCOMPARE(from.count(), moved.count()); - QCOMPARE(view->count(), logical.count()); + QCOMPARE(from.size(), to.size()); + QCOMPARE(from.size(), moved.size()); + QCOMPARE(view->count(), logical.size()); QSignalSpy spy1(view, &QHeaderView::sectionMoved); QCOMPARE(view->sectionsMoved(), false); @@ -973,7 +981,7 @@ void tst_QHeaderView::moveSection() for (int h : hidden) view->setSectionHidden(h, true); - for (int i = 0; i < from.count(); ++i) { + for (int i = 0; i < from.size(); ++i) { view->moveSection(from.at(i), to.at(i)); QCOMPARE(view->sectionsMoved(), moved.at(i)); } @@ -981,7 +989,7 @@ void tst_QHeaderView::moveSection() for (int j = 0; j < view->count(); ++j) QCOMPARE(view->logicalIndex(j), logical.at(j)); - QCOMPARE(spy1.count(), count); + QCOMPARE(spy1.size(), count); } void tst_QHeaderView::resizeAndMoveSection_data() @@ -1166,14 +1174,14 @@ void tst_QHeaderView::resizeWithResizeModes() QFETCH(const IntList, expected); view->setStretchLastSection(false); - for (int i = 0; i < sections.count(); ++i) { + for (int i = 0; i < sections.size(); ++i) { view->resizeSection(i, sections.at(i)); view->setSectionResizeMode(i, modes.at(i)); } topLevel->show(); QVERIFY(QTest::qWaitForWindowExposed(topLevel)); view->resize(size, size); - for (int j = 0; j < expected.count(); ++j) + for (int j = 0; j < expected.size(); ++j) QCOMPARE(view->sectionSize(j), expected.at(j)); } @@ -1200,7 +1208,7 @@ void tst_QHeaderView::moveAndInsertSection() view->moveSection(from, to); model->insertRow(insert); - for (int i = 0; i < mapping.count(); ++i) + for (int i = 0; i < mapping.size(); ++i) QCOMPARE(view->logicalIndex(i), mapping.at(i)); } @@ -1271,21 +1279,21 @@ void tst_QHeaderView::resizeSection() view->setSectionsMovable(true); view->setStretchLastSection(false); - for (int i = 0; i < logical.count(); ++i) + for (int i = 0; i < logical.size(); ++i) if (logical.at(i) > -1 && logical.at(i) < view->count()) // for now view->setSectionResizeMode(logical.at(i), mode.at(i)); - for (int j = 0; j < logical.count(); ++j) + for (int j = 0; j < logical.size(); ++j) view->resizeSection(logical.at(j), initial); QSignalSpy spy(view, &QHeaderView::sectionResized); - for (int k = 0; k < logical.count(); ++k) + for (int k = 0; k < logical.size(); ++k) view->resizeSection(logical.at(k), size.at(k)); - QCOMPARE(spy.count(), resized); + QCOMPARE(spy.size(), resized); - for (int l = 0; l < logical.count(); ++l) + for (int l = 0; l < logical.size(); ++l) QCOMPARE(view->sectionSize(logical.at(l)), expected.at(l)); } @@ -1338,19 +1346,19 @@ void tst_QHeaderView::clearSectionSorting() QSignalSpy sectionClickedSpy(&h, &QHeaderView::sectionClicked); QVERIFY(sectionClickedSpy.isValid()); - QCOMPARE(sectionClickedSpy.count(), 0); + QCOMPARE(sectionClickedSpy.size(), 0); QSignalSpy sortIndicatorChangedSpy(&h, &QHeaderView::sortIndicatorChanged); QVERIFY(sortIndicatorChangedSpy.isValid()); - QCOMPARE(sortIndicatorChangedSpy.count(), 0); + QCOMPARE(sortIndicatorChangedSpy.size(), 0); enum { Count = 30 }; // normal behavior: clicking multiple times will just toggle the sort indicator for (int i = 0; i < Count; ++i) { QTest::mouseClick(h.viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(5, 5)); - QCOMPARE(sectionClickedSpy.count(), i + 1); - QCOMPARE(sortIndicatorChangedSpy.count(), i + 1); + QCOMPARE(sectionClickedSpy.size(), i + 1); + QCOMPARE(sortIndicatorChangedSpy.size(), i + 1); QCOMPARE(h.sortIndicatorSection(), 0); const auto expectedOrder = (i % 2) == 0 ? Qt::AscendingOrder : Qt::DescendingOrder; QCOMPARE(h.sortIndicatorOrder(), expectedOrder); @@ -1367,8 +1375,8 @@ void tst_QHeaderView::clearSectionSorting() // clearing behavior: clicking multiple times will be tristate (asc, desc, nothing) for (int i = 0; i < Count; ++i) { QTest::mouseClick(h.viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(5, 5)); - QCOMPARE(sectionClickedSpy.count(), i + 1); - QCOMPARE(sortIndicatorChangedSpy.count(), i + 1); + QCOMPARE(sectionClickedSpy.size(), i + 1); + QCOMPARE(sortIndicatorChangedSpy.size(), i + 1); switch (i % 3) { case 0: QCOMPARE(h.sortIndicatorSection(), 0); @@ -1612,7 +1620,6 @@ void tst_QHeaderView::focusPolicy() widget.show(); widget.setFocus(Qt::OtherFocusReason); - QApplication::setActiveWindow(&widget); widget.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&widget)); QVERIFY(widget.hasFocus()); @@ -1736,7 +1743,7 @@ static void saveRestoreImpl(const QByteArray &state, SaveRestoreOption option) h2.setModel(&m); QVERIFY(h2.restoreState(state)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toInt(), 2); QCOMPARE(h2.logicalIndex(0), 2); @@ -2040,9 +2047,9 @@ void tst_QHeaderView::sectionPressedSignal() QSignalSpy spy(&h, &QHeaderView::sectionPressed); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QTest::mousePress(h.viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(5, 5)); - QCOMPARE(spy.count(), count); + QCOMPARE(spy.size(), count); } void tst_QHeaderView::sectionClickedSignal() @@ -2062,19 +2069,19 @@ void tst_QHeaderView::sectionClickedSignal() QSignalSpy spy(&h, &QHeaderView::sectionClicked); QSignalSpy spy2(&h, &QHeaderView::sortIndicatorChanged); - QCOMPARE(spy.count(), 0); - QCOMPARE(spy2.count(), 0); + QCOMPARE(spy.size(), 0); + QCOMPARE(spy2.size(), 0); QTest::mouseClick(h.viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(5, 5)); - QCOMPARE(spy.count(), count); - QCOMPARE(spy2.count(), count); + QCOMPARE(spy.size(), count); + QCOMPARE(spy2.size(), count); //now let's try with the sort indicator hidden (the result should be the same spy.clear(); spy2.clear(); h.setSortIndicatorShown(false); QTest::mouseClick(h.viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(5, 5)); - QCOMPARE(spy.count(), count); - QCOMPARE(spy2.count(), count); + QCOMPARE(spy.size(), count); + QCOMPARE(spy2.size(), count); } void tst_QHeaderView::defaultSectionSize_data() @@ -2190,6 +2197,9 @@ void tst_QHeaderView::preserveHiddenSectionWidth() void tst_QHeaderView::invisibleStretchLastSection() { + if (QGuiApplication::platformName().startsWith(QLatin1String("eglfs"), Qt::CaseInsensitive)) + QSKIP("EGLFS does not allow resizing on top window"); + int count = 6; QStandardItemModel model(1, count); QHeaderView view(Qt::Horizontal); @@ -2255,7 +2265,7 @@ void tst_QHeaderView::task236450_hidden() for (int i : hide1) view.hideSection(i); - QCOMPARE(view.hiddenSectionCount(), hide1.count()); + QCOMPARE(view.hiddenSectionCount(), hide1.size()); for (int i = 0; i < 6; i++) QCOMPARE(!view.isSectionHidden(i), !hide1.contains(i)); @@ -2263,13 +2273,13 @@ void tst_QHeaderView::task236450_hidden() view.scheduleDelayedItemsLayout(); view.executeDelayedItemsLayout(); //force to do a relayout - QCOMPARE(view.hiddenSectionCount(), hide1.count()); + QCOMPARE(view.hiddenSectionCount(), hide1.size()); for (int i = 0; i < 6; i++) { QCOMPARE(!view.isSectionHidden(i), !hide1.contains(i)); view.setSectionHidden(i, hide2.contains(i)); } - QCOMPARE(view.hiddenSectionCount(), hide2.count()); + QCOMPARE(view.hiddenSectionCount(), hide2.size()); for (int i = 0; i < 6; i++) QCOMPARE(!view.isSectionHidden(i), !hide2.contains(i)); } @@ -2301,10 +2311,10 @@ void tst_QHeaderView::task248050_hideRow() //returns 0 if everything is fine. static int checkHeaderViewOrder(const QHeaderView *view, const IntList &expected) { - if (view->count() != expected.count()) + if (view->count() != expected.size()) return 1; - for (int i = 0; i < expected.count(); i++) { + for (int i = 0; i < expected.size(); i++) { if (view->logicalIndex(i) != expected.at(i)) return i + 10; if (view->visualIndex(expected.at(i)) != i) @@ -2395,8 +2405,8 @@ void tst_QHeaderView::QTBUG7833_sectionClicked() QTest::mouseClick(tv.horizontalHeader()->viewport(), Qt::LeftButton, Qt::NoModifier, QPoint(tv.horizontalHeader()->sectionViewportPosition(11) + tv.horizontalHeader()->sectionSize(11) / 2, 5)); - QCOMPARE(clickedSpy.count(), 1); - QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(clickedSpy.size(), 1); + QCOMPARE(pressedSpy.size(), 1); QCOMPARE(clickedSpy.at(0).at(0).toInt(), 11); QCOMPARE(pressedSpy.at(0).at(0).toInt(), 11); @@ -2404,8 +2414,8 @@ void tst_QHeaderView::QTBUG7833_sectionClicked() QPoint(tv.horizontalHeader()->sectionViewportPosition(8) + tv.horizontalHeader()->sectionSize(0) / 2, 5)); - QCOMPARE(clickedSpy.count(), 2); - QCOMPARE(pressedSpy.count(), 2); + QCOMPARE(clickedSpy.size(), 2); + QCOMPARE(pressedSpy.size(), 2); QCOMPARE(clickedSpy.at(1).at(0).toInt(), 8); QCOMPARE(pressedSpy.at(1).at(0).toInt(), 8); @@ -2413,8 +2423,8 @@ void tst_QHeaderView::QTBUG7833_sectionClicked() QPoint(tv.horizontalHeader()->sectionViewportPosition(0) + tv.horizontalHeader()->sectionSize(0) / 2, 5)); - QCOMPARE(clickedSpy.count(), 3); - QCOMPARE(pressedSpy.count(), 3); + QCOMPARE(clickedSpy.size(), 3); + QCOMPARE(pressedSpy.size(), 3); QCOMPARE(clickedSpy.at(2).at(0).toInt(), 0); QCOMPARE(pressedSpy.at(2).at(0).toInt(), 0); } @@ -2541,7 +2551,7 @@ public: void insertRowAtBeginning() { Q_EMIT layoutAboutToBeChanged(); - m_displayNames.insert(0, QStringLiteral("Item %1").arg(m_displayNames.count())); + m_displayNames.insert(0, QStringLiteral("Item %1").arg(m_displayNames.size())); // Rows are always inserted at the beginning, so move all others. const auto pl = persistentIndexList(); // The vertical header view will have a persistent index stored here on the second call to insertRowAtBeginning. @@ -2557,7 +2567,7 @@ public: QModelIndex index(int row, int column, const QModelIndex &) const override { return createIndex(row, column); } QModelIndex parent(const QModelIndex &) const override { return QModelIndex(); } - int rowCount(const QModelIndex &) const override { return m_displayNames.count(); } + int rowCount(const QModelIndex &) const override { return m_displayNames.size(); } int columnCount(const QModelIndex &) const override { return 1; } private: @@ -2841,10 +2851,6 @@ void tst_QHeaderView::calculateAndCheck(int cppline, const int precalced_compare int sum_visual = 0; int sum_logical = 0; - int sum_size = 0; - int sum_hidden_size = 0; - int sum_lookup_visual = 0; - int sum_lookup_logical = 0; int chk_visual = 1; int chk_logical = 1; @@ -2864,7 +2870,6 @@ void tst_QHeaderView::calculateAndCheck(int cppline, const int precalced_compare sum_visual += visual; sum_logical += logical; - sum_size += ssize; if (visual >= 0) { chk_visual %= p2; @@ -2884,7 +2889,6 @@ void tst_QHeaderView::calculateAndCheck(int cppline, const int precalced_compare if (view->isSectionHidden(i)) { view->showSection(i); int hiddensize = view->sectionSize(i); - sum_hidden_size += hiddensize; chk_hidden_size %= p2; chk_hidden_size += ( (hiddensize + 1) * (i + 1) * p1); // (hiddensize + 1) in the above to differ between hidden and size 0 @@ -2903,8 +2907,6 @@ void tst_QHeaderView::calculateAndCheck(int cppline, const int precalced_compare for (int u = 0; u < max_lookup_count; ++u) { int visu = view->visualIndexAt(u); int logi = view->logicalIndexAt(u); - sum_lookup_visual += logi; - sum_lookup_logical += visu; chk_lookup_visual %= p2; chk_lookup_visual *= ( (u + 1) * p1 * (visu + 2)); chk_lookup_logical %= p2; @@ -3609,7 +3611,6 @@ void tst_QHeaderView::statusTips() headerView.setGeometry(QRect(QPoint(QGuiApplication::primaryScreen()->geometry().center() - QPoint(250, 250)), QSize(500, 500))); headerView.show(); - QApplication::setActiveWindow(&headerView); QVERIFY(QTest::qWaitForWindowActive(&headerView)); // Ensure it is moved away first and then moved to the relevant section @@ -3651,10 +3652,33 @@ void tst_QHeaderView::testModelMovingColumns() hv.setModel(&model); hv.resizeSections(QHeaderView::ResizeToContents); hv.show(); + hv.hideSection(3); + QVERIFY(!hv.isSectionHidden(1)); + QVERIFY(hv.isSectionHidden(3)); QPersistentModelIndex index3 = model.index(0, 3); model.moveColumn(3, 1); QCOMPARE(index3.column(), 1); + QVERIFY(hv.isSectionHidden(1)); + QVERIFY(!hv.isSectionHidden(3)); +} + +void tst_QHeaderView::testModelMovingRows() +{ + QtTestModel model(10, 10); + QHeaderView hv(Qt::Vertical); + hv.setModel(&model); + hv.resizeSections(QHeaderView::ResizeToContents); + hv.show(); + hv.hideSection(3); + QVERIFY(!hv.isSectionHidden(1)); + QVERIFY(hv.isSectionHidden(3)); + + QPersistentModelIndex index3 = model.index(3, 0); + model.moveRow(3, 1); + QCOMPARE(index3.row(), 1); + QVERIFY(hv.isSectionHidden(1)); + QVERIFY(!hv.isSectionHidden(3)); } QTEST_MAIN(tst_QHeaderView) diff --git a/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST b/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST deleted file mode 100644 index 21cfa7cd0f..0000000000 --- a/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[editorKeyPress] -ubuntu-20.04 diff --git a/tests/auto/widgets/itemviews/qitemdelegate/CMakeLists.txt b/tests/auto/widgets/itemviews/qitemdelegate/CMakeLists.txt index 575cd4996b..58a00fdc9d 100644 --- a/tests/auto/widgets/itemviews/qitemdelegate/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qitemdelegate/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qitemdelegate.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qitemdelegate Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qitemdelegate LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qitemdelegate SOURCES tst_qitemdelegate.cpp diff --git a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp index 68a7268473..769456951f 100644 --- a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp +++ b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp @@ -1,10 +1,11 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "../../../shared/highdpi.h" #include <QTest> #include <QTimeZone> +#include <QDateTime> #include <QTimer> #include <QTestEventLoop> #include <QSignalSpy> @@ -34,6 +35,7 @@ #include <qscreen.h> #include <QtWidgets/private/qabstractitemdelegate_p.h> +#include <QtWidgets/private/qapplication_p.h> Q_DECLARE_METATYPE(QAbstractItemDelegate::EndEditHint) @@ -205,6 +207,8 @@ private slots: void dateTextForRole_data(); void dateTextForRole(); + void reuseEditor(); + private: #ifdef QT_BUILD_INTERNAL struct RoleDelegate : public QItemDelegate @@ -325,7 +329,7 @@ void tst_QItemDelegate::editorKeyPress() view.edit(index); QList<QLineEdit*> lineEditors = view.viewport()->findChildren<QLineEdit *>(); - QCOMPARE(lineEditors.count(), 1); + QCOMPARE(lineEditors.size(), 1); QLineEdit *editor = lineEditors.at(0); QCOMPARE(editor->selectedText(), initial); @@ -353,7 +357,7 @@ void tst_QItemDelegate::doubleEditorNegativeInput() view.edit(index); QList<QDoubleSpinBox*> editors = view.viewport()->findChildren<QDoubleSpinBox *>(); - QCOMPARE(editors.count(), 1); + QCOMPARE(editors.size(), 1); QDoubleSpinBox *editor = editors.at(0); QCOMPARE(editor->value(), double(10)); @@ -670,33 +674,33 @@ void tst_QItemDelegate::testEventFilter() //For each test we send a key event and check if signals were emitted. event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier); QVERIFY(delegate.eventFilter(&widget, event)); - QCOMPARE(closeEditorSpy.count(), 1); - QCOMPARE(commitDataSpy.count(), 1); + QCOMPARE(closeEditorSpy.size(), 1); + QCOMPARE(commitDataSpy.size(), 1); delete event; event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier); QVERIFY(delegate.eventFilter(&widget, event)); - QCOMPARE(closeEditorSpy.count(), 2); - QCOMPARE(commitDataSpy.count(), 2); + QCOMPARE(closeEditorSpy.size(), 2); + QCOMPARE(commitDataSpy.size(), 2); delete event; event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier); QVERIFY(delegate.eventFilter(&widget, event)); - QCOMPARE(closeEditorSpy.count(), 3); - QCOMPARE(commitDataSpy.count(), 2); + QCOMPARE(closeEditorSpy.size(), 3); + QCOMPARE(commitDataSpy.size(), 2); delete event; event = new QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier); QVERIFY(!delegate.eventFilter(&widget, event)); - QCOMPARE(closeEditorSpy.count(), 3); - QCOMPARE(commitDataSpy.count(), 2); + QCOMPARE(closeEditorSpy.size(), 3); + QCOMPARE(commitDataSpy.size(), 2); delete event; //Subtest focusEvent event = new QFocusEvent(QEvent::FocusOut); QVERIFY(!delegate.eventFilter(&widget, event)); - QCOMPARE(closeEditorSpy.count(), 4); - QCOMPARE(commitDataSpy.count(), 3); + QCOMPARE(closeEditorSpy.size(), 4); + QCOMPARE(commitDataSpy.size(), 3); delete event; } @@ -743,7 +747,6 @@ void tst_QItemDelegate::dateTimeEditor() widget.setItem(0, 2, item3); widget.show(); QVERIFY(QTest::qWaitForWindowExposed(&widget)); - QApplication::setActiveWindow(&widget); widget.editItem(item1); @@ -759,7 +762,6 @@ void tst_QItemDelegate::dateTimeEditor() timeEditor->setTime(time.addSecs(60)); widget.clearFocus(); - qApp->setActiveWindow(&widget); widget.setFocus(); widget.editItem(item2); @@ -1023,7 +1025,6 @@ void tst_QItemDelegate::decoration() TestItemDelegate delegate; table.setItemDelegate(&delegate); table.show(); - QApplication::setActiveWindow(&table); QVERIFY(QTest::qWaitForWindowActive(&table)); QVariant value; @@ -1278,7 +1279,6 @@ void tst_QItemDelegate::enterKey() QListView view; view.setModel(&model); view.show(); - QApplication::setActiveWindow(&view); view.setFocus(); QVERIFY(QTest::qWaitForWindowActive(&view)); @@ -1312,7 +1312,7 @@ void tst_QItemDelegate::enterKey() view.edit(index); QList<QWidget*> lineEditors = view.viewport()->findChildren<QWidget *>(QString::fromLatin1("TheEditor")); - QCOMPARE(lineEditors.count(), 1); + QCOMPARE(lineEditors.size(), 1); QPointer<QWidget> editor = lineEditors.at(0); QCOMPARE(editor->hasFocus(), true); @@ -1338,7 +1338,6 @@ void tst_QItemDelegate::task257859_finalizeEdit() QListView view; view.setModel(&model); view.show(); - QApplication::setActiveWindow(&view); view.setFocus(); QVERIFY(QTest::qWaitForWindowActive(&view)); @@ -1346,7 +1345,7 @@ void tst_QItemDelegate::task257859_finalizeEdit() view.edit(index); QList<QLineEdit *> lineEditors = view.viewport()->findChildren<QLineEdit *>(); - QCOMPARE(lineEditors.count(), 1); + QCOMPARE(lineEditors.size(), 1); QPointer<QWidget> editor = lineEditors.at(0); QCOMPARE(editor->hasFocus(), true); @@ -1400,7 +1399,7 @@ void tst_QItemDelegate::comboBox() widget.setItem(0, 0, item1); widget.show(); QVERIFY(QTest::qWaitForWindowExposed(&widget)); - QApplication::setActiveWindow(&widget); + QApplicationPrivate::setActiveWindow(&widget); widget.editItem(item1); @@ -1465,7 +1464,6 @@ void tst_QItemDelegate::testLineEditValidation() view.setItemDelegate(&delegate); view.show(); view.setFocus(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QPointer<QLineEdit> editor; @@ -1477,7 +1475,7 @@ void tst_QItemDelegate::testLineEditValidation() const auto findEditors = [&]() { return view.findChildren<QLineEdit *>(QStringLiteral("TheEditor")); }; - QCOMPARE(findEditors().count(), 1); + QCOMPARE(findEditors().size(), 1); editor = findEditors().at(0); editor->clear(); @@ -1497,7 +1495,7 @@ void tst_QItemDelegate::testLineEditValidation() view.setCurrentIndex(index); view.edit(index); - QTRY_COMPARE(findEditors().count(), 1); + QTRY_COMPARE(findEditors().size(), 1); editor = findEditors().at(0); editor->clear(); @@ -1519,13 +1517,13 @@ void tst_QItemDelegate::testLineEditValidation() // reset the view to forcibly close the editor view.reset(); - QTRY_COMPARE(findEditors().count(), 0); + QTRY_COMPARE(findEditors().size(), 0); // set a valid text again view.setCurrentIndex(index); view.edit(index); - QTRY_COMPARE(findEditors().count(), 1); + QTRY_COMPARE(findEditors().size(), 1); editor = findEditors().at(0); editor->clear(); @@ -1589,12 +1587,12 @@ void tst_QItemDelegate::dateTextForRole_data() QDate date(2013, 12, 11); QTime time(10, 9, 8, 765); // Ensure we exercise every time-spec variant: - QTest::newRow("local") << QDateTime(date, time, Qt::LocalTime); - QTest::newRow("UTC") << QDateTime(date, time, Qt::UTC); -#if QT_CONFIG(timezone) + QTest::newRow("local") << QDateTime(date, time); + QTest::newRow("UTC") << QDateTime(date, time, QTimeZone::UTC); +# if QT_CONFIG(timezone) QTest::newRow("zone") << QDateTime(date, time, QTimeZone("Europe/Dublin")); -#endif - QTest::newRow("offset") << QDateTime(date, time, Qt::OffsetFromUTC, 36000); +# endif + QTest::newRow("offset") << QDateTime(date, time, QTimeZone::fromSecondsAheadOfUtc(36000)); #endif } @@ -1617,6 +1615,75 @@ void tst_QItemDelegate::dateTextForRole() #endif } +void tst_QItemDelegate::reuseEditor() +{ + class ReusingDelegate: public QItemDelegate { + public: + using QItemDelegate::QItemDelegate; + ~ReusingDelegate() + { + if (cached) + cached->deleteLater(); + } + + QWidget* createEditor(QWidget* parent, + const QStyleOptionViewItem&, + const QModelIndex&) const override + { + auto *cb = new QComboBox(parent); + cb->addItem("One"); + cb->addItem("Two"); + cb->setEditable(true); + return cb; + } + + void setEditorData(QWidget* editor, const QModelIndex& index) + const override + { + auto *cb = qobject_cast<QComboBox*>(editor); + cb->setCurrentText(index.data(Qt::DisplayRole).toString()); + } + + void setModelData(QWidget* editor, + QAbstractItemModel* model, + const QModelIndex& index) const override + { + auto *cb = qobject_cast<QComboBox*>(editor); + model->setData(index, cb->currentText(), Qt::DisplayRole); + } + + void destroyEditor(QWidget* editor, const QModelIndex&) const override + { + auto *cb = qobject_cast<QComboBox*>(editor); + cb->setParent(nullptr); // How to completely detach the editor from treeview ? + cb->hide(); + cb->setEnabled(false); + cached = cb; + } + + private: + mutable QComboBox* cached = nullptr; + }; + + QStandardItemModel model; + model.appendRow(new QStandardItem("One")); + model.appendRow(new QStandardItem("Two")); + + ReusingDelegate delegate; + + QTreeView tree; + tree.setModel(&model); + tree.setItemDelegate(&delegate); + + tree.show(); + QVERIFY(QTest::qWaitForWindowActive(&tree)); + + tree.edit(model.index(0, 0)); + QTRY_VERIFY(qobject_cast<QComboBox *>(tree.focusWidget())); + + tree.close(); +} + // ### _not_ covered: // editing with a custom editor factory diff --git a/tests/auto/widgets/itemviews/qitemeditorfactory/CMakeLists.txt b/tests/auto/widgets/itemviews/qitemeditorfactory/CMakeLists.txt index d3fef08c43..608c323b44 100644 --- a/tests/auto/widgets/itemviews/qitemeditorfactory/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qitemeditorfactory/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qitemeditorfactory.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qitemeditorfactory Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qitemeditorfactory LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qitemeditorfactory SOURCES tst_qitemeditorfactory.cpp diff --git a/tests/auto/widgets/itemviews/qitemeditorfactory/tst_qitemeditorfactory.cpp b/tests/auto/widgets/itemviews/qitemeditorfactory/tst_qitemeditorfactory.cpp index b11c64df6e..dcd751c696 100644 --- a/tests/auto/widgets/itemviews/qitemeditorfactory/tst_qitemeditorfactory.cpp +++ b/tests/auto/widgets/itemviews/qitemeditorfactory/tst_qitemeditorfactory.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QDoubleSpinBox> diff --git a/tests/auto/widgets/itemviews/qitemview/CMakeLists.txt b/tests/auto/widgets/itemviews/qitemview/CMakeLists.txt index 04c95e03a8..8ff1fd67c9 100644 --- a/tests/auto/widgets/itemviews/qitemview/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qitemview/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qitemview.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qitemview Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qitemview LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qitemview SOURCES tst_qitemview.cpp diff --git a/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp b/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp index 1b60328691..d5a6ddea6e 100644 --- a/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp +++ b/tests/auto/widgets/itemviews/qitemview/tst_qitemview.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QRandomGenerator> #include <QStack> diff --git a/tests/auto/widgets/itemviews/qitemview/viewstotest.cpp b/tests/auto/widgets/itemviews/qitemview/viewstotest.cpp index 1a7e037248..0c7c17503e 100644 --- a/tests/auto/widgets/itemviews/qitemview/viewstotest.cpp +++ b/tests/auto/widgets/itemviews/qitemview/viewstotest.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QHeaderView> #include <QListView> diff --git a/tests/auto/widgets/itemviews/qlistview/BLACKLIST b/tests/auto/widgets/itemviews/qlistview/BLACKLIST deleted file mode 100644 index ec1c3722bd..0000000000 --- a/tests/auto/widgets/itemviews/qlistview/BLACKLIST +++ /dev/null @@ -1,3 +0,0 @@ -# QTBUG-94250 -[internalDragDropMove] -opensuse-leap diff --git a/tests/auto/widgets/itemviews/qlistview/CMakeLists.txt b/tests/auto/widgets/itemviews/qlistview/CMakeLists.txt index 60d6f138e5..f6c9f154de 100644 --- a/tests/auto/widgets/itemviews/qlistview/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qlistview/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qlistview.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qlistview Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qlistview LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qlistview SOURCES tst_qlistview.cpp diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp index ad52e40254..236cd6212f 100644 --- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp +++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QListWidget> @@ -18,6 +18,7 @@ #include <QtTest/private/qtesthelpers_p.h> #include <QtWidgets/private/qlistview_p.h> +#include <QtWidgets/private/qapplication_p.h> using namespace QTestPrivate; @@ -67,8 +68,14 @@ public: { return QListView::visualRegionForSelection(selectionModel()->selection()); } + void moveEvent(QMoveEvent *e) override + { + QListView::moveEvent(e); + m_gotValidResizeEvent = !e->pos().isNull(); + } friend class tst_QListView; + bool m_gotValidResizeEvent = false; }; class tst_QListView : public QObject @@ -155,6 +162,7 @@ private slots: void spacingWithWordWrap(); void scrollOnRemove_data(); void scrollOnRemove(); + void wordWrapNullIcon(); }; // Testing get/set functions @@ -611,7 +619,7 @@ void tst_QListView::moveCursor4() void tst_QListView::moveCursor5() { - PublicListView listView;; + PublicListView listView; QStandardItemModel model; QIcon icon(QPixmap(300,300)); model.appendRow(new QStandardItem(icon,"11")); @@ -718,7 +726,7 @@ void tst_QListView::clicked() continue; QSignalSpy spy(&view, &QListView::clicked); QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } } @@ -1147,7 +1155,7 @@ void tst_QListView::selection() v.setSelection(selectionRect, QItemSelectionModel::ClearAndSelect); const QModelIndexList selected = v.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), expectedItems.count()); + QCOMPARE(selected.size(), expectedItems.size()); for (const auto &idx : selected) QVERIFY(expectedItems.contains(idx.row())); } @@ -1557,7 +1565,7 @@ void tst_QListView::task203585_selectAll() QVERIFY(view.selectionModel()->selectedIndexes().isEmpty()); view.setRowHidden(0, false); view.selectAll(); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); } void tst_QListView::task228566_infiniteRelayout() @@ -1642,7 +1650,7 @@ void tst_QListView::task196118_visualRegionForSelection() view.selectionModel()->select(top1.index(), QItemSelectionModel::Select); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); QVERIFY(view.getVisualRegionForSelection().isEmpty()); } @@ -1699,7 +1707,6 @@ void tst_QListView::keyboardSearch() QListView view; view.setModel(&model); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QTest::keyClick(&view, Qt::Key_K); @@ -1740,7 +1747,7 @@ void tst_QListView::shiftSelectionWithNonUniformItemSizes() QTRY_COMPARE(view.currentIndex(), model.index(1, 0)); QModelIndexList selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 3); + QCOMPARE(selected.size(), 3); QVERIFY(!selected.contains(model.index(0, 0))); } { // Second test: QListView::TopToBottom flow @@ -1767,7 +1774,7 @@ void tst_QListView::shiftSelectionWithNonUniformItemSizes() QTRY_COMPARE(view.currentIndex(), model.index(1, 0)); QModelIndexList selected = view.selectionModel()->selectedIndexes(); - QCOMPARE(selected.count(), 3); + QCOMPARE(selected.size(), 3); QVERIFY(!selected.contains(model.index(0, 0))); } } @@ -1801,7 +1808,6 @@ void tst_QListView::shiftSelectionWithItemAlignment() view.resize(300, view.sizeHintForRow(0) * items.size() / 2 + view.horizontalScrollBar()->height()); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(static_cast<QWidget *>(&view), QApplication::activeWindow()); @@ -1829,7 +1835,7 @@ void tst_QListView::clickOnViewportClearsSelection() view.selectAll(); QModelIndex index = model.index(0); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); QVERIFY(view.selectionModel()->isSelected(index)); //we try to click outside of the index @@ -1837,7 +1843,7 @@ void tst_QListView::clickOnViewportClearsSelection() QTest::mousePress(view.viewport(), Qt::LeftButton, {}, point); //at this point, the selection shouldn't have changed - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); QVERIFY(view.selectionModel()->isSelected(index)); QTest::mouseRelease(view.viewport(), Qt::LeftButton, {}, point); @@ -1860,7 +1866,6 @@ void tst_QListView::task262152_setModelColumnNavigate() view.setModelColumn(1); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QCOMPARE(&view, QApplication::activeWindow()); QTest::keyClick(&view, Qt::Key_Down); @@ -1946,7 +1951,7 @@ void tst_QListView::taskQTBUG_435_deselectOnViewportClick() view.setModel(&model); view.setSelectionMode(QAbstractItemView::ExtendedSelection); view.selectAll(); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), model.rowCount()); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), model.rowCount()); const QRect itemRect = view.visualRect(model.index(model.rowCount() - 1)); @@ -1956,7 +1961,7 @@ void tst_QListView::taskQTBUG_435_deselectOnViewportClick() QVERIFY(!view.selectionModel()->hasSelection()); view.selectAll(); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), model.rowCount()); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), model.rowCount()); //and now the right button QTest::mouseClick(view.viewport(), Qt::RightButton, {}, p); @@ -2562,8 +2567,9 @@ void tst_QListView::taskQTBUG_58749_adjustToContent() // use the long text and make sure the width is adjusted. model.setData(model.index(0, 0), longText); QApplication::processEvents(); - QVERIFY(w.width() > longTextWidth); - QVERIFY(view->width() >= longTextWidth); + const QRect itemRect = view->visualRect(model.index(0, 0)); + QVERIFY(w.width() > itemRect.width()); + QCOMPARE_GE(view->width(), itemRect.width()); } void tst_QListView::taskQTBUG_51086_skippingIndexesInSelectedIndexes() @@ -2715,9 +2721,9 @@ public: if (idxPar.isValid()) { TstMoveItem *parentItem = static_cast<TstMoveItem *>(idxPar.internalPointer()); Q_ASSERT(parentItem); - cnt = parentItem->childItems.count(); + cnt = parentItem->childItems.size(); } else { - cnt = rootItem->childItems.count(); + cnt = rootItem->childItems.size(); } return cnt; } @@ -2734,9 +2740,9 @@ public: if (parent.isValid()) { TstMoveItem *parentItem = static_cast<TstMoveItem *>(parent.internalPointer()); Q_ASSERT(parentItem); - ret = parentItem->childItems.count() > 0; + ret = parentItem->childItems.size() > 0; } else { - ret = rootItem->childItems.count() > 0; + ret = rootItem->childItems.size() > 0; } return ret; } @@ -2758,8 +2764,8 @@ public: TstMoveItem *itmDestParent = itemAt(destinationParent); if (itmSrcParent && sourceRow >= 0 - && sourceRow + count <= itmSrcParent->childItems.count() - && itmDestParent && destinationChild <= itmDestParent->childItems.count()) { + && sourceRow + count <= itmSrcParent->childItems.size() + && itmDestParent && destinationChild <= itmDestParent->childItems.size()) { beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destinationParent, destinationChild); QList<TstMoveItem *> itemsToMove; @@ -2767,7 +2773,7 @@ public: TstMoveItem *itm = itmSrcParent->childItems.at(sourceRow+i); itemsToMove.append(itm); } - for (int i = itemsToMove.count() -1; i >= 0; --i) { + for (int i = itemsToMove.size() -1; i >= 0; --i) { TstMoveItem *itm = itemsToMove.at(i); itm->parentItem->childItems.removeAll(itm); itm->parentItem = itmDestParent; @@ -2805,7 +2811,6 @@ void tst_QListView::moveLastRow() view.setViewMode(QListView::IconMode); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QModelIndex sourceParent = model.index(0, 0); @@ -2992,6 +2997,7 @@ void tst_QListView::internalDragDropMove() // The test relies on the global position of mouse events; make sure // the window is properly mapped on X11. QVERIFY(QTest::qWaitForWindowActive(&list)); + QVERIFY(QTest::qWaitFor([&]() { return list.m_gotValidResizeEvent; })); // execute as soon as the eventloop is running again // which is the case inside list.startDrag() QTimer::singleShot(0, [&]() @@ -3056,6 +3062,11 @@ void tst_QListView::spacingWithWordWrap() } }; + QStyle *oldStyle = QApplication::style(); + oldStyle->setParent(nullptr); + const auto resetStyle = qScopeGuard([oldStyle]{ + QApplication::setStyle(oldStyle); + }); QApplication::setStyle(new MyStyle(scrollBarOverlap)); const int listViewResizeCount = 200; @@ -3169,10 +3180,26 @@ void tst_QListView::scrollOnRemove() model.removeRow(25); // if nothing is selected now, then the view should not have scrolled - if (!view.selectionModel()->selectedIndexes().count()) + if (!view.selectionModel()->selectedIndexes().size()) QTRY_COMPARE(view.verticalScrollBar()->value(), item25Position); } +void tst_QListView::wordWrapNullIcon() +{ + QListView listView; + listView.setViewMode(QListView::IconMode); + listView.setWrapping(true); + listView.setWordWrap(true); + listView.setFixedSize(QSize(100, 500)); + + QStandardItemModel model; + QStandardItem *item = new QStandardItem(QIcon(), "This is a long text for word wrapping Item_"); + model.appendRow(item); + listView.setModel(&model); + + listView.indexAt(QPoint(0, 0)); +} + QTEST_MAIN(tst_QListView) #include "tst_qlistview.moc" diff --git a/tests/auto/widgets/itemviews/qlistwidget/CMakeLists.txt b/tests/auto/widgets/itemviews/qlistwidget/CMakeLists.txt index 10d24cc5e7..fea17e1d75 100644 --- a/tests/auto/widgets/itemviews/qlistwidget/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qlistwidget/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qlistwidget.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qlistwidget Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qlistwidget LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qlistwidget SOURCES tst_qlistwidget.cpp diff --git a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp index 3fe14c682c..14a6cee0d9 100644 --- a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp +++ b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QCompleter> #include <QHBoxLayout> @@ -8,8 +8,11 @@ #include <QSignalSpy> #include <QStyledItemDelegate> #include <QTest> +#include <QLabel> #include <private/qlistwidget_p.h> +#include <QtWidgets/private/qapplication_p.h> + using IntList = QList<int>; class tst_QListWidget : public QObject @@ -72,6 +75,8 @@ private slots: void sortItems(); void sortHiddenItems(); void sortHiddenItems_data(); + void sortCheckStability_data(); + void sortCheckStability(); void closeEditor(); void setData_data(); void setData(); @@ -103,6 +108,7 @@ private slots: void moveRows(); void moveRowsInvalid_data(); void moveRowsInvalid(); + void noopDragDrop(); protected slots: void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last) @@ -344,7 +350,7 @@ void tst_QListWidget::addItems() QString::number(testWidget->count() + 3), label}; testWidget->addItems(stringList); - QCOMPARE(testWidget->count(), count + stringList.count()); + QCOMPARE(testWidget->count(), count + stringList.size()); QCOMPARE(testWidget->item(testWidget->count()-1)->text(), label); } @@ -356,30 +362,30 @@ void tst_QListWidget::openPersistentEditor() QListWidgetItem *item = new QListWidgetItem(QString::number(testWidget->count())); testWidget->openPersistentEditor(item); - int childCount = testWidget->viewport()->children().count(); + int childCount = testWidget->viewport()->children().size(); testWidget->addItem(item); testWidget->openPersistentEditor(item); - QCOMPARE(childCount + 1, testWidget->viewport()->children().count()); + QCOMPARE(childCount + 1, testWidget->viewport()->children().size()); } void tst_QListWidget::closePersistentEditor() { // Boundary checking - int childCount = testWidget->viewport()->children().count(); + int childCount = testWidget->viewport()->children().size(); testWidget->closePersistentEditor(nullptr); QListWidgetItem *item = new QListWidgetItem(QString::number(testWidget->count())); testWidget->closePersistentEditor(item); - QCOMPARE(childCount, testWidget->viewport()->children().count()); + QCOMPARE(childCount, testWidget->viewport()->children().size()); // Create something testWidget->addItem(item); testWidget->openPersistentEditor(item); // actual test - childCount = testWidget->viewport()->children().count(); + childCount = testWidget->viewport()->children().size(); testWidget->closePersistentEditor(item); QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); - QCOMPARE(testWidget->viewport()->children().count(), childCount - 1); + QCOMPARE(testWidget->viewport()->children().size(), childCount - 1); } void tst_QListWidget::setItemHidden() @@ -529,7 +535,7 @@ void tst_QListWidget::editItem() item->setFlags(item->flags() | Qt::ItemIsEditable); testWidget->addItem(item); - int childCount = testWidget->viewport()->children().count(); + int childCount = testWidget->viewport()->children().size(); QWidget *existsAlready = testWidget->indexWidget(testWidget->model()->index(testWidget->row(item), 0)); testWidget->editItem(item); Qt::ItemFlags flags = item->flags(); @@ -537,7 +543,7 @@ void tst_QListWidget::editItem() // There doesn't seem to be a way to detect if the item has already been edited... if (!existsAlready && flags & Qt::ItemIsEditable && flags & Qt::ItemIsEnabled) { QList<QObject *> children = testWidget->viewport()->children(); - QVERIFY(children.count() > childCount); + QVERIFY(children.size() > childCount); bool found = false; for (int i = 0; i < children.size(); ++i) { if (children.at(i)->inherits("QExpandingLineEdit")) @@ -545,7 +551,7 @@ void tst_QListWidget::editItem() } QVERIFY(found); } else { - QCOMPARE(testWidget->viewport()->children().count(), childCount); + QCOMPARE(testWidget->viewport()->children().size(), childCount); } } @@ -554,12 +560,12 @@ void tst_QListWidget::findItems() // This really just tests that the items that are returned are converted from index's to items correctly. // Boundary checking - QCOMPARE(testWidget->findItems("GirlsCanWearJeansAndCutTheirHairShort", Qt::MatchExactly).count(), 0); + QCOMPARE(testWidget->findItems("GirlsCanWearJeansAndCutTheirHairShort", Qt::MatchExactly).size(), 0); populate(); for (int i = 0; i < testWidget->count(); ++i) - QCOMPARE(testWidget->findItems(testWidget->item(i)->text(), Qt::MatchExactly).count(), 1); + QCOMPARE(testWidget->findItems(testWidget->item(i)->text(), Qt::MatchExactly).size(), 1); } @@ -574,8 +580,8 @@ void tst_QListWidget::insertItem_data() QTest::newRow("Insert less then 0") << initialItems << -1 << "inserted" << 0; QTest::newRow("Insert at 0") << initialItems << 0 << "inserted" << 0; - QTest::newRow("Insert beyond count") << initialItems << initialItems.count()+1 << "inserted" << initialItems.count(); - QTest::newRow("Insert at count") << initialItems << initialItems.count() << "inserted" << initialItems.count(); + QTest::newRow("Insert beyond count") << initialItems << initialItems.size()+1 << "inserted" << initialItems.size(); + QTest::newRow("Insert at count") << initialItems << initialItems.size() << "inserted" << initialItems.size(); QTest::newRow("Insert in the middle") << initialItems << 1 << "inserted" << 1; } @@ -587,7 +593,7 @@ void tst_QListWidget::insertItem() QFETCH(int, expectedIndex); testWidget->insertItems(0, initialItems); - QCOMPARE(testWidget->count(), initialItems.count()); + QCOMPARE(testWidget->count(), initialItems.size()); testWidget->insertItem(insertIndex, itemLabel); @@ -596,7 +602,7 @@ void tst_QListWidget::insertItem() QCOMPARE(rcFirst[RowsInserted], expectedIndex); QCOMPARE(rcLast[RowsInserted], expectedIndex); - QCOMPARE(testWidget->count(), initialItems.count() + 1); + QCOMPARE(testWidget->count(), initialItems.size() + 1); QCOMPARE(testWidget->item(expectedIndex)->text(), itemLabel); } @@ -669,8 +675,8 @@ void tst_QListWidget::insertItems() for (int i = 0; i < testWidget->count(); ++i) QCOMPARE(testWidget->item(i)->listWidget(), testWidget); - QCOMPARE(itemChangedSpy.count(), 0); - QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(itemChangedSpy.size(), 0); + QCOMPARE(dataChangedSpy.size(), 0); } void tst_QListWidget::itemAssignment() @@ -825,7 +831,7 @@ void tst_QListWidget::selectedItems() QListWidgetItem *item = testWidget->item(i); item->setSelected(true); QVERIFY(item->isSelected()); - QCOMPARE(testWidget->selectedItems().count(), 1); + QCOMPARE(testWidget->selectedItems().size(), 1); } //let's clear the selection testWidget->clearSelection(); @@ -843,7 +849,7 @@ void tst_QListWidget::selectedItems() // check that the correct number of items and the expected items are there QList<QListWidgetItem *> selectedItems = testWidget->selectedItems(); - QCOMPARE(selectedItems.count(), expectedRows.count()); + QCOMPARE(selectedItems.size(), expectedRows.size()); for (int row : expectedRows) QVERIFY(selectedItems.contains(testWidget->item(row))); @@ -939,20 +945,20 @@ void tst_QListWidget::moveItemsPriv() else QCOMPARE(testWidget->item(dstRow)->text(), QString::number(srcRow)); - QCOMPARE(beginMoveSpy.count(), 1); + QCOMPARE(beginMoveSpy.size(), 1); const QList<QVariant> &beginMoveArgs = beginMoveSpy.takeFirst(); QCOMPARE(beginMoveArgs.at(1).toInt(), srcRow); QCOMPARE(beginMoveArgs.at(2).toInt(), srcRow); QCOMPARE(beginMoveArgs.at(4).toInt(), dstRow); - QCOMPARE(movedSpy.count(), 1); + QCOMPARE(movedSpy.size(), 1); const QList<QVariant> &movedArgs = movedSpy.takeFirst(); QCOMPARE(movedArgs.at(1).toInt(), srcRow); QCOMPARE(movedArgs.at(2).toInt(), srcRow); QCOMPARE(movedArgs.at(4).toInt(), dstRow); } else { - QCOMPARE(beginMoveSpy.count(), 0); - QCOMPARE(movedSpy.count(), 0); + QCOMPARE(beginMoveSpy.size(), 0); + QCOMPARE(movedSpy.size(), 0); } } @@ -1045,7 +1051,7 @@ void tst_QListWidget::sortItems() testWidget->sortItems(order); - QCOMPARE(testWidget->count(), expectedList.count()); + QCOMPARE(testWidget->count(), expectedList.size()); for (int i = 0; i < testWidget->count(); ++i) QCOMPARE(testWidget->item(i)->text(), expectedList.at(i).toString()); @@ -1115,7 +1121,7 @@ void tst_QListWidget::sortHiddenItems() tw->setSortingEnabled(true); tw->sortItems(order); - QCOMPARE(tw->count(), expectedList.count()); + QCOMPARE(tw->count(), expectedList.size()); for (int i = 0; i < tw->count(); ++i) { QCOMPARE(tw->item(i)->text(), expectedList.at(i)); QCOMPARE(tw->item(i)->isHidden(), !expectedVisibility.at(i)); @@ -1127,6 +1133,64 @@ void tst_QListWidget::sortHiddenItems() delete tw; } +void tst_QListWidget::sortCheckStability_data() { + QTest::addColumn<Qt::SortOrder>("order"); + QTest::addColumn<QVariantList>("initialList"); + QTest::addColumn<QVariantList>("expectedList"); + + QTest::newRow("ascending strings") + << Qt::AscendingOrder + << QVariantList{ QString("a"), QString("b"), QString("b"), QString("a")} + << QVariantList{ QString("a"), QString("a"), QString("b"), QString("b")}; + + QTest::newRow("descending strings") + << Qt::DescendingOrder + << QVariantList{ QString("a"), QString("b"), QString("b"), QString("a")} + << QVariantList{ QString("b"), QString("b"), QString("a"), QString("a")}; + + QTest::newRow("ascending numbers") + << Qt::AscendingOrder + << QVariantList{ 1, 2, 2, 1} + << QVariantList{ 1, 1, 2, 2}; + + QTest::newRow("descending numbers") + << Qt::DescendingOrder + << QVariantList{ 1, 2, 2, 1} + << QVariantList{ 2, 2, 1, 1}; +} + +void tst_QListWidget::sortCheckStability() { + QFETCH(Qt::SortOrder, order); + QFETCH(const QVariantList, initialList); + QFETCH(const QVariantList, expectedList); + + for (const QVariant &data : initialList) { + QListWidgetItem *item = new QListWidgetItem(testWidget); + item->setData(Qt::DisplayRole, data); + } + + QAbstractItemModel *model = testWidget->model(); + QList<QPersistentModelIndex> persistent; + for (int j = 0; j < model->rowCount(QModelIndex()); ++j) + persistent << model->index(j, 0, QModelIndex()); + + testWidget->sortItems(order); + + QCOMPARE(testWidget->count(), expectedList.size()); + for (int i = 0; i < testWidget->count(); ++i) + QCOMPARE(testWidget->item(i)->text(), expectedList.at(i).toString()); + + QVector<QListWidgetItem*> itemOrder(testWidget->count()); + for (int i = 0; i < testWidget->count(); ++i) + itemOrder[i] = testWidget->item(i); + + qobject_cast<QListModel*>(testWidget->model())->ensureSorted(0, order, 1, 1); + testWidget->sortItems(order); + + for (int i = 0; i < testWidget->count(); ++i) + QCOMPARE(itemOrder[i],testWidget->item(i)); +} + class TestListWidget : public QListWidget { Q_OBJECT @@ -1212,17 +1276,17 @@ void tst_QListWidget::setData() QFETCH(QVariantList, values); QFETCH(int, expectedSignalCount); - QCOMPARE(roles.count(), values.count()); + QCOMPARE(roles.size(), values.size()); for (int manipulateModel = 0; manipulateModel < 2; ++manipulateModel) { testWidget->clear(); testWidget->insertItems(0, initialItems); - QCOMPARE(testWidget->count(), initialItems.count()); + QCOMPARE(testWidget->count(), initialItems.size()); QSignalSpy itemChanged(testWidget, &QListWidget::itemChanged); QSignalSpy dataChanged(testWidget->model(), &QAbstractItemModel::dataChanged); - for (int i = 0; i < roles.count(); ++i) { + for (int i = 0; i < roles.size(); ++i) { if (manipulateModel) testWidget->model()->setData( testWidget->model()->index(itemIndex, 0, testWidget->rootIndex()), @@ -1233,12 +1297,12 @@ void tst_QListWidget::setData() } // make sure the data is actually set - for (int i = 0; i < roles.count(); ++i) + for (int i = 0; i < roles.size(); ++i) QCOMPARE(testWidget->item(itemIndex)->data(roles.at(i)), values.at(i)); // make sure we get the right number of emits - QCOMPARE(itemChanged.count(), expectedSignalCount); - QCOMPARE(dataChanged.count(), expectedSignalCount); + QCOMPARE(itemChanged.size(), expectedSignalCount); + QCOMPARE(dataChanged.size(), expectedSignalCount); } } @@ -1380,11 +1444,11 @@ void tst_QListWidget::insertItemsWithSorting() w.addItem(str); break; } - QCOMPARE(w.count(), expectedItems.count()); + QCOMPARE(w.count(), expectedItems.size()); for (int i = 0; i < w.count(); ++i) QCOMPARE(w.item(i)->text(), expectedItems.at(i)); - for (int k = 0; k < persistent.count(); ++k) + for (int k = 0; k < persistent.size(); ++k) QCOMPARE(persistent.at(k).row(), expectedRows.at(k)); } } @@ -1480,7 +1544,7 @@ void tst_QListWidget::itemData() QCOMPARE(widget.currentRoles, QList<int> { Qt::UserRole + i }); } QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0)); - QCOMPARE(flags.count(), 6); + QCOMPARE(flags.size(), 6); for (int i = 0; i < 4; ++i) QCOMPARE(flags[Qt::UserRole + i].toString(), QString::number(i + 1)); @@ -1524,19 +1588,19 @@ void tst_QListWidget::changeDataWithSorting() QListWidgetItem *item = w.item(itemIndex); item->setText(newValue); - for (int i = 0; i < expectedItems.count(); ++i) { + for (int i = 0; i < expectedItems.size(); ++i) { QCOMPARE(w.item(i)->text(), expectedItems.at(i)); - for (int j = 0; j < persistent.count(); ++j) { + for (int j = 0; j < persistent.size(); ++j) { if (persistent.at(j).row() == i) // the same toplevel row QCOMPARE(persistent.at(j).internalPointer(), static_cast<void *>(w.item(i))); } } - for (int k = 0; k < persistent.count(); ++k) + for (int k = 0; k < persistent.size(); ++k) QCOMPARE(persistent.at(k).row(), expectedRows.at(k)); - QCOMPARE(dataChangedSpy.count(), 1); - QCOMPARE(layoutChangedSpy.count(), reorderingExpected ? 1 : 0); + QCOMPARE(dataChangedSpy.size(), 1); + QCOMPARE(layoutChangedSpy.size(), reorderingExpected ? 1 : 0); } void tst_QListWidget::itemWidget() @@ -1615,7 +1679,7 @@ void tst_QListWidget::insertUnchanged() QListWidget w; QSignalSpy itemChangedSpy(&w, &QListWidget::itemChanged); QListWidgetItem item("foo", &w); - QCOMPARE(itemChangedSpy.count(), 0); + QCOMPARE(itemChangedSpy.size(), 0); } void tst_QListWidget::setSortingEnabled() @@ -1706,12 +1770,12 @@ void tst_QListWidget::QTBUG8086_currentItemChangedOnClick() QVERIFY(QTest::qWaitForWindowExposed(&win)); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QTest::mouseClick(list.viewport(), Qt::LeftButton, {}, list.visualItemRect(list.item(2)).center()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } @@ -1746,7 +1810,6 @@ void tst_QListWidget::QTBUG14363_completerWithAnyKeyPressedEditTriggers() new QListWidgetItem(QLatin1String("completer"), &listWidget); listWidget.show(); listWidget.setCurrentItem(item); - QApplication::setActiveWindow(&listWidget); QVERIFY(QTest::qWaitForWindowActive(&listWidget)); listWidget.setFocus(); QCOMPARE(QApplication::focusWidget(), &listWidget); @@ -1810,14 +1873,14 @@ void tst_QListWidget::QTBUG50891_ensureSelectionModelSignalConnectionsAreSet() QSignalSpy currentItemChangedSpy(&list, &QListWidget::currentItemChanged); QSignalSpy itemSelectionChangedSpy(&list, &QListWidget::itemSelectionChanged); - QCOMPARE(currentItemChangedSpy.count(), 0); - QCOMPARE(itemSelectionChangedSpy.count(), 0); + QCOMPARE(currentItemChangedSpy.size(), 0); + QCOMPARE(itemSelectionChangedSpy.size(), 0); QTest::mouseClick(list.viewport(), Qt::LeftButton, {}, list.visualItemRect(list.item(2)).center()); - QCOMPARE(currentItemChangedSpy.count(), 1); - QCOMPARE(itemSelectionChangedSpy.count(), 1); + QCOMPARE(currentItemChangedSpy.size(), 1); + QCOMPARE(itemSelectionChangedSpy.size(), 1); } @@ -1887,6 +1950,58 @@ void tst_QListWidget::createPersistentOnLayoutAboutToBeChangedAutoSort() // QTBU QCOMPARE(layoutChangedSpy.size(), 1); } +// Test that dropping an item on or beneath itself remains a no-op +void tst_QListWidget::noopDragDrop() // QTBUG-100128 +{ + QListWidget listWidget; + QList<QListWidgetItem *> items; + for (int i = 0; i < 5; ++i) { + const QString number = QString::number(i); + QListWidgetItem *item = new QListWidgetItem(&listWidget); + item->setData(Qt::UserRole, number); + QLabel *label = new QLabel(number); + listWidget.setItemWidget(item, label); + items.append(item); + } + + listWidget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&listWidget)); + + const QRect &lastItemRect = listWidget.visualItemRect(items.at(4)); + const QPoint &dragStart = lastItemRect.center(); + const QPoint &dropPointNirvana = lastItemRect.center() + QPoint(20, 2 * lastItemRect.height()); + + // Implement check as a macro (not a method) to safely determine the error location. + // The macro checks that item data and item widget remain unchanged when drag&drop are executed. + // In order to verify that the assets do *not* change, we can't use QTRY*: These macros would + // spin the event loop only once, while 3/4 mouse events need to get processed. + // That's why we spin the event loop 13 times, to make sure other unexpected or pending events + // get processed. +#define CHECK_ITEM {\ + const QString number = QString::number(4);\ + for (int i = 0; i < 13; ++i)\ + QApplication::processEvents();\ + QLabel *label = qobject_cast<QLabel *>(listWidget.itemWidget(items.at(4)));\ + QVERIFY(label);\ + QCOMPARE(label->text(), number);\ + const QString &data = items.at(4)->data(Qt::UserRole).toString();\ + QCOMPARE(data, number);\ + } + + // Test dropping last item beneath itself + QTest::mousePress(&listWidget, Qt::LeftButton, Qt::KeyboardModifiers(), dragStart); + QTest::mouseMove(&listWidget, dropPointNirvana); + QTest::mouseRelease(&listWidget, Qt::LeftButton); + CHECK_ITEM; + + // Test dropping last item on itself + QTest::mousePress(&listWidget, Qt::LeftButton, Qt::KeyboardModifiers(), dragStart); + QTest::mouseMove(&listWidget, dropPointNirvana); + QTest::mouseMove(&listWidget, dragStart); + QTest::mouseRelease(&listWidget, Qt::LeftButton); + CHECK_ITEM; +} + #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) void tst_QListWidget::clearItemData() { diff --git a/tests/auto/widgets/itemviews/qtableview/CMakeLists.txt b/tests/auto/widgets/itemviews/qtableview/CMakeLists.txt index f72e9b7bbd..af78c0f5d3 100644 --- a/tests/auto/widgets/itemviews/qtableview/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qtableview/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qtableview.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtableview Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtableview LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtableview SOURCES tst_qtableview.cpp diff --git a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp index edd5453259..681be2491d 100644 --- a/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp +++ b/tests/auto/widgets/itemviews/qtableview/tst_qtableview.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QIdentityProxyModel> #include <QLabel> @@ -52,6 +52,13 @@ public: : QAbstractTableModel(parent), row_count(rows), column_count(columns) {} + void insertRows(int rows) + { + beginInsertRows(QModelIndex(), row_count, row_count + rows - 1); + row_count += rows; + endInsertRows(); + } + int rowCount(const QModelIndex& = QModelIndex()) const override { return row_count; @@ -384,6 +391,7 @@ private slots: void resizeToContents(); void resizeToContentsSpans(); + void resizeToContentsEarly(); void tabFocus(); void bigModel(); @@ -416,6 +424,7 @@ private slots: void selectColumnsAndCells(); void selectWithHeader_data(); void selectWithHeader(); + void resetDefaultSectionSize(); #if QT_CONFIG(wheelevent) void mouseWheel_data(); @@ -429,6 +438,7 @@ private slots: void viewOptions(); void taskQTBUG_7232_AllowUserToControlSingleStep(); + void rowsInVerticalHeader(); #if QT_CONFIG(textmarkdownwriter) void markdownWriter(); @@ -503,7 +513,7 @@ void tst_QTableView::emptyModel() QSignalSpy spy(&model, &QtTestTableModel::invalidIndexEncountered); view.setModel(&model); view.show(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QTableView::removeRows_data() @@ -528,10 +538,10 @@ void tst_QTableView::removeRows() view.show(); model.removeLastRow(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); model.removeAllRows(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QTableView::removeColumns_data() @@ -556,10 +566,10 @@ void tst_QTableView::removeColumns() view.show(); model.removeLastColumn(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); model.removeAllColumns(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QTableView::keyboardNavigation_data() @@ -600,7 +610,6 @@ void tst_QTableView::keyboardNavigation() view.setCurrentIndex(index); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); int row = rowCount - 1; @@ -1597,7 +1606,7 @@ void tst_QTableView::selection() view.setSelection(QRect(x, y, width, height), command); - QCOMPARE(view.selectedIndexes().count(), selectedCount); + QCOMPARE(view.selectedIndexes().size(), selectedCount); } void tst_QTableView::selectRow_data() @@ -1710,12 +1719,12 @@ void tst_QTableView::selectRow() view.setSelectionMode(mode); view.setSelectionBehavior(behavior); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 0); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 0); view.selectRow(row); //test we have 10 items selected - QCOMPARE(view.selectionModel()->selectedIndexes().count(), selectedItems); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), selectedItems); //test that all 10 items are in the same row for (int i = 0; selectedItems > 0 && i < rowCount; ++i) QCOMPARE(view.selectionModel()->selectedIndexes().at(i).row(), row); @@ -1831,11 +1840,11 @@ void tst_QTableView::selectColumn() view.setSelectionMode(mode); view.setSelectionBehavior(behavior); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), 0); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), 0); view.selectColumn(column); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), selectedItems); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), selectedItems); for (int i = 0; selectedItems > 0 && i < columnCount; ++i) QCOMPARE(view.selectionModel()->selectedIndexes().at(i).column(), column); } @@ -1980,22 +1989,22 @@ void tst_QTableView::selectall() // try slot first view.clearSelection(); - QCOMPARE(view.selectedIndexes().count(), 0); + QCOMPARE(view.selectedIndexes().size(), 0); view.selectAll(); - QCOMPARE(view.selectedIndexes().count(), selectedCount); + QCOMPARE(view.selectedIndexes().size(), selectedCount); // try by key sequence view.clearSelection(); - QCOMPARE(view.selectedIndexes().count(), 0); + QCOMPARE(view.selectedIndexes().size(), 0); QTest__keySequence(&view, QKeySequence(QKeySequence::SelectAll)); - QCOMPARE(view.selectedIndexes().count(), selectedCount); + QCOMPARE(view.selectedIndexes().size(), selectedCount); // check again with no selection mode view.clearSelection(); view.setSelectionMode(QAbstractItemView::NoSelection); - QCOMPARE(view.selectedIndexes().count(), 0); + QCOMPARE(view.selectedIndexes().size(), 0); QTest__keySequence(&view, QKeySequence(QKeySequence::SelectAll)); - QCOMPARE(view.selectedIndexes().count(), 0); + QCOMPARE(view.selectedIndexes().size(), 0); } #endif // QT_CONFIG(shortcut) @@ -2188,7 +2197,7 @@ void tst_QTableView::resizeRowsToContents() QSignalSpy resizedSpy(view.verticalHeader(), &QHeaderView::sectionResized); view.resizeRowsToContents(); - QCOMPARE(resizedSpy.count(), model.rowCount()); + QCOMPARE(resizedSpy.size(), model.rowCount()); for (int r = 0; r < model.rowCount(); ++r) QCOMPARE(view.rowHeight(r), rowHeight); } @@ -2234,7 +2243,7 @@ void tst_QTableView::resizeColumnsToContents() QSignalSpy resizedSpy(view.horizontalHeader(), &QHeaderView::sectionResized); view.resizeColumnsToContents(); - QCOMPARE(resizedSpy.count(), model.columnCount()); + QCOMPARE(resizedSpy.size(), model.columnCount()); for (int c = 0; c < model.columnCount(); ++c) QCOMPARE(view.columnWidth(c), columnWidth); } @@ -2348,7 +2357,7 @@ void tst_QTableView::rowAt() for (int r = 0; r < rowCount; ++r) view.setRowHeight(r, rowHeight); - for (int i = 0; i < hiddenRows.count(); ++i) + for (int i = 0; i < hiddenRows.size(); ++i) view.hideRow(hiddenRows.at(i)); QCOMPARE(view.rowAt(coordinate), row); @@ -2511,7 +2520,7 @@ void tst_QTableView::columnAt() for (int c = 0; c < columnCount; ++c) view.setColumnWidth(c, columnWidth); - for (int i = 0; i < hiddenColumns.count(); ++i) + for (int i = 0; i < hiddenColumns.size(); ++i) view.hideColumn(hiddenColumns.at(i)); QCOMPARE(view.columnAt(coordinate), column); @@ -3768,6 +3777,35 @@ void tst_QTableView::resizeToContentsSpans() QCOMPARE(view2.columnWidth(0), view3.columnWidth(0) - view2.columnWidth(1)); } +void tst_QTableView::resizeToContentsEarly() +{ + QStringListModel model; + QTableView view; + + // connect to the model before setting it on the view + connect(&model, &QStringListModel::modelReset, &model, [&view]{ + view.resizeColumnsToContents(); + }); + connect(&model, &QStringListModel::modelReset, &model, [&view]{ + view.resizeRowsToContents(); + }); + + // the view only connects now to the model's signals, so responds to the + // reset signal *after* the lambdas above + view.setModel(&model); + + QStringList data(200, QString("Hello World")); + model.setStringList(data); + + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum()); + + data = data.sliced(data.size() / 2); + model.setStringList(data); +} + QT_BEGIN_NAMESPACE extern bool Q_WIDGETS_EXPORT qt_tab_all_widgets(); // qapplication.cpp QT_END_NAMESPACE @@ -3790,7 +3828,6 @@ void tst_QTableView::tabFocus() QLineEdit *edit = new QLineEdit(&window); window.show(); - QApplication::setActiveWindow(&window); window.setFocus(); window.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&window)); @@ -4865,7 +4902,7 @@ void tst_QTableView::selectWithHeader() QVERIFY(QTest::qWaitForWindowExposed(&view)); - QHeaderView *header; + QHeaderView *header = nullptr; QPoint clickPos; QModelIndex lastIndex; @@ -4901,6 +4938,22 @@ void tst_QTableView::selectWithHeader() QVERIFY(!isSelected()); } +void tst_QTableView::resetDefaultSectionSize() +{ + // Create a table and change its default section size and then reset it. + // This should be a no op so clicking on row 1 should select row 1 and not row + // 0 as previously. QTBUG-116013 + QTableWidget view(10, 10); + view.resize(300, 300); + view.verticalHeader()->setSectionResizeMode(QHeaderView::Fixed); + view.verticalHeader()->setDefaultSectionSize(120); + view.verticalHeader()->resetDefaultSectionSize(); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + QEXPECT_FAIL("", "Reverted fix for QTBUG-116013 due to QTBUG-122109", Continue); + QCOMPARE(view.verticalHeader()->logicalIndexAt(9, 45), 1); +} + // This has nothing to do with QTableView, but it's convenient to reuse the QtTestTableModel #if QT_CONFIG(textmarkdownwriter) @@ -4929,5 +4982,18 @@ void tst_QTableView::markdownWriter() } #endif +void tst_QTableView::rowsInVerticalHeader() +{ + QtTestTableModel model(0, 2); + QTableView view; + view.setModel(&model); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + auto *verticalHeader = view.verticalHeader(); + QCOMPARE(verticalHeader->count(), 0); + model.insertRows(2); + QCOMPARE(verticalHeader->count(), 2); +} + QTEST_MAIN(tst_QTableView) #include "tst_qtableview.moc" diff --git a/tests/auto/widgets/itemviews/qtablewidget/CMakeLists.txt b/tests/auto/widgets/itemviews/qtablewidget/CMakeLists.txt index f22c839941..306ba4bdff 100644 --- a/tests/auto/widgets/itemviews/qtablewidget/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qtablewidget/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qtablewidget.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtablewidget Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtablewidget LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtablewidget SOURCES tst_qtablewidget.cpp diff --git a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp index 39cbe0ab66..34972bc3e8 100644 --- a/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp +++ b/tests/auto/widgets/itemviews/qtablewidget/tst_qtablewidget.cpp @@ -1,9 +1,10 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QHeaderView> #include <QLineEdit> #include <QMimeData> +#include <QScrollBar> #include <QSignalSpy> #include <QTableWidget> #include <QTest> @@ -63,6 +64,7 @@ private slots: void task219380_removeLastRow(); void task262056_sortDuplicate(); void itemWithHeaderItems(); + void checkHeaderItemFlagsConflict(); void mimeData(); void selectedRowAfterSorting(); void search(); @@ -192,8 +194,8 @@ void tst_QTableWidget::clear() QVERIFY(bla.isNull()); QVERIFY(!testWidget->item(0,0)); - QVERIFY(!testWidget->selectedRanges().count()); - QVERIFY(!testWidget->selectedItems().count()); + QVERIFY(!testWidget->selectedRanges().size()); + QVERIFY(!testWidget->selectedItems().size()); } void tst_QTableWidget::rowCount() @@ -360,7 +362,7 @@ void tst_QTableWidget::takeItem() QCOMPARE(item->text(), QString::number(row * column + column)); delete item; - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); const QList<QVariant> arguments = spy.takeFirst(); QCOMPARE(arguments.size(), 2); QCOMPARE(arguments.at(0).toInt(), row); @@ -525,24 +527,24 @@ void tst_QTableWidget::selectedItems() testWidget->setColumnHidden(column, true); // make sure we don't have any previous selections hanging around - QVERIFY(!testWidget->selectedRanges().count()); - QVERIFY(!testWidget->selectedItems().count()); + QVERIFY(!testWidget->selectedRanges().size()); + QVERIFY(!testWidget->selectedItems().size()); // select range and check that it is set correctly testWidget->setRangeSelected(selectionRange, true); if (selectionRange.topRow() >= 0) { - QCOMPARE(testWidget->selectedRanges().count(), 1); + QCOMPARE(testWidget->selectedRanges().size(), 1); QCOMPARE(testWidget->selectedRanges().at(0).topRow(), selectionRange.topRow()); QCOMPARE(testWidget->selectedRanges().at(0).bottomRow(), selectionRange.bottomRow()); QCOMPARE(testWidget->selectedRanges().at(0).leftColumn(), selectionRange.leftColumn()); QCOMPARE(testWidget->selectedRanges().at(0).rightColumn(), selectionRange.rightColumn()); } else { - QCOMPARE(testWidget->selectedRanges().count(), 0); + QCOMPARE(testWidget->selectedRanges().size(), 0); } // check that the correct number of items and the expected items are there const QList<QTableWidgetItem *> selectedItems = testWidget->selectedItems(); - QCOMPARE(selectedItems.count(), expectedItems.count()); + QCOMPARE(selectedItems.size(), expectedItems.size()); for (const auto &intPair : expectedItems) QVERIFY(selectedItems.contains(testWidget->item(intPair.first, intPair.second))); @@ -627,7 +629,7 @@ void tst_QTableWidget::selectedSpannedCells() // QTBUG-255 testWidget.visualRect(testWidget.model()->index(selectionEndCell.y(), selectionEndCell.x())).center()); auto ranges = testWidget.selectedRanges(); - QCOMPARE(ranges.count(), expectedSelectionRangeCount); + QCOMPARE(ranges.size(), expectedSelectionRangeCount); QCOMPARE(ranges.first(), expectedFirstSelectionRange); } @@ -1194,15 +1196,15 @@ void tst_QTableWidget::sortItems() persistent << model->index(r, sortColumn, QModelIndex()); } - for (int h = 0; h < initialHidden.count(); ++h) + for (int h = 0; h < initialHidden.size(); ++h) testWidget->hideRow(initialHidden.at(h)); - QCOMPARE(testWidget->verticalHeader()->hiddenSectionCount(), initialHidden.count()); + QCOMPARE(testWidget->verticalHeader()->hiddenSectionCount(), initialHidden.size()); testWidget->sortItems(sortColumn, sortOrder); int te = 0; - for (int i = 0; i < rows.count(); ++i) { + for (int i = 0; i < rows.size(); ++i) { for (int j = 0; j < columnCount; ++j) { QString value; QTableWidgetItem *itm = testWidget->item(i, j); @@ -1216,7 +1218,7 @@ void tst_QTableWidget::sortItems() // << "expected" << rows.at(i); } - for (int k = 0; k < expectedHidden.count(); ++k) + for (int k = 0; k < expectedHidden.size(); ++k) QVERIFY(testWidget->isRowHidden(expectedHidden.at(k))); } @@ -1397,18 +1399,18 @@ void tst_QTableWidget::setItemWithSorting() } } - for (int k = 0; k < persistent.count(); ++k) { + for (int k = 0; k < persistent.size(); ++k) { QCOMPARE(persistent.at(k).row(), expectedRows.at(k)); int i = (persistent.at(k).row() * columnCount) + sortColumn; QCOMPARE(persistent.at(k).data().toString(), expectedValues.at(i)); } if (i == 0) - QCOMPARE(dataChangedSpy.count(), reorderingExpected ? 0 : 1); + QCOMPARE(dataChangedSpy.size(), reorderingExpected ? 0 : 1); else - QCOMPARE(dataChangedSpy.count(), 1); + QCOMPARE(dataChangedSpy.size(), 1); - QCOMPARE(layoutChangedSpy.count(), reorderingExpected ? 1 : 0); + QCOMPARE(layoutChangedSpy.size(), reorderingExpected ? 1 : 0); } } @@ -1444,7 +1446,7 @@ void tst_QTableWidget::itemData() QCOMPARE(widget.currentRoles, QList<int> { Qt::UserRole + i }); } QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0)); - QCOMPARE(flags.count(), 6); + QCOMPARE(flags.size(), 6); for (int i = 0; i < 4; ++i) QCOMPARE(flags[Qt::UserRole + i].toString(), QString::number(i + 1)); } @@ -1457,7 +1459,7 @@ void tst_QTableWidget::setItemData() QTableWidgetItem *item = new QTableWidgetItem; table.setItem(0, 0, item); - QCOMPARE(dataChangedSpy.count(), 1); + QCOMPARE(dataChangedSpy.size(), 1); QModelIndex idx = qvariant_cast<QModelIndex>(dataChangedSpy.takeFirst().at(0)); QMap<int, QVariant> data; @@ -1469,7 +1471,7 @@ void tst_QTableWidget::setItemData() QCOMPARE(table.model()->data(idx, Qt::DisplayRole).toString(), QLatin1String("Display")); QCOMPARE(table.model()->data(idx, Qt::EditRole).toString(), QLatin1String("Display")); QCOMPARE(table.model()->data(idx, Qt::ToolTipRole).toString(), QLatin1String("ToolTip")); - QCOMPARE(dataChangedSpy.count(), 1); + QCOMPARE(dataChangedSpy.size(), 1); QCOMPARE(idx, qvariant_cast<QModelIndex>(dataChangedSpy.first().at(0))); QCOMPARE(idx, qvariant_cast<QModelIndex>(dataChangedSpy.first().at(1))); const auto roles = qvariant_cast<QList<int>>(dataChangedSpy.first().at(2)); @@ -1480,13 +1482,13 @@ void tst_QTableWidget::setItemData() dataChangedSpy.clear(); table.model()->setItemData(idx, data); - QCOMPARE(dataChangedSpy.count(), 0); + QCOMPARE(dataChangedSpy.size(), 0); data.clear(); data.insert(Qt::DisplayRole, QLatin1String("dizplaye")); table.model()->setItemData(idx, data); QCOMPARE(table.model()->data(idx, Qt::DisplayRole).toString(), QLatin1String("dizplaye")); - QCOMPARE(dataChangedSpy.count(), 1); + QCOMPARE(dataChangedSpy.size(), 1); QCOMPARE(QList<int>({ Qt::DisplayRole, Qt::EditRole }), qvariant_cast<QList<int>>(dataChangedSpy.first().at(2))); @@ -1555,6 +1557,12 @@ void tst_QTableWidget::sizeHint() QFETCH(Qt::ScrollBarPolicy, scrollBarPolicy); QFETCH(QSize, viewSize); + const QString defaultStyle = QApplication::style()->name(); + QApplication::setStyle("windows"); + const auto resetStyle = qScopeGuard([defaultStyle]{ + QApplication::setStyle(defaultStyle); + }); + QTableWidget view(2, 2); view.setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); view.setVerticalScrollBarPolicy(scrollBarPolicy); @@ -1574,18 +1582,21 @@ void tst_QTableWidget::sizeHint() QTRY_COMPARE(view.size(), viewSize); } + QApplication::processEvents(); // execute delayed layouts auto sizeHint = view.sizeHint(); view.hide(); QCOMPARE(view.sizeHint(), sizeHint); view.horizontalHeader()->hide(); view.show(); + QApplication::processEvents(); // execute delayed layouts sizeHint = view.sizeHint(); view.hide(); QCOMPARE(view.sizeHint(), sizeHint); view.verticalHeader()->hide(); view.show(); + QApplication::processEvents(); // execute delayed layouts sizeHint = view.sizeHint(); view.hide(); QCOMPARE(view.sizeHint(), sizeHint); @@ -1649,7 +1660,7 @@ void tst_QTableWidget::task262056_sortDuplicate() QSignalSpy layoutChangedSpy(testWidget->model(), &QAbstractItemModel::layoutChanged); testWidget->item(3,0)->setBackground(Qt::red); - QCOMPARE(layoutChangedSpy.count(),0); + QCOMPARE(layoutChangedSpy.size(),0); } @@ -1669,6 +1680,25 @@ void tst_QTableWidget::itemWithHeaderItems() QCOMPARE(table.item(0, 1), nullptr); } +void tst_QTableWidget::checkHeaderItemFlagsConflict() +{ + // QTBUG-113209 + // Check that setting header item doesn't set Qt::ItemNeverHasChildren + // Chech that header items do not emit itemChanged. + QTableWidget table(1, 1); + QSignalSpy itemChangeSpy(&table, &QTableWidget::itemChanged); + QVERIFY(itemChangeSpy.isValid()); + + QTableWidgetItem *item = new QTableWidgetItem("Initial"); + table.setHorizontalHeaderItem(0, item); + + QVERIFY(!(item->flags() & Qt::ItemNeverHasChildren)); + + item->setData(Qt::DisplayRole, "updated"); + + QCOMPARE(itemChangeSpy.size(), 0); +} + class TestTableWidget : public QTableWidget { Q_OBJECT @@ -1746,7 +1776,7 @@ void tst_QTableWidget::selectedRowAfterSorting() table.setProperty("sortingEnabled",true); table.selectRow(1); table.item(1,1)->setText("9"); - QCOMPARE(table.selectedItems().count(),3); + QCOMPARE(table.selectedItems().size(),3); const auto selectedItems = table.selectedItems(); for (QTableWidgetItem *item : selectedItems) QCOMPARE(item->row(), 0); diff --git a/tests/auto/widgets/itemviews/qtreeview/BLACKLIST b/tests/auto/widgets/itemviews/qtreeview/BLACKLIST deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/auto/widgets/itemviews/qtreeview/BLACKLIST +++ /dev/null diff --git a/tests/auto/widgets/itemviews/qtreeview/CMakeLists.txt b/tests/auto/widgets/itemviews/qtreeview/CMakeLists.txt index 15817f5478..deccd71f59 100644 --- a/tests/auto/widgets/itemviews/qtreeview/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qtreeview/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qtreeview.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtreeview Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtreeview LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtreeview SOURCES ../../../../shared/fakedirmodel.h diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp index 8fa942dd06..9b02b0e80d 100644 --- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "../../../../shared/fakedirmodel.h" @@ -24,6 +24,8 @@ #include <private/qtreeview_p.h> #include <private/qtesthelpers_p.h> +#include <QtWidgets/private/qapplication_p.h> + using namespace QTestPrivate; #if QT_CONFIG(draganddrop) @@ -1238,7 +1240,6 @@ void tst_QTreeView::keyboardSearchMultiColumn() view.setModel(&model); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); view.setCurrentIndex(model.index(0, 1)); @@ -1279,7 +1280,7 @@ void tst_QTreeView::setModel() QCOMPARE(view.header()->model(), model); QCOMPARE(view.selectionModel() != oldSelectionModel, (i == 0)); } - QTRY_COMPARE(modelDestroyedSpy.count(), 0); + QTRY_COMPARE(modelDestroyedSpy.size(), 0); view.setModel(nullptr); QCOMPARE(view.model(), nullptr); @@ -1334,7 +1335,7 @@ void tst_QTreeView::setHeader() Qt::Orientation orient = x ? Qt::Vertical : Qt::Horizontal; QHeaderView *head = new QHeaderView(orient); view.setHeader(head); - QCOMPARE(destroyedSpy.count(), 1); + QCOMPARE(destroyedSpy.size(), 1); QCOMPARE(head->parent(), &view); QCOMPARE(view.header(), head); view.setHeader(head); @@ -1517,10 +1518,10 @@ void tst_QTreeView::limitedExpand() QVERIFY(spy.isValid()); view.expand(model.index(0, 0)); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); view.expand(model.index(1, 0)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } { QStringListModel model(QStringList() << "one" << "two"); @@ -1531,9 +1532,9 @@ void tst_QTreeView::limitedExpand() QVERIFY(spy.isValid()); view.expand(model.index(0, 0)); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); view.expandAll(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } } @@ -1572,58 +1573,58 @@ void tst_QTreeView::expandAndCollapse() view.expand(QModelIndex()); QCOMPARE(view.isExpanded(QModelIndex()), false); view.collapse(QModelIndex()); - QCOMPARE(expandedSpy.count(), 0); - QCOMPARE(collapsedSpy.count(), 0); + QCOMPARE(expandedSpy.size(), 0); + QCOMPARE(collapsedSpy.size(), 0); // expand a first level item QVERIFY(!view.isExpanded(a)); view.expand(a); QVERIFY(view.isExpanded(a)); - QCOMPARE(expandedSpy.count(), 1); - QCOMPARE(collapsedSpy.count(), 0); + QCOMPARE(expandedSpy.size(), 1); + QCOMPARE(collapsedSpy.size(), 0); args = expandedSpy.takeFirst(); QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a); view.expand(a); QVERIFY(view.isExpanded(a)); - QCOMPARE(expandedSpy.count(), 0); - QCOMPARE(collapsedSpy.count(), 0); + QCOMPARE(expandedSpy.size(), 0); + QCOMPARE(collapsedSpy.size(), 0); // expand a second level item QVERIFY(!view.isExpanded(b)); view.expand(b); QVERIFY(view.isExpanded(a)); QVERIFY(view.isExpanded(b)); - QCOMPARE(expandedSpy.count(), 1); - QCOMPARE(collapsedSpy.count(), 0); + QCOMPARE(expandedSpy.size(), 1); + QCOMPARE(collapsedSpy.size(), 0); args = expandedSpy.takeFirst(); QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), b); view.expand(b); QVERIFY(view.isExpanded(b)); - QCOMPARE(expandedSpy.count(), 0); - QCOMPARE(collapsedSpy.count(), 0); + QCOMPARE(expandedSpy.size(), 0); + QCOMPARE(collapsedSpy.size(), 0); // collapse the first level item view.collapse(a); QVERIFY(!view.isExpanded(a)); QVERIFY(view.isExpanded(b)); - QCOMPARE(expandedSpy.count(), 0); - QCOMPARE(collapsedSpy.count(), 1); + QCOMPARE(expandedSpy.size(), 0); + QCOMPARE(collapsedSpy.size(), 1); args = collapsedSpy.takeFirst(); QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a); view.collapse(a); QVERIFY(!view.isExpanded(a)); - QCOMPARE(expandedSpy.count(), 0); - QCOMPARE(collapsedSpy.count(), 0); + QCOMPARE(expandedSpy.size(), 0); + QCOMPARE(collapsedSpy.size(), 0); // expand the first level item again view.expand(a); QVERIFY(view.isExpanded(a)); QVERIFY(view.isExpanded(b)); - QCOMPARE(expandedSpy.count(), 1); - QCOMPARE(collapsedSpy.count(), 0); + QCOMPARE(expandedSpy.size(), 1); + QCOMPARE(collapsedSpy.size(), 0); args = expandedSpy.takeFirst(); QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a); @@ -1631,8 +1632,8 @@ void tst_QTreeView::expandAndCollapse() view.collapse(b); QVERIFY(view.isExpanded(a)); QVERIFY(!view.isExpanded(b)); - QCOMPARE(expandedSpy.count(), 0); - QCOMPARE(collapsedSpy.count(), 1); + QCOMPARE(expandedSpy.size(), 0); + QCOMPARE(collapsedSpy.size(), 1); args = collapsedSpy.takeFirst(); QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), b); @@ -1640,8 +1641,8 @@ void tst_QTreeView::expandAndCollapse() view.collapse(a); QVERIFY(!view.isExpanded(a)); QVERIFY(!view.isExpanded(b)); - QCOMPARE(expandedSpy.count(), 0); - QCOMPARE(collapsedSpy.count(), 1); + QCOMPARE(expandedSpy.size(), 0); + QCOMPARE(collapsedSpy.size(), 1); args = collapsedSpy.takeFirst(); QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a); @@ -1653,8 +1654,8 @@ void tst_QTreeView::expandAndCollapse() QVERIFY(view.isExpanded(a)); QVERIFY(view.isExpanded(b)); QVERIFY(!view.isExpanded(c)); - QCOMPARE(expandedSpy.count(), 2); - QCOMPARE(collapsedSpy.count(), 0); + QCOMPARE(expandedSpy.size(), 2); + QCOMPARE(collapsedSpy.size(), 0); args = expandedSpy.takeFirst(); QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a); args = expandedSpy.takeFirst(); @@ -1665,8 +1666,8 @@ void tst_QTreeView::expandAndCollapse() QVERIFY(!view.isExpanded(a)); QVERIFY(!view.isExpanded(b)); QVERIFY(!view.isExpanded(c)); - QCOMPARE(expandedSpy.count(), 0); - QCOMPARE(collapsedSpy.count(), 2); + QCOMPARE(expandedSpy.size(), 0); + QCOMPARE(collapsedSpy.size(), 2); args = collapsedSpy.takeFirst(); QCOMPARE(qvariant_cast<QModelIndex>(args.at(0)), a); args = collapsedSpy.takeFirst(); @@ -1728,22 +1729,22 @@ void tst_QTreeView::expandAndCollapseAll() view.expandAll(); checkExpandState(model, view, QModelIndex(), true, &count); - QCOMPARE(collapsedSpy.count(), 0); - QCOMPARE(expandedSpy.count(), 39); // == 3 (first) + 9 (second) + 27 (third level) + QCOMPARE(collapsedSpy.size(), 0); + QCOMPARE(expandedSpy.size(), 39); // == 3 (first) + 9 (second) + 27 (third level) QCOMPARE(count, 39); collapsedSpy.clear(); expandedSpy.clear(); view.collapseAll(); checkExpandState(model, view, QModelIndex(), false, &count); - QCOMPARE(collapsedSpy.count(), 39); - QCOMPARE(expandedSpy.count(), 0); + QCOMPARE(collapsedSpy.size(), 39); + QCOMPARE(expandedSpy.size(), 0); QCOMPARE(count, 39); collapsedSpy.clear(); expandedSpy.clear(); view.expandRecursively(model.index(0, 0)); - QCOMPARE(expandedSpy.count(), 13); // 1 + 3 + 9 + QCOMPARE(expandedSpy.size(), 13); // 1 + 3 + 9 checkExpandState(model, view, model.index(0, 0), true, &count); QCOMPARE(count, 13); @@ -1755,9 +1756,9 @@ void tst_QTreeView::expandAndCollapseAll() expandedSpy.clear(); view.collapseAll(); view.expandRecursively(model.index(0, 0), 1); - QCOMPARE(expandedSpy.count(), 4); // 1 + 3 + QCOMPARE(expandedSpy.size(), 4); // 1 + 3 view.expandRecursively(model.index(0, 0), 2); - QCOMPARE(expandedSpy.count(), 13); // (1 + 3) + 9 + QCOMPARE(expandedSpy.size(), 13); // (1 + 3) + 9 checkExpandState(model, view, model.index(0, 0), true, &count); QCOMPARE(count, 13); @@ -1924,7 +1925,6 @@ void tst_QTreeView::moveCursor() view.setColumnHidden(0, true); QVERIFY(view.isColumnHidden(0)); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); //here the first visible index should be selected @@ -2043,7 +2043,7 @@ void tst_QTreeView::setSelection() QVERIFY(selectionModel); const QModelIndexList selectedIndexes = selectionModel->selectedIndexes(); - QCOMPARE(selectedIndexes.count(), expectedItems.count()); + QCOMPARE(selectedIndexes.size(), expectedItems.size()); for (const QModelIndex &idx : selectedIndexes) QVERIFY(expectedItems.contains(QPoint(idx.column(), idx.row()))); } @@ -2147,7 +2147,7 @@ void tst_QTreeView::clicked() continue; QSignalSpy spy(&view, &QTreeView::clicked); QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); } } @@ -2228,7 +2228,7 @@ void tst_QTreeView::rowsAboutToBeRemoved() model.removeRows(1,1); QCOMPARE((view.state()), 0); // Should not be 5 (or any other number for that sake :) - QCOMPARE(spy1.count(), 1); + QCOMPARE(spy1.size(), 1); } @@ -2540,28 +2540,28 @@ void tst_QTreeView::selectionWithHiddenItems() //child should not be selected as it is hidden (its parent is not expanded) view.selectAll(); - QCOMPARE(view.selectionModel()->selection().count(), 1); //one range - QCOMPARE(view.selectionModel()->selectedRows().count(), 4); + QCOMPARE(view.selectionModel()->selection().size(), 1); //one range + QCOMPARE(view.selectionModel()->selectedRows().size(), 4); view.expandAll(); QVERIFY(view.isExpanded(item1.index())); - QCOMPARE(view.selectionModel()->selection().count(), 1); - QCOMPARE(view.selectionModel()->selectedRows().count(), 4); + QCOMPARE(view.selectionModel()->selection().size(), 1); + QCOMPARE(view.selectionModel()->selectedRows().size(), 4); QVERIFY( !view.selectionModel()->isSelected(model.indexFromItem(&child))); view.clearSelection(); QVERIFY(view.isExpanded(item1.index())); //child should be selected as it is visible (its parent is expanded) view.selectAll(); - QCOMPARE(view.selectionModel()->selection().count(), 2); - QCOMPARE(view.selectionModel()->selectedRows().count(), 5); //everything is selected + QCOMPARE(view.selectionModel()->selection().size(), 2); + QCOMPARE(view.selectionModel()->selectedRows().size(), 5); //everything is selected view.clearSelection(); //we hide the node with a child (there should then be 3 items selected in 2 ranges) view.setRowHidden(1, QModelIndex(), true); QVERIFY(view.isExpanded(item1.index())); view.selectAll(); - QCOMPARE(view.selectionModel()->selection().count(), 2); - QCOMPARE(view.selectionModel()->selectedRows().count(), 3); + QCOMPARE(view.selectionModel()->selection().size(), 2); + QCOMPARE(view.selectionModel()->selectedRows().size(), 3); QVERIFY(!view.selectionModel()->isSelected(model.indexFromItem(&item1))); QVERIFY(!view.selectionModel()->isSelected(model.indexFromItem(&child))); @@ -2574,8 +2574,8 @@ void tst_QTreeView::selectionWithHiddenItems() QVERIFY(view.isExpanded(item1.index())); view.selectAll(); QVERIFY(view.isExpanded(item1.index())); - QCOMPARE(view.selectionModel()->selection().count(), 3); - QCOMPARE(view.selectionModel()->selectedRows().count(), 4); + QCOMPARE(view.selectionModel()->selection().size(), 3); + QCOMPARE(view.selectionModel()->selectedRows().size(), 4); QVERIFY( !view.selectionModel()->isSelected(model.indexFromItem(&item2))); view.setRowHidden(2, QModelIndex(), false); QVERIFY(view.isExpanded(item1.index())); @@ -2590,21 +2590,21 @@ void tst_QTreeView::selectAll() view2.setSelectionMode(QAbstractItemView::ExtendedSelection); view2.selectAll(); // Should work with an empty model //everything should be selected since we are in ExtendedSelection mode - QCOMPARE(view2.selectedIndexes().count(), model.rowCount() * model.columnCount()); + QCOMPARE(view2.selectedIndexes().size(), model.rowCount() * model.columnCount()); for (int i = 0; i < model.rowCount(); ++i) model.setData(model.index(i,0), QLatin1String("row ") + QString::number(i)); QTreeView view; view.setModel(&model); - int selectedCount = view.selectedIndexes().count(); + int selectedCount = view.selectedIndexes().size(); view.selectAll(); - QCOMPARE(view.selectedIndexes().count(), selectedCount); + QCOMPARE(view.selectedIndexes().size(), selectedCount); QTreeView view3; view3.setModel(&model); view3.setSelectionMode(QAbstractItemView::NoSelection); view3.selectAll(); - QCOMPARE(view3.selectedIndexes().count(), 0); + QCOMPARE(view3.selectedIndexes().size(), 0); } void tst_QTreeView::extendedSelection_data() @@ -2630,7 +2630,7 @@ void tst_QTreeView::extendedSelection() topLevel.show(); QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); QTest::mousePress(view.viewport(), Qt::LeftButton, {}, mousePressPos); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), selectedCount); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), selectedCount); } void tst_QTreeView::rowSizeHint() @@ -2870,7 +2870,7 @@ public: } void kill() { - for (int i = children.count() -1; i >= 0; --i) { + for (int i = children.size() -1; i >= 0; --i) { children.at(i)->kill(); if (parent == nullptr) { deadChildren.append(children.at(i)); @@ -2912,7 +2912,7 @@ public: emit layoutAboutToBeChanged(); QModelIndexList oldList = persistentIndexList(); QList<QStack<int>> oldListPath; - for (int i = 0; i < oldList.count(); ++i) { + for (int i = 0; i < oldList.size(); ++i) { QModelIndex idx = oldList.at(i); QStack<int> path; while (idx.isValid()) { @@ -2924,7 +2924,7 @@ public: root->kill(); QModelIndexList newList; - for (auto path : qAsConst(oldListPath)) { + for (auto path : std::as_const(oldListPath)) { QModelIndex idx; while (!path.isEmpty()) idx = index(path.pop(), 0, idx); @@ -2943,7 +2943,7 @@ public: if (parentNode->isDead) qFatal("%s: parentNode is dead!", Q_FUNC_INFO); } - return parentNode->children.count(); + return parentNode->children.size(); } int columnCount(const QModelIndex &parent = QModelIndex()) const override { @@ -3534,7 +3534,7 @@ void tst_QTreeView::task174627_moveLeftToRoot() QSignalSpy spy(&view, &task174627_TreeView::signalCurrentChanged); QTest::keyClick(&view, Qt::Key_Left); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QTreeView::task171902_expandWith1stColHidden() @@ -3703,7 +3703,6 @@ void tst_QTreeView::task224091_appendColumns() treeView->setModel(model); topLevel->show(); treeView->resize(50, 50); - QApplication::setActiveWindow(topLevel); QVERIFY(QTest::qWaitForWindowActive(topLevel)); QVERIFY(!treeView->verticalScrollBar()->isVisible()); @@ -4040,7 +4039,7 @@ void tst_QTreeView::task248022_changeSelection() &view, &TreeView::handleSelectionChanged); QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, view.visualRect(model.index(1)).center()); - QCOMPARE(view.selectionModel()->selectedIndexes().count(), list.count()); + QCOMPARE(view.selectionModel()->selectedIndexes().size(), list.size()); } void tst_QTreeView::task245654_changeModelAndExpandAll() @@ -4079,7 +4078,6 @@ void tst_QTreeView::doubleClickedWithSpans() view.setModel(&model); view.setFirstColumnSpanned(0, QModelIndex(), true); view.show(); - QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QVERIFY(view.isActiveWindow()); @@ -4089,7 +4087,7 @@ void tst_QTreeView::doubleClickedWithSpans() QTest::mousePress(view.viewport(), Qt::LeftButton, {}, p); QTest::mouseDClick(view.viewport(), Qt::LeftButton, {}, p); QTest::mouseRelease(view.viewport(), Qt::LeftButton, {}, p); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); //let's click on the 2nd column p.setX(p.x() + view.header()->sectionSize(0)); @@ -4100,7 +4098,7 @@ void tst_QTreeView::doubleClickedWithSpans() QTest::mousePress(view.viewport(), Qt::LeftButton, {}, p); QTest::mouseDClick(view.viewport(), Qt::LeftButton, {}, p); QTest::mouseRelease(view.viewport(), Qt::LeftButton, {}, p); - QTRY_COMPARE(spy.count(), 2); + QTRY_COMPARE(spy.size(), 2); } void tst_QTreeView::taskQTBUG_6450_selectAllWith1stColumnHidden() @@ -4181,7 +4179,6 @@ void tst_QTreeView::keyboardNavigationWithDisabled() view.resize(200, view.visualRect(model.index(0,0)).height()*10); topLevel.show(); - QApplication::setActiveWindow(&topLevel); QVERIFY(QTest::qWaitForWindowActive(&topLevel)); QVERIFY(topLevel.isActiveWindow()); @@ -4767,7 +4764,6 @@ void tst_QTreeView::statusTip() mw.setGeometry(QRect(QPoint(QGuiApplication::primaryScreen()->geometry().center() - QPoint(250, 250)), QSize(500, 500))); mw.show(); - QApplication::setActiveWindow(&mw); QVERIFY(QTest::qWaitForWindowActive(&mw)); // Ensure it is moved away first and then moved to the relevant section QTest::mouseMove(mw.windowHandle(), view->mapTo(&mw, view->rect().bottomLeft() + QPoint(20, 20))); @@ -4818,6 +4814,9 @@ void tst_QTreeView::fetchMoreOnScroll() if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) QSKIP("Wayland: This fails. Figure out why."); + if (QGuiApplication::platformName().startsWith(QLatin1String("eglfs"), Qt::CaseInsensitive)) + QSKIP("EGLFS does not allow resizing on top level window"); + QTreeView tw; FetchMoreModel im; tw.setModel(&im); @@ -4895,6 +4894,9 @@ void tst_QTreeView::checkIntersectedRect_data() void tst_QTreeView::checkIntersectedRect() { + if (QGuiApplication::platformName().startsWith(QLatin1String("eglfs"), Qt::CaseInsensitive)) + QSKIP("EGLFS does not allow resizing on top level window"); + QFETCH(QStandardItemModel *, model); QFETCH(const QList<QModelIndex>, changedIndexes); QFETCH(bool, isEmpty); @@ -5117,7 +5119,7 @@ void tst_QTreeView::fetchUntilScreenFull() TreeItem* parentItem = parent.isValid() ? static_cast<TreeItem*>(parent.internalPointer()) : m_root; - return parentItem->children.count(); + return parentItem->children.size(); } int columnCount(const QModelIndex&) const override { return 2; } @@ -5196,6 +5198,10 @@ void tst_QTreeView::fetchUntilScreenFull() TreeItem* m_root; }; + if (QGuiApplication::platformName().startsWith(QLatin1String("eglfs"), Qt::CaseInsensitive)) + QSKIP("EGLFS does not allow resizing on top level window"); + + QTreeView tv; TreeModel model; tv.setModel(&model); diff --git a/tests/auto/widgets/itemviews/qtreewidget/CMakeLists.txt b/tests/auto/widgets/itemviews/qtreewidget/CMakeLists.txt index 8be1ba50da..251dbb9b79 100644 --- a/tests/auto/widgets/itemviews/qtreewidget/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qtreewidget/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qtreewidget.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtreewidget Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtreewidget LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtreewidget SOURCES tst_qtreewidget.cpp diff --git a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp index 652d6f76d9..f4423831ca 100644 --- a/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp +++ b/tests/auto/widgets/itemviews/qtreewidget/tst_qtreewidget.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QApplication> @@ -281,8 +281,8 @@ void tst_QTreeWidget::addTopLevelItem() while (!tops.isEmpty()) { TreeItem *ti = tops.takeFirst(); delete ti; - QCOMPARE(tree.topLevelItemCount(), tops.count()); - for (int i = 0; i < tops.count(); ++i) + QCOMPARE(tree.topLevelItemCount(), tops.size()); + for (int i = 0; i < tops.size(); ++i) QCOMPARE(tree.topLevelItem(i), tops.at(i)); } @@ -378,12 +378,12 @@ void tst_QTreeWidget::currentItem() tree.setCurrentItem(item); QCOMPARE(tree.currentItem(), item); - QCOMPARE(currentItemChangedSpy.count(), 1); + QCOMPARE(currentItemChangedSpy.size(), 1); QVariantList args = currentItemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(1)), previous); - QCOMPARE(itemSelectionChangedSpy.count(), 1); + QCOMPARE(itemSelectionChangedSpy.size(), 1); itemSelectionChangedSpy.clear(); previous = item; @@ -396,15 +396,15 @@ void tst_QTreeWidget::currentItem() if (!currentItemChangedSpy.isEmpty()) { // ### we get a currentItemChanged() when what really // changed was just currentColumn(). Should it be like this? - QCOMPARE(currentItemChangedSpy.count(), 1); + QCOMPARE(currentItemChangedSpy.size(), 1); QVariantList args = currentItemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(1)), item); if (tree.selectionBehavior() == QAbstractItemView::SelectItems) { - QCOMPARE(itemSelectionChangedSpy.count(), 1); + QCOMPARE(itemSelectionChangedSpy.size(), 1); itemSelectionChangedSpy.clear(); } else { - QCOMPARE(itemSelectionChangedSpy.count(), 0); + QCOMPARE(itemSelectionChangedSpy.size(), 0); } } } @@ -464,7 +464,7 @@ void tst_QTreeWidget::editItem() QTest::keyClick(editor, Qt::Key_A); QTest::keyClick(editor, Qt::Key_Enter); QCoreApplication::processEvents(); - QCOMPARE(itemChangedSpy.count(), 1); + QCOMPARE(itemChangedSpy.size(), 1); QVariantList args = itemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem *>(args.at(0)), item); QCOMPARE(qvariant_cast<int>(args.at(1)), col); @@ -620,7 +620,7 @@ void tst_QTreeWidget::setItemHidden2() { // From Task 78587 const QStringList hl({"ID", "Desc"}); - testWidget->setColumnCount(hl.count()); + testWidget->setColumnCount(hl.size()); testWidget->setHeaderLabels(hl); testWidget->setSortingEnabled(true); @@ -821,7 +821,7 @@ void tst_QTreeWidget::selectedItems() // check selectedItems const auto sel = testWidget->selectedItems(); - QCOMPARE(sel.count(), expectedItems.count()); + QCOMPARE(sel.size(), expectedItems.size()); for (const auto &itemPath : expectedItems) { QTreeWidgetItem *item = nullptr; for (int index : itemPath) { @@ -857,7 +857,7 @@ void tst_QTreeWidget::selectedItems() } item->setSelected(false); } - QCOMPARE(testWidget->selectedItems().count(), 0); + QCOMPARE(testWidget->selectedItems().size(), 0); } void tst_QTreeWidget::itemAssignment() @@ -1090,9 +1090,9 @@ void tst_QTreeWidget::findItems() QList<QTreeWidgetItem*> result = testWidget->findItems(pattern, Qt::MatchExactly|Qt::MatchRecursive); - QCOMPARE(result.count(), resultCount); + QCOMPARE(result.size(), resultCount); - for (int k = 0; k < result.count() && k < resultText.count(); ++k) + for (int k = 0; k < result.size() && k < resultText.size(); ++k) QCOMPARE(result.at(k)->text(column), resultText.at(k)); } @@ -1110,7 +1110,7 @@ void tst_QTreeWidget::findItemsInColumn() // Recursively search column one for 400. QList<QTreeWidgetItem*> items = testWidget->findItems("400", Qt::MatchExactly|Qt::MatchRecursive, 1); - QCOMPARE(items.count(), 1); + QCOMPARE(items.size(), 1); } void tst_QTreeWidget::sortItems_data() @@ -1177,16 +1177,16 @@ void tst_QTreeWidget::sortItems() testWidget->sortItems(column, order); QCOMPARE(testWidget->sortColumn(), column); - for (int k = 0; k < topLevelResult.count(); ++k) { + for (int k = 0; k < topLevelResult.size(); ++k) { QTreeWidgetItem *item = testWidget->topLevelItem(k); QCOMPARE(item->text(column), topLevelResult.at(k)); - for (int l = 0; l < childResult.count(); ++l) + for (int l = 0; l < childResult.size(); ++l) QCOMPARE(item->child(l)->text(column), childResult.at(l)); } - for (int m = 0; m < tops.count(); ++m) + for (int m = 0; m < tops.size(); ++m) QCOMPARE(tops.at(m).row(), expectedTopRows.at(m)); - for (int n = 0; n < children.count(); ++n) + for (int n = 0; n < children.size(); ++n) QCOMPARE(children.at(n).row(), expectedChildRows.at(n)); } @@ -1346,17 +1346,17 @@ void tst_QTreeWidget::insertTopLevelItems_data() const QStringList insert{ "baz" }; QTest::newRow("Insert at count") << initial << insert - << initial.count() << initial.count() - << initial.count() << initial.count(); + << initial.size() << initial.size() + << initial.size() << initial.size(); QTest::newRow("Insert in the middle") << initial << insert - << (initial.count() / 2) << (initial.count() / 2) - << (initial.count() / 2) << (initial.count() / 2); + << (initial.size() / 2) << (initial.size() / 2) + << (initial.size() / 2) << (initial.size() / 2); QTest::newRow("Insert less than 0") << initial << insert << -1 << -1 << -1 << -1; QTest::newRow("Insert beyond count") << initial << insert - << initial.count() + 1 << -1 - << initial.count() + 1 << -1; + << initial.size() + 1 << -1 + << initial.size() + 1 << -1; } void tst_QTreeWidget::insertTopLevelItems() @@ -1371,26 +1371,26 @@ void tst_QTreeWidget::insertTopLevelItems() { // insert the initial items QCOMPARE(testWidget->topLevelItemCount(), 0); - for (int i = 0; i < initialText.count(); ++i) { + for (int i = 0; i < initialText.size(); ++i) { QTreeWidgetItem *top = new QTreeWidgetItem(QStringList(initialText.at(i))); testWidget->addTopLevelItem(top); QCOMPARE(testWidget->indexOfTopLevelItem(top), i); } - QCOMPARE(testWidget->topLevelItemCount(), initialText.count()); + QCOMPARE(testWidget->topLevelItemCount(), initialText.size()); } { // test adding children QTreeWidgetItem *topLevel = testWidget->topLevelItem(0); - for (int i = 0; i < initialText.count(); ++i) + for (int i = 0; i < initialText.size(); ++i) topLevel->addChild(new QTreeWidgetItem(QStringList(initialText.at(i)))); - QCOMPARE(topLevel->childCount(), initialText.count()); + QCOMPARE(topLevel->childCount(), initialText.size()); } { // test adding more top level items QTreeWidgetItem *topsy = new QTreeWidgetItem(QStringList(insertText.at(0))); testWidget->insertTopLevelItem(insertTopLevelIndex, topsy); if (expectedTopLevelIndex == -1) { - QCOMPARE(testWidget->topLevelItemCount(), initialText.count()); + QCOMPARE(testWidget->topLevelItemCount(), initialText.size()); delete topsy; } else { QTreeWidgetItem *item = testWidget->topLevelItem(expectedTopLevelIndex); @@ -1406,7 +1406,7 @@ void tst_QTreeWidget::insertTopLevelItems() QTreeWidgetItem *child = new QTreeWidgetItem(QStringList(insertText.at(0))); topLevel->insertChild(insertChildIndex, child); if (expectedChildIndex == -1) { - QCOMPARE(topLevel->childCount(), initialText.count()); + QCOMPARE(topLevel->childCount(), initialText.size()); delete child; } else { QTreeWidgetItem *item = topLevel->child(expectedChildIndex); @@ -1504,7 +1504,7 @@ void tst_QTreeWidget::keyboardNavigation() if (testWidget->currentItem() != item) { QCOMPARE(testWidget->currentItem(), item->parent()); item = testWidget->currentItem(); - row = item->parent() ? item->parent()->indexOfChild(item) : testWidget->indexOfTopLevelItem(item);; + row = item->parent() ? item->parent()->indexOfChild(item) : testWidget->indexOfTopLevelItem(item); } break; case Qt::Key_Right: @@ -1592,7 +1592,7 @@ void tst_QTreeWidget::scrollToItem() void tst_QTreeWidget::setSortingEnabled() { const QStringList hl{ "ID" }; - testWidget->setColumnCount(hl.count()); + testWidget->setColumnCount(hl.size()); testWidget->setHeaderLabels(hl); QTreeWidgetItem *item1 = new QTreeWidgetItem(testWidget); @@ -1661,7 +1661,7 @@ void tst_QTreeWidget::addChild() QList<QTreeWidgetItem*> taken = item->takeChildren(); QCOMPARE(taken, children); QCOMPARE(item->childCount(), 0); - for (int i = 0; i < taken.count(); ++i) { + for (int i = 0; i < taken.size(); ++i) { QCOMPARE(taken.at(i)->parent(), nullptr); QCOMPARE(taken.at(i)->treeWidget(), nullptr); item->addChild(taken.at(i)); // re-add @@ -1671,8 +1671,8 @@ void tst_QTreeWidget::addChild() while (!children.isEmpty()) { QTreeWidgetItem *ti = children.takeFirst(); delete ti; - QCOMPARE(item->childCount(), children.count()); - for (int i = 0; i < children.count(); ++i) + QCOMPARE(item->childCount(), children.size()); + for (int i = 0; i < children.size(); ++i) QCOMPARE(item->child(i), children.at(i)); } @@ -1719,9 +1719,9 @@ void tst_QTreeWidget::setData() QSignalSpy itemChangedSpy( testWidget, &QTreeWidget::itemChanged); headerItem->setText(0, "test"); - QCOMPARE(dataChangedSpy.count(), 0); - QCOMPARE(headerDataChangedSpy.count(), 1); - QCOMPARE(itemChangedSpy.count(), 0); // no itemChanged() signal for header item + QCOMPARE(dataChangedSpy.size(), 0); + QCOMPARE(headerDataChangedSpy.size(), 1); + QCOMPARE(itemChangedSpy.size(), 0); // no itemChanged() signal for header item headerItem->setData(-1, -1, QVariant()); } @@ -1739,24 +1739,24 @@ void tst_QTreeWidget::setData() const QString text = QLatin1String("text ") + iS; item->setText(j, text); QCOMPARE(item->text(j), text); - QCOMPARE(itemChangedSpy.count(), 1); + QCOMPARE(itemChangedSpy.size(), 1); args = itemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<int>(args.at(1)), j); item->setText(j, text); - QCOMPARE(itemChangedSpy.count(), 0); + QCOMPARE(itemChangedSpy.size(), 0); QPixmap pixmap(32, 32); pixmap.fill((i == 1) ? Qt::red : Qt::green); QIcon icon(pixmap); item->setIcon(j, icon); QCOMPARE(item->icon(j), icon); - QCOMPARE(itemChangedSpy.count(), 1); + QCOMPARE(itemChangedSpy.size(), 1); args = itemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<int>(args.at(1)), j); item->setIcon(j, icon); - QCOMPARE(itemChangedSpy.count(), 1); + QCOMPARE(itemChangedSpy.size(), 1); args = itemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<int>(args.at(1)), j); @@ -1764,94 +1764,94 @@ void tst_QTreeWidget::setData() const QString toolTip = QLatin1String("toolTip ") + iS; item->setToolTip(j, toolTip); QCOMPARE(item->toolTip(j), toolTip); - QCOMPARE(itemChangedSpy.count(), 1); + QCOMPARE(itemChangedSpy.size(), 1); args = itemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<int>(args.at(1)), j); item->setToolTip(j, toolTip); - QCOMPARE(itemChangedSpy.count(), 0); + QCOMPARE(itemChangedSpy.size(), 0); const QString statusTip = QLatin1String("statusTip ") + iS; item->setStatusTip(j, statusTip); QCOMPARE(item->statusTip(j), statusTip); - QCOMPARE(itemChangedSpy.count(), 1); + QCOMPARE(itemChangedSpy.size(), 1); args = itemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<int>(args.at(1)), j); item->setStatusTip(j, statusTip); - QCOMPARE(itemChangedSpy.count(), 0); + QCOMPARE(itemChangedSpy.size(), 0); const QString whatsThis = QLatin1String("whatsThis ") + iS; item->setWhatsThis(j, whatsThis); QCOMPARE(item->whatsThis(j), whatsThis); - QCOMPARE(itemChangedSpy.count(), 1); + QCOMPARE(itemChangedSpy.size(), 1); args = itemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<int>(args.at(1)), j); item->setWhatsThis(j, whatsThis); - QCOMPARE(itemChangedSpy.count(), 0); + QCOMPARE(itemChangedSpy.size(), 0); QSize sizeHint(64*i, 48*i); item->setSizeHint(j, sizeHint); QCOMPARE(item->sizeHint(j), sizeHint); - QCOMPARE(itemChangedSpy.count(), 1); + QCOMPARE(itemChangedSpy.size(), 1); args = itemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<int>(args.at(1)), j); item->setSizeHint(j, sizeHint); - QCOMPARE(itemChangedSpy.count(), 0); + QCOMPARE(itemChangedSpy.size(), 0); QFont font; item->setFont(j, font); QCOMPARE(item->font(j), font); - QCOMPARE(itemChangedSpy.count(), 1); + QCOMPARE(itemChangedSpy.size(), 1); args = itemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<int>(args.at(1)), j); item->setFont(j, font); - QCOMPARE(itemChangedSpy.count(), 0); + QCOMPARE(itemChangedSpy.size(), 0); Qt::Alignment textAlignment((i == 1) ? Qt::AlignLeft|Qt::AlignVCenter : Qt::AlignRight); item->setTextAlignment(j, textAlignment); QCOMPARE(item->textAlignment(j), int(textAlignment)); - QCOMPARE(itemChangedSpy.count(), 1); + QCOMPARE(itemChangedSpy.size(), 1); args = itemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<int>(args.at(1)), j); item->setTextAlignment(j, textAlignment); - QCOMPARE(itemChangedSpy.count(), 0); + QCOMPARE(itemChangedSpy.size(), 0); QColor backgroundColor((i == 1) ? Qt::blue : Qt::yellow); item->setBackground(j, backgroundColor); QCOMPARE(item->background(j).color(), backgroundColor); - QCOMPARE(itemChangedSpy.count(), 1); + QCOMPARE(itemChangedSpy.size(), 1); args = itemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<int>(args.at(1)), j); item->setBackground(j, backgroundColor); - QCOMPARE(itemChangedSpy.count(), 0); + QCOMPARE(itemChangedSpy.size(), 0); const QColor foregroundColor((i == 1) ? Qt::green : Qt::cyan); item->setForeground(j, foregroundColor); QCOMPARE(item->foreground(j), foregroundColor); - QCOMPARE(itemChangedSpy.count(), 1); + QCOMPARE(itemChangedSpy.size(), 1); args = itemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<int>(args.at(1)), j); item->setForeground(j, foregroundColor); - QCOMPARE(itemChangedSpy.count(), 0); + QCOMPARE(itemChangedSpy.size(), 0); Qt::CheckState checkState((i == 1) ? Qt::PartiallyChecked : Qt::Checked); item->setCheckState(j, checkState); QCOMPARE(item->checkState(j), checkState); - QCOMPARE(itemChangedSpy.count(), 1); + QCOMPARE(itemChangedSpy.size(), 1); args = itemChangedSpy.takeFirst(); QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<int>(args.at(1)), j); item->setCheckState(j, checkState); - QCOMPARE(itemChangedSpy.count(), 0); + QCOMPARE(itemChangedSpy.size(), 0); QCOMPARE(item->text(j), text); QCOMPARE(item->icon(j), icon); @@ -1884,7 +1884,7 @@ void tst_QTreeWidget::setData() QCOMPARE(qvariant_cast<QTreeWidgetItem*>(args.at(0)), item); QCOMPARE(qvariant_cast<int>(args.at(1)), j); item->setBackground(j, pixmap); - QCOMPARE(itemChangedSpy.count(), 0); + QCOMPARE(itemChangedSpy.size(), 0); item->setData(j, Qt::DisplayRole, QVariant()); item->setData(j, Qt::DecorationRole, QVariant()); @@ -1897,7 +1897,7 @@ void tst_QTreeWidget::setData() item->setData(j, Qt::BackgroundRole, QVariant()); item->setData(j, Qt::ForegroundRole, QVariant()); item->setData(j, Qt::CheckStateRole, QVariant()); - QCOMPARE(itemChangedSpy.count(), 11); + QCOMPARE(itemChangedSpy.size(), 11); itemChangedSpy.clear(); QCOMPARE(item->data(j, Qt::DisplayRole).toString(), QString()); @@ -1960,11 +1960,11 @@ void tst_QTreeWidget::itemData() QCOMPARE(widget.currentRoles, QList<int> { Qt::UserRole + i }); } QMap<int, QVariant> flags = widget.model()->itemData(widget.model()->index(0, 0)); - QCOMPARE(flags.count(), 6); + QCOMPARE(flags.size(), 6); for (int i = 0; i < 4; ++i) QCOMPARE(flags[Qt::UserRole + i].toString(), QString::number(i + 1)); flags = widget.model()->itemData(widget.model()->index(0, 1)); - QCOMPARE(flags.count(), 0); + QCOMPARE(flags.size(), 0); item.setBackground(0, QBrush(Qt::red)); item.setForeground(0, QBrush(Qt::green)); @@ -2033,7 +2033,7 @@ void tst_QTreeWidget::setHeaderLabels() { QStringList list = QString("a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z").split(QLatin1Char(',')); testWidget->setHeaderLabels(list); - QCOMPARE(testWidget->header()->count(), list.count()); + QCOMPARE(testWidget->header()->count(), list.size()); } void tst_QTreeWidget::setHeaderItem() @@ -2263,11 +2263,11 @@ void tst_QTreeWidget::insertItemsWithSorting() w.addTopLevelItem(new QTreeWidgetItem({ txt })); break; } - QCOMPARE(w.topLevelItemCount(), expectedItems.count()); + QCOMPARE(w.topLevelItemCount(), expectedItems.size()); for (int i = 0; i < w.topLevelItemCount(); ++i) QCOMPARE(w.topLevelItem(i)->text(0), expectedItems.at(i)); - for (int k = 0; k < persistent.count(); ++k) + for (int k = 0; k < persistent.size(); ++k) QCOMPARE(persistent.at(k).row(), expectedRows.at(k)); } } @@ -2308,13 +2308,13 @@ void tst_QTreeWidget::insertExpandedItemsWithSorting() QTreeWidgetItem *child = new QTreeWidgetItem(parent, {text}); items << child; } - QCOMPARE(parent->childCount(), childTexts.count()); + QCOMPARE(parent->childCount(), childTexts.size()); QVERIFY(parent->isExpanded()); } - QCOMPARE(tree.model()->rowCount(), parentTexts.count()); + QCOMPARE(tree.model()->rowCount(), parentTexts.size()); // verify that the items are still expanded - for (const QTreeWidgetItem *item : qAsConst(items)) { + for (const QTreeWidgetItem *item : std::as_const(items)) { if (item->childCount() > 0) QVERIFY(item->isExpanded()); QModelIndex idx = tree.indexFromItem(item); @@ -2332,10 +2332,10 @@ void tst_QTreeWidget::insertExpandedItemsWithSorting() PersistentModelIndexVec children; for (int i = 0; i < model->rowCount(parents.constFirst()); ++i) children.push_back(model->index(i, 0, parents.constFirst())); - for (int i = 0; i < parentResult.count(); ++i) { + for (int i = 0; i < parentResult.size(); ++i) { QTreeWidgetItem *item = tree.topLevelItem(i); QCOMPARE(item->text(0), parentResult.at(i)); - for (int j = 0; j < childResult.count(); ++j) + for (int j = 0; j < childResult.size(); ++j) QCOMPARE(item->child(j)->text(0), childResult.at(j)); } } @@ -2427,19 +2427,19 @@ void tst_QTreeWidget::changeDataWithSorting() QTreeWidgetItem *item = w.topLevelItem(itemIndex); item->setText(0, newValue); - for (int i = 0; i < expectedItems.count(); ++i) { + for (int i = 0; i < expectedItems.size(); ++i) { QCOMPARE(w.topLevelItem(i)->text(0), expectedItems.at(i)); - for (const QPersistentModelIndex &p : qAsConst(persistent)) { + for (const QPersistentModelIndex &p : std::as_const(persistent)) { if (p.row() == i) // the same toplevel row QCOMPARE(p.internalPointer(), static_cast<void *>(w.topLevelItem(i))); } } - for (int k = 0; k < persistent.count(); ++k) + for (int k = 0; k < persistent.size(); ++k) QCOMPARE(persistent.at(k).row(), expectedRows.at(k)); - QCOMPARE(dataChangedSpy.count(), 1); - QCOMPARE(layoutChangedSpy.count(), reorderingExpected ? 1 : 0); + QCOMPARE(dataChangedSpy.size(), 1); + QCOMPARE(layoutChangedSpy.size(), reorderingExpected ? 1 : 0); } void tst_QTreeWidget::changeDataWithStableSorting_data() @@ -2596,19 +2596,19 @@ void tst_QTreeWidget::changeDataWithStableSorting() item->setText(0, newValue); if (forceChange) item->emitDataChanged(); - for (int i = 0; i < expectedItems.count(); ++i) { + for (int i = 0; i < expectedItems.size(); ++i) { QCOMPARE(w.topLevelItem(i)->text(0), expectedItems.at(i)); - for (const QPersistentModelIndex &p : qAsConst(persistent)) { + for (const QPersistentModelIndex &p : std::as_const(persistent)) { if (p.row() == i) // the same toplevel row QCOMPARE(p.internalPointer(), static_cast<void *>(w.topLevelItem(i))); } } - for (int k = 0; k < persistent.count(); ++k) + for (int k = 0; k < persistent.size(); ++k) QCOMPARE(persistent.at(k).row(), expectedRows.at(k)); - QCOMPARE(dataChangedSpy.count(), 1); - QCOMPARE(layoutChangedSpy.count(), reorderingExpected ? 1 : 0); + QCOMPARE(dataChangedSpy.size(), 1); + QCOMPARE(layoutChangedSpy.size(), reorderingExpected ? 1 : 0); } void tst_QTreeWidget::sizeHint_data() @@ -2627,6 +2627,12 @@ void tst_QTreeWidget::sizeHint() QFETCH(Qt::ScrollBarPolicy, scrollBarPolicy); QFETCH(QSize, viewSize); + const QString defaultStyle = QApplication::style()->name(); + QApplication::setStyle("fusion"); + const auto resetStyle = qScopeGuard([defaultStyle]{ + QApplication::setStyle(defaultStyle); + }); + QTreeWidget view; view.setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); view.setVerticalScrollBarPolicy(scrollBarPolicy); @@ -2644,6 +2650,7 @@ void tst_QTreeWidget::sizeHint() QTRY_COMPARE(view.size(), viewSize); } + QApplication::processEvents(); // execute delayed layouts auto sizeHint = view.sizeHint(); view.hide(); QCOMPARE(view.sizeHint(), sizeHint); @@ -2714,8 +2721,8 @@ void tst_QTreeWidget::sortedIndexOfChild() tw.sortItems(0, sortOrder); tw.expandAll(); - QCOMPARE(itms.count(), expectedIndexes.count()); - for (int j = 0; j < expectedIndexes.count(); ++j) + QCOMPARE(itms.size(), expectedIndexes.size()); + for (int j = 0; j < expectedIndexes.size(); ++j) QCOMPARE(top->indexOfChild(itms.at(j)), expectedIndexes.at(j)); } @@ -2740,8 +2747,8 @@ void tst_QTreeWidget::expandAndCallapse() tw.collapseItem(top); tw.collapseItem(top); - QCOMPARE(spy0.count(), 3); - QCOMPARE(spy1.count(), 2); + QCOMPARE(spy0.size(), 3); + QCOMPARE(spy1.size(), 2); } void tst_QTreeWidget::setDisabled() @@ -2854,13 +2861,13 @@ void tst_QTreeWidget::removeSelectedItem() QItemSelectionModel *selModel = w->selectionModel(); QCOMPARE(selModel->hasSelection(), true); - QCOMPARE(selModel->selectedRows().count(), 1); + QCOMPARE(selModel->selectedRows().size(), 1); const QScopedPointer<QTreeWidgetItem> taken(w->takeTopLevelItem(2)); QCOMPARE(taken->text(0), QLatin1String("C")); QCOMPARE(selModel->hasSelection(), false); - QCOMPARE(selModel->selectedRows().count(), 0); + QCOMPARE(selModel->selectedRows().size(), 0); QItemSelection sel = selModel->selection(); QCOMPARE(selModel->isSelected(w->model()->index(0,0)), false); } @@ -2971,7 +2978,7 @@ protected: auto newItem = new QTreeWidgetItem({QString::number(i++)}); m_list.append(newItem); insertTopLevelItem(0, newItem); - while (m_list.count() > 10) + while (m_list.size() > 10) delete m_list.takeFirst(); } QTreeWidget::timerEvent(event); @@ -3285,7 +3292,7 @@ void tst_QTreeWidget::emitDataChanged() auto item = new PublicTreeItem; tree.insertTopLevelItem(0, item); item->emitDataChanged(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } void tst_QTreeWidget::setCurrentItemExpandsParent() diff --git a/tests/auto/widgets/itemviews/qtreewidgetitemiterator/CMakeLists.txt b/tests/auto/widgets/itemviews/qtreewidgetitemiterator/CMakeLists.txt index b8efcf2bca..d82eaadced 100644 --- a/tests/auto/widgets/itemviews/qtreewidgetitemiterator/CMakeLists.txt +++ b/tests/auto/widgets/itemviews/qtreewidgetitemiterator/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qtreewidgetitemiterator.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtreewidgetitemiterator Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtreewidgetitemiterator LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtreewidgetitemiterator SOURCES tst_qtreewidgetitemiterator.cpp diff --git a/tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp b/tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp index 7c1ce7c426..a650eb229e 100644 --- a/tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp +++ b/tests/auto/widgets/itemviews/qtreewidgetitemiterator/tst_qtreewidgetitemiterator.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTreeWidget> @@ -866,7 +866,7 @@ void tst_QTreeWidgetItemIterator::iteratorflags() QTreeWidgetItemIterator it(testWidget, iteratorflags); it += start; int iMatch = 0; - while (*it && iMatch < matches.count()) { + while (*it && iMatch < matches.size()) { QTreeWidgetItem *item = *it; QCOMPARE(item->text(0), matches[iMatch]); ++it; diff --git a/tests/auto/widgets/kernel/CMakeLists.txt b/tests/auto/widgets/kernel/CMakeLists.txt index d87bedc708..2d4880ea3c 100644 --- a/tests/auto/widgets/kernel/CMakeLists.txt +++ b/tests/auto/widgets/kernel/CMakeLists.txt @@ -1,7 +1,5 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from kernel.pro. +# SPDX-License-Identifier: BSD-3-Clause add_subdirectory(qapplication) add_subdirectory(qboxlayout) diff --git a/tests/auto/widgets/kernel/qaction/CMakeLists.txt b/tests/auto/widgets/kernel/qaction/CMakeLists.txt index 202eb2c8f6..9d1985da0b 100644 --- a/tests/auto/widgets/kernel/qaction/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qaction/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qaction.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qaction Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qaction LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qaction SOURCES tst_qaction.cpp @@ -15,4 +19,5 @@ qt_internal_add_test(tst_qaction Qt::Gui Qt::GuiPrivate Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp index 49123c33d5..2820fd710b 100644 --- a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp +++ b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QDialog> #include <QMainWindow> @@ -17,6 +17,8 @@ #include <qpa/qplatformintegration.h> #include <private/qguiapplication_p.h> +#include <QtWidgets/private/qapplication_p.h> + class tst_QAction : public QObject { Q_OBJECT @@ -111,7 +113,6 @@ void tst_QAction::actionEvent() // add action MyWidget testWidget(this); testWidget.show(); - QApplication::setActiveWindow(&testWidget); testWidget.addAction(&a); qApp->processEvents(); @@ -141,7 +142,7 @@ void tst_QAction::alternateShortcuts() MyWidget testWidget(this); testWidget.show(); - QApplication::setActiveWindow(&testWidget); + QApplicationPrivate::setActiveWindow(&testWidget); { QAction act(&testWidget); @@ -153,11 +154,11 @@ void tst_QAction::alternateShortcuts() act.setAutoRepeat(true); QTest::keyClick(&testWidget, Qt::Key_A, Qt::ControlModifier); - QCOMPARE(spy.count(), 1); //act should have been triggered + QCOMPARE(spy.size(), 1); //act should have been triggered act.setAutoRepeat(false); QTest::keyClick(&testWidget, Qt::Key_A, Qt::ControlModifier); - QCOMPARE(spy.count(), 2); //act should have been triggered a 2nd time + QCOMPARE(spy.size(), 2); //act should have been triggered a 2nd time //end of the scope of the action, it will be destroyed and removed from wid //This action should also unregister its shortcuts @@ -172,7 +173,7 @@ void tst_QAction::keysequence() { MyWidget testWidget(this); testWidget.show(); - QApplication::setActiveWindow(&testWidget); + QApplicationPrivate::setActiveWindow(&testWidget); { QAction act(&testWidget); @@ -187,12 +188,12 @@ void tst_QAction::keysequence() act.setAutoRepeat(true); QTest::keySequence(&testWidget, ks); QCoreApplication::processEvents(); - QCOMPARE(spy.count(), 1); // act should have been triggered + QCOMPARE(spy.size(), 1); // act should have been triggered act.setAutoRepeat(false); QTest::keySequence(&testWidget, ks); QCoreApplication::processEvents(); - QCOMPARE(spy.count(), 2); //act should have been triggered a 2nd time + QCOMPARE(spy.size(), 2); //act should have been triggered a 2nd time // end of the scope of the action, it will be destroyed and removed from widget // This action should also unregister its shortcuts @@ -206,7 +207,7 @@ void tst_QAction::enabledVisibleInteraction() { MyWidget testWidget(this); testWidget.show(); - QApplication::setActiveWindow(&testWidget); + QApplicationPrivate::setActiveWindow(&testWidget); QAction act(nullptr); // check defaults @@ -228,15 +229,15 @@ void tst_QAction::enabledVisibleInteraction() act.setEnabled(true); act.setVisible(false); QTest::keyClick(&testWidget, Qt::Key_T, Qt::ControlModifier); - QCOMPARE(spy.count(), 0); //act is not visible, so don't trigger + QCOMPARE(spy.size(), 0); //act is not visible, so don't trigger act.setVisible(false); act.setEnabled(true); QTest::keyClick(&testWidget, Qt::Key_T, Qt::ControlModifier); - QCOMPARE(spy.count(), 0); //act is not visible, so don't trigger + QCOMPARE(spy.size(), 0); //act is not visible, so don't trigger act.setVisible(true); act.setEnabled(true); QTest::keyClick(&testWidget, Qt::Key_T, Qt::ControlModifier); - QCOMPARE(spy.count(), 1); //act is visible and enabled, so trigger + QCOMPARE(spy.size(), 1); //act is visible and enabled, so trigger } #endif // QT_CONFIG(shortcut) @@ -254,12 +255,12 @@ void tst_QAction::task229128TriggeredSignalWhenInActiongroup() QSignalSpy actionSpy(checkedAction, QOverload<bool>::of(&QAction::triggered)); QSignalSpy actionGroupSpy(&ag, QOverload<QAction*>::of(&QActionGroup::triggered)); - QCOMPARE(actionGroupSpy.count(), 0); - QCOMPARE(actionSpy.count(), 0); + QCOMPARE(actionGroupSpy.size(), 0); + QCOMPARE(actionSpy.size(), 0); checkedAction->trigger(); // check that both the group and the action have emitted the signal - QCOMPARE(actionGroupSpy.count(), 1); - QCOMPARE(actionSpy.count(), 1); + QCOMPARE(actionGroupSpy.size(), 1); + QCOMPARE(actionSpy.size(), 1); } #if QT_CONFIG(shortcut) @@ -271,7 +272,6 @@ void tst_QAction::repeat() MyWidget testWidget(this); testWidget.show(); - QApplication::setActiveWindow(&testWidget); QVERIFY(QTest::qWaitForWindowActive(&testWidget)); QAction act(&testWidget); @@ -282,7 +282,7 @@ void tst_QAction::repeat() act.setAutoRepeat(true); QTest::keyPress(&testWidget, Qt::Key_F); QTest::keyRelease(&testWidget, Qt::Key_F); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); QTest::keyPress(&testWidget, Qt::Key_F); @@ -290,7 +290,7 @@ void tst_QAction::repeat() QTest::simulateEvent(&testWidget, true, Qt::Key_F, Qt::NoModifier, QString("f"), true); QTest::simulateEvent(&testWidget, true, Qt::Key_F, Qt::NoModifier, QString("f"), true); QTest::keyRelease(&testWidget, Qt::Key_F); - QCOMPARE(spy.count(), 3); + QCOMPARE(spy.size(), 3); spy.clear(); act.setAutoRepeat(false); @@ -298,14 +298,14 @@ void tst_QAction::repeat() QTest::simulateEvent(&testWidget, true, Qt::Key_F, Qt::NoModifier, QString("f"), true); QTest::simulateEvent(&testWidget, true, Qt::Key_F, Qt::NoModifier, QString("f"), true); QTest::keyRelease(&testWidget, Qt::Key_F); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); act.setAutoRepeat(true); QTest::keyPress(&testWidget, Qt::Key_F); QTest::simulateEvent(&testWidget, true, Qt::Key_F, Qt::NoModifier, QString("f"), true); QTest::keyRelease(&testWidget, Qt::Key_F); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); } void tst_QAction::disableShortcutsWithBlockedWidgets_data() @@ -350,12 +350,11 @@ void tst_QAction::disableShortcutsWithBlockedWidgets() dialog.show(); QVERIFY(QTest::qWaitForWindowExposed(&dialog)); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); QSignalSpy spy(&action, &QAction::triggered); QTest::keyPress(&window, Qt::Key_1); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } class ShortcutOverrideWidget : public QWidget @@ -393,7 +392,7 @@ void tst_QAction::shortcutFromKeyEvent() // shortcut route for us QKeyEvent e(QEvent::KeyPress, Qt::Key_1, Qt::NoModifier); QApplication::sendEvent(&testWidget, &e); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(testWidget.shortcutOverrideCount, 1); } @@ -412,6 +411,9 @@ void tst_QAction::disableShortcutInMenuAction_data() void tst_QAction::disableShortcutInMenuAction() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QFETCH(QByteArray, property); QMainWindow mw; @@ -429,42 +431,42 @@ void tst_QAction::disableShortcutInMenuAction() QKeyEvent event(QEvent::KeyPress, Qt::Key_A, Qt::ControlModifier); QApplication::sendEvent(&mw, &event); - QCOMPARE(spy.count(), ++expectedTriggerCount); + QCOMPARE(spy.size(), ++expectedTriggerCount); testMenu->menuAction()->setProperty(property, false); QApplication::sendEvent(&mw, &event); - QCOMPARE(spy.count(), expectedTriggerCount); + QCOMPARE(spy.size(), expectedTriggerCount); testMenu->menuAction()->setProperty(property, true); QApplication::sendEvent(&mw, &event); - QCOMPARE(spy.count(), ++expectedTriggerCount); + QCOMPARE(spy.size(), ++expectedTriggerCount); // If the action lives somewhere else, then keep firing even // if the menu has been hidden or disabled. toolBar->addAction(testAction); QApplication::sendEvent(&mw, &event); - QCOMPARE(spy.count(), ++expectedTriggerCount); + QCOMPARE(spy.size(), ++expectedTriggerCount); testMenu->menuAction()->setProperty(property, false); QApplication::sendEvent(&mw, &event); - QCOMPARE(spy.count(), ++expectedTriggerCount); + QCOMPARE(spy.size(), ++expectedTriggerCount); // unless all other widgets in which the action lives have // been hidden... toolBar->hide(); QApplication::sendEvent(&mw, &event); - QCOMPARE(spy.count(), expectedTriggerCount); + QCOMPARE(spy.size(), expectedTriggerCount); // ... or disabled toolBar->show(); toolBar->setEnabled(false); QApplication::sendEvent(&mw, &event); - QCOMPARE(spy.count(), expectedTriggerCount); + QCOMPARE(spy.size(), expectedTriggerCount); // back to normal toolBar->setEnabled(true); QApplication::sendEvent(&mw, &event); - QCOMPARE(spy.count(), ++expectedTriggerCount); + QCOMPARE(spy.size(), ++expectedTriggerCount); } #endif // QT_CONFIG(shortcut) diff --git a/tests/auto/widgets/kernel/qactiongroup/CMakeLists.txt b/tests/auto/widgets/kernel/qactiongroup/CMakeLists.txt index 408392f7ae..e26ee75bc1 100644 --- a/tests/auto/widgets/kernel/qactiongroup/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qactiongroup/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qactiongroup.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qactiongroup Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qactiongroup LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qactiongroup SOURCES tst_qactiongroup.cpp diff --git a/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp b/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp index 56d2feee47..0d42340bfb 100644 --- a/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp +++ b/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/kernel/qapplication/BLACKLIST b/tests/auto/widgets/kernel/qapplication/BLACKLIST index 364a2abe4f..c68c7d6b14 100644 --- a/tests/auto/widgets/kernel/qapplication/BLACKLIST +++ b/tests/auto/widgets/kernel/qapplication/BLACKLIST @@ -1,6 +1,3 @@ -[sendEventsOnProcessEvents] -ubuntu-20.04 -ubuntu-22.04 [touchEventPropagation] # QTBUG-66745 opensuse-leap diff --git a/tests/auto/widgets/kernel/qapplication/CMakeLists.txt b/tests/auto/widgets/kernel/qapplication/CMakeLists.txt index f562675377..524db06560 100644 --- a/tests/auto/widgets/kernel/qapplication/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qapplication/CMakeLists.txt @@ -1,8 +1,17 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +# SPDX-License-Identifier: BSD-3-Clause -# Generated from qapplication.pro. +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qapplication LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() add_subdirectory(desktopsettingsaware) add_subdirectory(modal) add_subdirectory(test) + +add_dependencies(tst_qapplication + desktopsettingsaware_helper + modal_helper +) diff --git a/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/CMakeLists.txt b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/CMakeLists.txt index 9082d2ddba..f094a451d2 100644 --- a/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/CMakeLists.txt @@ -1,17 +1,15 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from desktopsettingsaware.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## desktopsettingsaware Binary: ##################################################################### -qt_internal_add_executable(desktopsettingsaware_helper # special case +qt_internal_add_executable(desktopsettingsaware_helper SOURCES main.cpp - OUTPUT_DIRECTORY # special case - ${CMAKE_CURRENT_BINARY_DIR}/.. # special case + OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/.. LIBRARIES Qt::Gui Qt::Widgets diff --git a/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp index 0584dbeab8..1bf3eef55c 100644 --- a/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp +++ b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QApplication> diff --git a/tests/auto/widgets/kernel/qapplication/modal/CMakeLists.txt b/tests/auto/widgets/kernel/qapplication/modal/CMakeLists.txt index 6af34c1756..79c5660650 100644 --- a/tests/auto/widgets/kernel/qapplication/modal/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qapplication/modal/CMakeLists.txt @@ -1,18 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from modal.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## modal Binary: ##################################################################### -qt_internal_add_executable(modal_helper # special case +qt_internal_add_executable(modal_helper SOURCES base.cpp base.h main.cpp - OUTPUT_DIRECTORY # special case - ${CMAKE_CURRENT_BINARY_DIR}/.. # special case + OUTPUT_DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/.. LIBRARIES Qt::Gui Qt::Widgets diff --git a/tests/auto/widgets/kernel/qapplication/modal/base.cpp b/tests/auto/widgets/kernel/qapplication/modal/base.cpp index 0108c9c789..49a90723dd 100644 --- a/tests/auto/widgets/kernel/qapplication/modal/base.cpp +++ b/tests/auto/widgets/kernel/qapplication/modal/base.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "base.h" diff --git a/tests/auto/widgets/kernel/qapplication/modal/base.h b/tests/auto/widgets/kernel/qapplication/modal/base.h index a78b2306ba..168da92f97 100644 --- a/tests/auto/widgets/kernel/qapplication/modal/base.h +++ b/tests/auto/widgets/kernel/qapplication/modal/base.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef BASE_H #define BASE_H diff --git a/tests/auto/widgets/kernel/qapplication/modal/main.cpp b/tests/auto/widgets/kernel/qapplication/modal/main.cpp index be38c41786..3f3496834d 100644 --- a/tests/auto/widgets/kernel/qapplication/modal/main.cpp +++ b/tests/auto/widgets/kernel/qapplication/modal/main.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QApplication> #include "base.h" diff --git a/tests/auto/widgets/kernel/qapplication/test/CMakeLists.txt b/tests/auto/widgets/kernel/qapplication/test/CMakeLists.txt index b89560990e..fc80b8af7e 100644 --- a/tests/auto/widgets/kernel/qapplication/test/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qapplication/test/CMakeLists.txt @@ -1,7 +1,5 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from test.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## test Test: @@ -11,7 +9,7 @@ list(APPEND test_data "../tmp/README") list(APPEND test_data "../modal") -qt_internal_add_test(tst_qapplication # special case +qt_internal_add_test(tst_qapplication SOURCES ../tst_qapplication.cpp LIBRARIES @@ -21,25 +19,13 @@ qt_internal_add_test(tst_qapplication # special case Qt::Widgets Qt::WidgetsPrivate TESTDATA ${test_data} - OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.." # special case + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.." ) ## Scopes: ##################################################################### -qt_internal_extend_target(tst_qapplication CONDITION builtin_testdata # special case +qt_internal_extend_target(tst_qapplication CONDITION builtin_testdata DEFINES BUILTIN_TESTDATA ) - -#### Keys ignored in scope 3:.:.:test.pro:NOT ANDROID: -# SUBPROGRAMS = "desktopsettingsaware" "modal" - -#### Keys ignored in scope 6:.:.:test.pro:NOT ANDROID: -# TEST_HELPER_INSTALLS = "../debug/helper" - -#### Keys ignored in scope 8:.:.:test.pro:NOT ANDROID: -# TEST_HELPER_INSTALLS = "../release/helper" - -#### Keys ignored in scope 10:.:.:test.pro:NOT ANDROID: -# TEST_HELPER_INSTALLS = "../helper" diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index 127182fd90..2eb2d84504 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #define QT_STATICPLUGIN #include <QtWidgets/qstyleplugin.h> @@ -23,6 +23,7 @@ #include <QtGui/QFontDatabase> #include <QtGui/QClipboard> +#include <QtGui/QStyleHints> #include <QtWidgets/QApplication> #include <QtWidgets/QMessageBox> @@ -94,7 +95,9 @@ private slots: void libraryPaths_qt_plugin_path_2(); #endif +#ifdef QT_BUILD_INTERNAL void sendPostedEvents(); +#endif // ifdef QT_BUILD_INTERNAL void thread(); void desktopSettingsAware(); @@ -117,6 +120,7 @@ private slots: void style(); void applicationPalettePolish(); + void setColorScheme(); void allWidgets(); void topLevelWidgets(); @@ -128,6 +132,7 @@ private slots: void wheelEventPropagation(); void qtbug_12673(); + void qtbug_103611(); void noQuitOnHide(); void globalStaticObjectDestruction(); // run this last @@ -163,6 +168,21 @@ void tst_QApplication::sendEventsOnProcessEvents() QCoreApplication::postEvent(&app, new QEvent(QEvent::Type(QEvent::User + 1))); QCoreApplication::processEvents(); + +#ifdef Q_OS_LINUX + if ((QSysInfo::productType() == "rhel" && QSysInfo::productVersion().startsWith(u'9')) + || (QSysInfo::productType() == "ubuntu" && QSysInfo::productVersion().startsWith(u'2'))) + { + QFile f("/proc/self/maps"); + QVERIFY(f.open(QIODevice::ReadOnly)); + + QByteArray libs = f.readAll(); + if (libs.contains("libqgtk3.") || libs.contains("libqgtk3TestInfix.")) { + QEXPECT_FAIL("", "Fails if qgtk3 (Glib) is loaded, see QTBUG-87137", Abort); + } + } +#endif + QVERIFY(spy.recordedEvents.contains(QEvent::User + 1)); } @@ -293,10 +313,8 @@ void tst_QApplication::alert() QApplication::alert(&widget, -1); QApplication::alert(&widget, 250); widget2.activateWindow(); - QApplication::setActiveWindow(&widget2); QApplication::alert(&widget, 0); widget.activateWindow(); - QApplication::setActiveWindow(&widget); QApplication::alert(&widget, 200); } @@ -485,7 +503,7 @@ static char **QString2cstrings(const QString &args) static QByteArrayList cache; const auto &list = QStringView{ args }.split(' '); - auto argarray = new char*[list.count() + 1]; + auto argarray = new char*[list.size() + 1]; int i = 0; for (; i < list.size(); ++i ) { @@ -574,7 +592,7 @@ void tst_QApplication::lastWindowClosed() QTimer::singleShot(1000, dialog.data(), &QDialog::accept); dialog->exec(); QVERIFY(dialog); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QPointer<CloseWidget>widget = new CloseWidget; widget->setWindowTitle(QLatin1String(QTest::currentTestFunction()) + QLatin1String("CloseWidget")); @@ -583,7 +601,7 @@ void tst_QApplication::lastWindowClosed() QObject::connect(&app, &QGuiApplication::lastWindowClosed, widget.data(), &QObject::deleteLater); QCoreApplication::exec(); QVERIFY(!widget); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); delete dialog; @@ -601,7 +619,7 @@ void tst_QApplication::lastWindowClosed() QTimer::singleShot(1000, &app, &QApplication::closeAllWindows); QCoreApplication::exec(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } class QuitOnLastWindowClosedDialog : public QDialog @@ -634,8 +652,8 @@ public slots: other.exec(); // verify that the eventloop ran and let the timer fire - QCOMPARE(spy.count(), 1); - QCOMPARE(appSpy.count(), 1); + QCOMPARE(spy.size(), 1); + QCOMPARE(appSpy.size(), 1); } private: @@ -660,7 +678,7 @@ public slots: timer1.setSingleShot(true); timer1.start(1000); dialog.exec(); - QCOMPARE(spy1.count(), 1); + QCOMPARE(spy1.size(), 1); show(); } @@ -681,7 +699,7 @@ void tst_QApplication::quitOnLastWindowClosed() QCoreApplication::exec(); // lastWindowClosed() signal should only be sent after the last dialog is closed - QCOMPARE(appSpy.count(), 2); + QCOMPARE(appSpy.size(), 2); } { int argc = 0; @@ -696,8 +714,8 @@ void tst_QApplication::quitOnLastWindowClosed() timer1.setSingleShot(true); timer1.start(1000); dialog.exec(); - QCOMPARE(spy1.count(), 1); - QCOMPARE(appSpy.count(), 0); + QCOMPARE(spy1.size(), 1); + QCOMPARE(appSpy.size(), 0); QTimer timer2; connect(&timer2, &QTimer::timeout, &app, &QCoreApplication::quit); @@ -706,8 +724,8 @@ void tst_QApplication::quitOnLastWindowClosed() timer2.start(1000); int returnValue = QCoreApplication::exec(); QCOMPARE(returnValue, 0); - QCOMPARE(spy2.count(), 1); - QCOMPARE(appSpy.count(), 0); + QCOMPARE(spy2.size(), 1); + QCOMPARE(appSpy.size(), 0); } { int argc = 0; @@ -738,8 +756,8 @@ void tst_QApplication::quitOnLastWindowClosed() QCoreApplication::exec(); - QCOMPARE(spy.count(), 1); - QVERIFY(spy2.count() < 15); // Should be around 10 if closing caused the quit + QCOMPARE(spy.size(), 1); + QVERIFY(spy2.size() < 15); // Should be around 10 if closing caused the quit } bool quitApplicationTriggered = false; @@ -769,7 +787,7 @@ void tst_QApplication::quitOnLastWindowClosed() QCoreApplication::exec(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QVERIFY(quitApplicationTriggered); } { @@ -791,8 +809,8 @@ void tst_QApplication::quitOnLastWindowClosed() QCOMPARE(returnValue, 0); // failure here means the timer above didn't fire, and the // quit was caused the dialog being closed (not the window) - QCOMPARE(timerSpy.count(), 1); - QCOMPARE(appSpy.count(), 2); + QCOMPARE(timerSpy.size(), 1); + QCOMPARE(appSpy.size(), 2); } { int argc = 0; @@ -841,7 +859,7 @@ void tst_QApplication::quitOnLastWindowClosed() QTimer::singleShot(100, &w1, &QWidget::close); QCoreApplication::exec(); - QVERIFY(timerSpy.count() < 10); + QVERIFY(timerSpy.size() < 10); } } @@ -885,6 +903,7 @@ void tst_QApplication::closeAllWindows() { int argc = 0; QApplication app(argc, nullptr); + app.setAttribute(Qt::AA_DontUseNativeDialogs, true); // create some windows new QWidget; @@ -893,7 +912,7 @@ void tst_QApplication::closeAllWindows() // show all windows auto topLevels = QApplication::topLevelWidgets(); - for (QWidget *w : qAsConst(topLevels)) { + for (QWidget *w : std::as_const(topLevels)) { w->show(); QVERIFY(QTest::qWaitForWindowExposed(w)); } @@ -910,14 +929,14 @@ void tst_QApplication::closeAllWindows() PromptOnCloseWidget *promptOnCloseWidget = new PromptOnCloseWidget; // show all windows topLevels = QApplication::topLevelWidgets(); - for (QWidget *w : qAsConst(topLevels)) { + for (QWidget *w : std::as_const(topLevels)) { w->show(); QVERIFY(QTest::qWaitForWindowExposed(w)); } // close the last window to open the prompt (eventloop recurses) promptOnCloseWidget->close(); // all windows should not be visible, except the one that opened the prompt - for (QWidget *w : qAsConst(topLevels)) { + for (QWidget *w : std::as_const(topLevels)) { if (w == promptOnCloseWidget) QVERIFY(w->isVisible()); else @@ -929,8 +948,8 @@ void tst_QApplication::closeAllWindows() bool isPathListIncluded(const QStringList &l, const QStringList &r) { - int size = r.count(); - if (size > l.count()) + int size = r.size(); + if (size > l.size()) return false; #if defined (Q_OS_WIN) Qt::CaseSensitivity cs = Qt::CaseInsensitive; @@ -938,13 +957,13 @@ bool isPathListIncluded(const QStringList &l, const QStringList &r) Qt::CaseSensitivity cs = Qt::CaseSensitive; #endif int i = 0, j = 0; - for ( ; i < l.count() && j < r.count(); ++i) { + for ( ; i < l.size() && j < r.size(); ++i) { if (QDir::toNativeSeparators(l[i]).compare(QDir::toNativeSeparators(r[j]), cs) == 0) { ++j; i = -1; } } - return j == r.count(); + return j == r.size(); } #if QT_CONFIG(library) @@ -1004,7 +1023,7 @@ void tst_QApplication::libraryPaths() { qCDebug(lcTests) << "Initial library path:" << QApplication::libraryPaths(); - int count = QApplication::libraryPaths().count(); + int count = QApplication::libraryPaths().size(); #if 0 // this test doesn't work if KDE 4 is installed QCOMPARE(count, 1); // before creating QApplication, only the PluginsPath is in the libraryPaths() @@ -1013,9 +1032,9 @@ void tst_QApplication::libraryPaths() QApplication::addLibraryPath(installPathPlugins); qCDebug(lcTests) << "installPathPlugins" << installPathPlugins; qCDebug(lcTests) << "After adding plugins path:" << QApplication::libraryPaths(); - QCOMPARE(QApplication::libraryPaths().count(), count); + QCOMPARE(QApplication::libraryPaths().size(), count); QApplication::addLibraryPath(testDir); - QCOMPARE(QApplication::libraryPaths().count(), count + 1); + QCOMPARE(QApplication::libraryPaths().size(), count + 1); // creating QApplication adds the applicationDirPath to the libraryPath int argc = 1; @@ -1025,19 +1044,19 @@ void tst_QApplication::libraryPaths() // On Windows CE these are identical and might also be the case for other // systems too if (appDirPath != installPathPlugins) - QCOMPARE(QApplication::libraryPaths().count(), count + 2); + QCOMPARE(QApplication::libraryPaths().size(), count + 2); } { int argc = 1; QApplication app(argc, &argv0); qCDebug(lcTests) << "Initial library path:" << QCoreApplication::libraryPaths(); - int count = QCoreApplication::libraryPaths().count(); + int count = QCoreApplication::libraryPaths().size(); QString installPathPlugins = QLibraryInfo::path(QLibraryInfo::PluginsPath); QCoreApplication::addLibraryPath(installPathPlugins); qCDebug(lcTests) << "installPathPlugins" << installPathPlugins; qCDebug(lcTests) << "After adding plugins path:" << QCoreApplication::libraryPaths(); - QCOMPARE(QCoreApplication::libraryPaths().count(), count); + QCOMPARE(QCoreApplication::libraryPaths().size(), count); QString appDirPath = QCoreApplication::applicationDirPath(); @@ -1045,14 +1064,14 @@ void tst_QApplication::libraryPaths() QCoreApplication::addLibraryPath(appDirPath + "/.."); qCDebug(lcTests) << "appDirPath" << appDirPath; qCDebug(lcTests) << "After adding appDirPath && appDirPath + /..:" << QCoreApplication::libraryPaths(); - QCOMPARE(QCoreApplication::libraryPaths().count(), count + 1); + QCOMPARE(QCoreApplication::libraryPaths().size(), count + 1); #ifdef Q_OS_MACOS QCoreApplication::addLibraryPath(appDirPath + "/../MacOS"); #else QCoreApplication::addLibraryPath(appDirPath + "/tmp/.."); #endif qCDebug(lcTests) << "After adding appDirPath + /tmp/..:" << QCoreApplication::libraryPaths(); - QCOMPARE(QCoreApplication::libraryPaths().count(), count + 1); + QCOMPARE(QCoreApplication::libraryPaths().size(), count + 1); } } @@ -1124,6 +1143,7 @@ void tst_QApplication::libraryPaths_qt_plugin_path_2() } #endif +#ifdef QT_BUILD_INTERNAL class SendPostedEventsTester : public QObject { Q_OBJECT @@ -1145,14 +1165,14 @@ void SendPostedEventsTester::doTest() QPointer<SendPostedEventsTester> p = this; QApplication::postEvent(this, new QEvent(QEvent::User)); // DeferredDelete should not be delivered until returning from this function - QApplication::postEvent(this, new QDeferredDeleteEvent()); + deleteLater(); QEventLoop eventLoop; QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection); eventLoop.exec(); QVERIFY(p != nullptr); - QCOMPARE(eventSpy.count(), 2); + QCOMPARE(eventSpy.size(), 2); QCOMPARE(eventSpy.at(0), int(QEvent::MetaCall)); QCOMPARE(eventSpy.at(1), int(QEvent::User)); eventSpy.clear(); @@ -1169,6 +1189,7 @@ void tst_QApplication::sendPostedEvents() (void) QCoreApplication::exec(); QVERIFY(p.isNull()); } +#endif void tst_QApplication::thread() { @@ -1313,9 +1334,6 @@ void DeleteLaterWidget::checkDeleteLater() void tst_QApplication::testDeleteLater() { -#ifdef Q_OS_MAC - QSKIP("This test fails and then hangs on OS X, see QTBUG-24318"); -#endif int argc = 0; QApplication app(argc, nullptr); connect(&app, &QGuiApplication::lastWindowClosed, &app, &QCoreApplication::quit); @@ -1541,7 +1559,7 @@ void tst_QApplication::setActiveWindow() delete pb2; w->show(); - QApplication::setActiveWindow(w); // needs this on twm (focus follows mouse) + QApplicationPrivate::setActiveWindow(w); // needs this on twm (focus follows mouse) QVERIFY(pb1->hasFocus()); delete w; } @@ -1577,6 +1595,9 @@ void tst_QApplication::activateDeactivateEvent() int argc = 0; QApplication app(argc, nullptr); + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + Window w1; Window w2; @@ -1603,7 +1624,6 @@ void tst_QApplication::focusWidget() QTextEdit te; te.show(); - QApplication::setActiveWindow(&te); QVERIFY(QTest::qWaitForWindowActive(&te)); const auto focusWidget = QApplication::focusWidget(); @@ -1619,7 +1639,6 @@ void tst_QApplication::focusWidget() QTextEdit te(&w); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); const auto focusWidget = QApplication::focusWidget(); @@ -1652,22 +1671,22 @@ void tst_QApplication::focusChanged() hbox1.addWidget(&le1); hbox1.addWidget(&pb1); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); parent1.show(); - QApplication::setActiveWindow(&parent1); // needs this on twm (focus follows mouse) - QCOMPARE(spy.count(), 1); - QCOMPARE(spy.at(0).count(), 2); + QApplicationPrivate::setActiveWindow(&parent1); // needs this on twm (focus follows mouse) + QCOMPARE(spy.size(), 1); + QCOMPARE(spy.at(0).size(), 2); old = qvariant_cast<QWidget*>(spy.at(0).at(0)); now = qvariant_cast<QWidget*>(spy.at(0).at(1)); QCOMPARE(now, &le1); QCOMPARE(now, QApplication::focusWidget()); QVERIFY(!old); spy.clear(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); pb1.setFocus(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); old = qvariant_cast<QWidget*>(spy.at(0).at(0)); now = qvariant_cast<QWidget*>(spy.at(0).at(1)); QCOMPARE(now, &pb1); @@ -1676,7 +1695,7 @@ void tst_QApplication::focusChanged() spy.clear(); lb1.setFocus(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); old = qvariant_cast<QWidget*>(spy.at(0).at(0)); now = qvariant_cast<QWidget*>(spy.at(0).at(1)); QCOMPARE(now, &lb1); @@ -1685,7 +1704,7 @@ void tst_QApplication::focusChanged() spy.clear(); lb1.clearFocus(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); old = qvariant_cast<QWidget*>(spy.at(0).at(0)); now = qvariant_cast<QWidget*>(spy.at(0).at(1)); QVERIFY(!now); @@ -1704,10 +1723,10 @@ void tst_QApplication::focusChanged() hbox2.addWidget(&pb2); parent2.show(); - QApplication::setActiveWindow(&parent2); // needs this on twm (focus follows mouse) - QVERIFY(spy.count() > 0); // one for deactivation, one for activation on Windows - old = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(0)); - now = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(1)); + QApplicationPrivate::setActiveWindow(&parent2); // needs this on twm (focus follows mouse) + QVERIFY(spy.size() > 0); // one for deactivation, one for activation on Windows + old = qvariant_cast<QWidget*>(spy.at(spy.size()-1).at(0)); + now = qvariant_cast<QWidget*>(spy.at(spy.size()-1).at(1)); QCOMPARE(now, &le2); QCOMPARE(now, QApplication::focusWidget()); QVERIFY(!old); @@ -1732,10 +1751,10 @@ void tst_QApplication::focusChanged() tab.simulate(now); if (!tabAllControls) { - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QCOMPARE(now, QApplication::focusWidget()); } else { - QVERIFY(spy.count() > 0); + QVERIFY(spy.size() > 0); old = qvariant_cast<QWidget*>(spy.at(0).at(0)); now = qvariant_cast<QWidget*>(spy.at(0).at(1)); QCOMPARE(now, &pb2); @@ -1745,11 +1764,11 @@ void tst_QApplication::focusChanged() } if (!tabAllControls) { - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QCOMPARE(now, QApplication::focusWidget()); } else { tab.simulate(now); - QVERIFY(spy.count() > 0); + QVERIFY(spy.size() > 0); old = qvariant_cast<QWidget*>(spy.at(0).at(0)); now = qvariant_cast<QWidget*>(spy.at(0).at(1)); QCOMPARE(now, &le2); @@ -1759,11 +1778,11 @@ void tst_QApplication::focusChanged() } if (!tabAllControls) { - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QCOMPARE(now, QApplication::focusWidget()); } else { backtab.simulate(now); - QVERIFY(spy.count() > 0); + QVERIFY(spy.size() > 0); old = qvariant_cast<QWidget*>(spy.at(0).at(0)); now = qvariant_cast<QWidget*>(spy.at(0).at(1)); QCOMPARE(now, &pb2); @@ -1774,12 +1793,12 @@ void tst_QApplication::focusChanged() if (!tabAllControls) { - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QCOMPARE(now, QApplication::focusWidget()); old = &pb2; } else { backtab.simulate(now); - QVERIFY(spy.count() > 0); + QVERIFY(spy.size() > 0); old = qvariant_cast<QWidget*>(spy.at(0).at(0)); now = qvariant_cast<QWidget*>(spy.at(0).at(1)); QCOMPARE(now, &le2); @@ -1790,10 +1809,10 @@ void tst_QApplication::focusChanged() click.simulate(old); if (!(pb2.focusPolicy() & Qt::ClickFocus)) { - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QCOMPARE(now, QApplication::focusWidget()); } else { - QVERIFY(spy.count() > 0); + QVERIFY(spy.size() > 0); old = qvariant_cast<QWidget*>(spy.at(0).at(0)); now = qvariant_cast<QWidget*>(spy.at(0).at(1)); QCOMPARE(now, &pb2); @@ -1802,7 +1821,7 @@ void tst_QApplication::focusChanged() spy.clear(); click.simulate(old); - QVERIFY(spy.count() > 0); + QVERIFY(spy.size() > 0); old = qvariant_cast<QWidget*>(spy.at(0).at(0)); now = qvariant_cast<QWidget*>(spy.at(0).at(1)); QCOMPARE(now, &le2); @@ -1812,16 +1831,16 @@ void tst_QApplication::focusChanged() } parent1.activateWindow(); - QApplication::setActiveWindow(&parent1); // needs this on twm (focus follows mouse) - QVERIFY(spy.count() == 1 || spy.count() == 2); // one for deactivation, one for activation on Windows + QApplicationPrivate::setActiveWindow(&parent1); // needs this on twm (focus follows mouse) + QVERIFY(spy.size() == 1 || spy.size() == 2); // one for deactivation, one for activation on Windows //on windows, the change of focus is made in 2 steps //(the focusChanged SIGNAL is emitted twice) - if (spy.count()==1) - old = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(0)); + if (spy.size()==1) + old = qvariant_cast<QWidget*>(spy.at(spy.size()-1).at(0)); else - old = qvariant_cast<QWidget*>(spy.at(spy.count()-2).at(0)); - now = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(1)); + old = qvariant_cast<QWidget*>(spy.at(spy.size()-2).at(0)); + now = qvariant_cast<QWidget*>(spy.at(spy.size()-1).at(1)); QCOMPARE(now, &le1); QCOMPARE(now, QApplication::focusWidget()); QCOMPARE(old, &le2); @@ -2034,6 +2053,122 @@ void tst_QApplication::applicationPalettePolish() } } +void tst_QApplication::setColorScheme() +{ + int argc = 1; + QApplication app(argc, &argv0); + + if (QStringList{"minimal", "offscreen", "wayland", "xcb", "wasm", "webassembly"} + .contains(QGuiApplication::platformName(), Qt::CaseInsensitive)) { + QSKIP("Setting the colorScheme is not implemented on this platform."); + } + qDebug() << "Testing setColorScheme on platform" << QGuiApplication::platformName(); + + if (QByteArrayView(app.style()->metaObject()->className()) == "QWindowsVistaStyle") + QSKIP("Setting the colorScheme is not supported with the Windows Vista style."); + + const Qt::ColorScheme defaultColorScheme = QApplication::styleHints()->colorScheme(); + // if we implement setColorScheme, then we must be able to read it + QVERIFY(defaultColorScheme != Qt::ColorScheme::Unknown); + const Qt::ColorScheme newColorScheme = defaultColorScheme == Qt::ColorScheme::Light + ? Qt::ColorScheme::Dark : Qt::ColorScheme::Light; + + class TopLevelWidget : public QWidget + { + QList<QEvent::Type> events; + public: + TopLevelWidget() + { + setObjectName("colorScheme TopLevelWidget"); + } + + void clearEvents() + { + events.clear(); + } + qsizetype eventCount(QEvent::Type type) const + { + return events.count(type); + } + protected: + bool event(QEvent *event) override + { + switch (event->type()) { + case QEvent::ApplicationPaletteChange: + case QEvent::PaletteChange: + case QEvent::ThemeChange: + events << event->type(); + break; + default: + break; + } + + return QWidget::event(event); + } + } topLevelWidget; + topLevelWidget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevelWidget)); + + QSignalSpy colorSchemeChangedSpy(app.styleHints(), &QStyleHints::colorSchemeChanged); + + // always start with a clean list + topLevelWidget.clearEvents(); + const QPalette defaultPalette = topLevelWidget.palette(); + + bool oldPaletteWhenSchemeChanged = false; + connect(app.styleHints(), &QStyleHints::colorSchemeChanged, this, + [defaultPalette, &topLevelWidget, &oldPaletteWhenSchemeChanged]{ + oldPaletteWhenSchemeChanged = defaultPalette == topLevelWidget.palette(); + }); + + app.styleHints()->setColorScheme(newColorScheme); + QTRY_COMPARE(colorSchemeChangedSpy.count(), 1); + // We have not yet updated the palette when we emit the colorSchemeChanged + // signal, so the toplevel widget should still use the previous palette + QVERIFY(oldPaletteWhenSchemeChanged); + QCOMPARE(topLevelWidget.eventCount(QEvent::ThemeChange), 1); + // We can't guarantee that there is only one ApplicationPaletteChange, + // and they might arrive asynchronously in response to ThemeChange + QTRY_COMPARE_GE(topLevelWidget.eventCount(QEvent::ApplicationPaletteChange), 1); + // But we can guarantee a single PaletteChange event for the widget + QCOMPARE(topLevelWidget.eventCount(QEvent::PaletteChange), 1); + // The palette should have changed + QCOMPARE_NE(topLevelWidget.palette(), defaultPalette); + + topLevelWidget.clearEvents(); + colorSchemeChangedSpy.clear(); + + // verify that a widget shown with a color scheme override in place respect that + QWidget newWidget; + newWidget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&newWidget)); + QCOMPARE(newWidget.palette(), topLevelWidget.palette()); + + // Setting to Unknown should follow the system preference again + app.styleHints()->setColorScheme(Qt::ColorScheme::Unknown); + QTRY_COMPARE(colorSchemeChangedSpy.count(), 1); + QCOMPARE(app.styleHints()->colorScheme(), defaultColorScheme); + QTRY_COMPARE(topLevelWidget.eventCount(QEvent::PaletteChange), 1); + + auto debugPalette = qScopeGuard([defaultPalette, &topLevelWidget]{ + qDebug() << "Inspecting palettes for differences"; + const QPalette palette = topLevelWidget.palette(); + for (int g = 0; g < QPalette::NColorGroups; ++g) { + for (int r = 0; r < QPalette::NColorRoles; ++r) { + const auto group = static_cast<QPalette::ColorGroup>(g); + const auto role = static_cast<QPalette::ColorRole>(r); + qDebug() << "...Checking" << group << role; + const auto actualBrush = palette.brush(group, role); + const auto expectedBrush = defaultPalette.brush(group, role); + if (palette.brush(group, role) != defaultPalette.brush(group, role)) + qWarning() << "...Difference in" << group << role << actualBrush << expectedBrush; + } + } + }); + QCOMPARE(topLevelWidget.palette(), defaultPalette); + debugPalette.dismiss(); +} + void tst_QApplication::allWidgets() { int argc = 1; @@ -2056,11 +2191,11 @@ void tst_QApplication::topLevelWidgets() #endif QCoreApplication::processEvents(); QVERIFY(QApplication::topLevelWidgets().contains(w)); - QCOMPARE(QApplication::topLevelWidgets().count(), 1); + QCOMPARE(QApplication::topLevelWidgets().size(), 1); delete w; w = nullptr; QCoreApplication::processEvents(); - QCOMPARE(QApplication::topLevelWidgets().count(), 0); + QCOMPARE(QApplication::topLevelWidgets().size(), 0); } @@ -2477,7 +2612,7 @@ void tst_QApplication::wheelEventPropagation() int vcount = 0; int hcount = 0; - for (const auto &event : qAsConst(events)) { + for (const auto &event : std::as_const(events)) { const QPoint pixelDelta = event.orientation == Qt::Vertical ? QPoint(0, -scrollStep) : QPoint(-scrollStep, 0); const QPoint angleDelta = event.orientation == Qt::Vertical ? QPoint(0, -120) : QPoint(-120, 0); QWindowSystemInterface::handleWheelEvent(outerArea.windowHandle(), center, global, @@ -2488,10 +2623,10 @@ void tst_QApplication::wheelEventPropagation() else ++hcount; QCoreApplication::processEvents(); - QCOMPARE(innerVSpy.count(), innerScrolls ? vcount : 0); - QCOMPARE(innerHSpy.count(), innerScrolls ? hcount : 0); - QCOMPARE(outerVSpy.count(), innerScrolls ? 0 : vcount); - QCOMPARE(outerHSpy.count(), innerScrolls ? 0 : hcount); + QCOMPARE(innerVSpy.size(), innerScrolls ? vcount : 0); + QCOMPARE(innerHSpy.size(), innerScrolls ? hcount : 0); + QCOMPARE(outerVSpy.size(), innerScrolls ? 0 : vcount); + QCOMPARE(outerHSpy.size(), innerScrolls ? 0 : hcount); } } @@ -2510,6 +2645,20 @@ void tst_QApplication::qtbug_12673() #endif } +void tst_QApplication::qtbug_103611() +{ + { + int argc = 0; + QApplication app(argc, nullptr); + auto ll = QLocale().uiLanguages(); + } + { + int argc = 0; + QApplication app(argc, nullptr); + auto ll = QLocale().uiLanguages(); + } +} + class NoQuitOnHideWidget : public QWidget { Q_OBJECT @@ -2539,8 +2688,26 @@ public: explicit ShowCloseShowWidget(bool showAgain, QWidget *parent = nullptr) : QWidget(parent), showAgain(showAgain) { + int timeout = 500; +#ifdef Q_OS_ANDROID + // On Android, CI Android emulator is not running HW accelerated graphics and can be slow, + // use a longer timeout to avoid flaky failures + timeout = 1000; +#endif + QTimer::singleShot(timeout, this, [] () { QCoreApplication::exit(1); }); + } + + bool shown = false; + +protected: + void showEvent(QShowEvent *) override + { QTimer::singleShot(0, this, &ShowCloseShowWidget::doClose); - QTimer::singleShot(500, this, [] () { QCoreApplication::exit(1); }); + shown = true; + } + void hideEvent(QHideEvent *) override + { + shown = false; } private slots: @@ -2556,16 +2723,21 @@ private: void tst_QApplication::abortQuitOnShow() { + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Wayland: This crash, see QTBUG-123172."); + int argc = 0; QApplication app(argc, nullptr); ShowCloseShowWidget window1(false); window1.setWindowTitle(QLatin1String(QTest::currentTestFunction())); window1.show(); + QVERIFY(QTest::qWaitFor([&window1](){ return window1.shown; })); QCOMPARE(QCoreApplication::exec(), 0); ShowCloseShowWidget window2(true); window2.setWindowTitle(QLatin1String(QTest::currentTestFunction())); window2.show(); + QVERIFY(QTest::qWaitFor([&window2](){ return window2.shown; })); QCOMPARE(QCoreApplication::exec(), 1); } @@ -2580,7 +2752,7 @@ void tst_QApplication::staticFunctions() QApplication::activeModalWidget(); QApplication::focusWidget(); QApplication::activeWindow(); - QApplication::setActiveWindow(nullptr); + QApplicationPrivate::setActiveWindow(nullptr); QApplication::widgetAt(QPoint(0, 0)); QApplication::topLevelAt(QPoint(0, 0)); QTest::ignoreMessage(QtWarningMsg, "Must construct a QApplication first."); diff --git a/tests/auto/widgets/kernel/qboxlayout/CMakeLists.txt b/tests/auto/widgets/kernel/qboxlayout/CMakeLists.txt index 1f084130c5..5b60382fba 100644 --- a/tests/auto/widgets/kernel/qboxlayout/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qboxlayout/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qboxlayout.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qboxlayout Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qboxlayout LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qboxlayout SOURCES tst_qboxlayout.cpp diff --git a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp index 3a7f33228b..4313d9891c 100644 --- a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp +++ b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -192,7 +192,7 @@ void tst_QBoxLayout::setStyleShouldChangeSpacing() window.setWindowTitle(QTest::currentTestFunction()); QHBoxLayout *hbox = new QHBoxLayout(&window); QPushButton *pb1 = new QPushButton(tr("The spacing between this")); - QPushButton *pb2 = new QPushButton(tr("and this button should depend on the style of the parent widget"));; + QPushButton *pb2 = new QPushButton(tr("and this button should depend on the style of the parent widget")); pb1->setAttribute(Qt::WA_LayoutUsesWidgetRect); pb2->setAttribute(Qt::WA_LayoutUsesWidgetRect); hbox->addWidget(pb1); @@ -517,14 +517,14 @@ void tst_QBoxLayout::testLayoutEngine() QHBoxLayout box; box.setSpacing(spacing); int i; - for (i = 0; i < itemDescriptions.count(); ++i) { + for (i = 0; i < itemDescriptions.size(); ++i) { Descr descr = itemDescriptions.at(i); LayoutItem *li = new LayoutItem(descr); box.addItem(li); box.setStretch(i, descr.stretch); } box.setGeometry(QRect(0,0,size,100)); - for (i = 0; i < expectedSizes.count(); ++i) { + for (i = 0; i < expectedSizes.size(); ++i) { int xSize = expectedSizes.at(i); int xPos = expectedPositions.at(i); QLayoutItem *item = box.itemAt(i); diff --git a/tests/auto/widgets/kernel/qformlayout/BLACKLIST b/tests/auto/widgets/kernel/qformlayout/BLACKLIST deleted file mode 100644 index e69de29bb2..0000000000 --- a/tests/auto/widgets/kernel/qformlayout/BLACKLIST +++ /dev/null diff --git a/tests/auto/widgets/kernel/qformlayout/CMakeLists.txt b/tests/auto/widgets/kernel/qformlayout/CMakeLists.txt index 440edaf876..9e1da4c6a3 100644 --- a/tests/auto/widgets/kernel/qformlayout/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qformlayout/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qformlayout.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qformlayout Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qformlayout LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qformlayout SOURCES tst_qformlayout.cpp diff --git a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp index 33e6bd64db..9638823538 100644 --- a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp +++ b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -112,6 +112,7 @@ private slots: void setLayout(); void hideShowRow(); void showWithHiddenRow(); + void hiddenRowAndStretch(); /* QLayoutItem *itemAt(int row, ItemRole role) const; @@ -1253,6 +1254,49 @@ void tst_QFormLayout::showWithHiddenRow() topLevel.show(); } +/* + Test that hiding rows does not leave outdated layout data behind + in hidden items that results in out-of-bounds array access. See + QTBUG-109237. +*/ +void tst_QFormLayout::hiddenRowAndStretch() +{ + QWidget topLevel; + QFormLayout layout; + layout.setRowWrapPolicy(QFormLayout::WrapAllRows); + + // We need our own stretcher item so that QFormLayout doesn't insert + // it's own, as that would grow the size of the layout data array again. + QSpacerItem *stretch = new QSpacerItem(100, 100, QSizePolicy::Expanding, QSizePolicy::Expanding); + layout.setItem(0, QFormLayout::FieldRole, stretch); + + QLabel *lastLabel = nullptr; + QLineEdit *lastField = nullptr; + for (int row = 1; row < 4; ++row) { + QLabel *label = new QLabel(QString("Label %1").arg(row)); + label->setWordWrap(true); + QLineEdit *field = new QLineEdit; + layout.setWidget(row, QFormLayout::LabelRole, label); + layout.setWidget(row, QFormLayout::FieldRole, field); + if (row == 3) { + lastLabel = label; + lastField = field; + } + } + + Q_ASSERT(lastLabel); + Q_ASSERT(lastField); + + topLevel.setLayout(&layout); + topLevel.sizeHint(); + + lastLabel->setVisible(false); + lastField->setVisible(false); + + // should not assert here + topLevel.show(); +} + void tst_QFormLayout::itemAt() { QWidget topLevel; diff --git a/tests/auto/widgets/kernel/qgesturerecognizer/CMakeLists.txt b/tests/auto/widgets/kernel/qgesturerecognizer/CMakeLists.txt index 995f95fa23..ffa54992d3 100644 --- a/tests/auto/widgets/kernel/qgesturerecognizer/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qgesturerecognizer/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgesturerecognizer.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgesturerecognizer Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgesturerecognizer LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgesturerecognizer SOURCES tst_qgesturerecognizer.cpp diff --git a/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp index 87e0290473..cdab480d84 100644 --- a/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp +++ b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtTest/QTest> @@ -71,7 +71,7 @@ TestWidget::TestWidget(const GestureTypeVector &gestureTypes) { setAttribute(Qt::WA_AcceptTouchEvents); - foreach (Qt::GestureType gestureType, gestureTypes) { + for (Qt::GestureType gestureType : gestureTypes) { grabGesture(gestureType); m_receivedGestures.insert(gestureType, false); } diff --git a/tests/auto/widgets/kernel/qgridlayout/CMakeLists.txt b/tests/auto/widgets/kernel/qgridlayout/CMakeLists.txt index dd26982ad8..bf72bc0ae6 100644 --- a/tests/auto/widgets/kernel/qgridlayout/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qgridlayout/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgridlayout.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgridlayout Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgridlayout LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgridlayout SOURCES sortdialog.ui diff --git a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp index fda88fcd83..3c325699a7 100644 --- a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp +++ b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -58,7 +58,8 @@ private slots: static inline int visibleTopLevelWidgetCount() { int result= 0; - foreach (const QWidget *topLevel, QApplication::topLevelWidgets()) { + const auto topLevels = QApplication::topLevelWidgets(); + for (const QWidget *topLevel : topLevels) { if (topLevel->isVisible()) ++result; } @@ -210,6 +211,9 @@ void tst_QGridLayout::badDistributionBug() void tst_QGridLayout::setMinAndMaxSize() { + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("This test crashes on Wayland, see also QTBUG-107184"); + QWidget widget; setFrameless(&widget); QGridLayout layout(&widget); @@ -658,7 +662,7 @@ void tst_QGridLayout::spacingsAndMargins() QSKIP("The screen is too small to run this test case"); // We are relying on the order here... - for (int pi = 0; pi < sizehinters.count(); ++pi) { + for (int pi = 0; pi < sizehinters.size(); ++pi) { QPoint pt = sizehinters.at(pi)->mapTo(&toplevel, QPoint(0, 0)); QCOMPARE(pt, expectedpositions.at(pi)); } @@ -828,7 +832,7 @@ void tst_QGridLayout::minMaxSize() QList<QPointer<SizeHinterFrame> > sizehinters; for (int i = 0; i < rows; ++i) { for (int j = 0; j < columns; ++j) { - SizeInfo si = sizeinfos.at(sizehinters.count()); + SizeInfo si = sizeinfos.at(sizehinters.size()); int numpixels = si.hfwNumPixels; if (pass == 1 && numpixels == -1) numpixels = -2; //### yuk, (and don't fake it if it already tests sizehint) @@ -857,7 +861,7 @@ void tst_QGridLayout::minMaxSize() QTRY_COMPARE(toplevel.size(), toplevel.sizeHint()); } // We are relying on the order here... - for (int pi = 0; pi < sizehinters.count(); ++pi) { + for (int pi = 0; pi < sizehinters.size(); ++pi) { QPoint pt = sizehinters.at(pi)->mapTo(&toplevel, QPoint(0, 0)); QCOMPARE(pt, sizeinfos.at(pi).expectedPos); } @@ -1027,7 +1031,7 @@ void tst_QGridLayout::styleDependentSpacingsAndMargins() widget.adjustSize(); QApplication::processEvents(); - for (int pi = 0; pi < expectedpositions.count(); ++pi) { + for (int pi = 0; pi < expectedpositions.size(); ++pi) { QCOMPARE(sizehinters.at(pi)->pos(), expectedpositions.at(pi)); } } @@ -1417,7 +1421,7 @@ void tst_QGridLayout::layoutSpacing() QLayout *layout = widget->layout(); QVERIFY(layout); - for (int pi = 0; pi < expectedpositions.count(); ++pi) { + for (int pi = 0; pi < expectedpositions.size(); ++pi) { QLayoutItem *item = layout->itemAt(pi); //qDebug() << item->widget()->pos(); QCOMPARE(item->widget()->pos(), expectedpositions.at(pi)); diff --git a/tests/auto/widgets/kernel/qlayout/CMakeLists.txt b/tests/auto/widgets/kernel/qlayout/CMakeLists.txt index ad5c774813..6bda750c0f 100644 --- a/tests/auto/widgets/kernel/qlayout/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qlayout/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qlayout.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qlayout Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qlayout LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Collect test data file(GLOB_RECURSE test_data_glob RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp index 9d5f7940cc..bd170ca8ab 100644 --- a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp +++ b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -378,10 +378,10 @@ void tst_QLayout::removeWidget() { QHBoxLayout layout; QCOMPARE(layout.count(), 0); - QWidget w; - layout.addWidget(&w); + std::unique_ptr<QWidget> w(new QWidget); + layout.addWidget(w.get()); QCOMPARE(layout.count(), 1); - layout.removeWidget(&w); + layout.removeWidget(w.get()); QCOMPARE(layout.count(), 0); QPointer<QLayout> childLayout(new QHBoxLayout); @@ -395,6 +395,12 @@ void tst_QLayout::removeWidget() QCOMPARE(layout.count(), 0); QVERIFY(!childLayout.isNull()); + + // Test inactive layout consumes ChildRemoved event (QTBUG-124151) + layout.addWidget(w.get()); + layout.setEnabled(false); + w.reset(); + layout.setEnabled(true); } QTEST_MAIN(tst_QLayout) diff --git a/tests/auto/widgets/kernel/qshortcut/CMakeLists.txt b/tests/auto/widgets/kernel/qshortcut/CMakeLists.txt index c1ba5db567..517286f324 100644 --- a/tests/auto/widgets/kernel/qshortcut/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qshortcut/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qshortcut.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qshortcut Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qshortcut LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qshortcut SOURCES tst_qshortcut.cpp @@ -16,4 +20,19 @@ qt_internal_add_test(tst_qshortcut Qt::Gui Qt::GuiPrivate Qt::Widgets + Qt::WidgetsPrivate +) + +qt_internal_add_test(tst_qguishortcut_with_qapplication + SOURCES + ../../../gui/kernel/qshortcut/tst_qshortcut.cpp + DEFINES + tst_QShortcut=tst_QGuiShortcutWithQApplication + INCLUDE_DIRECTORIES + .. + LIBRARIES + Qt::Gui + Qt::GuiPrivate + Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp b/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp index 2beecc7112..d34df43b01 100644 --- a/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp +++ b/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -23,6 +23,8 @@ #include <QtGui/private/qguiapplication_p.h> #include <QtGui/qpa/qplatformintegration.h> +#include <QtWidgets/private/qapplication_p.h> + QT_BEGIN_NAMESPACE class QMainWindow; class QTextEdit; @@ -313,11 +315,11 @@ void tst_QShortcut::number_data() Shift + Qt::Key_Plus on Shift + Qt::Key_Pluss Qt::Key_Plus on Shift + Qt::Key_Pluss */ - QTest::newRow("N002 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT | Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N002:Shift+M - [Shift+M]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; + QTest::newRow("N002 - slot1") << SetupAccel << TriggerSlot1 << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_M).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; + QTest::newRow("N002:Shift+M - [Shift+M]") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_M).toCombined() << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("N002:M - [Shift+M]") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N002 - slot2") << SetupAccel << TriggerSlot2 << QString() << int(Qt::SHIFT | Qt::Key_Plus) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N002:Shift++ [Shift++]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; + QTest::newRow("N002 - slot2") << SetupAccel << TriggerSlot2 << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Plus).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; + QTest::newRow("N002:Shift++ [Shift++]") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Plus).toCombined() << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; QTest::newRow("N002:+ [Shift++]") << TestAccel << NoWidget << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("N002 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all @@ -335,8 +337,8 @@ void tst_QShortcut::number_data() Qt::Key_F1 on Shift + Qt::Key_F1 */ - QTest::newRow("N004 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT | Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N004:Shift+F1 - [Shift+F1]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; + QTest::newRow("N004 - slot1") << SetupAccel << TriggerSlot1 << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_F1).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; + QTest::newRow("N004:Shift+F1 - [Shift+F1]") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_F1).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("N004:F1 - [Shift+F1]") << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("N004 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all @@ -352,7 +354,7 @@ void tst_QShortcut::number_data() //QTest::newRow("N005a:Shift+Tab - [Tab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; // (Shift+)BackTab != Tab, but Shift+BackTab == Shift+Tab QTest::newRow("N005a:Backtab - [Tab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N005a:Shift+Backtab - [Tab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; + QTest::newRow("N005a:Shift+Backtab - [Tab]") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Backtab).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("N005a - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all /* Testing Single Sequences @@ -361,11 +363,11 @@ void tst_QShortcut::number_data() Qt::Key_Backtab on Shift + Qt::Key_Tab Shift + Qt::Key_Backtab on Shift + Qt::Key_Tab */ - QTest::newRow("N005b - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT | Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; + QTest::newRow("N005b - slot1") << SetupAccel << TriggerSlot1 << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Tab).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("N005b:Tab - [Shift+Tab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N005b:Shift+Tab - [Shift+Tab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; + QTest::newRow("N005b:Shift+Tab - [Shift+Tab]") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Tab).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("N005b:BackTab - [Shift+Tab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N005b:Shift+BackTab - [Shift+Tab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; + QTest::newRow("N005b:Shift+BackTab - [Shift+Tab]") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Backtab).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("N005b - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all /* Testing Single Sequences @@ -378,10 +380,10 @@ void tst_QShortcut::number_data() QTest::newRow("N006a:Tab - [BackTab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // This should work, since platform dependent code will transform the // Shift+Tab into a Shift+BackTab, which should trigger the shortcut - QTest::newRow("N006a:Shift+Tab - [BackTab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; //XFAIL + QTest::newRow("N006a:Shift+Tab - [BackTab]") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Tab).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; //XFAIL QTest::newRow("N006a:BackTab - [BackTab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; //commented out because the behaviour changed, those tests should be updated - //QTest::newRow("N006a:Shift+BackTab - [BackTab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; + //QTest::newRow("N006a:Shift+BackTab - [BackTab]") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Backtab).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("N006a - clear") << ClearAll << NoWidget<< QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all /* Testing Single Sequences @@ -390,11 +392,11 @@ void tst_QShortcut::number_data() Qt::Key_Backtab on Shift + Qt::Key_Backtab Shift + Qt::Key_Backtab on Shift + Qt::Key_Backtab */ - QTest::newRow("N006b - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT | Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; + QTest::newRow("N006b - slot1") << SetupAccel << TriggerSlot1 << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Backtab).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("N006b:Tab - [Shift+BackTab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N006b:Shift+Tab - [Shift+BackTab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; + QTest::newRow("N006b:Shift+Tab - [Shift+BackTab]") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Tab).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("N006b:BackTab - [Shift+BackTab]") << TestAccel << NoWidget << QString() << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N006b:Shift+BackTab - [Shift+BackTab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; //XFAIL + QTest::newRow("N006b:Shift+BackTab - [Shift+BackTab]") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Backtab).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; //XFAIL QTest::newRow("N006b - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all //=========================================== @@ -407,9 +409,9 @@ void tst_QShortcut::number_data() Shift + Qt::Key_F1 */ QTest::newRow("N007 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N007 - slot2") << SetupAccel << TriggerSlot2 << QString() << int(Qt::SHIFT | Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; + QTest::newRow("N007 - slot2") << SetupAccel << TriggerSlot2 << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_F1).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("N007:F1") << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; - QTest::newRow("N007:Shift + F1") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; + QTest::newRow("N007:Shift + F1") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_F1).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; QTest::newRow("N007 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all /* Testing Single Sequences @@ -419,13 +421,13 @@ void tst_QShortcut::number_data() Alt + Qt::Key_M */ QTest::newRow("N01 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N02 - slot2") << SetupAccel << TriggerSlot2 << QString() << int(Qt::SHIFT | Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N03 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::CTRL | Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N04 - slot2") << SetupAccel << TriggerSlot2 << QString() << int(Qt::ALT | Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; + QTest::newRow("N02 - slot2") << SetupAccel << TriggerSlot2 << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_M).toCombined() << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; + QTest::newRow("N03 - slot1") << SetupAccel << TriggerSlot1 << QString() << QKeyCombination(Qt::CTRL, Qt::Key_M).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; + QTest::newRow("N04 - slot2") << SetupAccel << TriggerSlot2 << QString() << QKeyCombination(Qt::ALT, Qt::Key_M).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("N:Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; - QTest::newRow("N:Shift+Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; - QTest::newRow("N:Ctrl+Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::CTRL | Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; - QTest::newRow("N:Alt+Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::ALT | Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; + QTest::newRow("N:Shift+Qt::Key_M") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_M).toCombined() << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; + QTest::newRow("N:Ctrl+Qt::Key_M") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::CTRL, Qt::Key_M).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; + QTest::newRow("N:Alt+Qt::Key_M") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::ALT, Qt::Key_M).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; /* Testing Single Sequence Ambiguity Qt::Key_M on shortcut2 @@ -440,11 +442,11 @@ void tst_QShortcut::number_data() Qt::Key_K */ QTest::newRow("N06 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N07 - slot2") << SetupAccel << TriggerSlot2 << QString() << int(Qt::SHIFT | Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; + QTest::newRow("N07 - slot2") << SetupAccel << TriggerSlot2 << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Aring).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("N08 - slot2") << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_K) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("N:Qt::Key_aring") << TestAccel << NoWidget << QString() << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; - QTest::newRow("N:Qt::Key_Aring") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; + QTest::newRow("N:Qt::Key_Aring") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Aring).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; QTest::newRow("N:Qt::Key_aring - Text Form") << TestAccel << NoWidget << QString() << 0 << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("N:Qt::Key_Aring - Text Form") << TestAccel << NoWidget << QString() << int(Qt::SHIFT) << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; QTest::newRow("N:Qt::Qt::Key_K") << TestAccel << NoWidget << QString() << int(Qt::Key_K) << int('k') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; @@ -457,11 +459,11 @@ void tst_QShortcut::number_data() */ QTest::newRow("N10 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("N11 - slot2") << SetupAccel << TriggerSlot2 << QString() << int(Qt::Key_I) << 0 << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("N12 - slot1") << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT | Qt::Key_I) << 0 << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << NoResult; + QTest::newRow("N12 - slot1") << SetupAccel << TriggerSlot1 << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_I).toCombined() << 0 << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("N:Qt::Key_M (2)") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("N:Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::Key_I) << int('i') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot2Triggered; - QTest::newRow("N:Shift+Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_I) << int('I') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot1Triggered; + QTest::newRow("N:Shift+Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_I).toCombined() << int('I') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("N:end") << TestEnd << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; } @@ -503,10 +505,10 @@ void tst_QShortcut::text_data() Ctrl + Qt::Key_Plus on Ctrl + Qt::Key_Pluss */ QTest::newRow("T002 - slot1") << SetupAccel << TriggerSlot1 << QString("Shift+M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("T002:Shift+M - [Shift+M]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; + QTest::newRow("T002:Shift+M - [Shift+M]") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_M).toCombined() << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("T002:M - [Shift+M]") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("T002 - slot2") << SetupAccel << TriggerSlot2 << QString("Shift++") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("T002:Shift++ [Shift++]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; + QTest::newRow("T002:Shift++ [Shift++]") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Plus).toCombined() << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; QTest::newRow("T002:+ [Shift++]") << TestAccel << NoWidget << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("T002 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all @@ -518,7 +520,7 @@ void tst_QShortcut::text_data() QTest::newRow("T002b - slot1") << SetupAccel << TriggerSlot1 << QString("Ctrl++") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; //commented out because the behaviour changed, those tests should be updated //QTest::newRow("T002b:Shift+Ctrl++ [Ctrl++]")<< TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::CTRL + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; - QTest::newRow("T002b:Ctrl++ [Ctrl++]") << TestAccel << NoWidget << QString() << int(Qt::CTRL | Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; + QTest::newRow("T002b:Ctrl++ [Ctrl++]") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::CTRL, Qt::Key_Plus).toCombined() << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("T002b:+ [Ctrl++]") << TestAccel << NoWidget << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("T002b - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all @@ -537,7 +539,7 @@ void tst_QShortcut::text_data() Qt::Key_F1 on Shift + Qt::Key_F1 */ QTest::newRow("T004 - slot1") << SetupAccel << TriggerSlot1 << QString("Shift+F1") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; - QTest::newRow("T004:Shift+F1 - [Shift+F1]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; + QTest::newRow("T004:Shift+F1 - [Shift+F1]") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_F1).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("T004:F1 - [Shift+F1]") << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("T004 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all @@ -553,7 +555,7 @@ void tst_QShortcut::text_data() QTest::newRow("T007 - slot1") << SetupAccel << TriggerSlot1 << QString("F1") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("T007 - slot2") << SetupAccel << TriggerSlot2 << QString("Shift+F1") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("T007:F1") << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; - QTest::newRow("T007:Shift + F1") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; + QTest::newRow("T007:Shift + F1") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_F1).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; QTest::newRow("T007 - clear") << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all /* Testing Single Sequences @@ -568,9 +570,9 @@ void tst_QShortcut::text_data() QTest::newRow("T04 - slot2") << SetupAccel << TriggerSlot2 << QString("Alt+M") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("T:Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; - QTest::newRow("T:Shift + Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; - QTest::newRow("T:Ctrl + Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::CTRL | Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; - QTest::newRow("T:Alt + Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::ALT | Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; + QTest::newRow("T:Shift + Qt::Key_M") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_M).toCombined() << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; + QTest::newRow("T:Ctrl + Qt::Key_M") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::CTRL, Qt::Key_M).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; + QTest::newRow("T:Alt + Qt::Key_M") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::ALT, Qt::Key_M).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; /* Testing Single Sequence Ambiguity Qt::Key_M on shortcut2 @@ -589,7 +591,7 @@ void tst_QShortcut::text_data() QTest::newRow("T07 - slot2") << SetupAccel << TriggerSlot2 << QString::fromLatin1("Shift+\x0C5")<< 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("T08 - slot2") << SetupAccel << TriggerSlot1 << QString("K") << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("T:Qt::Key_aring") << TestAccel << NoWidget << QString() << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; - QTest::newRow("T:Qt::Key_Aring") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; + QTest::newRow("T:Qt::Key_Aring") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_Aring).toCombined() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; QTest::newRow("T:Qt::Key_aring - Text Form") << TestAccel << NoWidget << QString() << 0 << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("T:Qt::Key_Aring - Text Form") << TestAccel << NoWidget << QString() << int(Qt::SHIFT) << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; QTest::newRow("T:Qt::Key_K") << TestAccel << NoWidget << QString() << int(Qt::Key_K) << int('k') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; @@ -605,7 +607,7 @@ void tst_QShortcut::text_data() QTest::newRow("T12 - slot1") << SetupAccel << TriggerSlot1 << QString("Shift+I, M")<< 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; QTest::newRow("T:Qt::Key_M (2)") << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("T:Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::Key_I) << int('i') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot2Triggered; - QTest::newRow("T:Shift+Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString() << int(Qt::SHIFT | Qt::Key_I) << int('I') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot1Triggered; + QTest::newRow("T:Shift+Qt::Key_I, Qt::Key_M") << TestAccel << NoWidget << QString() << QKeyCombination(Qt::SHIFT, Qt::Key_I).toCombined() << int('I') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot1Triggered; QTest::newRow("T:end") << TestEnd << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; } @@ -1062,7 +1064,6 @@ void tst_QShortcut::context() // Focus on 'other1' edit, so Active Window context should trigger other1->activateWindow(); // <--- - QApplication::setActiveWindow(other1); QCOMPARE(QApplication::activeWindow(), other1->window()); QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(other1)); @@ -1154,7 +1155,6 @@ void tst_QShortcut::duplicatedShortcutOverride() w.resize(200, 200); w.move(QGuiApplication::primaryScreen()->availableGeometry().center() - QPoint(100, 100)); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); QTest::keyPress(w.windowHandle(), Qt::Key_A); QCoreApplication::processEvents(); @@ -1350,10 +1350,10 @@ void tst_QShortcut::keys() QCOMPARE(QApplication::focusWidget(), &le); QTest::keyEvent(QTest::Press, QApplication::focusWidget(), Qt::Key_Enter); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); QTest::keyEvent(QTest::Press, QApplication::focusWidget(), Qt::Key_Return); - QTRY_COMPARE(spy.count(), 2); + QTRY_COMPARE(spy.size(), 2); } QTEST_MAIN(tst_QShortcut) diff --git a/tests/auto/widgets/kernel/qsizepolicy/CMakeLists.txt b/tests/auto/widgets/kernel/qsizepolicy/CMakeLists.txt index 50ac18eb71..efdd72db73 100644 --- a/tests/auto/widgets/kernel/qsizepolicy/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qsizepolicy/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qsizepolicy.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qsizepolicy Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsizepolicy LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qsizepolicy SOURCES tst_qsizepolicy.cpp diff --git a/tests/auto/widgets/kernel/qsizepolicy/tst_qsizepolicy.cpp b/tests/auto/widgets/kernel/qsizepolicy/tst_qsizepolicy.cpp index 5b64f122e2..19d267f7e5 100644 --- a/tests/auto/widgets/kernel/qsizepolicy/tst_qsizepolicy.cpp +++ b/tests/auto/widgets/kernel/qsizepolicy/tst_qsizepolicy.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qsizepolicy.h> @@ -95,7 +95,7 @@ void tst_QSizePolicy::constExpr() { // QTBUG-69983: For ControlType != QSizePolicy::DefaultType, qCountTrailingZeroBits() // is used, which MSVC 15.8.1 does not consider constexpr due to built-ins -# if defined(QT_HAS_CONSTEXPR_BUILTINS) && (!defined(Q_CC_MSVC) || _MSC_VER < 1915) +# if defined(QT_HAS_CONSTEXPR_BITOPS) constexpr auto sp = QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed, QSizePolicy::CheckBox); # else constexpr auto sp = QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding, QSizePolicy::DefaultType); diff --git a/tests/auto/widgets/kernel/qstackedlayout/CMakeLists.txt b/tests/auto/widgets/kernel/qstackedlayout/CMakeLists.txt index 6dfcc77bc3..5701f455b5 100644 --- a/tests/auto/widgets/kernel/qstackedlayout/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qstackedlayout/CMakeLists.txt @@ -1,16 +1,21 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qstackedlayout.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qstackedlayout Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qstackedlayout LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qstackedlayout SOURCES tst_qstackedlayout.cpp LIBRARIES Qt::Gui Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp b/tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp index 06e97e69b6..c73b9725b2 100644 --- a/tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp +++ b/tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -11,6 +11,8 @@ #include <QPushButton> #include <QSignalSpy> +#include <QtWidgets/private/qapplication_p.h> + class tst_QStackedLayout : public QObject { Q_OBJECT @@ -107,7 +109,7 @@ void tst_QStackedLayout::testCase() // One widget added to layout QWidget *w1 = new QWidget(testWidget); testLayout->addWidget(w1); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toInt(), 0); spy.clear(); QCOMPARE(testLayout->currentIndex(), 0); @@ -124,7 +126,7 @@ void tst_QStackedLayout::testCase() // Change the current index testLayout->setCurrentIndex(1); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toInt(), 1); spy.clear(); QCOMPARE(testLayout->currentIndex(), 1); @@ -138,7 +140,7 @@ void tst_QStackedLayout::testCase() // Second widget removed from layout; back to nothing testLayout->removeWidget(w2); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toInt(), -1); spy.clear(); QCOMPARE(testLayout->currentIndex(), -1); @@ -287,7 +289,6 @@ void tst_QStackedLayout::keepFocusAfterSetCurrent() stackLayout->setCurrentIndex(0); testWidget->show(); - QApplication::setActiveWindow(testWidget); QVERIFY(QTest::qWaitForWindowActive(testWidget)); edit1->setFocus(); diff --git a/tests/auto/widgets/kernel/qtooltip/CMakeLists.txt b/tests/auto/widgets/kernel/qtooltip/CMakeLists.txt index 18040085af..af2de80e24 100644 --- a/tests/auto/widgets/kernel/qtooltip/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qtooltip/CMakeLists.txt @@ -1,16 +1,21 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qtooltip.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtooltip Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtooltip LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtooltip SOURCES tst_qtooltip.cpp LIBRARIES Qt::Gui Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp index f1532ae3ac..bc0624c9ab 100644 --- a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp +++ b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -11,6 +11,8 @@ #include <qwhatsthis.h> #include <qscreen.h> +#include <QtWidgets/private/qapplication_p.h> + class tst_QToolTip : public QObject { Q_OBJECT @@ -24,6 +26,7 @@ private slots: void setPalette(); void qtbug64550_stylesheet(); void dontCrashOutsideScreenGeometry(); + void marginSetWithStyleSheet(); }; void tst_QToolTip::init() @@ -95,7 +98,6 @@ void tst_QToolTip::keyEvent() widget.setWindowTitle(QLatin1String(QTest::currentTestFunction()) + QLatin1Char(' ') + QLatin1String(QTest::currentDataTag())); widget.show(); - QApplication::setActiveWindow(&widget); QVERIFY(QTest::qWaitForWindowActive(&widget)); widget.showDelayedToolTip(100); @@ -115,7 +117,8 @@ void tst_QToolTip::keyEvent() static QWidget *findWhatsThat() { - foreach (QWidget *widget, QApplication::topLevelWidgets()) { + const auto widgets = QApplication::topLevelWidgets(); + for (QWidget *widget : widgets) { if (widget->inherits("QWhatsThat")) return widget; } @@ -189,7 +192,6 @@ void tst_QToolTip::qtbug64550_stylesheet() Widget widget; widget.setStyleSheet(QStringLiteral("* { font-size: 48pt; }\n")); widget.show(); - QApplication::setActiveWindow(&widget); QVERIFY(QTest::qWaitForWindowActive(&widget)); widget.showDelayedToolTip(100); @@ -211,5 +213,30 @@ void tst_QToolTip::dontCrashOutsideScreenGeometry() { QToolTip::hideText(); } +void tst_QToolTip::marginSetWithStyleSheet() +{ + const char *toolTipText = "Test Tool Tip"; + + qApp->setStyleSheet("QToolTip {font-size: 8px; margin: 5px;}"); + QToolTip::showText(QGuiApplication::primaryScreen()->availableGeometry().topLeft(), toolTipText); + QTRY_VERIFY(QToolTip::isVisible()); + QWidget *toolTip = findToolTip(); + QVERIFY(toolTip); + QTRY_VERIFY(toolTip->isVisible()); + int toolTipHeight = toolTip->size().height(); + qApp->setStyleSheet(QString()); + QToolTip::hideText(); + + qApp->setStyleSheet("QToolTip {font-size: 8px; margin: 10px;}"); + QToolTip::showText(QGuiApplication::primaryScreen()->availableGeometry().topLeft(), toolTipText); + QTRY_VERIFY(QToolTip::isVisible()); + toolTip = findToolTip(); + QVERIFY(toolTip); + QTRY_VERIFY(toolTip->isVisible()); + QCOMPARE_LE(toolTip->size().height(), toolTipHeight + 10); + qApp->setStyleSheet(QString()); + QToolTip::hideText(); +} + QTEST_MAIN(tst_QToolTip) #include "tst_qtooltip.moc" diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST index 24387635b4..4c17af245b 100644 --- a/tests/auto/widgets/kernel/qwidget/BLACKLIST +++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST @@ -1,31 +1,12 @@ -# OSX QTBUG-25300 QTBUG-45502 -[normalGeometry] -ubuntu-16.04 -[restoreVersion1Geometry] -ubuntu-16.04 -[focusProxyAndInputMethods] -rhel-7.6 -centos -opensuse-leap -ubuntu [raise] opensuse-leap -# QTBUG-68175 -opensuse-42.3 -[renderInvisible] -macos -[optimizedResizeMove] -osx [optimizedResize_topLevel] osx [render_windowOpacity] macos arm [render_systemClip] osx -[moveInResizeEvent] -ubuntu-16.04 [multipleToplevelFocusCheck] -rhel-7.6 centos opensuse-leap ubuntu @@ -33,6 +14,8 @@ sles-15 # QTBUG-87668 [showMinimizedKeepsFocus] android +macos-13 ci +macos-14 ci [normalGeometry] android [saveRestoreGeometry] @@ -59,3 +42,8 @@ android android [optimizedResize_topLevel] android +[hoverPosition] +macos-14 x86 +# QTBUG-124291 +[setParentChangesFocus:make dialog parentless, after] +android diff --git a/tests/auto/widgets/kernel/qwidget/CMakeLists.txt b/tests/auto/widgets/kernel/qwidget/CMakeLists.txt index d3668e1afa..f18bc98bb3 100644 --- a/tests/auto/widgets/kernel/qwidget/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qwidget/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qwidget.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qwidget Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qwidget LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Resources: set(qwidget_resource_files "geometry-fullscreen.dat" @@ -29,9 +33,6 @@ qt_internal_add_test(tst_qwidget BUILTIN_TESTDATA ) -#### Keys ignored in scope 1:.:.:qwidget.pro:<TRUE>: -# testcase.timeout = "600" - ## Scopes: ##################################################################### @@ -40,14 +41,6 @@ qt_internal_extend_target(tst_qwidget CONDITION AIX -fpermissive ) -qt_internal_extend_target(tst_qwidget CONDITION APPLE - SOURCES - tst_qwidget_mac_helpers.mm - LIBRARIES - ${FWAppKit} - ${FWSecurity} -) - qt_internal_extend_target(tst_qwidget CONDITION WIN32 LIBRARIES gdi32 diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index b43494ab54..666cb70da9 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "../../../shared/highdpi.h" @@ -13,6 +13,7 @@ #include <qlineedit.h> #include <qlistview.h> #include <qmessagebox.h> +#include <qmimedata.h> #include <qpainter.h> #include <qpoint.h> #include <qpushbutton.h> @@ -37,6 +38,7 @@ #include <QtGui/qbackingstore.h> #include <QtGui/qguiapplication.h> #include <QtGui/qpa/qplatformwindow.h> +#include <QtGui/qpa/qplatformdrag.h> #include <QtGui/qscreen.h> #include <qmenubar.h> #include <qcompleter.h> @@ -49,10 +51,7 @@ #include <QtGui/qwindow.h> #include <qtimer.h> #include <QtWidgets/QDoubleSpinBox> - -#if defined(Q_OS_MACOS) -#include "tst_qwidget_mac_helpers.h" // Abstract the ObjC stuff out so not everyone must run an ObjC++ compile. -#endif +#include <QtWidgets/QComboBox> #include <QtTest/QTest> #include <QtTest/private/qtesthelpers_p.h> @@ -123,6 +122,34 @@ static QByteArray msgComparisonFailed(T v1, const char *op, T v2) return s.toLocal8Bit(); } +template<class T> class EventSpy : public QObject +{ +public: + EventSpy(T *widget, QEvent::Type event) + : m_widget(widget), eventToSpy(event) + { + if (m_widget) + m_widget->installEventFilter(this); + } + + T *widget() const { return m_widget; } + int count() const { return m_count; } + void clear() { m_count = 0; } + +protected: + bool eventFilter(QObject *object, QEvent *event) override + { + if (event->type() == eventToSpy) + ++m_count; + return QObject::eventFilter(object, event); + } + +private: + T *m_widget; + const QEvent::Type eventToSpy; + int m_count = 0; +}; + Q_LOGGING_CATEGORY(lcTests, "qt.widgets.tests") class tst_QWidget : public QObject @@ -136,7 +163,9 @@ public: public slots: void initTestCase(); void cleanup(); + private slots: + void nativeWindowAttribute(); void addActionOverloads(); void getSetCheck(); void fontPropagation(); @@ -162,11 +191,15 @@ private slots: void mapFromAndTo(); void focusChainOnHide(); void focusChainOnReparent(); + void focusAbstraction(); void defaultTabOrder(); void reverseTabOrder(); void tabOrderWithProxy(); void tabOrderWithProxyDisabled(); + void tabOrderWithProxyOutOfOrder(); void tabOrderWithCompoundWidgets(); + void tabOrderWithCompoundWidgetsInflection_data(); + void tabOrderWithCompoundWidgetsInflection(); void tabOrderWithCompoundWidgetsNoFocusPolicy(); void tabOrderNoChange(); void tabOrderNoChange2(); @@ -174,6 +207,9 @@ private slots: void appFocusWidgetWhenLosingFocusProxy(); void explicitTabOrderWithComplexWidget(); void explicitTabOrderWithSpinBox_QTBUG81097(); + void tabOrderList(); + void tabOrderComboBox_data(); + void tabOrderComboBox(); #if defined(Q_OS_WIN) void activation(); #endif @@ -198,6 +234,8 @@ private slots: void saveRestoreGeometry(); void restoreVersion1Geometry_data(); void restoreVersion1Geometry(); + void restoreGeometryAfterScreenChange_data(); + void restoreGeometryAfterScreenChange(); void widgetAt(); #ifdef Q_OS_MACOS @@ -218,6 +256,7 @@ private slots: void ensureCreated(); void createAndDestroy(); + void eventsAndAttributesOnDestroy(); void winIdChangeEvent(); void persistentWinId(); void showNativeChild(); @@ -280,6 +319,7 @@ private slots: void renderTargetOffset(); void renderInvisible(); void renderWithPainter(); + void renderRTL(); void render_task188133(); void render_task211796(); void render_task217815(); @@ -345,6 +385,7 @@ private slots: void enterLeaveOnWindowShowHide_data(); void enterLeaveOnWindowShowHide(); void taskQTBUG_4055_sendSyntheticEnterLeave(); + void hoverPosition(); void underMouse(); void taskQTBUG_27643_enterEvents(); #endif @@ -368,7 +409,6 @@ private slots: void openModal_taskQTBUG_5804(); void focusProxy(); - void focusProxyAndInputMethods(); void imEnabledNotImplemented(); #ifdef QT_BUILD_INTERNAL @@ -428,6 +468,19 @@ private slots: void showFullscreenAndroid(); #endif + void setVisibleDuringDestruction(); + + void explicitShowHide(); + + void dragEnterLeaveSymmetry(); + + void reparentWindowHandles_data(); + void reparentWindowHandles(); + +#ifndef QT_NO_CONTEXTMENU + void contextMenuTrigger(); +#endif + private: const QString m_platform; QSize m_testWidgetSize; @@ -436,6 +489,16 @@ private: const bool m_windowsAnimationsEnabled; QPointingDevice *m_touchScreen; const int m_fuzz; + QPalette simplePalette(); + +private: + enum class ScreenPosition { + OffAbove, + OffLeft, + OffBelow, + OffRight, + Contained + }; }; // Testing get/set functions @@ -631,6 +694,10 @@ tst_QWidget::~tst_QWidget() void tst_QWidget::initTestCase() { +#ifdef Q_OS_ANDROID + if (QNativeInterface::QAndroidApplication::sdkVersion() == 33) + QSKIP("Is flaky on Android 13 / RHEL 8.6 and 8.8 (QTQAINFRA-5606)"); +#endif // Size of reference widget, 200 for < 2000, scale up for larger screens // to avoid Windows warnings about minimum size for decorated windows. int width = 200; @@ -663,6 +730,24 @@ struct ImplicitlyConvertibleTo { void testFunction0() {} void testFunction1(bool) {} +void tst_QWidget::nativeWindowAttribute() +{ + QWidget parent; + QWidget child(&parent); + + QCOMPARE(parent.windowHandle(), nullptr); + QCOMPARE(child.windowHandle(), nullptr); + + // Setting WA_NativeWindow should create window handle + parent.setAttribute(Qt::WA_NativeWindow); + QVERIFY(parent.windowHandle() != nullptr); + // But not its child's window handle + QCOMPARE(child.windowHandle(), nullptr); + // Until the child also gains WA_NativeWindow + child.setAttribute(Qt::WA_NativeWindow); + QVERIFY(child.windowHandle() != nullptr); +} + void tst_QWidget::addActionOverloads() { // almost exhaustive check of addAction() overloads: @@ -1817,6 +1902,7 @@ void tst_QWidget::focusChainOnReparent() } QWidget window2; + child22->setParent(child21); child2->setParent(&window2); QWidget *expectedNewChain[5] = {&window2, child2, child21, child22, &window2}; @@ -1857,8 +1943,6 @@ void tst_QWidget::focusChainOnHide() QWidget::setTabOrder(child, parent.data()); parent->show(); - QApplication::setActiveWindow(parent->window()); - child->activateWindow(); child->setFocus(); QTRY_VERIFY(child->hasFocus()); @@ -1899,8 +1983,11 @@ public: setObjectName(name); lineEdit1 = new QLineEdit; + lineEdit1->setObjectName(name + "/lineEdit1"); lineEdit2 = new QLineEdit; + lineEdit2->setObjectName(name + "/lineEdit2"); lineEdit3 = new QLineEdit; + lineEdit3->setObjectName(name + "/lineEdit3"); lineEdit3->setEnabled(false); QHBoxLayout* hbox = new QHBoxLayout(this); @@ -1915,6 +2002,112 @@ public: QLineEdit *lineEdit3; }; +static QList<QWidget *> getFocusChain(QWidget *start, bool bForward) +{ + QList<QWidget *> ret; + QWidget *cur = start; + // detect infinite loop + int count = 100; + auto loopGuard = qScopeGuard([]{ + QFAIL("Inifinite loop detected in focus chain"); + }); + do { + ret += cur; + cur = bForward ? cur->nextInFocusChain() : cur->previousInFocusChain(); + if (!--count) + return ret; + } while (cur != start); + loopGuard.dismiss(); + return ret; +} + +void tst_QWidget::focusAbstraction() +{ + QLoggingCategory::setFilterRules("qt.widgets.focus=true"); + QWidget *widget1 = new QWidget; + widget1->setObjectName("Widget 1"); + QWidget *widget2 = new QWidget; + widget2->setObjectName("Widget 2"); + QWidget *widget3 = new QWidget; + widget3->setObjectName("Widget 3"); + QWidgetPrivate *priv1 = QWidgetPrivate::get(widget1); + QWidgetPrivate *priv2 = QWidgetPrivate::get(widget2); + QWidgetPrivate *priv3 = QWidgetPrivate::get(widget3); + + // Verify initialization + QVERIFY(!priv1->isInFocusChain()); + QVERIFY(!priv2->isInFocusChain()); + QVERIFY(!priv3->isInFocusChain()); + + // Verify, that parenting builds a focus chain. + QWidget parent; + parent.setObjectName("Parent"); + widget1->setParent(&parent); + widget2->setParent(&parent); + widget3->setParent(&parent); + QVERIFY(priv1->isInFocusChain()); + QVERIFY(priv2->isInFocusChain()); + QVERIFY(priv3->isInFocusChain()); + QWidgetList expected{widget1, widget2, widget3, &parent}; + QCOMPARE(getFocusChain(widget1, true), expected); + + // Verify, that reparented focus children end up behind parent. + widget1->setParent(widget2); + priv2->insertIntoFocusChainAfter(widget3); + priv2->reparentFocusChildren(QWidgetPrivate::FocusDirection::Next); + expected = {widget1, &parent, widget3, widget2}; + QCOMPARE(getFocusChain(widget1, true), expected); + QVERIFY(priv1->isInFocusChain()); + QVERIFY(priv2->isInFocusChain()); + QVERIFY(priv3->isInFocusChain()); + + // Check removal + priv3->removeFromFocusChain(QWidgetPrivate::FocusChainRemovalRule::AssertConsistency); + expected.removeOne(widget3); + QCOMPARE(getFocusChain(widget1, true), expected); + QVERIFY(priv1->isInFocusChain()); + QVERIFY(priv2->isInFocusChain()); + QVERIFY(!priv3->isInFocusChain()); + + // Check insert + priv3->insertIntoFocusChain(QWidgetPrivate::FocusDirection::Previous, widget1); + expected = {widget3, widget1, &parent, widget2}; + QCOMPARE(getFocusChain(widget3, true), expected); + + // Verify, that take doesn't break + const QWidgetList taken = QWidgetPrivate::takeFromFocusChain(widget1, widget2); + QVERIFY(priv1->isFocusChainConsistent()); + expected = {widget1, &parent, widget2}; + QCOMPARE(taken, expected); + QVERIFY(priv1->isInFocusChain()); + QVERIFY(priv2->isInFocusChain()); + QVERIFY(!priv3->isInFocusChain()); + + // Verify insertion of multiple widgets + QWidgetPrivate::insertIntoFocusChain(taken, QWidgetPrivate::FocusDirection::Next, widget3); + expected = {widget3, widget1, &parent, widget2}; + QCOMPARE(getFocusChain(widget3, true), expected); + QVERIFY(priv1->isInFocusChain()); + QVERIFY(priv2->isInFocusChain()); + QVERIFY(priv2->isInFocusChain()); + + // Verify broken chain identification + // d'tor asserts chain consistency => repair before going out of scope + auto guard = qScopeGuard([priv2, widget3]{ priv2->focus_next = widget3; }); + + // Nullptr is not allowed + priv2->focus_next = nullptr; + QVERIFY(!priv1->isFocusChainConsistent()); + + // Chain looping back in the middle + priv2->focus_next = widget1; + QVERIFY(!priv1->isFocusChainConsistent()); + + // "last" element pointing to itself + priv2->focus_next = widget2; + QVERIFY(!priv1->isFocusChainConsistent()); +} + void tst_QWidget::defaultTabOrder() { if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) @@ -1938,7 +2131,6 @@ void tst_QWidget::defaultTabOrder() container.setWindowTitle(QLatin1String(QTest::currentTestFunction())); container.show(); container.activateWindow(); - QApplication::setActiveWindow(&container); QVERIFY(QTest::qWaitForWindowActive(&container)); QTRY_VERIFY(firstEdit->hasFocus()); @@ -1974,23 +2166,29 @@ void tst_QWidget::defaultTabOrder() void tst_QWidget::reverseTabOrder() { - if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + if (QGuiApplication::platformName().startsWith(QLatin1StringView("wayland"), Qt::CaseInsensitive)) QSKIP("Wayland: This fails. Figure out why."); const int compositeCount = 2; Container container; - container.setWindowTitle(QLatin1String(QTest::currentTestFunction())); + container.setObjectName(QLatin1StringView("Container")); + container.setWindowTitle(QLatin1StringView(QTest::currentTestFunction())); Composite* composite[compositeCount]; QLineEdit *firstEdit = new QLineEdit(); + firstEdit->setObjectName(QLatin1StringView("FirstEdit")); container.box->addWidget(firstEdit); + static constexpr QLatin1StringView comp("Composite-%1"); for (int i = 0; i < compositeCount; i++) { - composite[i] = new Composite(); + const QString name = QString(comp).arg(i); + composite[i] = new Composite(nullptr, name); + composite[i]->setObjectName(name); container.box->addWidget(composite[i]); } QLineEdit *lastEdit = new QLineEdit(); + lastEdit->setObjectName(QLatin1StringView("LastEdit")); container.box->addWidget(lastEdit); // Reverse tab order inside each composite @@ -1999,7 +2197,6 @@ void tst_QWidget::reverseTabOrder() container.show(); container.activateWindow(); - QApplication::setActiveWindow(&container); QVERIFY(QTest::qWaitForWindowActive(&container)); QTRY_VERIFY(firstEdit->hasFocus()); @@ -2034,6 +2231,139 @@ void tst_QWidget::reverseTabOrder() QVERIFY(firstEdit->hasFocus()); } +void tst_QWidget::tabOrderList() +{ + Composite c; + QCOMPARE(getFocusChain(&c, true), + QList<QWidget *>({&c, c.lineEdit1, c.lineEdit2, c.lineEdit3})); + QWidget::setTabOrder({c.lineEdit3, c.lineEdit2, c.lineEdit1}); + // not starting with 3 like one would maybe expect, but still 3, 2, 1 + QCOMPARE(getFocusChain(&c, true), + QList<QWidget *>({&c, c.lineEdit1, c.lineEdit3, c.lineEdit2})); +} + +void tst_QWidget::tabOrderComboBox_data() +{ + QTest::addColumn<const bool>("editableAtBeginning"); + QTest::addColumn<const QList<int>>("firstTabOrder"); + QTest::addColumn<const QList<int>>("secondTabOrder"); + + QTest::addRow("3 not editable") << false << QList<int>{2, 1, 0} << QList<int>{0, 1, 2}; + QTest::addRow("4 editable") << true << QList<int>{2, 1, 0, 3} << QList<int>{3, 0, 2, 1}; +} + +QWidgetList expectedFocusChain(const QList<QComboBox *> &boxes, const QList<int> &sequence) +{ + Q_ASSERT(boxes.count() == sequence.count()); + QWidgetList widgets; + for (int i : sequence) { + Q_ASSERT(i >= 0); + Q_ASSERT(i < boxes.count()); + QComboBox *box = boxes.at(i); + widgets.append(box); + if (box->lineEdit()) + widgets.append(box->lineEdit()); + } + + return widgets; +} + +QWidgetList realFocusChain(const QList<QComboBox *> &boxes, const QList<int> &sequence) +{ + const QWidgetList all = getFocusChain(boxes.at(sequence.at(0)), true); + QWidgetList chain; + // Filter everything with NoFocus + for (auto *widget : all) { + if (widget->focusPolicy() != Qt::NoFocus) + chain << widget; + } + return chain; +} + +void setTabOrder(const QList<QComboBox *> &boxes, const QList<int> &sequence) +{ + Q_ASSERT(boxes.count() == sequence.count()); + QWidget *previous = nullptr; + for (int i : sequence) { + Q_ASSERT(i >= 0); + Q_ASSERT(i < boxes.count()); + QWidget *box = boxes.at(i); + if (!previous) { + previous = box; + } else { + QWidget::setTabOrder(previous, box); + previous = box; + } + } +} + +void tst_QWidget::tabOrderComboBox() +{ + QFETCH(const bool, editableAtBeginning); + QFETCH(const QList<int>, firstTabOrder); + QFETCH(const QList<int>, secondTabOrder); + const int count = firstTabOrder.count(); + Q_ASSERT(count == secondTabOrder.count()); + Q_ASSERT(count > 1); + + QWidget w; + w.setObjectName("MainWidget"); + QVBoxLayout* layout = new QVBoxLayout(); + w.setLayout(layout); + + QList<QComboBox *> boxes; + for (int i = 0; i < count; ++i) { + auto box = new QComboBox; + box->setObjectName("ComboBox " + QString::number(i)); + if (editableAtBeginning) { + box->setEditable(true); + box->lineEdit()->setObjectName("LineEdit " + QString::number(i)); + } + boxes.append(box); + layout->addWidget(box); + } + layout->addStretch(); + +#define COMPARE(seq)\ + setTabOrder(boxes, seq);\ + QCOMPARE(realFocusChain(boxes, seq), expectedFocusChain(boxes, seq)) + + COMPARE(firstTabOrder); + + if (!editableAtBeginning) { + for (auto *box : boxes) + box->setEditable(box); + } + + COMPARE(secondTabOrder); + + // Remove the focus proxy of the first combobox's line edit. + QComboBox *box = boxes.at(0); + QLineEdit *lineEdit = box->lineEdit(); + const QWidget *prev = lineEdit->previousInFocusChain(); + const QWidget *next = lineEdit->nextInFocusChain(); + const QWidget *proxy = lineEdit->focusProxy(); + QCOMPARE(proxy, box); + lineEdit->setFocusProxy(nullptr); + QCOMPARE(lineEdit->focusProxy(), nullptr); + QCOMPARE(lineEdit->previousInFocusChain(), prev); + QCOMPARE(lineEdit->nextInFocusChain(), next); + + // Remove first item and check chain consistency + boxes.removeFirst(); + delete box; + + // Create new list with 0 removed and other indexes updated + QList<int> thirdTabOrder(secondTabOrder); + thirdTabOrder.removeIf([](int i){ return i == 0; }); + for (int &i : thirdTabOrder) + --i; + + COMPARE(thirdTabOrder); + +#undef COMPARE +} + void tst_QWidget::tabOrderWithProxy() { if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) @@ -2061,7 +2391,6 @@ void tst_QWidget::tabOrderWithProxy() container.show(); container.activateWindow(); - QApplication::setActiveWindow(&container); QVERIFY(QTest::qWaitForWindowActive(&container)); QTRY_VERIFY(firstEdit->hasFocus()); @@ -2095,6 +2424,13 @@ void tst_QWidget::tabOrderWithProxy() QVERIFY(firstEdit->hasFocus()); } +static QString focusWidgetName() +{ + return QApplication::focusWidget() != nullptr + ? QApplication::focusWidget()->objectName() + : QStringLiteral("No focus widget"); +} + void tst_QWidget::tabOrderWithProxyDisabled() { Container container; @@ -2122,28 +2458,45 @@ void tst_QWidget::tabOrderWithProxyDisabled() container.show(); container.activateWindow(); - QApplication::setActiveWindow(&container); if (!QTest::qWaitForWindowActive(&container)) QSKIP("Window failed to activate, skipping test"); QVERIFY2(lineEdit1.hasFocus(), - qPrintable(QApplication::focusWidget()->objectName())); + qPrintable(focusWidgetName())); container.tab(); QVERIFY2(!lineEdit2.hasFocus(), - qPrintable(QApplication::focusWidget()->objectName())); + qPrintable(focusWidgetName())); QVERIFY2(lineEdit3.hasFocus(), - qPrintable(QApplication::focusWidget()->objectName())); + qPrintable(focusWidgetName())); container.tab(); QVERIFY2(lineEdit1.hasFocus(), - qPrintable(QApplication::focusWidget()->objectName())); + qPrintable(focusWidgetName())); container.backTab(); QVERIFY2(lineEdit3.hasFocus(), - qPrintable(QApplication::focusWidget()->objectName())); + qPrintable(focusWidgetName())); container.backTab(); QVERIFY2(!lineEdit2.hasFocus(), - qPrintable(QApplication::focusWidget()->objectName())); + qPrintable(focusWidgetName())); QVERIFY2(lineEdit1.hasFocus(), - qPrintable(QApplication::focusWidget()->objectName())); + qPrintable(focusWidgetName())); +} + +//#define DEBUG_FOCUS_CHAIN +static void dumpFocusChain(QWidget *start, bool bForward, const char *desc = nullptr) +{ +#ifdef DEBUG_FOCUS_CHAIN + qDebug() << "Dump focus chain, start:" << start << "isForward:" << bForward << desc; + QWidget *cur = start; + do { + qDebug() << "-" << cur; + auto widgetPrivate = static_cast<QWidgetPrivate *>(qt_widget_private(cur)); + cur = bForward ? widgetPrivate->focus_next : widgetPrivate->focus_prev; + } while (cur != start); +#else + Q_UNUSED(start); + Q_UNUSED(bForward); + Q_UNUSED(desc); +#endif } void tst_QWidget::tabOrderWithCompoundWidgets() @@ -2186,7 +2539,6 @@ void tst_QWidget::tabOrderWithCompoundWidgets() container.show(); container.activateWindow(); - QApplication::setActiveWindow(&container); QVERIFY(QTest::qWaitForWindowActive(&container)); lastEdit->setFocus(); @@ -2237,34 +2589,180 @@ void tst_QWidget::tabOrderWithCompoundWidgets() QVERIFY(lastEdit->hasFocus()); } -static QList<QWidget *> getFocusChain(QWidget *start, bool bForward) +void tst_QWidget::tabOrderWithProxyOutOfOrder() { - QList<QWidget *> ret; - QWidget *cur = start; - do { - ret += cur; - auto widgetPrivate = static_cast<QWidgetPrivate *>(qt_widget_private(cur)); - cur = bForward ? widgetPrivate->focus_next : widgetPrivate->focus_prev; - } while (cur != start); - return ret; + Container container; + container.setWindowTitle(QLatin1String(QTest::currentTestFunction())); + container.setObjectName(QLatin1StringView("Container")); + + // important to create the widgets with parent so that they are + // added to the focus chain already now, and with the buttonBox + // before the outsideButton. + QWidget buttonBox(&container); + buttonBox.setObjectName(QLatin1StringView("buttonBox")); + QPushButton outsideButton(&container); + outsideButton.setObjectName(QLatin1StringView("outsideButton")); + + container.box->addWidget(&outsideButton); + container.box->addWidget(&buttonBox); + QCOMPARE(getFocusChain(&container, true), + QList<QWidget*>({&container, &buttonBox, &outsideButton})); + + // this now adds okButon and cancelButton to the focus chain, + // after the outsideButton - so the outsideButton is in between + // the buttonBox and the children of the buttonBox! + QPushButton okButton(&buttonBox); + okButton.setObjectName("okButton"); + QPushButton cancelButton(&buttonBox); + cancelButton.setObjectName("cancelButton"); + QCOMPARE(getFocusChain(&container, true), + QList<QWidget*>({&container, &buttonBox, &outsideButton, &okButton, &cancelButton})); + + // by setting the okButton as the focusProxy, the outsideButton becomes + // unreachable when navigating the focus chain as the buttonBox is in front + // of, and proxies to the okButton behind the outsideButton. setFocusProxy + // must fix that by moving the buttonBox in front of the first sibling of + // the proxy. + buttonBox.setFocusProxy(&okButton); + QCOMPARE(getFocusChain(&container, true), + QList<QWidget*>({&container, &outsideButton, &buttonBox, &okButton, &cancelButton})); + + container.show(); + container.activateWindow(); + if (!QTest::qWaitForWindowActive(&container)) + QSKIP("Window failed to activate, skipping test"); + + QCOMPARE(QApplication::focusWidget(), &outsideButton); + container.tab(); + QCOMPARE(QApplication::focusWidget(), &okButton); + container.tab(); + QCOMPARE(QApplication::focusWidget(), &cancelButton); + container.tab(); + QCOMPARE(QApplication::focusWidget(), &outsideButton); + + container.backTab(); + QCOMPARE(QApplication::focusWidget(), &cancelButton); + container.backTab(); + QCOMPARE(QApplication::focusWidget(), &okButton); + container.backTab(); + QCOMPARE(QApplication::focusWidget(), &outsideButton); + container.backTab(); + QCOMPARE(QApplication::focusWidget(), &cancelButton); } -//#define DEBUG_FOCUS_CHAIN -static void dumpFocusChain(QWidget *start, bool bForward, const char *desc = nullptr) +static bool isFocusChainConsistent(QWidget *widget) { -#ifdef DEBUG_FOCUS_CHAIN - qDebug() << "Dump focus chain, start:" << start << "isForward:" << bForward << desc; - QWidget *cur = start; - do { - qDebug() << cur; - auto widgetPrivate = static_cast<QWidgetPrivate *>(qt_widget_private(cur)); - cur = bForward ? widgetPrivate->focus_next : widgetPrivate->focus_prev; - } while (cur != start); -#else - Q_UNUSED(start); - Q_UNUSED(bForward); - Q_UNUSED(desc); -#endif + auto forward = getFocusChain(widget, true); + auto backward = getFocusChain(widget, false); + auto logger = qScopeGuard([=]{ + qCritical("Focus chain is not consistent!"); + qWarning() << forward.size() << "forwards: " << forward; + qWarning() << backward.size() << "backwards:" << backward; + }); + // both lists start with the same, the widget + if (forward.takeFirst() != backward.takeFirst()) + return false; + const qsizetype chainLength = forward.size(); + if (backward.size() != chainLength) + return false; + for (qsizetype i = 0; i < chainLength; ++i) { + if (forward.at(i) != backward.at(chainLength - i - 1)) + return false; + } + logger.dismiss(); + return true; +} + +/* + This tests that we end up with consistent and complete chains when we set + the tab order from a widget (the lineEdit) inside a compound (the tabWidget) + to the compound, or visa versa. In that case, QWidget::setTabOrder will walk + the focus chain to the focus child inside the compound to replace the compound + itself when manipulating the tab order. If that last focus child is then + however also the lineEdit, then we must not create an inconsistent or + incomplete loop. + + The tabWidget is seen as a compound because QTabWidget sets the tab bar as + the focus proxy, and it has more widgets inside, like pages, toolbuttons etc. +*/ +void tst_QWidget::tabOrderWithCompoundWidgetsInflection_data() +{ + QTest::addColumn<QByteArrayList>("tabOrder"); + + QTest::addRow("forward") + << QByteArrayList{"dialog", "tabWidget", "lineEdit", "compound", "okButton", "cancelButton"}; + QTest::addRow("backward") + << QByteArrayList{"dialog", "cancelButton", "okButton", "compound", "lineEdit", "tabWidget"}; +} + +void tst_QWidget::tabOrderWithCompoundWidgetsInflection() +{ + QFETCH(const QByteArrayList, tabOrder); + + QDialog dialog; + dialog.setObjectName("dialog"); + QTabWidget *tabWidget = new QTabWidget; + tabWidget->setObjectName("tabWidget"); + tabWidget->setFocusPolicy(Qt::TabFocus); + QWidget *page = new QWidget; + page->setObjectName("page"); + QLineEdit *lineEdit = new QLineEdit; + lineEdit->setObjectName("lineEdit"); + QWidget *compound = new QWidget; + compound->setObjectName("compound"); + compound->setFocusPolicy(Qt::TabFocus); + QPushButton *okButton = new QPushButton("Ok"); + okButton->setObjectName("okButton"); + okButton->setFocusPolicy(Qt::TabFocus); + QPushButton *cancelButton = new QPushButton("Cancel"); + cancelButton->setObjectName("cancelButton"); + cancelButton->setFocusPolicy(Qt::TabFocus); + + QVBoxLayout *pageLayout = new QVBoxLayout; + pageLayout->addWidget(lineEdit); + page->setLayout(pageLayout); + tabWidget->addTab(page, "Tab"); + + QHBoxLayout *compoundLayout = new QHBoxLayout; + compoundLayout->addStretch(); + compoundLayout->addWidget(cancelButton); + compoundLayout->addWidget(okButton); + compound->setFocusProxy(okButton); + compound->setLayout(compoundLayout); + + QVBoxLayout *dialogLayout = new QVBoxLayout; + dialogLayout->addWidget(tabWidget); + dialogLayout->addWidget(compound); + dialog.setLayout(dialogLayout); + + QVERIFY(isFocusChainConsistent(&dialog)); + + QList<QWidget *> expectedFocusChain; + for (qsizetype i = 0; i < tabOrder.size() - 1; ++i) { + QWidget *first = dialog.findChild<QWidget *>(tabOrder.at(i)); + if (!first && tabOrder.at(i) == dialog.objectName()) + first = &dialog; + QVERIFY(first); + if (i == 0) + expectedFocusChain.append(first); + QWidget *second = dialog.findChild<QWidget *>(tabOrder.at(i + 1)); + QVERIFY(second); + expectedFocusChain.append(second); + QWidget::setTabOrder(first, second); + QVERIFY(isFocusChainConsistent(&dialog)); + } + + const auto forwardChain = getFocusChain(&dialog, true); + auto logger = qScopeGuard([=]{ + qCritical("Order of widgets in focus chain not matching:"); + qCritical() << " Actual :" << forwardChain; + qCritical() << " Expected:" << expectedFocusChain; + }); + for (qsizetype i = 0; i < expectedFocusChain.size() - 2; ++i) { + QCOMPARE_LT(forwardChain.indexOf(expectedFocusChain.at(i)), + forwardChain.indexOf(expectedFocusChain.at(i + 1))); + } + logger.dismiss(); } void tst_QWidget::tabOrderWithCompoundWidgetsNoFocusPolicy() @@ -2288,28 +2786,27 @@ void tst_QWidget::tabOrderWithCompoundWidgetsNoFocusPolicy() container.show(); container.activateWindow(); - QApplication::setActiveWindow(&container); if (!QTest::qWaitForWindowActive(&container)) QSKIP("Window failed to activate, skipping test"); QVERIFY2(spinbox1.hasFocus(), - qPrintable(QApplication::focusWidget()->objectName())); + qPrintable(focusWidgetName())); container.tab(); QVERIFY2(!spinbox2.hasFocus(), - qPrintable(QApplication::focusWidget()->objectName())); + qPrintable(focusWidgetName())); QVERIFY2(spinbox3.hasFocus(), - qPrintable(QApplication::focusWidget()->objectName())); + qPrintable(focusWidgetName())); container.tab(); QVERIFY2(spinbox1.hasFocus(), - qPrintable(QApplication::focusWidget()->objectName())); + qPrintable(focusWidgetName())); container.backTab(); QVERIFY2(spinbox3.hasFocus(), - qPrintable(QApplication::focusWidget()->objectName())); + qPrintable(focusWidgetName())); container.backTab(); QVERIFY2(!spinbox2.hasFocus(), - qPrintable(QApplication::focusWidget()->objectName())); + qPrintable(focusWidgetName())); QVERIFY2(spinbox1.hasFocus(), - qPrintable(QApplication::focusWidget()->objectName())); + qPrintable(focusWidgetName())); } void tst_QWidget::tabOrderNoChange() @@ -2394,7 +2891,6 @@ void tst_QWidget::appFocusWidgetWithFocusProxyLater() QLineEdit *lineEdit = new QLineEdit(&window); lineEdit->setFocus(); window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); QCOMPARE(QApplication::focusWidget(), lineEdit); @@ -2422,7 +2918,6 @@ void tst_QWidget::appFocusWidgetWhenLosingFocusProxy() lineEdit->setFocusProxy(lineEditFocusProxy); lineEdit->setFocus(); window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); QCOMPARE(QApplication::focusWidget(), lineEditFocusProxy); QVERIFY(lineEdit->hasFocus()); @@ -2449,7 +2944,6 @@ void tst_QWidget::explicitTabOrderWithComplexWidget() QWidget::setTabOrder(lineEditOne, lineEditTwo); lineEditOne->setFocus(); window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); QTRY_COMPARE(QApplication::focusWidget(), lineEditOne); @@ -2478,7 +2972,6 @@ void tst_QWidget::explicitTabOrderWithSpinBox_QTBUG81097() QWidget::setTabOrder(spinBoxTwo, lineEdit); spinBoxOne->setFocus(); window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); QTRY_COMPARE(QApplication::focusWidget(), spinBoxOne); @@ -2691,18 +3184,15 @@ void tst_QWidget::resizePropagation() QSKIP("resizePropagation test is designed for XCB only"); #endif - // Platform specific notes: - // Linux/XCB: - // - Unless maximized, a widget and its corresponding window can have different sizes - // - windowStateChanged can be fired multiple times (QTBUG-102478) when widget is maximized - // // Windows: // When a widget is maximized after it has been resized, the widget retains its original size, - // while the window shows maximum size + // while the window shows maximum size. + // windowStateChanged signal gets fired on a no-op change from/to WindowNoState // Initialize widget and signal spy for window handle QWidget widget; widget.showMaximized(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); QWindow *window = widget.windowHandle(); QTRY_VERIFY(window); QSignalSpy spy(window, &QWindow::windowStateChanged); @@ -2712,10 +3202,14 @@ void tst_QWidget::resizePropagation() const QSize size1 = QSize(screenSize.width() * 0.5, screenSize.height() * 0.5); const QSize size2 = QSize(screenSize.width() * 0.625, screenSize.height() * 0.833); - auto verifyResize = [&](const QSize &size, Qt::WindowState windowState, bool checkCountIncrement, bool checkTargetSize) + enum CountIncrementCheck {Equal, Greater}; + enum TargetSizeCheck {Fail, Warn}; + auto verifyResize = [&](const QSize &size, Qt::WindowState windowState, + CountIncrementCheck checkCountIncrement, + TargetSizeCheck checkTargetSize) { // Capture count of latest async signals - if (!checkCountIncrement) + if (checkCountIncrement == Equal) count = spy.count(); // Resize if required @@ -2726,13 +3220,24 @@ void tst_QWidget::resizePropagation() QVERIFY(QTest::qWaitForWindowExposed(&widget)); // Check signal count and qDebug output for fail analysis - if (checkCountIncrement) { - QTRY_VERIFY(spy.count() > count); - qDebug() << "spy count:" << spy.count() << "previous count:" << count; - count = spy.count(); - } else { - qDebug() << spy << widget.windowState() << window->windowState(); - QCOMPARE(spy.count(), count); + switch (checkCountIncrement) { + case Greater: { + auto logger = qScopeGuard([&](){ + qDebug() << "spy count:" << spy.count() << "previous count:" << count; + }); + QTRY_VERIFY(spy.count() > count); + logger.dismiss(); + count = spy.count(); + } + break; + case Equal: { + auto logger = qScopeGuard([&](){ + qDebug() << spy << widget.windowState() << window->windowState(); + }); + QCOMPARE(spy.count(), count); + logger.dismiss(); + } + break; } // QTRY necessary because state changes are propagated async @@ -2740,32 +3245,37 @@ void tst_QWidget::resizePropagation() QTRY_COMPARE(window->windowState(), windowState); // Check target size with fail or warning - if (checkTargetSize) { + switch (checkTargetSize) { + case Fail: QCOMPARE(widget.size(), window->size()); - } else if (widget.size() != window->size()) { - qWarning() << m_platform << "size mismtach tolerated. Widget:" - << widget.size() << "Window:" << window->size(); + break; + case Warn: + if (widget.size() != window->size()) { + qWarning() << m_platform << "size mismtach tolerated. Widget:" + << widget.size() << "Window:" << window->size(); + } + break; } }; // test state and size consistency of maximized window - verifyResize(QSize(), Qt::WindowMaximized, true, true); + verifyResize(QSize(), Qt::WindowMaximized, Equal, Fail); if (QTest::currentTestFailed()) return; // test state transition, state and size consistency after resize - verifyResize(size1, Qt::WindowNoState, true, !xcb ); + verifyResize(size1, Qt::WindowNoState, Greater, xcb ? Warn : Fail ); if (QTest::currentTestFailed()) return; // test unchanged state, state and size consistency after resize - verifyResize(size2, Qt::WindowNoState, false, !xcb); + verifyResize(size2, Qt::WindowNoState, Equal, xcb ? Warn : Fail); if (QTest::currentTestFailed()) return; // test state transition, state and size consistency after maximize widget.showMaximized(); - verifyResize(QSize(), Qt::WindowMaximized, true, xcb); + verifyResize(QSize(), Qt::WindowMaximized, Greater, xcb ? Fail : Warn); if (QTest::currentTestFailed()) return; @@ -3065,7 +3575,7 @@ void tst_QWidget::showMinimizedKeepsFocus() child1.setFocusPolicy(Qt::StrongFocus); child2.setFocusPolicy(Qt::StrongFocus); window.show(); - QApplication::setActiveWindow(&window); + QApplicationPrivate::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); child2.setFocus(); @@ -3089,7 +3599,6 @@ void tst_QWidget::showMinimizedKeepsFocus() QWidget *child = new QWidget(&window); child->setFocusPolicy(Qt::StrongFocus); window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); child->setFocus(); QTRY_COMPARE(window.focusWidget(), child); @@ -3108,7 +3617,6 @@ void tst_QWidget::showMinimizedKeepsFocus() QWidget *child = new QWidget(&window); child->setFocusPolicy(Qt::StrongFocus); window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); child->setFocus(); QTRY_COMPARE(window.focusWidget(), child); @@ -3128,7 +3636,6 @@ void tst_QWidget::showMinimizedKeepsFocus() QWidget *child = new QWidget(&window); child->setFocusPolicy(Qt::StrongFocus); window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); child->setFocus(); QTRY_COMPARE(window.focusWidget(), child); @@ -3149,7 +3656,6 @@ void tst_QWidget::showMinimizedKeepsFocus() QWidget *child = new QWidget(&window); child->setFocusPolicy(Qt::StrongFocus); window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); child->setFocus(); QTRY_COMPARE(window.focusWidget(), child); @@ -3166,7 +3672,6 @@ void tst_QWidget::showMinimizedKeepsFocus() QTRY_COMPARE(QApplication::focusWidget(), nullptr); window.showNormal(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); #ifdef Q_OS_MACOS if (!macHasAccessToWindowsServer()) @@ -3231,7 +3736,7 @@ void tst_QWidget::reparent() void tst_QWidget::setScreen() { const auto screens = QApplication::screens(); - if (screens.count() < 2) + if (screens.size() < 2) QSKIP("This test tests nothing on a machine with a single screen."); QScreen *screen0 = screens.at(0); @@ -3625,9 +4130,9 @@ void tst_QWidget::raise() QObjectList list1{child1, child2, child3, child4}; QCOMPARE(parentPtr->children(), list1); - QCOMPARE(allChildren.count(), list1.count()); + QCOMPARE(allChildren.size(), list1.size()); - for (UpdateWidget *child : qAsConst(allChildren)) { + for (UpdateWidget *child : std::as_const(allChildren)) { int expectedPaintEvents = child == child4 ? 1 : 0; if (expectedPaintEvents == 0) { QCOMPARE(child->numPaintEvents, 0); @@ -3641,9 +4146,10 @@ void tst_QWidget::raise() for (int i = 0; i < 5; ++i) child2->raise(); - QTest::qWait(50); + QVERIFY(QTest::qWaitForWindowExposed(child2)); + QApplication::processEvents(); // process events that could be triggered by raise(); - for (UpdateWidget *child : qAsConst(allChildren)) { + for (UpdateWidget *child : std::as_const(allChildren)) { int expectedPaintEvents = child == child2 ? 1 : 0; int expectedZOrderChangeEvents = child == child2 ? 1 : 0; QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents); @@ -3670,15 +4176,17 @@ void tst_QWidget::raise() onTop->show(); QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); QTRY_VERIFY(onTop->numPaintEvents > 0); + QApplication::processEvents(); // process remaining paint events if there's more than one onTop->reset(); // Reset all the children. - for (UpdateWidget *child : qAsConst(allChildren)) + for (UpdateWidget *child : std::as_const(allChildren)) child->reset(); for (int i = 0; i < 5; ++i) child3->raise(); - QTest::qWait(50); + QVERIFY(QTest::qWaitForWindowExposed(child3)); + QApplication::processEvents(); // process events that could be triggered by raise(); QCOMPARE(onTop->numPaintEvents, 0); QCOMPARE(onTop->numZOrderChangeEvents, 0); @@ -3686,7 +4194,7 @@ void tst_QWidget::raise() QObjectList list3{child1, child4, child2, child3}; QCOMPARE(parent->children(), list3); - for (UpdateWidget *child : qAsConst(allChildren)) { + for (UpdateWidget *child : std::as_const(allChildren)) { int expectedPaintEvents = 0; int expectedZOrderChangeEvents = child == child3 ? 1 : 0; QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents); @@ -3724,9 +4232,9 @@ void tst_QWidget::lower() QObjectList list1{child1, child2, child3, child4}; QCOMPARE(parent->children(), list1); - QCOMPARE(allChildren.count(), list1.count()); + QCOMPARE(allChildren.size(), list1.size()); - for (UpdateWidget *child : qAsConst(allChildren)) { + for (UpdateWidget *child : std::as_const(allChildren)) { int expectedPaintEvents = child == child4 ? 1 : 0; if (expectedPaintEvents == 0) { QCOMPARE(child->numPaintEvents, 0); @@ -3743,7 +4251,7 @@ void tst_QWidget::lower() QTest::qWait(100); - for (UpdateWidget *child : qAsConst(allChildren)) { + for (UpdateWidget *child : std::as_const(allChildren)) { int expectedPaintEvents = child == child3 ? 1 : 0; int expectedZOrderChangeEvents = child == child4 ? 1 : 0; QTRY_COMPARE(child->numZOrderChangeEvents, expectedZOrderChangeEvents); @@ -3789,7 +4297,7 @@ void tst_QWidget::stackUnder() QObjectList list1{child1, child2, child3, child4}; QCOMPARE(parent->children(), list1); - for (UpdateWidget *child : qAsConst(allChildren)) { + for (UpdateWidget *child : std::as_const(allChildren)) { int expectedPaintEvents = child == child4 ? 1 : 0; #if defined(Q_OS_WIN) || defined(Q_OS_MACOS) if (expectedPaintEvents == 1 && child->numPaintEvents == 2) @@ -3807,7 +4315,7 @@ void tst_QWidget::stackUnder() QObjectList list2{child1, child4, child2, child3}; QCOMPARE(parent->children(), list2); - for (UpdateWidget *child : qAsConst(allChildren)) { + for (UpdateWidget *child : std::as_const(allChildren)) { int expectedPaintEvents = child == child3 ? 1 : 0; int expectedZOrderChangeEvents = child == child4 ? 1 : 0; QTRY_COMPARE(child->numPaintEvents, expectedPaintEvents); @@ -3822,7 +4330,7 @@ void tst_QWidget::stackUnder() QObjectList list3{child4, child2, child1, child3}; QCOMPARE(parent->children(), list3); - for (UpdateWidget *child : qAsConst(allChildren)) { + for (UpdateWidget *child : std::as_const(allChildren)) { int expectedZOrderChangeEvents = child == child1 ? 1 : 0; if (child == child3) { #ifndef Q_OS_MACOS @@ -3944,6 +4452,13 @@ void tst_QWidget::saveRestoreGeometry() QVERIFY(QTest::qWaitForWindowExposed(&widget)); QApplication::processEvents(); + + /* --------------------------------------------------------------------- + * This test function is likely to flake when debugged with Qt Creator. + * (29px offset making the following QTRY_VERIFY2 fail) + * --------------------------------------------------------------------- + */ + QTRY_VERIFY2(HighDpi::fuzzyCompare(widget.pos(), position, m_fuzz), qPrintable(HighDpi::msgPointMismatch(widget.pos(), position))); QCOMPARE(widget.size(), size); @@ -4099,8 +4614,7 @@ void tst_QWidget::restoreVersion1Geometry() const Qt::WindowStates WindowStateMask = Qt::WindowFullScreen | Qt::WindowMaximized | Qt::WindowMinimized; QFile f(fileName); - QVERIFY(f.exists()); - f.open(QIODevice::ReadOnly); + QVERIFY(f.open(QIODevice::ReadOnly)); const QByteArray savedGeometry = f.readAll(); QCOMPARE(savedGeometry.size(), 46); f.close(); @@ -4156,6 +4670,68 @@ void tst_QWidget::restoreVersion1Geometry() #endif } +void tst_QWidget::restoreGeometryAfterScreenChange_data() +{ + QTest::addColumn<ScreenPosition>("screenPosition"); + QTest::addColumn<int>("deltaWidth"); + QTest::addColumn<int>("deltaHeight"); + QTest::addColumn<int>("frameMargin"); + QTest::addColumn<bool>("outside"); + + QTest::newRow("offAboveLarge") << ScreenPosition::OffAbove << 200 << 250 << 20 << true; + QTest::newRow("fitting") << ScreenPosition::Contained << 80 << 80 << 20 << false; + QTest::newRow("offRightWide") << ScreenPosition::OffRight << 150 << 80 << 20 << false; + QTest::newRow("offLeftFitting") << ScreenPosition::OffLeft << 70 << 70 << 20 << true; + QTest::newRow("offBelowHigh") << ScreenPosition::OffBelow << 80 << 200 << 20 << false; +} + +void tst_QWidget::restoreGeometryAfterScreenChange() +{ + const QList<QScreen *> &screens = QApplication::screens(); + QVERIFY2(!screens.isEmpty(), "No screens found."); + const QRect screenGeometry = screens.at(0)->geometry(); + + QFETCH(ScreenPosition, screenPosition); + QFETCH(int, deltaWidth); + QFETCH(int, deltaHeight); + QFETCH(int, frameMargin); + QFETCH(bool, outside); + + QRect restoredGeometry = screenGeometry; + restoredGeometry.setHeight(screenGeometry.height() * deltaHeight / 100); + restoredGeometry.setWidth(screenGeometry.width() * deltaWidth / 100); + const float moveMargin = outside ? 1.2 : 0.75; + + switch (screenPosition) { + case ScreenPosition::OffLeft: + restoredGeometry.setLeft(restoredGeometry.width() * (-moveMargin)); + break; + case ScreenPosition::OffAbove: + restoredGeometry.setTop(restoredGeometry.height() * (-moveMargin)); + break; + case ScreenPosition::OffRight: + restoredGeometry.setRight(restoredGeometry.width() * moveMargin); + break; + case ScreenPosition::OffBelow: + restoredGeometry.setBottom(restoredGeometry.height() * moveMargin); + break; + case ScreenPosition::Contained: + break; + } + + // If restored geometry fits into screen and has not been moved, + // it is changed only by frame margin plus one pixel at each edge + const QRect originalGeometry = restoredGeometry.adjusted(1, frameMargin + 1, 1, frameMargin + 1); + + QWidgetPrivate::checkRestoredGeometry(screenGeometry, &restoredGeometry, frameMargin); + + if (deltaHeight < 100 && deltaWidth < 100 && screenPosition == ScreenPosition::Contained) + QCOMPARE(originalGeometry, restoredGeometry); + + // new geometry has to fit on the screen + QVERIFY(screenGeometry.contains(restoredGeometry)); +} + void tst_QWidget::widgetAt() { #ifdef Q_OS_MACOS @@ -4421,22 +4997,20 @@ class StaticWidget : public QWidget Q_OBJECT public: bool partial = false; - bool gotPaintEvent = false; QRegion paintedRegion; - explicit StaticWidget(QWidget *parent = nullptr) : QWidget(parent) + explicit StaticWidget(const QPalette &palette, QWidget *parent = nullptr) : QWidget(parent) { setAttribute(Qt::WA_StaticContents); setAttribute(Qt::WA_OpaquePaintEvent); - setPalette(Qt::red); // Make sure we have an opaque palette. + setPalette(palette); setAutoFillBackground(true); } void paintEvent(QPaintEvent *e) override { paintedRegion += e->region(); - gotPaintEvent = true; -// qDebug() << "paint" << e->region(); + ++paintEvents; // Look for a full update, set partial to false if found. for (QRect r : e->region()) { partial = (r != rect()); @@ -4444,107 +5018,114 @@ public: break; } } + + // Wait timeout ms until at least one paint event has been consumed + // and the counter is no longer increasing. + // => making sure to consume multiple paint events relating to one operation + // before returning true. + bool waitForPaintEvent(int timeout = 100) + { + QDeadlineTimer deadline(timeout); + int count = -1; + while (!deadline.hasExpired() && count != paintEvents) { + count = paintEvents; + QCoreApplication::processEvents(); + if (count == paintEvents && count > 0) { + paintEvents = 0; + return true; + } + } + paintEvents = 0; + return false; + } +private: + int paintEvents = 0; }; /* Test that widget resizes and moves can be done with minimal repaints when WA_StaticContents - and WA_OpaquePaintEvent is set. Test is mac-only for now. + and WA_OpaquePaintEvent is set. */ void tst_QWidget::optimizedResizeMove() { - if (m_platform == QStringLiteral("wayland")) - QSKIP("Wayland: This fails. Figure out why."); + const bool wayland = QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive); + QWidget parent; - parent.setWindowTitle(QLatin1String(QTest::currentTestFunction())); + parent.setPalette(simplePalette()); + parent.setWindowTitle(QTest::currentTestFunction()); parent.resize(400, 400); - StaticWidget staticWidget(&parent); - staticWidget.gotPaintEvent = false; + StaticWidget staticWidget(simplePalette(), &parent); staticWidget.move(150, 150); staticWidget.resize(150, 150); parent.show(); QVERIFY(QTest::qWaitForWindowExposed(&parent)); - QTRY_VERIFY(staticWidget.gotPaintEvent); + QVERIFY(staticWidget.waitForPaintEvent()); - staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(10, 10)); - QTest::qWait(20); - QCOMPARE(staticWidget.gotPaintEvent, false); + if (!wayland) { + QVERIFY(!staticWidget.waitForPaintEvent()); + } else { + if (staticWidget.waitForPaintEvent()) + QSKIP("Wayland is not optimising paint events. Skipping test."); + } - staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(-10, -10)); - QTest::qWait(20); - QCOMPARE(staticWidget.gotPaintEvent, false); + QVERIFY(!staticWidget.waitForPaintEvent()); - staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(-10, 10)); - QTest::qWait(20); - QCOMPARE(staticWidget.gotPaintEvent, false); + QVERIFY(!staticWidget.waitForPaintEvent()); - staticWidget.gotPaintEvent = false; staticWidget.resize(staticWidget.size() + QSize(10, 10)); - QTRY_VERIFY(staticWidget.gotPaintEvent); + QVERIFY(staticWidget.waitForPaintEvent()); QCOMPARE(staticWidget.partial, true); - staticWidget.gotPaintEvent = false; staticWidget.resize(staticWidget.size() + QSize(-10, -10)); - QTest::qWait(20); - QCOMPARE(staticWidget.gotPaintEvent, false); + QVERIFY(!staticWidget.waitForPaintEvent()); - staticWidget.gotPaintEvent = false; staticWidget.resize(staticWidget.size() + QSize(10, -10)); - QTRY_VERIFY(staticWidget.gotPaintEvent); + QVERIFY(staticWidget.waitForPaintEvent()); QCOMPARE(staticWidget.partial, true); - staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(10, 10)); staticWidget.resize(staticWidget.size() + QSize(-10, -10)); - QTest::qWait(20); - QCOMPARE(staticWidget.gotPaintEvent, false); + QVERIFY(!staticWidget.waitForPaintEvent()); - staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(10, 10)); staticWidget.resize(staticWidget.size() + QSize(10, 10)); - QTRY_VERIFY(staticWidget.gotPaintEvent); + QVERIFY(staticWidget.waitForPaintEvent()); QCOMPARE(staticWidget.partial, true); - staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(-10, -10)); staticWidget.resize(staticWidget.size() + QSize(-10, -10)); - QTest::qWait(20); - QCOMPARE(staticWidget.gotPaintEvent, false); + QVERIFY(!staticWidget.waitForPaintEvent()); staticWidget.setAttribute(Qt::WA_StaticContents, false); - staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(-10, -10)); staticWidget.resize(staticWidget.size() + QSize(-10, -10)); - QTRY_VERIFY(staticWidget.gotPaintEvent); + QVERIFY(staticWidget.waitForPaintEvent()); QCOMPARE(staticWidget.partial, false); staticWidget.setAttribute(Qt::WA_StaticContents, true); staticWidget.setAttribute(Qt::WA_StaticContents, false); - staticWidget.gotPaintEvent = false; staticWidget.move(staticWidget.pos() + QPoint(10, 10)); - QTest::qWait(20); - QCOMPARE(staticWidget.gotPaintEvent, false); + QVERIFY(!staticWidget.waitForPaintEvent()); staticWidget.setAttribute(Qt::WA_StaticContents, true); } void tst_QWidget::optimizedResize_topLevel() { - if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) - QSKIP("Wayland: This fails. Figure out why."); + const bool wayland = QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive); if (QHighDpiScaling::isActive()) QSKIP("Skip due to rounding errors in the regions."); - StaticWidget topLevel; + StaticWidget topLevel(simplePalette()); + topLevel.setPalette(simplePalette()); topLevel.setWindowTitle(QLatin1String(QTest::currentTestFunction())); - topLevel.gotPaintEvent = false; topLevel.show(); QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); - QTRY_VERIFY(topLevel.gotPaintEvent); + QVERIFY(topLevel.waitForPaintEvent()); - topLevel.gotPaintEvent = false; topLevel.partial = false; topLevel.paintedRegion = QRegion(); @@ -4569,10 +5150,15 @@ void tst_QWidget::optimizedResize_topLevel() QRegion expectedUpdateRegion(topLevel.rect()); expectedUpdateRegion -= QRect(QPoint(), topLevel.size() - QSize(10, 10)); - QTRY_VERIFY(topLevel.gotPaintEvent); + QVERIFY(topLevel.waitForPaintEvent()); if (m_platform == QStringLiteral("xcb") || m_platform == QStringLiteral("offscreen")) QSKIP("QTBUG-26424"); - QCOMPARE(topLevel.partial, true); + if (!wayland) { + QCOMPARE(topLevel.partial, true); + } else { + if (!topLevel.partial) + QSKIP("Wayland does repaint partially. Skipping test."); + } QCOMPARE(topLevel.paintedRegion, expectedUpdateRegion); } @@ -4742,7 +5328,7 @@ protected: } public: QList<WId> m_winIdList; - int winIdChangeEventCount() const { return m_winIdList.count(); } + int winIdChangeEventCount() const { return m_winIdList.size(); } }; class CreateDestroyWidget : public WinIdChangeWidget @@ -4797,6 +5383,84 @@ void tst_QWidget::createAndDestroy() QVERIFY(widget.internalWinId()); } +void tst_QWidget::eventsAndAttributesOnDestroy() +{ + // The events and attributes when destroying a widget should + // include those of hiding the widget. + + CreateDestroyWidget widget; + EventSpy<QWidget> showEventSpy(&widget, QEvent::Show); + EventSpy<QWidget> hideEventSpy(&widget, QEvent::Hide); + + QCOMPARE(widget.testAttribute(Qt::WA_WState_Created), false); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), false); + QCOMPARE(widget.testAttribute(Qt::WA_Mapped), false); + + widget.show(); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Created), true); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), true); + QTRY_COMPARE(widget.testAttribute(Qt::WA_Mapped), true); + QCOMPARE(showEventSpy.count(), 1); + QCOMPARE(hideEventSpy.count(), 0); + + widget.hide(); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Created), true); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), false); + QCOMPARE(widget.testAttribute(Qt::WA_Mapped), false); + QCOMPARE(showEventSpy.count(), 1); + QCOMPARE(hideEventSpy.count(), 1); + + widget.show(); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Created), true); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), true); + QTRY_COMPARE(widget.testAttribute(Qt::WA_Mapped), true); + QCOMPARE(showEventSpy.count(), 2); + QCOMPARE(hideEventSpy.count(), 1); + + widget.destroy(); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Created), false); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), false); + QCOMPARE(widget.testAttribute(Qt::WA_Mapped), false); + QCOMPARE(showEventSpy.count(), 2); + QCOMPARE(hideEventSpy.count(), 2); + + const int hideEventsAfterDestroy = hideEventSpy.count(); + + widget.create(); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Created), true); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), false); + QCOMPARE(widget.testAttribute(Qt::WA_Mapped), false); + QCOMPARE(showEventSpy.count(), 2); + QCOMPARE(hideEventSpy.count(), hideEventsAfterDestroy); + + QWidgetPrivate::get(&widget)->setVisible(true); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Created), true); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), true); + QTRY_COMPARE(widget.testAttribute(Qt::WA_Mapped), true); + QCOMPARE(showEventSpy.count(), 3); + QCOMPARE(hideEventSpy.count(), hideEventsAfterDestroy); + + // Make sure the destroy that happens when a top level + // is moved to being a child does not prevent the child + // being shown again. + + QWidget parent; + QWidget child; + parent.show(); + QVERIFY(QTest::qWaitForWindowExposed(&parent)); + child.show(); + QVERIFY(QTest::qWaitForWindowExposed(&child)); + + child.setParent(&parent); + QCOMPARE(child.testAttribute(Qt::WA_WState_Created), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Visible), false); + + child.show(); + QCOMPARE(child.testAttribute(Qt::WA_WState_Created), true); + QCOMPARE(child.testAttribute(Qt::WA_WState_Visible), true); + QVERIFY(QTest::qWaitForWindowExposed(&child)); +} + void tst_QWidget::winIdChangeEvent() { { @@ -4964,24 +5628,29 @@ void tst_QWidget::closeAndShowWithNativeChild() QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); QWidget topLevel; + topLevel.setObjectName("TopLevel"); QWidget *nativeChild = new QWidget; + nativeChild->setObjectName("NativeChild"); nativeChild->setFixedSize(200, 200); - QWidget *nativeHiddenChild = new QWidget; - nativeHiddenChild->setFixedSize(200, 200); QWidget *normalChild = new QWidget; + normalChild->setObjectName("NormalChild"); normalChild->setFixedSize(200, 200); QHBoxLayout *layout = new QHBoxLayout; layout->addWidget(nativeChild); - layout->addWidget(nativeHiddenChild); layout->addWidget(normalChild); topLevel.setLayout(layout); - nativeHiddenChild->hide(); + nativeChild->setAttribute(Qt::WA_NativeWindow); + + QCOMPARE(normalChild->testAttribute(Qt::WA_WState_Hidden), false); + QCOMPARE(normalChild->testAttribute(Qt::WA_WState_ExplicitShowHide), false); + + QCOMPARE(nativeChild->testAttribute(Qt::WA_WState_Hidden), false); + QCOMPARE(nativeChild->testAttribute(Qt::WA_WState_ExplicitShowHide), false); topLevel.show(); QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); - nativeChild->winId(); const QSize originalSize = topLevel.size(); topLevel.close(); @@ -5149,6 +5818,7 @@ void tst_QWidget::update() Q_CHECK_PAINTEVENTS UpdateWidget w; + w.setPalette(simplePalette()); w.setWindowTitle(QLatin1String(QTest::currentTestFunction())); w.resize(100, 100); centerOnScreen(&w); @@ -5162,6 +5832,7 @@ void tst_QWidget::update() w.reset(); UpdateWidget child(&w); + child.setPalette(simplePalette()); child.setGeometry(10, 10, 80, 80); child.show(); @@ -5233,6 +5904,7 @@ void tst_QWidget::update() // overlapping sibling UpdateWidget sibling(&w); + sibling.setPalette(simplePalette()); child.setGeometry(10, 10, 20, 20); sibling.setGeometry(15, 15, 20, 20); sibling.show(); @@ -5312,9 +5984,11 @@ void tst_QWidget::isOpaque() { #ifndef Q_OS_MACOS QWidget w; + w.setPalette(simplePalette()); QVERIFY(::isOpaque(&w)); QWidget child(&w); + child.setPalette(simplePalette()); QVERIFY(!::isOpaque(&child)); child.setAutoFillBackground(true); @@ -5396,11 +6070,11 @@ void tst_QWidget::scroll() const int h = qMin(500, screen->availableGeometry().height() / 2); UpdateWidget updateWidget; + updateWidget.setPalette(simplePalette()); updateWidget.resize(w, h); updateWidget.reset(); updateWidget.move(m_availableTopLeft); updateWidget.showNormal(); - QApplication::setActiveWindow(&updateWidget); QVERIFY(QTest::qWaitForWindowActive(&updateWidget)); QVERIFY(updateWidget.numPaintEvents > 0); @@ -5514,7 +6188,7 @@ public: } QObjectCastChecker(QObjectCastChecker &&other) noexcept - : m_target(qExchange(other.m_target, nullptr)) + : m_target(std::exchange(other.m_target, nullptr)) {} QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QObjectCastChecker) @@ -5588,7 +6262,7 @@ void tst_QWidget::setWindowGeometry_data() const Qt::WindowFlags windowFlags[] = {Qt::WindowFlags(), Qt::FramelessWindowHint}; const bool skipEmptyRects = (m_platform == QStringLiteral("windows")); - for (Rects l : qAsConst(rects)) { + for (Rects l : std::as_const(rects)) { if (skipEmptyRects) l.removeIf([] (const QRect &r) { return r.isEmpty(); }); const QRect &rect = l.constFirst(); @@ -5607,8 +6281,8 @@ void tst_QWidget::setWindowGeometry_data() void tst_QWidget::setWindowGeometry() { - if (m_platform == QStringLiteral("xcb")) - QSKIP("X11: Skip this test due to Window manager positioning issues."); + if (m_platform == QStringLiteral("xcb") || m_platform.startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("X11/Wayland: Skip this test due to Window manager positioning issues."); QFETCH(Rects, rects); QFETCH(int, windowFlags); @@ -5625,7 +6299,7 @@ void tst_QWidget::setWindowGeometry() QCOMPARE(widget.geometry(), rect); // setGeometry() without showing - for (const QRect &r : qAsConst(rects)) { + for (const QRect &r : std::as_const(rects)) { widget.setGeometry(r); QTest::qWait(100); QCOMPARE(widget.geometry(), r); @@ -5651,7 +6325,7 @@ void tst_QWidget::setWindowGeometry() QTRY_COMPARE(widget.geometry(), rect); // setGeometry() while shown - for (const QRect &r : qAsConst(rects)) { + for (const QRect &r : std::as_const(rects)) { widget.setGeometry(r); QTest::qWait(10); QTRY_COMPARE(widget.geometry(), r); @@ -5666,7 +6340,7 @@ void tst_QWidget::setWindowGeometry() QTRY_COMPARE(widget.geometry(), rect); // setGeometry() after hide() - for (const QRect &r : qAsConst(rects)) { + for (const QRect &r : std::as_const(rects)) { widget.setGeometry(r); QTest::qWait(10); QTRY_COMPARE(widget.geometry(), r); @@ -5702,7 +6376,7 @@ void tst_QWidget::setWindowGeometry() QTRY_COMPARE(widget.geometry(), rect); // setGeometry() while shown - for (const QRect &r : qAsConst(rects)) { + for (const QRect &r : std::as_const(rects)) { widget.setGeometry(r); QTest::qWait(10); QTRY_COMPARE(widget.geometry(), r); @@ -5717,7 +6391,7 @@ void tst_QWidget::setWindowGeometry() QTRY_COMPARE(widget.geometry(), rect); // setGeometry() after hide() - for (const QRect &r : qAsConst(rects)) { + for (const QRect &r : std::as_const(rects)) { widget.setGeometry(r); QTest::qWait(10); QTRY_COMPARE(widget.geometry(), r); @@ -5796,7 +6470,7 @@ void tst_QWidget::windowMoveResize() QTRY_COMPARE(widget.size(), rect.size()); // move() without showing - for (const QRect &r : qAsConst(rects)) { + for (const QRect &r : std::as_const(rects)) { widget.move(r.topLeft()); widget.resize(r.size()); QApplication::processEvents(); @@ -5826,7 +6500,7 @@ void tst_QWidget::windowMoveResize() QTRY_COMPARE(widget.size(), rect.size()); // move() while shown - for (const QRect &r : qAsConst(rects)) { + for (const QRect &r : std::as_const(rects)) { // XCB: First resize after show of zero-sized gets wrong win_gravity. const bool expectMoveFail = !windowFlags && ((widget.width() == 0 || widget.height() == 0) && r.width() != 0 && r.height() != 0) @@ -5855,7 +6529,7 @@ void tst_QWidget::windowMoveResize() QTRY_COMPARE(widget.size(), rect.size()); // move() after hide() - for (const QRect &r : qAsConst(rects)) { + for (const QRect &r : std::as_const(rects)) { widget.move(r.topLeft()); widget.resize(r.size()); QApplication::processEvents(); @@ -5906,7 +6580,7 @@ void tst_QWidget::windowMoveResize() QTRY_COMPARE(widget.size(), rect.size()); // move() while shown - for (const QRect &r : qAsConst(rects)) { + for (const QRect &r : std::as_const(rects)) { widget.move(r.topLeft()); widget.resize(r.size()); QApplication::processEvents(); @@ -5926,7 +6600,7 @@ void tst_QWidget::windowMoveResize() QTRY_COMPARE(widget.size(), rect.size()); // move() after hide() - for (const QRect &r : qAsConst(rects)) { + for (const QRect &r : std::as_const(rects)) { widget.move(r.topLeft()); widget.resize(r.size()); QApplication::processEvents(); @@ -6133,6 +6807,9 @@ void tst_QWidget::moveChild() void tst_QWidget::showAndMoveChild() { +#ifdef ANDROID + QSKIP("Fails on Android due to removed grabWindow(): QTBUG-118849"); +#endif if (m_platform == QStringLiteral("wayland")) QSKIP("Wayland: This fails. Figure out why."); QWidget parent(nullptr, Qt::Window | Qt::WindowStaysOnTopHint); @@ -6150,7 +6827,6 @@ void tst_QWidget::showAndMoveChild() parent.setGeometry(desktopDimensions); parent.setPalette(Qt::red); parent.show(); - QApplication::setActiveWindow(&parent); QVERIFY(QTest::qWaitForWindowActive(&parent)); QWidget child(&parent); @@ -6269,17 +6945,17 @@ void tst_QWidget::multipleToplevelFocusCheck() w2.show(); QVERIFY(QTest::qWaitForWindowExposed(&w2)); - QApplication::setActiveWindow(&w1); w1.activateWindow(); + QApplicationPrivate::setActiveWindow(&w1); QVERIFY(QTest::qWaitForWindowActive(&w1)); - QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1)); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1)); QTest::mouseDClick(&w1, Qt::LeftButton); QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit)); w2.activateWindow(); - QApplication::setActiveWindow(&w2); + QApplicationPrivate::setActiveWindow(&w2); QVERIFY(QTest::qWaitForWindowActive(&w2)); - QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2)); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2)); QTest::mouseClick(&w2, Qt::LeftButton); QTRY_COMPARE(QApplication::focusWidget(), nullptr); @@ -6287,16 +6963,16 @@ void tst_QWidget::multipleToplevelFocusCheck() QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w2.edit)); w1.activateWindow(); - QApplication::setActiveWindow(&w1); + QApplicationPrivate::setActiveWindow(&w1); QVERIFY(QTest::qWaitForWindowActive(&w1)); - QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1)); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w1)); QTest::mouseDClick(&w1, Qt::LeftButton); QTRY_COMPARE(QApplication::focusWidget(), static_cast<QWidget *>(w1.edit)); w2.activateWindow(); - QApplication::setActiveWindow(&w2); + QApplicationPrivate::setActiveWindow(&w2); QVERIFY(QTest::qWaitForWindowActive(&w2)); - QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2)); + QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&w2)); QTest::mouseClick(&w2, Qt::LeftButton); QTRY_COMPARE(QApplication::focusWidget(), nullptr); } @@ -6359,7 +7035,7 @@ void tst_QWidget::setFocus() { // move focus to another window testWidget->activateWindow(); - QApplication::setActiveWindow(testWidget.data()); + QApplicationPrivate::setActiveWindow(testWidget.data()); if (testWidget->focusWidget()) testWidget->focusWidget()->clearFocus(); else @@ -6405,7 +7081,7 @@ void tst_QWidget::setFocus() // note: window may be active, but we don't want it to be testWidget->activateWindow(); - QApplication::setActiveWindow(testWidget.data()); + QApplicationPrivate::setActiveWindow(testWidget.data()); if (testWidget->focusWidget()) testWidget->focusWidget()->clearFocus(); else @@ -6581,34 +7257,6 @@ void tst_QWidget::setFocus() } } -template<class T> class EventSpy : public QObject -{ -public: - EventSpy(T *widget, QEvent::Type event) - : m_widget(widget), eventToSpy(event) - { - if (m_widget) - m_widget->installEventFilter(this); - } - - T *widget() const { return m_widget; } - int count() const { return m_count; } - void clear() { m_count = 0; } - -protected: - bool eventFilter(QObject *object, QEvent *event) override - { - if (event->type() == eventToSpy) - ++m_count; - return QObject::eventFilter(object, event); - } - -private: - T *m_widget; - const QEvent::Type eventToSpy; - int m_count = 0; -}; - #ifndef QT_NO_CURSOR void tst_QWidget::setCursor() { @@ -6812,7 +7460,7 @@ void tst_QWidget::testWindowIconChangeEventPropagation() QWidgetList widgets; widgets << &topLevelWidget << &topLevelChild << &dialog << &dialogChild; - QCOMPARE(widgets.count(), 4); + QCOMPARE(widgets.size(), 4); topLevelWidget.show(); dialog.show(); @@ -6826,13 +7474,13 @@ void tst_QWidget::testWindowIconChangeEventPropagation() // Create spy lists. QList <EventSpyPtr> applicationEventSpies; QList <EventSpyPtr> widgetEventSpies; - for (QWidget *widget : qAsConst(widgets)) { + for (QWidget *widget : std::as_const(widgets)) { applicationEventSpies.append(EventSpyPtr::create(widget, QEvent::ApplicationWindowIconChange)); widgetEventSpies.append(EventSpyPtr::create(widget, QEvent::WindowIconChange)); } QList <WindowEventSpyPtr> appWindowEventSpies; QList <WindowEventSpyPtr> windowEventSpies; - for (QWindow *window : qAsConst(windows)) { + for (QWindow *window : std::as_const(windows)) { appWindowEventSpies.append(WindowEventSpyPtr::create(window, QEvent::ApplicationWindowIconChange)); windowEventSpies.append(WindowEventSpyPtr::create(window, QEvent::WindowIconChange)); } @@ -6841,7 +7489,7 @@ void tst_QWidget::testWindowIconChangeEventPropagation() const QIcon windowIcon = qApp->style()->standardIcon(QStyle::SP_TitleBarMenuButton); qApp->setWindowIcon(windowIcon); - for (int i = 0; i < widgets.count(); ++i) { + for (int i = 0; i < widgets.size(); ++i) { // Check QEvent::ApplicationWindowIconChange EventSpyPtr spy = applicationEventSpies.at(i); QWidget *widget = spy->widget(); @@ -6858,7 +7506,7 @@ void tst_QWidget::testWindowIconChangeEventPropagation() QCOMPARE(spy->count(), 1); spy->clear(); } - for (int i = 0; i < windows.count(); ++i) { + for (int i = 0; i < windows.size(); ++i) { // Check QEvent::ApplicationWindowIconChange (sent to QWindow) // QWidgetWindows don't get this event, since the widget takes care of changing the icon WindowEventSpyPtr spy = appWindowEventSpies.at(i); @@ -6876,7 +7524,7 @@ void tst_QWidget::testWindowIconChangeEventPropagation() // Set icon on a top-level widget. topLevelWidget.setWindowIcon(QIcon()); - for (int i = 0; i < widgets.count(); ++i) { + for (int i = 0; i < widgets.size(); ++i) { // Check QEvent::ApplicationWindowIconChange EventSpyPtr spy = applicationEventSpies.at(i); QCOMPARE(spy->count(), 0); @@ -7033,7 +7681,6 @@ void tst_QWidget::clean_qt_x11_enforce_cursor() child->setAttribute(Qt::WA_SetCursor, true); window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); QTest::qWait(100); QCursor::setPos(window.geometry().center()); @@ -7410,6 +8057,9 @@ private: void tst_QWidget::render() { +#ifdef Q_OS_ANDROID + QSKIP("QTBUG-118984: crashes on Android."); +#endif QCalendarWidget source; source.setWindowTitle(QLatin1String(QTest::currentTestFunction())); // disable anti-aliasing to eliminate potential differences when subpixel antialiasing @@ -7466,7 +8116,8 @@ void tst_QWidget::renderChildFillsBackground() #ifndef Q_OS_ANDROID // On Android all widgets are shown maximized, so the pixmaps // will be similar - QEXPECT_FAIL("", "This test fails on all platforms", Continue); + if (!m_platform.startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QEXPECT_FAIL("", "This test fails on all platforms", Continue); #endif QCOMPARE(childPixmap, windowPixmap); } @@ -7501,15 +8152,12 @@ void tst_QWidget::renderTargetOffset() QCOMPARE(image.pixel(120, 120), QColor(Qt::blue).rgb()); } -// On Windows the active palette is used instead of the inactive palette even -// though the widget is invisible. This is probably related to task 178507/168682, -// but for the renderInvisible test it doesn't matter, we're mostly interested -// in testing the geometry so just workaround the palette issue for now. +// On some platforms the active palette is used instead of the inactive palette even +// though the widget is invisible, but for the renderInvisible test it doesn't matter, +// as we're mostly interested in testing the geometry, so just workaround the palette +// issue for now. static void workaroundPaletteIssue(QWidget *widget) { -#ifndef Q_OS_WIN - return; -#endif if (!widget) return; @@ -7530,6 +8178,9 @@ void tst_QWidget::renderInvisible() if (m_platform == QStringLiteral("xcb")) QSKIP("QTBUG-26424"); + if (m_platform.startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Wayland: Skip this test, see also QTBUG-107157"); + QScopedPointer<QCalendarWidget> calendar(new QCalendarWidget); calendar->move(m_availableTopLeft + QPoint(100, 100)); calendar->setWindowTitle(QLatin1String(QTest::currentTestFunction())); @@ -7550,7 +8201,7 @@ void tst_QWidget::renderInvisible() // Create normal reference image. const QSize calendarSize = calendar->size(); - QImage referenceImage(calendarSize, QImage::Format_ARGB32); + QImage referenceImage(calendarSize, QImage::Format_ARGB32_Premultiplied); calendar->render(&referenceImage); #ifdef RENDER_DEBUG referenceImage.save("referenceImage.png"); @@ -7561,7 +8212,7 @@ void tst_QWidget::renderInvisible() const QSize calendarSizeResized = calendar->size() + QSize(50, 50); calendar->resize(calendarSizeResized); QTest::qWait(30); - QImage referenceImageResized(calendarSizeResized, QImage::Format_ARGB32); + QImage referenceImageResized(calendarSizeResized, QImage::Format_ARGB32_Premultiplied); calendar->render(&referenceImageResized); #ifdef RENDER_DEBUG referenceImageResized.save("referenceImageResized.png"); @@ -7574,7 +8225,7 @@ void tst_QWidget::renderInvisible() workaroundPaletteIssue(calendar.data()); { // Make sure we get the same image when the calendar is explicitly hidden. - QImage testImage(calendarSizeResized, QImage::Format_ARGB32); + QImage testImage(calendarSizeResized, QImage::Format_ARGB32_Premultiplied); calendar->render(&testImage); #ifdef RENDER_DEBUG testImage.save("explicitlyHiddenCalendarResized.png"); @@ -7590,7 +8241,7 @@ void tst_QWidget::renderInvisible() workaroundPaletteIssue(calendar.data()); { // Never been visible, created or laid out. - QImage testImage(calendarSize, QImage::Format_ARGB32); + QImage testImage(calendarSize, QImage::Format_ARGB32_Premultiplied); calendar->render(&testImage); #ifdef RENDER_DEBUG testImage.save("neverBeenVisibleCreatedOrLaidOut.png"); @@ -7602,7 +8253,7 @@ void tst_QWidget::renderInvisible() QTest::qWait(30); { // Calendar explicitly hidden. - QImage testImage(calendarSize, QImage::Format_ARGB32); + QImage testImage(calendarSize, QImage::Format_ARGB32_Premultiplied); calendar->render(&testImage); #ifdef RENDER_DEBUG testImage.save("explicitlyHiddenCalendar.png"); @@ -7616,7 +8267,7 @@ void tst_QWidget::renderInvisible() navigationBar->hide(); { // Check that the navigation bar isn't drawn when rendering the entire calendar. - QImage testImage(calendarSize, QImage::Format_ARGB32); + QImage testImage(calendarSize, QImage::Format_ARGB32_Premultiplied); calendar->render(&testImage); #ifdef RENDER_DEBUG testImage.save("calendarWithoutNavigationBar.png"); @@ -7625,7 +8276,7 @@ void tst_QWidget::renderInvisible() } { // Make sure the navigation bar renders correctly even though it's hidden. - QImage testImage(navigationBar->size(), QImage::Format_ARGB32); + QImage testImage(navigationBar->size(), QImage::Format_ARGB32_Premultiplied); navigationBar->render(&testImage); #ifdef RENDER_DEBUG testImage.save("explicitlyHiddenNavigationBar.png"); @@ -7639,7 +8290,7 @@ void tst_QWidget::renderInvisible() { // Render next month button. // Fill test image with correct background color. - QImage testImage(nextMonthButton->size(), QImage::Format_ARGB32); + QImage testImage(nextMonthButton->size(), QImage::Format_ARGB32_Premultiplied); navigationBar->render(&testImage, QPoint(), QRegion(), QWidget::RenderFlags()); #ifdef RENDER_DEBUG testImage.save("nextMonthButtonBackground.png"); @@ -7677,7 +8328,7 @@ void tst_QWidget::renderInvisible() QCoreApplication::processEvents(); { // Make sure we get an image equal to the resized reference image. - QImage testImage(calendarSizeResized, QImage::Format_ARGB32); + QImage testImage(calendarSizeResized, QImage::Format_ARGB32_Premultiplied); calendar->render(&testImage); #ifdef RENDER_DEBUG testImage.save("calendarResized.png"); @@ -7689,7 +8340,7 @@ void tst_QWidget::renderInvisible() QCalendarWidget calendar; const QSize calendarSize = calendar.sizeHint(); - QImage image(2 * calendarSize, QImage::Format_ARGB32); + QImage image(2 * calendarSize, QImage::Format_ARGB32_Premultiplied); image.fill(QColor(Qt::red).rgb()); calendar.render(&image); @@ -7829,6 +8480,47 @@ void tst_QWidget::renderWithPainter() QCOMPARE(painter.renderHints(), oldRenderHints); } +void tst_QWidget::renderRTL() +{ + QFont f; + f.setStyleStrategy(QFont::NoAntialias); + const QScopedPointer<QStyle> style(QStyleFactory::create(QLatin1String("Windows"))); + + QMenu menu; + menu.setMinimumWidth(200); + menu.setFont(f); + menu.setStyle(style.data()); + menu.addAction("I"); + menu.show(); + menu.setLayoutDirection(Qt::LeftToRight); + QVERIFY(QTest::qWaitForWindowExposed(&menu)); + + QImage imageLTR(menu.size(), QImage::Format_ARGB32); + menu.render(&imageLTR); + //imageLTR.save("/tmp/rendered_1.png"); + + menu.setLayoutDirection(Qt::RightToLeft); + QImage imageRTL(menu.size(), QImage::Format_ARGB32); + menu.render(&imageRTL); + imageRTL = imageRTL.mirrored(true, false); + //imageRTL.save("/tmp/rendered_2.png"); + + QCOMPARE(imageLTR.height(), imageRTL.height()); + QCOMPARE(imageLTR.width(), imageRTL.width()); + static constexpr auto border = 4; + for (int h = border; h < imageRTL.height() - border; ++h) { + // there should be no difference on the right (aka no text) + for (int w = imageRTL.width() / 2; w < imageRTL.width() - border; ++w) { + auto pixLTR = imageLTR.pixel(w, h); + auto pixRTL = imageRTL.pixel(w, h); + if (pixLTR != pixRTL) + qDebug() << "Pixel do not match at" << w << h << ":" + << Qt::hex << pixLTR << "<->" << pixRTL; + QCOMPARE(pixLTR, pixRTL); + } + } +} + void tst_QWidget::render_task188133() { QMainWindow mainWindow; @@ -8493,6 +9185,7 @@ void tst_QWidget::updateWhileMinimized() QSKIP("Platform does not support showMinimized()"); #endif UpdateWidget widget; + widget.setPalette(simplePalette()); widget.setWindowTitle(QLatin1String(QTest::currentTestFunction())); // Filter out activation change and focus events to avoid update() calls in QWidget. widget.updateOnActivationChangeAndFocusIn = false; @@ -9066,6 +9759,7 @@ void tst_QWidget::doubleRepaint() QSKIP("Not having window server access causes the wrong number of repaints to be issues"); #endif UpdateWidget widget; + widget.setPalette(simplePalette()); widget.setWindowTitle(QLatin1String(QTest::currentTestFunction())); centerOnScreen(&widget); widget.setFocusPolicy(Qt::StrongFocus); @@ -9097,9 +9791,10 @@ void tst_QWidget::resizeInPaintEvent() QWidget window; window.setWindowTitle(QLatin1String(QTest::currentTestFunction())); UpdateWidget widget(&window); + widget.setPalette(simplePalette()); window.resize(200, 200); window.show(); - QApplication::setActiveWindow(&window); + QApplicationPrivate::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowExposed(&window)); QTRY_VERIFY(widget.numPaintEvents > 0); @@ -9155,6 +9850,9 @@ void tst_QWidget::opaqueChildren() void tst_QWidget::dumpObjectTree() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QWidget w; w.setWindowTitle(QLatin1String(QTest::currentTestFunction())); Q_SET_OBJECT_NAME(w); @@ -9177,7 +9875,6 @@ void tst_QWidget::dumpObjectTree() } QTestPrivate::androidCompatibleShow(&w); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); { @@ -9225,6 +9922,7 @@ public slots: void tst_QWidget::setMaskInResizeEvent() { UpdateWidget w; + w.setPalette(simplePalette()); w.setWindowTitle(QLatin1String(QTest::currentTestFunction())); w.reset(); w.resize(200, 200); @@ -9304,6 +10002,7 @@ void tst_QWidget::immediateRepaintAfterInvalidateBackingStore() QSKIP("We don't support immediate repaint right after show on other platforms."); QScopedPointer<UpdateWidget> widget(new UpdateWidget); + widget->setPalette(simplePalette()); widget->setWindowTitle(QLatin1String(QTest::currentTestFunction())); centerOnScreen(widget.data()); widget->show(); @@ -9755,11 +10454,12 @@ void tst_QWidget::setClearAndResizeMask() QSKIP("Wayland: This fails. Figure out why."); UpdateWidget topLevel; + topLevel.setPalette(simplePalette()); topLevel.setWindowTitle(QLatin1String(QTest::currentTestFunction())); topLevel.resize(160, 160); centerOnScreen(&topLevel); topLevel.show(); - QApplication::setActiveWindow(&topLevel); + QApplicationPrivate::setActiveWindow(&topLevel); QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); QTRY_VERIFY(topLevel.numPaintEvents > 0); topLevel.reset(); @@ -9789,6 +10489,7 @@ void tst_QWidget::setClearAndResizeMask() } UpdateWidget child(&topLevel); + child.setPalette(simplePalette()); child.setAutoFillBackground(true); // NB! Opaque child. child.setPalette(Qt::red); child.resize(100, 100); @@ -10182,6 +10883,9 @@ void tst_QWidget::enterLeaveOnWindowShowHide_data() */ void tst_QWidget::enterLeaveOnWindowShowHide() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QFETCH(Qt::WindowType, windowType); class Widget : public QWidget { @@ -10251,7 +10955,6 @@ void tst_QWidget::enterLeaveOnWindowShowHide() if (!QTest::qWaitFor([&]{ return widget.geometry().contains(QCursor::pos()); })) QSKIP("We can't move the cursor"); widget.show(); - QApplication::setActiveWindow(&widget); QVERIFY(QTest::qWaitForWindowActive(&widget)); ++expectedEnter; @@ -10381,6 +11084,110 @@ void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave() QTRY_COMPARE(child.numEnterEvents, 1); QCOMPARE(child.numMouseMoveEvents, 0); } + +void tst_QWidget::hoverPosition() +{ + if (m_platform == QStringLiteral("wayland")) + QSKIP("Wayland: Clients can't set cursor position on wayland."); + + class HoverWidget : public QWidget + { + public: + HoverWidget(QWidget *parent = nullptr) : QWidget(parent) { + setMouseTracking(true); + setAttribute(Qt::WA_Hover); + } + bool event(QEvent *ev) override { + switch (ev->type()) { + case QEvent::HoverMove: + // The docs say that WA_Hover will cause a paint event on enter and leave, but not on move. + update(); + Q_FALLTHROUGH(); + case QEvent::HoverEnter: + case QEvent::HoverLeave: { + qCDebug(lcTests) << ev; + lastHoverType = ev->type(); + ++hoverEventCount; + QHoverEvent *hov = static_cast<QHoverEvent *>(ev); + mousePos = hov->position().toPoint(); + mouseScenePos = hov->scenePosition().toPoint(); + if (ev->type() == QEvent::HoverEnter) + mouseEnterScenePos = hov->scenePosition().toPoint(); + break; + } + default: + break; + } + return QWidget::event(ev); + } + void paintEvent(QPaintEvent *) override { + ++paintEventCount; + QPainter painter(this); + if (mousePos.x() > 0) + painter.setPen(Qt::red); + painter.drawRect(0, 0, width(), height()); + painter.setPen(Qt::darkGreen); + painter.drawLine(mousePos - QPoint(crossHalfWidth, 0), mousePos + QPoint(crossHalfWidth, 0)); + painter.drawLine(mousePos - QPoint(0, crossHalfWidth), mousePos + QPoint(0, crossHalfWidth)); + } + + QEvent::Type lastHoverType = QEvent::None; + int hoverEventCount = 0; + int paintEventCount = 0; + QPoint mousePos; + QPoint mouseScenePos; + QPoint mouseEnterScenePos; + + private: + const int crossHalfWidth = 5; + }; + + QCursor::setPos(m_safeCursorPos); + if (!QTest::qWaitFor([this]{ return QCursor::pos() == m_safeCursorPos; })) + QSKIP("Can't move cursor"); + + QWidget root; + root.resize(300, 300); + HoverWidget h(&root); + h.setGeometry(100, 100, 100, 100); + root.show(); + QVERIFY(QTest::qWaitForWindowExposed(&root)); + + const QPoint middle(50, 50); + // wait until we got the correct global pos + QPoint expectedGlobalPos = root.geometry().topLeft() + QPoint(100, 100) + middle; + if (!QTest::qWaitFor([&]{ return expectedGlobalPos == h.mapToGlobal(middle); })) + QSKIP("Can't move cursor"); + QPoint curpos = h.mapToGlobal(middle); + QCursor::setPos(curpos); + if (!QTest::qWaitFor([curpos]{ return QCursor::pos() == curpos; })) + QSKIP("Can't move cursor"); + QTRY_COMPARE_GE(h.hoverEventCount, 1); // HoverEnter and then probably HoverMove, so usually 2 + QTRY_COMPARE_GE(h.paintEventCount, 2); + const int enterHoverEventCount = h.hoverEventCount; + qCDebug(lcTests) << "hover enter events:" << enterHoverEventCount << "last was" << h.lastHoverType + << "; paint events:" << h.paintEventCount; + QCOMPARE(h.mousePos, middle); + QCOMPARE(h.mouseEnterScenePos, h.mapToParent(middle)); + QCOMPARE(h.mouseScenePos, h.mapToParent(middle)); + QCOMPARE(h.lastHoverType, enterHoverEventCount == 1 ? QEvent::HoverEnter : QEvent::HoverMove); + + curpos += {10, 10}; + QCursor::setPos(curpos); + if (!QTest::qWaitFor([curpos]{ return QCursor::pos() == curpos; })) + QSKIP("Can't move cursor"); + QTRY_COMPARE(h.hoverEventCount, enterHoverEventCount + 1); + QCOMPARE(h.lastHoverType, QEvent::HoverMove); + QTRY_COMPARE_GE(h.paintEventCount, 3); + + curpos += {50, 50}; // in the outer widget, but leaving the inner widget + QCursor::setPos(curpos); + if (!QTest::qWaitFor([curpos]{ return QCursor::pos() == curpos; })) + QSKIP("Can't move cursor"); + QTRY_COMPARE(h.lastHoverType, QEvent::HoverLeave); + QCOMPARE_GE(h.hoverEventCount, enterHoverEventCount + 2); + QTRY_COMPARE_GE(h.paintEventCount, 4); +} #endif void tst_QWidget::windowFlags() @@ -10486,6 +11293,7 @@ void tst_QWidget::focusWidget_task254563() void tst_QWidget::destroyBackingStore() { UpdateWidget w; + w.setPalette(simplePalette()); w.setWindowTitle(QLatin1String(QTest::currentTestFunction())); centerOnScreen(&w); w.reset(); @@ -10956,36 +11764,11 @@ void tst_QWidget::focusProxy() QCOMPARE(container2->focusOutCount, 1); } -void tst_QWidget::focusProxyAndInputMethods() +void tst_QWidget::imEnabledNotImplemented() { if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) - QSKIP("Window activation is not supported."); - QScopedPointer<QWidget> toplevel(new QWidget(nullptr, Qt::X11BypassWindowManagerHint)); - toplevel->setWindowTitle(QLatin1String(QTest::currentTestFunction())); - toplevel->resize(200, 200); - toplevel->setAttribute(Qt::WA_InputMethodEnabled, true); + QSKIP("QWindow::requestActivate() is not supported."); - QWidget *child = new QWidget(toplevel.data()); - child->setFocusProxy(toplevel.data()); - child->setAttribute(Qt::WA_InputMethodEnabled, true); - - toplevel->setFocusPolicy(Qt::WheelFocus); - child->setFocusPolicy(Qt::WheelFocus); - - QVERIFY(!child->hasFocus()); - QVERIFY(!toplevel->hasFocus()); - - toplevel->show(); - QVERIFY(QTest::qWaitForWindowExposed(toplevel.data())); - QApplication::setActiveWindow(toplevel.data()); - QVERIFY(QTest::qWaitForWindowActive(toplevel.data())); - QVERIFY(toplevel->hasFocus()); - QVERIFY(child->hasFocus()); - QCOMPARE(qApp->focusObject(), toplevel.data()); -} - -void tst_QWidget::imEnabledNotImplemented() -{ // Check that a plain widget doesn't report that it supports IM. Only // widgets that implements either Qt::ImEnabled, or the Qt4 backup // solution, Qt::ImSurroundingText, should do so. @@ -10995,7 +11778,6 @@ void tst_QWidget::imEnabledNotImplemented() topLevel.show(); QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); - QApplication::setActiveWindow(&topLevel); QVERIFY(QTest::qWaitForWindowActive(&topLevel)); // A plain widget should return false for ImEnabled @@ -11012,11 +11794,12 @@ void tst_QWidget::imEnabledNotImplemented() QVERIFY(imEnabled.isValid()); QVERIFY(imEnabled.toBool()); - // ...even if it's read-only + // ImEnabled should be false when a lineedit is read-only since + // ImEnabled indicates the widget accepts input method _input_. edit.setReadOnly(true); imEnabled = QApplication::inputMethod()->queryFocusObject(Qt::ImEnabled, QVariant()); QVERIFY(imEnabled.isValid()); - QVERIFY(imEnabled.toBool()); + QVERIFY(!imEnabled.toBool()); } #ifdef QT_BUILD_INTERNAL @@ -11375,7 +12158,6 @@ void tst_QWidget::grabMouse() layout->addWidget(grabber); centerOnScreen(&w); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); QStringList expectedLog; @@ -11412,7 +12194,6 @@ void tst_QWidget::grabKeyboard() layout->addWidget(nonGrabber); centerOnScreen(&w); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); nonGrabber->setFocus(); grabber->grabKeyboard(); @@ -11506,6 +12287,9 @@ public: void tst_QWidget::touchEventSynthesizedMouseEvent() { + if (m_platform.startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("This test failed on Wayland. See also QTBUG-107157."); + { // Simple case, we ignore the touch events, we get mouse events instead TouchMouseWidget widget; @@ -12214,6 +12998,7 @@ void tst_QWidget::resizeStaticContentsChildWidget_QTBUG35282() widget.resize(200,200); UpdateWidget childWidget(&widget); + childWidget.setPalette(simplePalette()); childWidget.setAttribute(Qt::WA_StaticContents); childWidget.setAttribute(Qt::WA_OpaquePaintEvent); childWidget.setGeometry(250, 250, 500, 500); @@ -12312,60 +13097,54 @@ void tst_QWidget::testForOutsideWSRangeFlag() } } -class TabletWidget : public QWidget +void tst_QWidget::tabletTracking() { -public: - TabletWidget(QWidget *parent) : QWidget(parent) { } + class TabletWidget : public QWidget + { + public: + using QWidget::QWidget; - int tabletEventCount = 0; - int pressEventCount = 0; - int moveEventCount = 0; - int releaseEventCount = 0; - int trackingChangeEventCount = 0; - qint64 uid = -1; + int tabletEventCount = 0; + int pressEventCount = 0; + int moveEventCount = 0; + int releaseEventCount = 0; + int trackingChangeEventCount = 0; + qint64 uid = -1; -protected: - void tabletEvent(QTabletEvent *event) override { - ++tabletEventCount; - uid = event->pointingDevice()->uniqueId().numericId(); - switch (event->type()) { - case QEvent::TabletMove: - ++moveEventCount; - break; - case QEvent::TabletPress: - ++pressEventCount; - break; - case QEvent::TabletRelease: - ++releaseEventCount; - break; - default: - break; + protected: + void tabletEvent(QTabletEvent *event) override { + ++tabletEventCount; + uid = event->pointingDevice()->uniqueId().numericId(); + switch (event->type()) { + case QEvent::TabletMove: + ++moveEventCount; + break; + case QEvent::TabletPress: + ++pressEventCount; + break; + case QEvent::TabletRelease: + ++releaseEventCount; + break; + default: + break; + } } - } - bool event(QEvent *ev) override { - if (ev->type() == QEvent::TabletTrackingChange) - ++trackingChangeEventCount; - return QWidget::event(ev); - } -}; - -void tst_QWidget::tabletTracking() -{ - QWidget parent; - parent.setWindowTitle(QLatin1String(QTest::currentTestFunction())); - parent.resize(200,200); - // QWidgetWindow::handleTabletEvent doesn't deliver tablet events to the window's widget, only to a child. - // So it doesn't do any good to show a TabletWidget directly: it needs a parent. - TabletWidget widget(&parent); + bool event(QEvent *ev) override { + if (ev->type() == QEvent::TabletTrackingChange) + ++trackingChangeEventCount; + return QWidget::event(ev); + } + } widget; + widget.setWindowTitle(QLatin1String(QTest::currentTestFunction())); widget.resize(200,200); - parent.showNormal(); - QVERIFY(QTest::qWaitForWindowExposed(&parent)); + widget.showNormal(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); widget.setAttribute(Qt::WA_TabletTracking); QTRY_COMPARE(widget.trackingChangeEventCount, 1); QVERIFY(widget.hasTabletTracking()); - QWindow *window = parent.windowHandle(); + QWindow *window = widget.windowHandle(); QPointF local(10, 10); QPointF global = window->mapToGlobal(local.toPoint()); QPointF deviceLocal = QHighDpi::toNativeLocalPosition(local, window); @@ -12687,7 +13466,7 @@ void tst_QWidget::deleteWindowInCloseEvent() QApplication::exec(); // It should still result in a single lastWindowClosed emit - QCOMPARE(quitSpy.count(), 1); + QCOMPARE(quitSpy.size(), 1); } /*! @@ -12708,7 +13487,7 @@ void tst_QWidget::quitOnClose() widget->close(); }); QApplication::exec(); - QCOMPARE(quitSpy.count(), 1); + QCOMPARE(quitSpy.size(), 1); widget->show(); QVERIFY(QTest::qWaitForWindowExposed(widget.get())); @@ -12716,7 +13495,7 @@ void tst_QWidget::quitOnClose() widget.reset(); }); QApplication::exec(); - QCOMPARE(quitSpy.count(), 2); + QCOMPARE(quitSpy.size(), 2); } void tst_QWidget::setParentChangesFocus_data() @@ -12776,20 +13555,24 @@ void tst_QWidget::setParentChangesFocus() QCOMPARE(secondary->focusWidget()->objectName(), focusWidget); } secondary->show(); - QApplication::setActiveWindow(secondary.get()); + QApplicationPrivate::setActiveWindow(secondary.get()); QVERIFY(QTest::qWaitForWindowActive(secondary.get())); if (!reparentBeforeShow) { secondary->setParent(targetParent ? &window : nullptr, targetType); secondary->show(); // reparenting hides, so show again - QApplication::setActiveWindow(secondary.get()); + QApplicationPrivate::setActiveWindow(secondary.get()); QVERIFY(QTest::qWaitForWindowActive(secondary.get())); } + QVERIFY(QTest::qWaitFor([]{ return QApplication::focusWidget(); })); QCOMPARE(QApplication::focusWidget()->objectName(), focusWidget); } void tst_QWidget::activateWhileModalHidden() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QDialog dialog; dialog.setWindowModality(Qt::ApplicationModal); dialog.show(); @@ -12807,6 +13590,35 @@ void tst_QWidget::activateWhileModalHidden() QCOMPARE(QApplication::activeWindow(), &window); } +// Create a simple palette to prevent multiple paint events +QPalette tst_QWidget::simplePalette() +{ + static QPalette simplePalette = []{ + const QColor windowText = Qt::black; + const QColor backGround = QColor(239, 239, 239); + const QColor light = backGround.lighter(150); + const QColor mid = (backGround.darker(130)); + const QColor midLight = mid.lighter(110); + const QColor base = Qt::white; + const QColor dark = backGround.darker(150); + const QColor text = Qt::black; + const QColor highlight = QColor(48, 140, 198); + const QColor hightlightedText = Qt::white; + const QColor button = backGround; + const QColor shadow = dark.darker(135); + + QPalette defaultPalette(windowText, backGround, light, dark, mid, text, base); + defaultPalette.setBrush(QPalette::Midlight, midLight); + defaultPalette.setBrush(QPalette::Button, button); + defaultPalette.setBrush(QPalette::Shadow, shadow); + defaultPalette.setBrush(QPalette::HighlightedText, hightlightedText); + defaultPalette.setBrush(QPalette::Active, QPalette::Highlight, highlight); + return defaultPalette; + }(); + + return simplePalette; +} + #ifdef Q_OS_ANDROID void tst_QWidget::showFullscreenAndroid() { @@ -12840,5 +13652,438 @@ void tst_QWidget::showFullscreenAndroid() } #endif // Q_OS_ANDROID +void tst_QWidget::setVisibleDuringDestruction() +{ + CreateDestroyWidget widget; + widget.create(); + QVERIFY(widget.windowHandle()); + + QSignalSpy signalSpy(widget.windowHandle(), &QWindow::visibleChanged); + EventSpy<QWindow> showEventSpy(widget.windowHandle(), QEvent::Show); + widget.show(); + QTRY_COMPARE(showEventSpy.count(), 1); + QTRY_COMPARE(signalSpy.count(), 1); + + EventSpy<QWindow> hideEventSpy(widget.windowHandle(), QEvent::Hide); + widget.hide(); + QTRY_COMPARE(hideEventSpy.count(), 1); + QTRY_COMPARE(signalSpy.count(), 2); + + widget.show(); + QTRY_COMPARE(showEventSpy.count(), 2); + QTRY_COMPARE(signalSpy.count(), 3); + + widget.destroy(); + QTRY_COMPARE(hideEventSpy.count(), 2); + QTRY_COMPARE(signalSpy.count(), 4); +} + +void tst_QWidget::explicitShowHide() +{ + { + QWidget parent; + parent.setObjectName("Parent"); + QWidget child(&parent); + child.setObjectName("Child"); + + QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide), false); + QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), true); + QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false); + + parent.show(); + QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide), true); + QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false); + + // Fix up earlier expected failure + child.setAttribute(Qt::WA_WState_ExplicitShowHide, false); + + parent.hide(); + QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide), true); + QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), true); + QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false); + } + + { + // Test what happens when a child is reparented after showing it + + QWidget parent; + parent.setObjectName("Parent"); + QWidget child; + child.setObjectName("Child"); + + child.show(); + QCOMPARE(child.isVisible(), true); + QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), true); + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false); + + child.setParent(&parent); + // As documented, a widget becomes invisible as part of changing + // its parent, even if it was previously visible. The user must call + // show() to make the widget visible again. + QCOMPARE(child.isVisible(), false); + + // However, the widget does not end up with Qt::WA_WState_Hidden, + // as QWidget::setParent treats it as a child, which normally will + // not get Qt::WA_WState_Hidden out of the box. + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false); + + // For some reason we reset WA_WState_ExplicitShowHide, and it's + // not clear whether this is correct or not See QWidget::setParent() + // for a comment with more details. + QEXPECT_FAIL("", "We reset WA_WState_ExplicitShowHide on widget re-parent", Continue); + QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), true); + + // The fact that the child doesn't have Qt::WA_WState_Hidden means + // it's sufficient to show the parent widget. We don't need to + // explicitly show the child. + parent.show(); + QCOMPARE(child.isVisible(), true); + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false); + } + + { + QWidget parent; + parent.setObjectName("Parent"); + QWidget child(&parent); + child.setObjectName("Child"); + + parent.show(); + + // If a non-native child ends up being closed, we will hide the + // widget, but do so via QWidget::hide(), which marks the widget + // as explicitly hidden. + + child.setAttribute(Qt::WA_WState_ExplicitShowHide, false); + QCOMPARE(child.close(), true); + QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), true); + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), true); + + child.show(); + child.setAttribute(Qt::WA_NativeWindow); + child.setAttribute(Qt::WA_WState_ExplicitShowHide, false); + QCOMPARE(child.close(), true); + QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), true); + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), true); + + child.show(); + child.setAttribute(Qt::WA_WState_ExplicitShowHide, false); + QCOMPARE(child.windowHandle()->close(), false); // Can't close non-top level QWindows + QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false); + + // If we end up in QWidgetPrivate::handleClose via QWidgetWindow::closeEvent, + // either through QWindow::close(), or via QWSI::handleCloseEvent, we'll still + // do the explicit hide. + + child.show(); + child.setAttribute(Qt::WA_WState_ExplicitShowHide, false); + QCOMPARE(QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::SynchronousDelivery>( + child.windowHandle()), true); + QEXPECT_FAIL("", "Closing a native child via QWSI is treated as an explicit hide", Continue); + QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), true); + } + + { + QWidget widget; + widget.show(); + widget.hide(); + + QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), false); + QCOMPARE(widget.testAttribute(Qt::WA_WState_ExplicitShowHide), true); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Hidden), true); + + // The widget is now explicitly hidden. Showing it again, via QWindow, + // should make the widget visible, and it should not stay hidden, as + // that's an invalid state for a widget. + + widget.windowHandle()->setVisible(true); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), true); + QCOMPARE(widget.testAttribute(Qt::WA_WState_ExplicitShowHide), true); + QCOMPARE(widget.testAttribute(Qt::WA_WState_Hidden), false); + } +} + +/*! + Verify that we deliver DragEnter/Leave events symmetrically, even if the + widget entered didn't accept the DragEnter event. +*/ +void tst_QWidget::dragEnterLeaveSymmetry() +{ + QWidget widget; + widget.setAcceptDrops(true); + QLineEdit lineEdit; + QLabel label("Hello world"); + label.setAcceptDrops(true); + + struct EventFilter : QObject + { + bool eventFilter(QObject *receiver, QEvent *event) override + { + switch (event->type()) { + case QEvent::DragEnter: + case QEvent::DragLeave: + receivers[event->type()] << receiver; + break; + + default: + break; + } + + return false; + } + + QMap<QEvent::Type, QList<QObject *>> receivers; + + void clear() { receivers.clear(); } + bool hasEntered(QWidget *widget) const + { + return receivers.value(QEvent::DragEnter).contains(widget); + } + bool hasLeft(QWidget *widget) const + { + return receivers.value(QEvent::DragLeave).contains(widget); + } + } filter; + + widget.installEventFilter(&filter); + lineEdit.installEventFilter(&filter); + label.installEventFilter(&filter); + + QVBoxLayout vbox; + vbox.setContentsMargins(10, 10, 10, 10); + vbox.addWidget(&lineEdit); + vbox.addWidget(&label); + widget.setLayout(&vbox); + + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + QMimeData data; + data.setColorData(QVariant::fromValue(Qt::red)); + QWindowSystemInterface::handleDrag(widget.windowHandle(), &data, QPoint(1, 1), + Qt::ActionMask, Qt::LeftButton, {}); + QVERIFY(filter.hasEntered(&widget)); + QVERIFY(!filter.hasEntered(&lineEdit)); + QVERIFY(!filter.hasEntered(&label)); + QVERIFY(widget.underMouse()); + QVERIFY(!lineEdit.underMouse()); + filter.clear(); + + QWindowSystemInterface::handleDrag(widget.windowHandle(), &data, lineEdit.geometry().center(), + Qt::ActionMask, Qt::LeftButton, {}); + // DragEnter propagates as the lineEdit doesn't want it, so the widget + // sees both a Leave and an Enter event + QVERIFY(filter.hasLeft(&widget)); + QVERIFY(filter.hasEntered(&widget)); + QVERIFY(filter.hasEntered(&widget)); + // both have the UnderMouse attribute set + QVERIFY(lineEdit.underMouse()); + QVERIFY(widget.underMouse()); + + // The lineEdit didn't accept the DragEnter, but it should still has to + // get the DragLeave so that UnderMouse is cleared; the widget gets both + // Leave and Enter through propagation. + QWindowSystemInterface::handleDrag(widget.windowHandle(), &data, label.geometry().center(), + Qt::ActionMask, Qt::LeftButton, {}); + QVERIFY(filter.hasLeft(&lineEdit)); + QVERIFY(filter.hasLeft(&widget)); + QVERIFY(filter.hasEntered(&label)); + QVERIFY(filter.hasEntered(&widget)); + + QVERIFY(!lineEdit.underMouse()); + QVERIFY(label.underMouse()); + QVERIFY(widget.underMouse()); +} + +void tst_QWidget::reparentWindowHandles_data() +{ + QTest::addColumn<int>("stage"); + QTest::addRow("reparent child") << 1; + QTest::addRow("top level to child") << 2; + QTest::addRow("transient parent") << 3; + QTest::addRow("window container") << 4; +} + +void tst_QWidget::reparentWindowHandles() +{ + const bool nativeSiblingsOriginal = qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); + auto nativeSiblingGuard = qScopeGuard([&]{ + qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, nativeSiblingsOriginal); + }); + + QFETCH(int, stage); + + switch (stage) { + case 1: { + // Reparent child widget + + QWidget topLevel; + topLevel.setAttribute(Qt::WA_NativeWindow); + QVERIFY(topLevel.windowHandle()); + QPointer<QWidget> child = new QWidget(&topLevel); + child->setAttribute(Qt::WA_DontCreateNativeAncestors); + child->setAttribute(Qt::WA_NativeWindow); + QVERIFY(child->windowHandle()); + + QWidget anotherTopLevel; + anotherTopLevel.setAttribute(Qt::WA_NativeWindow); + QVERIFY(anotherTopLevel.windowHandle()); + QPointer<QWidget> intermediate = new QWidget(&anotherTopLevel); + QPointer<QWidget> leaf = new QWidget(intermediate); + leaf->setAttribute(Qt::WA_DontCreateNativeAncestors); + leaf->setAttribute(Qt::WA_NativeWindow); + QVERIFY(leaf->windowHandle()); + QVERIFY(!intermediate->windowHandle()); + + // Reparenting a native widget should reparent the QWindow + child->setParent(leaf); + QCOMPARE(child->windowHandle()->parent(), leaf->windowHandle()); + QCOMPARE(child->windowHandle()->transientParent(), nullptr); + QVERIFY(!intermediate->windowHandle()); + + // So should reparenting a non-native widget with native children + intermediate->setParent(&topLevel); + QVERIFY(!intermediate->windowHandle()); + QCOMPARE(leaf->windowHandle()->parent(), topLevel.windowHandle()); + QCOMPARE(leaf->windowHandle()->transientParent(), nullptr); + QCOMPARE(child->windowHandle()->parent(), leaf->windowHandle()); + QCOMPARE(child->windowHandle()->transientParent(), nullptr); + } + break; + case 2: { + // Top level to child + + QWidget topLevel; + topLevel.setAttribute(Qt::WA_NativeWindow); + + // A regular top level loses its nativeness + QPointer<QWidget> regularToplevel = new QWidget; + regularToplevel->show(); + QVERIFY(QTest::qWaitForWindowExposed(regularToplevel)); + QVERIFY(regularToplevel->windowHandle()); + regularToplevel->setParent(&topLevel); + QVERIFY(!regularToplevel->windowHandle()); + + // A regular top level loses its nativeness + QPointer<QWidget> regularToplevelWithNativeChildren = new QWidget; + QPointer<QWidget> nativeChild = new QWidget(regularToplevelWithNativeChildren); + nativeChild->setAttribute(Qt::WA_DontCreateNativeAncestors); + nativeChild->setAttribute(Qt::WA_NativeWindow); + QVERIFY(nativeChild->windowHandle()); + regularToplevelWithNativeChildren->show(); + QVERIFY(QTest::qWaitForWindowExposed(regularToplevelWithNativeChildren)); + QVERIFY(regularToplevelWithNativeChildren->windowHandle()); + regularToplevelWithNativeChildren->setParent(&topLevel); + QVERIFY(!regularToplevelWithNativeChildren->windowHandle()); + // But the native child does not + QVERIFY(nativeChild->windowHandle()); + QCOMPARE(nativeChild->windowHandle()->parent(), topLevel.windowHandle()); + + // An explicitly native top level keeps its nativeness, and the window handle moves + QPointer<QWidget> nativeTopLevel = new QWidget; + nativeTopLevel->setAttribute(Qt::WA_NativeWindow); + QVERIFY(nativeTopLevel->windowHandle()); + nativeTopLevel->setParent(&topLevel); + QVERIFY(nativeTopLevel->windowHandle()); + QCOMPARE(nativeTopLevel->windowHandle()->parent(), topLevel.windowHandle()); + } + break; + case 3: { + // Transient parent + + QWidget topLevel; + topLevel.setAttribute(Qt::WA_NativeWindow); + QVERIFY(topLevel.windowHandle()); + QPointer<QWidget> child = new QWidget(&topLevel); + child->setAttribute(Qt::WA_NativeWindow); + QVERIFY(child->windowHandle()); + + QWidget anotherTopLevel; + anotherTopLevel.setAttribute(Qt::WA_NativeWindow); + QVERIFY(anotherTopLevel.windowHandle()); + + // Make transient child of top level + anotherTopLevel.setParent(&topLevel, Qt::Window); + QCOMPARE(anotherTopLevel.windowHandle()->parent(), nullptr); + QCOMPARE(anotherTopLevel.windowHandle()->transientParent(), topLevel.windowHandle()); + + // Make transient child of child + anotherTopLevel.setParent(child, Qt::Window); + QCOMPARE(anotherTopLevel.windowHandle()->parent(), nullptr); + QCOMPARE(anotherTopLevel.windowHandle()->transientParent(), topLevel.windowHandle()); + } + break; + case 4: { + // Window container + + QWidget topLevel; + topLevel.setAttribute(Qt::WA_NativeWindow); + QVERIFY(topLevel.windowHandle()); + + QPointer<QWidget> child = new QWidget(&topLevel); + QVERIFY(!child->windowHandle()); + + QWindow *window = new QWindow; + QWidget *container = QWidget::createWindowContainer(window); + container->setParent(child); + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + QCOMPARE(window->parent(), topLevel.windowHandle()); + + QWidget anotherTopLevel; + anotherTopLevel.setAttribute(Qt::WA_NativeWindow); + QVERIFY(anotherTopLevel.windowHandle()); + + child->setParent(&anotherTopLevel); + QCOMPARE(window->parent(), anotherTopLevel.windowHandle()); + } + break; + default: + Q_UNREACHABLE(); + } +} + +#ifndef QT_NO_CONTEXTMENU +void tst_QWidget::contextMenuTrigger() +{ + class ContextMenuWidget : public QWidget + { + public: + int events = 0; + + protected: + void contextMenuEvent(QContextMenuEvent *) override { ++events; } + }; + + const Qt::ContextMenuTrigger wasTrigger = QGuiApplication::styleHints()->contextMenuTrigger(); + auto restoreTriggerGuard = qScopeGuard([wasTrigger]{ + QGuiApplication::styleHints()->setContextMenuTrigger(wasTrigger); + }); + + ContextMenuWidget widget; + widget.show(); + QVERIFY(!qApp->topLevelWindows().empty()); + auto *window = qApp->topLevelWindows()[0]; + QVERIFY(window); + QCOMPARE(widget.events, 0); + QGuiApplication::styleHints()->setContextMenuTrigger(Qt::ContextMenuTrigger::Press); + QTest::mousePress(window, Qt::RightButton); + QCOMPARE(widget.events, 1); + QTest::mouseRelease(window, Qt::RightButton); + QCOMPARE(widget.events, 1); + QGuiApplication::styleHints()->setContextMenuTrigger(Qt::ContextMenuTrigger::Release); + QTest::mousePress(window, Qt::RightButton); + QCOMPARE(widget.events, 1); + QTest::mouseRelease(window, Qt::RightButton); + QCOMPARE(widget.events, 2); +} +#endif + QTEST_MAIN(tst_QWidget) #include "tst_qwidget.moc" diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.h b/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.h deleted file mode 100644 index fec9706ef5..0000000000 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 -#include <QtCore/QString> -#include <QtCore/QPair> -#include <QtWidgets/QWidget> - -#pragma once // Yeah, it's deprecated in general, but it's standard practice for Mac OS X. - -QString nativeWindowTitle(QWidget *widget, Qt::WindowState state); -bool nativeWindowModified(QWidget *widget); diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.mm b/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.mm deleted file mode 100644 index 19c5c0d714..0000000000 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget_mac_helpers.mm +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -// some versions of CALayer.h use 'slots' as an identifier -#define QT_NO_KEYWORDS - -#include "tst_qwidget_mac_helpers.h" -#include <QApplication> -#include <qpa/qplatformnativeinterface.h> -#include <private/qcore_mac_p.h> - -#include <AppKit/AppKit.h> - -QString nativeWindowTitle(QWidget *window, Qt::WindowState state) -{ - QWindow *qwindow = window->windowHandle(); - NSWindow *nswindow = (NSWindow *) qApp->platformNativeInterface()->nativeResourceForWindow("nswindow", qwindow); - QCFString macTitle; - if (state == Qt::WindowMinimized) { - macTitle = reinterpret_cast<CFStringRef>([[nswindow miniwindowTitle] retain]); - } else { - macTitle = reinterpret_cast<CFStringRef>([[nswindow title] retain]); - } - return macTitle; -} - -bool nativeWindowModified(QWidget *widget) -{ - QWindow *qwindow = widget->windowHandle(); - NSWindow *nswindow = (NSWindow *) qApp->platformNativeInterface()->nativeResourceForWindow("nswindow", qwindow); - return [nswindow isDocumentEdited]; -} diff --git a/tests/auto/widgets/kernel/qwidget_window/BLACKLIST b/tests/auto/widgets/kernel/qwidget_window/BLACKLIST index 0e1a2d58dc..77853a3e8c 100644 --- a/tests/auto/widgets/kernel/qwidget_window/BLACKLIST +++ b/tests/auto/widgets/kernel/qwidget_window/BLACKLIST @@ -1,7 +1,3 @@ -[tst_resize_count] -# QTBUG-66345 -opensuse-42.3 -ubuntu-16.04 # QTBUG-87412 [tst_move_show] android diff --git a/tests/auto/widgets/kernel/qwidget_window/CMakeLists.txt b/tests/auto/widgets/kernel/qwidget_window/CMakeLists.txt index cd4bf159e4..af60c92cbf 100644 --- a/tests/auto/widgets/kernel/qwidget_window/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qwidget_window/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qwidget_window.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qwidget_window Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qwidget_window LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qwidget_window SOURCES tst_qwidget_window.cpp @@ -16,4 +20,5 @@ qt_internal_add_test(tst_qwidget_window Qt::GuiPrivate Qt::TestPrivate Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp index 09956e69a2..1fab69fdcc 100644 --- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp +++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -28,6 +28,8 @@ #include <QtTest/private/qtesthelpers_p.h> +#include <QtWidgets/private/qapplication_p.h> + using namespace QTestPrivate; // Compare a window position that may go through scaling in the platform plugin with fuzz. @@ -51,6 +53,7 @@ public: tst_QWidget_window(); public slots: + void init(); void initTestCase(); void cleanupTestCase(); void cleanup(); @@ -108,8 +111,13 @@ private slots: void mouseMoveWithPopup_data(); void mouseMoveWithPopup(); + void showHideWindowHandle_data(); + void showHideWindowHandle(); + void resetFocusObjectOnDestruction(); + void cleanupOnDestruction(); + private: QSize m_testWidgetSize; const int m_fuzz; @@ -127,6 +135,11 @@ void tst_QWidget_window::initTestCase() { } +void tst_QWidget_window::init() +{ + QTest::failOnWarning(QRegularExpression(".*No such slot.*")); +} + void tst_QWidget_window::cleanupTestCase() { } @@ -678,7 +691,6 @@ void tst_QWidget_window::tst_dnd() dndTestWidget.show(); QVERIFY(QTest::qWaitForWindowExposed(&dndTestWidget)); - qApp->setActiveWindow(&dndTestWidget); QVERIFY(QTest::qWaitForWindowActive(&dndTestWidget)); QMimeData mimeData; @@ -1450,6 +1462,9 @@ void tst_QWidget_window::mouseMoveWithPopup_data() void tst_QWidget_window::mouseMoveWithPopup() { + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Wayland: Skip this test, see also QTBUG-107154"); + QFETCH(Qt::WindowType, windowType); class Window : public QWidget @@ -1619,14 +1634,164 @@ void tst_QWidget_window::mouseMoveWithPopup() // but the release event will still be delivered to the first popup - dialogs might not get it QCOMPARE(mouseAction(Qt::LeftButton), QEvent::MouseButtonRelease); - if (topLevel.popup->mouseReleaseCount != 1 - && !QGuiApplication::platformName().startsWith(QLatin1String("windows"), Qt::CaseInsensitive)) + if (topLevel.popup->mouseReleaseCount != 1) QEXPECT_FAIL("Dialog", "Platform specific behavior", Continue); QCOMPARE(topLevel.popup->mouseReleaseCount, 1); } +struct ShowHideEntry { + QEvent::Type action; + Qt::WindowType target; + using List = QList<ShowHideEntry>; +}; + +void tst_QWidget_window::showHideWindowHandle_data() +{ + QTest::addColumn<ShowHideEntry::List>("entries"); + + QTest::addRow("show/hide widget") << ShowHideEntry::List{ + { QEvent::Show, Qt::Widget }, { QEvent::Hide, Qt::Widget } + }; + QTest::addRow("show/hide window") << ShowHideEntry::List{ + { QEvent::Show, Qt::Window }, { QEvent::Hide, Qt::Window } + }; + QTest::addRow("show widget, hide window") << ShowHideEntry::List{ + { QEvent::Show, Qt::Widget }, { QEvent::Hide, Qt::Window } + }; + QTest::addRow("show window, hide widget") << ShowHideEntry::List{ + { QEvent::Show, Qt::Window }, { QEvent::Hide, Qt::Widget } + }; + QTest::addRow("show/hide widget, then show window, hide widget") << ShowHideEntry::List{ + { QEvent::Show, Qt::Widget }, { QEvent::Hide, Qt::Widget }, + { QEvent::Show, Qt::Window }, { QEvent::Hide, Qt::Widget } + }; + QTest::addRow("show widget, close widget, show widget") << ShowHideEntry::List{ + { QEvent::Show, Qt::Widget }, { QEvent::Close, Qt::Widget }, { QEvent::Show, Qt::Widget } + }; + QTest::addRow("show widget, close widget, show window") << ShowHideEntry::List{ + { QEvent::Show, Qt::Widget }, { QEvent::Close, Qt::Widget }, { QEvent::Show, Qt::Window } + }; + QTest::addRow("show widget, close window, show widget") << ShowHideEntry::List{ + { QEvent::Show, Qt::Widget }, { QEvent::Close, Qt::Window }, { QEvent::Show, Qt::Widget } + }; + QTest::addRow("show widget, close window, show window") << ShowHideEntry::List{ + { QEvent::Show, Qt::Widget }, { QEvent::Close, Qt::Window }, { QEvent::Show, Qt::Window } + }; +} + +void tst_QWidget_window::showHideWindowHandle() +{ + QWidget parent; + parent.setObjectName("Parent"); + QCOMPARE(parent.isVisible(), false); + QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide), false); + QCOMPARE(parent.testAttribute(Qt::WA_WState_Visible), false); + QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), true); + + QWidget child; + child.setObjectName("Child"); + QCOMPARE(child.isVisible(), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Visible), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), true); + + child.setParent(&parent); + QCOMPARE(child.isVisible(), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Visible), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false); + + QFETCH(QList<ShowHideEntry>, entries); + for (const auto entry : entries) { + + if (entry.action == QEvent::Show) { + if (entry.target == Qt::Window && !parent.windowHandle()) { + parent.setAttribute(Qt::WA_NativeWindow); + QVERIFY(parent.windowHandle()); + + QCOMPARE(parent.isVisible(), false); + QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide), false); + QCOMPARE(parent.testAttribute(Qt::WA_WState_Visible), false); + QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), true); + } + + bool wasExplicitShowHide = parent.testAttribute(Qt::WA_WState_ExplicitShowHide); + + if (entry.target == Qt::Widget) + parent.show(); + else + parent.windowHandle()->show(); + + QVERIFY(QTest::qWaitForWindowActive(&parent)); + + QCOMPARE(parent.isVisible(), true); + QVERIFY(parent.windowHandle()); + QCOMPARE(parent.windowHandle()->isVisible(), true); + + QCOMPARE(parent.testAttribute(Qt::WA_WState_Visible), true); + QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), false); + QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide), + entry.target == Qt::Widget || wasExplicitShowHide); + + QCOMPARE(child.isVisible(), true); + QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Visible), true); + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false); + + } else if (entry.action == QEvent::Hide) { + + bool wasExplicitShowHide = parent.testAttribute(Qt::WA_WState_ExplicitShowHide); + + if (entry.target == Qt::Widget) + parent.hide(); + else + parent.windowHandle()->hide(); + + QCOMPARE(parent.isVisible(), false); + QVERIFY(parent.windowHandle()); + QCOMPARE(parent.windowHandle()->isVisible(), false); + + QCOMPARE(parent.testAttribute(Qt::WA_WState_Visible), false); + QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), true); + QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide), + entry.target == Qt::Widget || wasExplicitShowHide); + + QCOMPARE(child.isVisible(), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Visible), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false); + + } else if (entry.action == QEvent::Close) { + + bool wasExplicitShowHide = parent.testAttribute(Qt::WA_WState_ExplicitShowHide); + + if (entry.target == Qt::Widget) + parent.close(); + else + parent.windowHandle()->close(); + + QCOMPARE(parent.isVisible(), false); + QVERIFY(parent.windowHandle()); + QCOMPARE(parent.windowHandle()->isVisible(), false); + + QCOMPARE(parent.testAttribute(Qt::WA_WState_Visible), false); + QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), true); + QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide), + entry.target == Qt::Widget || wasExplicitShowHide); + + QCOMPARE(child.isVisible(), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Visible), false); + QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false); + } + } +} + void tst_QWidget_window::resetFocusObjectOnDestruction() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + QSignalSpy focusObjectChangedSpy(qApp, &QGuiApplication::focusObjectChanged); // single top level widget that has focus @@ -1636,9 +1801,9 @@ void tst_QWidget_window::resetFocusObjectOnDestruction() widget->show(); QVERIFY(QTest::qWaitForWindowActive(widget.get())); - int activeCount = focusObjectChangedSpy.count(); + int activeCount = focusObjectChangedSpy.size(); widget.reset(); - QVERIFY(focusObjectChangedSpy.count() > activeCount); + QVERIFY(focusObjectChangedSpy.size() > activeCount); QCOMPARE(focusObjectChangedSpy.last().last().value<QObject*>(), nullptr); focusObjectChangedSpy.clear(); @@ -1651,12 +1816,37 @@ void tst_QWidget_window::resetFocusObjectOnDestruction() widget->show(); QVERIFY(QTest::qWaitForWindowActive(widget.get())); - activeCount = focusObjectChangedSpy.count(); + activeCount = focusObjectChangedSpy.size(); widget.reset(); // we might get more than one signal emission - QVERIFY(focusObjectChangedSpy.count() > activeCount); + QVERIFY(focusObjectChangedSpy.size() > activeCount); QCOMPARE(focusObjectChangedSpy.last().last().value<QObject*>(), nullptr); } +class CreateDestroyWidget : public QWidget +{ +public: + using QWidget::create; + using QWidget::destroy; +}; + +void tst_QWidget_window::cleanupOnDestruction() +{ + CreateDestroyWidget widget; + QWidget child(&widget); + + QWidget grandChild(&child); + // Ensure there's not a 1:1 native window hierarhcy that we could + // recurse during QWidget::destroy(), triggering the issue that + // we were failing to clean up when not destroyed via QWidget. + grandChild.setAttribute(Qt::WA_DontCreateNativeAncestors); + grandChild.winId(); + + widget.destroy(); + widget.create(); + + widget.show(); +} + QTEST_MAIN(tst_QWidget_window) #include "tst_qwidget_window.moc" diff --git a/tests/auto/widgets/kernel/qwidgetaction/CMakeLists.txt b/tests/auto/widgets/kernel/qwidgetaction/CMakeLists.txt index 40a4fcbff1..fb5409464d 100644 --- a/tests/auto/widgets/kernel/qwidgetaction/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qwidgetaction/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qwidgetaction.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qwidgetaction Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qwidgetaction LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qwidgetaction SOURCES tst_qwidgetaction.cpp diff --git a/tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp b/tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp index 031856e0f9..a06e072b71 100644 --- a/tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp +++ b/tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -222,7 +222,7 @@ void tst_QWidgetAction::customWidget() tb1.addAction(action); QList<QWidget *> combos = action->createdWidgets(); - QCOMPARE(combos.count(), 1); + QCOMPARE(combos.size(), 1); QPointer<QComboBox> combo1 = qobject_cast<QComboBox *>(combos.at(0)); QVERIFY(combo1); @@ -230,7 +230,7 @@ void tst_QWidgetAction::customWidget() tb2.addAction(action); combos = action->createdWidgets(); - QCOMPARE(combos.count(), 2); + QCOMPARE(combos.size(), 2); QCOMPARE(combos.at(0), combo1.data()); QPointer<QComboBox> combo2 = qobject_cast<QComboBox *>(combos.at(1)); diff --git a/tests/auto/widgets/kernel/qwidgetmetatype/CMakeLists.txt b/tests/auto/widgets/kernel/qwidgetmetatype/CMakeLists.txt index 68eb4dece2..431a584a60 100644 --- a/tests/auto/widgets/kernel/qwidgetmetatype/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qwidgetmetatype/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qwidgetmetatype.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qwidgetmetatype Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qwidgetmetatype LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qwidgetmetatype SOURCES tst_qwidgetmetatype.cpp diff --git a/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp b/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp index da417b377e..885c26a128 100644 --- a/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp +++ b/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com> -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/kernel/qwidgetrepaintmanager/CMakeLists.txt b/tests/auto/widgets/kernel/qwidgetrepaintmanager/CMakeLists.txt index df19ff8a28..ae91af064c 100644 --- a/tests/auto/widgets/kernel/qwidgetrepaintmanager/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qwidgetrepaintmanager/CMakeLists.txt @@ -1,5 +1,11 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qwidgetrepaintmanager LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() qt_internal_add_test(tst_qwidgetrepaintmanager SOURCES diff --git a/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp b/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp index fb959821bc..64ebeb08b0 100644 --- a/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp +++ b/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -11,7 +11,9 @@ #include <private/qhighdpiscaling_p.h> #include <private/qwidget_p.h> #include <private/qwidgetrepaintmanager_p.h> +#include <qpa/qplatformintegration.h> #include <qpa/qplatformbackingstore.h> +#include <private/qguiapplication_p.h> //#define MANUAL_DEBUG @@ -33,14 +35,33 @@ public: void initialShow() { show(); - if (isWindow()) + if (isWindow()) { QVERIFY(QTest::qWaitForWindowExposed(this)); + QVERIFY(waitForPainted()); + } paintedRegions = {}; } bool waitForPainted(int timeout = 5000) { - return QTest::qWaitFor([this]{ return !paintedRegions.isEmpty(); }, timeout); + int remaining = timeout; + QDeadlineTimer deadline(remaining, Qt::PreciseTimer); + if (!QTest::qWaitFor([this]{ return !paintedRegions.isEmpty(); }, timeout)) + return false; + + // In case of multiple paint events: + // Process events and wait until all have been consumed, + // i.e. paintedRegions no longer changes. + QRegion reg; + while (remaining > 0 && reg != paintedRegions) { + reg = paintedRegions; + QCoreApplication::processEvents(QEventLoop::AllEvents, remaining); + if (reg == paintedRegions) + return true; + + remaining = int(deadline.remainingTime()); + } + return false; } QRegion takePaintedRegions() @@ -51,6 +72,17 @@ public: } QRegion paintedRegions; + bool event(QEvent *event) override + { + const auto type = event->type(); + if (type == QEvent::WindowActivate || type == QEvent::WindowDeactivate) + return true; + if (type == QEvent::UpdateRequest) + ++updateRequests; + return QWidget::event(event); + } + int updateRequests = 0; + protected: void paintEvent(QPaintEvent *event) override { @@ -71,6 +103,14 @@ public: setAttribute(Qt::WA_OpaquePaintEvent); } + bool event(QEvent *event) override + { + const auto type = event->type(); + if (type == QEvent::WindowActivate || type == QEvent::WindowDeactivate) + return true; + return QWidget::event(event); + } + protected: void paintEvent(QPaintEvent *e) override { @@ -186,6 +226,14 @@ public: QSize sizeHint() const override { return QSize(400, 400); } + bool event(QEvent *event) override + { + const auto type = event->type(); + if (type == QEvent::WindowActivate || type == QEvent::WindowDeactivate) + return true; + return QWidget::event(event); + } + protected: void resizeEvent(QResizeEvent *) override { @@ -211,6 +259,9 @@ private slots: void opaqueChildren(); void staticContents(); void scroll(); + void paintOnScreenUpdates(); + void evaluateRhi(); + #if defined(QT_BUILD_INTERNAL) void scrollWithOverlap(); void overlappedRegion(); @@ -226,13 +277,14 @@ protected: */ bool compareWidget(QWidget *w) { + QBackingStore *backingStore = w->window()->backingStore(); + Q_ASSERT(backingStore && backingStore->handle()); + QPlatformBackingStore *platformBackingStore = backingStore->handle(); + if (!waitForFlush(w)) { qWarning() << "Widget" << w << "failed to flush"; return false; } - QBackingStore *backingStore = w->window()->backingStore(); - Q_ASSERT(backingStore && backingStore->handle()); - QPlatformBackingStore *platformBackingStore = backingStore->handle(); QImage backingstoreContent = platformBackingStore->toImage(); if (!w->isWindow()) { @@ -259,7 +311,14 @@ protected: } bool waitForFlush(QWidget *widget) const { + if (!widget) + return true; + auto *repaintManager = QWidgetPrivate::get(widget->window())->maybeRepaintManager(); + + if (!repaintManager) + return true; + return QTest::qWaitFor([repaintManager]{ return !repaintManager->isDirty(); } ); }; #endif // QT_BUILD_INTERNAL @@ -282,7 +341,7 @@ void tst_QWidgetRepaintManager::initTestCase() QVERIFY(QTest::qWaitForWindowExposed(&widget)); m_implementsScroll = widget.backingStore()->handle()->scroll(QRegion(widget.rect()), 1, 1); - qDebug() << QGuiApplication::platformName() << "QPA backend implements scroll:" << m_implementsScroll; + qInfo() << QGuiApplication::platformName() << "QPA backend implements scroll:" << m_implementsScroll; } void tst_QWidgetRepaintManager::cleanup() @@ -321,6 +380,7 @@ void tst_QWidgetRepaintManager::children() TestWidget *child1 = new TestWidget(&widget); child1->move(20, 20); child1->show(); + QVERIFY(QTest::qWaitForWindowExposed(child1)); QVERIFY(child1->waitForPainted()); QCOMPARE(widget.takePaintedRegions(), QRegion(child1->geometry())); QCOMPARE(child1->takePaintedRegions(), QRegion(child1->rect())); @@ -377,16 +437,26 @@ void tst_QWidgetRepaintManager::opaqueChildren() */ void tst_QWidgetRepaintManager::staticContents() { + const auto *integration = QGuiApplicationPrivate::platformIntegration(); + if (!integration->hasCapability(QPlatformIntegration::BackingStoreStaticContents)) + QSKIP("Platform does not support static backingstore content"); + TestWidget widget; widget.setAttribute(Qt::WA_StaticContents); widget.initialShow(); - const QSize oldSize = widget.size(); + // Trigger resize via QWindow (similar to QWSI code path) + QVERIFY(widget.windowHandle()); + QSize oldSize = widget.size(); + widget.windowHandle()->resize(widget.width(), widget.height() + 10); + QVERIFY(widget.waitForPainted()); + QCOMPARE(widget.takePaintedRegions(), QRegion(0, oldSize.width(), widget.width(), 10)); + // Trigger resize via QWidget + oldSize = widget.size(); widget.resize(widget.width() + 10, widget.height()); - QVERIFY(widget.waitForPainted()); - QEXPECT_FAIL("", "This should just repaint the newly exposed region", Continue); + QEXPECT_FAIL("", "QWidgetPrivate::setGeometry_sys wrongly triggers full update", Continue); QCOMPARE(widget.takePaintedRegions(), QRegion(oldSize.width(), 0, 10, widget.height())); } @@ -427,6 +497,306 @@ void tst_QWidgetRepaintManager::scroll() QCOMPARE(widget.takePaintedRegions(), QRegion()); } +class PaintOnScreenWidget : public TestWidget +{ +public: + using TestWidget::TestWidget; + + // Explicit override to prevent noPaintOnScreen on Windows + QPaintEngine *paintEngine() const override + { + return nullptr; + } +}; + +void tst_QWidgetRepaintManager::paintOnScreenUpdates() +{ + { + TestWidget topLevel; + topLevel.setObjectName("TopLevel"); + topLevel.resize(500, 500); + TestWidget renderToTextureWidget(&topLevel); + renderToTextureWidget.setObjectName("RenderToTexture"); + renderToTextureWidget.setGeometry(0, 0, 200, 200); + QWidgetPrivate::get(&renderToTextureWidget)->setRenderToTexture(); + + PaintOnScreenWidget paintOnScreenWidget(&topLevel); + paintOnScreenWidget.setObjectName("PaintOnScreen"); + paintOnScreenWidget.setGeometry(200, 200, 300, 300); + + topLevel.initialShow(); + + // Updating before toggling WA_PaintOnScreen should work fine + paintOnScreenWidget.update(); + paintOnScreenWidget.waitForPainted(); + QVERIFY(paintOnScreenWidget.waitForPainted()); + +#ifdef Q_OS_ANDROID + QEXPECT_FAIL("", "This test fails on Android", Abort); +#endif + QCOMPARE(paintOnScreenWidget.takePaintedRegions(), paintOnScreenWidget.rect()); + + renderToTextureWidget.update(); + QVERIFY(renderToTextureWidget.waitForPainted()); + QCOMPARE(renderToTextureWidget.takePaintedRegions(), renderToTextureWidget.rect()); + + // Then toggle WA_PaintOnScreen + paintOnScreenWidget.setAttribute(Qt::WA_PaintOnScreen); + + // The render-to-texture widget updates fine + renderToTextureWidget.update(); + QVERIFY(renderToTextureWidget.waitForPainted()); + QCOMPARE(renderToTextureWidget.takePaintedRegions(), renderToTextureWidget.rect()); + + // Updating the paint-on-screen texture widget will not result + // in a paint event, but should result in an update request. + paintOnScreenWidget.updateRequests = 0; + paintOnScreenWidget.update(); + QVERIFY(QTest::qWaitFor([&]{ return paintOnScreenWidget.updateRequests > 0; })); + + // And should not prevent the render-to-texture widget from receiving updates + renderToTextureWidget.update(); + QVERIFY(renderToTextureWidget.waitForPainted()); + QCOMPARE(renderToTextureWidget.takePaintedRegions(), renderToTextureWidget.rect()); + } + + { + TestWidget paintOnScreenTopLevel; + paintOnScreenTopLevel.setObjectName("PaintOnScreenTopLevel"); + paintOnScreenTopLevel.setAttribute(Qt::WA_PaintOnScreen); + + paintOnScreenTopLevel.initialShow(); + + paintOnScreenTopLevel.updateRequests = 0; + paintOnScreenTopLevel.update(); + QVERIFY(QTest::qWaitFor([&]{ return paintOnScreenTopLevel.updateRequests > 0; })); + + // Turn off paint on screen and make it a render-to-texture widget. + // This will lead us into a QWidgetRepaintManager::markDirty() code + // path that checks updateRequestSent, which is still set from the + // update above since paint-on-screen handling doesn't reset it. + paintOnScreenTopLevel.setAttribute(Qt::WA_PaintOnScreen, false); + QWidgetPrivate::get(&paintOnScreenTopLevel)->setRenderToTexture(); + paintOnScreenTopLevel.update(); + QVERIFY(QTest::qWaitFor([&]{ return paintOnScreenTopLevel.updateRequests > 1; })); + } +} + +class RhiWidgetPrivate : public QWidgetPrivate +{ +public: + RhiWidgetPrivate(const QPlatformBackingStoreRhiConfig &config) + : config(config) + { + } + + QPlatformBackingStoreRhiConfig rhiConfig() const override + { + return config; + } + + QPlatformBackingStoreRhiConfig config = QPlatformBackingStoreRhiConfig::Null; +}; + +class RhiWidget : public QWidget +{ +public: + RhiWidget(const QPlatformBackingStoreRhiConfig &config = QPlatformBackingStoreRhiConfig::Null, QWidget *parent = nullptr) + : QWidget(*new RhiWidgetPrivate(config), parent, {}) + { + } +}; + +void tst_QWidgetRepaintManager::evaluateRhi() +{ + const auto *integration = QGuiApplicationPrivate::platformIntegration(); + if (!integration->hasCapability(QPlatformIntegration::RhiBasedRendering)) + QSKIP("Platform does not support RHI based rendering"); + + // We need full control over whether widgets are native or not + const bool nativeSiblingsOriginal = qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true); + auto nativeSiblingGuard = qScopeGuard([&]{ + qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, nativeSiblingsOriginal); + }); + + auto defaultSurfaceType = QSurface::RasterSurface; + bool usesRhiBackingStore = false; + + { + // Plain QWidget doesn't enable RHI + QWidget regularWidget; + regularWidget.show(); + QVERIFY(QTest::qWaitForWindowExposed(®ularWidget)); + QVERIFY(!QWidgetPrivate::get(®ularWidget)->usesRhiFlush); + + // The platform might use a non-raster surface type if it uses + // an RHI backingstore by default (e.g. Android, iOS, QNX). + defaultSurfaceType = regularWidget.windowHandle()->surfaceType(); + + // Record whether the platform uses an RHI backingstore, + // so we can opt out of some tests further down. + if (defaultSurfaceType != QSurface::RasterSurface) + usesRhiBackingStore = QWidgetPrivate::get(®ularWidget)->rhi(); + else + QVERIFY(!QWidgetPrivate::get(®ularWidget)->rhi()); + } + + { + // But a top level RHI widget does + RhiWidget rhiWidget; + rhiWidget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&rhiWidget)); + QVERIFY(QWidgetPrivate::get(&rhiWidget)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&rhiWidget)->rhi()); + } + +#if QT_CONFIG(opengl) + { + // Non-native child RHI widget enables RHI for top level regular widget + QWidget topLevel; + RhiWidget rhiWidget(QPlatformBackingStoreRhiConfig::OpenGL, &topLevel); + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + QCOMPARE(topLevel.windowHandle()->surfaceType(), QSurface::OpenGLSurface); + QVERIFY(QWidgetPrivate::get(&topLevel)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&topLevel)->rhi()); + // Only the native widget that actually flushes will report usesRhiFlush + QVERIFY(!QWidgetPrivate::get(&rhiWidget)->usesRhiFlush); + // But it should have an RHI it can use + QVERIFY(QWidgetPrivate::get(&rhiWidget)->rhi()); + } + + { + // Native child RHI widget does not enable RHI for top level + QWidget topLevel; + RhiWidget nativeRhiWidget(QPlatformBackingStoreRhiConfig::OpenGL, &topLevel); + nativeRhiWidget.setAttribute(Qt::WA_NativeWindow); + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + QCOMPARE(nativeRhiWidget.windowHandle()->surfaceType(), QSurface::OpenGLSurface); + QVERIFY(QWidgetPrivate::get(&nativeRhiWidget)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&nativeRhiWidget)->rhi()); + QCOMPARE(topLevel.windowHandle()->surfaceType(), defaultSurfaceType); + QVERIFY(!QWidgetPrivate::get(&topLevel)->usesRhiFlush); + + if (!usesRhiBackingStore) + QVERIFY(!QWidgetPrivate::get(&topLevel)->rhi()); + } + + { + // Non-native RHI child of native child enables RHI for native child, + // but not top level. + QWidget topLevel; + QWidget nativeChild(&topLevel); + nativeChild.setAttribute(Qt::WA_NativeWindow); + RhiWidget rhiWidget(QPlatformBackingStoreRhiConfig::OpenGL, &nativeChild); + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + + QCOMPARE(nativeChild.windowHandle()->surfaceType(), QSurface::OpenGLSurface); + QVERIFY(QWidgetPrivate::get(&nativeChild)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&nativeChild)->rhi()); + QVERIFY(!QWidgetPrivate::get(&rhiWidget)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&rhiWidget)->rhi()); + QCOMPARE(topLevel.windowHandle()->surfaceType(), defaultSurfaceType); + QVERIFY(!QWidgetPrivate::get(&topLevel)->usesRhiFlush); + if (!usesRhiBackingStore) + QVERIFY(!QWidgetPrivate::get(&topLevel)->rhi()); + } + + { + // Native child RHI widget does not prevent RHI for top level + // if non-native RHI child widget is also present. + QWidget topLevel; + RhiWidget rhiWidget(QPlatformBackingStoreRhiConfig::OpenGL, &topLevel); + RhiWidget nativeRhiWidget(QPlatformBackingStoreRhiConfig::OpenGL, &topLevel); + nativeRhiWidget.setAttribute(Qt::WA_NativeWindow); + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + + QCOMPARE(nativeRhiWidget.windowHandle()->surfaceType(), QSurface::OpenGLSurface); + QVERIFY(QWidgetPrivate::get(&nativeRhiWidget)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&nativeRhiWidget)->rhi()); + QVERIFY(!QWidgetPrivate::get(&rhiWidget)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&rhiWidget)->rhi()); + QCOMPARE(topLevel.windowHandle()->surfaceType(), QSurface::OpenGLSurface); + QVERIFY(QWidgetPrivate::get(&topLevel)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&topLevel)->rhi()); + } + + { + // Reparenting into a window that already matches the required + // surface type should still mark the parent as flushing with RHI. + QWidget topLevel; + + RhiWidget rhiWidget(QPlatformBackingStoreRhiConfig::Null); + rhiWidget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&rhiWidget)); + QVERIFY(QWidgetPrivate::get(&rhiWidget)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&rhiWidget)->rhi()); + + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + rhiWidget.setParent(&topLevel); + QVERIFY(QWidgetPrivate::get(&topLevel)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&topLevel)->rhi()); + } + + { + // Non-native RHI child of native child enables RHI for native child, + // but does not prevent top level from flushing with RHI. + QWidget topLevel; + QWidget nativeChild(&topLevel); + nativeChild.setAttribute(Qt::WA_NativeWindow); + RhiWidget rhiGranchild(QPlatformBackingStoreRhiConfig::OpenGL, &nativeChild); + RhiWidget rhiChild(QPlatformBackingStoreRhiConfig::OpenGL, &topLevel); + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + + QCOMPARE(nativeChild.windowHandle()->surfaceType(), QSurface::OpenGLSurface); + QVERIFY(QWidgetPrivate::get(&nativeChild)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&nativeChild)->rhi()); + QVERIFY(!QWidgetPrivate::get(&rhiGranchild)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&rhiGranchild)->rhi()); + QCOMPARE(topLevel.windowHandle()->surfaceType(), QSurface::OpenGLSurface); + QVERIFY(QWidgetPrivate::get(&topLevel)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&topLevel)->rhi()); + QVERIFY(!QWidgetPrivate::get(&rhiChild)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&rhiChild)->rhi()); + } + +#if QT_CONFIG(metal) + QRhiMetalInitParams metalParams; + if (QRhi::probe(QRhi::Metal, &metalParams)) { + // Native RHI childen allows mixing RHI backends + QWidget topLevel; + RhiWidget openglWidget(QPlatformBackingStoreRhiConfig::OpenGL, &topLevel); + openglWidget.setAttribute(Qt::WA_NativeWindow); + RhiWidget metalWidget(QPlatformBackingStoreRhiConfig::Metal, &topLevel); + metalWidget.setAttribute(Qt::WA_NativeWindow); + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + + QCOMPARE(topLevel.windowHandle()->surfaceType(), defaultSurfaceType); + QVERIFY(!QWidgetPrivate::get(&topLevel)->usesRhiFlush); + if (!usesRhiBackingStore) + QVERIFY(!QWidgetPrivate::get(&topLevel)->rhi()); + + QCOMPARE(openglWidget.windowHandle()->surfaceType(), QSurface::OpenGLSurface); + QVERIFY(QWidgetPrivate::get(&openglWidget)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&openglWidget)->rhi()); + + QCOMPARE(metalWidget.windowHandle()->surfaceType(), QSurface::MetalSurface); + QVERIFY(QWidgetPrivate::get(&metalWidget)->usesRhiFlush); + QVERIFY(QWidgetPrivate::get(&metalWidget)->rhi()); + + QVERIFY(QWidgetPrivate::get(&openglWidget)->rhi() != QWidgetPrivate::get(&metalWidget)->rhi()); + } +#endif // QT_CONFIG(metal) + +#endif // QT_CONFIG(opengl) +} #if defined(QT_BUILD_INTERNAL) @@ -447,6 +817,8 @@ void tst_QWidgetRepaintManager::scrollWithOverlap() : QWidget(parent, Qt::WindowStaysOnTopHint) { m_scrollArea = new QScrollArea(this); + m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QWidget *w = new QWidget; w->setPalette(QPalette(Qt::gray)); w->setAutoFillBackground(true); @@ -594,6 +966,7 @@ void tst_QWidgetRepaintManager::fastMove() QCOMPARE(dirtyRegion(scene.yellowChild), QRect(0, 0, 100, 100)); } QCOMPARE(dirtyRegion(&scene), QRect(0, 0, 25, 100)); + QTRY_VERIFY(dirtyRegion(&scene).isEmpty()); QVERIFY(compareWidget(&scene)); } diff --git a/tests/auto/widgets/kernel/qwidgetsvariant/CMakeLists.txt b/tests/auto/widgets/kernel/qwidgetsvariant/CMakeLists.txt index 9e6d763d0a..bb3c1e2ad6 100644 --- a/tests/auto/widgets/kernel/qwidgetsvariant/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qwidgetsvariant/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qwidgetsvariant.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qwidgetsvariant Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qwidgetsvariant LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qwidgetsvariant SOURCES tst_qwidgetsvariant.cpp diff --git a/tests/auto/widgets/kernel/qwidgetsvariant/tst_qwidgetsvariant.cpp b/tests/auto/widgets/kernel/qwidgetsvariant/tst_qwidgetsvariant.cpp index bb30f3fd43..0a03fb9e1d 100644 --- a/tests/auto/widgets/kernel/qwidgetsvariant/tst_qwidgetsvariant.cpp +++ b/tests/auto/widgets/kernel/qwidgetsvariant/tst_qwidgetsvariant.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/kernel/qwindowcontainer/CMakeLists.txt b/tests/auto/widgets/kernel/qwindowcontainer/CMakeLists.txt index 619ca34b9b..787505972f 100644 --- a/tests/auto/widgets/kernel/qwindowcontainer/CMakeLists.txt +++ b/tests/auto/widgets/kernel/qwindowcontainer/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qwindowcontainer.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qwindowcontainer Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qwindowcontainer LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qwindowcontainer SOURCES tst_qwindowcontainer.cpp diff --git a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp index 19c9606d79..52aaf094b4 100644 --- a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp +++ b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -7,12 +7,14 @@ #include <qapplication.h> #include <qwindow.h> #include <qwidget.h> +#include <qlineedit.h> #include <qdockwidget.h> #include <qmainwindow.h> #include <qscreen.h> #include <qscopedpointer.h> #include <qevent.h> +#include <qboxlayout.h> class Window : public QWindow @@ -46,6 +48,7 @@ public: private slots: void testShow(); void testPositionAndSize(); + void testSizeHints(); void testExposeObscure(); void testOwnership(); void testBehindTheScenesDeletion(); @@ -57,6 +60,8 @@ private slots: void testDockWidget(); void testNativeContainerParent(); void testPlatformSurfaceEvent(); + void embedWidgetWindow(); + void testFocus(); void cleanup(); private: @@ -108,7 +113,29 @@ void tst_QWindowContainer::testPositionAndSize() QCOMPARE(window->height(), container->height()); } +void tst_QWindowContainer::testSizeHints() +{ + QScopedPointer<QWidget> tlw(new QWidget); + QWindow *window = new QWindow(); + window->setMinimumSize(QSize(200, 200)); + window->setGeometry(m_availableGeometry.x() + 300, m_availableGeometry.y() + 400, 500, 600); + + QScopedPointer<QWidget> container(QWidget::createWindowContainer(window)); + container->setWindowTitle(QTest::currentTestFunction()); + QVBoxLayout *vbox = new QVBoxLayout(tlw.data()); + vbox->addWidget(container.data()); + vbox->setContentsMargins(0, 0, 0, 0); + + // Size hints should work regardless of visibility + QCOMPARE(container->minimumSizeHint(), window->minimumSize()); + QCOMPARE(vbox->minimumSize(), window->minimumSize()); + + // Respect dynamic updates + window->setMinimumSize(QSize(210, 210)); + QCOMPARE(container->minimumSizeHint(), window->minimumSize()); + QCOMPARE(vbox->minimumSize(), window->minimumSize()); +} void tst_QWindowContainer::testExposeObscure() { @@ -410,6 +437,99 @@ void tst_QWindowContainer::testPlatformSurfaceEvent() QVERIFY(ok); } +void tst_QWindowContainer::embedWidgetWindow() +{ + { + QWidget parent; + QWidget *widget = new QWidget; + widget->show(); + QVERIFY(QTest::qWaitForWindowExposed(widget)); + QVERIFY(widget->windowHandle()); + QPointer<QWindow> widgetWindow = widget->windowHandle(); + auto *container = QWidget::createWindowContainer(widgetWindow, &parent); + QCOMPARE(container, widget); + QCOMPARE(widget->parent(), &parent); + delete widget; + QTRY_VERIFY(widgetWindow.isNull()); + } + + QPointer<QWidget> widget = new QWidget; + QPointer<QWindow> widgetWindow; + { + QWidget parent; + widget->show(); + QVERIFY(QTest::qWaitForWindowExposed(widget)); + QVERIFY(widget->windowHandle()); + widgetWindow = widget->windowHandle(); + auto *container = QWidget::createWindowContainer(widgetWindow, &parent); + QCOMPARE(container, widget); + QCOMPARE(widget->parent(), &parent); + } + QTRY_VERIFY(widget.isNull()); + QTRY_VERIFY(widgetWindow.isNull()); + +} + +void tst_QWindowContainer::testFocus() +{ + QWidget root; + root.setGeometry(m_availableGeometry); + + QLineEdit *lineEdit = new QLineEdit(&root); + lineEdit->setGeometry(0, 0, m_availableGeometry.width() * 0.1, 17); + lineEdit->setFocusPolicy(Qt::FocusPolicy::StrongFocus); + + QWindow *embedded = new QWindow(); + QWidget *container = QWidget::createWindowContainer(embedded, &root); + container->setGeometry(0, lineEdit->height() + 10, m_availableGeometry.width() * 0.2, m_availableGeometry.height() - (lineEdit->height() + 10)); + container->setFocusPolicy(Qt::StrongFocus); + + root.show(); + QVERIFY(QTest::qWaitForWindowExposed(&root)); + lineEdit->setFocus(); + QTRY_VERIFY(lineEdit->hasFocus()); + QCOMPARE(QGuiApplication::focusWindow(), root.windowHandle()); + QCOMPARE(QApplication::focusWidget(), lineEdit); + + // embedded window gets focused because of mouse click + QPoint embeddedCenter = container->rect().center(); + QTest::mousePress(root.windowHandle(), Qt::LeftButton, {}, embeddedCenter); + QVERIFY(QTest::qWaitForWindowFocused(embedded)); + QVERIFY(container->hasFocus()); + QCOMPARE(QGuiApplication::focusWindow(), embedded); + QCOMPARE(QApplication::focusWidget(), container); + QVERIFY(!lineEdit->hasFocus()); + + QTest::mouseClick(lineEdit, Qt::LeftButton, {}); + QVERIFY(QTest::qWaitForWindowFocused(root.windowHandle())); + QCOMPARE(QGuiApplication::focusWindow(), root.windowHandle()); + QCOMPARE(QApplication::focusWidget(), lineEdit); + QVERIFY(lineEdit->hasFocus()); + + // embedded window gets focused because of Tab key event + QTest::keyClick(root.windowHandle(), Qt::Key_Tab); + QVERIFY(QTest::qWaitForWindowFocused(embedded)); + QVERIFY(container->hasFocus()); + QCOMPARE(QGuiApplication::focusWindow(), embedded); + QCOMPARE(QApplication::focusWidget(), container); + QVERIFY(!lineEdit->hasFocus()); + // A key tab event sent to the root window should cause + // the nextInFocusChain of the window container to get focused + QTest::keyClick(root.windowHandle(), Qt::Key_Tab); + QVERIFY(QTest::qWaitForWindowFocused(root.windowHandle())); + QCOMPARE(QGuiApplication::focusWindow(), root.windowHandle()); + QCOMPARE(QApplication::focusWidget(), lineEdit); + QVERIFY(lineEdit->hasFocus()); + + // embedded window gets focused programmatically + embedded->requestActivate(); + QVERIFY(QTest::qWaitForWindowFocused(embedded)); + QVERIFY(container->hasFocus()); + QCOMPARE(QGuiApplication::focusWindow(), embedded); + QCOMPARE(QApplication::focusWidget(), container); + QVERIFY(!lineEdit->hasFocus()); +} + QTEST_MAIN(tst_QWindowContainer) #include "tst_qwindowcontainer.moc" diff --git a/tests/auto/widgets/styles/CMakeLists.txt b/tests/auto/widgets/styles/CMakeLists.txt index c945dbc1f5..a957dfd373 100644 --- a/tests/auto/widgets/styles/CMakeLists.txt +++ b/tests/auto/widgets/styles/CMakeLists.txt @@ -1,7 +1,5 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from styles.pro. +# SPDX-License-Identifier: BSD-3-Clause if(APPLE) add_subdirectory(qmacstyle) diff --git a/tests/auto/widgets/styles/qmacstyle/CMakeLists.txt b/tests/auto/widgets/styles/qmacstyle/CMakeLists.txt index 9151b4bb8c..861a327418 100644 --- a/tests/auto/widgets/styles/qmacstyle/CMakeLists.txt +++ b/tests/auto/widgets/styles/qmacstyle/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qmacstyle.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qmacstyle Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmacstyle LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qmacstyle SOURCES tst_qmacstyle.cpp diff --git a/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp b/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp index 458a108538..9cfd50bc08 100644 --- a/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp +++ b/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/styles/qstyle/CMakeLists.txt b/tests/auto/widgets/styles/qstyle/CMakeLists.txt index e2fe075941..2c617ebe49 100644 --- a/tests/auto/widgets/styles/qstyle/CMakeLists.txt +++ b/tests/auto/widgets/styles/qstyle/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qstyle.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qstyle Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qstyle LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qstyle SOURCES tst_qstyle.cpp diff --git a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp index fc182ae0f2..95e24da21d 100644 --- a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp +++ b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -633,7 +633,7 @@ void tst_QStyle::testStyleOptionInit() QStringList keys = QStyleFactory::keys(); keys.prepend(QString()); // QCommonStyle marker - for (const QString &key : qAsConst(keys)) { + for (const QString &key : std::as_const(keys)) { QStyle* style = key.isEmpty() ? new QCommonStyle : QStyleFactory::create(key); TestStyleOptionInitProxy testStyle; testStyle.setBaseStyle(style); diff --git a/tests/auto/widgets/styles/qstyleoption/CMakeLists.txt b/tests/auto/widgets/styles/qstyleoption/CMakeLists.txt index ec6304d469..e0a4cc38e2 100644 --- a/tests/auto/widgets/styles/qstyleoption/CMakeLists.txt +++ b/tests/auto/widgets/styles/qstyleoption/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qstyleoption.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qstyleoption Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qstyleoption LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qstyleoption SOURCES tst_qstyleoption.cpp @@ -14,6 +18,3 @@ qt_internal_add_test(tst_qstyleoption Qt::Gui Qt::Widgets ) - -#### Keys ignored in scope 1:.:.:qstyleoption.pro:<TRUE>: -# TEMPLATE = "app" diff --git a/tests/auto/widgets/styles/qstyleoption/tst_qstyleoption.cpp b/tests/auto/widgets/styles/qstyleoption/tst_qstyleoption.cpp index 1d20a9a42b..f173c9a8df 100644 --- a/tests/auto/widgets/styles/qstyleoption/tst_qstyleoption.cpp +++ b/tests/auto/widgets/styles/qstyleoption/tst_qstyleoption.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/styles/qstylesheetstyle/CMakeLists.txt b/tests/auto/widgets/styles/qstylesheetstyle/CMakeLists.txt index 2fd93d5f46..6543ec9961 100644 --- a/tests/auto/widgets/styles/qstylesheetstyle/CMakeLists.txt +++ b/tests/auto/widgets/styles/qstylesheetstyle/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qstylesheetstyle.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qstylesheetstyle Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qstylesheetstyle LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Resources: set(resources_resource_files "images/testimage.png" @@ -26,5 +30,4 @@ qt_internal_add_test(tst_qstylesheetstyle BUILTIN_TESTDATA ) -#### Keys ignored in scope 1:.:.:qstylesheetstyle.pro:<TRUE>: # _REQUIREMENTS = "qtConfig(private_tests)" diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp index 82d48b1692..a9a1817b8a 100644 --- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp +++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtWidgets/QApplication> #include <QtWidgets/QCheckBox> @@ -38,6 +38,8 @@ #include <private/qstylesheetstyle_p.h> #include <private/qhighdpiscaling_p.h> #include <QtTest/private/qtesthelpers_p.h> +#include <qpa/qplatformtheme.h> +#include <QtWidgets/private/qapplication_p.h> using namespace QTestPrivate; @@ -92,6 +94,7 @@ private slots: void proxyStyle(); void dialogButtonBox(); void emptyStyleSheet(); + void toolTip_data(); void toolTip(); void embeddedFonts(); void opaquePaintEvent_data(); @@ -104,6 +107,7 @@ private slots: void QTBUG36933_brokenPseudoClassLookup(); void styleSheetChangeBeforePolish(); void placeholderColor(); + void accent(); void enumPropertySelector_data(); void enumPropertySelector(); //at the end because it mess with the style. @@ -118,6 +122,8 @@ private slots: void iconSizes_data(); void iconSizes(); + void inheritWidgetPalette_data(); + void inheritWidgetPalette(); private: static QColor COLOR(const QWidget &w) @@ -974,7 +980,6 @@ void tst_QStyleSheetStyle::focusColors() centerOnScreen(&frame); frame.show(); - QApplication::setActiveWindow(&frame); QVERIFY(QTest::qWaitForWindowActive(&frame)); for (QWidget *widget : frame.widgets()) { @@ -1020,7 +1025,6 @@ void tst_QStyleSheetStyle::hoverColors() QCursor::setPos(frame.geometry().topLeft() - QPoint(100, 0)); frame.show(); - QApplication::setActiveWindow(&frame); QVERIFY(QTest::qWaitForWindowActive(&frame)); QWindow *frameWindow = frame.windowHandle(); @@ -1653,19 +1657,32 @@ private: const QString m_oldStyleName; }; +void tst_QStyleSheetStyle::toolTip_data() +{ + QTest::addColumn<QString>("style"); + + QTest::newRow("fusion") << QString("Fusion"); +#ifdef Q_OS_WINDOWS + QTest::newRow("windowsvista") << QString("WindowsVista"); +#endif +} + void tst_QStyleSheetStyle::toolTip() { + QFETCH(QString, style); + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) QSKIP("Wayland: This fails. Figure out why."); - qApp->setStyleSheet(QString()); QWidget w; w.resize(m_testSize); w.setWindowTitle(QTest::currentTestFunction()); + // Use "Fusion" to prevent the Vista style from clobbering the tooltip palette in polish(). - QStyle *fusionStyle = QStyleFactory::create(QLatin1String("Fusion")); - QVERIFY(fusionStyle); - ApplicationStyleSetter as(fusionStyle); + QStyle *appStyle = QStyleFactory::create(style); + QVERIFY(appStyle); + ApplicationStyleSetter as(appStyle); + QHBoxLayout layout(&w); w.setLayout(&layout); @@ -1693,37 +1710,65 @@ void tst_QStyleSheetStyle::toolTip() wid4->setToolTip("this is wid4"); wid4->setObjectName("wid4"); + QWidget *wid5 = new QPushButton("wid5", &w); + layout.addWidget(wid5); + wid5->setStyleSheet("QToolTip { background: #ff0; color: #f00 }"); + wid5->setToolTip("this is wid5"); + wid5->setObjectName("wid5"); + centerOnScreen(&w); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); - const QColor normalToolTip = QToolTip::palette().color(QPalette::Inactive, QPalette::ToolTipBase); + QColor normalToolTipBgColor = QToolTip::palette().color(QPalette::Inactive, QPalette::ToolTipBase); + +#ifdef Q_OS_MACOS + // macOS uses tool tip text color set in label palette + const QPalette *labelPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::LabelPalette); + QColor normalToolTipFgColor = labelPalette->color(QPalette::Inactive, QPalette::ToolTipText); +#else + QColor normalToolTipFgColor = QToolTip::palette().color(QPalette::Inactive, QPalette::ToolTipText); +#endif + // Tooltip on the widget without stylesheet, then to other widget, // including one without stylesheet (the tooltip will be reused, // but its color must change) - const QWidgetList widgets{wid4, wid1, wid2, wid3, wid4}; - const QList<QColor> colors { normalToolTip, QColor("#ae2"), QColor("#f81"), QColor("#0b8"), - normalToolTip }; + const QWidgetList widgets{wid4, wid1, wid2, wid3, wid4, wid5}; + const QList<QColor> bgcolors { normalToolTipBgColor, QColor("#ae2"), QColor("#f81"), + QColor("#0b8"), normalToolTipBgColor, QColor("#ff0")}; + const QList<QColor> fgcolors { normalToolTipFgColor, normalToolTipFgColor, normalToolTipFgColor, + normalToolTipFgColor, normalToolTipFgColor, QColor("#f00")}; QWidgetList topLevels; - for (int i = 0; i < widgets.count() ; ++i) { + for (int i = 0; i < widgets.size() ; ++i) { QWidget *wid = widgets.at(i); - QColor col = colors.at(i); + QColor bgColor = bgcolors.at(i); + QColor fgColor = fgcolors.at(i); QToolTip::showText( QPoint(0,0) , "This is " + wid->objectName(), wid); topLevels = QApplication::topLevelWidgets(); QWidget *tooltip = nullptr; - for (QWidget *widget : qAsConst(topLevels)) { + for (QWidget *widget : std::as_const(topLevels)) { if (widget->inherits("QTipLabel")) { tooltip = widget; break; } } + QVERIFY(tooltip); QTRY_VERIFY(tooltip->isVisible()); // Wait until Roll-Effect is finished (Windows Vista) - QCOMPARE(tooltip->palette().color(tooltip->backgroundRole()), col); + +#ifdef Q_OS_WINDOWS + // If tooltip palette contains empty resolve mask, validate with inherited palette + if (!tooltip->palette().resolveMask()) { + bgColor = w.palette().color(tooltip->backgroundRole()); + fgColor = w.palette().color(tooltip->foregroundRole()); + } +#endif + + QCOMPARE(tooltip->palette().color(tooltip->backgroundRole()), bgColor); + QCOMPARE(tooltip->palette().color(tooltip->foregroundRole()), fgColor); } QToolTip::showText( QPoint(0,0) , "This is " + wid3->objectName(), wid3); @@ -1731,7 +1776,7 @@ void tst_QStyleSheetStyle::toolTip() delete wid3; //should not crash; QTest::qWait(10); topLevels = QApplication::topLevelWidgets(); - for (QWidget *widget : qAsConst(topLevels)) + for (QWidget *widget : std::as_const(topLevels)) widget->update(); //should not crash either } @@ -1841,7 +1886,6 @@ void tst_QStyleSheetStyle::complexWidgetFocus() centerOnScreen(&frame); frame.show(); - QApplication::setActiveWindow(&frame); QVERIFY(QTest::qWaitForWindowActive(&frame)); for (QWidget *widget : widgets) { widget->setFocus(); @@ -1930,7 +1974,6 @@ void tst_QStyleSheetStyle::task232085_spinBoxLineEditBg() centerOnScreen(&frame); frame.show(); - QApplication::setActiveWindow(&frame); spinbox->setFocus(); QVERIFY(QTest::qWaitForWindowActive(&frame)); @@ -2066,7 +2109,6 @@ void tst_QStyleSheetStyle::QTBUG36933_brokenPseudoClassLookup() QVERIFY(QTest::qWaitForWindowExposed(&widget)); widget.activateWindow(); - QApplication::setActiveWindow(&widget); QVERIFY(QTest::qWaitForWindowActive(&widget)); QHeaderView *verticalHeader = widget.verticalHeader(); @@ -2339,11 +2381,32 @@ void tst_QStyleSheetStyle::placeholderColor() QLineEdit le2; le2.setEnabled(false); le1.ensurePolished(); - QCOMPARE(le1.palette().placeholderText(), red); + QColor phColor = le1.palette().placeholderText().color(); + QCOMPARE(phColor.rgb(), red.rgb()); + QVERIFY(phColor.alpha() < red.alpha()); + le2.ensurePolished(); - QCOMPARE(le2.palette().placeholderText(), red); + phColor = le2.palette().placeholderText().color(); + QCOMPARE(phColor.rgb(), red.rgb()); + QVERIFY(phColor.alpha() < red.alpha()); + le2.setEnabled(true); - QCOMPARE(le2.palette().placeholderText(), red); + phColor = le2.palette().placeholderText().color(); + QCOMPARE(phColor.rgb(), red.rgb()); + QVERIFY(phColor.alpha() < red.alpha()); + + const char *phSpec = "#aabbccdd"; + le1.setStyleSheet(QString("QLineEdit { placeholder-text-color: %1; }").arg(phSpec)); + QCOMPARE(le1.palette().placeholderText().color(), QColor(phSpec)); +} + +void tst_QStyleSheetStyle::accent() +{ + QLineEdit lineEdit; + const QColor universe(42, 42, 42); + lineEdit.setStyleSheet(QString("QLineEdit { accent-color: %1; }").arg(universe.name())); + lineEdit.ensurePolished(); + QCOMPARE(lineEdit.palette().accent().color(), universe); } void tst_QStyleSheetStyle::enumPropertySelector_data() @@ -2440,6 +2503,31 @@ void tst_QStyleSheetStyle::iconSizes() QCOMPARE(button.iconSize(), iconSize); } +void tst_QStyleSheetStyle::inheritWidgetPalette_data() +{ + QTest::addColumn<const QString>("styleSheet"); + QTest::addColumn<const QColor>("phColorPalette"); + + QTest::addRow("blueAndGreen") << "QLineEdit {color: rgb(0,0,255);}" << QColor(Qt::green); + QTest::addRow("emptyStyleSheet") << QString() << QColor(Qt::green); + +} + +void tst_QStyleSheetStyle::inheritWidgetPalette() +{ + QFETCH(const QString, styleSheet); + QFETCH(const QColor, phColorPalette); + + QLineEdit edit; + QPalette palette = edit.palette(); + palette.setBrush(QPalette::PlaceholderText, phColorPalette); + edit.setPalette(palette); + edit.setStyleSheet(styleSheet); + const QColor phColor = edit.palette().placeholderText().color(); + + QCOMPARE(phColor, phColorPalette); +} + QTEST_MAIN(tst_QStyleSheetStyle) #include "tst_qstylesheetstyle.moc" diff --git a/tests/auto/widgets/util/CMakeLists.txt b/tests/auto/widgets/util/CMakeLists.txt index 24d0084b8b..31725573c7 100644 --- a/tests/auto/widgets/util/CMakeLists.txt +++ b/tests/auto/widgets/util/CMakeLists.txt @@ -1,7 +1,5 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from util.pro. +# SPDX-License-Identifier: BSD-3-Clause add_subdirectory(qcompleter) add_subdirectory(qscroller) diff --git a/tests/auto/widgets/util/qcompleter/BLACKLIST b/tests/auto/widgets/util/qcompleter/BLACKLIST index 367270fdf2..5487a1fe44 100644 --- a/tests/auto/widgets/util/qcompleter/BLACKLIST +++ b/tests/auto/widgets/util/qcompleter/BLACKLIST @@ -1,6 +1,2 @@ [QTBUG_14292_filesystem] -ubuntu-16.04 opensuse-leap -rhel-7.4 -rhel-6.6 -opensuse-42.3 diff --git a/tests/auto/widgets/util/qcompleter/CMakeLists.txt b/tests/auto/widgets/util/qcompleter/CMakeLists.txt index 389de04aff..a96945771f 100644 --- a/tests/auto/widgets/util/qcompleter/CMakeLists.txt +++ b/tests/auto/widgets/util/qcompleter/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qcompleter.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qcompleter Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qcompleter LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qcompleter SOURCES tst_qcompleter.cpp @@ -14,7 +18,5 @@ qt_internal_add_test(tst_qcompleter Qt::Gui Qt::TestPrivate Qt::Widgets + Qt::WidgetsPrivate ) - -#### Keys ignored in scope 1:.:.:qcompleter.pro:<TRUE>: -# TEMPLATE = "app" diff --git a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp index 92158190b8..b2e77bc935 100644 --- a/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp +++ b/tests/auto/widgets/util/qcompleter/tst_qcompleter.cpp @@ -1,11 +1,10 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QtGui> #include <QtWidgets> #include <QtDebug> -#include <QPair> #include <QList> #include <QPointer> #include <QSignalSpy> @@ -16,6 +15,8 @@ #include <memory> +#include <QtWidgets/private/qapplication_p.h> + Q_DECLARE_METATYPE(QCompleter::CompletionMode) using namespace QTestPrivate; @@ -57,7 +58,7 @@ QString CsvCompleter::pathFromIndex(const QModelIndex &sourceIndex) const idx = parent.sibling(parent.row(), sourceIndex.column()); } while (idx.isValid()); - return list.count() == 1 ? list.constFirst() : list.join(QLatin1Char(',')); + return list.size() == 1 ? list.constFirst() : list.join(QLatin1Char(',')); } class tst_QCompleter : public QObject @@ -108,6 +109,8 @@ private slots: void dynamicSortOrder(); void disabledItems(); + void hideWidget(); + // task-specific tests below me void task178797_activatedOnReturn(); void task189564_omitNonSelectableItems(); @@ -121,6 +124,7 @@ private slots: void QTBUG_52028_tabAutoCompletes(); void QTBUG_51889_activatedSentTwice(); void showPopupInGraphicsView(); + void inheritedEventFilter(); private: void filter(bool assync = false); @@ -1058,7 +1062,6 @@ void tst_QCompleter::multipleWidgets() window.setWindowTitle(QLatin1String(QTest::currentTestFunction())); window.move(200, 200); window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); QFocusEvent focusIn(QEvent::FocusIn); @@ -1070,7 +1073,6 @@ void tst_QCompleter::multipleWidgets() comboBox->setFocus(); comboBox->show(); window.activateWindow(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); QCOMPARE(QApplication::focusWidget(), comboBox); comboBox->lineEdit()->setText("it"); @@ -1105,7 +1107,6 @@ void tst_QCompleter::focusIn() window.move(200, 200); window.show(); window.activateWindow(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); auto comboBox = new QComboBox(&window); @@ -1176,13 +1177,39 @@ void tst_QCompleter::disabledItems() QAbstractItemView *view = lineEdit.completer()->popup(); QVERIFY(view->isVisible()); QTest::mouseClick(view->viewport(), Qt::LeftButton, {}, view->visualRect(view->model()->index(0, 0)).center()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QVERIFY(view->isVisible()); QTest::mouseClick(view->viewport(), Qt::LeftButton, {}, view->visualRect(view->model()->index(1, 0)).center()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QVERIFY(!view->isVisible()); } +void tst_QCompleter::hideWidget() +{ + // hiding the widget should hide/close the popup + QWidget w; + w.setWindowTitle(QLatin1String(QTest::currentTestFunction())); + w.setLayout(new QVBoxLayout); + + QLineEdit edit; + edit.setCompleter(new QCompleter({ "foo", "bar" })); + + w.layout()->addWidget(&edit); + + const auto pos = w.screen()->availableGeometry().topLeft() + QPoint(200, 200); + w.move(pos); + w.show(); + QApplicationPrivate::setActiveWindow(&w); + QVERIFY(QTest::qWaitForWindowActive(&w)); + + // activate the completer + QTest::keyClick(&edit, Qt::Key_F); + QVERIFY(edit.completer()->popup()); + QTRY_VERIFY(edit.completer()->popup()->isVisible()); + edit.hide(); + QVERIFY(!edit.completer()->popup()->isVisible()); +} + void tst_QCompleter::task178797_activatedOnReturn() { if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) @@ -1193,10 +1220,9 @@ void tst_QCompleter::task178797_activatedOnReturn() auto completer = new QCompleter({"foobar1", "foobar2"}, &ledit); ledit.setCompleter(completer); QSignalSpy spy(completer, QOverload<const QString &>::of(&QCompleter::activated)); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); ledit.move(200, 200); ledit.show(); - QApplication::setActiveWindow(&ledit); QVERIFY(QTest::qWaitForWindowActive(&ledit)); QTest::keyClick(&ledit, Qt::Key_F); QCoreApplication::processEvents(); @@ -1205,7 +1231,7 @@ void tst_QCompleter::task178797_activatedOnReturn() QCoreApplication::processEvents(); QTest::keyClick(QApplication::activePopupWidget(), Qt::Key_Return); QCoreApplication::processEvents(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } class task189564_StringListModel : public QStringListModel @@ -1280,14 +1306,13 @@ void tst_QCompleter::task246056_setCompletionPrefix() comboBox.addItem("a2"); comboBox.move(200, 200); comboBox.show(); - QApplication::setActiveWindow(&comboBox); QVERIFY(QTest::qWaitForWindowActive(&comboBox)); QSignalSpy spy(comboBox.completer(), QOverload<const QModelIndex &>::of(&QCompleter::activated)); QTest::keyPress(&comboBox, 'a'); QTest::keyPress(comboBox.completer()->popup(), Qt::Key_Down); QTest::keyPress(comboBox.completer()->popup(), Qt::Key_Down); QTest::keyPress(comboBox.completer()->popup(), Qt::Key_Enter); // don't crash! - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); const auto index = spy.at(0).constFirst().toModelIndex(); QVERIFY(!index.isValid()); } @@ -1346,7 +1371,6 @@ void tst_QCompleter::task250064_lostFocus() task250064_Widget widget; widget.setWindowTitle(QLatin1String(QTest::currentTestFunction())); widget.show(); - QApplication::setActiveWindow(&widget); QVERIFY(QTest::qWaitForWindowActive(&widget)); QTest::keyPress(widget.textEdit(), 'a'); Qt::FocusPolicy origPolicy = widget.textEdit()->focusPolicy(); @@ -1391,7 +1415,6 @@ void tst_QCompleter::task253125_lineEditCompletion() edit.move(200, 200); edit.show(); edit.setFocus(); - QApplication::setActiveWindow(&edit); QVERIFY(QTest::qWaitForWindowActive(&edit)); QTest::keyClick(&edit, 'i'); @@ -1554,7 +1577,6 @@ void tst_QCompleter::task247560_keyboardNavigation() edit.move(200, 200); edit.show(); edit.setFocus(); - QApplication::setActiveWindow(&edit); QVERIFY(QTest::qWaitForWindowActive(&edit)); QTest::keyClick(&edit, 'r'); @@ -1668,7 +1690,6 @@ void tst_QCompleter::QTBUG_14292_filesystem() edit.move(200, 200); edit.show(); - QApplication::setActiveWindow(&edit); QVERIFY(QTest::qWaitForWindowActive(&edit)); QCOMPARE(QApplication::activeWindow(), &edit); edit.setFocus(); @@ -1684,6 +1705,7 @@ void tst_QCompleter::QTBUG_14292_filesystem() QTRY_VERIFY(comp.popup()->isVisible()); QCOMPARE(comp.popup()->model()->rowCount(), 2); QApplication::processEvents(); + QCOMPARE(qApp->focusObject(), &edit); // for QTBUG_108522 QTest::keyClick(&edit, 'h'); QCOMPARE(comp.popup()->model()->rowCount(), 2); QTest::keyClick(&edit, 'e'); @@ -1712,7 +1734,6 @@ void tst_QCompleter::QTBUG_14292_filesystem() QWidget w; w.move(400, 200); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); QVERIFY(!edit.hasFocus() && !comp.popup()->hasFocus()); @@ -1749,7 +1770,7 @@ void tst_QCompleter::QTBUG_52028_tabAutoCompletes() const auto pos = w.screen()->availableGeometry().topLeft() + QPoint(200,200); w.move(pos); w.show(); - QApplication::setActiveWindow(&w); + QApplicationPrivate::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); QSignalSpy activatedSpy(&cbox, &QComboBox::activated); @@ -1761,10 +1782,10 @@ void tst_QCompleter::QTBUG_52028_tabAutoCompletes() QTRY_VERIFY(cbox.completer()->popup()->isVisible()); QTest::keyClick(cbox.completer()->popup(), Qt::Key_Tab); QCOMPARE(cbox.completer()->currentCompletion(), QLatin1String("hux")); - QCOMPARE(activatedSpy.count(), 0); + QCOMPARE(activatedSpy.size(), 0); QEXPECT_FAIL("", "QTBUG-52028 will not be fixed today.", Abort); QCOMPARE(cbox.currentText(), QLatin1String("hux")); - QCOMPARE(activatedSpy.count(), 0); + QCOMPARE(activatedSpy.size(), 0); QVERIFY(!le->hasFocus()); } @@ -1793,7 +1814,6 @@ void tst_QCompleter::QTBUG_51889_activatedSentTwice() const auto pos = w.screen()->availableGeometry().topLeft() + QPoint(200,200); w.move(pos); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); QSignalSpy activatedSpy(&cbox, &QComboBox::activated); @@ -1805,7 +1825,7 @@ void tst_QCompleter::QTBUG_51889_activatedSentTwice() QTRY_VERIFY(cbox.completer()->popup()->isVisible()); QTest::keyClick(cbox.completer()->popup(), Qt::Key_Down); QTest::keyClick(cbox.completer()->popup(), Qt::Key_Return); - QTRY_COMPARE(activatedSpy.count(), 1); + QTRY_COMPARE(activatedSpy.size(), 1); // Navigate + enter activates only once (non-first item) cbox.lineEdit()->clear(); @@ -1815,7 +1835,7 @@ void tst_QCompleter::QTBUG_51889_activatedSentTwice() QTRY_VERIFY(cbox.completer()->popup()->isVisible()); QTest::keyClick(cbox.completer()->popup(), Qt::Key_Down); QTest::keyClick(cbox.completer()->popup(), Qt::Key_Return); - QTRY_COMPARE(activatedSpy.count(), 1); + QTRY_COMPARE(activatedSpy.size(), 1); // Full text + enter activates only once cbox.lineEdit()->clear(); @@ -1824,11 +1844,14 @@ void tst_QCompleter::QTBUG_51889_activatedSentTwice() QVERIFY(cbox.completer()->popup()); QTRY_VERIFY(cbox.completer()->popup()->isVisible()); QTest::keyClick(&cbox, Qt::Key_Return); - QTRY_COMPARE(activatedSpy.count(), 1); + QTRY_COMPARE(activatedSpy.size(), 1); } void tst_QCompleter::showPopupInGraphicsView() { + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Wayland: Skip this test, see also QTBUG-107186"); + QGraphicsView view; QGraphicsScene scene; view.setScene(&scene); @@ -1858,5 +1881,42 @@ void tst_QCompleter::showPopupInGraphicsView() QVERIFY(lineEdit.completer()->popup()->geometry().bottom() < lineEdit.mapToGlobal(QPoint(0, 0)).y()); } +void tst_QCompleter::inheritedEventFilter() +{ + class Completer : public QCompleter + { + public: + explicit Completer(QWidget *parent) : QCompleter(parent) + { + Q_ASSERT(parent); + setPopup(new QListView()); + popup()->installEventFilter(this); + } + + bool m_popupChildAdded = false; + + protected: + bool eventFilter(QObject *watched, QEvent *event) override + { + if (watched == popup() && event->type() == QEvent::ChildAdded) + m_popupChildAdded = true; + + return QCompleter::eventFilter(watched, event); + } + }; + + QComboBox comboBox; + comboBox.setEditable(true); + Completer *completer = new Completer(&comboBox); + comboBox.setCompleter(completer); + + // comboBox.show() must not crash with an infinite loop in the event filter + comboBox.show(); + QVERIFY(QTest::qWaitForWindowExposed(&comboBox)); + + // Since event orders are platform dependent, only the the ChildAdded event is checked. + QVERIFY(QTest::qWaitFor([completer](){return completer->m_popupChildAdded; })); +} + QTEST_MAIN(tst_QCompleter) #include "tst_qcompleter.moc" diff --git a/tests/auto/widgets/util/qscroller/CMakeLists.txt b/tests/auto/widgets/util/qscroller/CMakeLists.txt index 89c402820a..2beee70109 100644 --- a/tests/auto/widgets/util/qscroller/CMakeLists.txt +++ b/tests/auto/widgets/util/qscroller/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qscroller.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qscroller Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qscroller LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qscroller SOURCES tst_qscroller.cpp @@ -14,4 +18,5 @@ qt_internal_add_test(tst_qscroller Qt::Gui Qt::GuiPrivate Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/util/qscroller/tst_qscroller.cpp b/tests/auto/widgets/util/qscroller/tst_qscroller.cpp index 491d5d48e3..101b502fc6 100644 --- a/tests/auto/widgets/util/qscroller/tst_qscroller.cpp +++ b/tests/auto/widgets/util/qscroller/tst_qscroller.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtGui> #include <QtWidgets> @@ -8,6 +8,8 @@ #include <QtGui/private/qeventpoint_p.h> #include <qpa/qwindowsysteminterface.h> +#include <QtWidgets/private/qapplication_p.h> + // #include <QDebug> class tst_QScrollerWidget : public QWidget @@ -103,6 +105,7 @@ private slots: void scroll(); void overshoot(); void multipleWindows(); + void mouseEventTimestamp(); private: QPointingDevice *m_touchScreen = QTest::createTouchDevice(); @@ -321,7 +324,6 @@ void tst_QScroller::scrollTo() { QScopedPointer<tst_QScrollerWidget> sw(new tst_QScrollerWidget); sw->show(); - QApplication::setActiveWindow(sw.data()); if (!QTest::qWaitForWindowExposed(sw.data()) || !QTest::qWaitForWindowActive(sw.data())) QSKIP("Failed to show and activate window"); @@ -353,7 +355,6 @@ void tst_QScroller::scroll() QScroller::grabGesture(sw.data(), QScroller::TouchGesture); sw->setGeometry(100, 100, 400, 300); sw->show(); - QApplication::setActiveWindow(sw.data()); if (!QTest::qWaitForWindowExposed(sw.data()) || !QTest::qWaitForWindowActive(sw.data())) QSKIP("Failed to show and activate window"); @@ -394,7 +395,6 @@ void tst_QScroller::overshoot() QScroller::grabGesture(sw.data(), QScroller::TouchGesture); sw->setGeometry(100, 100, 400, 300); sw->show(); - QApplication::setActiveWindow(sw.data()); if (!QTest::qWaitForWindowExposed(sw.data()) || !QTest::qWaitForWindowActive(sw.data())) QSKIP("Failed to show and activate window"); @@ -516,6 +516,66 @@ void tst_QScroller::multipleWindows() #endif } +/*! + This test verifies that mouse events arrive at the target widget + with valid timestamp, even if there is a gesture filtering (and then + replaying a copy of) the event. QTBUG-102010 + + We cannot truly simulate the double click here, as simulated events don't + go through the exact same event machinery as real events, so double clicks + don't get generated by Qt here. But we can verify that the timestamps of + the eventually delivered events are maintained. +*/ +void tst_QScroller::mouseEventTimestamp() +{ +#if QT_CONFIG(gestures) && QT_CONFIG(scroller) + QScopedPointer<tst_QScrollerWidget> sw(new tst_QScrollerWidget()); + sw->scrollArea = QRectF(0, 0, 1000, 1000); + QScroller::grabGesture(sw.data(), QScroller::LeftMouseButtonGesture); + sw->setGeometry(100, 100, 400, 300); + sw->show(); + if (!QTest::qWaitForWindowExposed(sw.data()) || !QTest::qWaitForWindowActive(sw.data())) + QSKIP("Failed to show and activate window"); + + QScroller *s1 = QScroller::scroller(sw.data()); + + struct EventFilter : QObject + { + QList<int> timestamps; + protected: + bool eventFilter(QObject *o, QEvent *e) override + { + if (e->isInputEvent()) + timestamps << static_cast<QInputEvent *>(e)->timestamp(); + return QObject::eventFilter(o, e); + } + + } eventFilter; + sw->installEventFilter(&eventFilter); + + const int interval = QGuiApplication::styleHints()->mouseDoubleClickInterval() / 10; + const QPoint point = sw->geometry().center(); + // Simulate double by pressing twice within the double click interval. + // Presses are filtered and then delayed by the scroller/gesture machinery, + // so we first record all events, and then make sure that the relative timestamps + // are maintained also for the replayed or synthesized events. + QTest::mousePress(sw->windowHandle(), Qt::LeftButton, {}, point); + QCOMPARE(s1->state(), QScroller::Pressed); + QTest::mouseRelease(sw->windowHandle(), Qt::LeftButton, {}, point, interval); + QCOMPARE(s1->state(), QScroller::Inactive); + QTest::mousePress(sw->windowHandle(), Qt::LeftButton, {}, point, interval); + QCOMPARE(s1->state(), QScroller::Pressed); + // also filtered and delayed by the scroller + QTest::mouseRelease(sw->windowHandle(), Qt::LeftButton, {}, point, interval); + QCOMPARE(s1->state(), QScroller::Inactive); + int lastTimestamp = -1; + for (int timestamp : std::as_const(eventFilter.timestamps)) { + QCOMPARE_GE(timestamp, lastTimestamp); + lastTimestamp = timestamp + interval; + } +#endif +} + QTEST_MAIN(tst_QScroller) #include "tst_qscroller.moc" diff --git a/tests/auto/widgets/util/qsystemtrayicon/CMakeLists.txt b/tests/auto/widgets/util/qsystemtrayicon/CMakeLists.txt index 44db0cba76..d4c517e88c 100644 --- a/tests/auto/widgets/util/qsystemtrayicon/CMakeLists.txt +++ b/tests/auto/widgets/util/qsystemtrayicon/CMakeLists.txt @@ -1,16 +1,26 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qsystemtrayicon.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qsystemtrayicon Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsystemtrayicon LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +set(resources_resource_files + "icons/icon.png" +) + qt_internal_add_test(tst_qsystemtrayicon SOURCES tst_qsystemtrayicon.cpp LIBRARIES Qt::Gui Qt::Widgets + TESTDATA ${resources_resource_files} + BUILTIN_TESTDATA ) diff --git a/tests/auto/widgets/util/qsystemtrayicon/tst_qsystemtrayicon.cpp b/tests/auto/widgets/util/qsystemtrayicon/tst_qsystemtrayicon.cpp index 5348942857..9a7cd2e534 100644 --- a/tests/auto/widgets/util/qsystemtrayicon/tst_qsystemtrayicon.cpp +++ b/tests/auto/widgets/util/qsystemtrayicon/tst_qsystemtrayicon.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -39,9 +39,9 @@ tst_QSystemTrayIcon::~tst_QSystemTrayIcon() void tst_QSystemTrayIcon::showHide() { QSystemTrayIcon icon; - icon.setIcon(QIcon("icons/icon.png")); + icon.setIcon(QIcon(":/icons/icon.png")); icon.show(); - icon.setIcon(QIcon("icons/icon.png")); + icon.setIcon(QIcon(":/icons/icon.png")); icon.hide(); } @@ -49,7 +49,7 @@ void tst_QSystemTrayIcon::showHide() void tst_QSystemTrayIcon::showMessage() { QSystemTrayIcon icon; - icon.setIcon(QIcon("icons/icon.png")); + icon.setIcon(QIcon(":/icons/icon.png")); icon.showMessage("Title", "Messagecontents"); icon.showMessage("Title", "Messagecontents", QSystemTrayIcon::NoIcon); @@ -72,7 +72,7 @@ void tst_QSystemTrayIcon::getSetCheck() QCOMPARE(true, "testToolTip" == icon.toolTip()); QCOMPARE(true, icon.icon().isNull()); - icon.setIcon(QIcon("icons/icon.png")); + icon.setIcon(QIcon(":/icons/icon.png")); QCOMPARE(false, icon.icon().isNull()); QMenu menu; @@ -104,13 +104,13 @@ void tst_QSystemTrayIcon::lastWindowClosed() QSignalSpy spy(qApp, &QGuiApplication::lastWindowClosed); QWidget window; QSystemTrayIcon icon; - icon.setIcon(QIcon("whatever.png")); + icon.setIcon(QIcon(":/icons/icon.png")); icon.show(); window.show(); QTimer::singleShot(2500, &window, SLOT(close())); QTimer::singleShot(20000, qApp, SLOT(quit())); // in case the test fails qApp->exec(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } QTEST_MAIN(tst_QSystemTrayIcon) diff --git a/tests/auto/widgets/widgets/CMakeLists.txt b/tests/auto/widgets/widgets/CMakeLists.txt index 58fa837bd3..eb44f3d103 100644 --- a/tests/auto/widgets/widgets/CMakeLists.txt +++ b/tests/auto/widgets/widgets/CMakeLists.txt @@ -1,7 +1,5 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from widgets.pro. +# SPDX-License-Identifier: BSD-3-Clause add_subdirectory(qabstractbutton) add_subdirectory(qabstractscrollarea) @@ -31,6 +29,7 @@ add_subdirectory(qscrollbar) add_subdirectory(qsizegrip) add_subdirectory(qslider) add_subdirectory(qspinbox) +add_subdirectory(qsplashscreen) add_subdirectory(qsplitter) add_subdirectory(qstackedwidget) add_subdirectory(qstatusbar) @@ -52,11 +51,12 @@ endif() add_subdirectory(qmenu) add_subdirectory(qlineedit) if(NOT ANDROID) - # QTBUG-87420 # special case + # QTBUG-87420 add_subdirectory(qmdiarea) - # QTBUG-87421 # special case + # QTBUG-87421 add_subdirectory(qmenubar) endif() if(QT_FEATURE_opengl) add_subdirectory(qopenglwidget) endif() +add_subdirectory(qrhiwidget) diff --git a/tests/auto/widgets/widgets/qabstractbutton/CMakeLists.txt b/tests/auto/widgets/widgets/qabstractbutton/CMakeLists.txt index 23f3b130d1..883614fc04 100644 --- a/tests/auto/widgets/widgets/qabstractbutton/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qabstractbutton/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qabstractbutton.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qabstractbutton Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qabstractbutton LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qabstractbutton SOURCES tst_qabstractbutton.cpp @@ -14,4 +18,5 @@ qt_internal_add_test(tst_qabstractbutton Qt::Gui Qt::GuiPrivate Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp b/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp index ec916925a3..cb91f0c6e6 100644 --- a/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp +++ b/tests/auto/widgets/widgets/qabstractbutton/tst_qabstractbutton.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -19,6 +19,8 @@ #include <qpa/qplatformintegration.h> #include <qpa/qplatformtheme.h> +#include <QtWidgets/private/qapplication_p.h> + class tst_QAbstractButton : public QObject { Q_OBJECT @@ -478,7 +480,6 @@ void tst_QAbstractButton::setShortcut() QKeySequence seq( Qt::Key_A ); testWidget->setShortcut( seq ); - QApplication::setActiveWindow(testWidget); testWidget->activateWindow(); // must be active to get shortcuts QVERIFY(QTest::qWaitForWindowActive(testWidget)); @@ -516,24 +517,24 @@ void tst_QAbstractButton::animateClick() button.animateClick(); QVERIFY(button.isDown()); - QCOMPARE(pressedSpy.count(), 1); - QCOMPARE(releasedSpy.count(), 0); - QCOMPARE(clickedSpy.count(), 0); + QCOMPARE(pressedSpy.size(), 1); + QCOMPARE(releasedSpy.size(), 0); + QCOMPARE(clickedSpy.size(), 0); qApp->processEvents(QEventLoop::AllEvents, 10); // QAbstractButton starts a 100ms timer which performs the click. If it // took more than 100ms to get here, then the button might no longer be down. if (elapsed.elapsed() < 100) { QVERIFY(button.isDown()); - QCOMPARE(pressedSpy.count(), 1); - QCOMPARE(releasedSpy.count(), 0); - QCOMPARE(clickedSpy.count(), 0); + QCOMPARE(pressedSpy.size(), 1); + QCOMPARE(releasedSpy.size(), 0); + QCOMPARE(clickedSpy.size(), 0); } QTRY_VERIFY(!button.isDown()); // but once the button has been clicked, it must have taken at least 100ms QVERIFY(elapsed.elapsed() >= 100); - QCOMPARE(pressedSpy.count(), 1); - QCOMPARE(releasedSpy.count(), 1); - QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(pressedSpy.size(), 1); + QCOMPARE(releasedSpy.size(), 1); + QCOMPARE(clickedSpy.size(), 1); } #if QT_CONFIG(shortcut) @@ -556,9 +557,9 @@ void tst_QAbstractButton::shortcutEvents() QTest::qWait(1000); // ensure animate timer is expired - QCOMPARE(pressedSpy.count(), 3); - QCOMPARE(releasedSpy.count(), 3); - QCOMPARE(clickedSpy.count(), 3); + QCOMPARE(pressedSpy.size(), 3); + QCOMPARE(releasedSpy.size(), 3); + QCOMPARE(clickedSpy.size(), 3); } #endif // QT_CONFIG(shortcut) @@ -600,14 +601,14 @@ void tst_QAbstractButton::mouseReleased() // QTBUG-53244 QSignalSpy spyRelease(&button, &QAbstractButton::released); QTest::mousePress(&button, Qt::LeftButton); - QCOMPARE(spyPress.count(), 1); + QCOMPARE(spyPress.size(), 1); QCOMPARE(button.isDown(), true); - QCOMPARE(spyRelease.count(), 0); + QCOMPARE(spyRelease.size(), 0); QTest::mouseClick(&button, Qt::RightButton); - QCOMPARE(spyPress.count(), 1); + QCOMPARE(spyPress.size(), 1); QCOMPARE(button.isDown(), true); - QCOMPARE(spyRelease.count(), 0); + QCOMPARE(spyRelease.size(), 0); QPointF posOutOfWidget = QPointF(30, 30); QMouseEvent me(QEvent::MouseMove, @@ -617,9 +618,9 @@ void tst_QAbstractButton::mouseReleased() // QTBUG-53244 qApp->sendEvent(&button, &me); // should emit released signal once mouse is dragging out of boundary - QCOMPARE(spyPress.count(), 1); + QCOMPARE(spyPress.size(), 1); QCOMPARE(button.isDown(), false); - QCOMPARE(spyRelease.count(), 1); + QCOMPARE(spyRelease.size(), 1); } #ifdef QT_KEYPAD_NAVIGATION @@ -639,7 +640,7 @@ void tst_QAbstractButton::keyNavigation() } widget.show(); - qApp->setActiveWindow(&widget); + QApplicationPrivate::setActiveWindow(&widget); widget.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&widget)); @@ -684,7 +685,7 @@ void tst_QAbstractButton::buttonPressKeys() const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ->themeHint(QPlatformTheme::ButtonPressKeys) .value<QList<Qt::Key>>(); - for (uint i = 0; i < buttonPressKeys.length(); ++i) { + for (uint i = 0; i < buttonPressKeys.size(); ++i) { QTest::keyClick(testWidget, buttonPressKeys[i]); QCOMPARE(click_count, i + 1); } diff --git a/tests/auto/widgets/widgets/qabstractscrollarea/CMakeLists.txt b/tests/auto/widgets/widgets/qabstractscrollarea/CMakeLists.txt index cc719d2751..ac1d8ad54a 100644 --- a/tests/auto/widgets/widgets/qabstractscrollarea/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qabstractscrollarea/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qabstractscrollarea.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qabstractscrollarea Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qabstractscrollarea LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qabstractscrollarea SOURCES tst_qabstractscrollarea.cpp diff --git a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp index 86c42a6522..fa1f799855 100644 --- a/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp +++ b/tests/auto/widgets/widgets/qabstractscrollarea/tst_qabstractscrollarea.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -13,6 +13,7 @@ #include <qwidget.h> #include <qdialog.h> #include <qscroller.h> +#include <qstyle.h> class tst_QAbstractScrollArea : public QObject { @@ -34,6 +35,7 @@ private slots: void margins(); void resizeWithOvershoot(); + void sizeHint(); }; tst_QAbstractScrollArea::tst_QAbstractScrollArea() @@ -408,5 +410,56 @@ void tst_QAbstractScrollArea::resizeWithOvershoot() QTRY_COMPARE(scrollArea.viewport()->pos(), originAtRest); } +void tst_QAbstractScrollArea::sizeHint() +{ + class ScrollArea : public QAbstractScrollArea + { + public: + QSize viewportSizeHint() const override { return {200, 200}; } + } scrollArea; + // We cannot reliable test the impact of the scrollbars on the size hint + // if the style uses transient scrollbars, so use the class Windows style. + const QString defaultStyle = QApplication::style()->name(); + QApplication::setStyle("Windows"); + auto resetStyle = qScopeGuard([defaultStyle]{ + QApplication::setStyle(defaultStyle); + }); + scrollArea.setFrameShape(QFrame::NoFrame); + scrollArea.setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); + scrollArea.show(); + + QSize sizeHint = scrollArea.sizeHint(); + QCOMPARE(sizeHint, scrollArea.viewportSizeHint()); + + scrollArea.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + scrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + const QSize sizeHintWithScrollBars = scrollArea.sizeHint(); + QTRY_COMPARE_GT(sizeHintWithScrollBars.width(), sizeHint.width()); + QTRY_COMPARE_GT(sizeHintWithScrollBars.height(), sizeHint.height()); + + sizeHint = scrollArea.sizeHint(); + + // whether the scroll area itself is visible or not should not influence + // the size hint + scrollArea.hide(); + QCOMPARE(scrollArea.sizeHint(), sizeHint); + scrollArea.show(); + QCOMPARE(scrollArea.sizeHint(), sizeHint); + + scrollArea.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + QCOMPARE(scrollArea.sizeHint(), scrollArea.viewportSizeHint()); + + scrollArea.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + scrollArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + + scrollArea.verticalScrollBar()->setRange(0, 1); + scrollArea.horizontalScrollBar()->setRange(0, 1); + scrollArea.resize(sizeHint / 2); + QApplication::processEvents(); // trigger lazy layout process + QCOMPARE(scrollArea.sizeHint(), sizeHintWithScrollBars); +} + QTEST_MAIN(tst_QAbstractScrollArea) #include "tst_qabstractscrollarea.moc" diff --git a/tests/auto/widgets/widgets/qabstractslider/CMakeLists.txt b/tests/auto/widgets/widgets/qabstractslider/CMakeLists.txt index 9d6d7e4c8d..711c73931d 100644 --- a/tests/auto/widgets/widgets/qabstractslider/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qabstractslider/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qabstractslider.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qabstractslider Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qabstractslider LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qabstractslider SOURCES tst_qabstractslider.cpp diff --git a/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp b/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp index edca1954fd..9be41ad799 100644 --- a/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp +++ b/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -1459,7 +1459,7 @@ void tst_QAbstractSlider::keyPressed() slider->setOrientation(Qt::Horizontal); slider->setInvertedAppearance(invertedAppearance); slider->setInvertedControls(invertedControls); - for (int i=0;i<keySequence.count();i++) { + for (int i=0;i<keySequence.size();i++) { QTest::keyClick(slider, keySequence.at(i)); } QCOMPARE(slider->sliderPosition(), expectedSliderPosition); @@ -1666,8 +1666,8 @@ void tst_QAbstractSlider::wheelEvent() #endif QCOMPARE(slider->sliderPosition(),expectedSliderPosition); int expectedSignalCount = (initialSliderPosition == expectedSliderPosition) ? 0 : 1; - QCOMPARE(spy1.count(), expectedSignalCount); - QCOMPARE(spy2.count(), expectedSignalCount); + QCOMPARE(spy1.size(), expectedSignalCount); + QCOMPARE(spy2.size(), expectedSignalCount); if (expectedSignalCount) QVERIFY(actionTriggeredTimeStamp < valueChangedTimeStamp); } @@ -1814,9 +1814,9 @@ void tst_QAbstractSlider::sliderPressedReleased() QTest::mousePress(slider, Qt::LeftButton, {}, QPoint(rect.center().x() + 2, rect.center().y() + 2)); - QCOMPARE(spy1.count(), expectedCount); + QCOMPARE(spy1.size(), expectedCount); QTest::mouseRelease(slider, Qt::LeftButton, {}, rect.center()); - QCOMPARE(spy2.count(), expectedCount); + QCOMPARE(spy2.size(), expectedCount); delete slider; } @@ -1885,7 +1885,7 @@ void tst_QAbstractSlider::sliderMoved() slider->setMaximum(maximum); slider->setSliderDown(sliderDown); slider->setSliderPosition(position); - QCOMPARE(spy.count(), expectedCount); + QCOMPARE(spy.size(), expectedCount); delete slider; } @@ -1957,7 +1957,7 @@ void tst_QAbstractSlider::rangeChanged() slider.setRange(minimum, maximum); QSignalSpy spy(&slider, SIGNAL(rangeChanged(int,int))); slider.setRange(newMin, newMax); - QCOMPARE(spy.count(), expectedCount); + QCOMPARE(spy.size(), expectedCount); } void tst_QAbstractSlider::setSliderPosition_data() @@ -1996,8 +1996,8 @@ void tst_QAbstractSlider::setSliderPosition() QSignalSpy spy2(slider, SIGNAL(valueChanged(int))); slider->setSliderPosition(targetPosition); QCOMPARE(slider->sliderPosition(), targetPosition); - QCOMPARE(spy1.count(), down ? 1 : 0); - QCOMPARE(spy2.count(), tracking ? 1 : 0); + QCOMPARE(spy1.size(), down ? 1 : 0); + QCOMPARE(spy2.size(), tracking ? 1 : 0); QCOMPARE(slider->value(), tracking ? targetPosition : initialValue); if (tracking && down) QVERIFY(sliderMovedTimeStamp < valueChangedTimeStamp); @@ -2021,17 +2021,21 @@ void tst_QAbstractSlider::setValue() slider->setRange(minimum, maximum); slider->setSliderDown(down); slider->setValue(49); // to force a valueChanged() below - QSignalSpy spy1(slider, SIGNAL(sliderMoved(int))); - QSignalSpy spy2(slider, SIGNAL(valueChanged(int))); - QSignalSpy spy3(slider, SIGNAL(actionTriggered(int))); + QSignalSpy spy1(slider, &QAbstractSlider::sliderMoved); + QSignalSpy spy2(slider, &QAbstractSlider::valueChanged); + QSignalSpy spy3(slider, &QAbstractSlider::actionTriggered); slider->setValue(50); - QCOMPARE(spy1.count(), down ? 1 : 0); - QCOMPARE(spy2.count(), 1); - QCOMPARE(spy3.count(), 0); + QCOMPARE(spy1.size(), down ? 1 : 0); + QCOMPARE(spy2.size(), 1); + QCOMPARE(spy3.size(), 0); QCOMPARE(slider->value(), reportedValue); QCOMPARE(slider->sliderPosition(), reportedSliderPosition); if (down) QVERIFY(sliderMovedTimeStamp < valueChangedTimeStamp); + + slider->setValue(50); + QApplication::processEvents(); + QCOMPARE(spy2.size(), 1); } void tst_QAbstractSlider::waitUntilTimeElapsed(const QElapsedTimer &t, int ms) @@ -2051,37 +2055,37 @@ void tst_QAbstractSlider::setRepeatAction() // Start repeat action with initial delay of 500 ms, and then repeating // every 250 ms. slider->setRepeatAction(QAbstractSlider::SliderPageStepAdd, 500, 250); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QCOMPARE(slider->value(), 55); QElapsedTimer t; t.start(); QTest::qWait(300); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QCOMPARE(slider->value(), 55); waitUntilTimeElapsed(t, 550); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); QCOMPARE(slider->value(), 65); QCOMPARE(spy.at(0).at(0).toUInt(), (uint)QAbstractSlider::SliderPageStepAdd); waitUntilTimeElapsed(t, 790); - QTRY_COMPARE(spy.count(), 2); + QTRY_COMPARE(spy.size(), 2); QCOMPARE(slider->value(), 75); QCOMPARE(spy.at(1).at(0).toUInt(), (uint)QAbstractSlider::SliderPageStepAdd); waitUntilTimeElapsed(t, 1790); - QTRY_COMPARE(spy.count(), 6); + QTRY_COMPARE(spy.size(), 6); QCOMPARE(slider->value(), 115); QCOMPARE(spy.at(4).at(0).toUInt(), (uint)QAbstractSlider::SliderPageStepAdd); QCOMPARE(spy.at(5).at(0).toUInt(), (uint)QAbstractSlider::SliderPageStepAdd); slider->setRepeatAction(QAbstractSlider::SliderNoAction); - QCOMPARE(spy.count(), 6); + QCOMPARE(spy.size(), 6); QCOMPARE(slider->value(), 115); QTest::qWait(300); - QCOMPARE(spy.count(), 6); + QCOMPARE(spy.size(), 6); QCOMPARE(slider->value(), 115); } diff --git a/tests/auto/widgets/widgets/qabstractspinbox/CMakeLists.txt b/tests/auto/widgets/widgets/qabstractspinbox/CMakeLists.txt index 0f196952e5..adaef01601 100644 --- a/tests/auto/widgets/widgets/qabstractspinbox/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qabstractspinbox/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qabstractspinbox.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qabstractspinbox Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qabstractspinbox LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qabstractspinbox SOURCES tst_qabstractspinbox.cpp diff --git a/tests/auto/widgets/widgets/qabstractspinbox/tst_qabstractspinbox.cpp b/tests/auto/widgets/widgets/qabstractspinbox/tst_qabstractspinbox.cpp index 6c3eaa5e9c..00d0fdaf94 100644 --- a/tests/auto/widgets/widgets/qabstractspinbox/tst_qabstractspinbox.cpp +++ b/tests/auto/widgets/widgets/qabstractspinbox/tst_qabstractspinbox.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/widgets/qbuttongroup/CMakeLists.txt b/tests/auto/widgets/widgets/qbuttongroup/CMakeLists.txt index 19cf21721a..b58775d2ff 100644 --- a/tests/auto/widgets/widgets/qbuttongroup/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qbuttongroup/CMakeLists.txt @@ -1,16 +1,21 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qbuttongroup.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qbuttongroup Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qbuttongroup LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qbuttongroup SOURCES tst_qbuttongroup.cpp LIBRARIES Qt::Gui Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp b/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp index f95f017d6b..3ff748ef27 100644 --- a/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp +++ b/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -19,6 +19,8 @@ #include <qsettings.h> #endif +#include <QtWidgets/private/qapplication_p.h> + class SpecialRadioButton: public QRadioButton { public: @@ -120,7 +122,6 @@ void tst_QButtonGroup::arrowKeyNavigation() layout.addWidget(&g2); dlg.show(); - qApp->setActiveWindow(&dlg); QVERIFY(QTest::qWaitForWindowActive(&dlg)); bt1.setFocus(); @@ -202,7 +203,6 @@ void tst_QButtonGroup::keyNavigationPushButtons() buttonGroup->addButton(pb3); dlg.show(); - qApp->setActiveWindow(&dlg); if (!QTest::qWaitForWindowActive(&dlg)) QSKIP("Window activation failed, skipping test"); @@ -349,17 +349,17 @@ void tst_QButtonGroup::testSignals() pb1.animateClick(); QTestEventLoop::instance().enterLoop(1); - QCOMPARE(clickedSpy.count(), 1); - QCOMPARE(clickedIdSpy.count(), 1); + QCOMPARE(clickedSpy.size(), 1); + QCOMPARE(clickedIdSpy.size(), 1); int expectedId = -2; QCOMPARE(clickedIdSpy.takeFirst().at(0).toInt(), expectedId); - QCOMPARE(pressedSpy.count(), 1); - QCOMPARE(pressedIdSpy.count(), 1); + QCOMPARE(pressedSpy.size(), 1); + QCOMPARE(pressedIdSpy.size(), 1); QCOMPARE(pressedIdSpy.takeFirst().at(0).toInt(), expectedId); - QCOMPARE(releasedSpy.count(), 1); - QCOMPARE(releasedIdSpy.count(), 1); + QCOMPARE(releasedSpy.size(), 1); + QCOMPARE(releasedIdSpy.size(), 1); QCOMPARE(releasedIdSpy.takeFirst().at(0).toInt(), expectedId); clickedSpy.clear(); @@ -372,14 +372,14 @@ void tst_QButtonGroup::testSignals() pb2.animateClick(); QTestEventLoop::instance().enterLoop(1); - QCOMPARE(clickedSpy.count(), 1); - QCOMPARE(clickedIdSpy.count(), 1); + QCOMPARE(clickedSpy.size(), 1); + QCOMPARE(clickedIdSpy.size(), 1); QCOMPARE(clickedIdSpy.takeFirst().at(0).toInt(), 23); - QCOMPARE(pressedSpy.count(), 1); - QCOMPARE(pressedIdSpy.count(), 1); + QCOMPARE(pressedSpy.size(), 1); + QCOMPARE(pressedIdSpy.size(), 1); QCOMPARE(pressedIdSpy.takeFirst().at(0).toInt(), 23); - QCOMPARE(releasedSpy.count(), 1); - QCOMPARE(releasedIdSpy.count(), 1); + QCOMPARE(releasedSpy.size(), 1); + QCOMPARE(releasedIdSpy.size(), 1); QCOMPARE(releasedIdSpy.takeFirst().at(0).toInt(), 23); @@ -389,18 +389,18 @@ void tst_QButtonGroup::testSignals() pb1.setCheckable(true); pb2.setCheckable(true); pb1.toggle(); - QCOMPARE(toggledSpy.count(), 1); - QCOMPARE(toggledIdSpy.count(), 1); + QCOMPARE(toggledSpy.size(), 1); + QCOMPARE(toggledIdSpy.size(), 1); pb2.toggle(); - QCOMPARE(toggledSpy.count(), 3); // equals 3 since pb1 and pb2 are both toggled - QCOMPARE(toggledIdSpy.count(), 3); + QCOMPARE(toggledSpy.size(), 3); // equals 3 since pb1 and pb2 are both toggled + QCOMPARE(toggledIdSpy.size(), 3); pb1.setCheckable(false); pb2.setCheckable(false); pb1.toggle(); - QCOMPARE(toggledSpy.count(), 3); - QCOMPARE(toggledIdSpy.count(), 3); + QCOMPARE(toggledSpy.size(), 3); + QCOMPARE(toggledIdSpy.size(), 3); } void tst_QButtonGroup::task106609() @@ -433,14 +433,13 @@ void tst_QButtonGroup::task106609() qRegisterMetaType<QAbstractButton*>("QAbstractButton*"); QSignalSpy spy1(buttons, SIGNAL(buttonClicked(QAbstractButton*))); - QApplication::setActiveWindow(&dlg); QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&dlg)); radio1->setFocus(); radio1->setChecked(true); QTestEventLoop::instance().enterLoop(1); - QCOMPARE(spy1.count(), 2); + QCOMPARE(spy1.size(), 2); } void tst_QButtonGroup::checkedButton() @@ -525,7 +524,7 @@ void tst_QButtonGroup::task209485_removeFromGroupInEventHandler() // NOTE: Reintroducing the bug of this task will cause the following line to crash: QTest::mouseClick(button, Qt::LeftButton); - QCOMPARE(spy1.count(), signalCount); + QCOMPARE(spy1.size(), signalCount); } void tst_QButtonGroup::autoIncrementId() diff --git a/tests/auto/widgets/widgets/qcalendarwidget/CMakeLists.txt b/tests/auto/widgets/widgets/qcalendarwidget/CMakeLists.txt index a31c6230dd..5140c37e94 100644 --- a/tests/auto/widgets/widgets/qcalendarwidget/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qcalendarwidget/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qcalendarwidget.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qcalendarwidget Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qcalendarwidget LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qcalendarwidget SOURCES tst_qcalendarwidget.cpp diff --git a/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp b/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp index 064b539f22..ca5cc06e99 100644 --- a/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp +++ b/tests/auto/widgets/widgets/qcalendarwidget/tst_qcalendarwidget.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -84,7 +84,7 @@ void tst_QCalendarWidget::getSetCheck() QDate selectedDate(2005, 7, 3); QSignalSpy spy(&object, SIGNAL(selectionChanged())); object.setSelectedDate(selectedDate); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(selectedDate, object.selectedDate()); //month and year object.setCurrentPage(2004, 1); @@ -110,11 +110,19 @@ void tst_QCalendarWidget::getSetCheck() object.setSelectedDate(selectedDate); QCOMPARE(minDate, object.selectedDate()); QVERIFY(selectedDate != object.selectedDate()); + object.clearMinimumDate(); + object.setSelectedDate(selectedDate); + QCOMPARE(selectedDate, object.selectedDate()); + //date should not go beyond the maximum. selectedDate = maxDate.addDays(10); object.setSelectedDate(selectedDate); QCOMPARE(maxDate, object.selectedDate()); QVERIFY(selectedDate != object.selectedDate()); + object.clearMaximumDate(); + object.setSelectedDate(selectedDate); + QCOMPARE(selectedDate, object.selectedDate()); + //show today QDate today = QDate::currentDate(); object.showToday(); diff --git a/tests/auto/widgets/widgets/qcheckbox/CMakeLists.txt b/tests/auto/widgets/widgets/qcheckbox/CMakeLists.txt index 81ba1d332c..9e3f0e9874 100644 --- a/tests/auto/widgets/widgets/qcheckbox/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qcheckbox/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qcheckbox.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qcheckbox Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qcheckbox LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qcheckbox SOURCES tst_qcheckbox.cpp diff --git a/tests/auto/widgets/widgets/qcheckbox/tst_qcheckbox.cpp b/tests/auto/widgets/widgets/qcheckbox/tst_qcheckbox.cpp index b0b34ee3fa..42eb81d3c7 100644 --- a/tests/auto/widgets/widgets/qcheckbox/tst_qcheckbox.cpp +++ b/tests/auto/widgets/widgets/qcheckbox/tst_qcheckbox.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -16,6 +16,7 @@ private slots: void initTestCase(); void setChecked(); + void setCheckedSignal(); void setTriState(); void setText_data(); void setText(); @@ -25,7 +26,7 @@ private slots: void toggle(); void pressed(); void toggled(); - void stateChanged(); + void checkStateChanged(); void foregroundRole(); void minimumSizeHint(); }; @@ -59,6 +60,25 @@ void tst_QCheckBox::setChecked() QVERIFY(!testWidget.isChecked()); } +void tst_QCheckBox::setCheckedSignal() +{ + QCheckBox testWidget; + testWidget.setCheckState(Qt::Unchecked); + QSignalSpy checkStateChangedSpy(&testWidget, &QCheckBox::checkStateChanged); + testWidget.setCheckState(Qt::Checked); + testWidget.setCheckState(Qt::Checked); + QTRY_COMPARE(checkStateChangedSpy.size(), 1); // get signal only once + QCOMPARE(testWidget.checkState(), Qt::Checked); + testWidget.setCheckState(Qt::Unchecked); + testWidget.setCheckState(Qt::Unchecked); + QTRY_COMPARE(checkStateChangedSpy.size(), 2); // get signal only once + QCOMPARE(testWidget.checkState(), Qt::Unchecked); + testWidget.setCheckState(Qt::PartiallyChecked); + testWidget.setCheckState(Qt::PartiallyChecked); + QTRY_COMPARE(checkStateChangedSpy.size(), 3); // get signal only once + QCOMPARE(testWidget.checkState(), Qt::PartiallyChecked); +} + void tst_QCheckBox::setTriState() { QCheckBox testWidget; @@ -188,30 +208,49 @@ void tst_QCheckBox::toggled() QCOMPARE(click_count, 0); } -void tst_QCheckBox::stateChanged() +void tst_QCheckBox::checkStateChanged() { QCheckBox testWidget; - int cur_state = -1; + QCOMPARE(testWidget.checkState(), Qt::Unchecked); + + Qt::CheckState cur_state = Qt::Unchecked; + QSignalSpy checkStateChangedSpy(&testWidget, &QCheckBox::checkStateChanged); +#if QT_DEPRECATED_SINCE(6, 9) + QT_IGNORE_DEPRECATIONS( QSignalSpy stateChangedSpy(&testWidget, &QCheckBox::stateChanged); - connect(&testWidget, &QCheckBox::stateChanged, this, [&](int state) { ++cur_state = state; }); + ) +#endif + connect(&testWidget, &QCheckBox::checkStateChanged, this, [&](auto state) { cur_state = state; }); testWidget.setChecked(true); - QCoreApplication::processEvents(); - QCOMPARE(cur_state, 2); + QTRY_COMPARE(checkStateChangedSpy.size(), 1); +#if QT_DEPRECATED_SINCE(6, 9) + QCOMPARE(stateChangedSpy.size(), 1); +#endif + QCOMPARE(cur_state, Qt::Checked); + QCOMPARE(testWidget.checkState(), Qt::Checked); - cur_state = -1; testWidget.setChecked(false); - QCoreApplication::processEvents(); - QCOMPARE(cur_state, 0); + QTRY_COMPARE(checkStateChangedSpy.size(), 2); +#if QT_DEPRECATED_SINCE(6, 9) + QCOMPARE(stateChangedSpy.size(), 2); +#endif + QCOMPARE(cur_state, Qt::Unchecked); + QCOMPARE(testWidget.checkState(), Qt::Unchecked); - cur_state = -1; testWidget.setCheckState(Qt::PartiallyChecked); - QCoreApplication::processEvents(); - QCOMPARE(cur_state, 1); + QTRY_COMPARE(checkStateChangedSpy.size(), 3); +#if QT_DEPRECATED_SINCE(6, 9) + QCOMPARE(stateChangedSpy.size(), 3); +#endif + QCOMPARE(cur_state, Qt::PartiallyChecked); + QCOMPARE(testWidget.checkState(), Qt::PartiallyChecked); - QCOMPARE(stateChangedSpy.count(), 3); testWidget.setCheckState(Qt::PartiallyChecked); QCoreApplication::processEvents(); - QCOMPARE(stateChangedSpy.count(), 3); + QCOMPARE(checkStateChangedSpy.size(), 3); +#if QT_DEPRECATED_SINCE(6, 9) + QCOMPARE(stateChangedSpy.size(), 3); +#endif } void tst_QCheckBox::isToggleButton() diff --git a/tests/auto/widgets/widgets/qcombobox/CMakeLists.txt b/tests/auto/widgets/widgets/qcombobox/CMakeLists.txt index f685f452f3..87ac247b24 100644 --- a/tests/auto/widgets/widgets/qcombobox/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qcombobox/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qcombobox.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qcombobox Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qcombobox LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Collect test data list(APPEND test_data "qtlogo.png") list(APPEND test_data "qtlogoinverted.png") diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp index 4ca3a1b5a5..66c1359bd8 100644 --- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QSignalSpy> @@ -8,6 +8,7 @@ #include "qcombobox.h" #include <private/qcombobox_p.h> #include <private/qguiapplication_p.h> +#include <qpa/qplatformintegration.h> #include <qpa/qplatformtheme.h> #include <qfontcombobox.h> @@ -24,6 +25,7 @@ #include <qtablewidget.h> #include <qscrollbar.h> #include <qboxlayout.h> +#include <qshortcut.h> #include <qstackedwidget.h> #include <qstandarditemmodel.h> @@ -40,11 +42,15 @@ #include <qstandarditemmodel.h> #include <qproxystyle.h> #include <qfont.h> +#include <qstylehints.h> #include "../../../shared/platforminputcontext.h" #include <private/qinputmethod_p.h> #include <QtTest/private/qtesthelpers_p.h> +#include <QtTest/private/qemulationdetector_p.h> + +#include <QtWidgets/private/qapplication_p.h> using namespace QTestPrivate; @@ -105,6 +111,7 @@ private slots: #ifndef QT_NO_STYLE_FUSION void task190351_layout(); void task191329_size(); + void popupPositionAfterStyleChange(); #endif void task166349_setEditableOnReturn(); void task190205_setModelAdjustToContents(); @@ -147,6 +154,8 @@ private slots: void propagateStyleChanges(); void buttonPressKeys(); void clearModel(); + void cancelClosesPopupNotDialog(); + void closePopupWithCheckableItems(); private: PlatformInputContext m_platformInputContext; @@ -449,11 +458,19 @@ void tst_QComboBox::setEditable() void tst_QComboBox::setPalette() { -#ifdef Q_OS_MAC - if (QApplication::style()->inherits("QMacStyle")) { - QSKIP("This test doesn't make sense for pixmap-based styles"); - } -#endif + // If (a) Palettes are pixmap based and/or (b) contain color groups/roles which the + // resolve mask prevents from being copied, the direct comparison of the inherited + // palette and the parent palette will fail. + // To prevent that, set a simple gray system palette for QComboBox and QLineEdit + const QPalette comboBoxPalette = qApp->palette("QComboBox"); + const QPalette lineEditPalette = qApp->palette("QLineEdit"); + auto guard = qScopeGuard([&]{ + qApp->setPalette(comboBoxPalette, "QComboBox"); + qApp->setPalette(lineEditPalette, "QLineEdit"); + }); + qApp->setPalette(QPalette(Qt::gray), "QComboBox"); + qApp->setPalette(QPalette(Qt::gray), "QLineEdit"); + TestWidget topLevel; topLevel.show(); QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); @@ -461,16 +478,15 @@ void tst_QComboBox::setPalette() QPalette pal = testWidget->palette(); pal.setColor(QPalette::Base, Qt::red); testWidget->setPalette(pal); - testWidget->setEditable(!testWidget->isEditable()); + testWidget->setEditable(true); pal.setColor(QPalette::Base, Qt::blue); testWidget->setPalette(pal); - const QObjectList comboChildren = testWidget->children(); - for (int i = 0; i < comboChildren.size(); ++i) { - QObject *o = comboChildren.at(i); - if (o->isWidgetType()) { - QCOMPARE(((QWidget*)o)->palette(), pal); + const QObjectList &comboChildren = testWidget->children(); + for (auto *child : comboChildren) { + if (auto *widget = qobject_cast<QWidget *>(child)) { + QCOMPARE(widget->palette(), pal); } } @@ -747,7 +763,7 @@ void tst_QComboBox::insertPolicy() testWidget->setInsertPolicy(insertPolicy); testWidget->addItems(initialEntries); testWidget->setEditable(true); - if (initialEntries.count() > 0) + if (initialEntries.size() > 0) testWidget->setCurrentIndex(currentIndex); // clear @@ -759,10 +775,10 @@ void tst_QComboBox::insertPolicy() // First check that there is the right number of entries, or // we may unwittingly pass - QCOMPARE((int)result.count(), testWidget->count()); + QCOMPARE((int)result.size(), testWidget->count()); // No need to compare if there are no strings to compare - if (result.count() > 0) { + if (result.size() > 0) { for (int i=0; i<testWidget->count(); ++i) { QCOMPARE(testWidget->itemText(i), result.at(i)); } @@ -833,7 +849,6 @@ void tst_QComboBox::autoCompletionCaseSensitivity() TestWidget topLevel; topLevel.show(); QComboBox *testWidget = topLevel.comboBox(); - qApp->setActiveWindow(&topLevel); testWidget->setFocus(); QVERIFY(QTest::qWaitForWindowActive(&topLevel)); QCOMPARE(qApp->focusWidget(), (QWidget *)testWidget); @@ -859,18 +874,18 @@ void tst_QComboBox::autoCompletionCaseSensitivity() QTest::keyClick(testWidget->lineEdit(), Qt::Key_A); qApp->processEvents(); QCOMPARE(testWidget->currentText(), QString("aww")); - QCOMPARE(spyReturn.count(), 0); + QCOMPARE(spyReturn.size(), 0); QTest::keyClick(testWidget->lineEdit(), Qt::Key_B); qApp->processEvents(); // autocompletions preserve userkey-case from 4.2 QCOMPARE(testWidget->currentText(), QString("abCDEF")); - QCOMPARE(spyReturn.count(), 0); + QCOMPARE(spyReturn.size(), 0); QTest::keyClick(testWidget->lineEdit(), Qt::Key_Enter); qApp->processEvents(); QCOMPARE(testWidget->currentText(), QString("aBCDEF")); // case restored to item's case - QCOMPARE(spyReturn.count(), 1); + QCOMPARE(spyReturn.size(), 1); testWidget->clearEditText(); QTest::keyClick(testWidget->lineEdit(), 'c'); @@ -1006,7 +1021,7 @@ void tst_QComboBox::currentIndex_data() expectedCurrentIndex = -1; expectedCurrentText = ""; expectedSignalCount = 2; - QTest::newRow("check that isetting the index to -1 works") + QTest::newRow("check that setting the index to -1 works") << initialItems << setCurrentIndex << removeIndex << insertIndex << insertText << expectedCurrentIndex << expectedCurrentText << expectedSignalCount; @@ -1149,66 +1164,71 @@ void tst_QComboBox::currentIndex() TestWidget topLevel; topLevel.show(); QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); - QComboBox *testWidget = topLevel.comboBox(); + QComboBox *comboBox = topLevel.comboBox(); // test both editable/non-editable combobox for (int edit = 0; edit < 2; ++edit) { - testWidget->clear(); - testWidget->setEditable(edit ? true : false); + comboBox->clear(); + comboBox->setEditable(edit ? true : false); if (edit) - QVERIFY(testWidget->lineEdit()); + QVERIFY(comboBox->lineEdit()); // verify it is empty, has no current index and no current text - QCOMPARE(testWidget->count(), 0); - QCOMPARE(testWidget->currentIndex(), -1); - QVERIFY(testWidget->currentText().isEmpty()); + QCOMPARE(comboBox->count(), 0); + QCOMPARE(comboBox->currentIndex(), -1); + QVERIFY(comboBox->currentText().isEmpty()); // spy on currentIndexChanged - QSignalSpy indexChangedInt(testWidget, SIGNAL(currentIndexChanged(int))); + QSignalSpy indexChangedSpy(comboBox, &QComboBox::currentIndexChanged); // stuff items into it - foreach(QString text, initialItems) { - testWidget->addItem(text); - } - QCOMPARE(testWidget->count(), initialItems.count()); + for (const QString &text : initialItems) + comboBox->addItem(text); + + QCOMPARE(comboBox->count(), initialItems.size()); // set current index, remove and/or insert if (setCurrentIndex >= -1) { - testWidget->setCurrentIndex(setCurrentIndex); - QCOMPARE(testWidget->currentIndex(), setCurrentIndex); + comboBox->setCurrentIndex(setCurrentIndex); + QCOMPARE(comboBox->currentIndex(), setCurrentIndex); } if (removeIndex >= 0) - testWidget->removeItem(removeIndex); + comboBox->removeItem(removeIndex); if (insertIndex >= 0) - testWidget->insertItem(insertIndex, insertText); + comboBox->insertItem(insertIndex, insertText); // compare with expected index and text - QCOMPARE(testWidget->currentIndex(), expectedCurrentIndex); - QCOMPARE(testWidget->currentText(), expectedCurrentText); + QCOMPARE(comboBox->currentIndex(), expectedCurrentIndex); + QCOMPARE(comboBox->currentText(), expectedCurrentText); // check that signal count is correct - QCOMPARE(indexChangedInt.count(), expectedSignalCount); + QCOMPARE(indexChangedSpy.size(), expectedSignalCount); // compare with last sent signal values - if (indexChangedInt.count()) - QCOMPARE(indexChangedInt.at(indexChangedInt.count() - 1).at(0).toInt(), - testWidget->currentIndex()); + if (indexChangedSpy.size()) + QCOMPARE(indexChangedSpy.at(indexChangedSpy.size() - 1).at(0).toInt(), + comboBox->currentIndex()); + + // Test a no-op index change + const int index = comboBox->currentIndex(); + comboBox->setCurrentIndex(index); + QCOMPARE(indexChangedSpy.size(), expectedSignalCount); if (edit) { - testWidget->setCurrentIndex(-1); - testWidget->setInsertPolicy(QComboBox::InsertAtBottom); - QTest::keyPress(testWidget, 'a'); - QTest::keyPress(testWidget, 'b'); - QCOMPARE(testWidget->currentText(), QString("ab")); - QCOMPARE(testWidget->currentIndex(), -1); - int numItems = testWidget->count(); - QTest::keyPress(testWidget, Qt::Key_Return); - QCOMPARE(testWidget->count(), numItems + 1); - QCOMPARE(testWidget->currentIndex(), numItems); - testWidget->setCurrentIndex(-1); - QTest::keyPress(testWidget, 'a'); - QTest::keyPress(testWidget, 'b'); - QCOMPARE(testWidget->currentIndex(), -1); + comboBox->setCurrentIndex(-1); + comboBox->setInsertPolicy(QComboBox::InsertAtBottom); + QTest::keyPress(comboBox, 'a'); + QTest::keyPress(comboBox, 'b'); + QCOMPARE(comboBox->currentText(), QString("ab")); + QCOMPARE(comboBox->currentIndex(), -1); + int numItems = comboBox->count(); + QTest::keyPress(comboBox, Qt::Key_Return); + QCOMPARE(comboBox->count(), numItems + 1); + QCOMPARE(comboBox->currentIndex(), numItems); + comboBox->setCurrentIndex(-1); + QTest::keyPress(comboBox, 'a'); + QTest::keyPress(comboBox, 'b'); + QCOMPARE(comboBox->currentIndex(), -1); } } } @@ -1228,8 +1248,8 @@ void tst_QComboBox::insertItems_data() QTest::newRow("prepend") << initialItems << insertedItems << 0 << 0; QTest::newRow("prepend with negative value") << initialItems << insertedItems << -1 << 0; - QTest::newRow("append") << initialItems << insertedItems << initialItems.count() << initialItems.count(); - QTest::newRow("append with too high value") << initialItems << insertedItems << 999 << initialItems.count(); + QTest::newRow("append") << initialItems << insertedItems << initialItems.size() << initialItems.size(); + QTest::newRow("append with too high value") << initialItems << insertedItems << 999 << initialItems.size(); QTest::newRow("insert") << initialItems << insertedItems << 1 << 1; } @@ -1245,12 +1265,12 @@ void tst_QComboBox::insertItems() QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); QComboBox *testWidget = topLevel.comboBox(); testWidget->insertItems(0, initialItems); - QCOMPARE(testWidget->count(), initialItems.count()); + QCOMPARE(testWidget->count(), initialItems.size()); testWidget->insertItems(insertIndex, insertedItems); - QCOMPARE(testWidget->count(), initialItems.count() + insertedItems.count()); - for (int i=0; i<insertedItems.count(); ++i) + QCOMPARE(testWidget->count(), initialItems.size() + insertedItems.size()); + for (int i=0; i<insertedItems.size(); ++i) QCOMPARE(testWidget->itemText(expectedIndex + i), insertedItems.at(i)); } @@ -1266,11 +1286,12 @@ void tst_QComboBox::insertItem_data() initialItems << "foo" << "bar"; for(int e = 0 ; e<2 ; e++) { bool editable = (e==0); - QTest::newRow("Insert less then 0") << initialItems << -1 << "inserted" << 0 << editable; - QTest::newRow("Insert at 0") << initialItems << 0 << "inserted" << 0 << editable; - QTest::newRow("Insert beyond count") << initialItems << 3 << "inserted" << 2 << editable; - QTest::newRow("Insert at count") << initialItems << 2 << "inserted" << 2 << editable; - QTest::newRow("Insert in the middle") << initialItems << 1 << "inserted" << 1 << editable; + const auto txt = editable ? QByteArray("editable: ") : QByteArray("non-editable: "); + QTest::newRow(txt + "Insert less then 0") << initialItems << -1 << "inserted" << 0 << editable; + QTest::newRow(txt + "Insert at 0") << initialItems << 0 << "inserted" << 0 << editable; + QTest::newRow(txt + "Insert beyond count") << initialItems << 3 << "inserted" << 2 << editable; + QTest::newRow(txt + "Insert at count") << initialItems << 2 << "inserted" << 2 << editable; + QTest::newRow(txt + "Insert in the middle") << initialItems << 1 << "inserted" << 1 << editable; } } @@ -1287,14 +1308,14 @@ void tst_QComboBox::insertItem() QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); QComboBox *testWidget = topLevel.comboBox(); testWidget->insertItems(0, initialItems); - QCOMPARE(testWidget->count(), initialItems.count()); + QCOMPARE(testWidget->count(), initialItems.size()); testWidget->setEditable(true); if (editable) testWidget->setEditText("FOO"); testWidget->insertItem(insertIndex, itemLabel); - QCOMPARE(testWidget->count(), initialItems.count() + 1); + QCOMPARE(testWidget->count(), initialItems.size() + 1); QCOMPARE(testWidget->itemText(expectedIndex), itemLabel); if (editable) @@ -1362,21 +1383,21 @@ void tst_QComboBox::textpixmapdata() QFETCH(IconList, icons); QFETCH(VariantList, variant); - QVERIFY(text.count() == icons.count() && text.count() == variant.count()); + QVERIFY(text.size() == icons.size() && text.size() == variant.size()); TestWidget topLevel; topLevel.show(); QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); QComboBox *testWidget = topLevel.comboBox(); - for (int i = 0; i<text.count(); ++i) { + for (int i = 0; i<text.size(); ++i) { testWidget->insertItem(i, text.at(i)); testWidget->setItemIcon(i, icons.at(i)); testWidget->setItemData(i, variant.at(i), Qt::UserRole); } - QCOMPARE(testWidget->count(), text.count()); + QCOMPARE(testWidget->count(), text.size()); - for (int i = 0; i<text.count(); ++i) { + for (int i = 0; i<text.size(); ++i) { QIcon icon = testWidget->itemIcon(i); QCOMPARE(icon.cacheKey(), icons.at(i).cacheKey()); QPixmap original = icons.at(i).pixmap(1024); @@ -1384,7 +1405,7 @@ void tst_QComboBox::textpixmapdata() QCOMPARE(pixmap.toImage(), original.toImage()); } - for (int i = 0; i<text.count(); ++i) { + for (int i = 0; i<text.size(); ++i) { QCOMPARE(testWidget->itemText(i), text.at(i)); // ### we should test icons/pixmap as well, but I need to fix the api mismatch first QCOMPARE(testWidget->itemData(i, Qt::UserRole), variant.at(i)); @@ -1485,42 +1506,70 @@ void tst_QComboBox::currentTextChanged() testWidget->addItems(QStringList() << "foo" << "bar"); QCOMPARE(testWidget->count(), 2); - QSignalSpy spy(testWidget, SIGNAL(currentTextChanged(QString))); + QSignalSpy textChangedSpy(testWidget, &QComboBox::currentTextChanged); testWidget->setEditable(editable); // set text in list testWidget->setCurrentIndex(0); QCOMPARE(testWidget->currentIndex(), 0); - spy.clear(); + textChangedSpy.clear(); testWidget->setCurrentText(QString("bar")); - QCOMPARE(spy.count(), 1); - QCOMPARE(qvariant_cast<QString>(spy.at(0).at(0)), QString("bar")); + QCOMPARE(textChangedSpy.size(), 1); + QCOMPARE(qvariant_cast<QString>(textChangedSpy.at(0).at(0)), QString("bar")); // set text not in list testWidget->setCurrentIndex(0); QCOMPARE(testWidget->currentIndex(), 0); - spy.clear(); + textChangedSpy.clear(); testWidget->setCurrentText(QString("qt")); if (editable) { - QCOMPARE(spy.count(), 1); - QCOMPARE(qvariant_cast<QString>(spy.at(0).at(0)), QString("qt")); + QCOMPARE(textChangedSpy.size(), 1); + QCOMPARE(qvariant_cast<QString>(textChangedSpy.at(0).at(0)), QString("qt")); } else { - QCOMPARE(spy.count(), 0); + QCOMPARE(textChangedSpy.size(), 0); } // item changed testWidget->setCurrentIndex(0); QCOMPARE(testWidget->currentIndex(), 0); - spy.clear(); + textChangedSpy.clear(); testWidget->setItemText(0, QString("ape")); - QCOMPARE(spy.count(), 1); - QCOMPARE(qvariant_cast<QString>(spy.at(0).at(0)), QString("ape")); + QCOMPARE(textChangedSpy.size(), 1); + QCOMPARE(qvariant_cast<QString>(textChangedSpy.at(0).at(0)), QString("ape")); + // change it back - spy.clear(); + textChangedSpy.clear(); testWidget->setItemText(0, QString("foo")); - QCOMPARE(spy.count(), 1); - QCOMPARE(qvariant_cast<QString>(spy.at(0).at(0)), QString("foo")); + QCOMPARE(textChangedSpy.size(), 1); + QCOMPARE(qvariant_cast<QString>(textChangedSpy.at(0).at(0)), QString("foo")); + + // currentIndexChanged vs. currentTextChanged + testWidget->clear(); + testWidget->addItems(QStringList() << "first" << "second" << "third" << "fourth" << "fourth"); + testWidget->setCurrentIndex(4); + textChangedSpy.clear(); + QSignalSpy indexChangedSpy(testWidget, &QComboBox::currentIndexChanged); + + // Index change w/o text change + testWidget->removeItem(3); + QCOMPARE(textChangedSpy.count(), 0); + QCOMPARE(indexChangedSpy.count(), 1); + + // Index and text change + testWidget->setCurrentIndex(0); + QCOMPARE(textChangedSpy.count(), 1); + QCOMPARE(indexChangedSpy.count(), 2); + + // remove item above current index + testWidget->removeItem(2); + QCOMPARE(textChangedSpy.count(), 1); + QCOMPARE(indexChangedSpy.count(), 2); + + // Text change w/o index change + testWidget->setItemText(0, "first class"); + QCOMPARE(textChangedSpy.count(), 2); + QCOMPARE(indexChangedSpy.count(), 2); } void tst_QComboBox::editTextChanged() @@ -1544,13 +1593,13 @@ void tst_QComboBox::editTextChanged() QCOMPARE(testWidget->currentIndex(), 0); testWidget->setCurrentIndex(0); QCOMPARE(testWidget->currentIndex(), 0); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); // no signal should be sent when changing to other index because we are not editable QCOMPARE(testWidget->currentIndex(), 0); testWidget->setCurrentIndex(1); QCOMPARE(testWidget->currentIndex(), 1); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); // now set to editable and reset current index testWidget->setEditable(true); @@ -1562,20 +1611,20 @@ void tst_QComboBox::editTextChanged() QCOMPARE(testWidget->currentIndex(), 0); testWidget->setCurrentIndex(0); QCOMPARE(testWidget->currentIndex(), 0); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); // signal should be sent when changing to other index QCOMPARE(testWidget->currentIndex(), 0); testWidget->setCurrentIndex(1); QCOMPARE(testWidget->currentIndex(), 1); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(qvariant_cast<QString>(spy.at(0).at(0)), QString("bar")); // insert some keys and notice they are all signaled spy.clear(); QTest::keyClicks(testWidget, "bingo"); - QCOMPARE(spy.count(), 5); + QCOMPARE(spy.size(), 5); QCOMPARE(qvariant_cast<QString>(spy.at(4).at(0)), QString("barbingo")); } @@ -1742,7 +1791,7 @@ void tst_QComboBox::setMaxCount() // insert 5 items at pos 2. Make sure only two get inserted QSignalSpy spy(box.model(), SIGNAL(rowsInserted(QModelIndex,int,int))); box.insertItems(2, items); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(1).toInt(), 2); QCOMPARE(spy.at(0).at(2).toInt(), 3); @@ -1972,7 +2021,7 @@ void tst_QComboBox::flaggedItems_data() disableFlagList << 1; keyMovementList.clear(); keyMovementList << Qt::Key_T << Qt::Key_Enter; - QTest::newRow(testCase.toLatin1() + "disabled") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2; + QTest::newRow(testCase.toLatin1() + "disabled with key") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2; QTest::newRow(testCase.toLatin1() + "broken autocompletion") << itemList << deselectFlagList << disableFlagList << keyMovementList << bool(editable) << 2; } } @@ -1984,8 +2033,8 @@ void tst_QComboBox::flaggedItems() QSKIP("Wayland: This fails. Figure out why."); QFETCH(QStringList, itemList); - QFETCH(IntList, deselectFlagList); - QFETCH(IntList, disableFlagList); + QFETCH(const IntList, deselectFlagList); + QFETCH(const IntList, disableFlagList); QFETCH(KeyList, keyMovementList); QFETCH(bool, editable); QFETCH(int, expectedIndex); @@ -1996,17 +2045,16 @@ void tst_QComboBox::flaggedItems() listWidget.addItems(itemList); comboBox.setEditable(editable); - foreach (int index, deselectFlagList) + for (int index : deselectFlagList) listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsSelectable); - foreach (int index, disableFlagList) + for (int index : disableFlagList) listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsEnabled); comboBox.setModel(listWidget.model()); comboBox.setView(&listWidget); comboBox.move(200, 200); comboBox.show(); - QApplication::setActiveWindow(&comboBox); comboBox.activateWindow(); comboBox.setFocus(); QVERIFY(QTest::qWaitForWindowActive(&comboBox)); @@ -2016,7 +2064,7 @@ void tst_QComboBox::flaggedItems() if (editable) comboBox.lineEdit()->selectAll(); - for (int i = 0; i < keyMovementList.count(); ++i) { + for (int i = 0; i < keyMovementList.size(); ++i) { Qt::Key key = keyMovementList[i]; QTest::keyClick(&comboBox, key); } @@ -2082,7 +2130,7 @@ void tst_QComboBox::mouseWheel_data() void tst_QComboBox::mouseWheel() { - QFETCH(IntList, disabledItems); + QFETCH(const IntList, disabledItems); QFETCH(int, startIndex); QFETCH(int, wheelDirection); QFETCH(int, expectedIndex); @@ -2097,7 +2145,7 @@ void tst_QComboBox::mouseWheel() QListWidget listWidget; listWidget.addItems(list); - foreach (int index, disabledItems) + for (int index : disabledItems) listWidget.item(index)->setFlags(listWidget.item(index)->flags() & ~Qt::ItemIsEnabled); box.setModel(listWidget.model()); @@ -2231,13 +2279,13 @@ void tst_QComboBox::separatorItem_data() void tst_QComboBox::separatorItem() { QFETCH(QStringList, items); - QFETCH(IntList, separators); + QFETCH(const IntList, separators); QComboBox box; box.addItems(items); - foreach(int index, separators) + for (int index : separators) box.insertSeparator(index); - QCOMPARE(box.count(), (items.count() + separators.count())); + QCOMPARE(box.count(), (items.size() + separators.size())); for (int i = 0, s = 0; i < box.count(); ++i) { if (i == separators.at(s)) { QCOMPARE(box.itemText(i), QString()); @@ -2356,7 +2404,8 @@ void tst_QComboBox::task191329_size() QFrame *container = tableCombo.findChild<QComboBoxPrivateContainer *>(); QVERIFY(container); QCOMPARE(static_cast<QAbstractItemView *>(table), container->findChild<QAbstractItemView *>()); - foreach (QWidget *button, container->findChildren<QComboBoxPrivateScroller *>()) { + const auto buttons = container->findChildren<QComboBoxPrivateScroller *>(); + for (QWidget *button : buttons) { //the popup should be large enough to contains everithing so the top and left button are hidden QVERIFY(!button->isVisible()); } @@ -2435,7 +2484,6 @@ void tst_QComboBox::task247863_keyBoardSelection() combo.addItem( QLatin1String("111")); combo.addItem( QLatin1String("222")); combo.show(); - QApplication::setActiveWindow(&combo); QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&combo)); QSignalSpy spy(&combo, &QComboBox::activated); @@ -2445,7 +2493,7 @@ void tst_QComboBox::task247863_keyBoardSelection() QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down); QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Enter); QCOMPARE(combo.currentText(), QLatin1String("222")); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } void tst_QComboBox::task220195_keyBoardSelection2() @@ -2461,7 +2509,6 @@ void tst_QComboBox::task220195_keyBoardSelection2() combo.addItem( QLatin1String("foo2")); combo.addItem( QLatin1String("foo3")); combo.show(); - QApplication::setActiveWindow(&combo); QVERIFY(QTest::qWaitForWindowActive(&combo)); combo.setCurrentIndex(-1); @@ -2720,16 +2767,16 @@ void tst_QComboBox::resetModel() QComboBox cb; StringListModel model({"1", "2"}); QSignalSpy spy(&cb, &QComboBox::currentIndexChanged); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QCOMPARE(cb.currentIndex(), -1); //no selection cb.setModel(&model); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(cb.currentIndex(), 0); //first item selected model.reset(); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); QCOMPARE(cb.currentIndex(), 0); //first item selected } @@ -2747,7 +2794,6 @@ void tst_QComboBox::keyBoardNavigationWithMouse() combo.move(200, 200); combo.showNormal(); - QApplication::setActiveWindow(&combo); QVERIFY(QTest::qWaitForWindowActive(&combo)); QCOMPARE(combo.currentText(), QLatin1String("0")); @@ -2803,17 +2849,16 @@ void tst_QComboBox::task_QTBUG_1071_changingFocusEmitsActivated() layout.addWidget(&edit); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); cb.clearEditText(); cb.setFocus(); QApplication::processEvents(); QTRY_VERIFY(cb.hasFocus()); QTest::keyClick(static_cast<QWidget *>(0), '1'); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); edit.setFocus(); QTRY_VERIFY(edit.hasFocus()); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); } void tst_QComboBox::maxVisibleItems_data() @@ -3155,31 +3200,55 @@ void tst_QComboBox::task_QTBUG_54191_slotOnEditTextChangedSetsComboBoxToReadOnly QCOMPARE(cb.currentIndex(), 1); } +class ComboBox : public QComboBox { +public: + using QComboBox::QComboBox; + + void keyPressEvent(QKeyEvent *e) override + { + QComboBox::keyPressEvent(e); + accepted = e->isAccepted(); + } + bool accepted = false; +}; + void tst_QComboBox::keyboardSelection() { - QComboBox comboBox; + ComboBox comboBox; const int keyboardInterval = QApplication::keyboardInputInterval(); - QStringList list; - list << "OA" << "OB" << "OC" << "OO" << "OP" << "PP"; + const QStringList list = {"OA", "OB", "OC", "OO", "OP", "PP"}; comboBox.addItems(list); // Clear any remaining keyboard input from previous tests. QTest::qWait(keyboardInterval); QTest::keyClicks(&comboBox, "oo", Qt::NoModifier, 50); QCOMPARE(comboBox.currentText(), list.at(3)); + QCOMPARE(comboBox.accepted, true); QTest::qWait(keyboardInterval); QTest::keyClicks(&comboBox, "op", Qt::NoModifier, 50); QCOMPARE(comboBox.currentText(), list.at(4)); + QCOMPARE(comboBox.accepted, true); QTest::keyClick(&comboBox, Qt::Key_P, Qt::NoModifier, keyboardInterval); QCOMPARE(comboBox.currentText(), list.at(5)); + QCOMPARE(comboBox.accepted, true); QTest::keyClick(&comboBox, Qt::Key_O, Qt::NoModifier, keyboardInterval); QCOMPARE(comboBox.currentText(), list.at(0)); + QCOMPARE(comboBox.accepted, true); QTest::keyClick(&comboBox, Qt::Key_O, Qt::NoModifier, keyboardInterval); QCOMPARE(comboBox.currentText(), list.at(1)); + QCOMPARE(comboBox.accepted, true); + + QTest::keyClick(&comboBox, Qt::Key_Tab, Qt::NoModifier, keyboardInterval); + QCOMPARE(comboBox.currentText(), list.at(1)); + QCOMPARE(comboBox.accepted, false); + + QTest::keyClick(&comboBox, Qt::Key_Tab, Qt::ControlModifier, keyboardInterval); + QCOMPARE(comboBox.currentText(), list.at(1)); + QCOMPARE(comboBox.accepted, false); } void tst_QComboBox::updateDelegateOnEditableChange() @@ -3231,11 +3300,11 @@ void tst_QComboBox::respectChangedOwnershipOfItemView() QTableView *v2 = new QTableView(&box1); box1.setView(v2); // Here we do not expect v1 to be deleted QApplication::processEvents(); - QCOMPARE(spy1.count(), 0); + QCOMPARE(spy1.size(), 0); QSignalSpy spy2(v2, SIGNAL(destroyed())); box1.setView(v1); - QCOMPARE(spy2.count(), 1); + QCOMPARE(spy2.size(), 1); } void tst_QComboBox::task_QTBUG_49831_scrollerNotActivated() @@ -3256,14 +3325,14 @@ void tst_QComboBox::task_QTBUG_49831_scrollerNotActivated() QVERIFY(container); QVERIFY(QTest::qWaitForWindowExposed(container)); - QList<QComboBoxPrivateScroller *> scrollers = container->findChildren<QComboBoxPrivateScroller *>(); + const QList<QComboBoxPrivateScroller *> scrollers = container->findChildren<QComboBoxPrivateScroller *>(); // Not all styles support scrollers. We rely only on those platforms that do to catch any regression. if (!scrollers.isEmpty()) { - Q_FOREACH (QComboBoxPrivateScroller *scroller, scrollers) { + for (QComboBoxPrivateScroller *scroller : scrollers) { if (scroller->isVisible()) { QSignalSpy doScrollSpy(scroller, SIGNAL(doScroll(int))); QTest::mouseMove(scroller, QPoint(5, 5), 500); - QTRY_VERIFY(doScrollSpy.count() > 0); + QTRY_VERIFY(doScrollSpy.size() > 0); } } } @@ -3341,6 +3410,65 @@ void tst_QComboBox::task_QTBUG_56693_itemFontFromModel() box.hidePopup(); } +#ifndef QT_NO_STYLE_FUSION +void tst_QComboBox::popupPositionAfterStyleChange() +{ +#ifdef Q_OS_QNX + QSKIP("Fails on QNX, QTBUG-123798"); +#endif + // Check that the popup opens up centered on top of the current + // index if the style has changed since the last time it was + // opened (QTBUG-113765). + QComboBox box; + QStyleOptionComboBox opt; + const bool usePopup = qApp->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, &box); + if (!usePopup) + QSKIP("This test is only relevant for styles that centers the popup on top of the combo!"); + if (QTestPrivate::isRunningArmOnX86()) + QSKIP("Flaky on QEMU, QTBUG-114760"); + + box.addItems({"first", "middle", "last"}); + box.show(); + QVERIFY(QTest::qWaitForWindowExposed(&box)); + box.showPopup(); + + QFrame *container = box.findChild<QComboBoxPrivateContainer *>(); + QVERIFY(container); + QVERIFY(QTest::qWaitForWindowExposed(container)); + + // Select the last menu item, which will close the popup. This item is then expected + // to be centered on top of the combobox the next time the popup opens. + const QRect lastItemRect = box.view()->visualRect(box.view()->model()->index(2, 0)); + QTest::mouseClick(box.view(), Qt::LeftButton, Qt::NoModifier, lastItemRect.center()); + + // Change style. This can make the popup smaller, which will result in up-and-down + // scroll widgets showing in the menu, directly underneath the mouse before the popup + // ends up hidden. This again will trigger the item view to scroll, which seems to be + // the root cause of QTBUG-113765. + qApp->setStyle(QStringLiteral("Fusion")); + + // Click on the combobox again to reopen it. But since both QComboBox + // (QComboBoxPrivateScroller) is using its own internal timer to do scrolling, we + // need to wait a bit until the scrolling is done before we can reopen it (since + // the scrolling is the sore spot that we want to test). + // But note, we expect, but don't require, the popup to scroll. And for that + // reason, we don't see it as a failure if the scrolling doesn't happen. + (void) QTest::qWaitFor([&box]{ return box.view()->verticalScrollBar()->value() > 0; }, 1000); + + // Verify that the popup is hidden before we click the button + QTRY_VERIFY(!container->isVisible()); + QTest::mouseClick(&box, Qt::LeftButton); + + // Click on item under mouse. But wait a bit, to avoid a double click + QTest::qWait(2 * QGuiApplication::styleHints()->mouseDoubleClickInterval()); + QTest::mouseClick(&box, Qt::LeftButton); + + // Ensure that the item that was centered on top of the combobox, and which + // we therefore clicked, was the same item we clicked on the first time. + QTRY_COMPARE(box.currentText(), QStringLiteral("last")); +} +#endif // QT_NO_STYLE_FUSION + void tst_QComboBox::inputMethodUpdate() { if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) @@ -3420,10 +3548,9 @@ void tst_QComboBox::task_QTBUG_52027_mapCompleterIndex() cbox.setCompleter(completer); QSignalSpy spy(&cbox, SIGNAL(activated(int))); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); cbox.move(200, 200); cbox.show(); - QApplication::setActiveWindow(&cbox); QVERIFY(QTest::qWaitForWindowActive(&cbox)); QTest::keyClicks(&cbox, "foobar2"); @@ -3449,7 +3576,6 @@ void tst_QComboBox::task_QTBUG_52027_mapCompleterIndex() cbox.activateWindow(); } - QApplication::setActiveWindow(&cbox); QVERIFY(QTest::qWaitForWindowActive(&cbox)); QTest::keyClicks(&cbox, "foobar1"); @@ -3517,7 +3643,6 @@ void tst_QComboBox::checkEmbeddedLineEditWhenStyleSheetIsSet() layout->addWidget(comboBox); topLevel.show(); comboBox->setEditable(true); - QApplication::setActiveWindow(&topLevel); QVERIFY(QTest::qWaitForWindowActive(&topLevel)); QImage grab = comboBox->grab().toImage(); @@ -3584,7 +3709,7 @@ void tst_QComboBox::buttonPressKeys() const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ->themeHint(QPlatformTheme::ButtonPressKeys) .value<QList<Qt::Key>>(); - for (int i = 0; i < buttonPressKeys.length(); ++i) { + for (int i = 0; i < buttonPressKeys.size(); ++i) { QTest::keyClick(&comboBox, buttonPressKeys[i]); // On some platforms, a window will not be immediately visible, // but take some event-loop iterations to complete. @@ -3614,11 +3739,11 @@ void tst_QComboBox::clearModel() model.setStringList({}); - QCOMPARE(indexSpy.count(), 1); + QCOMPARE(indexSpy.size(), 1); const int index = indexSpy.takeFirst().at(0).toInt(); QCOMPARE(index, -1); - QCOMPARE(textSpy.count(), 1); + QCOMPARE(textSpy.size(), 1); const QString text = textSpy.takeFirst().at(0).toString(); QCOMPARE(text, QString()); @@ -3626,5 +3751,93 @@ void tst_QComboBox::clearModel() QCOMPARE(combo.currentText(), QString()); } +void tst_QComboBox::cancelClosesPopupNotDialog() +{ + if (QGuiApplication::platformName() == "offscreen") + QSKIP("The offscreen platform plugin doesn't activate popups."); + + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + + QDialog dialog; + QComboBox combobox; + combobox.addItems({"A", "B", "C"}); + + std::unique_ptr<QShortcut> shortcut(new QShortcut(QKeySequence::Cancel, &dialog)); + bool shortcutTriggered = false; + connect(shortcut.get(), &QShortcut::activated, [&shortcutTriggered]{ + shortcutTriggered = true; + }); + + QVBoxLayout vbox; + vbox.addWidget(&combobox); + dialog.setLayout(&vbox); + + dialog.show(); + QVERIFY(QTest::qWaitForWindowActive(&dialog)); + + // while the combobox is closed, escape key triggers the shortcut + QTest::keyClick(dialog.window()->windowHandle(), Qt::Key_Escape); + QVERIFY(shortcutTriggered); + shortcutTriggered = false; + + combobox.showPopup(); + QTRY_VERIFY(combobox.view()->isVisible()); + + // an open combobox overrides and accepts the escape key to close + QTest::keyClick(dialog.window()->windowHandle(), Qt::Key_Escape); + QVERIFY(!shortcutTriggered); + shortcutTriggered = false; + QTRY_VERIFY(!combobox.view()->isVisible()); + QVERIFY(dialog.isVisible()); + + // once closed, escape key triggers the shortcut again + QTest::keyClick(dialog.window()->windowHandle(), Qt::Key_Escape); + QVERIFY(shortcutTriggered); + shortcutTriggered = false; + QVERIFY(dialog.isVisible()); + + shortcut.reset(); + + // without shortcut, escape key propagates to the parent + QTest::keyClick(dialog.window()->windowHandle(), Qt::Key_Escape); + QVERIFY(!dialog.isVisible()); +} + +void tst_QComboBox::closePopupWithCheckableItems() +{ + QWidget widget; + + QVBoxLayout *vb = new QVBoxLayout(&widget); + + QLabel *dlgLabel = new QLabel("Click when combo expanded."); + vb->addWidget(dlgLabel); + + QComboBox *combo = new QComboBox(); + vb->addWidget(combo); + + QStandardItemModel model; + const int rowCount = 10; + for (int r = 0; r < rowCount; ++r) { + QString str = "Item: " + QString::number(r); + QStandardItem *item = new QStandardItem(str); + const bool isChecked = (r % 2); + + item->setData(isChecked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole); + item->setFlags(Qt::ItemIsUserCheckable | (item->flags() & ~(Qt::ItemIsSelectable)) ); + model.appendRow(item); + } + + combo->setModel(&model); + + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + QTest::mouseClick(widget.windowHandle(), Qt::LeftButton, {}, combo->geometry().center()); + QVERIFY(QTest::qWaitForWindowExposed(combo->view())); + QTest::mouseClick(widget.windowHandle(), Qt::LeftButton, {}, dlgLabel->geometry().center()); + QTRY_VERIFY(!combo->view()->isVisible()); +} + QTEST_MAIN(tst_QComboBox) #include "tst_qcombobox.moc" diff --git a/tests/auto/widgets/widgets/qcommandlinkbutton/CMakeLists.txt b/tests/auto/widgets/widgets/qcommandlinkbutton/CMakeLists.txt index 8370e01459..b89c5aa1dd 100644 --- a/tests/auto/widgets/widgets/qcommandlinkbutton/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qcommandlinkbutton/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qcommandlinkbutton.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qcommandlinkbutton Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qcommandlinkbutton LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qcommandlinkbutton SOURCES tst_qcommandlinkbutton.cpp diff --git a/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp b/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp index 6b02775786..e0c63e5ced 100644 --- a/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp +++ b/tests/auto/widgets/widgets/qcommandlinkbutton/tst_qcommandlinkbutton.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/widgets/qdatetimeedit/CMakeLists.txt b/tests/auto/widgets/widgets/qdatetimeedit/CMakeLists.txt index 9b5fe88e9a..9c2e777380 100644 --- a/tests/auto/widgets/widgets/qdatetimeedit/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qdatetimeedit/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qdatetimeedit.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qdatetimeedit Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qdatetimeedit LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qdatetimeedit SOURCES tst_qdatetimeedit.cpp diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp index fe20de9d86..2d9689db41 100644 --- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp +++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qapplication.h> #include <qgroupbox.h> @@ -47,6 +47,8 @@ #include <private/qdatetimeedit_p.h> +#include <QtWidgets/private/qapplication_p.h> + #ifdef Q_OS_WIN # include <qt_windows.h> #endif @@ -231,10 +233,12 @@ private slots: void nextPrevSection(); void dateEditTimeEditFormats(); +#if QT_DEPRECATED_SINCE(6, 10) void timeSpec_data(); void timeSpec(); - void timeSpecBug(); - void timeSpecInit(); +#endif + void timeZoneBug(); + void timeZoneInit(); void setDateTime_data(); void setDateTime(); @@ -250,7 +254,7 @@ private slots: void task196924(); void focusNextPrevChild(); - void taskQTBUG_12384_timeSpecShowTimeOnly(); + void taskQTBUG_12384_timeZoneShowTimeOnly(); void deleteCalendarWidget(); @@ -404,8 +408,8 @@ void tst_QDateTimeEdit::initTestCase() qWarning("Running under locale %s/%s -- this test may generate failures due to language differences", qPrintable(QLocale::languageToString(system.language())), qPrintable(QLocale::territoryToString(system.territory()))); - testWidget = new EditorDateEdit(0); - testFocusWidget = new QWidget(0); + testWidget = new EditorDateEdit; + testFocusWidget = new QWidget(nullptr); testFocusWidget->resize(200, 100); testFocusWidget->show(); } @@ -434,7 +438,7 @@ void tst_QDateTimeEdit::cleanup() { testWidget->clearMinimumDateTime(); testWidget->clearMaximumDateTime(); - testWidget->setTimeSpec(Qt::LocalTime); + testWidget->setTimeZone(QTimeZone::LocalTime); testWidget->setSpecialValueText(QString()); testWidget->setWrapping(false); // Restore the default. @@ -823,7 +827,6 @@ void tst_QDateTimeEdit::selectAndScrollWithKeys() return; #endif - qApp->setActiveWindow(testWidget); testWidget->setDate(QDate(2004, 05, 11)); testWidget->setDisplayFormat("dd/MM/yyyy"); testWidget->show(); @@ -925,7 +928,6 @@ void tst_QDateTimeEdit::selectAndScrollWithKeys() void tst_QDateTimeEdit::backspaceKey() { - qApp->setActiveWindow(testWidget); testWidget->setDate(QDate(2004, 05, 11)); testWidget->setDisplayFormat("d/MM/yyyy"); testWidget->show(); @@ -991,7 +993,6 @@ void tst_QDateTimeEdit::backspaceKey() void tst_QDateTimeEdit::deleteKey() { - qApp->setActiveWindow(testWidget); testWidget->setDate(QDate(2004, 05, 11)); testWidget->setDisplayFormat("d/MM/yyyy"); #ifdef Q_OS_MAC @@ -1010,7 +1011,6 @@ void tst_QDateTimeEdit::deleteKey() void tst_QDateTimeEdit::tabKeyNavigation() { - qApp->setActiveWindow(testWidget); testWidget->setDate(QDate(2004, 05, 11)); testWidget->setDisplayFormat("dd/MM/yyyy"); testWidget->show(); @@ -1028,7 +1028,6 @@ void tst_QDateTimeEdit::tabKeyNavigation() void tst_QDateTimeEdit::tabKeyNavigationWithPrefix() { - qApp->setActiveWindow(testWidget); testWidget->setDate(QDate(2004, 05, 11)); testWidget->setDisplayFormat("prefix dd/MM/yyyy"); @@ -1046,7 +1045,6 @@ void tst_QDateTimeEdit::tabKeyNavigationWithPrefix() void tst_QDateTimeEdit::tabKeyNavigationWithSuffix() { - qApp->setActiveWindow(testWidget); testWidget->setDate(QDate(2004, 05, 11)); testWidget->setDisplayFormat("dd/MM/yyyy 'suffix'"); @@ -1062,7 +1060,6 @@ void tst_QDateTimeEdit::tabKeyNavigationWithSuffix() void tst_QDateTimeEdit::enterKey() { - qApp->setActiveWindow(testWidget); testWidget->setDate(QDate(2004, 5, 11)); testWidget->setDisplayFormat("prefix d/MM/yyyy 'suffix'"); testWidget->lineEdit()->setFocus(); @@ -1120,7 +1117,7 @@ void tst_QDateTimeEdit::enterKey() // we include this test so a change to the behaviour can't go unnoticed. QSignalSpy enterSpy(testWidget, SIGNAL(dateChanged(QDate))); QTest::keyClick(testWidget, Qt::Key_Enter); - QCOMPARE(enterSpy.count(), 1); + QCOMPARE(enterSpy.size(), 1); QVariantList list = enterSpy.takeFirst(); QCOMPARE(list.at(0).toDate(), QDate(2004, 5, 9)); } @@ -1314,7 +1311,7 @@ void tst_QDateTimeEdit::editingRanged_data() << QDate(2010, 12, 30) << QTime() << QDate(2011, 1, 2) << QTime() << QString::fromLatin1("01012011") - << QDateTime(QDate(2011, 1, 1), QTime(), Qt::UTC); + << QDateTime(QDate(2011, 1, 1), QTime(), QTimeZone::UTC); } void tst_QDateTimeEdit::editingRanged() @@ -1350,7 +1347,6 @@ void tst_QDateTimeEdit::editingRanged() }); edit->show(); - QApplication::setActiveWindow(edit.get()); if (!QTest::qWaitForWindowActive(edit.get())) QSKIP("Failed to make window active, aborting"); edit->setFocus(); @@ -2195,7 +2191,7 @@ void tst_QDateTimeEdit::dateSignalChecking() QSignalSpy timeSpy(testWidget, SIGNAL(timeChanged(QTime))); testWidget->setDate(newDate); - QCOMPARE(dateSpy.count(), timesEmitted); + QCOMPARE(dateSpy.size(), timesEmitted); if (timesEmitted > 0) { QList<QVariant> list = dateSpy.takeFirst(); @@ -2203,8 +2199,8 @@ void tst_QDateTimeEdit::dateSignalChecking() d = qvariant_cast<QDate>(list.at(0)); QCOMPARE(d, newDate); } - QCOMPARE(dateTimeSpy.count(), timesEmitted); - QCOMPARE(timeSpy.count(), 0); + QCOMPARE(dateTimeSpy.size(), timesEmitted); + QCOMPARE(timeSpy.size(), 0); } void tst_QDateTimeEdit::timeSignalChecking_data() @@ -2231,7 +2227,7 @@ void tst_QDateTimeEdit::timeSignalChecking() QSignalSpy timeSpy(testWidget, SIGNAL(timeChanged(QTime))); testWidget->setTime(newTime); - QCOMPARE(timeSpy.count(), timesEmitted); + QCOMPARE(timeSpy.size(), timesEmitted); if (timesEmitted > 0) { QList<QVariant> list = timeSpy.takeFirst(); @@ -2239,8 +2235,8 @@ void tst_QDateTimeEdit::timeSignalChecking() t = qvariant_cast<QTime>(list.at(0)); QCOMPARE(t, newTime); } - QCOMPARE(dateTimeSpy.count(), timesEmitted); - QCOMPARE(dateSpy.count(), 0); + QCOMPARE(dateTimeSpy.size(), timesEmitted); + QCOMPARE(dateSpy.size(), 0); } void tst_QDateTimeEdit::dateTimeSignalChecking_data() @@ -2281,7 +2277,7 @@ void tst_QDateTimeEdit::dateTimeSignalChecking() QSignalSpy dateTimeSpy(testWidget, SIGNAL(dateTimeChanged(QDateTime))); testWidget->setDateTime(newDateTime); - QCOMPARE(dateSpy.count(), timesDateEmitted); + QCOMPARE(dateSpy.size(), timesDateEmitted); if (timesDateEmitted > 0) { QCOMPARE(timesDateEmitted, 1); QList<QVariant> list = dateSpy.takeFirst(); @@ -2289,14 +2285,14 @@ void tst_QDateTimeEdit::dateTimeSignalChecking() d = qvariant_cast<QDate>(list.at(0)); QCOMPARE(d, newDateTime.date()); } - QCOMPARE(timeSpy.count(), timesTimeEmitted); + QCOMPARE(timeSpy.size(), timesTimeEmitted); if (timesTimeEmitted > 0) { QList<QVariant> list = timeSpy.takeFirst(); QTime t; t = qvariant_cast<QTime>(list.at(0)); QCOMPARE(t, newDateTime.time()); } - QCOMPARE(dateTimeSpy.count(), timesDateTimeEmitted); + QCOMPARE(dateTimeSpy.size(), timesDateTimeEmitted); if (timesDateTimeEmitted > 0) { QList<QVariant> list = dateTimeSpy.takeFirst(); QDateTime dt; @@ -3160,22 +3156,22 @@ void tst_QDateTimeEdit::task149097() testWidget->setDisplayFormat("yyyy/MM/dd hh:mm:ss"); testWidget->setDateTime(QDateTime(QDate(2001, 02, 03), QTime(5, 1, 2))); // QTest::keyClick(testWidget, Qt::Key_Enter); - QCOMPARE(dtSpy.count(), 1); - QCOMPARE(dSpy.count(), 1); - QCOMPARE(tSpy.count(), 1); + QCOMPARE(dtSpy.size(), 1); + QCOMPARE(dSpy.size(), 1); + QCOMPARE(tSpy.size(), 1); testWidget->setCurrentSection(QDateTimeEdit::YearSection); testWidget->stepBy(1); - QCOMPARE(dtSpy.count(), 2); - QCOMPARE(dSpy.count(), 2); - QCOMPARE(tSpy.count(), 1); + QCOMPARE(dtSpy.size(), 2); + QCOMPARE(dSpy.size(), 2); + QCOMPARE(tSpy.size(), 1); testWidget->setCurrentSection(QDateTimeEdit::MinuteSection); testWidget->stepBy(1); - QCOMPARE(dtSpy.count(), 3); - QCOMPARE(dSpy.count(), 2); - QCOMPARE(tSpy.count(), 2); + QCOMPARE(dtSpy.size(), 3); + QCOMPARE(dSpy.size(), 2); + QCOMPARE(tSpy.size(), 2); } void tst_QDateTimeEdit::task148725() @@ -3363,7 +3359,7 @@ void tst_QDateTimeEdit::wheelEvent() QFETCH(QDate, startDate); QFETCH(DateList, expectedDates); - EditorDateEdit edit(0); + EditorDateEdit edit; edit.setDate(startDate); edit.setCurrentSection(section); @@ -3489,6 +3485,7 @@ void tst_QDateTimeEdit::dateEditTimeEditFormats() QCOMPARE(d.displayedSections(), QDateTimeEdit::YearSection); } +#if QT_DEPRECATED_SINCE(6, 10) void tst_QDateTimeEdit::timeSpec_data() { QTest::addColumn<bool>("useSetProperty"); @@ -3496,6 +3493,8 @@ void tst_QDateTimeEdit::timeSpec_data() QTest::newRow("setTimeSpec") << false; } +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED void tst_QDateTimeEdit::timeSpec() { QFETCH(bool, useSetProperty); @@ -3521,7 +3520,7 @@ void tst_QDateTimeEdit::timeSpec() QCOMPARE(edit.timeSpec(), Qt::LocalTime); const QDateTime utc = dt.toUTC(); if (dt.time() != utc.time()) { - const QDateTime min(QDate(1999, 1, 1), QTime(1, 0, 0), Qt::LocalTime); + const QDateTime min(QDate(1999, 1, 1), QTime(1, 0)); edit.setMinimumDateTime(min); QCOMPARE(edit.minimumTime(), min.time()); if (useSetProperty) { @@ -3536,10 +3535,12 @@ void tst_QDateTimeEdit::timeSpec() QSKIP("Not tested in the GMT timezone"); } } +QT_WARNING_POP +#endif // test deprecated timeSpec property -void tst_QDateTimeEdit::timeSpecBug() +void tst_QDateTimeEdit::timeZoneBug() { - testWidget->setTimeSpec(Qt::UTC); + testWidget->setTimeZone(QTimeZone::UTC); testWidget->setDisplayFormat("hh:mm"); testWidget->setTime(QTime(2, 2)); const QString oldText = testWidget->text(); @@ -3549,57 +3550,33 @@ void tst_QDateTimeEdit::timeSpecBug() QCOMPARE(oldText, testWidget->text()); } -void tst_QDateTimeEdit::timeSpecInit() +void tst_QDateTimeEdit::timeZoneInit() { - QDateTime utc(QDate(2000, 1, 1), QTime(12, 0, 0), Qt::UTC); + QDateTime utc(QDate(2000, 1, 1), QTime(12, 0), QTimeZone::UTC); QDateTimeEdit widget(utc); QCOMPARE(widget.dateTime(), utc); } void tst_QDateTimeEdit::setDateTime_data() { - QTest::addColumn<Qt::TimeSpec>("spec"); - QDateTime localNoon(QDate(2019, 12, 24), QTime(12, 0), Qt::LocalTime); -#if 0 // Not yet supported - QTest::addColumn<int>("offset"); - QTest::addColumn<QByteArray>("zoneName"); - - QTest::newRow("OffsetFromUTC/LocalTime") - << Qt::OffsetFromUTC << 7200 << "" - << localNoon << localNoon.toOffsetFromUtc(7200); -#if QT_CONFIG(timezone) - QTest::newRow("TimeZone/LocalTime") - << Qt::TimeZone << 0 << "Europe/Berlin" - << localNoon << localNoon.toTimeZone(QTimeZone("Europe/Berlin")); -#endif -#endif // unsupported + const QDateTime localNoon(QDate(2019, 12, 24), QTime(12, 0)); + const QTimeZone UTC(QTimeZone::UTC), local(QTimeZone::LocalTime); + QTest::addColumn<QTimeZone>("zone"); QTest::addColumn<QDateTime>("store"); QTest::addColumn<QDateTime>("expect"); - QTest::newRow("LocalTime/LocalTime") - << Qt::LocalTime // << 0 << "" - << localNoon << localNoon; - QTest::newRow("LocalTime/UTC") - << Qt::LocalTime // << 0 << "" - << localNoon.toUTC() << localNoon; - QTest::newRow("UTC/LocalTime") - << Qt::UTC // << 0 << "" - << localNoon << localNoon.toUTC(); - QTest::newRow("UTC/UTC") - << Qt::UTC // << 0 << "" - << localNoon.toUTC() << localNoon.toUTC(); + QTest::newRow("LocalTime/LocalTime") << local << localNoon << localNoon; + QTest::newRow("LocalTime/UTC") << local << localNoon.toUTC() << localNoon; + QTest::newRow("UTC/LocalTime") << UTC << localNoon << localNoon.toUTC(); + QTest::newRow("UTC/UTC") << UTC << localNoon.toUTC() << localNoon.toUTC(); } void tst_QDateTimeEdit::setDateTime() { - QFETCH(const Qt::TimeSpec, spec); -#if 0 // Not yet supported - QFETCH(const int, offset); - QFETCH(const QByteArray, zoneName); -#endif // configuring the spec, when OffsetFromUTC or TimeZone + QFETCH(const QTimeZone, zone); QFETCH(const QDateTime, store); QFETCH(const QDateTime, expect); QDateTimeEdit editor; - editor.setTimeSpec(spec); + editor.setTimeZone(zone); editor.setDateTime(store); QCOMPARE(editor.dateTime(), expect); } @@ -3793,14 +3770,14 @@ void tst_QDateTimeEdit::focusNextPrevChild() QCOMPARE(edit.currentSection(), QDateTimeEdit::MonthSection); } -void tst_QDateTimeEdit::taskQTBUG_12384_timeSpecShowTimeOnly() +void tst_QDateTimeEdit::taskQTBUG_12384_timeZoneShowTimeOnly() { QDateTime time = QDateTime::fromString("20100723 04:02:40", "yyyyMMdd hh:mm:ss"); - time.setTimeSpec(Qt::UTC); + time.setTimeZone(QTimeZone::UTC); EditorDateEdit edit; edit.setDisplayFormat("hh:mm:ss"); - edit.setTimeSpec(Qt::UTC); + edit.setTimeZone(QTimeZone::UTC); edit.setDateTime(time); QCOMPARE(edit.minimumTime(), QTime(0, 0, 0, 0)); @@ -3816,7 +3793,7 @@ void tst_QDateTimeEdit::deleteCalendarWidget() QVERIFY(!edit.calendarWidget()); edit.setCalendarPopup(true); QVERIFY(edit.calendarWidget()); - edit.calendarWidget()->setObjectName("cw1");; + edit.calendarWidget()->setObjectName("cw1"); // delete delete edit.calendarWidget(); @@ -4442,7 +4419,7 @@ void tst_QDateTimeEdit::stepModifierButtons() testWidget->hide(); - EditorDateEdit edit(0); + EditorDateEdit edit; edit.setTime(startTime); edit.show(); QVERIFY(QTest::qWaitForWindowActive(&edit)); @@ -4528,11 +4505,15 @@ void tst_QDateTimeEdit::stepModifierPressAndHold() QFETCH(Qt::KeyboardModifiers, modifiers); QFETCH(int, expectedStepModifier); - const QDate startDate(2000, 1, 1); + // Some west African zones (e.g. Niamey, Conakry) changed from 1 hour west + // of GMT to GMT at the start of 1960; and spy.size() can get as high as 4, + // causing the expectedDate below, when expectedStepModifier is -10, to land + // in a transition gap for these zones, if we use Jan 1st; so use Jan 2nd. + const QDate startDate(2000, 1, 2); testWidget->hide(); - EditorDateEdit edit(0); + EditorDateEdit edit; edit.setDate(startDate); QScopedPointer<StepModifierStyle, QScopedPointerDeleteLater> stepModifierStyle( @@ -4553,12 +4534,12 @@ void tst_QDateTimeEdit::stepModifierPressAndHold() QStyle::CC_SpinBox, &spinBoxStyleOption, subControl, &edit); QTest::mousePress(&edit, Qt::LeftButton, modifiers, buttonRect.center()); - QTRY_VERIFY(spy.length() >= 3); + QTRY_VERIFY(spy.size() >= 3); QTest::mouseRelease(&edit, Qt::LeftButton, modifiers, buttonRect.center()); const auto value = spy.last().at(0); QVERIFY(value.userType() == QMetaType::QDate); - const QDate expectedDate = startDate.addYears(spy.length() * + const QDate expectedDate = startDate.addYears(spy.size() * expectedStepModifier); QCOMPARE(value.toDate(), expectedDate); } @@ -4582,13 +4563,20 @@ static QDateTime findSpring(int year, const QTimeZone &timeZone) const QTimeZone::OffsetData transition = midSummer.isDaylightTime() ? timeZone.previousTransition(midSummer) : timeZone.nextTransition(midSummer); - const QDateTime spring = transition.atUtc.toLocalTime(); + const QDateTime spring = transition.atUtc.toTimeZone(timeZone); // there might have been DST at some point, but not in the year we care about if (spring.date().year() != year || !spring.isDaylightTime()) return QDateTime(); return spring; }; + +// Number of missing seconds between a day before and a day after when. +// If when is the time of a spring-forward transition, this is the width of its gap. +static int missingSecondsNear(const QDateTime &when) +{ + return 2 * 24 * 60 * 60 - when.addDays(-1).secsTo(when.addDays(1)); +} #endif /*! @@ -4612,36 +4600,40 @@ void tst_QDateTimeEdit::springForward_data() QSKIP("Failed to obtain valid spring forward datetime for 2019!"); const QDate springDate = springTransition.date(); - const int gapWidth = timeZone.daylightTimeOffset(springTransition.addDays(1)); + const int gapWidth = missingSecondsNear(springTransition); + if (gapWidth <= 0) + QSKIP("Spring forward transition did not actually skip any time!"); + const QTime springGap = springTransition.time().addSecs(-gapWidth); - const QByteArray springTime = springGap.toString("hh:mm").toLocal8Bit(); - const QTime springGapMiddle = springTransition.time().addSecs(-gapWidth/2); + const QTime springGapMiddle = springTransition.time().addSecs(-gapWidth / 2); + const QByteArray startGapTime = springGap.toString("hh:mm").toLocal8Bit(); + const QByteArray midGapTime = springGapMiddle.toString("hh:mm").toLocal8Bit(); - QTest::addRow("forward to %s, correct to previous", springTime.data()) + QTest::addRow("forward to %s, correct to previous", startGapTime.data()) << QDateTime(springDate, springGap.addSecs(-gapWidth)) << QAbstractSpinBox::CorrectToPreviousValue << springGap << QDateTime(springDate, springGap.addSecs(-gapWidth)); - QTest::addRow("back to %s, correct to previous", springTime.data()) + QTest::addRow("back to %s, correct to previous", startGapTime.data()) << springTransition << QAbstractSpinBox::CorrectToPreviousValue << springGap << springTransition; - QTest::addRow("forward to %s, correct to nearest", springTime.data()) + QTest::addRow("forward to %s, correct to nearest", midGapTime.data()) << QDateTime(springDate, springGap.addSecs(-gapWidth)) << QAbstractSpinBox::CorrectToNearestValue << springGapMiddle << springTransition; - QTest::addRow("back to %s, correct to nearest", springTime.data()) + QTest::addRow("back to %s, correct to nearest", midGapTime.data()) << springTransition << QAbstractSpinBox::CorrectToNearestValue << springGapMiddle << springTransition; - QTest::addRow("jump to %s, correct to nearest", qPrintable(springGapMiddle.toString("hh:mm"))) + QTest::addRow("jump to %s, correct to nearest", midGapTime.data()) << QDateTime(QDate(1980, 5, 10), springGap) << QAbstractSpinBox::CorrectToNearestValue << springGapMiddle @@ -4669,11 +4661,11 @@ void tst_QDateTimeEdit::springForward() edit.setSelectedSection(QDateTimeEdit::DaySection); const QDate date = expected.date(); - const QString day = QString::number(date.day()).rightJustified(2, QLatin1Char('0')); - const QString month = QString::number(date.month()).rightJustified(2, QLatin1Char('0')); + const QString day = QString::number(date.day()).rightJustified(2, u'0'); + const QString month = QString::number(date.month()).rightJustified(2, u'0'); const QString year = QString::number(date.year()); - const QString hour = QString::number(inputTime.hour()).rightJustified(2, QLatin1Char('0')); - const QString minute = QString::number(inputTime.minute()).rightJustified(2, QLatin1Char('0')); + const QString hour = QString::number(inputTime.hour()).rightJustified(2, u'0'); + const QString minute = QString::number(inputTime.minute()).rightJustified(2, u'0'); QTest::keyClicks(&edit, day); QTest::keyClicks(&edit, month); QTest::keyClicks(&edit, year); @@ -4700,7 +4692,7 @@ void tst_QDateTimeEdit::stepIntoDSTGap_data() QTest::addColumn<int>("steps"); QTest::addColumn<QDateTime>("end"); - const QTimeZone timeZone = QTimeZone("Europe/Oslo"); + const QTimeZone timeZone = QTimeZone::systemTimeZone(); if (!timeZone.hasDaylightTime()) QSKIP("This test needs to run in a timezone that observes DST!"); @@ -4709,11 +4701,14 @@ void tst_QDateTimeEdit::stepIntoDSTGap_data() QSKIP("Failed to obtain valid spring forward datetime for 2007!"); const QDate spring = springTransition.date(); - const int gapWidth = timeZone.daylightTimeOffset(springTransition.addDays(1)); + const int gapWidth = missingSecondsNear(springTransition); + if (gapWidth <= 0) + QSKIP("Spring forward transition did not actually skip any time!"); + const QTime springGap = springTransition.time().addSecs(-gapWidth); const QByteArray springTime = springGap.toString("hh:mm").toLocal8Bit(); - // change hour + // change hour (can't change day): if (springGap.hour() != 0) { QTest::addRow("hour up into %s gap", springTime.data()) << QDateTime(spring, springGap.addSecs(-3600)) @@ -4723,7 +4718,7 @@ void tst_QDateTimeEdit::stepIntoDSTGap_data() // 3:00:10 into 2:00:10 should get us to 1:00:10 QTest::addRow("hour down into %s gap", springTime.data()) - << QDateTime(spring, springGap.addSecs(3610)) + << QDateTime(spring, springGap.addSecs(gapWidth + 10)) << QDateTimeEdit::HourSection << -1 << QDateTime(spring, springGap.addSecs(-3590)); @@ -4748,28 +4743,31 @@ void tst_QDateTimeEdit::stepIntoDSTGap_data() } // change month - QTest::addRow("month up into %s gap", springTime.data()) - << QDateTime(spring.addMonths(-1), springGap) - << QDateTimeEdit::MonthSection - << +1 - << springTransition; - QTest::addRow("month down into %s gap", springTime.data()) - << QDateTime(spring.addMonths(1), springGap) - << QDateTimeEdit::MonthSection - << -1 - << springTransition; + // Previous month may well be February, so lack the day-of-month that + // matches spring (e.g. Asia/Jerusalem, March 30). + if (QDate prior = spring.addMonths(-1); prior.day() == spring.day()) { + QTest::addRow("month up into %s gap", springTime.data()) + << QDateTime(prior, springGap) << QDateTimeEdit::MonthSection << +1 << springTransition; + } + // America/{Jujuy,Cordoba,Catamarca} did a 2007 Dec 30th 00:00 spring + // forward; and QDTE month steps won't change the year. + if (QDate prior = spring.addMonths(1); + prior.year() == spring.year() && prior.day() == spring.day()) { + QTest::addRow("month down into %s gap", springTime.data()) + << QDateTime(prior, springGap) << QDateTimeEdit::MonthSection << -1 << springTransition; + } // change year - QTest::addRow("year up into %s gap", springTime.data()) - << QDateTime(spring.addYears(-1), springGap) - << QDateTimeEdit::YearSection - << +1 - << springTransition; - QTest::addRow("year down into %s gap", springTime.data()) - << QDateTime(spring.addYears(1), springGap) - << QDateTimeEdit::YearSection - << -1 - << springTransition; + // Some zones (e.g. Asia/Baghdad) do transitions on a fixed date; for these, + // the springGap moment is invalid every year, so skip this test. + if (QDateTime prior = QDateTime(spring.addYears(-1), springGap); prior.isValid()) { + QTest::addRow("year up into %s gap", springTime.data()) + << prior << QDateTimeEdit::YearSection << +1 << springTransition; + } + if (QDateTime later(spring.addYears(1), springGap); later.isValid()) { + QTest::addRow("year down into %s gap", springTime.data()) + << later << QDateTimeEdit::YearSection << -1 << springTransition; + } #else QSKIP("Needs timezone feature enabled"); #endif diff --git a/tests/auto/widgets/widgets/qdial/CMakeLists.txt b/tests/auto/widgets/widgets/qdial/CMakeLists.txt index 21344be2c8..5e300eec94 100644 --- a/tests/auto/widgets/widgets/qdial/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qdial/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qdial.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qdial Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qdial LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qdial SOURCES tst_qdial.cpp diff --git a/tests/auto/widgets/widgets/qdial/tst_qdial.cpp b/tests/auto/widgets/widgets/qdial/tst_qdial.cpp index 3008714576..d0274ace2a 100644 --- a/tests/auto/widgets/widgets/qdial/tst_qdial.cpp +++ b/tests/auto/widgets/widgets/qdial/tst_qdial.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -17,6 +17,7 @@ private slots: void valueChanged(); void sliderMoved(); void wrappingCheck(); + void minEqualMaxValueOutsideRange(); void notchSize_data(); void notchSize(); @@ -52,14 +53,14 @@ void tst_QDial::valueChanged() dial.setMaximum(100); QSignalSpy spy(&dial, SIGNAL(valueChanged(int))); dial.setValue(50); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); dial.setValue(25); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); // repeat! dial.setValue(25); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QDial::sliderMoved() @@ -88,8 +89,8 @@ void tst_QDial::sliderMoved() QMouseEvent moveevent(QEvent::MouseMove, init, dial.mapToGlobal(init), Qt::LeftButton, Qt::LeftButton, {}); qApp->sendEvent(&dial, &moveevent); - QCOMPARE( sliderspy.count(), 1); - QCOMPARE( valuespy.count(), 0); + QCOMPARE( sliderspy.size(), 1); + QCOMPARE( valuespy.size(), 0); } @@ -98,14 +99,14 @@ void tst_QDial::sliderMoved() QMouseEvent moveevent(QEvent::MouseMove, init, dial.mapToGlobal(init), Qt::LeftButton, Qt::LeftButton, {}); qApp->sendEvent(&dial, &moveevent); - QCOMPARE( sliderspy.count(), 2); - QCOMPARE( valuespy.count(), 0); + QCOMPARE( sliderspy.size(), 2); + QCOMPARE( valuespy.size(), 0); } QMouseEvent releaseevent(QEvent::MouseButtonRelease, init, dial.mapToGlobal(init), Qt::LeftButton, Qt::LeftButton, {}); qApp->sendEvent(&dial, &releaseevent); - QCOMPARE( valuespy.count(), 1); // valuechanged signal should be called at this point + QCOMPARE( valuespy.size(), 1); // valuechanged signal should be called at this point } @@ -172,6 +173,15 @@ void tst_QDial::wrappingCheck() } } +// QTBUG-104641 +void tst_QDial::minEqualMaxValueOutsideRange() +{ + QDial dial; + dial.setRange(30, 30); + dial.setWrapping(true); + dial.setValue(45); +} + /* Verify that the notchSizes calculated don't change compared to Qt 5.15 results for dial sizes at the edge values of the diff --git a/tests/auto/widgets/widgets/qdialogbuttonbox/CMakeLists.txt b/tests/auto/widgets/widgets/qdialogbuttonbox/CMakeLists.txt index fc5db81839..098b129cbc 100644 --- a/tests/auto/widgets/widgets/qdialogbuttonbox/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qdialogbuttonbox/CMakeLists.txt @@ -1,16 +1,21 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qdialogbuttonbox.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qdialogbuttonbox Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qdialogbuttonbox LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qdialogbuttonbox SOURCES tst_qdialogbuttonbox.cpp LIBRARIES Qt::Gui Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp b/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp index c2a9f27295..3e7dc92da1 100644 --- a/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp +++ b/tests/auto/widgets/widgets/qdialogbuttonbox/tst_qdialogbuttonbox.cpp @@ -1,13 +1,17 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QSignalSpy> #include <QtWidgets/QPushButton> #include <QtWidgets/QStyle> #include <QtWidgets/QLayout> #include <QtWidgets/QDialog> +#include <QtWidgets/QLineEdit> #include <QtGui/QAction> +#include <QtGui/QStyleHints> #include <qdialogbuttonbox.h> +#include <QtWidgets/private/qdialogbuttonbox_p.h> +#include <QtWidgets/private/qabstractbutton_p.h> #include <limits.h> Q_DECLARE_METATYPE(QDialogButtonBox::ButtonRole) @@ -49,6 +53,10 @@ private slots: void clear(); void removeButton_data(); void removeButton(); +#ifdef QT_BUILD_INTERNAL + void hideAndShowButton(); +#endif + void hideAndShowStandardButton(); void buttonRole_data(); void buttonRole(); void setStandardButtons_data(); @@ -74,6 +82,9 @@ private slots: void task191642_default(); void testDeletedStandardButton(); + void automaticDefaultButton(); + void initialFocus_data(); + void initialFocus(); private: qint64 timeStamp; @@ -97,7 +108,7 @@ void tst_QDialogButtonBox::testConstructor1() QDialogButtonBox buttonbox; QCOMPARE(buttonbox.orientation(), Qt::Horizontal); - QCOMPARE(buttonbox.buttons().count(), 0); + QCOMPARE(buttonbox.buttons().size(), 0); } void tst_QDialogButtonBox::layoutReuse() @@ -130,7 +141,7 @@ void tst_QDialogButtonBox::testConstructor2() QDialogButtonBox buttonBox(orient); QCOMPARE(buttonBox.orientation(), orient); - QCOMPARE(buttonBox.buttons().count(), 0); + QCOMPARE(buttonBox.buttons().size(), 0); } void tst_QDialogButtonBox::testConstructor3_data() @@ -167,7 +178,7 @@ void tst_QDialogButtonBox::testConstructor3() QDialogButtonBox buttonBox(buttons, (Qt::Orientation)orientation); QCOMPARE(int(buttonBox.orientation()), orientation); - QTEST(int(buttonBox.buttons().count()), "buttonCount"); + QTEST(int(buttonBox.buttons().size()), "buttonCount"); } void tst_QDialogButtonBox::testConstructor4_data() @@ -202,7 +213,7 @@ void tst_QDialogButtonBox::testConstructor4() QDialogButtonBox buttonBox(buttons); QCOMPARE(buttonBox.orientation(), Qt::Horizontal); - QTEST(int(buttonBox.buttons().count()), "buttonCount"); + QTEST(int(buttonBox.buttons().size()), "buttonCount"); } void tst_QDialogButtonBox::setOrientation_data() @@ -265,12 +276,12 @@ void tst_QDialogButtonBox::addButton1() { QFETCH(QDialogButtonBox::ButtonRole, role); QDialogButtonBox buttonBox; - QCOMPARE(buttonBox.buttons().count(), 0); + QCOMPARE(buttonBox.buttons().size(), 0); QPushButton *button = new QPushButton(); buttonBox.addButton(button, role); - QTEST(int(buttonBox.buttons().count()), "totalCount"); + QTEST(int(buttonBox.buttons().size()), "totalCount"); QList<QAbstractButton *> children = buttonBox.findChildren<QAbstractButton *>(); - QTEST(int(children.count()), "totalCount"); + QTEST(int(children.size()), "totalCount"); delete button; } @@ -293,11 +304,11 @@ void tst_QDialogButtonBox::addButton2() QFETCH(QString, text); QFETCH(QDialogButtonBox::ButtonRole, role); QDialogButtonBox buttonBox; - QCOMPARE(buttonBox.buttons().count(), 0); + QCOMPARE(buttonBox.buttons().size(), 0); buttonBox.addButton(text, role); - QTEST(int(buttonBox.buttons().count()), "totalCount"); + QTEST(int(buttonBox.buttons().size()), "totalCount"); QList<QAbstractButton *> children = buttonBox.findChildren<QAbstractButton *>(); - QTEST(int(children.count()), "totalCount"); + QTEST(int(children.size()), "totalCount"); } void tst_QDialogButtonBox::addButton3_data() @@ -320,11 +331,11 @@ void tst_QDialogButtonBox::addButton3() { QFETCH(QDialogButtonBox::StandardButton, button); QDialogButtonBox buttonBox; - QCOMPARE(buttonBox.buttons().count(), 0); + QCOMPARE(buttonBox.buttons().size(), 0); buttonBox.addButton(button); - QTEST(int(buttonBox.buttons().count()), "totalCount"); + QTEST(int(buttonBox.buttons().size()), "totalCount"); QList<QAbstractButton *> children = buttonBox.findChildren<QAbstractButton *>(); - QTEST(int(children.count()), "totalCount"); + QTEST(int(children.size()), "totalCount"); } void tst_QDialogButtonBox::clear_data() @@ -344,9 +355,9 @@ void tst_QDialogButtonBox::clear() for (int i = 1; i < rolesToAdd; ++i) buttonBox.addButton("Happy", QDialogButtonBox::ButtonRole(i)); buttonBox.clear(); - QCOMPARE(buttonBox.buttons().count(), 0); + QCOMPARE(buttonBox.buttons().size(), 0); QList<QAbstractButton *> children = buttonBox.findChildren<QAbstractButton *>(); - QCOMPARE(children.count(), 0); + QCOMPARE(children.size(), 0); } void tst_QDialogButtonBox::removeButton_data() @@ -362,31 +373,95 @@ void tst_QDialogButtonBox::removeButton() QFETCH(QDialogButtonBox::ButtonRole, roleToAdd); QDialogButtonBox buttonBox; - QCOMPARE(buttonBox.buttons().count(), 0); + QCOMPARE(buttonBox.buttons().size(), 0); QPushButton *button = new QPushButton("RemoveButton test"); buttonBox.addButton(button, roleToAdd); - QTEST(int(buttonBox.buttons().count()), "expectedCount"); + QTEST(int(buttonBox.buttons().size()), "expectedCount"); buttonBox.removeButton(button); - QCOMPARE(buttonBox.buttons().count(), 0); + QCOMPARE(buttonBox.buttons().size(), 0); delete button; } +#ifdef QT_BUILD_INTERNAL +void tst_QDialogButtonBox::hideAndShowButton() +{ + if (QGuiApplication::styleHints()->tabFocusBehavior() == Qt::NoTabFocus) + QSKIP("Test skipped with Qt::NoTabFocus"); + + QDialogButtonBox buttonBox; + QDialogButtonBoxPrivate *d = static_cast<QDialogButtonBoxPrivate *>(QObjectPrivate::get(&buttonBox)); + auto *apply = buttonBox.addButton( "Apply", QDialogButtonBox::ApplyRole ); + auto *accept = buttonBox.addButton( "Accept", QDialogButtonBox::AcceptRole ); + buttonBox.addButton( "Reject", QDialogButtonBox::RejectRole ); + auto *widget = new QWidget(); + auto *layout = new QHBoxLayout(widget); + layout->addWidget(&buttonBox); + + // apply button shows first on macOS. accept button on all other OSes. + QAbstractButton *hideButton; +#ifdef Q_OS_MACOS + hideButton = apply; + Q_UNUSED(accept); +#else + hideButton = accept; + Q_UNUSED(apply); +#endif + + hideButton->hide(); + widget->show(); + QVERIFY(QTest::qWaitForWindowExposed(widget)); + QTRY_VERIFY(buttonBox.focusWidget()); // QTBUG-114377: Without fixing, focusWidget() == nullptr + QCOMPARE(d->visibleButtons().count(), 2); + QCOMPARE(d->hiddenButtons.count(), 1); + QVERIFY(d->hiddenButtons.contains(hideButton)); + QCOMPARE(buttonBox.buttons().count(), 3); + QSignalSpy spy(qApp, &QApplication::focusChanged); + QTest::sendKeyEvent(QTest::KeyAction::Click, &buttonBox, Qt::Key_Tab, QString(), Qt::KeyboardModifiers()); + QCOMPARE(spy.count(), 1); // QTBUG-114377: Without fixing, tabbing wouldn't work. + hideButton->show(); + QCOMPARE_GE(spy.count(), 1); + QTRY_COMPARE(QApplication::focusWidget(), hideButton); + QCOMPARE(d->visibleButtons().count(), 3); + QCOMPARE(d->hiddenButtons.count(), 0); + QCOMPARE(buttonBox.buttons().count(), 3); + spy.clear(); + QTest::sendKeyEvent(QTest::KeyAction::Click, &buttonBox, Qt::Key_Backtab, QString(), Qt::KeyboardModifiers()); + QCOMPARE(spy.count(), 1); +} +#endif + +void tst_QDialogButtonBox::hideAndShowStandardButton() +{ + QDialogButtonBox buttonBox; + buttonBox.setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + buttonBox.show(); + QVERIFY(QTest::qWaitForWindowExposed(&buttonBox)); + auto *button = buttonBox.button(QDialogButtonBox::Cancel); + QVERIFY(button); + button->hide(); + QVERIFY(QTest::qWaitFor([button](){ return !button->isVisible(); })); + QCOMPARE(button, buttonBox.button(QDialogButtonBox::Cancel)); + button->show(); + QVERIFY(QTest::qWaitForWindowExposed(button)); + QCOMPARE(button, buttonBox.button(QDialogButtonBox::Cancel)); +} + void tst_QDialogButtonBox::testDelete() { QDialogButtonBox buttonBox; - QCOMPARE(buttonBox.buttons().count(), 0); + QCOMPARE(buttonBox.buttons().size(), 0); QPushButton *deleteMe = new QPushButton("Happy"); buttonBox.addButton(deleteMe, QDialogButtonBox::HelpRole); - QCOMPARE(buttonBox.buttons().count(), 1); + QCOMPARE(buttonBox.buttons().size(), 1); QList<QAbstractButton *> children = buttonBox.findChildren<QAbstractButton *>(); - QCOMPARE(children.count(), 1); + QCOMPARE(children.size(), 1); delete deleteMe; children = buttonBox.findChildren<QAbstractButton *>(); - QCOMPARE(children.count(), 0); - QCOMPARE(buttonBox.buttons().count(), 0); + QCOMPARE(children.size(), 0); + QCOMPARE(buttonBox.buttons().size(), 0); } class ObjectDeleter : public QObject @@ -408,7 +483,7 @@ void tst_QDialogButtonBox::testSignalEmissionAfterDelete_QTBUG_45835() { { QDialogButtonBox buttonBox; - QCOMPARE(buttonBox.buttons().count(), 0); + QCOMPARE(buttonBox.buttons().size(), 0); QSignalSpy buttonClickedSpy(&buttonBox, &QDialogButtonBox::clicked); QVERIFY(buttonClickedSpy.isValid()); @@ -417,21 +492,21 @@ void tst_QDialogButtonBox::testSignalEmissionAfterDelete_QTBUG_45835() QVERIFY(buttonBoxAcceptedSpy.isValid()); QPushButton *button = buttonBox.addButton("Test", QDialogButtonBox::AcceptRole); - QCOMPARE(buttonBox.buttons().count(), 1); + QCOMPARE(buttonBox.buttons().size(), 1); ObjectDeleter objectDeleter; connect(&buttonBox, &QDialogButtonBox::clicked, &objectDeleter, &ObjectDeleter::deleteButton); button->click(); - QCOMPARE(buttonBox.buttons().count(), 0); - QCOMPARE(buttonClickedSpy.count(), 1); - QCOMPARE(buttonBoxAcceptedSpy.count(), 1); + QCOMPARE(buttonBox.buttons().size(), 0); + QCOMPARE(buttonClickedSpy.size(), 1); + QCOMPARE(buttonBoxAcceptedSpy.size(), 1); } { QPointer<QDialogButtonBox> buttonBox(new QDialogButtonBox); - QCOMPARE(buttonBox->buttons().count(), 0); + QCOMPARE(buttonBox->buttons().size(), 0); QSignalSpy buttonClickedSpy(buttonBox.data(), &QDialogButtonBox::clicked); QVERIFY(buttonClickedSpy.isValid()); @@ -440,7 +515,7 @@ void tst_QDialogButtonBox::testSignalEmissionAfterDelete_QTBUG_45835() QVERIFY(buttonBoxAcceptedSpy.isValid()); QPushButton *button = buttonBox->addButton("Test", QDialogButtonBox::AcceptRole); - QCOMPARE(buttonBox->buttons().count(), 1); + QCOMPARE(buttonBox->buttons().size(), 1); ObjectDeleter objectDeleter; connect(buttonBox.data(), &QDialogButtonBox::clicked, &objectDeleter, &ObjectDeleter::deleteSender); @@ -448,8 +523,8 @@ void tst_QDialogButtonBox::testSignalEmissionAfterDelete_QTBUG_45835() button->click(); QVERIFY(buttonBox.isNull()); - QCOMPARE(buttonClickedSpy.count(), 1); - QCOMPARE(buttonBoxAcceptedSpy.count(), 0); + QCOMPARE(buttonClickedSpy.size(), 1); + QCOMPARE(buttonBoxAcceptedSpy.size(), 0); } } @@ -457,24 +532,24 @@ void tst_QDialogButtonBox::testMultipleAdd() { // Add a button into the thing multiple times. QDialogButtonBox buttonBox; - QCOMPARE(buttonBox.buttons().count(), 0); + QCOMPARE(buttonBox.buttons().size(), 0); QPushButton *button = new QPushButton("Foo away"); buttonBox.addButton(button, QDialogButtonBox::AcceptRole); - QCOMPARE(buttonBox.buttons().count(), 1); + QCOMPARE(buttonBox.buttons().size(), 1); QCOMPARE(buttonBox.buttonRole(button), QDialogButtonBox::AcceptRole); buttonBox.addButton(button, QDialogButtonBox::AcceptRole); - QCOMPARE(buttonBox.buttons().count(), 1); + QCOMPARE(buttonBox.buttons().size(), 1); QCOMPARE(buttonBox.buttonRole(button), QDialogButtonBox::AcceptRole); // Add it again with a different role buttonBox.addButton(button, QDialogButtonBox::RejectRole); - QCOMPARE(buttonBox.buttons().count(), 1); + QCOMPARE(buttonBox.buttons().size(), 1); QCOMPARE(buttonBox.buttonRole(button), QDialogButtonBox::RejectRole); // Add it as an "invalid" role buttonBox.addButton(button, QDialogButtonBox::InvalidRole); - QCOMPARE(buttonBox.buttons().count(), 1); + QCOMPARE(buttonBox.buttons().size(), 1); QCOMPARE(buttonBox.buttonRole(button), QDialogButtonBox::RejectRole); } @@ -594,13 +669,13 @@ void tst_QDialogButtonBox::testSignals() if (clickMe) clickMe->click(); - QTRY_COMPARE(clicked2.count(), clicked2Count); - if (clicked2.count() > 0) + QTRY_COMPARE(clicked2.size(), clicked2Count); + if (clicked2.size() > 0) QCOMPARE(qvariant_cast<QAbstractButton *>(clicked2.at(0).at(0)), clickMe); - QTEST(int(accept.count()), "acceptCount"); - QTEST(int(reject.count()), "rejectCount"); - QTEST(int(helpRequested.count()), "helpRequestedCount"); + QTEST(int(accept.size()), "acceptCount"); + QTEST(int(reject.size()), "rejectCount"); + QTEST(int(helpRequested.size()), "helpRequestedCount"); } void tst_QDialogButtonBox::testSignalOrder() @@ -756,7 +831,7 @@ void tst_QDialogButtonBox::testRemove() button->click(); QTest::qWait(100); - QCOMPARE(clicked.count(), 0); + QCOMPARE(clicked.size(), 0); delete button; } @@ -818,7 +893,7 @@ void tst_QDialogButtonBox::task191642_default() QVERIFY(QTest::qWaitForWindowActive(&dlg)); QVERIFY(def->isDefault()); QTest::keyPress( &dlg, Qt::Key_Enter ); - QCOMPARE(clicked.count(), 1); + QCOMPARE(clicked.size(), 1); } void tst_QDialogButtonBox::testDeletedStandardButton() @@ -838,5 +913,87 @@ void tst_QDialogButtonBox::testDeletedStandardButton() QVERIFY(!buttonC); } +void tst_QDialogButtonBox::automaticDefaultButton() +{ + // Having a QDialogButtonBox inside a QDialog triggers Qt to + // enable autoDefault for QPushButtons inside the button box. + // Check that the logic for resolving a default button based + // on the Accept role is not overridden by the first button + // in the dialog (the focus proxy) taking focus, and hence + // stealing the default button state. + + { + QDialog dialog; + QDialogButtonBox *bb = new QDialogButtonBox(&dialog); + // Force horizontal orientation, where we know the order between + // Reset and Accept roles are always the same for all layouts. + bb->setOrientation(Qt::Horizontal); + auto *okButton = bb->addButton(QDialogButtonBox::Ok); + auto *resetButton = bb->addButton(QDialogButtonBox::Reset); + // Double check our assumption about Reset being first + QCOMPARE(bb->layout()->itemAt(0)->widget(), resetButton); + + dialog.show(); + QVERIFY(QTest::qWaitForWindowActive(&dialog)); + + QVERIFY(okButton->isDefault()); + QSignalSpy buttonClicked(okButton, &QPushButton::clicked); + QTest::keyPress(&dialog, Qt::Key_Enter); + QCOMPARE(buttonClicked.count(), 1); + } + + // However, if an explicit button has been focused, we respect that. + + { + QDialog dialog; + QDialogButtonBox *bb = new QDialogButtonBox(&dialog); + bb->setOrientation(Qt::Horizontal); + bb->addButton(QDialogButtonBox::Ok); + auto *resetButton = bb->addButton(QDialogButtonBox::Reset); + resetButton->setFocus(); + dialog.show(); + QVERIFY(QTest::qWaitForWindowActive(&dialog)); + + QVERIFY(resetButton->isDefault()); + QSignalSpy buttonClicked(resetButton, &QPushButton::clicked); + QTest::keyPress(&dialog, Qt::Key_Enter); + QCOMPARE(buttonClicked.count(), 1); + } +} + +void tst_QDialogButtonBox::initialFocus_data() +{ + QTest::addColumn<Qt::FocusPolicy>("focusPolicy"); + QTest::addColumn<bool>("lineEditHasFocus"); + + QTest::addRow("TabFocus") << Qt::FocusPolicy::TabFocus << false; + QTest::addRow("StrongFocus") << Qt::FocusPolicy::StrongFocus << true; + QTest::addRow("NoFocus") << Qt::FocusPolicy::NoFocus << false; + QTest::addRow("ClickFocus") << Qt::FocusPolicy::ClickFocus << false; + QTest::addRow("WheelFocus") << Qt::FocusPolicy::WheelFocus << false; +} + +void tst_QDialogButtonBox::initialFocus() +{ + QFETCH(const Qt::FocusPolicy, focusPolicy); + QFETCH(const bool, lineEditHasFocus); + QDialog dialog; + QVBoxLayout *layout = new QVBoxLayout(&dialog); + QLineEdit *lineEdit = new QLineEdit(&dialog); + lineEdit->setFocusPolicy(focusPolicy); + layout->addWidget(lineEdit); + QDialogButtonBox *dialogButtonBox = new QDialogButtonBox(&dialog); + layout->addWidget(dialogButtonBox); + dialogButtonBox->addButton(QDialogButtonBox::Reset); + const auto *firstAcceptButton = dialogButtonBox->addButton(QDialogButtonBox::Ok); + dialogButtonBox->addButton(QDialogButtonBox::Cancel); + dialog.show(); + dialog.activateWindow(); + if (lineEditHasFocus) + QTRY_VERIFY(lineEdit->hasFocus()); + else + QTRY_VERIFY(firstAcceptButton->hasFocus()); +} + QTEST_MAIN(tst_QDialogButtonBox) #include "tst_qdialogbuttonbox.moc" diff --git a/tests/auto/widgets/widgets/qdockwidget/BLACKLIST b/tests/auto/widgets/widgets/qdockwidget/BLACKLIST index 8b7a126b4d..8873589ff4 100644 --- a/tests/auto/widgets/widgets/qdockwidget/BLACKLIST +++ b/tests/auto/widgets/widgets/qdockwidget/BLACKLIST @@ -5,23 +5,32 @@ android # QDockWidget::isFloating() is flaky after state change on these OS [closeAndDelete] macos +b2qt +arm +android + +# QTBUG-103091 [floatingTabs] +arm +android +qnx +macos +b2qt + # QTBUG-103091 +[hoverWithoutDrop] +arm +android qnx macos -[closeAndDelete] b2qt -[floatingTabs] -macos b2qt arm android -[closeAndDelete] + +# OSes are flaky because of unplugging and plugging requires +# precise calculation of the title bar area for mouse emulation +# That's not possible for floating dock widgets. +[deleteFloatingTabWithSingleDockWidget] +qnx b2qt -[floatingTabs] arm -[closeAndDelete] -macos b2qt arm android -[floatingTabs] -arm -[closeAndDelete] -android -[floatingTabs] android +macos diff --git a/tests/auto/widgets/widgets/qdockwidget/CMakeLists.txt b/tests/auto/widgets/widgets/qdockwidget/CMakeLists.txt index 0f3837aef3..21d8fb60cc 100644 --- a/tests/auto/widgets/widgets/qdockwidget/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qdockwidget/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qdockwidget.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qdockwidget Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qdockwidget LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qdockwidget SOURCES tst_qdockwidget.cpp diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp index 6b1abac228..88a7057d2e 100644 --- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp +++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QSignalSpy> @@ -10,12 +10,17 @@ #include "private/qmainwindowlayout_p.h" #include <QAbstractButton> #include <qlineedit.h> +#include <QtGui/qpa/qplatformwindow.h> #include <qtabbar.h> #include <QScreen> #include <QTimer> #include <QtGui/QPainter> #include <QLabel> +Q_LOGGING_CATEGORY(lcTestDockWidget, "qt.widgets.tests.qdockwidget") + +#include <QtWidgets/private/qapplication_p.h> + bool hasFeature(QDockWidget *dockwidget, QDockWidget::DockWidgetFeature feature) { return (dockwidget->features() & feature) == feature; } @@ -61,21 +66,50 @@ private slots: // Dock area permissions for DockWidgets and DockWidgetGroupWindows void dockPermissions(); - // test floating tabs and item_tree consistency + // test floating tabs, item_tree and window title consistency void floatingTabs(); + void hoverWithoutDrop(); + + // floating tab gets removed, when last child goes away + void deleteFloatingTabWithSingleDockWidget_data(); + void deleteFloatingTabWithSingleDockWidget(); // test hide & show void hideAndShow(); // test closing and deleting consistency void closeAndDelete(); + void closeUnclosable(); + + // test save and restore consistency + void saveAndRestore(); private: // helpers and consts for dockPermissions, hideAndShow, closeAndDelete #ifdef QT_BUILD_INTERNAL - void createTestWidgets(QMainWindow* &MainWindow, QPointer<QWidget> ¢, QPointer<QDockWidget> &d1, QPointer<QDockWidget> &d2) const; + void createTestWidgets(QMainWindow* &MainWindow, QPointer<QWidget> ¢, + QPointer<QDockWidget> &d1, QPointer<QDockWidget> &d2) const; + void unplugAndResize(QMainWindow* MainWindow, QDockWidget* dw, QPoint home, QSize size) const; + void createFloatingTabs(QMainWindow* &MainWindow, QPointer<QWidget> ¢, + QPointer<QDockWidget> &d1, QPointer<QDockWidget> &d2, + QList<int> &path1, QList<int> &path2) const; + +#if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX) +#define qCreateFloatingTabs(mainWindow, centralWidget, d1, d2, path1, path2)\ + mainWindow = nullptr;\ + Q_UNUSED(path1);\ + Q_UNUSED(path2);\ + QSKIP("Platform not supported"); +#else +#define qCreateFloatingTabs(mainWindow, centralWidget, d1, d2, path1, path2)\ + createFloatingTabs(mainWindow, centralWidget, d1, d2, path1, path2);\ + std::unique_ptr<QMainWindow> up_mainWindow(mainWindow);\ + if (!platformSupportingRaise)\ + QSKIP("Platform not supporting raise(). Floating tab based tests will fail.") +#endif + static inline QPoint dragPoint(QDockWidget* dockWidget); static inline QPoint home1(QMainWindow* MainWindow) { return MainWindow->mapToGlobal(MainWindow->rect().topLeft() + QPoint(0.1 * MainWindow->width(), 0.1 * MainWindow->height())); } @@ -95,12 +129,27 @@ private: bool checkFloatingTabs(QMainWindow* MainWindow, QPointer<QDockWidgetGroupWindow> &ftabs, const QList<QDockWidget*> &dwList = {}) const; // move a dock widget - void moveDockWidget(QDockWidget* dw, QPoint to, QPoint from = QPoint()) const; + enum class MoveDockWidgetRule { + Drop, + Abort + }; + void moveDockWidget(QDockWidget* dw, QPoint to, QPoint from, MoveDockWidgetRule rule) const; + +#ifdef QT_BUILD_INTERNAL // Message handling for xcb error QTBUG 82059 static void xcbMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg); + + enum class ChildRemovalReason { + Destroyed, + Closed, + Reparented + }; + public: bool xcbError = false; + bool platformSupportingRaise = true; +#endif private: #ifdef QT_DEBUG @@ -121,11 +170,6 @@ private: }; -// Statics for xcb error / msg handler -static tst_QDockWidget *qThis = nullptr; -static void (*oldMessageHandler)(QtMsgType, const QMessageLogContext&, const QString&); -#define QXCBVERIFY(cond) do { if (xcbError) QSKIP("Test skipped due to XCB error"); QVERIFY(cond); } while (0) - // Testing get/set functions void tst_QDockWidget::getSetCheck() { @@ -265,12 +309,12 @@ void tst_QDockWidget::features() QVERIFY(!hasFeature(&dw, QDockWidget::DockWidgetClosable)); QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable)); QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetFloatable)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE((int)*(static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData())), (int)dw.features()); spy.clear(); dw.setFeatures(dw.features()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); setFeature(&dw, QDockWidget::DockWidgetClosable); @@ -278,12 +322,12 @@ void tst_QDockWidget::features() QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable)); QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable)); QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetFloatable)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()), (int)dw.features()); spy.clear(); dw.setFeatures(dw.features()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); setFeature(&dw, QDockWidget::DockWidgetMovable, false); @@ -291,12 +335,12 @@ void tst_QDockWidget::features() QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable)); QVERIFY(!hasFeature(&dw, QDockWidget::DockWidgetMovable)); QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetFloatable)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()), (int)dw.features()); spy.clear(); dw.setFeatures(dw.features()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); setFeature(&dw, QDockWidget::DockWidgetMovable); @@ -304,12 +348,12 @@ void tst_QDockWidget::features() QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable)); QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable)); QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetFloatable)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()), (int)dw.features()); spy.clear(); dw.setFeatures(dw.features()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); setFeature(&dw, QDockWidget::DockWidgetFloatable, false); @@ -317,12 +361,12 @@ void tst_QDockWidget::features() QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable)); QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable)); QVERIFY(!hasFeature(&dw, QDockWidget::DockWidgetFloatable)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()), (int)dw.features()); spy.clear(); dw.setFeatures(dw.features()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); setFeature(&dw, QDockWidget::DockWidgetFloatable); @@ -330,12 +374,12 @@ void tst_QDockWidget::features() QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable)); QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable)); QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetFloatable)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()), (int)dw.features()); spy.clear(); dw.setFeatures(dw.features()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); // set all at once @@ -344,12 +388,12 @@ void tst_QDockWidget::features() QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable)); QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable)); QVERIFY(!hasFeature(&dw, QDockWidget::DockWidgetFloatable)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()), (int)dw.features()); spy.clear(); dw.setFeatures(dw.features()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); dw.setFeatures(QDockWidget::DockWidgetClosable); @@ -357,12 +401,12 @@ void tst_QDockWidget::features() QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable)); QVERIFY(!hasFeature(&dw, QDockWidget::DockWidgetMovable)); QVERIFY(!hasFeature(&dw, QDockWidget::DockWidgetFloatable)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()), (int)dw.features()); spy.clear(); dw.setFeatures(dw.features()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); dw.setFeatures(allDockWidgetFeatures); @@ -370,12 +414,12 @@ void tst_QDockWidget::features() QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetClosable)); QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetMovable)); QVERIFY(hasFeature(&dw, QDockWidget::DockWidgetFloatable)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE((int)*static_cast<const QDockWidget::DockWidgetFeature *>(spy.at(0).value(0).constData()), (int)dw.features()); spy.clear(); dw.setFeatures(dw.features()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); } @@ -402,21 +446,38 @@ void tst_QDockWidget::setFloating() QVERIFY((dockedPosition - floatingPosition).manhattanLength() < 50); QVERIFY(dw.isFloating()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).value(0).toBool(), dw.isFloating()); spy.clear(); dw.setFloating(dw.isFloating()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); dw.setFloating(false); QVERIFY(!dw.isFloating()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).value(0).toBool(), dw.isFloating()); spy.clear(); dw.setFloating(dw.isFloating()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); + +#if defined(QT_BUILD_INTERNAL) && !defined(Q_OS_WIN) + // Check that setFloating() reparents the dock widget to the main window, + // in case it has a QDockWidgetGroupWindow parent + QPointer<QDockWidget> d1; + QPointer<QDockWidget> d2; + QPointer<QWidget> cent; + QMainWindow* mainWindow; + QList<int> path1; + QList<int> path2; + qCreateFloatingTabs(mainWindow, cent, d1, d2, path1, path2); + QVERIFY(qobject_cast<QDockWidgetGroupWindow *>(d1->parentWidget())); + QVERIFY(qobject_cast<QDockWidgetGroupWindow *>(d2->parentWidget())); + d1->setFloating(true); + QTRY_COMPARE(mainWindow, d1->parentWidget()); + QTRY_COMPARE(mainWindow, d2->parentWidget()); +#endif // defined(QT_BUILD_INTERNAL) && !defined(Q_OS_WIN) } void tst_QDockWidget::allowedAreas() @@ -439,12 +500,12 @@ void tst_QDockWidget::allowedAreas() QVERIFY(!dw.isAreaAllowed(Qt::RightDockWidgetArea)); QVERIFY(!dw.isAreaAllowed(Qt::TopDockWidgetArea)); QVERIFY(!dw.isAreaAllowed(Qt::BottomDockWidgetArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()), dw.allowedAreas()); spy.clear(); dw.setAllowedAreas(dw.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); dw.setAllowedAreas(Qt::RightDockWidgetArea); QCOMPARE(dw.allowedAreas(), Qt::RightDockWidgetArea); @@ -452,12 +513,12 @@ void tst_QDockWidget::allowedAreas() QVERIFY(dw.isAreaAllowed(Qt::RightDockWidgetArea)); QVERIFY(!dw.isAreaAllowed(Qt::TopDockWidgetArea)); QVERIFY(!dw.isAreaAllowed(Qt::BottomDockWidgetArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()), dw.allowedAreas()); spy.clear(); dw.setAllowedAreas(dw.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); dw.setAllowedAreas(Qt::TopDockWidgetArea); QCOMPARE(dw.allowedAreas(), Qt::TopDockWidgetArea); @@ -465,12 +526,12 @@ void tst_QDockWidget::allowedAreas() QVERIFY(!dw.isAreaAllowed(Qt::RightDockWidgetArea)); QVERIFY(dw.isAreaAllowed(Qt::TopDockWidgetArea)); QVERIFY(!dw.isAreaAllowed(Qt::BottomDockWidgetArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()), dw.allowedAreas()); spy.clear(); dw.setAllowedAreas(dw.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); dw.setAllowedAreas(Qt::BottomDockWidgetArea); QCOMPARE(dw.allowedAreas(), Qt::BottomDockWidgetArea); @@ -478,12 +539,12 @@ void tst_QDockWidget::allowedAreas() QVERIFY(!dw.isAreaAllowed(Qt::RightDockWidgetArea)); QVERIFY(!dw.isAreaAllowed(Qt::TopDockWidgetArea)); QVERIFY(dw.isAreaAllowed(Qt::BottomDockWidgetArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()), dw.allowedAreas()); spy.clear(); dw.setAllowedAreas(dw.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); // multiple dock window areas dw.setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); @@ -493,12 +554,12 @@ void tst_QDockWidget::allowedAreas() QVERIFY(dw.isAreaAllowed(Qt::TopDockWidgetArea)); QVERIFY(dw.isAreaAllowed(Qt::BottomDockWidgetArea)); //QVERIFY(!dw.isAreaAllowed(Qt::FloatingDockWidgetArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()), dw.allowedAreas()); spy.clear(); dw.setAllowedAreas(dw.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); dw.setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); QCOMPARE(dw.allowedAreas(), Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); @@ -507,12 +568,12 @@ void tst_QDockWidget::allowedAreas() QVERIFY(!dw.isAreaAllowed(Qt::TopDockWidgetArea)); QVERIFY(!dw.isAreaAllowed(Qt::BottomDockWidgetArea)); //QVERIFY(!dw.isAreaAllowed(Qt::FloatingDockWidgetArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()), dw.allowedAreas()); spy.clear(); dw.setAllowedAreas(dw.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); dw.setAllowedAreas(Qt::TopDockWidgetArea | Qt::LeftDockWidgetArea); QCOMPARE(dw.allowedAreas(), Qt::TopDockWidgetArea | Qt::LeftDockWidgetArea); @@ -521,12 +582,12 @@ void tst_QDockWidget::allowedAreas() QVERIFY(dw.isAreaAllowed(Qt::TopDockWidgetArea)); QVERIFY(!dw.isAreaAllowed(Qt::BottomDockWidgetArea)); //QVERIFY(!dw.isAreaAllowed(Qt::FloatingDockWidgetArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()), dw.allowedAreas()); spy.clear(); dw.setAllowedAreas(dw.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); //dw.setAllowedAreas(Qt::BottomDockWidgetArea | Qt::FloatingDockWidgetArea); dw.setAllowedAreas(Qt::BottomDockWidgetArea); @@ -536,12 +597,12 @@ void tst_QDockWidget::allowedAreas() QVERIFY(!dw.isAreaAllowed(Qt::TopDockWidgetArea)); QVERIFY(dw.isAreaAllowed(Qt::BottomDockWidgetArea)); //QVERIFY(dw.isAreaAllowed(Qt::FloatingDockWidgetArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()), dw.allowedAreas()); spy.clear(); dw.setAllowedAreas(dw.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); dw.setAllowedAreas(Qt::BottomDockWidgetArea | Qt::RightDockWidgetArea); QCOMPARE(dw.allowedAreas(), Qt::BottomDockWidgetArea | Qt::RightDockWidgetArea); @@ -550,12 +611,12 @@ void tst_QDockWidget::allowedAreas() QVERIFY(!dw.isAreaAllowed(Qt::TopDockWidgetArea)); QVERIFY(dw.isAreaAllowed(Qt::BottomDockWidgetArea)); //QVERIFY(!dw.isAreaAllowed(Qt::FloatingDockWidgetArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::DockWidgetAreas *>(spy.at(0).value(0).constData()), dw.allowedAreas()); spy.clear(); dw.setAllowedAreas(dw.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QDockWidget::toggleViewAction() @@ -583,65 +644,65 @@ void tst_QDockWidget::visibilityChanged() mw.addDockWidget(Qt::LeftDockWidgetArea, &dw); mw.show(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toBool(), true); spy.clear(); dw.hide(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toBool(), false); spy.clear(); dw.hide(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); dw.show(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toBool(), true); spy.clear(); dw.show(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QDockWidget dw2; mw.tabifyDockWidget(&dw, &dw2); dw2.show(); dw2.raise(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toBool(), false); spy.clear(); dw2.hide(); qApp->processEvents(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toBool(), true); spy.clear(); dw2.show(); dw2.raise(); qApp->processEvents(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toBool(), false); spy.clear(); dw.raise(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toBool(), true); spy.clear(); dw.raise(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); dw2.raise(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toBool(), false); spy.clear(); dw2.raise(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); mw.addDockWidget(Qt::RightDockWidgetArea, &dw2); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toBool(), true); } @@ -668,6 +729,9 @@ void tst_QDockWidget::updateTabBarOnVisibilityChanged() mw.tabifyDockWidget(dw1, dw2); mw.tabifyDockWidget(dw2, dw3); + const auto list1 = QList<QDockWidget *>{dw1, dw2, dw3}; + QCOMPARE(mw.tabifiedDockWidgets(dw0), list1); + QTabBar *tabBar = mw.findChild<QTabBar *>(); QVERIFY(tabBar); tabBar->setCurrentIndex(2); @@ -681,6 +745,11 @@ void tst_QDockWidget::updateTabBarOnVisibilityChanged() dw1->hide(); QTRY_COMPARE(tabBar->count(), 2); QCOMPARE(tabBar->currentIndex(), 0); + + QCOMPARE(mw.tabifiedDockWidgets(dw2), {dw3}); + + mw.removeDockWidget(dw3); + QCOMPARE(mw.tabifiedDockWidgets(dw2).count(), 0); } Q_DECLARE_METATYPE(Qt::DockWidgetArea) @@ -695,56 +764,56 @@ void tst_QDockWidget::dockLocationChanged() QSignalSpy spy(&dw, SIGNAL(dockLocationChanged(Qt::DockWidgetArea))); mw.addDockWidget(Qt::LeftDockWidgetArea, &dw); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)), Qt::LeftDockWidgetArea); spy.clear(); mw.addDockWidget(Qt::LeftDockWidgetArea, &dw); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)), Qt::LeftDockWidgetArea); spy.clear(); mw.addDockWidget(Qt::RightDockWidgetArea, &dw); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)), Qt::RightDockWidgetArea); spy.clear(); mw.removeDockWidget(&dw); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QDockWidget dw2; dw2.setObjectName("dock2"); mw.addDockWidget(Qt::TopDockWidgetArea, &dw2); mw.tabifyDockWidget(&dw2, &dw); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)), Qt::TopDockWidgetArea); spy.clear(); mw.splitDockWidget(&dw2, &dw, Qt::Horizontal); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)), Qt::TopDockWidgetArea); spy.clear(); dw.setFloating(true); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)), Qt::NoDockWidgetArea); spy.clear(); dw.setFloating(false); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)), Qt::TopDockWidgetArea); spy.clear(); QByteArray ba = mw.saveState(); mw.restoreState(ba); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(qvariant_cast<Qt::DockWidgetArea>(spy.at(0).at(0)), Qt::TopDockWidgetArea); } @@ -1015,9 +1084,9 @@ void tst_QDockWidget::task258459_visibilityChanged() QSignalSpy spy2(&dock2, SIGNAL(visibilityChanged(bool))); win.show(); QVERIFY(QTest::qWaitForWindowActive(&win)); - QCOMPARE(spy1.count(), 1); + QCOMPARE(spy1.size(), 1); QCOMPARE(spy1.first().first().toBool(), false); //dock1 is invisible - QCOMPARE(spy2.count(), 1); + QCOMPARE(spy2.size(), 1); QCOMPARE(spy2.first().first().toBool(), true); //dock1 is visible } @@ -1067,9 +1136,10 @@ void tst_QDockWidget::setWindowTitle() QMainWindow window; QDockWidget dock1(&window); QDockWidget dock2(&window); - const QString dock1Title = QStringLiteral("&Window"); - const QString dock2Title = QStringLiteral("&Modifiable Window [*]"); + constexpr QLatin1StringView dock1Title("&Window"); + constexpr QLatin1StringView dock2Title("&Modifiable Window [*]"); + // Set title on docked dock widgets, before main window is shown dock1.setWindowTitle(dock1Title); dock2.setWindowTitle(dock2Title); window.addDockWidget(Qt::RightDockWidgetArea, &dock1); @@ -1080,6 +1150,7 @@ void tst_QDockWidget::setWindowTitle() QCOMPARE(dock1.windowTitle(), dock1Title); QCOMPARE(dock2.windowTitle(), dock2Title); + // Check if title remains unchanged when docking / undocking dock1.setFloating(true); dock1.show(); QVERIFY(QTest::qWaitForWindowExposed(&dock1)); @@ -1089,12 +1160,16 @@ void tst_QDockWidget::setWindowTitle() dock1.setFloating(true); dock1.show(); QVERIFY(QTest::qWaitForWindowExposed(&dock1)); - const QString changed = QStringLiteral("Changed "); + + // Change a floating dock widget's title and check remains unchanged when docking + constexpr QLatin1StringView changed("Changed "); dock1.setWindowTitle(QString(changed + dock1Title)); QCOMPARE(dock1.windowTitle(), QString(changed + dock1Title)); dock1.setFloating(false); + QVERIFY(QTest::qWaitFor([&dock1](){ return !dock1.windowHandle(); })); QCOMPARE(dock1.windowTitle(), QString(changed + dock1Title)); + // Test consistency after toggling modified and floating dock2.setWindowModified(true); QCOMPARE(dock2.windowTitle(), dock2Title); dock2.setFloating(true); @@ -1109,6 +1184,12 @@ void tst_QDockWidget::setWindowTitle() dock2.show(); QVERIFY(QTest::qWaitForWindowExposed(&dock2)); QCOMPARE(dock2.windowTitle(), dock2Title); + + // Test title change of a closed dock widget + static constexpr QLatin1StringView closedDock2("Closed D2"); + dock2.close(); + dock2.setWindowTitle(closedDock2); + QCOMPARE(dock2.windowTitle(), closedDock2); } // helpers for dockPermissions, hideAndShow, closeAndDelete @@ -1135,13 +1216,17 @@ void tst_QDockWidget::createTestWidgets(QMainWindow* &mainWindow, QPointer<QWidg mainWindow->setDockOptions(QMainWindow::AllowTabbedDocks | QMainWindow::GroupedDragging); mainWindow->move(m_topLeft); + const int minWidth = QApplication::style()->pixelMetric(QStyle::PM_TitleBarHeight); + const QSize minSize(minWidth, 2 * minWidth); d1 = new QDockWidget(mainWindow); + d1->setMinimumSize(minSize); d1->setWindowTitle("I am D1"); d1->setObjectName("D1"); d1->setFeatures(QDockWidget::DockWidgetFeatureMask); d1->setAllowedAreas(Qt::DockWidgetArea::AllDockWidgetAreas); d2 = new QDockWidget(mainWindow); + d2->setMinimumSize(minSize); d2->setWindowTitle("I am D2"); d2->setObjectName("D2"); d2->setFeatures(QDockWidget::DockWidgetFeatureMask); @@ -1152,7 +1237,7 @@ void tst_QDockWidget::createTestWidgets(QMainWindow* &mainWindow, QPointer<QWidg d1->show(); d2->show(); mainWindow->show(); - QApplication::setActiveWindow(mainWindow); + QApplicationPrivate::setActiveWindow(mainWindow); } @@ -1164,7 +1249,7 @@ QPoint tst_QDockWidget::dragPoint(QDockWidget* dockWidget) return dockWidget->mapToGlobal(dwlayout->titleArea().center()); } -void tst_QDockWidget::moveDockWidget(QDockWidget* dw, QPoint to, QPoint from) const +void tst_QDockWidget::moveDockWidget(QDockWidget* dw, QPoint to, QPoint from, MoveDockWidgetRule rule) const { Q_ASSERT(dw); @@ -1175,18 +1260,28 @@ void tst_QDockWidget::moveDockWidget(QDockWidget* dw, QPoint to, QPoint from) co // move and log const QPoint source = dw->mapFromGlobal(from); const QPoint target = dw->mapFromGlobal(to); - qCDebug(lcQpaDockWidgets) << "Move" << dw->objectName() << "from" << source; - qCDebug(lcQpaDockWidgets) << "Move" << dw->objectName() << "from" << from; + qCDebug(lcTestDockWidget) << "Move" << dw->objectName() << "from" << source; + qCDebug(lcTestDockWidget) << "Move" << dw->objectName() << "from" << from; QTest::mousePress(dw, Qt::LeftButton, Qt::KeyboardModifiers(), source); QTest::mouseMove(dw, target); - qCDebug(lcQpaDockWidgets) << "Move" << dw->objectName() << "to" << target; - qCDebug(lcQpaDockWidgets) << "Move" << dw->objectName() << "to" << to; - QTest::mouseRelease(dw, Qt::LeftButton, Qt::KeyboardModifiers(), target); - QTest::qWait(waitingTime); + qCDebug(lcTestDockWidget) << "Move" << dw->objectName() << "to" << target; + qCDebug(lcTestDockWidget) << "Move" << dw->objectName() << "to" << to; + if (rule == MoveDockWidgetRule::Drop) { + QTest::mouseRelease(dw, Qt::LeftButton, Qt::KeyboardModifiers(), target); + QTest::qWait(waitingTime); + + // Verify WindowActive only for floating dock widgets + if (dw->isFloating()) + QTRY_VERIFY(QTest::qWaitForWindowActive(dw)); + return; + } + qCDebug(lcTestDockWidget) << "Aborting move and dropping at origin"; - // Verify WindowActive only for floating dock widgets - if (dw->isFloating()) - QTRY_VERIFY(QTest::qWaitForWindowActive(dw)); + // Give animations some time + QTest::qWait(waitingTime); + QTest::mouseMove(dw, from); + QTest::mouseRelease(dw, Qt::LeftButton, Qt::KeyboardModifiers(), from); + QTest::qWait(waitingTime); } void tst_QDockWidget::unplugAndResize(QMainWindow* mainWindow, QDockWidget* dw, QPoint home, QSize size) const @@ -1223,21 +1318,33 @@ void tst_QDockWidget::unplugAndResize(QMainWindow* mainWindow, QDockWidget* dw, return; } + // Remember size for comparison with unplugged object +#ifdef Q_OS_LINUX + const int pluggedWidth = dw->width(); + const int pluggedHeight = dw->height(); +#endif + // unplug and resize a dock Widget - qCDebug(lcQpaDockWidgets) << "*** unplug and resize" << dw->objectName(); + qCDebug(lcTestDockWidget) << "*** unplug and resize" << dw->objectName(); QPoint pos1 = dw->mapToGlobal(dw->rect().center()); pos1.rx() += mx; pos1.ry() += my; - moveDockWidget(dw, pos1, dw->mapToGlobal(dw->rect().center())); - //QTest::mousePress(dw, Qt::LeftButton, Qt::KeyboardModifiers(), dw->mapFromGlobal(pos1)); + moveDockWidget(dw, pos1, dw->mapToGlobal(dw->rect().center()), MoveDockWidgetRule::Drop); QTRY_VERIFY(dw->isFloating()); - qCDebug(lcQpaDockWidgets) << "Resizing" << dw->objectName() << "to" << size; + // Unplugged object's size may differ max. by 2x frame size +#ifdef Q_OS_LINUX + const int xMargin = 2 * dw->frameSize().width(); + const int yMargin = 2 * dw->frameSize().height(); + QVERIFY(dw->height() - pluggedHeight <= xMargin); + QVERIFY(dw->width() - pluggedWidth <= yMargin); +#endif + + qCDebug(lcTestDockWidget) << "Resizing" << dw->objectName() << "to" << size; dw->setFixedSize(size); QTest::qWait(waitingTime); - qCDebug(lcQpaDockWidgets) << "Move" << dw->objectName() << "to its home" << dw->mapFromGlobal(home); + qCDebug(lcTestDockWidget) << "Move" << dw->objectName() << "to its home" << dw->mapFromGlobal(home); dw->move(home); - //moveDockWidget(dw, home); } bool tst_QDockWidget::checkFloatingTabs(QMainWindow* mainWindow, QPointer<QDockWidgetGroupWindow> &ftabs, const QList<QDockWidget*> &dwList) const @@ -1247,62 +1354,115 @@ bool tst_QDockWidget::checkFloatingTabs(QMainWindow* mainWindow, QPointer<QDockW // Check if mainWindow has a floatingTab child ftabs = mainWindow->findChild<QDockWidgetGroupWindow*>(); if (ftabs.isNull()) { - qCDebug(lcQpaDockWidgets) << "MainWindow has no DockWidgetGroupWindow" << mainWindow; + qCDebug(lcTestDockWidget) << "MainWindow has no DockWidgetGroupWindow" << mainWindow; return false; } QTabBar* tab = ftabs->findChild<QTabBar*>(); if (!tab) { - qCDebug(lcQpaDockWidgets) << "DockWidgetGroupWindow has no tab bar" << ftabs; + qCDebug(lcTestDockWidget) << "DockWidgetGroupWindow has no tab bar" << ftabs; return false; } // both dock widgets must be direct children of the main window const QList<QDockWidget*> children = ftabs->findChildren<QDockWidget*>(QString(), Qt::FindDirectChildrenOnly); - if (dwList.count() > 0) + if (dwList.size() > 0) { - if (dwList.count() != children.count()) { - qCDebug(lcQpaDockWidgets) << "Expected DockWidgetGroupWindow children:" << dwList.count() - << "Children found:" << children.count(); + if (dwList.size() != children.size()) { + qCDebug(lcTestDockWidget) << "Expected DockWidgetGroupWindow children:" << dwList.size() + << "Children found:" << children.size(); - qCDebug(lcQpaDockWidgets) << "Expected:" << dwList; - qCDebug(lcQpaDockWidgets) << "Found in" << ftabs << ":" << children.count(); + qCDebug(lcTestDockWidget) << "Expected:" << dwList; + qCDebug(lcTestDockWidget) << "Found in" << ftabs << ":" << children.size(); return false; } for (const QDockWidget* child : dwList) { if (!children.contains(child)) { - qCDebug(lcQpaDockWidgets) << "Expected child" << child << "not found in" << children; + qCDebug(lcTestDockWidget) << "Expected child" << child << "not found in" << children; return false; } } } // Always select first tab position - qCDebug(lcQpaDockWidgets) << "click on first tab"; + qCDebug(lcTestDockWidget) << "click on first tab"; QTest::mouseClick(tab, Qt::LeftButton, Qt::KeyboardModifiers(), tab->tabRect(0).center()); return true; } -// detect xcb error +#ifdef QT_BUILD_INTERNAL +// Statics for xcb error, raise() suppert / msg handler +static tst_QDockWidget *qThis = nullptr; +static void (*oldMessageHandler)(QtMsgType, const QMessageLogContext &, const QString &); +#define QXCBVERIFY(cond) do { if (xcbError) QSKIP("Test skipped due to XCB error"); QVERIFY(cond); } while (0) + +// detect xcb error and missing raise() support // qt.qpa.xcb: internal error: void QXcbWindow::setNetWmStateOnUnmappedWindow() called on mapped window void tst_QDockWidget::xcbMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { Q_ASSERT(oldMessageHandler); - if (type == QtWarningMsg && QString(context.category) == "qt.qpa.xcb" && msg.contains("internal error")) { + if (type == QtWarningMsg) { Q_ASSERT(qThis); - qThis->xcbError = true; + if (QString(context.category) == "qt.qpa.xcb" && msg.contains("internal error")) + qThis->xcbError = true; + if (msg.contains("does not support raise")) + qThis->platformSupportingRaise = false; } return oldMessageHandler(type, context, msg); } +#endif + +void tst_QDockWidget::createFloatingTabs(QMainWindow* &mainWindow, QPointer<QWidget> ¢, + QPointer<QDockWidget> &d1, QPointer<QDockWidget> &d2, + QList<int> &path1, QList<int> &path2) const +{ + createTestWidgets(mainWindow, cent, d1, d2); + +#ifdef QT_BUILD_INTERNAL + qThis = const_cast<tst_QDockWidget *>(this); + oldMessageHandler = qInstallMessageHandler(xcbMessageHandler); + auto resetMessageHandler = qScopeGuard([] { qInstallMessageHandler(oldMessageHandler); }); +#endif + + // Test will fail if platform doesn't support raise. + mainWindow->windowHandle()->handle()->raise(); + if (!platformSupportingRaise) + return; + // remember paths to d1 and d2 + QMainWindowLayout* layout = qobject_cast<QMainWindowLayout *>(mainWindow->layout()); + path1 = layout->layoutState.indexOf(d1); + path2 = layout->layoutState.indexOf(d2); + + // unplug and resize both dock widgets + unplugAndResize(mainWindow, d1, home1(mainWindow), size1(mainWindow)); + unplugAndResize(mainWindow, d2, home2(mainWindow), size2(mainWindow)); + + // docks must be parented to the main window, no group window must exist + QCOMPARE(d1->parentWidget(), mainWindow); + QCOMPARE(d2->parentWidget(), mainWindow); + QVERIFY(mainWindow->findChildren<QDockWidgetGroupWindow *>().isEmpty()); + + // Test plugging + qCDebug(lcTestDockWidget) << "*** move d1 dock over d2 dock ***"; + qCDebug(lcTestDockWidget) << "**********(test plugging)*************"; + qCDebug(lcTestDockWidget) << "Move d1 over d2"; + moveDockWidget(d1, d2->mapToGlobal(d2->rect().center()), QPoint(), MoveDockWidgetRule::Drop); + + // Now MainWindow has to have a floatingTab child + QPointer<QDockWidgetGroupWindow> ftabs; + QTRY_VERIFY(checkFloatingTabs(mainWindow, ftabs, QList<QDockWidget *>() << d1 << d2)); +} #endif // QT_BUILD_INTERNAL // test floating tabs and item_tree consistency void tst_QDockWidget::floatingTabs() { + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Test skipped on Wayland."); #ifdef Q_OS_WIN QSKIP("Test skipped on Windows platforms"); #endif // Q_OS_WIN @@ -1312,33 +1472,19 @@ void tst_QDockWidget::floatingTabs() QPointer<QDockWidget> d2; QPointer<QWidget> cent; QMainWindow* mainWindow; - createTestWidgets(mainWindow, cent, d1, d2); - std::unique_ptr<QMainWindow> up_mainWindow(mainWindow); + QList<int> path1; + QList<int> path2; + qCreateFloatingTabs(mainWindow, cent, d1, d2, path1, path2); + + QCOMPARE(mainWindow->tabifiedDockWidgets(d1), {d2}); + QCOMPARE(mainWindow->tabifiedDockWidgets(d2), {d1}); /* * unplug both dockwidgets, resize them and plug them into a joint floating tab * expected behavior: QDOckWidgetGroupWindow with both widgets is created */ - // remember paths to d1 and d2 - QMainWindowLayout* layout = qobject_cast<QMainWindowLayout*>(mainWindow->layout()); - const QList<int> path1 = layout->layoutState.indexOf(d1); - const QList<int> path2 = layout->layoutState.indexOf(d2); - - // unplug and resize both dock widgets - unplugAndResize(mainWindow, d1, home1(mainWindow), size1(mainWindow)); - unplugAndResize(mainWindow, d2, home2(mainWindow), size2(mainWindow)); - - // Test plugging - qCDebug(lcQpaDockWidgets) << "*** move d1 dock over d2 dock ***"; - qCDebug(lcQpaDockWidgets) << "**********(test plugging)*************"; - qCDebug(lcQpaDockWidgets) << "Move d1 over d2"; - moveDockWidget(d1, d2->mapToGlobal(d2->rect().center())); - - // Both dock widgets must no longer be floating // disabled due to flakiness on macOS and Windows - //QTRY_VERIFY(!d1->isFloating()); - //QTRY_VERIFY(!d2->isFloating()); if (d1->isFloating()) qWarning("OS flakiness: D1 is docked and reports being floating"); if (d2->isFloating()) @@ -1346,40 +1492,57 @@ void tst_QDockWidget::floatingTabs() // Now MainWindow has to have a floatingTab child QPointer<QDockWidgetGroupWindow> ftabs; - QTRY_VERIFY(checkFloatingTabs(mainWindow, ftabs, QList<QDockWidget*>() << d1 << d2)); + QTRY_VERIFY(checkFloatingTabs(mainWindow, ftabs, QList<QDockWidget *>() << d1 << d2)); + + // Hide both dock widgets. Verify that the group window is also hidden. + qCDebug(lcTestDockWidget) << "*** Hide and show tabbed dock widgets ***"; + d1->hide(); + d2->hide(); + QTRY_VERIFY(ftabs->isHidden()); + + // Show both dockwidgets again. Verify that the group window is visible. + d1->show(); + d2->show(); + QTRY_VERIFY(ftabs->isVisible()); /* * replug both dock widgets into their initial position - * expected behavior: both docks are plugged and no longer floating + * expected behavior: + - both docks are plugged + - both docks are no longer floating + - title changes have been propagated */ // limitation: QTest cannot handle drag to unplug. // reason: Object under mouse mutates from QTabBar::tab to QDockWidget. QTest cannot handle that. // => click float button to unplug - qCDebug(lcQpaDockWidgets) << "*** test unplugging from floating dock ***"; + qCDebug(lcTestDockWidget) << "*** test unplugging from floating dock ***"; // QDockWidget must have a QAbstractButton with object name "qt_dockwidget_floatbutton" QAbstractButton* floatButton = d1->findChild<QAbstractButton*>("qt_dockwidget_floatbutton", Qt::FindDirectChildrenOnly); QTRY_VERIFY(floatButton != nullptr); QPoint pos1 = floatButton->rect().center(); - qCDebug(lcQpaDockWidgets) << "unplug d1" << pos1; + qCDebug(lcTestDockWidget) << "unplug d1" << pos1; QTest::mouseClick(floatButton, Qt::LeftButton, Qt::KeyboardModifiers(), pos1); QTest::qWait(waitingTime); - // d1 must be floating again, while d2 is still in its GroupWindow + // d1 and d2 must be floating again QTRY_VERIFY(d1->isFloating()); - QTRY_VERIFY(!d2->isFloating()); + QTRY_VERIFY(d2->isFloating()); + + // d2 was the active tab, so d1 was not visible + QTRY_VERIFY(d1->isVisible()); + QTRY_VERIFY(d2->isVisible()); // Plug back into dock areas - qCDebug(lcQpaDockWidgets) << "*** test plugging back to dock areas ***"; - qCDebug(lcQpaDockWidgets) << "Move d1 to left dock"; - //moveDockWidget(d1, d1->mapFrom(MainWindow, dockPoint(MainWindow, Qt::LeftDockWidgetArea))); - moveDockWidget(d1, dockPoint(mainWindow, Qt::LeftDockWidgetArea)); - qCDebug(lcQpaDockWidgets) << "Move d2 to right dock"; - moveDockWidget(d2, dockPoint(mainWindow, Qt::RightDockWidgetArea)); - - qCDebug(lcQpaDockWidgets) << "Waiting" << waitBeforeClose << "ms before plugging back."; + qCDebug(lcTestDockWidget) << "*** test plugging back to dock areas ***"; + qCDebug(lcTestDockWidget) << "Move d1 to left dock"; + moveDockWidget(d1, dockPoint(mainWindow, Qt::LeftDockWidgetArea), QPoint(), MoveDockWidgetRule::Drop); + qCDebug(lcTestDockWidget) << "Move d2 to right dock"; + moveDockWidget(d2, dockPoint(mainWindow, Qt::RightDockWidgetArea), QPoint(), MoveDockWidgetRule::Drop); + + qCDebug(lcTestDockWidget) << "Waiting" << waitBeforeClose << "ms before plugging back."; QTest::qWait(waitBeforeClose); // Both dock widgets must no longer be floating @@ -1391,13 +1554,97 @@ void tst_QDockWidget::floatingTabs() QTRY_VERIFY(ftabs.isNull()); // Check if paths are consistent - qCDebug(lcQpaDockWidgets) << "Checking path consistency" << layout->layoutState.indexOf(d1) << layout->layoutState.indexOf(d2); + QMainWindowLayout* layout = qobject_cast<QMainWindowLayout *>(mainWindow->layout()); + qCDebug(lcTestDockWidget) << "Checking path consistency" << layout->layoutState.indexOf(d1) << layout->layoutState.indexOf(d2); + + // Paths must be identical + QTRY_COMPARE(layout->layoutState.indexOf(d1), path1); + QTRY_COMPARE(layout->layoutState.indexOf(d2), path2); + + QCOMPARE(mainWindow->tabifiedDockWidgets(d1), {}); + QCOMPARE(mainWindow->tabifiedDockWidgets(d2), {}); +#else + QSKIP("test requires -developer-build option"); +#endif // QT_BUILD_INTERNAL +} - // Path1 must be identical - QTRY_VERIFY(path1 == layout->layoutState.indexOf(d1)); +void tst_QDockWidget::deleteFloatingTabWithSingleDockWidget_data() +{ +#ifdef QT_BUILD_INTERNAL + QTest::addColumn<int>("reason"); + QTest::addRow("Delete child") << static_cast<int>(ChildRemovalReason::Destroyed); + QTest::addRow("Close child") << static_cast<int>(ChildRemovalReason::Closed); + QTest::addRow("Reparent child") << static_cast<int>(ChildRemovalReason::Reparented); +#endif +} + +void tst_QDockWidget::deleteFloatingTabWithSingleDockWidget() +{ + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Test skipped on Wayland."); +#ifdef Q_OS_WIN + QSKIP("Test skipped on Windows platforms"); +#endif // Q_OS_WIN +#ifdef QT_BUILD_INTERNAL + + QFETCH(int, reason); + const ChildRemovalReason removalReason = static_cast<ChildRemovalReason>(reason); + + QPointer<QDockWidget> d1; + QPointer<QDockWidget> d2; + QPointer<QWidget> cent; + QMainWindow* mainWindow; + QList<int> path1; + QList<int> path2; + qCreateFloatingTabs(mainWindow, cent, d1, d2, path1, path2); + + switch (removalReason) { + case ChildRemovalReason::Destroyed: + delete d1; + break; + case ChildRemovalReason::Closed: + d1->close(); + break; + case ChildRemovalReason::Reparented: + // This will create an invalid state, because setParent() doesn't fix the item_list. + // Testing this case anyway, because setParent() includig item_list fixup is executed, + // when the 2nd last dock widget is dragged out of a floating tab. + // => despite of the broken state, the group window has to be gone. + d1->setParent(mainWindow); + break; + } + + QTRY_VERIFY(!qobject_cast<QDockWidgetGroupWindow *>(d2->parentWidget())); + QTRY_VERIFY(mainWindow->findChildren<QDockWidgetGroupWindow *>().isEmpty()); +#endif // QT_BUILD_INTERNAL +} + +void tst_QDockWidget::hoverWithoutDrop() +{ + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Test skipped on Wayland."); +#ifdef QT_BUILD_INTERNAL + + QPointer<QDockWidget> d1; + QPointer<QDockWidget> d2; + QPointer<QWidget> cent; + QMainWindow* mainWindow; + createTestWidgets(mainWindow, cent, d1, d2); + std::unique_ptr<QMainWindow> up_mainWindow(mainWindow); - // d1 must have a gap item due to size change - QTRY_VERIFY(layout->layoutState.indexOf(d2) == QList<int>() << path2 << 0); + // unplug and resize both dock widgets + unplugAndResize(mainWindow, d1, home1(mainWindow), size1(mainWindow)); + unplugAndResize(mainWindow, d2, home2(mainWindow), size2(mainWindow)); + + // Test plugging + qCDebug(lcTestDockWidget) << "*** move d1 dock over d2 dock ***"; + qCDebug(lcTestDockWidget) << "*******(test hovering)***********"; + qCDebug(lcTestDockWidget) << "Move d1 over d2, wait and return to origin"; + const QPoint source = d1->mapToGlobal(d1->rect().center()); + const QPoint target = d2->mapToGlobal(d2->rect().center()); + moveDockWidget(d1, target, source, MoveDockWidgetRule::Abort); + auto *groupWindow = mainWindow->findChild<QDockWidgetGroupWindow *>(); + QCOMPARE(groupWindow, nullptr); #else QSKIP("test requires -developer-build option"); #endif // QT_BUILD_INTERNAL @@ -1406,6 +1653,8 @@ void tst_QDockWidget::floatingTabs() // test hide & show void tst_QDockWidget::hideAndShow() { + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Test skipped on Wayland."); #ifdef QT_BUILD_INTERNAL // Skip test if xcb error is launched qThis = this; @@ -1421,14 +1670,14 @@ void tst_QDockWidget::hideAndShow() std::unique_ptr<QMainWindow> up_mainWindow(mainWindow); // Check hiding of docked widgets - qCDebug(lcQpaDockWidgets) << "Hiding mainWindow with plugged dock widgets" << mainWindow; + qCDebug(lcTestDockWidget) << "Hiding mainWindow with plugged dock widgets" << mainWindow; mainWindow->hide(); QXCBVERIFY(!mainWindow->isVisible()); QXCBVERIFY(!d1->isVisible()); QXCBVERIFY(!d2->isVisible()); // Check showing everything again - qCDebug(lcQpaDockWidgets) << "Showing mainWindow with plugged dock widgets" << mainWindow; + qCDebug(lcTestDockWidget) << "Showing mainWindow with plugged dock widgets" << mainWindow; mainWindow->show(); QXCBVERIFY(QTest::qWaitForWindowActive(mainWindow)); QXCBVERIFY(QTest::qWaitForWindowExposed(mainWindow)); @@ -1448,8 +1697,8 @@ void tst_QDockWidget::hideAndShow() unplugAndResize(mainWindow, d1, home1(mainWindow), size1(mainWindow)); unplugAndResize(mainWindow, d2, home2(mainWindow), size2(mainWindow)); - // Check hiding of undocked widgets - qCDebug(lcQpaDockWidgets) << "Hiding mainWindow with unplugged dock widgets" << mainWindow; + // Check hiding of undocked widgets + qCDebug(lcTestDockWidget) << "Hiding mainWindow with unplugged dock widgets" << mainWindow; mainWindow->hide(); QTRY_VERIFY(!mainWindow->isVisible()); QTRY_VERIFY(d1->isVisible()); @@ -1459,7 +1708,17 @@ void tst_QDockWidget::hideAndShow() QTRY_VERIFY(!d1->isVisible()); QTRY_VERIFY(!d2->isVisible()); - qCDebug(lcQpaDockWidgets) << "Waiting" << waitBeforeClose << "ms before closing."; + + // Check floating, hidden dock widgets remain hidden, when their state is restored + qCDebug(lcTestDockWidget) << "Restoring state of unplugged, hidden dock widgets" << mainWindow; + const QByteArray state = mainWindow->saveState(); + mainWindow->restoreState(state); + mainWindow->show(); + QVERIFY(QTest::qWaitForWindowExposed(mainWindow)); + QTRY_VERIFY(!d1->isVisible()); + QTRY_VERIFY(!d2->isVisible()); + + qCDebug(lcTestDockWidget) << "Waiting" << waitBeforeClose << "ms before closing."; QTest::qWait(waitBeforeClose); #else QSKIP("test requires -developer-build option"); @@ -1469,7 +1728,12 @@ void tst_QDockWidget::hideAndShow() // test closing and deleting consistency void tst_QDockWidget::closeAndDelete() { + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Test skipped on Wayland."); #ifdef QT_BUILD_INTERNAL + if (QSysInfo::productType() == "rhel") + QSKIP("Memory leak on RHEL 9.2 QTBUG-124559", TestFailMode::Abort); + // Create a mainwindow with a central widget and two dock widgets QPointer<QDockWidget> d1; QPointer<QDockWidget> d2; @@ -1483,8 +1747,8 @@ void tst_QDockWidget::closeAndDelete() unplugAndResize(mainWindow, d2, home2(mainWindow), size2(mainWindow)); // Create a floating tab and unplug it again - qCDebug(lcQpaDockWidgets) << "Move d1 over d2"; - moveDockWidget(d1, d2->mapToGlobal(d2->rect().center())); + qCDebug(lcTestDockWidget) << "Move d1 over d2"; + moveDockWidget(d1, d2->mapToGlobal(d2->rect().center()), QPoint(), MoveDockWidgetRule::Drop); // Both dock widgets must no longer be floating // disabled due to flakiness on macOS and Windows @@ -1496,8 +1760,10 @@ void tst_QDockWidget::closeAndDelete() qWarning("OS flakiness: D2 is docked and reports being floating"); // Close everything with a single shot. Expected behavior: Event loop stops - bool eventLoopStopped = true; - QTimer::singleShot(0, this, [mainWindow, d1, d2] { + QSignalSpy closeSpy(qApp, &QApplication::lastWindowClosed); + QObject localContext; + + QTimer::singleShot(0, &localContext, [&](){ mainWindow->close(); QTRY_VERIFY(!mainWindow->isVisible()); QTRY_VERIFY(d1->isVisible()); @@ -1506,21 +1772,14 @@ void tst_QDockWidget::closeAndDelete() d2->close(); QTRY_VERIFY(!d1->isVisible()); QTRY_VERIFY(!d2->isVisible()); - }); - - // Fallback timer to report event loop still running - QTimer::singleShot(100, this, [&eventLoopStopped] { - qCDebug(lcQpaDockWidgets) << "Last dock widget hasn't shout down event loop!"; - eventLoopStopped = false; + QTRY_COMPARE(closeSpy.count(), 1); QApplication::quit(); }); QApplication::exec(); - QTRY_VERIFY(eventLoopStopped); - // Check heap cleanup - qCDebug(lcQpaDockWidgets) << "Deleting mainWindow"; + qCDebug(lcTestDockWidget) << "Deleting mainWindow"; up_mainWindow.reset(); QTRY_VERIFY(d1.isNull()); QTRY_VERIFY(d2.isNull()); @@ -1530,9 +1789,29 @@ void tst_QDockWidget::closeAndDelete() #endif // QT_BUILD_INTERNAL } +void tst_QDockWidget::closeUnclosable() +{ + QDockWidget *dockWidget = new QDockWidget("dock"); + dockWidget->setWidget(new QScrollArea); + dockWidget->setFeatures(QDockWidget::DockWidgetFloatable); + + QMainWindow mw; + mw.addDockWidget(Qt::TopDockWidgetArea, dockWidget); + mw.show(); + + QVERIFY(QTest::qWaitForWindowExposed(&mw)); + dockWidget->setFloating(true); + + QCOMPARE(dockWidget->close(), false); + mw.close(); + QCOMPARE(dockWidget->close(), true); +} + // Test dock area permissions void tst_QDockWidget::dockPermissions() { + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Test skipped on Wayland."); #ifdef Q_OS_WIN QSKIP("Test skipped on Windows platforms"); #endif // Q_OS_WIN @@ -1561,7 +1840,7 @@ void tst_QDockWidget::dockPermissions() // both dock widgets must be direct children of the main window { const QList<QDockWidget*> children = mainWindow->findChildren<QDockWidget*>(QString(), Qt::FindDirectChildrenOnly); - QTRY_VERIFY(children.count() == 2); + QTRY_VERIFY(children.size() == 2); for (const QDockWidget* child : children) QTRY_VERIFY(child == d1 || child == d2); } @@ -1570,28 +1849,188 @@ void tst_QDockWidget::dockPermissions() QTRY_VERIFY(mainWindow->findChild<QDockWidgetGroupWindow*>() == nullptr); // Test unpermitted dock areas with d2 - qCDebug(lcQpaDockWidgets) << "*** move d2 to forbidden docks ***"; + qCDebug(lcTestDockWidget) << "*** move d2 to forbidden docks ***"; // Move d2 to non allowed dock areas and verify it remains floating - qCDebug(lcQpaDockWidgets) << "Move d2 to top dock"; - moveDockWidget(d2, dockPoint(mainWindow, Qt::TopDockWidgetArea)); + qCDebug(lcTestDockWidget) << "Move d2 to top dock"; + moveDockWidget(d2, dockPoint(mainWindow, Qt::TopDockWidgetArea), QPoint(), MoveDockWidgetRule::Drop); QTRY_VERIFY(d2->isFloating()); - qCDebug(lcQpaDockWidgets) << "Move d2 to left dock"; + qCDebug(lcTestDockWidget) << "Move d2 to left dock"; //moveDockWidget(d2, d2->mapFrom(MainWindow, dockPoint(MainWindow, Qt::LeftDockWidgetArea))); - moveDockWidget(d2, dockPoint(mainWindow, Qt::LeftDockWidgetArea)); + moveDockWidget(d2, dockPoint(mainWindow, Qt::LeftDockWidgetArea), QPoint(), MoveDockWidgetRule::Drop); QTRY_VERIFY(d2->isFloating()); - qCDebug(lcQpaDockWidgets) << "Move d2 to bottom dock"; - moveDockWidget(d2, dockPoint(mainWindow, Qt::BottomDockWidgetArea)); + qCDebug(lcTestDockWidget) << "Move d2 to bottom dock"; + moveDockWidget(d2, dockPoint(mainWindow, Qt::BottomDockWidgetArea), QPoint(), MoveDockWidgetRule::Drop); QTRY_VERIFY(d2->isFloating()); - qCDebug(lcQpaDockWidgets) << "Waiting" << waitBeforeClose << "ms before closing."; + qCDebug(lcTestDockWidget) << "Waiting" << waitBeforeClose << "ms before closing."; QTest::qWait(waitBeforeClose); #else QSKIP("test requires -developer-build option"); #endif // QT_BUILD_INTERNAL } +/*! + \internal + + This test checks consistency of QMainWindow::saveState() / QMainWindow::restoreState(). + These methods (de)serialize dock widget properties via a QDataStream into a QByteArray. + + If the logic of (de)serializing Qt datatypes and classes changes, old settings can fail + to restore properly without triggering warnings or assertions. + + The test consists of two parts: + \list 1 + \li Read properties from a hard coded byte array and check if it is deserialized correctly. + \li Serialize properties into a \a QByteArray and check if it is serialized correctly. + \endlist +*/ +void tst_QDockWidget::saveAndRestore() +{ + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Test skipped on Wayland."); +#ifdef Q_OS_WIN + QSKIP("Test skipped on Windows platforms"); +#endif // Q_OS_WIN +#ifndef QT_BUILD_INTERNAL + QSKIP("test requires -developer-build option"); +#else + + // Hard coded byte array for test initialization + const QByteArray testArray = QByteArrayLiteral( + "\x00\x00\x00\xFF\x00\x00\x00\x00\xFD\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x05\xE8\xFC\x02\x00\x00\x00\x01\xFB\x00\x00\x00\x04\x00" + "D\x00" + "1\x03\x00\x00\x01\f\x00\x00\x00\x97\x00\x00\x02\x19\x00\x00\x01z\x00\x00\x00\x01\x00\x00\x00\x13\x00\x00\x05\xE8\xFC\x02\x00\x00\x00\x01\xFB\x00\x00\x00\x04\x00" + "D\x00" + "2\x03\x00\x00\x06L\x00\x00\x00\xFF\x00\x00\x01\f\x00\x00\x00\xE2\x00\x00\n\x80\x00\x00\x05\xE8\x00\x00\x00\x04\x00\x00\x00\x04\x00\x00\x00\b\x00\x00\x00\b\xFC\x00\x00\x00\x00" + ); + + QByteArray referenceArray; // Copy of testArray, corrected for current screen limits + QPoint topLeft1; // Top left point of dock widget d1 + QPoint topLeft2; // Top left point of dock widget d2 + QSize widgetSize1; // Size of dock widget d1 + QSize widgetSize2; // Size of dock widget d2 + bool isFloating1; // Floating status of dock widget d1 + bool isFloating2; // Floating status of dock widget d2 + + // Create a mainwindow with a central widget and two dock widgets. + // Import properties from hard coded byte array. + // Use a scope to delete objects from screen after test. + { + QPointer<QDockWidget> d1; + QPointer<QDockWidget> d2; + QPointer<QWidget> cent; + QMainWindow* mainWindow; + createTestWidgets(mainWindow, cent, d1, d2); + + // Failure to restore properties might lead to inconsistencies and crash. + // To leave a clean environment when the test inexpectedly goes out of scope, + // => store main window pointer in a std::unique_ptr + std::unique_ptr<QMainWindow> up_mainWindow(mainWindow); + + // Restore, wait for events to be processed + mainWindow->restoreState(testArray); + QVERIFY(QTest::qWaitForWindowExposed(d1)); + QVERIFY(QTest::qWaitForWindowExposed(d2)); + + // Serialized dock widget positions and sizes might be overridden due + // screen size limitations => do not check them here. + // If the test fails between here and scope end, serialization format/sequence have changed + QTRY_VERIFY(d1->isFloating()); + QTRY_VERIFY(d2->isFloating()); + + // Hide main window and save their floating status. + // Reason: + // - KDE window managers do not take control over dock widgets. + // => They always close with the main window. + // - Some non KDE window managers do take control over dock widgets. + // => They prevent them from closing with the main window (QTBUG-103474). + // If properties are restored correctly, closing behavior must be consistent + // throughout this test. + mainWindow->hide(); + // FIXME: No method exists in 6.5 to wait for a window to be hidden. + // => wait and hope the best, replace with qWaitForWindowHidden once implemented. + QTest::qWait(200); + isFloating1 = d1->isFloating(); + isFloating2 = d2->isFloating(); + } + + // Create a mainwindow with a central widget and two dock widgets. + // Assign different properties to each dock widgets. + // Write properties to a byte array. + // Remember position and size properties for comparison. + // Use a scope to delete objects from screen after test. + { + QPointer<QDockWidget> d1; + QPointer<QDockWidget> d2; + QPointer<QWidget> cent; + QMainWindow* mainWindow; + createTestWidgets(mainWindow, cent, d1, d2); + std::unique_ptr<QMainWindow> up_mainWindow(mainWindow); + + // unplug, position and resize both dock widgets relative to screen size + unplugAndResize(mainWindow, d1, home1(mainWindow), size1(mainWindow)); + unplugAndResize(mainWindow, d2, home2(mainWindow), size2(mainWindow)); + + topLeft1 = d1->pos(); + topLeft2 = d2->pos(); + widgetSize1 = d1->size(); + widgetSize2 = d2->size(); + + // save properties, potentially corrected for screen limits + referenceArray = mainWindow->saveState(); + + // Check closing behavior consistency + mainWindow->hide(); + QTRY_VERIFY(d1->isFloating()); + QTRY_VERIFY(d2->isFloating()); + QCOMPARE(d1->isFloating(), isFloating1); + QCOMPARE(d2->isFloating(), isFloating2); + } + + // Create a new main window, central window and two dock widgets. + QPointer<QDockWidget> d1; + QPointer<QDockWidget> d2; + QPointer<QWidget> cent; + QMainWindow* mainWindow; + createTestWidgets(mainWindow, cent, d1, d2); + + // Failure to restore properties might lead to inconsistencies and crash. + // To leave a clean environment when the test inexpectedly goes out of scope, + // - store main window pointer in a std::unique_ptr + std::unique_ptr<QMainWindow> up_mainWindow(mainWindow); + + // Restore properties and wait for events to be processed + mainWindow->restoreState(referenceArray); + QVERIFY(QTest::qWaitForWindowExposed(d1)); + QVERIFY(QTest::qWaitForWindowExposed(d2)); + + // Compare positions, sizes and floating status + // If the test fails in the following 12 lines, + // the de-serialization format/sequence have changed + QCOMPARE(topLeft1, d1->pos()); + QCOMPARE(topLeft2, d2->pos()); + QCOMPARE(widgetSize1, d1->size()); + QCOMPARE(widgetSize2, d2->size()); + QVERIFY(d1->isFloating()); + QVERIFY(d2->isFloating()); + + // Serialize again to compare all remaining properties + const QByteArray comparisonArray = mainWindow->saveState(); + QCOMPARE(comparisonArray, referenceArray); + + // Check closing behavior consistency + mainWindow->hide(); + QTRY_VERIFY(d1->isFloating()); + QTRY_VERIFY(d2->isFloating()); + QCOMPARE(d1->isFloating(), isFloating1); + QCOMPARE(d2->isFloating(), isFloating2); + +#undef qCreateFloatingTabs +#endif // QT_BUILD_INTERNAL +} + QTEST_MAIN(tst_QDockWidget) #include "tst_qdockwidget.moc" diff --git a/tests/auto/widgets/widgets/qdoublespinbox/CMakeLists.txt b/tests/auto/widgets/widgets/qdoublespinbox/CMakeLists.txt index bc388f61bc..b023174dc9 100644 --- a/tests/auto/widgets/widgets/qdoublespinbox/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qdoublespinbox/CMakeLists.txt @@ -1,16 +1,21 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qdoublespinbox.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qdoublespinbox Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qdoublespinbox LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qdoublespinbox SOURCES tst_qdoublespinbox.cpp LIBRARIES Qt::Gui Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp index 3d7eece17a..999b5cac07 100644 --- a/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp +++ b/tests/auto/widgets/widgets/qdoublespinbox/tst_qdoublespinbox.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -22,6 +22,8 @@ #include <QStyle> #include <QProxyStyle> +#include <QtWidgets/private/qapplication_p.h> + class DoubleSpinBox : public QDoubleSpinBox { Q_OBJECT @@ -855,8 +857,15 @@ void tst_QDoubleSpinBox::editingFinished() testFocusWidget.show(); testFocusWidget.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&testFocusWidget)); + + box->show(); + QVERIFY(QTest::qWaitForWindowExposed(box)); box->setFocus(); - QTRY_VERIFY(box->hasFocus()); + + // Box may fail to acquire focus due to a system popup + // it is fair in that case to skip the test + if (!QTest::qWaitForWindowActive(box)) + QSKIP("Focus acquisition failed."); QSignalSpy editingFinishedSpy1(box, SIGNAL(editingFinished())); QSignalSpy editingFinishedSpy2(box2, SIGNAL(editingFinished())); @@ -865,37 +874,37 @@ void tst_QDoubleSpinBox::editingFinished() QTest::keyClick(box, Qt::Key_Up); - QCOMPARE(editingFinishedSpy1.count(), 0); - QCOMPARE(editingFinishedSpy2.count(), 0); + QCOMPARE(editingFinishedSpy1.size(), 0); + QCOMPARE(editingFinishedSpy2.size(), 0); QTest::keyClick(box2, Qt::Key_Up); QTest::keyClick(box2, Qt::Key_Up); box2->setFocus(); - QCOMPARE(editingFinishedSpy1.count(), 1); + QCOMPARE(editingFinishedSpy1.size(), 1); box->setFocus(); - QCOMPARE(editingFinishedSpy1.count(), 1); - QCOMPARE(editingFinishedSpy2.count(), 1); + QCOMPARE(editingFinishedSpy1.size(), 1); + QCOMPARE(editingFinishedSpy2.size(), 1); QTest::keyClick(box, Qt::Key_Up); - QCOMPARE(editingFinishedSpy1.count(), 1); - QCOMPARE(editingFinishedSpy2.count(), 1); + QCOMPARE(editingFinishedSpy1.size(), 1); + QCOMPARE(editingFinishedSpy2.size(), 1); QTest::keyClick(box, Qt::Key_Enter); - QCOMPARE(editingFinishedSpy1.count(), 2); - QCOMPARE(editingFinishedSpy2.count(), 1); + QCOMPARE(editingFinishedSpy1.size(), 2); + QCOMPARE(editingFinishedSpy2.size(), 1); QTest::keyClick(box, Qt::Key_Return); - QCOMPARE(editingFinishedSpy1.count(), 3); - QCOMPARE(editingFinishedSpy2.count(), 1); + QCOMPARE(editingFinishedSpy1.size(), 3); + QCOMPARE(editingFinishedSpy2.size(), 1); box2->setFocus(); - QCOMPARE(editingFinishedSpy1.count(), 4); - QCOMPARE(editingFinishedSpy2.count(), 1); + QCOMPARE(editingFinishedSpy1.size(), 4); + QCOMPARE(editingFinishedSpy2.size(), 1); QTest::keyClick(box2, Qt::Key_Enter); - QCOMPARE(editingFinishedSpy1.count(), 4); - QCOMPARE(editingFinishedSpy2.count(), 2); + QCOMPARE(editingFinishedSpy1.size(), 4); + QCOMPARE(editingFinishedSpy2.size(), 2); QTest::keyClick(box2, Qt::Key_Return); - QCOMPARE(editingFinishedSpy1.count(), 4); - QCOMPARE(editingFinishedSpy2.count(), 3); + QCOMPARE(editingFinishedSpy1.size(), 4); + QCOMPARE(editingFinishedSpy2.size(), 3); testFocusWidget.hide(); - QCOMPARE(editingFinishedSpy1.count(), 4); - QCOMPARE(editingFinishedSpy2.count(), 4); + QCOMPARE(editingFinishedSpy1.size(), 4); + QCOMPARE(editingFinishedSpy2.size(), 4); } void tst_QDoubleSpinBox::removeAll() @@ -1145,7 +1154,6 @@ void tst_QDoubleSpinBox::taskQTBUG_5008_textFromValueAndValidate() spinbox.show(); spinbox.activateWindow(); spinbox.setFocus(); - QApplication::setActiveWindow(&spinbox); QVERIFY(QTest::qWaitForWindowActive(&spinbox)); QCOMPARE(static_cast<QWidget *>(&spinbox), QApplication::activeWindow()); QTRY_VERIFY(spinbox.hasFocus()); @@ -1751,12 +1759,12 @@ void tst_QDoubleSpinBox::stepModifierPressAndHold() QStyle::CC_SpinBox, &spinBoxStyleOption, subControl, &spin); QTest::mousePress(&spin, Qt::LeftButton, modifiers, buttonRect.center()); - QTRY_VERIFY(spy.length() >= 3); + QTRY_VERIFY(spy.size() >= 3); QTest::mouseRelease(&spin, Qt::LeftButton, modifiers, buttonRect.center()); const auto value = spy.last().at(0); QVERIFY(value.userType() == QMetaType::Double); - QCOMPARE(value.toDouble(), spy.length() * expectedStepModifier); + QCOMPARE(value.toDouble(), spy.size() * expectedStepModifier); } QTEST_MAIN(tst_QDoubleSpinBox) diff --git a/tests/auto/widgets/widgets/qfocusframe/CMakeLists.txt b/tests/auto/widgets/widgets/qfocusframe/CMakeLists.txt index 140d9cddd9..5e2f3bd955 100644 --- a/tests/auto/widgets/widgets/qfocusframe/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qfocusframe/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qfocusframe.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qfocusframe Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qfocusframe LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qfocusframe SOURCES tst_qfocusframe.cpp diff --git a/tests/auto/widgets/widgets/qfocusframe/tst_qfocusframe.cpp b/tests/auto/widgets/widgets/qfocusframe/tst_qfocusframe.cpp index ce711b7ed7..560ba686cc 100644 --- a/tests/auto/widgets/widgets/qfocusframe/tst_qfocusframe.cpp +++ b/tests/auto/widgets/widgets/qfocusframe/tst_qfocusframe.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/widgets/qfontcombobox/CMakeLists.txt b/tests/auto/widgets/widgets/qfontcombobox/CMakeLists.txt index 8dc977dc8e..15dad99b9c 100644 --- a/tests/auto/widgets/widgets/qfontcombobox/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qfontcombobox/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qfontcombobox.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qfontcombobox Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qfontcombobox LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qfontcombobox SOURCES tst_qfontcombobox.cpp diff --git a/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp b/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp index 6a0749d7e3..abb9262288 100644 --- a/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp +++ b/tests/auto/widgets/widgets/qfontcombobox/tst_qfontcombobox.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -77,7 +77,7 @@ void tst_QFontComboBox::currentFont_data() if (!QFontDatabase::isPrivateFamily(defaultFont.family())) QTest::newRow("default2") << defaultFont; QStringList list = QFontDatabase::families(); - for (int i = 0; i < list.count(); ++i) { + for (int i = 0; i < list.size(); ++i) { QFont f = QFont(QStringList{QFontInfo(QFont(list.at(i))).family()}); if (!QFontDatabase::isPrivateFamily(f.families().first())) QTest::newRow(qPrintable(list.at(i))) << f; @@ -105,7 +105,7 @@ void tst_QFontComboBox::currentFont() if (oldCurrentFont != box.currentFont()) { //the signal may be emit twice if there is a foundry into brackets - QCOMPARE(spy0.count(),1); + QCOMPARE(spy0.size(),1); } } @@ -155,7 +155,7 @@ void tst_QFontComboBox::fontFilters() if((fontFilters & spacingMask) == spacingMask) fontFilters &= ~spacingMask; - for (int i = 0; i < list.count(); ++i) { + for (int i = 0; i < list.size(); ++i) { if (QFontDatabase::isPrivateFamily(list[i])) continue; if (fontFilters & QFontComboBox::ScalableFonts) { @@ -180,7 +180,7 @@ void tst_QFontComboBox::fontFilters() if (c == 0) QCOMPARE(box.currentFont(), QFont()); - QCOMPARE(spy0.count(), (currentFont != box.currentFont()) ? 1 : 0); + QCOMPARE(spy0.size(), (currentFont != box.currentFont()) ? 1 : 0); } // public QSize sizeHint() const @@ -221,17 +221,17 @@ void tst_QFontComboBox::writingSystem() QCOMPARE(box.writingSystem(), writingSystem); QStringList list = QFontDatabase::families(writingSystem); - int c = list.count(); - for (int i = 0; i < list.count(); ++i) { + int c = list.size(); + for (int i = 0; i < list.size(); ++i) { if (QFontDatabase::isPrivateFamily(list[i])) c--; } QCOMPARE(box.model()->rowCount(), c); - if (list.count() == 0) + if (list.size() == 0) QCOMPARE(box.currentFont(), QFont()); - QCOMPARE(spy0.count(), (currentFont != box.currentFont()) ? 1 : 0); + QCOMPARE(spy0.size(), (currentFont != box.currentFont()) ? 1 : 0); } // protected void currentFontChanged(QFont const& f) @@ -245,11 +245,11 @@ void tst_QFontComboBox::currentFontChanged() if (box->model()->rowCount() > 2) { QTest::keyPress(box, Qt::Key_Down); - QCOMPARE(spy0.count(), 1); + QCOMPARE(spy0.size(), 1); QFont f( "Sans Serif" ); box->setCurrentFont(f); - QCOMPARE(spy0.count(), 2); + QCOMPARE(spy0.size(), 2); } else qWarning("Not enough fonts installed on test system. Consider adding some"); } diff --git a/tests/auto/widgets/widgets/qframe/CMakeLists.txt b/tests/auto/widgets/widgets/qframe/CMakeLists.txt index 985f8f486b..2213f4a7d9 100644 --- a/tests/auto/widgets/widgets/qframe/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qframe/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qframe.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qframe Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qframe LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Collect test data file(GLOB_RECURSE test_data_glob RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} @@ -14,7 +18,7 @@ file(GLOB_RECURSE test_data_glob list(APPEND test_data ${test_data_glob}) qt_internal_add_test(tst_qframe - LOWDPI # special case + LOWDPI SOURCES tst_qframe.cpp LIBRARIES diff --git a/tests/auto/widgets/widgets/qframe/tst_qframe.cpp b/tests/auto/widgets/widgets/qframe/tst_qframe.cpp index 40cb897ed1..324c512219 100644 --- a/tests/auto/widgets/widgets/qframe/tst_qframe.cpp +++ b/tests/auto/widgets/widgets/qframe/tst_qframe.cpp @@ -1,6 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QFrame> diff --git a/tests/auto/widgets/widgets/qgroupbox/CMakeLists.txt b/tests/auto/widgets/widgets/qgroupbox/CMakeLists.txt index f4b3fc4bf4..0414ce0cf5 100644 --- a/tests/auto/widgets/widgets/qgroupbox/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qgroupbox/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qgroupbox.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qgroupbox Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qgroupbox LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qgroupbox SOURCES tst_qgroupbox.cpp @@ -14,4 +18,5 @@ qt_internal_add_test(tst_qgroupbox Qt::Gui Qt::GuiPrivate Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp b/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp index 6c42baf147..b178707e7a 100644 --- a/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp +++ b/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -14,6 +14,8 @@ #include <private/qguiapplication_p.h> #include <qpa/qplatformtheme.h> +#include <QtWidgets/private/qapplication_p.h> + #include "qgroupbox.h" class tst_QGroupBox : public QObject @@ -371,8 +373,8 @@ void tst_QGroupBox::clicked() else QTest::mouseClick(&testWidget, Qt::LeftButton); - QTEST(int(spy.count()), "clickedCount"); - if (spy.count() > 0) + QTEST(int(spy.size()), "clickedCount"); + if (spy.size() > 0) QTEST(spy.at(0).at(0).toBool(), "finalCheck"); QTEST(testWidget.isChecked(), "finalCheck"); } @@ -386,9 +388,9 @@ void tst_QGroupBox::toggledVsClicked() QSignalSpy clickSpy(&groupBox, SIGNAL(clicked(bool))); groupBox.setChecked(!groupBox.isChecked()); - QCOMPARE(clickSpy.count(), 0); - QCOMPARE(toggleSpy.count(), 1); - if (toggleSpy.count() > 0) + QCOMPARE(clickSpy.size(), 0); + QCOMPARE(toggleSpy.size(), 1); + if (toggleSpy.size() > 0) QCOMPARE(toggleSpy.at(0).at(0).toBool(), groupBox.isChecked()); connect(&groupBox, SIGNAL(clicked(bool)), this, SLOT(clickTimestampSlot())); @@ -401,8 +403,8 @@ void tst_QGroupBox::toggledVsClicked() QStyle::SC_GroupBoxCheckBox, &groupBox); QTest::mouseClick(&groupBox, Qt::LeftButton, {}, rect.center()); - QCOMPARE(clickSpy.count(), 1); - QCOMPARE(toggleSpy.count(), 2); + QCOMPARE(clickSpy.size(), 1); + QCOMPARE(toggleSpy.size(), 2); QVERIFY(toggleTimeStamp < clickTimeStamp); } @@ -428,7 +430,7 @@ void tst_QGroupBox::childrenAreDisabled() layout->addWidget(new QRadioButton); box.setLayout(layout); - foreach (QObject *object, box.children()) { + for (QObject *object : box.children()) { if (QWidget *widget = qobject_cast<QWidget *>(object)) { QVERIFY(!widget->isEnabled()); QVERIFY(!widget->testAttribute(Qt::WA_ForceDisabled)); @@ -436,7 +438,7 @@ void tst_QGroupBox::childrenAreDisabled() } box.setChecked(true); - foreach (QObject *object, box.children()) { + for (QObject *object : box.children()) { if (QWidget *widget = qobject_cast<QWidget *>(object)) { QVERIFY(widget->isEnabled()); QVERIFY(!widget->testAttribute(Qt::WA_ForceDisabled)); @@ -444,7 +446,7 @@ void tst_QGroupBox::childrenAreDisabled() } box.setChecked(false); - foreach (QObject *object, box.children()) { + for (QObject *object : box.children()) { if (QWidget *widget = qobject_cast<QWidget *>(object)) { QVERIFY(!widget->isEnabled()); QVERIFY(!widget->testAttribute(Qt::WA_ForceDisabled)); @@ -460,7 +462,6 @@ void tst_QGroupBox::propagateFocus() QGroupBox box; QLineEdit lineEdit(&box); box.show(); - QApplication::setActiveWindow(&box); QVERIFY(QTest::qWaitForWindowActive(&box)); box.setFocus(); QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget*>(&lineEdit)); @@ -598,9 +599,9 @@ void tst_QGroupBox::buttonPressKeys() const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ->themeHint(QPlatformTheme::ButtonPressKeys) .value<QList<Qt::Key>>(); - for (int i = 0; i < buttonPressKeys.length(); ++i) { + for (int i = 0; i < buttonPressKeys.size(); ++i) { QTest::keyClick(&groupBox, buttonPressKeys[i]); - QCOMPARE(clickedSpy.length(), i + 1); + QCOMPARE(clickedSpy.size(), i + 1); } } diff --git a/tests/auto/widgets/widgets/qkeysequenceedit/CMakeLists.txt b/tests/auto/widgets/widgets/qkeysequenceedit/CMakeLists.txt index 45ea9e2078..0cf0b1bdd3 100644 --- a/tests/auto/widgets/widgets/qkeysequenceedit/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qkeysequenceedit/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qkeysequenceedit.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qkeysequenceedit Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qkeysequenceedit LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qkeysequenceedit SOURCES tst_qkeysequenceedit.cpp diff --git a/tests/auto/widgets/widgets/qkeysequenceedit/tst_qkeysequenceedit.cpp b/tests/auto/widgets/widgets/qkeysequenceedit/tst_qkeysequenceedit.cpp index a0a2fe023a..301be319bf 100644 --- a/tests/auto/widgets/widgets/qkeysequenceedit/tst_qkeysequenceedit.cpp +++ b/tests/auto/widgets/widgets/qkeysequenceedit/tst_qkeysequenceedit.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -37,7 +37,7 @@ void tst_QKeySequenceEdit::testSetters() edit.clear(); QCOMPARE(edit.keySequence(), QKeySequence()); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); } void tst_QKeySequenceEdit::testKeys_data() @@ -99,9 +99,9 @@ void tst_QKeySequenceEdit::testKeys() QTest::keyPress(&edit, key, modifiers); QTest::keyRelease(&edit, key, modifiers); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QCOMPARE(edit.keySequence(), keySequence); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); } void tst_QKeySequenceEdit::testLineEditContents() @@ -146,21 +146,21 @@ void tst_QKeySequenceEdit::testFinishingKeyCombinations() QKeySequenceEdit edit; QSignalSpy spy(&edit, SIGNAL(editingFinished())); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); edit.setFinishingKeyCombinations({QKeyCombination(modifiers, key)}); QTest::keyPress(&edit, key, modifiers); QTest::keyRelease(&edit, key, modifiers); QCOMPARE(edit.keySequence(), QKeySequence()); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); edit.setFinishingKeyCombinations({}); QTest::keyPress(&edit, key, modifiers); QTest::keyRelease(&edit, key, modifiers); QCOMPARE(edit.keySequence(), keySequence); - QTRY_COMPARE(spy.count(), 2); + QTRY_COMPARE(spy.size(), 2); } QTEST_MAIN(tst_QKeySequenceEdit) diff --git a/tests/auto/widgets/widgets/qlabel/CMakeLists.txt b/tests/auto/widgets/widgets/qlabel/CMakeLists.txt index 7e100fdae4..e29000a6ca 100644 --- a/tests/auto/widgets/widgets/qlabel/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qlabel/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qlabel.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qlabel Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qlabel LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Collect test data file(GLOB_RECURSE test_data_glob RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp index 3441e6296d..325e188091 100644 --- a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp +++ b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -18,6 +18,8 @@ #include <qmath.h> #include <private/qlabel_p.h> +#include <QtWidgets/private/qapplication_p.h> + class Widget : public QWidget { Q_OBJECT @@ -75,12 +77,16 @@ private Q_SLOTS: #ifndef QT_NO_CONTEXTMENU void taskQTBUG_7902_contextMenuCrash(); + void contextMenu_data(); + void contextMenu(); #endif void taskQTBUG_48157_dprPixmap(); void taskQTBUG_48157_dprMovie(); void resourceProvider(); + void mouseEventPropagation_data(); + void mouseEventPropagation(); private: QLabel *testWidget; @@ -165,7 +171,7 @@ void tst_QLabel::setBuddy() layout->addWidget(test_edit); layout->addWidget(test_edit2); test_box->show(); - qApp->setActiveWindow(test_box); + QApplicationPrivate::setActiveWindow(test_box); QVERIFY(test_box->isActiveWindow()); test_label->setBuddy( test_edit ); @@ -557,6 +563,43 @@ void tst_QLabel::taskQTBUG_7902_contextMenuCrash() QTest::qWait(350); // No crash, it's allright. } + +void tst_QLabel::contextMenu_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<Qt::TextInteractionFlag>("interactionFlags"); + QTest::addColumn<bool>("showsContextMenu"); + + QTest::addRow("Read-only") << "Plain Text" + << Qt::NoTextInteraction + << false; + QTest::addRow("Selectable") << "Plain Text" + << Qt::TextEditorInteraction + << true; + QTest::addRow("Link") << "<a href=\"nowhere\">Rich text with link</a>" + << Qt::TextBrowserInteraction + << true; + QTest::addRow("Rich text") << "<b>Rich text without link</b>" + << Qt::TextBrowserInteraction + << true; +} + +void tst_QLabel::contextMenu() +{ + QFETCH(QString, text); + QFETCH(Qt::TextInteractionFlag, interactionFlags); + QFETCH(bool, showsContextMenu); + + QLabel label(text); + label.setTextInteractionFlags(interactionFlags); + label.show(); + QVERIFY(QTest::qWaitForWindowExposed(&label)); + + const QPoint menuPosition = label.rect().center(); + QContextMenuEvent cme(QContextMenuEvent::Mouse, menuPosition, label.mapToGlobal(menuPosition)); + QApplication::sendEvent(&label, &cme); + QCOMPARE(cme.isAccepted(), showsContextMenu); +} #endif void tst_QLabel::taskQTBUG_48157_dprPixmap() @@ -598,5 +641,94 @@ void tst_QLabel::resourceProvider() QVERIFY(providerCalled > 0); } +// Test if mouse events are correctly propagated to the parent widget, +// even if a label contains rich text (QTBUG-110055) +void tst_QLabel::mouseEventPropagation_data() +{ + QTest::addColumn<const QString>("text"); + QTest::addColumn<const Qt::TextInteractionFlag>("interaction"); + QTest::addColumn<const QList<Qt::MouseButton>>("buttons"); + QTest::addColumn<const bool>("expectPropagation"); + + + QTest::newRow("RichText") + << QString("<b>This is a rich text propagating mouse events</b>") + << Qt::LinksAccessibleByMouse + << QList<Qt::MouseButton>{Qt::LeftButton, Qt::RightButton, Qt::MiddleButton} + << true; + QTest::newRow("PlainText") + << QString("This is a plain text propagating mouse events") + << Qt::LinksAccessibleByMouse + << QList<Qt::MouseButton>{Qt::LeftButton, Qt::RightButton, Qt::MiddleButton} + << true; + QTest::newRow("PlainTextConsume") + << QString("This is a plain text consuming mouse events") + << Qt::TextSelectableByMouse + << QList<Qt::MouseButton>{Qt::LeftButton} + << false; + QTest::newRow("RichTextConsume") + << QString("<b>This is a rich text consuming mouse events</b>") + << Qt::TextSelectableByMouse + << QList<Qt::MouseButton>{Qt::LeftButton} + << false; + QTest::newRow("PlainTextNoInteraction") + << QString("This is a text not interacting with mouse") + << Qt::NoTextInteraction + << QList<Qt::MouseButton>{Qt::LeftButton, Qt::RightButton, Qt::MiddleButton} + << true; + QTest::newRow("RichTextNoInteraction") + << QString("<b>This is a rich text not interacting with mouse</b>") + << Qt::NoTextInteraction + << QList<Qt::MouseButton>{Qt::LeftButton, Qt::RightButton, Qt::MiddleButton} + << true; +} + +void tst_QLabel::mouseEventPropagation() +{ + class MouseEventWidget : public QWidget + { + public: + uint pressed() const { return m_pressed; } + uint released() const { return m_released; } + + private: + uint m_pressed = 0; + uint m_released = 0; + void mousePressEvent(QMouseEvent *event) override + { + ++m_pressed; + return QWidget::mousePressEvent(event); + } + + void mouseReleaseEvent(QMouseEvent *event) override + { + ++m_released; + return QWidget::mouseReleaseEvent(event); + } + }; + + QFETCH(const QString, text); + QFETCH(const Qt::TextInteractionFlag, interaction); + QFETCH(const QList<Qt::MouseButton>, buttons); + QFETCH(const bool, expectPropagation); + + MouseEventWidget widget; + auto *layout = new QVBoxLayout(&widget); + auto *label = new QLabel(text); + label->setTextInteractionFlags(interaction); + + layout->addWidget(label); + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + const QPoint labelCenter = label->rect().center(); + for (Qt::MouseButton mouseButton : buttons) + QTest::mouseClick(label, mouseButton, Qt::KeyboardModifiers(), labelCenter); + + const uint count = expectPropagation ? buttons.count() : 0; + QTRY_COMPARE(widget.pressed(), count); + QTRY_COMPARE(widget.released(), count); +} + QTEST_MAIN(tst_QLabel) #include "tst_qlabel.moc" diff --git a/tests/auto/widgets/widgets/qlcdnumber/CMakeLists.txt b/tests/auto/widgets/widgets/qlcdnumber/CMakeLists.txt index c378535b1f..954ec095e5 100644 --- a/tests/auto/widgets/widgets/qlcdnumber/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qlcdnumber/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qlcdnumber.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qlcdnumber Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qlcdnumber LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qlcdnumber SOURCES tst_qlcdnumber.cpp diff --git a/tests/auto/widgets/widgets/qlcdnumber/tst_qlcdnumber.cpp b/tests/auto/widgets/widgets/qlcdnumber/tst_qlcdnumber.cpp index c339268e8e..8fcf9c49fe 100644 --- a/tests/auto/widgets/widgets/qlcdnumber/tst_qlcdnumber.cpp +++ b/tests/auto/widgets/widgets/qlcdnumber/tst_qlcdnumber.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/widgets/qlineedit/CMakeLists.txt b/tests/auto/widgets/widgets/qlineedit/CMakeLists.txt index ab2917b4d0..22ecf40aed 100644 --- a/tests/auto/widgets/widgets/qlineedit/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qlineedit/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qlineedit.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qlineedit Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qlineedit LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qlineedit SOURCES tst_qlineedit.cpp diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp index b1928e3785..7a63c156f3 100644 --- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp +++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -267,6 +267,8 @@ private slots: void inputMethodQueryImHints_data(); void inputMethodQueryImHints(); + void inputMethodQueryEnterKeyType(); + void inputMethodUpdate(); void undoRedoAndEchoModes_data(); @@ -290,6 +292,13 @@ private slots: void QTBUG_60319_setInputMaskCheckImSurroundingText(); void testQuickSelectionWithMouse(); void inputRejected(); + void keyReleasePropagates(); + +#if QT_CONFIG(shortcut) + void deleteWordByKeySequence_data(); + void deleteWordByKeySequence(); +#endif + protected slots: void editingFinished(); @@ -652,7 +661,7 @@ void tst_QLineEdit::setInputMask() testWidget->insert(input); } else { psKeyClick(testWidget, Qt::Key_Home); - for (int i=0; i<input.length(); i++) + for (int i=0; i<input.size(); i++) QTest::keyClick(testWidget, input.at(i).toLatin1()); } @@ -919,8 +928,8 @@ void tst_QLineEdit::hasAcceptableInputValidator() qApp->sendEvent(testWidget, &lostFocus); QVERIFY(testWidget->hasAcceptableInput()); - QCOMPARE(spyChanged.count(), 2); - QCOMPARE(spyEdited.count(), 0); + QCOMPARE(spyChanged.size(), 2); + QCOMPARE(spyEdited.size(), 0); } @@ -1592,7 +1601,7 @@ void tst_QLineEdit::setText() QSignalSpy editedSpy(testWidget, SIGNAL(textEdited(QString))); QSignalSpy changedSpy(testWidget, SIGNAL(textChanged(QString))); testWidget->setText("hello"); - QCOMPARE(editedSpy.count(), 0); + QCOMPARE(editedSpy.size(), 0); QCOMPARE(changedSpy.value(0).value(0).toString(), QString("hello")); } @@ -1664,7 +1673,7 @@ void tst_QLineEdit::displayText_data() QString input; QString pass; input = "Hello World"; - pass.resize(input.length()); + pass.resize(input.size()); pass.fill(passChar); QTest::newRow(QString(s + " text0").toLatin1()) << input << pass << m << bool(use_setText); QTest::newRow(QString(s + " text1").toLatin1()) << QString("") << @@ -1672,14 +1681,14 @@ void tst_QLineEdit::displayText_data() m << bool(use_setText); QTest::newRow(QString(s + " text2").toLatin1()) << QString("A") << QString(passChar) << m << bool(use_setText); input = QString("ryyryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryryrryryryryryryryryryryryryry"); - pass.resize(input.length()); + pass.resize(input.size()); pass.fill(passChar); QTest::newRow(QString(s + " text3").toLatin1()) << input << pass << m << bool(use_setText); input = QString("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890`~!@#$%^&*()_-+={[}]|\\:;'?/>.<,\""); - pass.fill(passChar, input.length()); + pass.fill(passChar, input.size()); QTest::newRow(QString(s + " text4").toLatin1()) << input << pass << m << bool(use_setText); input = QString("Hello") + QChar(0xa0) + "World"; - pass.resize(input.length()); + pass.resize(input.size()); pass.fill(passChar); QTest::newRow(QString(s + " text with nbsp").toLatin1()) << input << pass << m << bool(use_setText); } @@ -2292,7 +2301,7 @@ void tst_QLineEdit::deleteSelectedText() #ifndef QT_NO_CONTEXTMENU QMenu *menu = edit.createStandardContextMenu(); - for (int i = 0; i < menu->actions().count(); ++i) { + for (int i = 0; i < menu->actions().size(); ++i) { QAction *current = menu->actions().at(i); if (current->text() == QLineEdit::tr("Delete")) { current->trigger(); //this will delete the whole text selected @@ -2425,7 +2434,7 @@ class QIntFixValidator : public QIntValidator { public: QIntFixValidator(int min, int max, QObject *parent) : QIntValidator(min, max, parent) {} void fixup (QString &input) const override { - for (int i=0; i<input.length(); ++i) + for (int i=0; i<input.size(); ++i) if (!input.at(i).isNumber()) { input[(int)i] = QChar('0'); } @@ -2991,7 +3000,7 @@ void tst_QLineEdit::setSelection_data() QTest::newRow(selectionTestName(start, length).constData()) << text << start << length << pos << QString("Abc ") << true; - start = -1; length = 0; pos = text.length(); + start = -1; length = 0; pos = text.size(); QTest::newRow(selectionTestName(start, length).constData()) << text << start << length << pos << QString() << false; @@ -3011,7 +3020,7 @@ void tst_QLineEdit::setSelection_data() QTest::newRow(selectionTestName(start, length).constData()) << text << start << length << pos << QString("A") << true; - start = -1; length = -1; pos = text.length(); + start = -1; length = -1; pos = text.size(); QTest::newRow(selectionTestName(start, length).constData()) << text << start << length << pos << QString() << false; } @@ -3308,7 +3317,7 @@ void tst_QLineEdit::validateOnFocusOut() QTest::keyPress(testWidget, '0'); QCOMPARE(testWidget->text(), QString("10")); testWidget->clearFocus(); - QCOMPARE(editingFinishedSpy.count(), 0); + QCOMPARE(editingFinishedSpy.size(), 0); testWidget->setFocus(); centerOnScreen(testWidget); @@ -3321,7 +3330,7 @@ void tst_QLineEdit::validateOnFocusOut() QTRY_COMPARE(testWidget->text(), QString("100")); testWidget->clearFocus(); - QCOMPARE(editingFinishedSpy.count(), 1); + QCOMPARE(editingFinishedSpy.size(), 1); } void tst_QLineEdit::editInvalidText() @@ -3499,7 +3508,7 @@ void tst_QLineEdit::noTextEditedOnClear() testWidget->setText("Test"); QSignalSpy textEditedSpy(testWidget, SIGNAL(textEdited(QString))); testWidget->clear(); - QCOMPARE(textEditedSpy.count(), 0); + QCOMPARE(textEditedSpy.size(), 0); } void tst_QLineEdit::textMargin_data() @@ -3515,11 +3524,12 @@ void tst_QLineEdit::textMargin_data() QLineEdit testWidget; QFontMetrics metrics(testWidget.font()); const QString s = QLatin1String("MMM MMM MMM"); + const int windows11StyleHorizontalOffset = qApp->style()->inherits("QWindows11Style") ? 8 : 0; // Different styles generate different offsets, so // calculate the width rather than hardcode it. - const int pixelWidthOfM = metrics.horizontalAdvance(s, 1); - const int pixelWidthOfMMM_MM = metrics.horizontalAdvance(s, 6); + const int pixelWidthOfM = windows11StyleHorizontalOffset + metrics.horizontalAdvance(s, 1); + const int pixelWidthOfMMM_MM = windows11StyleHorizontalOffset + metrics.horizontalAdvance(s, 6); QTest::newRow("default-0") << 0 << 0 << 0 << 0 << QPoint(pixelWidthOfMMM_MM, 0) << 6; QTest::newRow("default-1") << 0 << 0 << 0 << 0 << QPoint(1, 1) << 0; @@ -3603,7 +3613,7 @@ void tst_QLineEdit::returnKeyClearsEditedFlag() // Focus drop with no edits shouldn't emit signal, edited flag == false testWidget.clearFocus(); // Signal not emitted QVERIFY(!testWidget.hasFocus()); - QCOMPARE(leSpy.count(), 0); + QCOMPARE(leSpy.size(), 0); // Focus drop after edits should emit signal, edited flag == true testWidget.setFocus(); @@ -3611,7 +3621,7 @@ void tst_QLineEdit::returnKeyClearsEditedFlag() QTest::keyClicks(&testWidget, "edit1 "); // edited flag set testWidget.clearFocus(); // edited flag cleared, signal emitted QVERIFY(!testWidget.hasFocus()); - QCOMPARE(leSpy.count(), 1); + QCOMPARE(leSpy.size(), 1); // Only text related keys should set edited flag testWidget.setFocus(); @@ -3621,7 +3631,7 @@ void tst_QLineEdit::returnKeyClearsEditedFlag() QTest::keyClick(&testWidget, Qt::Key_PageUp); testWidget.clearFocus(); // Signal not emitted QVERIFY(!testWidget.hasFocus()); - QCOMPARE(leSpy.count(), 1); // No change + QCOMPARE(leSpy.size(), 1); // No change // Return should always emit signal testWidget.setFocus(); @@ -3629,12 +3639,12 @@ void tst_QLineEdit::returnKeyClearsEditedFlag() QTest::keyClick(&testWidget, Qt::Key_Return); /* Without edits, signal emitted, edited flag cleared */ - QCOMPARE(leSpy.count(), 2); + QCOMPARE(leSpy.size(), 2); QTest::keyClicks(&testWidget, "edit2 "); // edited flag set QTest::keyClick(&testWidget, Qt::Key_Return); /* With edits, signal emitted, edited flag cleared */ - QCOMPARE(leSpy.count(), 3); + QCOMPARE(leSpy.size(), 3); /* After editing the line edit following a Return key press with a focus drop should not emit signal a second time since Return now @@ -3642,10 +3652,10 @@ void tst_QLineEdit::returnKeyClearsEditedFlag() QTest::keyClicks(&testWidget, "edit3 "); // edited flag set QTest::keyClick(&testWidget, Qt::Key_Return); /* signal emitted, edited flag cleared */ - QCOMPARE(leSpy.count(), 4); + QCOMPARE(leSpy.size(), 4); testWidget.clearFocus(); // Signal not emitted since edited == false QVERIFY(!testWidget.hasFocus()); - QCOMPARE(leSpy.count(), 4); // No change + QCOMPARE(leSpy.size(), 4); // No change } #ifndef QT_NO_CURSOR @@ -3712,7 +3722,6 @@ void tst_QLineEdit::task174640_editingFinished() layout->addWidget(le2); mw.show(); - QApplication::setActiveWindow(&mw); mw.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&mw)); QCOMPARE(&mw, QApplication::activeWindow()); @@ -3721,19 +3730,19 @@ void tst_QLineEdit::task174640_editingFinished() le1->setFocus(); QTRY_VERIFY(le1->hasFocus()); - QCOMPARE(editingFinishedSpy.count(), 0); + QCOMPARE(editingFinishedSpy.size(), 0); le2->setFocus(); QTRY_VERIFY(le2->hasFocus()); // editingFinished will not be emitted anew because no editing happened - QCOMPARE(editingFinishedSpy.count(), 0); + QCOMPARE(editingFinishedSpy.size(), 0); le1->setFocus(); QTRY_VERIFY(le1->hasFocus()); QTest::keyPress(le1, Qt::Key_Plus); le2->setFocus(); QTRY_VERIFY(le2->hasFocus()); - QCOMPARE(editingFinishedSpy.count(), 1); + QCOMPARE(editingFinishedSpy.size(), 1); editingFinishedSpy.clear(); le1->setFocus(); @@ -3748,7 +3757,7 @@ void tst_QLineEdit::task174640_editingFinished() mw.activateWindow(); delete testMenu1; - QCOMPARE(editingFinishedSpy.count(), 0); + QCOMPARE(editingFinishedSpy.size(), 0); QTRY_VERIFY(le1->hasFocus()); // Ensure le1 has been edited QTest::keyPress(le1, Qt::Key_Plus); @@ -3761,7 +3770,7 @@ void tst_QLineEdit::task174640_editingFinished() QTest::qWait(20); mw.activateWindow(); delete testMenu2; - QCOMPARE(editingFinishedSpy.count(), 1); + QCOMPARE(editingFinishedSpy.size(), 1); } #if QT_CONFIG(completer) @@ -3820,7 +3829,6 @@ void tst_QLineEdit::task210502_caseInsensitiveInlineCompletion() completer.setCompletionMode(QCompleter::InlineCompletion); lineEdit.setCompleter(&completer); lineEdit.show(); - QApplication::setActiveWindow(&lineEdit); QVERIFY(QTest::qWaitForWindowActive(&lineEdit)); lineEdit.setFocus(); QTRY_VERIFY(lineEdit.hasFocus()); @@ -3846,7 +3854,7 @@ void tst_QLineEdit::task229938_dontEmitChangedWhenTextIsNotChanged() QTest::keyPress(&lineEdit, 'd'); QTest::keyPress(&lineEdit, 'e'); QTest::keyPress(&lineEdit, 'f'); - QCOMPARE(changedSpy.count(), 5); + QCOMPARE(changedSpy.size(), 5); } void tst_QLineEdit::task233101_cursorPosAfterInputMethod_data() @@ -3921,7 +3929,6 @@ void tst_QLineEdit::task241436_passwordEchoOnEditRestoreEchoMode() testWidget->setFocus(); centerOnScreen(testWidget); testWidget->show(); - QApplication::setActiveWindow(testWidget); QVERIFY(QTest::qWaitForWindowActive(testWidget)); QVERIFY(testWidget->hasFocus()); @@ -3972,7 +3979,6 @@ void tst_QLineEdit::taskQTBUG_4401_enterKeyClearsPassword() testWidget->selectAll(); centerOnScreen(testWidget); testWidget->show(); - QApplication::setActiveWindow(testWidget); QVERIFY(QTest::qWaitForWindowActive(testWidget)); QTest::keyPress(testWidget, Qt::Key_Enter); @@ -4055,13 +4061,12 @@ void tst_QLineEdit::taskQTBUG_7395_readOnlyShortcut() le.show(); QVERIFY(QTest::qWaitForWindowExposed(&le)); - QApplication::setActiveWindow(&le); QVERIFY(QTest::qWaitForWindowActive(&le)); le.setFocus(); QTRY_VERIFY(le.hasFocus()); QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_P); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } void tst_QLineEdit::QTBUG697_paletteCurrentColorGroup() @@ -4077,7 +4082,6 @@ void tst_QLineEdit::QTBUG697_paletteCurrentColorGroup() le.setPalette(p); le.show(); - QApplication::setActiveWindow(&le); QVERIFY(QTest::qWaitForWindowActive(&le)); le.setFocus(); QTRY_VERIFY(le.hasFocus()); @@ -4348,14 +4352,14 @@ void tst_QLineEdit::inputMethodSelection() testWidget->setSelection(0,0); QSignalSpy selectionSpy(testWidget, SIGNAL(selectionChanged())); - QCOMPARE(selectionSpy.count(), 0); + QCOMPARE(selectionSpy.size(), 0); QCOMPARE(testWidget->selectionStart(), -1); QCOMPARE(testWidget->selectionEnd(), -1); QCOMPARE(testWidget->selectionLength(), 0); testWidget->setSelection(0,5); - QCOMPARE(selectionSpy.count(), 1); + QCOMPARE(selectionSpy.size(), 1); QCOMPARE(testWidget->selectionStart(), 0); QCOMPARE(testWidget->selectionEnd(), 5); QCOMPARE(testWidget->selectionLength(), 5); @@ -4369,7 +4373,7 @@ void tst_QLineEdit::inputMethodSelection() QApplication::sendEvent(testWidget, &event); } - QCOMPARE(selectionSpy.count(), 2); + QCOMPARE(selectionSpy.size(), 2); QCOMPARE(testWidget->selectionStart(), 12); QCOMPARE(testWidget->selectionEnd(), 17); QCOMPARE(testWidget->selectionLength(), 5); @@ -4382,7 +4386,7 @@ void tst_QLineEdit::inputMethodSelection() QApplication::sendEvent(testWidget, &event); } - QCOMPARE(selectionSpy.count(), 3); + QCOMPARE(selectionSpy.size(), 3); QCOMPARE(testWidget->selectionStart(), -1); QCOMPARE(testWidget->selectionEnd(), -1); QCOMPARE(testWidget->selectionLength(), 0); @@ -4409,6 +4413,33 @@ void tst_QLineEdit::inputMethodQueryImHints() QCOMPARE(static_cast<Qt::InputMethodHints>(value.toInt()), hints); } +void tst_QLineEdit::inputMethodQueryEnterKeyType() +{ + QWidget mw; + QVBoxLayout layout(&mw); + QLineEdit le1(&mw); + layout.addWidget(&le1); + mw.show(); + QVariant enterType = le1.inputMethodQuery(Qt::ImEnterKeyType); + QCOMPARE(enterType.value<Qt::EnterKeyType>(), Qt::EnterKeyDefault); + + mw.hide(); + QLineEdit le2(&mw); + layout.addWidget(&le2); + mw.show(); + + enterType = le1.inputMethodQuery(Qt::ImEnterKeyType); +#ifdef Q_OS_ANDROID + // QTBUG-61652 + // EnterKey is changed to EnterKeyNext if the focus can be moved to widget below + QCOMPARE(enterType.value<Qt::EnterKeyType>(), Qt::EnterKeyNext); +#else + QCOMPARE(enterType.value<Qt::EnterKeyType>(), Qt::EnterKeyDefault); +#endif + enterType = le2.inputMethodQuery(Qt::ImEnterKeyType); + QCOMPARE(enterType.value<Qt::EnterKeyType>(), Qt::EnterKeyDefault); +} + void tst_QLineEdit::inputMethodUpdate() { if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) @@ -4545,7 +4576,6 @@ void tst_QLineEdit::clearButton() l->addWidget(listView); testWidget.move(300, 300); testWidget.show(); - qApp->setActiveWindow(&testWidget); QVERIFY(QTest::qWaitForWindowActive(&testWidget)); // Flip the clear button on,off, trying to detect crashes. filterLineEdit->setClearButtonEnabled(true); @@ -4570,11 +4600,11 @@ void tst_QLineEdit::clearButton() QSignalSpy spyEdited(filterLineEdit, &QLineEdit::textEdited); const QPoint clearButtonCenterPos = QRect(QPoint(0, 0), clearButton->size()).center(); QTest::mouseClick(clearButton, Qt::LeftButton, {}, clearButtonCenterPos); - QCOMPARE(spyEdited.count(), 1); + QCOMPARE(spyEdited.size(), 1); QTRY_COMPARE(clearButton->cursor().shape(), filterLineEdit->cursor().shape()); QTRY_COMPARE(filterModel->rowCount(), 3); QCoreApplication::processEvents(); - QCOMPARE(spyEdited.count(), 1); + QCOMPARE(spyEdited.size(), 1); filterLineEdit->setReadOnly(true); // QTBUG-34315 QVERIFY(!clearButton->isEnabled()); @@ -4656,7 +4686,8 @@ void tst_QLineEdit::sideWidgets() testWidget.move(300, 300); testWidget.show(); QVERIFY(QTest::qWaitForWindowExposed(&testWidget)); - foreach (QToolButton *button, lineEdit->findChildren<QToolButton *>()) + const auto buttons = lineEdit->findChildren<QToolButton *>(); + for (QToolButton *button : buttons) QCOMPARE(button->cursor().shape(), Qt::ArrowCursor); // Arbitrarily add/remove actions, trying to detect crashes. Add QTRY_VERIFY(false) to view the result. delete label3Action; @@ -4671,7 +4702,8 @@ void tst_QLineEdit::sideWidgets() template <class T> T *findAssociatedWidget(const QAction *a) { - foreach (QObject *w, a->associatedObjects()) { + const auto associatedObjects = a->associatedObjects(); + for (QObject *w : associatedObjects) { if (T *result = qobject_cast<T *>(w)) return result; } @@ -4851,7 +4883,7 @@ void tst_QLineEdit::QTBUG1266_setInputMaskEmittingTextEdited() QSignalSpy spy(&lineEdit, SIGNAL(textEdited(QString))); lineEdit.setInputMask("AAAA"); lineEdit.setInputMask(QString()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } #if QT_CONFIG(shortcut) @@ -4912,7 +4944,7 @@ void tst_QLineEdit::shortcutOverrideOnReadonlyLineEdit() } const int activationCount = shouldBeHandledByQLineEdit ? 0 : 1; - QCOMPARE(spy.count(), activationCount); + QCOMPARE(spy.size(), activationCount); } #endif // QT_CONFIG(shortcut) @@ -4945,7 +4977,7 @@ void tst_QLineEdit::QTBUG59957_clearButtonLeftmostAction() bool tst_QLineEdit::unselectingWithLeftOrRightChangesCursorPosition() { -#if defined Q_OS_WIN || defined Q_OS_QNX //Windows and QNX do not jump to the beginning of the selection +#if defined Q_OS_WIN || defined Q_OS_QNX || defined Q_OS_VXWORKS //Windows, QNX and VxWorks do not jump to the beginning of the selection return true; #endif // Platforms minimal/offscreen also need left after unselecting with right @@ -4965,10 +4997,10 @@ void tst_QLineEdit::QTBUG_60319_setInputMaskCheckImSurroundingText() QLineEdit *testWidget = ensureTestWidget(); QString mask("+000(000)-000-00-00"); testWidget->setInputMask(mask); - testWidget->setCursorPosition(mask.length()); + testWidget->setCursorPosition(mask.size()); QString surroundingText = testWidget->inputMethodQuery(Qt::ImSurroundingText).toString(); int cursorPosition = testWidget->inputMethodQuery(Qt::ImCursorPosition).toInt(); - QCOMPARE(surroundingText.length(), cursorPosition); + QCOMPARE(surroundingText.size(), cursorPosition); } void tst_QLineEdit::testQuickSelectionWithMouse() @@ -5065,18 +5097,18 @@ void tst_QLineEdit::inputRejected() QSignalSpy spyInputRejected(testWidget, SIGNAL(inputRejected())); QTest::keyClicks(testWidget, "abcde"); - QCOMPARE(spyInputRejected.count(), 0); + QCOMPARE(spyInputRejected.size(), 0); testWidget->setText("fghij"); - QCOMPARE(spyInputRejected.count(), 0); + QCOMPARE(spyInputRejected.size(), 0); testWidget->insert("k"); - QCOMPARE(spyInputRejected.count(), 0); + QCOMPARE(spyInputRejected.size(), 0); testWidget->clear(); testWidget->setMaxLength(5); QTest::keyClicks(testWidget, "abcde"); - QCOMPARE(spyInputRejected.count(), 0); + QCOMPARE(spyInputRejected.size(), 0); QTest::keyClicks(testWidget, "fgh"); - QCOMPARE(spyInputRejected.count(), 3); + QCOMPARE(spyInputRejected.size(), 3); #if QT_CONFIG(clipboard) testWidget->clear(); spyInputRejected.clear(); @@ -5084,7 +5116,7 @@ void tst_QLineEdit::inputRejected() testWidget->paste(); // The first 5 characters are accepted, but // the last 2 are not. - QCOMPARE(spyInputRejected.count(), 1); + QCOMPARE(spyInputRejected.size(), 1); #endif testWidget->setMaxLength(INT_MAX); @@ -5093,15 +5125,15 @@ void tst_QLineEdit::inputRejected() QIntValidator intValidator(1, 100); testWidget->setValidator(&intValidator); QTest::keyClicks(testWidget, "11"); - QCOMPARE(spyInputRejected.count(), 0); + QCOMPARE(spyInputRejected.size(), 0); QTest::keyClicks(testWidget, "a#"); - QCOMPARE(spyInputRejected.count(), 2); + QCOMPARE(spyInputRejected.size(), 2); #if QT_CONFIG(clipboard) testWidget->clear(); spyInputRejected.clear(); QApplication::clipboard()->setText("a#"); testWidget->paste(); - QCOMPARE(spyInputRejected.count(), 1); + QCOMPARE(spyInputRejected.size(), 1); #endif testWidget->clear(); @@ -5109,10 +5141,154 @@ void tst_QLineEdit::inputRejected() spyInputRejected.clear(); testWidget->setInputMask("999.999.999.999;_"); QTest::keyClicks(testWidget, "11"); - QCOMPARE(spyInputRejected.count(), 0); + QCOMPARE(spyInputRejected.size(), 0); QTest::keyClicks(testWidget, "a#"); - QCOMPARE(spyInputRejected.count(), 2); + QCOMPARE(spyInputRejected.size(), 2); +} + +void tst_QLineEdit::keyReleasePropagates() +{ + struct Dialog : QWidget + { + QLineEdit *lineEdit; + int releasedKey = {}; + + Dialog() + { + lineEdit = new QLineEdit; + QHBoxLayout *hbox = new QHBoxLayout; + + hbox->addWidget(lineEdit); + setLayout(hbox); + } + + protected: + void keyReleaseEvent(QKeyEvent *e) override + { + releasedKey = e->key(); + } + } dialog; + + dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + + QTest::keyPress(dialog.lineEdit, Qt::Key_A); + QTest::keyRelease(dialog.lineEdit, Qt::Key_A); + + QCOMPARE(dialog.releasedKey, Qt::Key_A); + + QTest::keyPress(dialog.lineEdit, Qt::Key_Alt); + QTest::keyRelease(dialog.lineEdit, Qt::Key_Alt); + + QCOMPARE(dialog.releasedKey, Qt::Key_Alt); } +#if QT_CONFIG(shortcut) + +void tst_QLineEdit::deleteWordByKeySequence_data() +{ + QTest::addColumn<QString>("startText"); + QTest::addColumn<int>("selectionStart"); + QTest::addColumn<int>("selectionEnd"); + QTest::addColumn<int>("cursorPosition"); + QTest::addColumn<QKeySequence::StandardKey>("key"); + QTest::addColumn<QString>("expectedText"); + QTest::addColumn<int>("expectedCursorPosition"); + + QTest::newRow("Delete start, no selection") + << QStringLiteral("Some Text") << 0 << 0 << 9 << QKeySequence::DeleteStartOfWord + << QStringLiteral("Some ") << 5; + QTest::newRow("Delete end, no selection") + << QStringLiteral("Some Text") << 0 << 0 << 5 << QKeySequence::DeleteEndOfWord + << QStringLiteral("Some ") << 5; + QTest::newRow("Delete start from middle, no selection") + << QStringLiteral("Some Text") << 0 << 0 << 7 << QKeySequence::DeleteStartOfWord + << QStringLiteral("Some xt") << 5; + QTest::newRow("Delete end from middle, no selection") + << QStringLiteral("Some Text") << 0 << 0 << 7 << QKeySequence::DeleteEndOfWord + << QStringLiteral("Some Te") << 7; + QTest::newRow("Delete end from first, no selection") + << QStringLiteral("Some Text") << 0 << 0 << 0 << QKeySequence::DeleteEndOfWord + << QStringLiteral("Text") << 0; + + QTest::newRow("Delete start, full selection") + << QStringLiteral("Some Text") << 0 << 9 << 0 << QKeySequence::DeleteStartOfWord + << QStringLiteral("") << 0; + QTest::newRow("Delete end, full selection") + << QStringLiteral("Some Text") << 0 << 9 << 0 << QKeySequence::DeleteEndOfWord + << QStringLiteral("") << 0; + QTest::newRow("Delete start, full selection, single word") + << QStringLiteral("Some") << 0 << 4 << 0 << QKeySequence::DeleteStartOfWord + << QStringLiteral("") << 0; + QTest::newRow("Delete end, full selection, single word") + << QStringLiteral("Some") << 0 << 4 << 0 << QKeySequence::DeleteEndOfWord + << QStringLiteral("") << 0; + + QTest::newRow("Delete start, word selection") + << QStringLiteral("Some Text") << 5 << 9 << 0 << QKeySequence::DeleteStartOfWord + << QStringLiteral("Some ") << 5; + QTest::newRow("Delete end, word selection") + << QStringLiteral("Some Text") << 5 << 9 << 0 << QKeySequence::DeleteEndOfWord + << QStringLiteral("Some ") << 5; + QTest::newRow("Delete start, partial word selection") + << QStringLiteral("Some Text") << 5 << 7 << 0 << QKeySequence::DeleteStartOfWord + << QStringLiteral("Some xt") << 5; + QTest::newRow("Delete end, partial word selection") + << QStringLiteral("Some Text") << 5 << 7 << 0 << QKeySequence::DeleteEndOfWord + << QStringLiteral("Some xt") << 5; + QTest::newRow("Delete start, partial inner word selection") + << QStringLiteral("Some Text") << 6 << 8 << 0 << QKeySequence::DeleteStartOfWord + << QStringLiteral("Some Tt") << 6; + QTest::newRow("Delete end, partial inner word selection") + << QStringLiteral("Some Text") << 6 << 8 << 0 << QKeySequence::DeleteEndOfWord + << QStringLiteral("Some Tt") << 6; + QTest::newRow("Delete start, selection with space") + << QStringLiteral("Some Text") << 3 << 9 << 0 << QKeySequence::DeleteStartOfWord + << QStringLiteral("Som") << 3; + QTest::newRow("Delete end, selection with space") + << QStringLiteral("Some Text") << 3 << 9 << 0 << QKeySequence::DeleteEndOfWord + << QStringLiteral("Som") << 3; + QTest::newRow("Delete start, partial word selection with space") + << QStringLiteral("Some Text") << 3 << 7 << 0 << QKeySequence::DeleteStartOfWord + << QStringLiteral("Somxt") << 3; + QTest::newRow("Delete end, partial selection with space") + << QStringLiteral("Some Text") << 3 << 7 << 0 << QKeySequence::DeleteEndOfWord + << QStringLiteral("Somxt") << 3; +} + +void tst_QLineEdit::deleteWordByKeySequence() +{ + QFETCH(QString, startText); + QFETCH(int, selectionStart); + QFETCH(int, selectionEnd); + QFETCH(int, cursorPosition); + QFETCH(QKeySequence::StandardKey, key); + QFETCH(QString, expectedText); + QFETCH(int, expectedCursorPosition); + + QWidget widget; + + QLineEdit *lineEdit = new QLineEdit(startText, &widget); + lineEdit->setFocus(); + lineEdit->setCursorPosition(cursorPosition); + if (selectionStart != selectionEnd) + lineEdit->setSelection(selectionStart, selectionEnd - selectionStart); + + widget.show(); + + QVERIFY(QTest::qWaitForWindowActive(&widget)); + + QTestEventList keys; + addKeySequenceStandardKey(keys, key); + keys.simulate(lineEdit); + + QCOMPARE(lineEdit->text(), expectedText); + QCOMPARE(lineEdit->selectionStart(), -1); + QCOMPARE(lineEdit->selectionEnd(), -1); + QCOMPARE(lineEdit->cursorPosition(), expectedCursorPosition); +} + +#endif // QT_CONFIG(shortcut) + QTEST_MAIN(tst_QLineEdit) #include "tst_qlineedit.moc" diff --git a/tests/auto/widgets/widgets/qmainwindow/BLACKLIST b/tests/auto/widgets/widgets/qmainwindow/BLACKLIST new file mode 100644 index 0000000000..28b08026d8 --- /dev/null +++ b/tests/auto/widgets/widgets/qmainwindow/BLACKLIST @@ -0,0 +1,2 @@ +[QTBUG52175_tabifiedDockWidgetActivated] +macos arm ci diff --git a/tests/auto/widgets/widgets/qmainwindow/CMakeLists.txt b/tests/auto/widgets/widgets/qmainwindow/CMakeLists.txt index 756905c9c5..93f94f78c7 100644 --- a/tests/auto/widgets/widgets/qmainwindow/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qmainwindow/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qmainwindow.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qmainwindow Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmainwindow LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qmainwindow SOURCES tst_qmainwindow.cpp diff --git a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp index 6996591946..093af90d1c 100644 --- a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp +++ b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -104,6 +104,7 @@ private slots: void restoreStateFromPreviousVersion(); void restoreStateSizeChanged_data(); void restoreStateSizeChanged(); + void restoreAndModify(); void createPopupMenu(); void hideBeforeLayout(); #ifdef QT_BUILD_INTERNAL @@ -1358,12 +1359,13 @@ void tst_QMainWindow::restoreState() //tests the restoration of the previous versions of window settings void tst_QMainWindow::restoreStateFromPreviousVersion() { - QList<QByteArray> restoreData; - restoreData << QByteArray((char*)restoreData41, sizeof(restoreData41)) - << QByteArray((char*)restoreData42, sizeof(restoreData42)) - << QByteArray((char*)restoreData43, sizeof(restoreData43)); + const QByteArray restoreData[] = { + QByteArray((char*)restoreData41, sizeof(restoreData41)), + QByteArray((char*)restoreData42, sizeof(restoreData42)), + QByteArray((char*)restoreData43, sizeof(restoreData43)), + }; - foreach(QByteArray ba, restoreData) { + for (const QByteArray &ba : restoreData) { QMainWindow win; win.setCentralWidget(new QTextEdit); @@ -1475,6 +1477,70 @@ void tst_QMainWindow::restoreStateSizeChanged() } } +/*! + If a main window's state is restored but also modified, then we + might have to forget the restored state to avoid dangling pointers. + See comment in QMainWindowLayout::applyRestoredState() and QTBUG-120025. +*/ +void tst_QMainWindow::restoreAndModify() +{ + class MainWindow : public QMainWindow + { + public: + MainWindow() + { + setCentralWidget(new QTextEdit); + + customers = new QDockWidget(tr("Customers"), this); + customers->setObjectName("Customers"); + customers->setAllowedAreas(Qt::LeftDockWidgetArea | + Qt::RightDockWidgetArea); + customers->setWidget(new QTextEdit); + addDockWidget(Qt::RightDockWidgetArea, customers); + + paragraphs = new QDockWidget(tr("Paragraphs"), this); + paragraphs->setObjectName("Paragraphs"); + paragraphs->setWidget(new QTextEdit); + addDockWidget(Qt::RightDockWidgetArea, paragraphs); + } + + void restore() + { + if (!savedGeometry.isEmpty()) + restoreGeometry(savedGeometry); + setWindowState(Qt::WindowMaximized); + if (!savedState.isEmpty()) + restoreState(savedState); + + tabifyDockWidget(customers, paragraphs); + } + protected: + void closeEvent(QCloseEvent *event) override + { + savedGeometry = saveGeometry(); + savedState = saveState(); + + return QMainWindow::closeEvent(event); + } + private: + QByteArray savedGeometry; + QByteArray savedState; + + QDockWidget *customers; + QDockWidget *paragraphs; + + } mainWindow; + + mainWindow.restore(); + mainWindow.show(); + QVERIFY(QTest::qWaitForWindowExposed(&mainWindow)); + mainWindow.close(); + + mainWindow.restore(); + mainWindow.show(); + QVERIFY(QTest::qWaitForWindowExposed(&mainWindow)); +} + void tst_QMainWindow::createPopupMenu() { { @@ -1671,25 +1737,25 @@ void MoveSeparator::apply(QMainWindow *mw) const QMap<QString, QRect> dockWidgetGeometries(QMainWindow *mw) { QMap<QString, QRect> result; - QList<QDockWidget*> dockWidgets = mw->findChildren<QDockWidget*>(); - foreach (QDockWidget *dw, dockWidgets) + const QList<QDockWidget*> dockWidgets = mw->findChildren<QDockWidget*>(); + for (QDockWidget *dw : dockWidgets) result.insert(dw->objectName(), dw->geometry()); return result; } #define COMPARE_DOCK_WIDGET_GEOS(_oldGeos, _newGeos) \ { \ - QMap<QString, QRect> __oldGeos = _oldGeos; \ - QMap<QString, QRect> __newGeos = _newGeos; \ - QCOMPARE(__newGeos.keys(), __oldGeos.keys()); \ - QStringList __keys = __newGeos.keys(); \ - foreach (const QString &key, __keys) { \ - QRect __r1 = __oldGeos[key]; \ - QRect __r2 = __newGeos[key]; \ - if (__r1 != __r2) \ - qWarning() << key << __r1 << __r2; \ + QMap<QString, QRect> _v_oldGeos = _oldGeos; \ + QMap<QString, QRect> _v_newGeos = _newGeos; \ + QCOMPARE(_v_newGeos.keys(), _v_oldGeos.keys()); \ + const QStringList _v_keys = _v_newGeos.keys(); \ + for (const QString &key : _v_keys) { \ + QRect _v_r1 = _v_oldGeos[key]; \ + QRect _v_r2 = _v_newGeos[key]; \ + if (_v_r1 != _v_r2) \ + qWarning() << key << _v_r1 << _v_r2; \ } \ - QCOMPARE(__newGeos, __oldGeos); \ + QCOMPARE(_v_newGeos, _v_oldGeos); \ } #ifdef QT_BUILD_INTERNAL @@ -1735,8 +1801,8 @@ void tst_QMainWindow::saveRestore_data() #ifdef QT_BUILD_INTERNAL void tst_QMainWindow::saveRestore() { - QFETCH(AddList, addList); - QFETCH(MoveList, moveList); + QFETCH(const AddList, addList); + QFETCH(const MoveList, moveList); QByteArray stateData; QMap<QString, QRect> dockWidgetGeos; @@ -1748,12 +1814,12 @@ void tst_QMainWindow::saveRestore() QTextEdit centralWidget("The rain in Spain falls mainly on the plains"); mainWindow.setCentralWidget(¢ralWidget); - foreach (const AddDockWidget &adw, addList) + for (const AddDockWidget &adw : addList) adw.apply(&mainWindow); mainWindow.show(); - foreach (const MoveSeparator &ms, moveList) + for (const MoveSeparator &ms : moveList) ms.apply(&mainWindow); dockWidgetGeos = dockWidgetGeometries(&mainWindow); @@ -1771,7 +1837,7 @@ void tst_QMainWindow::saveRestore() QTextEdit centralWidget("The rain in Spain falls mainly on the plains"); mainWindow.setCentralWidget(¢ralWidget); - foreach (const AddDockWidget &adw, addList) + for (const AddDockWidget &adw : addList) adw.apply(&mainWindow); mainWindow.show(); @@ -1788,7 +1854,7 @@ void tst_QMainWindow::saveRestore() QTextEdit centralWidget("The rain in Spain falls mainly on the plains"); mainWindow.setCentralWidget(¢ralWidget); - foreach (const AddDockWidget &adw, addList) + for (const AddDockWidget &adw : addList) adw.apply(&mainWindow); mainWindow.resize(size); mainWindow.restoreState(stateData); @@ -1864,7 +1930,7 @@ void tst_QMainWindow::addToolbarAfterShow() void tst_QMainWindow::centralWidgetSize() { if (qGuiApp->styleHints()->showIsFullScreen()) - QSKIP("The platform is auto maximizing, so the test makes no sense");; + QSKIP("The platform is auto maximizing, so the test makes no sense"); QMainWindow mainWindow; mainWindow.menuBar()->addMenu("menu"); @@ -2096,10 +2162,11 @@ void tst_QMainWindow::resizeDocks() mw.setDockNestingEnabled(true); mw.resize(1800, 600); - foreach (const AddDockWidget &i, addList) + for (const AddDockWidget &i : std::as_const(addList)) i.apply(&mw); - foreach (QDockWidget *dw, mw.findChildren<QDockWidget *>()) + const auto dockWidgets = mw.findChildren<QDockWidget *>(); + for (QDockWidget *dw : dockWidgets) dw->setStyleSheet( "* { background-color: " + dw->objectName() +" }"); mw.setCentralWidget(new QTextEdit); @@ -2108,11 +2175,11 @@ void tst_QMainWindow::resizeDocks() QVERIFY(QTest::qWaitForWindowExposed(&mw)); QFETCH(Qt::Orientation, orientation); - QFETCH(QStringList, docks); + QFETCH(const QStringList, docks); QFETCH(QList<int>, sizes); QList<QDockWidget *> list; - foreach (const QString &name, docks) { + for (const QString &name : docks) { QDockWidget *d = mw.findChild<QDockWidget *>(name); QVERIFY(d); list << d; @@ -2124,14 +2191,14 @@ void tst_QMainWindow::resizeDocks() int totalFromList = 0; int actualTotal = 0; - for (int i = 0; i < docks.count(); ++i) { + for (int i = 0; i < docks.size(); ++i) { totalFromList += sizes[i]; QSize s = list[i]->size(); actualTotal += (orientation == Qt::Horizontal) ? s.width() : s.height(); // qDebug() << list[i] << list[i]->size() << sizes[i]; } - for (int i = 0; i < docks.count(); ++i) { + for (int i = 0; i < docks.size(); ++i) { QSize s = list[i]->size(); int value = (orientation == Qt::Horizontal) ? s.width() : s.height(); QCOMPARE(value, qRound(sizes[i]*actualTotal/double(totalFromList))); diff --git a/tests/auto/widgets/widgets/qmdiarea/BLACKLIST b/tests/auto/widgets/widgets/qmdiarea/BLACKLIST index 3091b73269..c3234bf56c 100644 --- a/tests/auto/widgets/widgets/qmdiarea/BLACKLIST +++ b/tests/auto/widgets/widgets/qmdiarea/BLACKLIST @@ -1,15 +1,7 @@ [tileSubWindows] -ubuntu-16.04 -rhel-7.6 centos opensuse-leap macos -ubuntu-18.04 -ubuntu-20.04 -macos -rhel-7.4 -macos -opensuse-42.3 [resizeTimer] macos diff --git a/tests/auto/widgets/widgets/qmdiarea/CMakeLists.txt b/tests/auto/widgets/widgets/qmdiarea/CMakeLists.txt index c42960b0b5..5f61dc8664 100644 --- a/tests/auto/widgets/widgets/qmdiarea/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qmdiarea/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qmdiarea.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qmdiarea Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmdiarea LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qmdiarea SOURCES tst_qmdiarea.cpp @@ -17,6 +21,7 @@ qt_internal_add_test(tst_qmdiarea Qt::Gui Qt::GuiPrivate Qt::Widgets + Qt::WidgetsPrivate ) ## Scopes: diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp index 1d76bb4d72..ef00dcaac0 100644 --- a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp +++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -24,6 +24,8 @@ #endif #include <QStyleHints> +#include <QtWidgets/private/qapplication_p.h> + static const Qt::WindowFlags DefaultWindowFlags = Qt::SubWindow | Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint; @@ -138,7 +140,7 @@ static bool verifyArrangement(QMdiArea *mdiArea, Arrangement arrangement, const case Tiled: { // Calculate the number of rows and columns. - const int n = subWindows.count(); + const int n = subWindows.size(); const int numColumns = qMax(qCeil(qSqrt(qreal(n))), 1); const int numRows = qMax((n % numColumns) ? (n / numColumns + 1) : (n / numColumns), 1); @@ -174,7 +176,7 @@ static bool verifyArrangement(QMdiArea *mdiArea, Arrangement arrangement, const // QWidget::childAt with the position of the first one and subsequently adding // dx and dy. QPoint subWindowPos(20, 5); - foreach (int expectedIndex, expectedIndices) { + for (int expectedIndex : expectedIndices) { QMdiSubWindow *expected = subWindows.at(expectedIndex); expected->raise(); if (mdiArea->viewport()->childAt(subWindowPos) != expected) @@ -185,7 +187,7 @@ static bool verifyArrangement(QMdiArea *mdiArea, Arrangement arrangement, const } // Restore stacking order. - foreach (QMdiSubWindow *subWindow, activationOrderList) { + for (QMdiSubWindow *subWindow : activationOrderList) { mdiArea->setActiveSubWindow(subWindow); qApp->processEvents(); } @@ -258,6 +260,7 @@ private slots: void task_236750(); void qtbug92240_title_data(); void qtbug92240_title(); + void tabbedview_singleSubWindow(); void tabbedview_activefirst(); void tabbedview_activesecond(); void tabbedview_activethird(); @@ -304,7 +307,7 @@ void tst_QMdiArea::subWindowActivated() QSignalSpy spy(workspace, SIGNAL(subWindowActivated(QMdiSubWindow*))); connect( workspace, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(activeChanged(QMdiSubWindow*))); mw.show(); - qApp->setActiveWindow(&mw); + QApplicationPrivate::setActiveWindow(&mw); QFETCH( int, count ); int i; @@ -317,12 +320,12 @@ void tst_QMdiArea::subWindowActivated() widget->show(); qApp->processEvents(); QVERIFY( activeWindow == workspace->activeSubWindow() ); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); } QList<QMdiSubWindow *> windows = workspace->subWindowList(); - QCOMPARE( (int)windows.count(), count ); + QCOMPARE( (int)windows.size(), count ); for ( i = 0; i < count; ++i ) { QMdiSubWindow *window = windows.at(i); @@ -346,13 +349,13 @@ void tst_QMdiArea::subWindowActivated() workspace->activeSubWindow()->close(); qApp->processEvents(); QCOMPARE(activeWindow, workspace->activeSubWindow()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); } QVERIFY(!activeWindow); QVERIFY(!workspace->activeSubWindow()); - QCOMPARE(workspace->subWindowList().count(), 0); + QCOMPARE(workspace->subWindowList().size(), 0); { workspace->hide(); @@ -360,14 +363,14 @@ void tst_QMdiArea::subWindowActivated() widget->setAttribute(Qt::WA_DeleteOnClose); QMdiSubWindow *window = workspace->addSubWindow(widget); widget->show(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); workspace->show(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); QVERIFY( activeWindow == window ); window->close(); qApp->processEvents(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); QVERIFY( activeWindow == 0 ); } @@ -379,15 +382,15 @@ void tst_QMdiArea::subWindowActivated() QMdiSubWindow *window = workspace->addSubWindow(widget); widget->showMaximized(); qApp->sendPostedEvents(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); workspace->show(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); QVERIFY( activeWindow == window ); window->close(); qApp->processEvents(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); QVERIFY( activeWindow == 0 ); } @@ -397,13 +400,13 @@ void tst_QMdiArea::subWindowActivated() widget->setAttribute(Qt::WA_DeleteOnClose); QMdiSubWindow *window = workspace->addSubWindow(widget); widget->showMinimized(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); QVERIFY( activeWindow == window ); QCOMPARE(workspace->activeSubWindow(), window); window->close(); qApp->processEvents(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); QVERIFY(!workspace->activeSubWindow()); QVERIFY(!activeWindow); @@ -431,12 +434,12 @@ void tst_QMdiArea::subWindowActivated2() QSignalSpy spy(&mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*))); for (int i = 0; i < 5; ++i) mdiArea.addSubWindow(new QWidget); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); mdiArea.show(); mdiArea.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&mdiArea)); - QTRY_COMPARE(spy.count(), 5); + QTRY_COMPARE(spy.size(), 5); QCOMPARE(mdiArea.activeSubWindow(), mdiArea.subWindowList().back()); spy.clear(); @@ -445,13 +448,13 @@ void tst_QMdiArea::subWindowActivated2() QMdiSubWindow *staysOnTopWindow = mdiArea.subWindowList().at(3); staysOnTopWindow->setWindowFlags(Qt::WindowStaysOnTopHint); mdiArea.setActiveSubWindow(staysOnTopWindow); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(mdiArea.activeSubWindow(), staysOnTopWindow); spy.clear(); QMdiSubWindow *activeSubWindow = mdiArea.subWindowList().at(2); mdiArea.setActiveSubWindow(activeSubWindow); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow); spy.clear(); @@ -459,7 +462,7 @@ void tst_QMdiArea::subWindowActivated2() // is unchanged after hide/show. mdiArea.hide(); QTest::qWait(100); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); QVERIFY(!mdiArea.activeSubWindow()); QCOMPARE(mdiArea.currentSubWindow(), activeSubWindow); spy.clear(); @@ -487,7 +490,7 @@ void tst_QMdiArea::subWindowActivated2() #endif if (!QGuiApplication::platformName().compare(QLatin1String("xcb"), Qt::CaseInsensitive)) QSKIP("QTBUG-25298: Unstable on some X11 window managers"); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); QVERIFY(!mdiArea.activeSubWindow()); QCOMPARE(mdiArea.currentSubWindow(), activeSubWindow); spy.clear(); @@ -497,7 +500,7 @@ void tst_QMdiArea::subWindowActivated2() mdiArea.showNormal(); mdiArea.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&mdiArea)); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow); spy.clear(); } @@ -512,7 +515,6 @@ void tst_QMdiArea::subWindowActivatedWithMinimize() QSignalSpy spy(workspace, SIGNAL(subWindowActivated(QMdiSubWindow*))); connect( workspace, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(activeChanged(QMdiSubWindow*)) ); mw.show(); - qApp->setActiveWindow(&mw); QWidget *widget = new QWidget(workspace); widget->setAttribute(Qt::WA_DeleteOnClose); QMdiSubWindow *window1 = workspace->addSubWindow(widget); @@ -534,7 +536,7 @@ void tst_QMdiArea::subWindowActivatedWithMinimize() QVERIFY(!workspace->activeSubWindow()); QVERIFY(!activeWindow); - QVERIFY( workspace->subWindowList().count() == 0 ); + QVERIFY( workspace->subWindowList().size() == 0 ); } void tst_QMdiArea::showWindows() @@ -657,7 +659,6 @@ void tst_QMdiArea::changeWindowTitle() #endif mw->show(); - qApp->setActiveWindow(mw); #ifdef USE_SHOW mw->showFullScreen(); @@ -813,14 +814,14 @@ void tst_QMdiArea::fixedSize() } QList<QMdiSubWindow *> windows = ws->subWindowList(); - for (i = 0; i < (int)windows.count(); ++i) { + for (i = 0; i < (int)windows.size(); ++i) { QMdiSubWindow *child = windows.at(i); QCOMPARE(child->size(), fixed); } ws->cascadeSubWindows(); ws->resize(800, 800); - for (i = 0; i < (int)windows.count(); ++i) { + for (i = 0; i < (int)windows.size(); ++i) { QMdiSubWindow *child = windows.at(i); QCOMPARE(child->size(), fixed); } @@ -828,13 +829,13 @@ void tst_QMdiArea::fixedSize() ws->tileSubWindows(); ws->resize(800, 800); - for (i = 0; i < (int)windows.count(); ++i) { + for (i = 0; i < (int)windows.size(); ++i) { QMdiSubWindow *child = windows.at(i); QCOMPARE(child->size(), fixed); } ws->resize(500, 500); - for (i = 0; i < (int)windows.count(); ++i) { + for (i = 0; i < (int)windows.size(); ++i) { QMdiSubWindow *child = windows.at(i); delete child; } @@ -902,7 +903,7 @@ void tst_QMdiArea::setActiveSubWindow() QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow*))); connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(activeChanged(QMdiSubWindow*))); - qApp->setActiveWindow(&workspace); + QApplicationPrivate::setActiveWindow(&workspace); // Activate hidden windows const int windowCount = 10; @@ -913,7 +914,7 @@ void tst_QMdiArea::setActiveSubWindow() QVERIFY(windows[i]->isHidden()); workspace.setActiveSubWindow(windows[i]); } - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QVERIFY(!activeWindow); spy.clear(); @@ -923,7 +924,7 @@ void tst_QMdiArea::setActiveSubWindow() QVERIFY(!windows[i]->isHidden()); workspace.setActiveSubWindow(windows[i]); qApp->processEvents(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(activeWindow, windows[i]); spy.clear(); } @@ -931,7 +932,7 @@ void tst_QMdiArea::setActiveSubWindow() // Deactivate active window QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]); workspace.setActiveSubWindow(0); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QVERIFY(!activeWindow); QVERIFY(!workspace.activeSubWindow()); @@ -961,7 +962,6 @@ void tst_QMdiArea::activeSubWindow() mainWindow.addDockWidget(Qt::LeftDockWidgetArea, dockWidget); mainWindow.show(); - qApp->setActiveWindow(&mainWindow); QVERIFY(QTest::qWaitForWindowActive(&mainWindow)); QCOMPARE(mdiArea->activeSubWindow(), subWindow); QCOMPARE(qApp->focusWidget(), (QWidget *)subWindowLineEdit); @@ -984,15 +984,13 @@ void tst_QMdiArea::activeSubWindow() dummyTopLevel.show(); QVERIFY(QTest::qWaitForWindowExposed(&dummyTopLevel)); - qApp->setActiveWindow(&dummyTopLevel); QCOMPARE(mdiArea->activeSubWindow(), subWindow); - qApp->setActiveWindow(&mainWindow); QCOMPARE(mdiArea->activeSubWindow(), subWindow); //task 202657 dockWidgetLineEdit->setFocus(); - qApp->setActiveWindow(&mainWindow); + QApplicationPrivate::setActiveWindow(&mainWindow); QVERIFY(dockWidgetLineEdit->hasFocus()); } @@ -1005,7 +1003,7 @@ void tst_QMdiArea::currentSubWindow() for (int i = 0; i < 5; ++i) mdiArea.addSubWindow(new QLineEdit)->show(); - qApp->setActiveWindow(&mdiArea); + QApplicationPrivate::setActiveWindow(&mdiArea); QCOMPARE(qApp->activeWindow(), (QWidget *)&mdiArea); // Check that the last added window is the active and the current. @@ -1020,7 +1018,6 @@ void tst_QMdiArea::currentSubWindow() // Move focus to another top-level and check that we still // have an active window. - qApp->setActiveWindow(&dummyTopLevel); QCOMPARE(qApp->activeWindow(), (QWidget *)&dummyTopLevel); QVERIFY(mdiArea.activeSubWindow()); @@ -1033,7 +1030,7 @@ void tst_QMdiArea::currentSubWindow() QCOMPARE(mdiArea.currentSubWindow(), mdiArea.subWindowList().front()); // Activate mdi area and check that active == current. - qApp->setActiveWindow(&mdiArea); + QApplicationPrivate::setActiveWindow(&mdiArea); active = mdiArea.activeSubWindow(); QVERIFY(active); QCOMPARE(mdiArea.activeSubWindow(), mdiArea.subWindowList().front()); @@ -1042,11 +1039,9 @@ void tst_QMdiArea::currentSubWindow() QCOMPARE(mdiArea.activeSubWindow(), active); QCOMPARE(mdiArea.currentSubWindow(), active); - qApp->setActiveWindow(&dummyTopLevel); QVERIFY(mdiArea.activeSubWindow()); QCOMPARE(mdiArea.currentSubWindow(), active); - qApp->setActiveWindow(&mdiArea); active->show(); QCOMPARE(mdiArea.activeSubWindow(), active); @@ -1076,11 +1071,11 @@ void tst_QMdiArea::addAndRemoveWindows() QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); { // addSubWindow with large widget - QCOMPARE(workspace.subWindowList().count(), 0); + QCOMPARE(workspace.subWindowList().size(), 0); QWidget *window = workspace.addSubWindow(new LargeWidget); QVERIFY(window); qApp->processEvents(); - QCOMPARE(workspace.subWindowList().count(), 1); + QCOMPARE(workspace.subWindowList().size(), 1); QCOMPARE(window->windowFlags(), DefaultWindowFlags); QCOMPARE(window->size(), workspace.viewport()->size()); } @@ -1091,7 +1086,7 @@ void tst_QMdiArea::addAndRemoveWindows() workspace.addSubWindow(window); QVERIFY(window); qApp->processEvents(); - QCOMPARE(workspace.subWindowList().count(), 2); + QCOMPARE(workspace.subWindowList().size(), 2); QCOMPARE(window->windowFlags(), DefaultWindowFlags); QCOMPARE(window->size(), window->minimumSize()); } @@ -1103,7 +1098,7 @@ void tst_QMdiArea::addAndRemoveWindows() workspace.addSubWindow(window); QVERIFY(window); qApp->processEvents(); - QCOMPARE(workspace.subWindowList().count(), 3); + QCOMPARE(workspace.subWindowList().size(), 3); QCOMPARE(window->windowFlags(), DefaultWindowFlags); QCOMPARE(window->size(), QSize(1500, 1500)); } @@ -1112,7 +1107,7 @@ void tst_QMdiArea::addAndRemoveWindows() QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: null pointer to widget"); QWidget *window = workspace.addSubWindow(0); QVERIFY(!window); - QCOMPARE(workspace.subWindowList().count(), 3); + QCOMPARE(workspace.subWindowList().size(), 3); } { // addChildWindow @@ -1121,7 +1116,7 @@ void tst_QMdiArea::addAndRemoveWindows() qApp->processEvents(); QCOMPARE(window->windowFlags(), DefaultWindowFlags); window->setWidget(new QWidget); - QCOMPARE(workspace.subWindowList().count(), 4); + QCOMPARE(workspace.subWindowList().size(), 4); QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: window is already added"); workspace.addSubWindow(window); } @@ -1129,15 +1124,16 @@ void tst_QMdiArea::addAndRemoveWindows() { // addChildWindow with 0 pointer QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: null pointer to widget"); workspace.addSubWindow(0); - QCOMPARE(workspace.subWindowList().count(), 4); + QCOMPARE(workspace.subWindowList().size(), 4); } // removeSubWindow - foreach (QWidget *window, workspace.subWindowList()) { + const auto subWindows = workspace.subWindowList(); + for (QWidget *window : subWindows) { workspace.removeSubWindow(window); delete window; } - QCOMPARE(workspace.subWindowList().count(), 0); + QCOMPARE(workspace.subWindowList().size(), 0); // removeSubWindow with 0 pointer QTest::ignoreMessage(QtWarningMsg, "QMdiArea::removeSubWindow: null pointer to widget"); @@ -1145,7 +1141,7 @@ void tst_QMdiArea::addAndRemoveWindows() workspace.addSubWindow(new QPushButton(QLatin1String("Dummy to make workspace non-empty"))); qApp->processEvents(); - QCOMPARE(workspace.subWindowList().count(), 1); + QCOMPARE(workspace.subWindowList().size(), 1); // removeSubWindow with window not inside workspace QTest::ignoreMessage(QtWarningMsg,"QMdiArea::removeSubWindow: window is not inside workspace"); @@ -1187,20 +1183,20 @@ void tst_QMdiArea::addAndRemoveWindowsWithReparenting() // 0 because the window list contains widgets and not actual // windows. Silly, but that's the behavior. - QCOMPARE(workspace.subWindowList().count(), 0); + QCOMPARE(workspace.subWindowList().size(), 0); window.setWidget(new QWidget); qApp->processEvents(); - QCOMPARE(workspace.subWindowList().count(), 1); + QCOMPARE(workspace.subWindowList().size(), 1); window.setParent(0); // Will also reset window flags - QCOMPARE(workspace.subWindowList().count(), 0); + QCOMPARE(workspace.subWindowList().size(), 0); window.setParent(&workspace); - QCOMPARE(workspace.subWindowList().count(), 1); + QCOMPARE(workspace.subWindowList().size(), 1); QCOMPARE(window.windowFlags(), DefaultWindowFlags); QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: window is already added"); workspace.addSubWindow(&window); - QCOMPARE(workspace.subWindowList().count(), 1); + QCOMPARE(workspace.subWindowList().size(), 1); } class MySubWindow : public QMdiSubWindow @@ -1251,23 +1247,22 @@ void tst_QMdiArea::closeWindows() { QMdiArea workspace; workspace.show(); - qApp->setActiveWindow(&workspace); // Close widget QWidget *widget = new QWidget; QMdiSubWindow *subWindow = workspace.addSubWindow(widget); qApp->processEvents(); - QCOMPARE(workspace.subWindowList().count(), 1); + QCOMPARE(workspace.subWindowList().size(), 1); subWindow->close(); - QCOMPARE(workspace.subWindowList().count(), 0); + QCOMPARE(workspace.subWindowList().size(), 0); // Close window QWidget *window = workspace.addSubWindow(new QWidget); qApp->processEvents(); - QCOMPARE(workspace.subWindowList().count(), 1); + QCOMPARE(workspace.subWindowList().size(), 1); window->close(); qApp->processEvents(); - QCOMPARE(workspace.subWindowList().count(), 0); + QCOMPARE(workspace.subWindowList().size(), 0); const int windowCount = 10; @@ -1275,7 +1270,7 @@ void tst_QMdiArea::closeWindows() for (int i = 0; i < windowCount; ++i) workspace.addSubWindow(new QWidget)->show(); qApp->processEvents(); - QCOMPARE(workspace.subWindowList().count(), windowCount); + QCOMPARE(workspace.subWindowList().size(), windowCount); int activeSubWindowCount = 0; while (workspace.activeSubWindow()) { workspace.activeSubWindow()->close(); @@ -1283,19 +1278,19 @@ void tst_QMdiArea::closeWindows() ++activeSubWindowCount; } QCOMPARE(activeSubWindowCount, windowCount); - QCOMPARE(workspace.subWindowList().count(), 0); + QCOMPARE(workspace.subWindowList().size(), 0); // Close all windows for (int i = 0; i < windowCount; ++i) workspace.addSubWindow(new QWidget)->show(); qApp->processEvents(); - QCOMPARE(workspace.subWindowList().count(), windowCount); + QCOMPARE(workspace.subWindowList().size(), windowCount); QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow*))); connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(activeChanged(QMdiSubWindow*))); workspace.closeAllSubWindows(); qApp->processEvents(); - QCOMPARE(workspace.subWindowList().count(), 0); - QCOMPARE(spy.count(), 1); + QCOMPARE(workspace.subWindowList().size(), 0); + QCOMPARE(spy.size(), 1); QVERIFY(!activeWindow); } @@ -1303,7 +1298,6 @@ void tst_QMdiArea::activateNextAndPreviousWindow() { QMdiArea workspace; workspace.show(); - qApp->setActiveWindow(&workspace); const int windowCount = 10; QMdiSubWindow *windows[windowCount]; @@ -1321,7 +1315,7 @@ void tst_QMdiArea::activateNextAndPreviousWindow() workspace.activateNextSubWindow(); qApp->processEvents(); QCOMPARE(workspace.activeSubWindow(), windows[i]); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); } QVERIFY(activeWindow); @@ -1333,7 +1327,7 @@ void tst_QMdiArea::activateNextAndPreviousWindow() workspace.activatePreviousSubWindow(); qApp->processEvents(); QCOMPARE(workspace.activeSubWindow(), windows[i]); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); if (i % 2 == 0) windows[i]->hide(); // 10, 8, 6, 4, 2, 0 @@ -1345,7 +1339,7 @@ void tst_QMdiArea::activateNextAndPreviousWindow() // activateNextSubWindow with every 2nd window hidden for (int i = 0; i < windowCount / 2; ++i) { workspace.activateNextSubWindow(); // 1, 3, 5, 7, 9 - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); } QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]); @@ -1353,7 +1347,7 @@ void tst_QMdiArea::activateNextAndPreviousWindow() // activatePreviousSubWindow with every 2nd window hidden for (int i = 0; i < windowCount / 2; ++i) { workspace.activatePreviousSubWindow(); // 7, 5, 3, 1, 9 - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); } QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]); @@ -1387,7 +1381,6 @@ void tst_QMdiArea::subWindowList() QMdiArea workspace; workspace.show(); - qApp->setActiveWindow(&workspace); QVERIFY(QTest::qWaitForWindowActive(&workspace)); QList<QMdiSubWindow *> activationOrder; @@ -1400,8 +1393,8 @@ void tst_QMdiArea::subWindowList() { QList<QMdiSubWindow *> widgets = workspace.subWindowList(windowOrder); - QCOMPARE(widgets.count(), windowCount); - for (int i = 0; i < widgets.count(); ++i) + QCOMPARE(widgets.size(), windowCount); + for (int i = 0; i < widgets.size(); ++i) QCOMPARE(widgets.at(i), windows[i]); } @@ -1420,9 +1413,9 @@ void tst_QMdiArea::subWindowList() } if (windowOrder == QMdiArea::StackingOrder) { - QCOMPARE(subWindows.at(subWindows.count() - 1), windows[staysOnTop1]); - QCOMPARE(subWindows.at(subWindows.count() - 2), windows[activeSubWindow]); - QCOMPARE(subWindows.count(), windowCount); + QCOMPARE(subWindows.at(subWindows.size() - 1), windows[staysOnTop1]); + QCOMPARE(subWindows.at(subWindows.size() - 2), windows[activeSubWindow]); + QCOMPARE(subWindows.size(), windowCount); } else { // ActivationHistoryOrder QCOMPARE(subWindows, activationOrder); } @@ -1437,11 +1430,11 @@ void tst_QMdiArea::subWindowList() activationOrder.move(activationOrder.indexOf(windows[activeSubWindow]), windowCount - 1); QList<QMdiSubWindow *> widgets = workspace.subWindowList(windowOrder); - QCOMPARE(widgets.count(), windowCount); + QCOMPARE(widgets.size(), windowCount); if (windowOrder == QMdiArea::StackingOrder) { - QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop2]); - QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]); - QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]); + QCOMPARE(widgets.at(widgets.size() - 1), windows[staysOnTop2]); + QCOMPARE(widgets.at(widgets.size() - 2), windows[staysOnTop1]); + QCOMPARE(widgets.at(widgets.size() - 3), windows[activeSubWindow]); } else { // ActivationHistory QCOMPARE(widgets, activationOrder); } @@ -1451,8 +1444,8 @@ void tst_QMdiArea::subWindowList() widgets = workspace.subWindowList(windowOrder); if (windowOrder == QMdiArea::StackingOrder) { - QCOMPARE(widgets.at(widgets.count() - 1), windows[activeSubWindow]); - QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]); + QCOMPARE(widgets.at(widgets.size() - 1), windows[activeSubWindow]); + QCOMPARE(widgets.at(widgets.size() - 2), windows[staysOnTop1]); QCOMPARE(widgets.at(0), windows[staysOnTop2]); } else { // ActivationHistoryOrder QCOMPARE(widgets, activationOrder); @@ -1463,9 +1456,9 @@ void tst_QMdiArea::subWindowList() widgets = workspace.subWindowList(windowOrder); if (windowOrder == QMdiArea::StackingOrder) { - QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop2]); - QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]); - QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]); + QCOMPARE(widgets.at(widgets.size() - 1), windows[staysOnTop2]); + QCOMPARE(widgets.at(widgets.size() - 2), windows[staysOnTop1]); + QCOMPARE(widgets.at(widgets.size() - 3), windows[activeSubWindow]); } else { // ActivationHistoryOrder QCOMPARE(widgets, activationOrder); } @@ -1475,9 +1468,9 @@ void tst_QMdiArea::subWindowList() widgets = workspace.subWindowList(windowOrder); if (windowOrder == QMdiArea::StackingOrder) { - QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop1]); - QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop2]); - QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]); + QCOMPARE(widgets.at(widgets.size() - 1), windows[staysOnTop1]); + QCOMPARE(widgets.at(widgets.size() - 2), windows[staysOnTop2]); + QCOMPARE(widgets.at(widgets.size() - 3), windows[activeSubWindow]); } else { // ActivationHistoryOrder QCOMPARE(widgets, activationOrder); } @@ -1518,14 +1511,14 @@ void tst_QMdiArea::setViewport() qApp->processEvents(); QList<QMdiSubWindow *> windowsBeforeViewportChange = workspace.subWindowList(); - QCOMPARE(windowsBeforeViewportChange.count(), windowCount); + QCOMPARE(windowsBeforeViewportChange.size(), windowCount); workspace.setViewport(new QWidget); qApp->processEvents(); QVERIFY(workspace.viewport() != firstViewport); QList<QMdiSubWindow *> windowsAfterViewportChange = workspace.subWindowList(); - QCOMPARE(windowsAfterViewportChange.count(), windowCount); + QCOMPARE(windowsAfterViewportChange.size(), windowCount); QCOMPARE(windowsAfterViewportChange, windowsBeforeViewportChange); // for (int i = 0; i < windowCount; ++i) { @@ -1541,7 +1534,7 @@ void tst_QMdiArea::setViewport() delete workspace.viewport(); qApp->processEvents(); - QCOMPARE(workspace.subWindowList().count(), 0); + QCOMPARE(workspace.subWindowList().size(), 0); QVERIFY(!workspace.activeSubWindow()); } @@ -1683,7 +1676,8 @@ void tst_QMdiArea::tileSubWindows() QTRY_COMPARE(workspace.size(), QSize(350, 150)); const QSize minSize(600, 130); - foreach (QMdiSubWindow *subWindow, workspace.subWindowList()) + const auto subWindows = workspace.subWindowList(); + for (QMdiSubWindow *subWindow : subWindows) subWindow->setMinimumSize(minSize); QCOMPARE(workspace.size(), QSize(350, 150)); @@ -1781,7 +1775,7 @@ void tst_QMdiArea::cascadeAndTileSubWindows() #endif QCOMPARE(windows.at(2)->geometry().top() - windows.at(1)->geometry().top(), dy); - for (int i = 0; i < windows.count(); ++i) { + for (int i = 0; i < windows.size(); ++i) { QMdiSubWindow *window = windows.at(i); if (i % 3 == 0) { QVERIFY(window->isMinimized()); @@ -1841,7 +1835,7 @@ void tst_QMdiArea::resizeMaximizedChildWindows() int newSize = startSize + increment * windowCount; QCOMPARE(workspaceSize, QSize(newSize, newSize)); - foreach (QWidget *window, windows) + for (QWidget *window : std::as_const(windows)) QCOMPARE(window->rect(), workspace.contentsRect()); } @@ -1866,7 +1860,7 @@ void tst_QMdiArea::focusWidgetAfterAddSubWindow() mdiArea.show(); view->show(); - qApp->setActiveWindow(&mdiArea); + QApplicationPrivate::setActiveWindow(&mdiArea); QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(lineEdit2)); } @@ -1875,7 +1869,6 @@ void tst_QMdiArea::dontMaximizeSubWindowOnActivation() QMdiArea mdiArea; mdiArea.show(); QVERIFY(QTest::qWaitForWindowExposed(&mdiArea)); - qApp->setActiveWindow(&mdiArea); // Add one maximized window. mdiArea.addSubWindow(new QWidget)->showMaximized(); @@ -1891,8 +1884,8 @@ void tst_QMdiArea::dontMaximizeSubWindowOnActivation() } // Verify that activated windows still are maximized on activation. - QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList(); - for (int i = 0; i < subWindows.count(); ++i) { + const QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList(); + for (int i = 0; i < subWindows.size(); ++i) { mdiArea.activateNextSubWindow(); QMdiSubWindow *window = subWindows.at(i); QCOMPARE(mdiArea.activeSubWindow(), window); @@ -1903,7 +1896,7 @@ void tst_QMdiArea::dontMaximizeSubWindowOnActivation() // Restore active window and verify that other windows aren't // maximized on activation. mdiArea.activeSubWindow()->showNormal(); - for (int i = 0; i < subWindows.count(); ++i) { + for (int i = 0; i < subWindows.size(); ++i) { mdiArea.activateNextSubWindow(); QMdiSubWindow *window = subWindows.at(i); QCOMPARE(mdiArea.activeSubWindow(), window); @@ -1917,7 +1910,7 @@ void tst_QMdiArea::dontMaximizeSubWindowOnActivation() int indexOfMaximized = subWindows.indexOf(mdiArea.activeSubWindow()); // Verify that windows are not maximized on activation. - for (int i = 0; i < subWindows.count(); ++i) { + for (int i = 0; i < subWindows.size(); ++i) { mdiArea.activateNextSubWindow(); QMdiSubWindow *window = subWindows.at(i); QCOMPARE(mdiArea.activeSubWindow(), window); @@ -1928,7 +1921,7 @@ void tst_QMdiArea::dontMaximizeSubWindowOnActivation() QVERIFY(mdiArea.activeSubWindow()->isMaximized()); // Minimize all windows. - foreach (QMdiSubWindow *window, subWindows) { + for (QMdiSubWindow *window : subWindows) { window->showMinimized(); QVERIFY(window->isMinimized()); qApp->processEvents(); @@ -1939,7 +1932,7 @@ void tst_QMdiArea::dontMaximizeSubWindowOnActivation() mdiArea.activeSubWindow()->showMaximized(); // Verify that minimized windows are maximized on activation. - for (int i = 0; i < subWindows.count(); ++i) { + for (int i = 0; i < subWindows.size(); ++i) { mdiArea.activateNextSubWindow(); QMdiSubWindow *window = subWindows.at(i); QCOMPARE(mdiArea.activeSubWindow(), window); @@ -1949,7 +1942,7 @@ void tst_QMdiArea::dontMaximizeSubWindowOnActivation() // Verify that activated windows are maximized after closing // the active window - for (int i = 0; i < subWindows.count(); ++i) { + for (int i = 0; i < subWindows.size(); ++i) { QVERIFY(mdiArea.activeSubWindow()); QVERIFY(mdiArea.activeSubWindow()->isMaximized()); mdiArea.activeSubWindow()->close(); @@ -2201,7 +2194,7 @@ void tst_QMdiArea::setActivationOrder() mdiArea.show(); QVERIFY(QTest::qWaitForWindowExposed(&mdiArea)); - for (int i = 0; i < subWindows.count(); ++i) { + for (int i = 0; i < subWindows.size(); ++i) { mdiArea.activateNextSubWindow(); QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(i)); qApp->processEvents(); @@ -2260,12 +2253,11 @@ void tst_QMdiArea::tabBetweenSubWindows() mdiArea.show(); QVERIFY(QTest::qWaitForWindowExposed(&mdiArea)); - qApp->setActiveWindow(&mdiArea); QWidget *focusWidget = subWindows.back()->widget(); QCOMPARE(qApp->focusWidget(), focusWidget); QSignalSpy spy(&mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*))); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); // Walk through the entire list of sub windows. #ifdef Q_OS_MAC @@ -2273,7 +2265,7 @@ void tst_QMdiArea::tabBetweenSubWindows() #endif QVERIFY(tabBetweenSubWindowsIn(&mdiArea)); QCOMPARE(mdiArea.activeSubWindow(), subWindows.back()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); mdiArea.setActiveSubWindow(subWindows.front()); QCOMPARE(mdiArea.activeSubWindow(), subWindows.front()); @@ -2282,12 +2274,12 @@ void tst_QMdiArea::tabBetweenSubWindows() // Walk through the entire list of sub windows in the opposite direction (Ctrl-Shift-Tab). QVERIFY(tabBetweenSubWindowsIn(&mdiArea, -1, true)); QCOMPARE(mdiArea.activeSubWindow(), subWindows.front()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); // Ctrl-Tab-Tab-Tab QVERIFY(tabBetweenSubWindowsIn(&mdiArea, 3)); QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(3)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); mdiArea.setActiveSubWindow(subWindows.at(1)); QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(1)); @@ -2296,7 +2288,7 @@ void tst_QMdiArea::tabBetweenSubWindows() // Quick switch (Ctrl-Tab once) -> switch back to the previously active sub-window. QVERIFY(tabBetweenSubWindowsIn(&mdiArea, 1)); QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(3)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } void tst_QMdiArea::setViewMode() @@ -2315,7 +2307,7 @@ void tst_QMdiArea::setViewMode() QVERIFY(QTest::qWaitForWindowExposed(&mdiArea)); QMdiSubWindow *activeSubWindow = mdiArea.activeSubWindow(); - QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList(); + const QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList(); // Default. QVERIFY(!activeSubWindow->isMaximized()); @@ -2330,7 +2322,7 @@ void tst_QMdiArea::setViewMode() QVERIFY(tabBar); QVERIFY(tabBar->isVisible()); - QCOMPARE(tabBar->count(), subWindows.count()); + QCOMPARE(tabBar->count(), subWindows.size()); QVERIFY(activeSubWindow->isMaximized()); QCOMPARE(tabBar->currentIndex(), subWindows.indexOf(activeSubWindow)); @@ -2384,13 +2376,12 @@ void tst_QMdiArea::setViewMode() QVERIFY(tabBar->isTabEnabled(tabIndex)); // Remove sub-windows and make sure the tab is removed. - foreach (QMdiSubWindow *subWindow, subWindows) { + for (QMdiSubWindow *subWindow : subWindows) { if (subWindow != activeSubWindow) { mdiArea.removeSubWindow(subWindow); delete subWindow; } } - subWindows.clear(); QCOMPARE(tabBar->count(), 1); // Go back to default (QMdiArea::SubWindowView). @@ -2591,8 +2582,11 @@ void tst_QMdiArea::nativeSubWindows() // No native widgets. QVERIFY(!mdiArea.viewport()->internalWinId()); - foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList()) - QVERIFY(!subWindow->internalWinId()); + { + const auto subWindows = mdiArea.subWindowList(); + for (QMdiSubWindow *subWindow : subWindows) + QVERIFY(!subWindow->internalWinId()); + } QWidget *nativeWidget = new QWidget; QVERIFY(nativeWidget->winId()); // enforce native window. @@ -2601,8 +2595,11 @@ void tst_QMdiArea::nativeSubWindows() // The viewport and all the sub-windows must be native. QVERIFY(mdiArea.viewport()->internalWinId()); - foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList()) - QVERIFY(subWindow->internalWinId()); + { + const auto subWindows = mdiArea.subWindowList(); + for (QMdiSubWindow *subWindow : subWindows) + QVERIFY(subWindow->internalWinId()); + } // Add a non-native widget. This should become native. QMdiSubWindow *subWindow = new QMdiSubWindow; @@ -2623,8 +2620,11 @@ void tst_QMdiArea::nativeSubWindows() // The viewport and all the sub-windows must be native. QVERIFY(mdiArea.viewport()->internalWinId()); - foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList()) - QVERIFY(subWindow->internalWinId()); + { + const auto subWindows = mdiArea.subWindowList(); + for (QMdiSubWindow *subWindow : subWindows) + QVERIFY(subWindow->internalWinId()); + } } { // Make a sub-window native *after* it's added to the area. @@ -2640,9 +2640,12 @@ void tst_QMdiArea::nativeSubWindows() // All the sub-windows should be native at this point QVERIFY(mdiArea.viewport()->internalWinId()); - foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList()) + { + const auto subWindows = mdiArea.subWindowList(); + for (QMdiSubWindow *subWindow : subWindows) QVERIFY(subWindow->internalWinId()); } + } } void tst_QMdiArea::task_209615() @@ -2713,6 +2716,21 @@ void tst_QMdiArea::qtbug92240_title() QTRY_COMPARE(w.windowTitle(), QLatin1String("QTBUG-92240 - [2]")); } +void tst_QMdiArea::tabbedview_singleSubWindow() +{ + // With only one sub-window, setViewMode() before addSubWindow(); and addSubWindow() + // before show(), ensure the sub-window is properly activated. + QMdiArea mdiArea; + mdiArea.setViewMode(QMdiArea::TabbedView); + auto *w = new QWidget(&mdiArea); + mdiArea.addSubWindow(w); + mdiArea.show(); + QVERIFY(QTest::qWaitForWindowExposed(&mdiArea)); + auto *sub = mdiArea.subWindowList().at(0); + QCOMPARE(mdiArea.activeSubWindow(), sub); + QVERIFY(sub->isMaximized()); +} + static void setupMdiAreaWithTabbedView(QMdiArea &mdiArea) { mdiArea.setViewMode(QMdiArea::TabbedView); diff --git a/tests/auto/widgets/widgets/qmdisubwindow/CMakeLists.txt b/tests/auto/widgets/widgets/qmdisubwindow/CMakeLists.txt index f84e59b5cb..45b7b74ac4 100644 --- a/tests/auto/widgets/widgets/qmdisubwindow/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qmdisubwindow/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qmdisubwindow.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qmdisubwindow Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmdisubwindow LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qmdisubwindow SOURCES tst_qmdisubwindow.cpp diff --git a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp index 1bdb1e8201..60b675b18a 100644 --- a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp +++ b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "qmdisubwindow.h" #include "private/qmdisubwindow_p.h" @@ -25,6 +25,8 @@ #include <QSignalSpy> #include <QList> +#include <QtWidgets/private/qapplication_p.h> + QT_BEGIN_NAMESPACE extern bool qt_tab_all_widgets(); QT_END_NAMESPACE @@ -382,7 +384,6 @@ void tst_QMdiSubWindow::mainWindowSupport() mainWindow.setCentralWidget(workspace); mainWindow.show(); mainWindow.menuBar()->setVisible(true); - QApplication::setActiveWindow(&mainWindow); bool nativeMenuBar = mainWindow.menuBar()->isNativeMenuBar(); // QMainWindow's window title is empty, so on a platform which does NOT have a native menubar, @@ -471,7 +472,7 @@ void tst_QMdiSubWindow::mainWindowSupport() workspace->activateNextSubWindow(); QCoreApplication::processEvents(); - for (QMdiSubWindow *window : qAsConst(windows)) { + for (QMdiSubWindow *window : std::as_const(windows)) { QCOMPARE(workspace->activeSubWindow(), window); QVERIFY(window->isMaximized()); QVERIFY(window->maximizedButtonsWidget()); @@ -508,7 +509,6 @@ void tst_QMdiSubWindow::emittingOfSignals() workspace.setWindowTitle(QLatin1String(QTest::currentTestFunction())); workspace.show(); QCoreApplication::processEvents(); - QApplication::setActiveWindow(&workspace); QMdiSubWindow *window = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget)); QCoreApplication::processEvents(); window->show(); @@ -528,9 +528,9 @@ void tst_QMdiSubWindow::emittingOfSignals() int count = 0; if (signal == SIGNAL(aboutToActivate())) { - count += spy.count(); + count += spy.size(); } else { - for (int i = 0; i < spy.count(); ++i) { + for (int i = 0; i < spy.size(); ++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) { @@ -553,7 +553,7 @@ void tst_QMdiSubWindow::emittingOfSignals() spy.clear(); triggerSignal(window, &workspace, signal); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); delete window; window = nullptr; @@ -952,6 +952,8 @@ void tst_QMdiSubWindow::mouseDoubleClick() if (!window->style()->styleHint(QStyle::SH_TitleBar_NoBorder, &options, window)) height += window->isMinimized() ? 8 : 4; QPoint mousePosition(window->width() / 2, height - 1); + if (window->style()->inherits("QWindows11Style")) + mousePosition = QPoint(8, height - 1); sendMouseMove(window, mousePosition, Qt::NoButton); // Without Qt::WindowShadeButtonHint flag set @@ -979,8 +981,10 @@ void tst_QMdiSubWindow::mouseDoubleClick() window->showMinimized(); QVERIFY(window->isMinimized()); + //Process QEvent::WindowStateChange + QCoreApplication::processEvents(); sendMouseDoubleClick(window, mousePosition); - QVERIFY(!window->isMinimized()); + QTRY_VERIFY(!window->isMinimized()); QCOMPARE(window->geometry(), originalGeometry); } @@ -1030,7 +1034,7 @@ void tst_QMdiSubWindow::setSystemMenu() subWindow->setSystemMenu(systemMenu); QCOMPARE(subWindow->systemMenu(), qobject_cast<QMenu *>(systemMenu)); QCOMPARE(subWindow->systemMenu()->parentWidget(), static_cast<QWidget *>(subWindow)); - QCOMPARE(subWindow->systemMenu()->actions().count(), 1); + QCOMPARE(subWindow->systemMenu()->actions().size(), 1); // Show the new system menu QVERIFY(!QApplication::activePopupWidget()); @@ -1134,7 +1138,7 @@ void tst_QMdiSubWindow::restoreFocus() topArea.show(); box->show(); - QApplication::setActiveWindow(&topArea); + QApplicationPrivate::setActiveWindow(&topArea); QMdiSubWindow *expectedFocusWindow = nestedWorkspace->subWindowList().last(); QVERIFY(expectedFocusWindow); QVERIFY(expectedFocusWindow->widget()); @@ -1226,7 +1230,6 @@ void tst_QMdiSubWindow::restoreFocusOverCreation() subWidget1->m_lineEdit2->setFocus(); subWindow1->show(); mdiArea.show(); - QApplication::setActiveWindow(&mdiArea); QVERIFY(QTest::qWaitForWindowActive(&mdiArea)); QCOMPARE(QApplication::focusWidget(), subWidget1->m_lineEdit2); @@ -1254,9 +1257,9 @@ void tst_QMdiSubWindow::changeFocusWithTab() mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction())); mdiArea.addSubWindow(widget); mdiArea.show(); - QCOMPARE(mdiArea.subWindowList().count(), 1); + QCOMPARE(mdiArea.subWindowList().size(), 1); - QApplication::setActiveWindow(&mdiArea); + QApplicationPrivate::setActiveWindow(&mdiArea); QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(firstLineEdit)); // Next @@ -1336,7 +1339,7 @@ void tst_QMdiSubWindow::closeEvent() QVERIFY(window->close()); QCOMPARE(closeSpy.count(), 3); - QCOMPARE(mdiArea.subWindowList().count(), 0); + QCOMPARE(mdiArea.subWindowList().size(), 0); } // There exists more tests in QMdiArea which covers window title support @@ -1371,7 +1374,7 @@ void tst_QMdiSubWindow::setWindowTitle() // other widgets which are not real top-level widgets). QCOMPARE(window->windowTitle(), expectedWindowTitle); - textEdit->setWindowModified(true);; + textEdit->setWindowModified(true); expectedWindowTitle = QLatin1String("Override child title"); window->setWindowTitle(expectedWindowTitle); QVERIFY(window->isWindowModified()); @@ -1865,7 +1868,6 @@ void tst_QMdiSubWindow::closeOnDoubleClick() void tst_QMdiSubWindow::setFont() { - QSKIP("This test function is unstable in CI, please see QTBUG-22544"); QMdiArea mdiArea; mdiArea.setWindowTitle(QLatin1String(QTest::currentTestFunction())); QMdiSubWindow *subWindow = mdiArea.addSubWindow(new TestPushButton(QLatin1String("test"))); @@ -1951,7 +1953,6 @@ void tst_QMdiSubWindow::task_182852() mainWindow.setCentralWidget(workspace); mainWindow.show(); mainWindow.menuBar()->setVisible(true); - QApplication::setActiveWindow(&mainWindow); if (mainWindow.menuBar()->isNativeMenuBar()) return; // The main window's title is not overwritten if we have a native menubar (macOS, Unity etc.) @@ -2101,7 +2102,7 @@ void tst_QMdiSubWindow::styleChange() // subWindowActivated should NOT be activated by a style change, // even if internally QMdiSubWindow un-minimizes subwindows temporarily. - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QMdiSubWindow::testFullScreenState() diff --git a/tests/auto/widgets/widgets/qmenu/BLACKLIST b/tests/auto/widgets/widgets/qmenu/BLACKLIST index dc1ab8ddd3..88484ddffa 100644 --- a/tests/auto/widgets/widgets/qmenu/BLACKLIST +++ b/tests/auto/widgets/widgets/qmenu/BLACKLIST @@ -16,6 +16,7 @@ android android [pushButtonPopulateOnAboutToShow] android +wayland [QTBUG8122_widgetActionCrashOnClose] android [click_while_dismissing_submenu] diff --git a/tests/auto/widgets/widgets/qmenu/CMakeLists.txt b/tests/auto/widgets/widgets/qmenu/CMakeLists.txt index d5bf060d4e..1716ab85da 100644 --- a/tests/auto/widgets/widgets/qmenu/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qmenu/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qmenu.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qmenu Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmenu LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qmenu SOURCES tst_qmenu.cpp @@ -15,6 +19,7 @@ qt_internal_add_test(tst_qmenu Qt::GuiPrivate Qt::TestPrivate Qt::Widgets + Qt::WidgetsPrivate ) ## Scopes: diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index 602795debb..57cc404fc7 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QtTest/private/qtesthelpers_p.h> @@ -27,6 +27,9 @@ #include <qpa/qplatformtheme.h> #include <qpa/qplatformintegration.h> +#include <QtWidgets/private/qapplication_p.h> +#include <QtWidgets/private/qmenu_p.h> + using namespace QTestPrivate; Q_DECLARE_METATYPE(Qt::Key); @@ -110,6 +113,9 @@ private slots: void tearOffMenuNotDisplayed(); void QTBUG_61039_menu_shortcuts(); void screenOrientationChangedCloseMenu(); + void deleteWhenTriggered(); + + void nestedTearOffDetached(); protected slots: void onActivated(QAction*); @@ -257,11 +263,11 @@ void tst_QMenu::onStatusMessageChanged(const QString &s) void tst_QMenu::addActionsAndClear() { - QCOMPARE(menus[0]->actions().count(), 0); + QCOMPARE(menus[0]->actions().size(), 0); createActions(); - QCOMPARE(menus[0]->actions().count(), 8); + QCOMPARE(menus[0]->actions().size(), 8); menus[0]->clear(); - QCOMPARE(menus[0]->actions().count(), 0); + QCOMPARE(menus[0]->actions().size(), 0); } static void testFunction0() {} @@ -481,7 +487,7 @@ void tst_QMenu::focus() QPushButton button("Push me", &window); centerOnScreen(&window); window.show(); - qApp->setActiveWindow(&window); + QApplicationPrivate::setActiveWindow(&window); QVERIFY(button.hasFocus()); QCOMPARE(QApplication::focusWidget(), (QWidget *)&button); @@ -525,7 +531,6 @@ void tst_QMenu::overrideMenuAction() m->addAction(aQuit); w.show(); - QApplication::setActiveWindow(&w); w.setFocus(); QVERIFY(QTest::qWaitForWindowActive(&w)); QVERIFY(w.hasFocus()); @@ -1140,14 +1145,18 @@ void tst_QMenu::pushButtonPopulateOnAboutToShow() QSKIP("Your window manager won't allow a window against the bottom of the screen"); } - QTimer::singleShot(300, buttonMenu, SLOT(hide())); QTest::mouseClick(&b, Qt::LeftButton, Qt::NoModifier, b.rect().center()); + QVERIFY(QTest::qWaitForWindowExposed(buttonMenu)); + QTest::qWait(300); + buttonMenu->hide(); QVERIFY2(!buttonMenu->geometry().intersects(b.geometry()), msgGeometryIntersects(buttonMenu->geometry(), b.geometry())); // note: we're assuming that, if we previously got the desired geometry, we'll get it here too b.move(10, screen.bottom()-buttonMenu->height()-5); - QTimer::singleShot(300, buttonMenu, SLOT(hide())); QTest::mouseClick(&b, Qt::LeftButton, Qt::NoModifier, b.rect().center()); + QVERIFY(QTest::qWaitForWindowExposed(buttonMenu)); + QTest::qWait(300); + buttonMenu->hide(); QVERIFY2(!buttonMenu->geometry().intersects(b.geometry()), msgGeometryIntersects(buttonMenu->geometry(), b.geometry())); } @@ -1262,7 +1271,7 @@ void tst_QMenu::click_while_dismissing_submenu() //the submenu must have been hidden for the bug to be triggered QVERIFY(!sub.isVisible()); QTest::mouseRelease(menuWindow, Qt::LeftButton, {}, menu.rect().center() - QPoint(0, 2), 300); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } #endif @@ -1603,7 +1612,6 @@ void tst_QMenu::transientParent() QWindow *topLevel = window.windowHandle(); QVERIFY(topLevel); - QApplication::setActiveWindow(&window); window.setFocus(); QVERIFY(QTest::qWaitForWindowActive(&window)); QVERIFY(window.hasFocus()); @@ -1838,12 +1846,12 @@ void tst_QMenu::menuSize_Scrolling() private: void showEvent(QShowEvent *e) override { - QVERIFY(actions().length() == m_numItems); + QVERIFY(actions().size() == m_numItems); int hmargin = style()->pixelMetric(QStyle::PM_MenuHMargin, nullptr, this); int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, nullptr, this); const QMargins cm = contentsMargins(); - QRect lastItem = actionGeometry(actions().at(actions().length() - 1)); + QRect lastItem = actionGeometry(actions().at(actions().size() - 1)); QSize s = size(); if (!QGuiApplication::platformName().compare(QLatin1String("minimal"), Qt::CaseInsensitive) || !QGuiApplication::platformName().compare(QLatin1String("offscreen"), Qt::CaseInsensitive)) { @@ -1909,7 +1917,7 @@ void tst_QMenu::menuSize_Scrolling() QVERIFY(QTest::qWaitForWindowExposed(&menu)); QList<QAction *> actions = menu.actions(); - QCOMPARE(actions.length(), numItems); + QCOMPARE(actions.size(), numItems); MenuMetrics mm(&menu); QTest::keyClick(&menu, Qt::Key_Home); @@ -1989,11 +1997,11 @@ void tst_QMenu::QTBUG_61039_menu_shortcuts() QSignalSpy actionKamenSpy(actionKamen, &QAction::triggered); QTest::keyClick(&widget, Qt::Key_K); - QTRY_COMPARE(actionKamenSpy.count(), 1); + QTRY_COMPARE(actionKamenSpy.size(), 1); QSignalSpy actionJoeSpy(actionJoe, &QAction::triggered); QTest::keyClick(&widget, Qt::Key_J, Qt::ControlModifier); - QTRY_COMPARE(actionJoeSpy.count(), 1); + QTRY_COMPARE(actionJoeSpy.size(), 1); } void tst_QMenu::screenOrientationChangedCloseMenu() @@ -2011,5 +2019,99 @@ void tst_QMenu::screenOrientationChangedCloseMenu() QTRY_COMPARE(menu.isVisible(),false); } +/* + Verify that deleting the menu in a slot connected to an + action's triggered signal doesn't crash. + QTBUG-106718 +*/ +void tst_QMenu::deleteWhenTriggered() +{ + QPointer<QMenu> menu = new QMenu; + QAction *action = menu->addAction("Action", [&menu]{ + delete menu; + }); + menu->popup(QGuiApplication::primaryScreen()->availableGeometry().center()); + menu->setActiveAction(action); + QTest::keyClick(menu, Qt::Key_Return); + QTRY_VERIFY(!menu); +} + +/* + QMenu uses the caused-stack to create the parent/child relationship + for tear-off menus. Since QTornOffMenu set the DeleteOnClose flag, closing a + tear-off in the parent chain will result in a null-pointer in the caused-stack. + Verify that we don't crash when traversing the chain, as reported in QTBUG-112217. + + The test has to open the submenus by hovering of the menu action, otherwise + the caused-stack remains empty and the issue doesn't reproduce. Due to QMenu's + timing and "sloppiness", we need to move the mouse within the action, with some + waiting and event processing in between to trigger the opening of the submenu. + If this fails we skip, as we then can't test what we are trying to test. +*/ +void tst_QMenu::nestedTearOffDetached() +{ + // Since QTornOffMenu is not declared in qmenuprivate.h we can't access the + // object even through QMenuPrivate. So use an event filter to watch out for + // a QTornOffMenu showing. + class TearOffWatcher : public QObject + { + public: + QMenu *tornOffMenu = nullptr; + protected: + bool eventFilter(QObject *receiver, QEvent *event) override + { + if (event->type() == QEvent::Show && receiver->inherits("QTornOffMenu")) + tornOffMenu = qobject_cast<QMenu *>(receiver); + return QObject::eventFilter(receiver, event); + } + } watcher; + qApp->installEventFilter(&watcher); + + QWidget widget; + QMenu *menu = new QMenu("Context", &widget); + + MenuMetrics mm(menu); + const int tearOffOffset = mm.fw + mm.vmargin + mm.tearOffHeight / 2; + + QMenu *subMenu = menu->addMenu("SubMenu"); + menu->setTearOffEnabled(true); + QMenu *subSubMenu = subMenu->addMenu("SubSubMenu"); + subMenu->setTearOffEnabled(true); + subSubMenu->addAction("Action!"); + subSubMenu->setTearOffEnabled(true); + + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + // open and tear off context menu + menu->popup(widget.geometry().center()); + QTest::mouseClick(menu, Qt::LeftButton, {}, QPoint(menu->width() / 2, tearOffOffset)); + + QMenu *menuTorn = watcher.tornOffMenu; + watcher.tornOffMenu = nullptr; + QVERIFY(menuTorn); + QVERIFY(QTest::qWaitForWindowExposed(menuTorn)); + + // open second menu and tear-off + QTest::mouseMove(menuTorn, menuTorn->actionGeometry(subMenu->menuAction()).topLeft()); + QTest::qWait(100); + QTest::mouseMove(menuTorn, menuTorn->actionGeometry(subMenu->menuAction()).center()); + if (!QTest::qWaitFor([subMenu]{ return subMenu->isVisible(); })) + QSKIP("Menu failed to show, skipping test"); + + QTest::mouseClick(subMenu, Qt::LeftButton, {}, QPoint(subMenu->width() / 2, tearOffOffset)); + menuTorn = watcher.tornOffMenu; + QVERIFY(menuTorn); + QVERIFY(QTest::qWaitForWindowExposed(menuTorn)); + // close the top level tear off + menu->hideTearOffMenu(); + // open third menu and tear-off + QTest::mouseMove(menuTorn, menuTorn->actionGeometry(subSubMenu->menuAction()).topLeft()); + QTest::qWait(100); + QTest::mouseMove(menuTorn, menuTorn->actionGeometry(subSubMenu->menuAction()).center()); + QTRY_VERIFY(subSubMenu->isVisible()); + QTest::mouseClick(subSubMenu, Qt::LeftButton, {}, QPoint(subSubMenu->width() / 2, tearOffOffset)); +} + QTEST_MAIN(tst_QMenu) #include "tst_qmenu.moc" diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu_mac.mm b/tests/auto/widgets/widgets/qmenu/tst_qmenu_mac.mm index be58cff8e6..ba76c28fd4 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu_mac.mm +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu_mac.mm @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #import <AppKit/AppKit.h> diff --git a/tests/auto/widgets/widgets/qmenubar/BLACKLIST b/tests/auto/widgets/widgets/qmenubar/BLACKLIST index 05984b6039..516fd39f86 100644 --- a/tests/auto/widgets/widgets/qmenubar/BLACKLIST +++ b/tests/auto/widgets/widgets/qmenubar/BLACKLIST @@ -1,11 +1,5 @@ [check_menuPosition] -ubuntu-16.04 -#QTBUG-66255 -ubuntu-18.04 -ubuntu-20.04 ubuntu-22.04 -[activatedCount] -opensuse-42.3 # QTBUG-87421 [cornerWidgets] android diff --git a/tests/auto/widgets/widgets/qmenubar/CMakeLists.txt b/tests/auto/widgets/widgets/qmenubar/CMakeLists.txt index 69cbf87052..f2b1c1bec6 100644 --- a/tests/auto/widgets/widgets/qmenubar/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qmenubar/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qmenubar.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qmenubar Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmenubar LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qmenubar SOURCES tst_qmenubar.cpp @@ -14,6 +18,7 @@ qt_internal_add_test(tst_qmenubar Qt::Gui Qt::TestPrivate Qt::Widgets + Qt::WidgetsPrivate ) ## Scopes: diff --git a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp index 18aacc52c3..06750b099b 100644 --- a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp +++ b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -20,6 +20,8 @@ #include <qobject.h> +#include <QtWidgets/private/qapplication_p.h> + QT_FORWARD_DECLARE_CLASS(QMainWindow) #include <qmenubar.h> @@ -91,13 +93,6 @@ private slots: #endif void allowActiveAndDisabled(); void taskQTBUG56860_focus(); - void check_endKey(); - void check_homeKey(); - -// void check_mouse1_data(); -// void check_mouse1(); -// void check_mouse2_data(); -// void check_mouse2(); void check_altPress(); void check_altClosePress(); @@ -129,6 +124,9 @@ private slots: void platformMenu(); void addActionQt5connect(); void QTBUG_65488_hiddenActionTriggered(); + void pressDragRelease_data(); + void pressDragRelease(); + protected slots: void onSimpleActivated( QAction*); void onComplexActionTriggered(); @@ -146,6 +144,7 @@ private: int m_simpleActivatedCount; int m_complexTriggerCount[int('k')]; QMenuBar* taskQTBUG53205MenuBar; + QScopedPointer<QPointingDevice> m_touchScreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice()); }; // Testing get/set functions @@ -334,7 +333,6 @@ void tst_QMenuBar::accel() QMainWindow w; const TestMenu menu = initWindowWithSimpleMenuBar(w); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); // shortcuts won't work unless the window is active QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_A, Qt::ControlModifier ); @@ -356,7 +354,6 @@ void tst_QMenuBar::activatedCount() QFETCH( bool, forceNonNative ); initWindowWithSimpleMenuBar(w, forceNonNative); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_A, Qt::ControlModifier ); @@ -556,7 +553,6 @@ void tst_QMenuBar::check_accelKeys() QMainWindow w; initWindowWithComplexMenuBar(w); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); // start with a bogus key that shouldn't trigger anything @@ -635,7 +631,6 @@ void tst_QMenuBar::check_cursorKeys1() QMainWindow w; initWindowWithComplexMenuBar(w); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); // start with a ALT + 1 that activates the first popupmenu @@ -675,7 +670,6 @@ void tst_QMenuBar::check_cursorKeys2() QMainWindow w; initWindowWithComplexMenuBar(w); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); // select popupmenu2 @@ -714,7 +708,6 @@ void tst_QMenuBar::check_cursorKeys3() QMainWindow w; initWindowWithComplexMenuBar(w); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); // select Popupmenu 2 @@ -756,7 +749,6 @@ void tst_QMenuBar::taskQTBUG56860_focus() w.setCentralWidget(e); w.show(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); QTRY_COMPARE(QApplication::focusWidget(), e); @@ -783,85 +775,6 @@ void tst_QMenuBar::taskQTBUG56860_focus() } /*! - If a popupmenu is active you can use home to go quickly to the first item in the menu. -*/ -void tst_QMenuBar::check_homeKey() -{ - // I'm temporarily shutting up this testcase. - // Seems like the behaviour i'm expecting isn't ok. - QSKIP("This test has been \"temporarily\" disabled at least since 2009 :)"); - - QEXPECT_FAIL( "0", "Popupmenu should respond to a Home key", Abort ); - - QMainWindow w; - initWindowWithComplexMenuBar(w); - w.show(); - QApplication::setActiveWindow(&w); - QVERIFY(QTest::qWaitForWindowActive(&w)); - - // select Popupmenu 2 - QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_2, Qt::AltModifier ); - - // Simulate some keys - QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down ); - QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down ); - QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Down ); - QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Home ); - // and press ENTER - QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Enter ); - // Let's see if the correct slot is called... -// QVERIFY2( m_complexActionTriggerCount[int('c')] == 1, "Popupmenu should respond to a Home key" ); - QCOMPARE(m_complexTriggerCount[int('c')], 1); - QCOMPARE(m_complexTriggerCount[3], 0); - QCOMPARE(m_complexTriggerCount[4], 0); - QCOMPARE(m_complexTriggerCount[int('a')], 0); - QCOMPARE(m_complexTriggerCount[int('b')], 0); - QCOMPARE(m_complexTriggerCount[int('d')], 0); - QCOMPARE(m_complexTriggerCount[int('e')], 0); - QCOMPARE(m_complexTriggerCount[int('f')], 0); - QCOMPARE(m_complexTriggerCount[int('g')], 0); - QCOMPARE(m_complexTriggerCount[int('h')], 0); -} - -/*! - If a popupmenu is active you can use end to go quickly to the last item in the menu. -*/ -void tst_QMenuBar::check_endKey() -{ - // I'm temporarily silenting this testcase. - // Seems like the behaviour i'm expecting isn't ok. - QSKIP("This test has been \"temporarily\" disabled at least since 2009 :)"); - - QEXPECT_FAIL( "0", "Popupmenu should respond to an End key", Abort ); - - QMainWindow w; - initWindowWithComplexMenuBar(w); - w.show(); - QApplication::setActiveWindow(&w); - QVERIFY(QTest::qWaitForWindowActive(&w)); - - // select Popupmenu 2 - QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_2, Qt::AltModifier ); - - // Simulate some keys - QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_End ); - // and press ENTER - QTest::keyClick(static_cast<QWidget *>(0), Qt::Key_Enter ); - // Let's see if the correct slot is called... -// QVERIFY2( m_complexActionTriggerCount[int('h')] == 1, "Popupmenu should respond to an End key" ); - QCOMPARE(m_complexTriggerCount[int('h')], 1);//, "Popupmenu should respond to an End key"); - QCOMPARE(m_complexTriggerCount[3], 0); - QCOMPARE(m_complexTriggerCount[4], 0); - QCOMPARE(m_complexTriggerCount[int('a')], 0); - QCOMPARE(m_complexTriggerCount[int('b')], 0); - QCOMPARE(m_complexTriggerCount[int('c')], 0); - QCOMPARE(m_complexTriggerCount[int('d')], 0); - QCOMPARE(m_complexTriggerCount[int('e')], 0); - QCOMPARE(m_complexTriggerCount[int('f')], 0); - QCOMPARE(m_complexTriggerCount[int('g')], 0); -} - -/*! If a popupmenu is active you can use esc to hide the menu and then the menubar should become active. If Down is pressed next the popup is activated again. @@ -878,7 +791,6 @@ void tst_QMenuBar::check_escKey() const TestMenu menu = initWindowWithComplexMenuBar(w); w.show(); w.setFocus(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); QVERIFY( !menu.menus.at(0)->isActiveWindow() ); @@ -916,112 +828,6 @@ void tst_QMenuBar::check_escKey() #endif -// void tst_QMenuBar::check_mouse1_data() -// { -// QTest::addColumn<QString>("popup_item"); -// QTest::addColumn<int>("itemA_count"); -// QTest::addColumn<int>("itemB_count"); - -// QTest::newRow( "A" ) << QString( "Item A Ctrl+A" ) << 1 << 0; -// QTest::newRow( "B" ) << QString( "Item B Ctrl+B" ) << 0 << 1; -// } - -// /*! -// Check if the correct signals are emitted if we select a popupmenu. -// */ -// void tst_QMenuBar::check_mouse1() -// { -// if (QSystem::curStyle() == "Motif") -// QSKIP("This fails in Motif due to a bug in the testing framework"); -// QFETCH( QString, popup_item ); -// QFETCH( int, itemA_count ); -// QFETCH( int, itemB_count ); - -// // initComplexMenubar(); -// QVERIFY( !pm1->isActiveWindow() ); -// QVERIFY( !pm2->isActiveWindow() ); - -// QTest::qWait(1000); -// QtTestMouse mouse; -// mouse.mouseEvent( QtTestMouse::MouseClick, mb, "Menu &1", Qt::LeftButton ); - -// QVERIFY( pm1->isActiveWindow() ); -// QVERIFY( !pm2->isActiveWindow() ); - -// QTest::qWait(1000); -// mouse.mouseEvent( QtTestMouse::MouseClick, pm1, popup_item, Qt::LeftButton ); - -// QCOMPARE(m_complexActionTriggerCount[3], 0); -// QCOMPARE(m_complexActionTriggerCount[4], 0); -// QCOMPARE(m_complexActionTriggerCount['a'], (uint)itemA_count); // this option should have fired -// QCOMPARE(m_complexActionTriggerCount['b'], (uint)itemB_count); -// QCOMPARE(m_complexActionTriggerCount['c'], 0); -// QCOMPARE(m_complexActionTriggerCount['d'], 0); -// QCOMPARE(m_complexActionTriggerCount['e'], 0); -// QCOMPARE(m_complexActionTriggerCount['f'], 0); -// QCOMPARE(m_complexActionTriggerCount['g'], 0); -// } - -// void tst_QMenuBar::check_mouse2_data() -// { -// QTest::addColumn<QString>("label"); -// QTest::addColumn<int>("itemA_count"); -// QTest::addColumn<int>("itemB_count"); -// QTest::addColumn<int>("itemC_count"); -// QTest::addColumn<int>("itemD_count"); -// QTest::addColumn<int>("itemE_count"); -// QTest::addColumn<int>("itemF_count"); -// QTest::addColumn<int>("itemG_count"); -// QTest::addColumn<int>("itemH_count"); -// QTest::addColumn<int>("menu3_count"); - -// QTest::newRow( "A" ) << QString( "Menu &1/Item A Ctrl+A" ) << 1 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0; -// QTest::newRow( "B" ) << QString( "Menu &1/Item B Ctrl+B" ) << 0 << 1 << 0 << 0 << 0 << 0 << 0 << 0 << 0; -// QTest::newRow( "C" ) << QString( "Menu &2/Item C Ctrl+C" ) << 0 << 0 << 1 << 0 << 0 << 0 << 0 << 0 << 0; -// QTest::newRow( "D" ) << QString( "Menu &2/Item D Ctrl+D" ) << 0 << 0 << 0 << 1 << 0 << 0 << 0 << 0 << 0; -// QTest::newRow( "E" ) << QString( "Menu &2/Item E Ctrl+E" ) << 0 << 0 << 0 << 0 << 1 << 0 << 0 << 0 << 0; -// QTest::newRow( "F" ) << QString( "Menu &2/Item F Ctrl+F" ) << 0 << 0 << 0 << 0 << 0 << 1 << 0 << 0 << 0; -// QTest::newRow( "G" ) << QString( "Menu &2/Item G Ctrl+G" ) << 0 << 0 << 0 << 0 << 0 << 0 << 1 << 0 << 0; -// QTest::newRow( "H" ) << QString( "Menu &2/Item H Ctrl+H" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 1 << 0; -// QTest::newRow( "menu 3" ) << QString( "M&enu 3" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 1; -// } - -// /*! -// Check if the correct signals are emitted if we select a popupmenu. -// This time, we use a little bit more magic from the testframework. -// */ -// void tst_QMenuBar::check_mouse2() -// { -// if (QSystem::curStyle() == "Motif") -// QSKIP("This fails in Motif due to a bug in the testing framework"); -// QFETCH( QString, label ); -// QFETCH( int, itemA_count ); -// QFETCH( int, itemB_count ); -// QFETCH( int, itemC_count ); -// QFETCH( int, itemD_count ); -// QFETCH( int, itemE_count ); -// QFETCH( int, itemF_count ); -// QFETCH( int, itemG_count ); -// QFETCH( int, itemH_count ); -// QFETCH( int, menu3_count ); - -// // initComplexMenubar(); -// QtTestMouse mouse; -// mouse.click( QtTestMouse::Menu, label, Qt::LeftButton ); - -// // check if the correct signals have fired -// QCOMPARE(m_complexActionTriggerCount[3], (uint)menu3_count); -// QCOMPARE(m_complexActionTriggerCount[4], 0); -// QCOMPARE(m_complexActionTriggerCount['a'], (uint)itemA_count); -// QCOMPARE(m_complexActionTriggerCount['b'], (uint)itemB_count); -// QCOMPARE(m_complexActionTriggerCount['c'], (uint)itemC_count); -// QCOMPARE(m_complexActionTriggerCount['d'], (uint)itemD_count); -// QCOMPARE(m_complexActionTriggerCount['e'], (uint)itemE_count); -// QCOMPARE(m_complexActionTriggerCount['f'], (uint)itemF_count); -// QCOMPARE(m_complexActionTriggerCount['g'], (uint)itemG_count); -// QCOMPARE(m_complexActionTriggerCount['h'], (uint)itemH_count); -// } - void tst_QMenuBar::allowActiveAndDisabled() { QMenuBar menuBar; @@ -1076,7 +882,6 @@ void tst_QMenuBar::check_altPress() initWindowWithSimpleMenuBar(w); w.show(); w.setFocus(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); QTest::keyClick( &w, Qt::Key_Alt ); @@ -1106,7 +911,6 @@ void tst_QMenuBar::check_altClosePress() w.show(); w.move(QGuiApplication::primaryScreen()->availableGeometry().center()); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); QTest::keyClick(&w, Qt::Key_F, Qt::AltModifier); @@ -1127,7 +931,6 @@ void tst_QMenuBar::check_shortcutPress() const TestMenu menu = initWindowWithComplexMenuBar(w); w.show(); w.setFocus(); - QApplication::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); QCOMPARE(m_complexTriggerCount[3], 0); @@ -1184,7 +987,6 @@ void tst_QMenuBar::check_menuPosition() QAction *menu_action = w.menuBar()->addMenu(&menu); centerOnScreen(&w); w.show(); - qApp->setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); //the menu should be below the menubar item @@ -1268,9 +1070,9 @@ void tst_QMenuBar::task223138_triggered() //let's trigger the first action top->trigger(); - QCOMPARE(menubarSpy.count(), 1); - QCOMPARE(menuSpy.count(), 1); - QCOMPARE(submenuSpy.count(), 0); + QCOMPARE(menubarSpy.size(), 1); + QCOMPARE(menuSpy.size(), 1); + QCOMPARE(submenuSpy.size(), 0); menubarSpy.clear(); menuSpy.clear(); @@ -1278,9 +1080,9 @@ void tst_QMenuBar::task223138_triggered() //let's trigger the sub action action->trigger(); - QCOMPARE(menubarSpy.count(), 1); - QCOMPARE(menuSpy.count(), 1); - QCOMPARE(submenuSpy.count(), 1); + QCOMPARE(menubarSpy.size(), 1); + QCOMPARE(menuSpy.size(), 1); + QCOMPARE(submenuSpy.size(), 1); } void tst_QMenuBar::task256322_highlight() @@ -1303,7 +1105,6 @@ void tst_QMenuBar::task256322_highlight() centerOnScreen(&win); win.show(); - QApplication::setActiveWindow(&win); QVERIFY(QTest::qWaitForWindowActive(&win)); const QPoint filePos = menuBarActionWindowPos(win.menuBar(), file); @@ -1359,8 +1160,8 @@ void tst_QMenuBar::menubarSizeHint() mb.setStyle(&style); //this is a list of arbitrary strings so that we check the geometry - QStringList list = QStringList() << "trer" << "ezrfgtgvqd" << "sdgzgzerzerzer" << "eerzertz" << "er"; - foreach(QString str, list) + const auto list = QStringList{"trer", "ezrfgtgvqd", "sdgzgzerzerzer", "eerzertz", "er"}; + for (const QString &str : list) mb.addAction(str); const int panelWidth = style.pixelMetric(QStyle::PM_MenuBarPanelWidth); @@ -1371,7 +1172,8 @@ void tst_QMenuBar::menubarSizeHint() centerOnScreen(&mb); mb.show(); QRect result; - foreach(QAction *action, mb.actions()) { + const auto actions = mb.actions(); + for (QAction *action : actions) { const QRect actionRect = mb.actionGeometry(action); if (!result.isNull()) //this is the first item QCOMPARE(actionRect.left() - result.right() - 1, spacing); @@ -1411,7 +1213,7 @@ void tst_QMenuBar::taskQTBUG4965_escapeEaten() #endif centerOnScreen(&menubar); menubar.show(); - QApplication::setActiveWindow(&menubar); + QApplicationPrivate::setActiveWindow(&menubar); QVERIFY(QTest::qWaitForWindowExposed(&menubar)); menubar.setActiveAction(first); QTRY_VERIFY(menu.isVisible()); @@ -1442,7 +1244,6 @@ void tst_QMenuBar::taskQTBUG11823_crashwithInvisibleActions() centerOnScreen(&menubar); menubar.show(); - QApplication::setActiveWindow(&menubar); QVERIFY(QTest::qWaitForWindowActive(&menubar)); menubar.setActiveAction(m); QCOMPARE(menubar.activeAction(), m); @@ -1473,7 +1274,6 @@ void tst_QMenuBar::closeOnSecondClickAndOpenOnThirdClick() // QTBUG-32807, menu QMenu *fileMenu = menuBar->addMenu(QStringLiteral("OpenCloseOpen")); fileMenu->addAction(QStringLiteral("Quit")); mainWindow.show(); - QApplication::setActiveWindow(&mainWindow); QVERIFY(QTest::qWaitForWindowActive(&mainWindow)); const QPoint center = menuBarActionWindowPos(mainWindow.menuBar(), fileMenu->menuAction()); @@ -1568,7 +1368,6 @@ void tst_QMenuBar::taskQTBUG53205_crashReparentNested() mainWindow.resize(300, 200); centerOnScreen(&mainWindow); const TestMenu testMenus = initWindowWithComplexMenuBar(mainWindow); - QApplication::setActiveWindow(&mainWindow); // they can't be windows QWidget hiddenParent(&mainWindow, {}); @@ -1618,12 +1417,75 @@ void tst_QMenuBar::QTBUG_65488_hiddenActionTriggered() // resize to action's size to make Action1 hidden win.resize(actRect.width() - 10, win.size().height()); win.show(); - QApplication::setActiveWindow(&win); QVERIFY(QTest::qWaitForWindowExposed(&win)); // click center of the blank area on the menubar where Action1 resided QTest::mouseClick(win.windowHandle(), Qt::LeftButton, Qt::NoModifier, win.menuBar()->geometry().center()); QCoreApplication::sendPostedEvents(); // make sure all queued events also dispatched - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); +} + +void tst_QMenuBar::pressDragRelease_data() +{ + QTest::addColumn<QPointingDevice *>("device"); + + QTest::newRow("mouse") << const_cast<QPointingDevice *>(QPointingDevice::primaryPointingDevice()); + QTest::newRow("touchscreen") << m_touchScreen.get(); +} + +void tst_QMenuBar::pressDragRelease() +{ + QFETCH(QPointingDevice *, device); + + QMainWindow w; + const TestMenu menu = initWindowWithComplexMenuBar(w); + const QMenu *firstMenu = menu.menus.first(); + QAction *hoveredAction = nullptr; + connect(firstMenu, &QMenu::hovered, firstMenu, [&hoveredAction](QAction *hov) { hoveredAction = hov; }); + w.show(); + QVERIFY(QTest::qWaitForWindowActive(&w)); + QWindow *win = w.windowHandle(); + const QPoint p1(50, w.menuBar()->geometry().height() / 2); + switch (device->type()) { + case QInputDevice::DeviceType::Mouse: + case QInputDevice::DeviceType::TouchPad: + QTest::mousePress(win, Qt::LeftButton, {}, p1); + break; + case QInputDevice::DeviceType::TouchScreen: + QTest::touchEvent(win, device).press(0, p1); + break; + default: + break; + } + + QTRY_VERIFY(firstMenu->isVisible()); + const QPoint firstMenuItemPos = firstMenu->geometry().center() - QPoint(0, 2); + const QPoint firstMenuItemPosInWin = w.mapFromGlobal(firstMenuItemPos); + switch (device->type()) { + case QInputDevice::DeviceType::Mouse: + case QInputDevice::DeviceType::TouchPad: + QTest::mouseMove(win, firstMenuItemPosInWin); + break; + case QInputDevice::DeviceType::TouchScreen: + QTest::touchEvent(win, device).move(0, firstMenuItemPosInWin); + break; + default: + break; + } + QVERIFY(hoveredAction); + QCOMPARE(hoveredAction, firstMenu->actionAt(firstMenu->mapFromGlobal(firstMenuItemPos))); + QSignalSpy triggeredSpy(hoveredAction, &QAction::triggered); + switch (device->type()) { + case QInputDevice::DeviceType::Mouse: + case QInputDevice::DeviceType::TouchPad: + QTest::mouseRelease(win, Qt::LeftButton, {}, firstMenuItemPosInWin); + break; + case QInputDevice::DeviceType::TouchScreen: + QTest::touchEvent(win, device).release(0, firstMenuItemPosInWin); + break; + default: + break; + } + QTRY_COMPARE(triggeredSpy.size(), 1); } // QTBUG-56526 @@ -1690,20 +1552,19 @@ void tst_QMenuBar::QTBUG_25669_menubarActionDoubleTriggered() QSignalSpy spy(win.menuBar(), &QMenuBar::triggered); win.show(); - QApplication::setActiveWindow(&win); QVERIFY(QTest::qWaitForWindowExposed(&win)); QPoint posAct1 = menuBarActionWindowPos(win.menuBar(), act1); QPoint posAct2 = menuBarActionWindowPos(win.menuBar(), act2); QTest::mouseClick(win.windowHandle(), Qt::LeftButton, Qt::NoModifier, posAct1); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); QTest::mouseClick(win.windowHandle(), Qt::LeftButton, Qt::NoModifier, posAct2); - QTRY_COMPARE(spy.count(), 2); + QTRY_COMPARE(spy.size(), 2); QTest::mouseClick(win.windowHandle(), Qt::LeftButton, Qt::NoModifier, posAct2); - QTRY_COMPARE(spy.count(), 3); + QTRY_COMPARE(spy.size(), 3); } void tst_QMenuBar::slotForTaskQTBUG53205() @@ -1727,7 +1588,6 @@ void tst_QMenuBar::taskQTBUG46812_doNotLeaveMenubarHighlighted() initWindowWithSimpleMenuBar(mainWindow); mainWindow.show(); - QApplication::setActiveWindow(&mainWindow); QVERIFY(QTest::qWaitForWindowActive(&mainWindow)); QVERIFY(!mainWindow.menuBar()->hasFocus()); @@ -1839,7 +1699,6 @@ void tst_QMenuBar::taskQTBUG55966_subMenuRemoved() delete subMenu; window.show(); - QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); QTest::qWait(500); } diff --git a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar_mac.mm b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar_mac.mm index fd8086772a..55e983a4d1 100644 --- a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar_mac.mm +++ b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar_mac.mm @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #import <Cocoa/Cocoa.h> diff --git a/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST b/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST index ecb962d8ca..6b96499889 100644 --- a/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST +++ b/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST @@ -1,5 +1,7 @@ -[stackWidgetOpaqueChildIsVisible] -windows-10 msvc-2017 +# Temporary solution COIN-966 +ubuntu +rhel +opensuse-leap # QTBUG-87436 [clearAndGrab] diff --git a/tests/auto/widgets/widgets/qopenglwidget/CMakeLists.txt b/tests/auto/widgets/widgets/qopenglwidget/CMakeLists.txt index 1079004e3a..78cef5300a 100644 --- a/tests/auto/widgets/widgets/qopenglwidget/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qopenglwidget/CMakeLists.txt @@ -1,14 +1,18 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qopenglwidget.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qopenglwidget Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qopenglwidget LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qopenglwidget - LOWDPI # special case + LOWDPI SOURCES tst_qopenglwidget.cpp LIBRARIES diff --git a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp index 9c0ce637c3..51f898c953 100644 --- a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp +++ b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp @@ -1,9 +1,10 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtOpenGLWidgets/QOpenGLWidget> #include <QtGui/QOpenGLFunctions> #include <QtGui/QPainter> +#include <QtGui/QBackingStore> #include <QtGui/QScreen> #include <QtGui/QStaticText> #include <QtWidgets/QGraphicsView> @@ -21,7 +22,9 @@ #include <private/qopengltextureglyphcache_p.h> #include <qpa/qplatformintegration.h> #include <private/qguiapplication_p.h> +#include <qpa/qplatformbackingstore.h> #include <qpa/qplatformintegration.h> +#include <rhi/qrhi.h> class tst_QOpenGLWidget : public QObject { @@ -33,6 +36,9 @@ private slots: void clearAndGrab(); void clearAndResizeAndGrab(); void createNonTopLevel(); +#if QT_CONFIG(egl) + void deviceLoss(); +#endif void painter(); void reparentToAlreadyCreated(); void reparentToNotYetCreated(); @@ -47,6 +53,8 @@ private slots: void offscreen(); void offscreenThenOnscreen(); void paintWhileHidden(); + void widgetWindowColorFormat_data(); + void widgetWindowColorFormat(); #ifdef QT_BUILD_INTERNAL void staticTextDanglingPointer(); @@ -68,7 +76,7 @@ void tst_QOpenGLWidget::create() QSignalSpy frameSwappedSpy(w.data(), SIGNAL(frameSwapped())); w->show(); QVERIFY(QTest::qWaitForWindowExposed(w.data())); - QVERIFY(frameSwappedSpy.count() > 0); + QVERIFY(frameSwappedSpy.size() > 0); QVERIFY(w->isValid()); QVERIFY(w->context()); @@ -163,7 +171,7 @@ void tst_QOpenGLWidget::createNonTopLevel() w.resize(400, 400); w.show(); QVERIFY(QTest::qWaitForWindowExposed(&w)); - QVERIFY(frameSwappedSpy.count() > 0); + QVERIFY(frameSwappedSpy.size() > 0); QVERIFY(glw->m_resizeCalled); glw->m_resizeCalled = false; @@ -187,6 +195,45 @@ void tst_QOpenGLWidget::createNonTopLevel() QVERIFY(QOpenGLContext::currentContext() == glw->context() && glw->context()); } +#if QT_CONFIG(egl) +void tst_QOpenGLWidget::deviceLoss() +{ + QScopedPointer<QOpenGLWidget> w(new ClearWidget(0, 640, 480)); + + w->resize(640, 480); + w->show(); + + auto rhi = w->backingStore()->handle()->rhi(w->windowHandle()); + QNativeInterface::QEGLContext *rhiContext = nullptr; + if (rhi->backend() == QRhi::OpenGLES2) { + auto rhiHandles = static_cast<const QRhiGles2NativeHandles *>(rhi->nativeHandles()); + rhiContext = rhiHandles->context->nativeInterface<QNativeInterface::QEGLContext>(); + } + if (!rhiContext) + QSKIP("deviceLoss needs EGL"); + + QVERIFY(QTest::qWaitForWindowExposed(w.data())); + + QImage image = w->grabFramebuffer(); + QVERIFY(!image.isNull()); + QCOMPARE(image.width(), w->width()); + QCOMPARE(image.height(), w->height()); + QVERIFY(image.pixel(30, 40) == qRgb(255, 0, 0)); + + rhiContext->invalidateContext(); + + w->resize(600, 600); + QSignalSpy frameSwappedSpy(w.get(), &QOpenGLWidget::resized); + QTRY_VERIFY(frameSwappedSpy.size() > 0); + + image = w->grabFramebuffer(); + QVERIFY(!image.isNull()); + QCOMPARE(image.width(), w->width()); + QCOMPARE(image.height(), w->height()); + QVERIFY(image.pixel(30, 40) == qRgb(255, 0, 0)); +} +#endif + class PainterWidget : public QOpenGLWidget, protected QOpenGLFunctions { public: @@ -324,7 +371,7 @@ void tst_QOpenGLWidget::reparentTopLevel() { QSignalSpy frameSwappedSpy(glw1, &QOpenGLWidget::frameSwapped); tabWidget.setCurrentIndex(tabWidget.addTab(glw1, "OpenGL widget 1")); - QTRY_VERIFY(frameSwappedSpy.count() > 0); + QTRY_VERIFY(frameSwappedSpy.size() > 0); } PainterWidget *glw2 = new PainterWidget; @@ -332,7 +379,7 @@ void tst_QOpenGLWidget::reparentTopLevel() { QSignalSpy frameSwappedSpy(glw2, &QOpenGLWidget::frameSwapped); tabWidget.setCurrentIndex(tabWidget.addTab(glw2, "OpenGL widget 2")); - QTRY_VERIFY(frameSwappedSpy.count() > 0); + QTRY_VERIFY(frameSwappedSpy.size() > 0); } QImage image = glw2->grabFramebuffer(); @@ -342,7 +389,7 @@ void tst_QOpenGLWidget::reparentTopLevel() { QSignalSpy frameSwappedSpy(glw1, &QOpenGLWidget::frameSwapped); delete glw2; - QTRY_VERIFY(frameSwappedSpy.count() > 0); + QTRY_VERIFY(frameSwappedSpy.size() > 0); } image = glw1->grabFramebuffer(); @@ -354,7 +401,7 @@ void tst_QOpenGLWidget::reparentTopLevel() glw1->setParent(nullptr); glw1->show(); QVERIFY(QTest::qWaitForWindowExposed(glw1)); - QTRY_VERIFY(frameSwappedSpy.count() > 0); + QTRY_VERIFY(frameSwappedSpy.size() > 0); } image = glw1->grabFramebuffer(); @@ -364,7 +411,7 @@ void tst_QOpenGLWidget::reparentTopLevel() { QSignalSpy frameSwappedSpy(glw1, &QOpenGLWidget::frameSwapped); tabWidget.setCurrentIndex(tabWidget.addTab(glw1, "Re-added OpenGL widget 1")); - QTRY_VERIFY(frameSwappedSpy.count() > 0); + QTRY_VERIFY(frameSwappedSpy.size() > 0); } image = glw1->grabFramebuffer(); @@ -421,6 +468,7 @@ void tst_QOpenGLWidget::asViewport() // repainted when going from Inactive to Active. So wait for the window to be // active before we continue, so the activation doesn't happen at a random // time below. And call processEvents to have the paint events delivered right away. + widget.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&widget)); qApp->processEvents(); } @@ -521,44 +569,187 @@ void tst_QOpenGLWidget::showHide() QVERIFY(image.pixel(30, 40) == qRgb(0, 0, 255)); } +QtMessageHandler oldHandler = nullptr; + +void nativeWindowMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + if (oldHandler) + oldHandler(type, context, msg); + + if (type == QtWarningMsg + && (msg.contains("QOpenGLContext::makeCurrent() called with non-opengl surface") + || msg.contains("Failed to make context current"))) + { + QFAIL("Unexpected warning got printed"); + } +} + void tst_QOpenGLWidget::nativeWindow() { #ifdef Q_OS_ANDROID QSKIP("Crashes on Android, figure out why (QTBUG-102043)"); #endif - QScopedPointer<ClearWidget> w(new ClearWidget(0, 800, 600)); - w->resize(800, 600); - w->show(); - w->winId(); - QVERIFY(QTest::qWaitForWindowExposed(w.data())); - QImage image = w->grabFramebuffer(); - QVERIFY(!image.isNull()); - QCOMPARE(image.width(), w->width()); - QCOMPARE(image.height(), w->height()); - QVERIFY(image.pixel(30, 40) == qRgb(255, 0, 0)); - QVERIFY(w->internalWinId()); - - // Now as a native child. - QWidget nativeParent; - nativeParent.resize(800, 600); - nativeParent.setAttribute(Qt::WA_NativeWindow); - ClearWidget *child = new ClearWidget(0, 800, 600); - child->setClearColor(0, 1, 0); - child->setParent(&nativeParent); - child->resize(400, 400); - child->move(23, 34); - nativeParent.show(); - QVERIFY(QTest::qWaitForWindowExposed(&nativeParent)); - - QVERIFY(nativeParent.internalWinId()); - QVERIFY(!child->internalWinId()); - - image = child->grabFramebuffer(); - QVERIFY(!image.isNull()); - QCOMPARE(image.width(), child->width()); - QCOMPARE(image.height(), child->height()); - QVERIFY(image.pixel(30, 40) == qRgb(0, 255, 0)); + // NB these tests do not fully verify that native child widgets are fully + // functional since there is no guarantee that the content is composed and + // presented correctly as we can only do verification with + // grabFramebuffer() here which only exercises a part of the pipeline. + + // Install a message handler that looks for some typical warnings from + // QRhi/QOpenGLConext that occur when the RHI-related logic in widgets goes wrong. + oldHandler = qInstallMessageHandler(nativeWindowMessageHandler); + + { + QScopedPointer<ClearWidget> w(new ClearWidget(nullptr, 800, 600)); + w->resize(800, 600); + w->show(); + w->winId(); + QVERIFY(QTest::qWaitForWindowExposed(w.data())); + + QImage image = w->grabFramebuffer(); + QVERIFY(!image.isNull()); + QCOMPARE(image.width(), w->width()); + QCOMPARE(image.height(), w->height()); + QVERIFY(image.pixel(30, 40) == qRgb(255, 0, 0)); + QVERIFY(w->internalWinId()); + } + + // QTBUG-113557: a plain _raster_ QWidget that is a _native_ child in a toplevel + // combined with a RHI-based (non-native) widget (QOpenGLWidget in this case) + // in the same toplevel. + { + QWidget topLevel; + topLevel.resize(800, 600); + + ClearWidget *child = new ClearWidget(&topLevel, 800, 600); + child->setClearColor(1, 0, 0); + child->resize(400, 400); + child->move(23, 34); + + QWidget *raster = new QWidget(&topLevel); + raster->setGeometry(23, 240, 120, 120); + raster->setStyleSheet("QWidget { background-color: yellow; }"); + + raster->winId(); + + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + + // Do not bother checking the output, i.e. if the yellow raster native child + // shows up as it should, but rather rely on the message handler catching the + // qWarnings if they occur. + } + + // Now with the QOpenGLWidget being a native child + { + QWidget topLevel; + topLevel.resize(800, 600); + + ClearWidget *child = new ClearWidget(nullptr, 800, 600); + child->setParent(&topLevel); + + // make it a native child (native window, but not top-level -> no backingstore) + child->winId(); + + child->setClearColor(0, 1, 0); + child->resize(400, 400); + child->move(23, 34); + + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + + QVERIFY(topLevel.internalWinId()); + QVERIFY(child->internalWinId()); + + QImage image = child->grabFramebuffer(); + QVERIFY(!image.isNull()); + QCOMPARE(image.width(), child->width()); + QCOMPARE(image.height(), child->height()); + QVERIFY(image.pixel(30, 40) == qRgb(0, 255, 0)); + } + + // Now the same with WA_NativeWindow instead + { + QWidget topLevel; + topLevel.resize(800, 600); + + ClearWidget *child = new ClearWidget(nullptr, 800, 600); + child->setParent(&topLevel); + + // make it a native child (native window, but not top-level -> no backingstore) + child->setAttribute(Qt::WA_NativeWindow); + + child->setClearColor(0, 1, 0); + child->resize(400, 400); + child->move(23, 34); + + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + + QVERIFY(child->internalWinId()); + + QImage image = child->grabFramebuffer(); + QCOMPARE(image.width(), child->width()); + QCOMPARE(image.height(), child->height()); + QVERIFY(image.pixel(30, 40) == qRgb(0, 255, 0)); + } + + // Now as a child of a native child + { + QWidget topLevel; + topLevel.resize(800, 600); + + QWidget *container = new QWidget(&topLevel); + // make it a native child (native window, but not top-level -> no backingstore) + container->winId(); + + ClearWidget *child = new ClearWidget(nullptr, 800, 600); + // set the parent separately, this is important, see next test case + child->setParent(container); + child->setClearColor(0, 0, 1); + child->resize(400, 400); + child->move(23, 34); + + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + + QVERIFY(topLevel.internalWinId()); + QVERIFY(container->internalWinId()); + QVERIFY(!child->internalWinId()); + + QImage image = child->grabFramebuffer(); + QCOMPARE(image.width(), child->width()); + QCOMPARE(image.height(), child->height()); + QVERIFY(image.pixel(30, 40) == qRgb(0, 0, 255)); + } + + // Again as a child of a native child, but this time specifying the parent + // upon construction, not with an explicit setParent() call afterwards. + { + QWidget topLevel; + topLevel.resize(800, 600); + QWidget *container = new QWidget(&topLevel); + container->winId(); + // parent it right away + ClearWidget *child = new ClearWidget(container, 800, 600); + child->setClearColor(0, 0, 1); + child->resize(400, 400); + child->move(23, 34); + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + QVERIFY(topLevel.internalWinId()); + QVERIFY(container->internalWinId()); + QVERIFY(!child->internalWinId()); + QImage image = child->grabFramebuffer(); + QCOMPARE(image.width(), child->width()); + QCOMPARE(image.height(), child->height()); + QVERIFY(image.pixel(30, 40) == qRgb(0, 0, 255)); + } + + if (oldHandler) { + qInstallMessageHandler(oldHandler); + oldHandler = nullptr; + } } static inline QString msgRgbMismatch(unsigned actual, unsigned expected) @@ -597,50 +788,59 @@ static QPixmap grabWidgetWithoutRepaint(const QWidget *widget, QRect clipArea) bool verifyColor(const QWidget *widget, const QRect &clipArea, const QColor &color, int callerLine) { - for (int t = 0; t < 6; t++) { - const QPixmap pixmap = grabWidgetWithoutRepaint(widget, clipArea); - if (!QTest::qCompare(pixmap.size(), - clipArea.size(), - "pixmap.size()", - "rect.size()", - __FILE__, - callerLine)) - return false; - - - const QImage image = pixmap.toImage(); - QPixmap expectedPixmap(pixmap); /* ensure equal formats */ - expectedPixmap.detach(); - expectedPixmap.fill(color); - + // Create a comparison target image + QPixmap expectedPixmap(grabWidgetWithoutRepaint(widget, clipArea)); /* ensure equal formats */ + expectedPixmap.detach(); + expectedPixmap.fill(color); + const QImage expectedImage = expectedPixmap.toImage(); + + // test image size + QPixmap pixmap; + auto testSize = [&](){ + pixmap = grabWidgetWithoutRepaint(widget, clipArea); + return pixmap.size() == clipArea.size(); + }; + + // test the first pixel's color + uint firstPixel; + auto testPixel = [&](){ + const QImage image = grabWidgetWithoutRepaint(widget, clipArea).toImage(); uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; - uint firstPixel = image.pixel(0,0) | alphaCorrection; - - // Retry a couple of times. Some window managers have transparency animation, or are - // just slow to render. - if (t < 5) { - if (firstPixel == QColor(color).rgb() - && image == expectedPixmap.toImage()) - return true; - else - QTest::qWait(200); - } else { - if (!QTest::qVerify(firstPixel == QColor(color).rgb(), - "firstPixel == QColor(color).rgb()", - qPrintable(msgRgbMismatch(firstPixel, QColor(color).rgb())), - __FILE__, callerLine)) { - return false; - } - if (!QTest::qVerify(image == expectedPixmap.toImage(), - "image == expectedPixmap.toImage()", - "grabbed pixmap differs from expected pixmap", - __FILE__, callerLine)) { - return false; - } - } + firstPixel = image.pixel(0,0) | alphaCorrection; + return firstPixel == QColor(color).rgb(); + }; + + // test the rendered image + QImage image; + auto testImage = [&](){ + image = grabWidgetWithoutRepaint(widget, clipArea).toImage(); + return image == expectedImage; + }; + + // Perform checks and make test case fail if unsuccessful + if (!QTest::qWaitFor(testSize)) + return QTest::qCompare(pixmap.size(), + clipArea.size(), + "pixmap.size()", + "rect.size()", + __FILE__, + callerLine); + + if (!QTest::qWaitFor(testPixel)) { + return QTest::qVerify(firstPixel == QColor(color).rgb(), + "firstPixel == QColor(color).rgb()", + qPrintable(msgRgbMismatch(firstPixel, QColor(color).rgb())), + __FILE__, callerLine); + } + + if (!QTest::qWaitFor(testImage)) { + return QTest::qVerify(image == expectedImage, + "image == expectedPixmap.toImage()", + "grabbed pixmap differs from expected pixmap", + __FILE__, callerLine); } - return false; + return true; } void tst_QOpenGLWidget::stackWidgetOpaqueChildIsVisible() @@ -673,11 +873,12 @@ void tst_QOpenGLWidget::stackWidgetOpaqueChildIsVisible() stack.resize(dimensionSize, dimensionSize); stack.show(); QVERIFY(QTest::qWaitForWindowExposed(&stack)); + stack.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&stack)); // Switch to the QOpenGLWidget. stack.setCurrentIndex(1); - QTRY_COMPARE(clearWidget->m_paintCalled, true); + QTRY_VERIFY(clearWidget->m_paintCalled); // Resize the tested region to be half size in the middle, because some OSes make the widget // have rounded corners (e.g. OSX), and the grabbed window pixmap will not coincide perfectly @@ -785,10 +986,34 @@ void tst_QOpenGLWidget::paintWhileHidden() // on-screen at the point when update() is called. w->setVisible(false); - w->m_paintCalled = 0; + w->m_paintCalled = false; w->update(); w->setVisible(true); - QTRY_VERIFY(w->m_paintCalled > 0); + QTRY_VERIFY(w->m_paintCalled); +} + +void tst_QOpenGLWidget::widgetWindowColorFormat_data() +{ + QTest::addColumn<bool>("translucent"); + QTest::newRow("Translucent background disabled") << false; + QTest::newRow("Translucent background enabled") << true; +} + +void tst_QOpenGLWidget::widgetWindowColorFormat() +{ + QFETCH(bool, translucent); + + QOpenGLWidget w; + w.setAttribute(Qt::WA_TranslucentBackground, translucent); + w.setWindowTitle(QLatin1String(QTest::currentTestFunction())); + w.setFixedSize(16, 16); + w.show(); + QVERIFY(QTest::qWaitForWindowExposed(&w)); + + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + QCOMPARE(w.format().redBufferSize(), ctx->format().redBufferSize()); + QCOMPARE(w.format().greenBufferSize(), ctx->format().greenBufferSize()); + QCOMPARE(w.format().blueBufferSize(), ctx->format().blueBufferSize()); } class StaticTextPainterWidget : public QOpenGLWidget diff --git a/tests/auto/widgets/widgets/qplaintextedit/CMakeLists.txt b/tests/auto/widgets/widgets/qplaintextedit/CMakeLists.txt index d2ccc3a035..b7528498cb 100644 --- a/tests/auto/widgets/widgets/qplaintextedit/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qplaintextedit/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qplaintextedit.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qplaintextedit Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qplaintextedit LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qplaintextedit SOURCES tst_qplaintextedit.cpp diff --git a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp index e0c213f8e0..ca7cc6d4b4 100644 --- a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp +++ b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -132,6 +132,8 @@ private slots: void appendTextWhenInvisible(); void placeholderVisibility_data(); void placeholderVisibility(); + void scrollBarSignals(); + void dontCrashWithCss(); private: void createSelection(); @@ -393,7 +395,7 @@ void tst_QPlainTextEdit::cursorPositionChanged() spy.clear(); QTest::keyClick(ed, Qt::Key_A); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QTextCursor cursor = ed->textCursor(); cursor.movePosition(QTextCursor::Start); @@ -401,23 +403,23 @@ void tst_QPlainTextEdit::cursorPositionChanged() cursor.movePosition(QTextCursor::End); spy.clear(); cursor.insertText("Test"); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); cursor.movePosition(QTextCursor::End); ed->setTextCursor(cursor); cursor.movePosition(QTextCursor::Start); spy.clear(); cursor.insertText("Test"); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); QTest::keyClick(ed, Qt::Key_Left); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); CursorPositionChangedRecorder spy2(ed); QVERIFY(ed->textCursor().position() > 0); ed->setPlainText("Hello World"); - QCOMPARE(spy2.cursorPositions.count(), 1); + QCOMPARE(spy2.cursorPositions.size(), 1); QCOMPARE(spy2.cursorPositions.at(0), 0); QCOMPARE(ed->textCursor().position(), 0); } @@ -434,7 +436,7 @@ void tst_QPlainTextEdit::setTextCursor() spy.clear(); ed->setTextCursor(cursor); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } #ifndef QT_NO_CLIPBOARD @@ -451,7 +453,7 @@ void tst_QPlainTextEdit::undoAvailableAfterPaste() const QString txt("Test"); QApplication::clipboard()->setText(txt); ed->paste(); - QVERIFY(spy.count() >= 1); + QVERIFY(spy.size() >= 1); QCOMPARE(ed->toPlainText(), txt); } #endif @@ -705,16 +707,16 @@ void tst_QPlainTextEdit::noPropertiesOnDefaultTextEditCharFormat() // on a text edit. Font properties instead should be taken from the // widget's font (in sync with defaultFont property in document) and the // foreground color should be taken from the palette. - QCOMPARE(ed->textCursor().charFormat().properties().count(), 0); + QCOMPARE(ed->textCursor().charFormat().properties().size(), 0); } void tst_QPlainTextEdit::setPlainTextShouldEmitTextChangedOnce() { QSignalSpy spy(ed, SIGNAL(textChanged())); ed->setPlainText("Yankee Doodle"); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); ed->setPlainText(""); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); } void tst_QPlainTextEdit::overwriteMode() @@ -994,7 +996,7 @@ void tst_QPlainTextEdit::copyAvailable_data() //Tests the copyAvailable slot for several cases void tst_QPlainTextEdit::copyAvailable() { - QFETCH(pairListType,keystrokes); + QFETCH(const pairListType, keystrokes); QFETCH(QList<bool>, copyAvailable); QFETCH(QString, function); @@ -1007,9 +1009,8 @@ void tst_QPlainTextEdit::copyAvailable() QSignalSpy spyCopyAvailabe(ed, SIGNAL(copyAvailable(bool))); //Execute Keystrokes - foreach(keyPairType keyPair, keystrokes) { + for (keyPairType keyPair : keystrokes) QTest::keyClick(ed, keyPair.first, keyPair.second ); - } //Execute ed->"function" if (function == "cut") @@ -1026,8 +1027,8 @@ void tst_QPlainTextEdit::copyAvailable() //Compare spied signals QEXPECT_FAIL("Case7 T,A,A, <- + shift, <- + shift, <- + shift, ctrl + x, undo() | signals: true, false, true", "Wrong undo selection behaviour. Should be fixed in some future release. (See task: 132482)", Abort); - QCOMPARE(spyCopyAvailabe.count(), copyAvailable.count()); - for (int i=0;i<spyCopyAvailabe.count(); i++) { + QCOMPARE(spyCopyAvailabe.size(), copyAvailable.size()); + for (int i=0;i<spyCopyAvailabe.size(); i++) { QVariant variantSpyCopyAvailable = spyCopyAvailabe.at(i).at(0); QVERIFY2(variantSpyCopyAvailable.toBool() == copyAvailable.at(i), QString("Spied singnal: %1").arg(i).toLatin1()); } @@ -1063,10 +1064,10 @@ void tst_QPlainTextEdit::moveCursor() QCOMPARE(ed->textCursor().position(), 0); ed->moveCursor(QTextCursor::NextCharacter); QCOMPARE(ed->textCursor().position(), 1); - QCOMPARE(cursorMovedSpy.count(), 1); + QCOMPARE(cursorMovedSpy.size(), 1); ed->moveCursor(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); QCOMPARE(ed->textCursor().position(), 2); - QCOMPARE(cursorMovedSpy.count(), 2); + QCOMPARE(cursorMovedSpy.size(), 2); QCOMPARE(ed->textCursor().selectedText(), QString("e")); } @@ -1278,7 +1279,7 @@ void tst_QPlainTextEdit::ensureVisibleWithRtl() ed->setLayoutDirection(Qt::RightToLeft); ed->setLineWrapMode(QPlainTextEdit::NoWrap); QString txt(500, QChar(QLatin1Char('a'))); - QCOMPARE(txt.length(), 500); + QCOMPARE(txt.size(), 500); ed->setPlainText(txt); ed->resize(100, 100); ed->show(); @@ -1331,7 +1332,7 @@ void tst_QPlainTextEdit::extraSelections() ed->setExtraSelections(QList<QTextEdit::ExtraSelection>() << sel); QList<QTextEdit::ExtraSelection> selections = ed->extraSelections(); - QCOMPARE(selections.count(), 1); + QCOMPARE(selections.size(), 1); QCOMPARE(selections.at(0).cursor.position(), endPos); QCOMPARE(selections.at(0).cursor.anchor(), wordPos); } @@ -1461,44 +1462,44 @@ void tst_QPlainTextEdit::selectionChanged() QTest::keyClick(ed, Qt::Key_Right); QCOMPARE(ed->textCursor().position(), 1); - QCOMPARE(selectionChangedSpy.count(), 0); + QCOMPARE(selectionChangedSpy.size(), 0); QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier); QCOMPARE(ed->textCursor().position(), 2); - QCOMPARE(selectionChangedSpy.count(), 1); + QCOMPARE(selectionChangedSpy.size(), 1); QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier); QCOMPARE(ed->textCursor().position(), 3); - QCOMPARE(selectionChangedSpy.count(), 2); + QCOMPARE(selectionChangedSpy.size(), 2); QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier); QCOMPARE(ed->textCursor().position(), 4); - QCOMPARE(selectionChangedSpy.count(), 3); + QCOMPARE(selectionChangedSpy.size(), 3); QTest::keyClick(ed, Qt::Key_Right); QCOMPARE(ed->textCursor().position(), 4); - QCOMPARE(selectionChangedSpy.count(), 4); + QCOMPARE(selectionChangedSpy.size(), 4); QTest::keyClick(ed, Qt::Key_Right); QCOMPARE(ed->textCursor().position(), 5); - QCOMPARE(selectionChangedSpy.count(), 4); + QCOMPARE(selectionChangedSpy.size(), 4); } void tst_QPlainTextEdit::blockCountChanged() { QSignalSpy blockCountCpangedSpy(ed, SIGNAL(blockCountChanged(int))); ed->setPlainText("Hello"); - QCOMPARE(blockCountCpangedSpy.count(), 0); + QCOMPARE(blockCountCpangedSpy.size(), 0); ed->setPlainText("Hello World"); - QCOMPARE(blockCountCpangedSpy.count(), 0); + QCOMPARE(blockCountCpangedSpy.size(), 0); ed->setPlainText("Hello \n World \n this \n has \n more \n blocks \n than \n just \n one"); - QCOMPARE(blockCountCpangedSpy.count(), 1); + QCOMPARE(blockCountCpangedSpy.size(), 1); ed->setPlainText("One"); - QCOMPARE(blockCountCpangedSpy.count(), 2); + QCOMPARE(blockCountCpangedSpy.size(), 2); ed->setPlainText("One \n Two"); - QCOMPARE(blockCountCpangedSpy.count(), 3); + QCOMPARE(blockCountCpangedSpy.size(), 3); ed->setPlainText("Three \n Four"); - QCOMPARE(blockCountCpangedSpy.count(), 3); + QCOMPARE(blockCountCpangedSpy.size(), 3); } @@ -1699,7 +1700,7 @@ void tst_QPlainTextEdit::contextMenu() QVERIFY(!ed->findChild<QAction *>(QStringLiteral("link-copy"))); QTextCursor cursor = ed->textCursor(); - cursor.setPosition(ed->toPlainText().length() - 2); + cursor.setPosition(ed->toPlainText().size() - 2); ed->setTextCursor(cursor); menu = ed->createStandardContextMenu(ed->cursorRect().center()); @@ -1782,7 +1783,7 @@ void tst_QPlainTextEdit::updateCursorPositionAfterEdit() QTest::keyClick(&plaintextEdit, Qt::Key_Up); // The curser should move back to the end of the copied text - QCOMPARE(plaintextEdit.textCursor().position(), initialPosition + txt.length()); + QCOMPARE(plaintextEdit.textCursor().position(), initialPosition + txt.size()); } #endif @@ -1829,7 +1830,7 @@ void tst_QPlainTextEdit::placeholderVisibility_data() QTest::addColumn<QList<SetupCommand>>("setupCommands"); QTest::addColumn<bool>("placeholderVisible"); QTest::addRow("no placeholder set + no text set") - << QList<SetupCommand>{} << true; + << QList<SetupCommand>{} << false; QTest::addRow("no placeholder set + text set or text set + no placeholder set") << QList<SetupCommand>{ SetContent } << false; QTest::addRow("no placeholder set + text set + empty text set") @@ -1839,7 +1840,7 @@ void tst_QPlainTextEdit::placeholderVisibility_data() << QList<SetupCommand>{ ClearContent, SetContent } << false; QTest::addRow("empty placeholder set + no text set") - << QList<SetupCommand>{ ClearPlaceHolder } << true; + << QList<SetupCommand>{ ClearPlaceHolder } << false; QTest::addRow("empty placeholder set + text set") << QList<SetupCommand>{ ClearPlaceHolder, SetContent } << false; @@ -1916,8 +1917,42 @@ void tst_QPlainTextEdit::placeholderVisibility() plainTextEdit.show(); QVERIFY(QTest::qWaitForWindowExposed(&plainTextEdit)); - QTRY_VERIFY(plainTextEdit_d->placeholderVisible == placeholderVisible); + QTRY_COMPARE(plainTextEdit_d->placeholderTextShown, placeholderVisible); } + +void tst_QPlainTextEdit::scrollBarSignals() +{ + QPlainTextEdit plainTextEdit; + QString longText; + for (uint i = 0; i < 500; ++i) + longText += "This is going to be a very long text for scroll signal testing.\n"; + plainTextEdit.setPlainText(longText); + QScrollBar *vbar = plainTextEdit.verticalScrollBar(); + plainTextEdit.show(); + QVERIFY(QTest::qWaitForWindowExposed(&plainTextEdit)); + QSignalSpy spy(vbar, &QScrollBar::valueChanged); + + QTest::keyClick(vbar, Qt::Key_Down); + QTRY_COMPARE(spy.count(), 1); + QTest::keyClick(vbar, Qt::Key_PageDown); + QTRY_COMPARE(spy.count(), 2); + QTest::keyClick(vbar, Qt::Key_PageDown); + QTRY_COMPARE(spy.count(), 3); + QTest::keyClick(vbar, Qt::Key_Up); + QTRY_COMPARE(spy.count(), 4); + QTest::keyClick(vbar, Qt::Key_PageUp); + QTRY_COMPARE(spy.count(), 5); +} + +void tst_QPlainTextEdit::dontCrashWithCss() +{ + qApp->setStyleSheet("QWidget { font: 10pt; }"); + QPlainTextEdit edit; + edit.show(); + qApp->setStyleSheet(QString()); +} + + QTEST_MAIN(tst_QPlainTextEdit) #include "tst_qplaintextedit.moc" diff --git a/tests/auto/widgets/widgets/qprogressbar/CMakeLists.txt b/tests/auto/widgets/widgets/qprogressbar/CMakeLists.txt index 7a66a722ab..61ce6c2692 100644 --- a/tests/auto/widgets/widgets/qprogressbar/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qprogressbar/CMakeLists.txt @@ -1,16 +1,21 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qprogressbar.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qprogressbar Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qprogressbar LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qprogressbar SOURCES tst_qprogressbar.cpp LIBRARIES Qt::Gui Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp b/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp index abe29345d2..4a90ed6667 100644 --- a/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp +++ b/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -11,6 +11,8 @@ #include <qtimer.h> #include <QStyleFactory> +#include <QtWidgets/private/qapplication_p.h> + class tst_QProgressBar : public QObject { Q_OBJECT @@ -223,7 +225,7 @@ void tst_QProgressBar::setMinMaxRepaint() pbar.setFormat("%v"); pbar.move(300, 300); pbar.show(); - qApp->setActiveWindow(&pbar); + QApplicationPrivate::setActiveWindow(&pbar); QVERIFY(QTest::qWaitForWindowActive(&pbar)); // No repaint when setting minimum to the current minimum diff --git a/tests/auto/widgets/widgets/qpushbutton/CMakeLists.txt b/tests/auto/widgets/widgets/qpushbutton/CMakeLists.txt index 913c3ecd4c..afd052fa17 100644 --- a/tests/auto/widgets/widgets/qpushbutton/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qpushbutton/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qpushbutton.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qpushbutton Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qpushbutton LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qpushbutton SOURCES tst_qpushbutton.cpp @@ -14,4 +18,5 @@ qt_internal_add_test(tst_qpushbutton Qt::Gui Qt::GuiPrivate Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp index 172c5878cb..73360ae21d 100644 --- a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp +++ b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -15,10 +15,13 @@ #include <QGridLayout> #include <QStyleFactory> #include <QTabWidget> +#include <QStyleOption> #include <private/qguiapplication_p.h> #include <qpa/qplatformtheme.h> +#include <QtWidgets/private/qapplication_p.h> + class tst_QPushButton : public QObject { Q_OBJECT @@ -52,20 +55,20 @@ private slots: void hitButton(); void iconOnlyStyleSheet(); void mousePressAndMove(); + void reactToMenuClosed(); protected slots: void resetCounters(); void onClicked(); - void onToggled( bool on ); + void onToggled(bool on); void onPressed(); void onReleased(); - void helperSlotDelete(); private: - uint click_count; - uint toggle_count; - uint press_count; - uint release_count; + int click_count; + int toggle_count; + int press_count; + int release_count; QPushButton *testWidget; QPointingDevice *m_touchScreen = QTest::createTouchDevice(); @@ -80,40 +83,40 @@ void tst_QPushButton::getSetCheck() QMenu *var1 = new QMenu; obj1.setMenu(var1); QCOMPARE(var1, obj1.menu()); - obj1.setMenu((QMenu *)0); - QCOMPARE((QMenu *)0, obj1.menu()); + obj1.setMenu(nullptr); + QCOMPARE(obj1.menu(), nullptr); delete var1; } void tst_QPushButton::initTestCase() { // Create the test class - testWidget = new QPushButton( "&Start", 0 ); + testWidget = new QPushButton("&Start", 0); testWidget->setObjectName("testWidget"); - testWidget->resize( 200, 200 ); + testWidget->resize(200, 200); testWidget->show(); - connect( testWidget, SIGNAL(clicked()), this, SLOT(onClicked()) ); - connect( testWidget, SIGNAL(pressed()), this, SLOT(onPressed()) ); - connect( testWidget, SIGNAL(released()), this, SLOT(onReleased()) ); - connect( testWidget, SIGNAL(toggled(bool)), this, SLOT(onToggled(bool)) ); + connect(testWidget, SIGNAL(clicked()), this, SLOT(onClicked())); + connect(testWidget, SIGNAL(pressed()), this, SLOT(onPressed())); + connect(testWidget, SIGNAL(released()), this, SLOT(onReleased())); + connect(testWidget, SIGNAL(toggled(bool)), this, SLOT(onToggled(bool))); } void tst_QPushButton::cleanupTestCase() { delete testWidget; - testWidget = 0; + testWidget = nullptr; } void tst_QPushButton::init() { - testWidget->setAutoRepeat( false ); - testWidget->setDown( false ); + testWidget->setAutoRepeat(false); + testWidget->setDown(false); testWidget->setText("Test"); - testWidget->setEnabled( true ); + testWidget->setEnabled(true); #if QT_CONFIG(shortcut) QKeySequence seq; - testWidget->setShortcut( seq ); + testWidget->setShortcut(seq); #endif resetCounters(); @@ -132,7 +135,7 @@ void tst_QPushButton::onClicked() click_count++; } -void tst_QPushButton::onToggled( bool /*on*/ ) +void tst_QPushButton::onToggled(bool /*on*/) { toggle_count++; } @@ -150,46 +153,46 @@ void tst_QPushButton::onReleased() void tst_QPushButton::autoRepeat() { // If this changes, this test must be completely revised. - QVERIFY( !testWidget->isCheckable() ); + QVERIFY(!testWidget->isCheckable()); // verify autorepeat is off by default. - QPushButton tmp( 0 ); + QPushButton tmp; tmp.setObjectName("tmp"); - QVERIFY( !tmp.autoRepeat() ); + QVERIFY(!tmp.autoRepeat()); // check if we can toggle the mode - testWidget->setAutoRepeat( true ); - QVERIFY( testWidget->autoRepeat() ); + testWidget->setAutoRepeat(true); + QVERIFY(testWidget->autoRepeat()); - testWidget->setAutoRepeat( false ); - QVERIFY( !testWidget->autoRepeat() ); + testWidget->setAutoRepeat(false); + QVERIFY(!testWidget->autoRepeat()); resetCounters(); // check that the button is down if we press space and not in autorepeat - testWidget->setDown( false ); - testWidget->setAutoRepeat( false ); - QTest::keyPress( testWidget, Qt::Key_Space ); + testWidget->setDown(false); + testWidget->setAutoRepeat(false); + QTest::keyPress(testWidget, Qt::Key_Space); - QTRY_VERIFY( testWidget->isDown() ); - QVERIFY( toggle_count == 0 ); - QVERIFY( press_count == 1 ); - QVERIFY( release_count == 0 ); - QVERIFY( click_count == 0 ); + QTRY_VERIFY(testWidget->isDown()); + QCOMPARE(toggle_count, 0); + QCOMPARE(press_count, 1); + QCOMPARE(release_count, 0); + QCOMPARE(click_count, 0); - QTest::keyRelease( testWidget, Qt::Key_Space ); + QTest::keyRelease(testWidget, Qt::Key_Space); resetCounters(); // check that the button is down if we press space while in autorepeat // we can't actually confirm how many times it is fired, more than 1 is enough. - testWidget->setDown( false ); - testWidget->setAutoRepeat( true ); - QTest::keyPress( testWidget, Qt::Key_Space ); + testWidget->setDown(false); + testWidget->setAutoRepeat(true); + QTest::keyPress(testWidget, Qt::Key_Space); QTRY_VERIFY(press_count > 3); - QVERIFY( testWidget->isDown() ); - QVERIFY( toggle_count == 0 ); - QTest::keyRelease( testWidget, Qt::Key_Space ); + QVERIFY(testWidget->isDown()); + QCOMPARE(toggle_count, 0); + QTest::keyRelease(testWidget, Qt::Key_Space); QCOMPARE(press_count, release_count); QCOMPARE(release_count, click_count); @@ -197,7 +200,7 @@ void tst_QPushButton::autoRepeat() // check that pressing ENTER has no effect resetCounters(); - testWidget->setDown( false ); + testWidget->setDown(false); // Skip after reset if ButtonPressKeys has Key_Enter const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() ->themeHint(QPlatformTheme::ButtonPressKeys) @@ -205,40 +208,40 @@ void tst_QPushButton::autoRepeat() if (buttonPressKeys.contains(Qt::Key_Enter)) { return; } - testWidget->setAutoRepeat( false ); - QTest::keyPress( testWidget, Qt::Key_Enter ); + testWidget->setAutoRepeat(false); + QTest::keyPress(testWidget, Qt::Key_Enter); - QTest::qWait( 300 ); + QTest::qWait(300); - QVERIFY( !testWidget->isDown() ); - QVERIFY( toggle_count == 0 ); - QVERIFY( press_count == 0 ); - QVERIFY( release_count == 0 ); - QVERIFY( click_count == 0 ); - QTest::keyRelease( testWidget, Qt::Key_Enter ); + QVERIFY(!testWidget->isDown()); + QCOMPARE(toggle_count, 0); + QCOMPARE(press_count, 0); + QCOMPARE(release_count, 0); + QCOMPARE(click_count, 0); + QTest::keyRelease(testWidget, Qt::Key_Enter); // check that pressing ENTER has no effect resetCounters(); - testWidget->setDown( false ); - testWidget->setAutoRepeat( true ); - QTest::keyClick( testWidget, Qt::Key_Enter ); - QTest::qWait( 300 ); - QVERIFY( !testWidget->isDown() ); - QVERIFY( toggle_count == 0 ); - QVERIFY( press_count == 0 ); - QVERIFY( release_count == 0 ); - QVERIFY( click_count == 0 ); + testWidget->setDown(false); + testWidget->setAutoRepeat(true); + QTest::keyClick(testWidget, Qt::Key_Enter); + QTest::qWait(300); + QVERIFY(!testWidget->isDown()); + QCOMPARE(toggle_count, 0); + QCOMPARE(press_count, 0); + QCOMPARE(release_count, 0); + QCOMPARE(click_count, 0); } void tst_QPushButton::pressed() { - QTest::keyPress( testWidget, ' ' ); - QCOMPARE( press_count, (uint)1 ); - QCOMPARE( release_count, (uint)0 ); + QTest::keyPress(testWidget, ' '); + QCOMPARE(press_count, 1); + QCOMPARE(release_count, 0); - QTest::keyRelease( testWidget, ' ' ); - QCOMPARE( press_count, (uint)1 ); - QCOMPARE( release_count, (uint)1 ); + QTest::keyRelease(testWidget, ' '); + QCOMPARE(press_count, 1); + QCOMPARE(release_count, 1); // Skip if ButtonPressKeys has Key_Enter const auto buttonPressKeys = QGuiApplicationPrivate::platformTheme() @@ -248,77 +251,77 @@ void tst_QPushButton::pressed() return; } - QTest::keyPress( testWidget,Qt::Key_Enter ); - QCOMPARE( press_count, (uint)1 ); - QCOMPARE( release_count, (uint)1 ); + QTest::keyPress(testWidget,Qt::Key_Enter); + QCOMPARE(press_count, 1); + QCOMPARE(release_count, 1); testWidget->setAutoDefault(true); - QTest::keyPress( testWidget,Qt::Key_Enter ); - QCOMPARE( press_count, (uint)2 ); - QCOMPARE( release_count, (uint)2 ); + QTest::keyPress(testWidget,Qt::Key_Enter); + QCOMPARE(press_count, 2); + QCOMPARE(release_count, 2); testWidget->setAutoDefault(false); } void tst_QPushButton::isCheckable() { - QVERIFY( !testWidget->isCheckable() ); + QVERIFY(!testWidget->isCheckable()); } void tst_QPushButton::setDown() { - testWidget->setDown( false ); - QVERIFY( !testWidget->isDown() ); + testWidget->setDown(false); + QVERIFY(!testWidget->isDown()); - testWidget->setDown( true ); - QVERIFY( testWidget->isDown() ); + testWidget->setDown(true); + QVERIFY(testWidget->isDown()); - testWidget->setDown( true ); - QTest::keyClick( testWidget, Qt::Key_Escape ); - QVERIFY( !testWidget->isDown() ); + testWidget->setDown(true); + QTest::keyClick(testWidget, Qt::Key_Escape); + QVERIFY(!testWidget->isDown()); } void tst_QPushButton::isChecked() { - testWidget->setDown( false ); - QVERIFY( !testWidget->isChecked() ); + testWidget->setDown(false); + QVERIFY(!testWidget->isChecked()); - testWidget->setDown( true ); - QVERIFY( !testWidget->isChecked() ); + testWidget->setDown(true); + QVERIFY(!testWidget->isChecked()); - testWidget->setDown( false ); + testWidget->setDown(false); testWidget->toggle(); - QVERIFY( testWidget->isChecked() == testWidget->isCheckable() ); + QCOMPARE(testWidget->isChecked(), testWidget->isCheckable()); } void tst_QPushButton::toggle() { // the pushbutton shouldn't toggle the button. testWidget->toggle(); - QVERIFY( testWidget->isChecked() == false ); + QCOMPARE(testWidget->isChecked(), false); } void tst_QPushButton::toggled() { // the pushbutton shouldn't send a toggled signal when we call the toggle slot. - QVERIFY( !testWidget->isCheckable() ); + QVERIFY(!testWidget->isCheckable()); testWidget->toggle(); - QVERIFY( toggle_count == 0 ); + QCOMPARE(toggle_count, 0); // do it again, just to be sure resetCounters(); testWidget->toggle(); - QVERIFY( toggle_count == 0 ); + QCOMPARE(toggle_count, 0); // finally check that we can toggle using the mouse resetCounters(); - QTest::mousePress( testWidget, Qt::LeftButton ); - QVERIFY( toggle_count == 0 ); - QVERIFY( click_count == 0 ); + QTest::mousePress(testWidget, Qt::LeftButton); + QCOMPARE(toggle_count, 0); + QCOMPARE(click_count, 0); - QTest::mouseRelease( testWidget, Qt::LeftButton ); - QVERIFY( click_count == 1 ); + QTest::mouseRelease(testWidget, Qt::LeftButton); + QCOMPARE(click_count, 1); } #if QT_CONFIG(shortcut) @@ -331,56 +334,55 @@ void tst_QPushButton::toggled() void tst_QPushButton::setAccel() { testWidget->setText("&AccelTest"); - QKeySequence seq( Qt::ALT | Qt::Key_A ); - testWidget->setShortcut( seq ); + QKeySequence seq(Qt::ALT | Qt::Key_A); + testWidget->setShortcut(seq); // The shortcut will not be activated unless the button is in a active // window and has focus - QApplication::setActiveWindow(testWidget); testWidget->setFocus(); QVERIFY(QTest::qWaitForWindowActive(testWidget)); - QTest::keyClick( testWidget, 'A', Qt::AltModifier ); - QTRY_VERIFY( click_count == 1 ); - QVERIFY( press_count == 1 ); - QVERIFY( release_count == 1 ); - QVERIFY( toggle_count == 0 ); + QTest::keyClick(testWidget, 'A', Qt::AltModifier); + QTRY_VERIFY(click_count == 1); + QCOMPARE(press_count, 1); + QCOMPARE(release_count, 1); + QCOMPARE(toggle_count, 0); // wait 200 ms because setAccel uses animateClick. // if we don't wait this may screw up a next test. QTest::qWait(200); - QTRY_VERIFY( !testWidget->isDown() ); + QTRY_VERIFY(!testWidget->isDown()); } #endif // QT_CONFIG(shortcut) void tst_QPushButton::clicked() { - QTest::mousePress( testWidget, Qt::LeftButton ); - QVERIFY( press_count == 1 ); - QVERIFY( release_count == 0 ); + QTest::mousePress(testWidget, Qt::LeftButton); + QCOMPARE(press_count, 1); + QCOMPARE(release_count, 0); - QTest::mouseRelease( testWidget, Qt::LeftButton ); - QCOMPARE( press_count, (uint)1 ); - QCOMPARE( release_count, (uint)1 ); + QTest::mouseRelease(testWidget, Qt::LeftButton); + QCOMPARE(press_count, 1); + QCOMPARE(release_count, 1); press_count = 0; release_count = 0; testWidget->setDown(false); for (uint i=0; i<10; i++) - QTest::mouseClick( testWidget, Qt::LeftButton ); - QCOMPARE( press_count, (uint)10 ); - QCOMPARE( release_count, (uint)10 ); + QTest::mouseClick(testWidget, Qt::LeftButton); + QCOMPARE(press_count, 10); + QCOMPARE(release_count, 10); } void tst_QPushButton::touchTap() { QTest::touchEvent(testWidget, m_touchScreen).press(0, QPoint(10, 10)); - QVERIFY( press_count == 1 ); - QVERIFY( release_count == 0 ); + QCOMPARE(press_count, 1); + QCOMPARE(release_count, 0); QTest::touchEvent(testWidget, m_touchScreen).release(0, QPoint(10, 10)); - QCOMPARE( press_count, (uint)1 ); - QCOMPARE( release_count, (uint)1 ); - QCOMPARE( click_count, (uint)1 ); + QCOMPARE(press_count, 1); + QCOMPARE(release_count, 1); + QCOMPARE(click_count, 1); press_count = 0; release_count = 0; @@ -390,26 +392,23 @@ void tst_QPushButton::touchTap() QTest::touchEvent(testWidget, m_touchScreen).press(0, QPoint(10, 10)); QTest::touchEvent(testWidget, m_touchScreen).release(0, QPoint(10, 10)); } - QCOMPARE( press_count, (uint)10 ); - QCOMPARE( release_count, (uint)10 ); - QCOMPARE( click_count, (uint)10 ); -} - -QPushButton *pb = 0; -void tst_QPushButton::helperSlotDelete() -{ - delete pb; - pb = 0; + QCOMPARE(press_count, 10); + QCOMPARE(release_count, 10); + QCOMPARE(click_count, 10); } void tst_QPushButton::popupCrash() { - pb = new QPushButton("foo"); + QPushButton *pb = new QPushButton("foo"); QMenu *menu = new QMenu("bar", pb); pb->setMenu(menu); - QTimer::singleShot(1000, this, SLOT(helperSlotDelete())); + QTimer::singleShot(1000, this, [&pb]{ + delete pb; + pb = nullptr; + }); pb->show(); pb->click(); + QTRY_COMPARE(pb, nullptr); } void tst_QPushButton::defaultAndAutoDefault() @@ -499,14 +498,14 @@ void tst_QPushButton::defaultAndAutoDefault() // Reparenting QVERIFY(button2.autoDefault()); - button2.setParent(0); + button2.setParent(nullptr); QVERIFY(!button2.autoDefault()); button2.setAutoDefault(false); button2.setParent(&dialog); QVERIFY(!button2.autoDefault()); button1.setAutoDefault(true); - button1.setParent(0); + button1.setParent(nullptr); QVERIFY(button1.autoDefault()); } } @@ -547,7 +546,7 @@ void tst_QPushButton::sizeHint() button->setParent(widget); button->sizeHint(); - widget->setParent(0); + widget->setParent(nullptr); delete dialog; button->setDefault(false); QCOMPARE(button->sizeHint(), initSizeHint); @@ -602,7 +601,7 @@ void tst_QPushButton::taskQTBUG_20191_shortcutWithKeypadModifer() dialog.setLayout(layout); dialog.show(); QVERIFY(QTest::qWaitForWindowExposed(&dialog)); - QApplication::setActiveWindow(&dialog); + QApplicationPrivate::setActiveWindow(&dialog); // add shortcut '5' to button1 and test with keyboard and keypad '5' keys QSignalSpy spy1(button1, SIGNAL(clicked())); @@ -611,7 +610,7 @@ void tst_QPushButton::taskQTBUG_20191_shortcutWithKeypadModifer() QTest::qWait(300); QTest::keyClick(&dialog, Qt::Key_5, Qt::KeypadModifier); QTest::qWait(300); - QCOMPARE(spy1.count(), 2); + QCOMPARE(spy1.size(), 2); // add shortcut 'keypad 5' to button2 spy1.clear(); @@ -621,8 +620,8 @@ void tst_QPushButton::taskQTBUG_20191_shortcutWithKeypadModifer() QTest::qWait(300); QTest::keyClick(&dialog, Qt::Key_5, Qt::KeypadModifier); QTest::qWait(300); - QCOMPARE(spy1.count(), 1); - QCOMPARE(spy2.count(), 1); + QCOMPARE(spy1.size(), 1); + QCOMPARE(spy2.size(), 1); // remove shortcut from button1 spy1.clear(); @@ -632,8 +631,8 @@ void tst_QPushButton::taskQTBUG_20191_shortcutWithKeypadModifer() QTest::qWait(300); QTest::keyClick(&dialog, Qt::Key_5, Qt::KeypadModifier); QTest::qWait(300); - QCOMPARE(spy1.count(), 0); - QCOMPARE(spy2.count(), 1); + QCOMPARE(spy1.size(), 0); + QCOMPARE(spy2.size(), 1); } #endif // QT_CONFIG(shortcut) @@ -649,7 +648,7 @@ void tst_QPushButton::emitReleasedAfterChange() dialog.setLayout(layout); dialog.show(); QVERIFY(QTest::qWaitForWindowExposed(&dialog)); - QApplication::setActiveWindow(&dialog); + QApplicationPrivate::setActiveWindow(&dialog); button1->setFocus(); QSignalSpy spy(button1, SIGNAL(released())); @@ -657,16 +656,16 @@ void tst_QPushButton::emitReleasedAfterChange() QVERIFY(button1->isDown()); QTest::keyClick(&dialog, Qt::Key_Tab); QVERIFY(!button1->isDown()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); button1->setFocus(); QTest::mousePress(button1, Qt::LeftButton); QVERIFY(button1->isDown()); button1->setEnabled(false); QVERIFY(!button1->isDown()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } /* @@ -744,22 +743,68 @@ void tst_QPushButton::mousePressAndMove() QSignalSpy releaseSpy(&button, &QAbstractButton::released); QTest::mousePress(&button, Qt::LeftButton); - QCOMPARE(pressSpy.count(), 1); - QCOMPARE(releaseSpy.count(), 0); + QCOMPARE(pressSpy.size(), 1); + QCOMPARE(releaseSpy.size(), 0); // mouse pressed and moving out QTest::mouseMove(&button, QPoint(100, 100)); // should emit released signal when the mouse is dragged out of boundary - QCOMPARE(pressSpy.count(), 1); - QCOMPARE(releaseSpy.count(), 1); + QCOMPARE(pressSpy.size(), 1); + QCOMPARE(releaseSpy.size(), 1); // mouse pressed and moving into QTest::mouseMove(&button, QPoint(10, 10)); // should emit pressed signal when the mouse is dragged into of boundary - QCOMPARE(pressSpy.count(), 2); - QCOMPARE(releaseSpy.count(), 1); + QCOMPARE(pressSpy.size(), 2); + QCOMPARE(releaseSpy.size(), 1); +} + +/* + Test checking that a QPushButton with a QMenu has a sunken style only + when the menu is open + QTBUG-120976 +*/ +void tst_QPushButton::reactToMenuClosed() +{ + // create a subclass of QPushButton to expose the initStyleOption method + class PushButton : public QPushButton { + public: + virtual void initStyleOption(QStyleOptionButton *option) const override + { + QPushButton::initStyleOption(option); + } + }; + + PushButton button; + QStyleOptionButton opt; + QMenu menu; + + // add a menu to the button + menu.addAction(tr("string")); + button.setMenu(&menu); + + // give the button a size and show it + button.setGeometry(0, 0, 50, 50); + button.show(); + QVERIFY(QTest::qWaitForWindowExposed(&button)); + + // click the button to open the menu + QTest::mouseClick(&button, Qt::LeftButton); + + // check the menu is visible and the button style is sunken + QTRY_VERIFY(menu.isVisible()); + button.initStyleOption(&opt); + QVERIFY(opt.state.testFlag(QStyle::StateFlag::State_Sunken)); + + // close the menu + menu.close(); + + // check the menu isn't visible and the style isn't sunken + QTRY_VERIFY(!menu.isVisible()); + button.initStyleOption(&opt); + QVERIFY(!opt.state.testFlag(QStyle::StateFlag::State_Sunken)); } QTEST_MAIN(tst_QPushButton) diff --git a/tests/auto/widgets/widgets/qradiobutton/CMakeLists.txt b/tests/auto/widgets/widgets/qradiobutton/CMakeLists.txt index e487765cf0..ce016975c8 100644 --- a/tests/auto/widgets/widgets/qradiobutton/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qradiobutton/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qradiobutton.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qradiobutton Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qradiobutton LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qradiobutton SOURCES tst_qradiobutton.cpp diff --git a/tests/auto/widgets/widgets/qradiobutton/tst_qradiobutton.cpp b/tests/auto/widgets/widgets/qradiobutton/tst_qradiobutton.cpp index 2fcf2e5545..144d91e9f2 100644 --- a/tests/auto/widgets/widgets/qradiobutton/tst_qradiobutton.cpp +++ b/tests/auto/widgets/widgets/qradiobutton/tst_qradiobutton.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/widgets/qrhiwidget/CMakeLists.txt b/tests/auto/widgets/widgets/qrhiwidget/CMakeLists.txt new file mode 100644 index 0000000000..f8d18bcf53 --- /dev/null +++ b/tests/auto/widgets/widgets/qrhiwidget/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qrhiwidget LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +file(GLOB_RECURSE qrhiwidget_resource_files + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" + data/* +) + +qt_internal_add_test(tst_qrhiwidget + SOURCES + tst_qrhiwidget.cpp + LIBRARIES + Qt::CorePrivate + Qt::Gui + Qt::GuiPrivate + Qt::Widgets + TESTDATA ${qrhiwidget_resource_files} + BUILTIN_TESTDATA +) diff --git a/tests/auto/widgets/widgets/qrhiwidget/data/simple.frag b/tests/auto/widgets/widgets/qrhiwidget/data/simple.frag new file mode 100644 index 0000000000..2aa500e09a --- /dev/null +++ b/tests/auto/widgets/widgets/qrhiwidget/data/simple.frag @@ -0,0 +1,8 @@ +#version 440 + +layout(location = 0) out vec4 fragColor; + +void main() +{ + fragColor = vec4(1.0, 0.0, 0.0, 1.0); +} diff --git a/tests/auto/widgets/widgets/qrhiwidget/data/simple.frag.qsb b/tests/auto/widgets/widgets/qrhiwidget/data/simple.frag.qsb Binary files differnew file mode 100644 index 0000000000..40d0a296ac --- /dev/null +++ b/tests/auto/widgets/widgets/qrhiwidget/data/simple.frag.qsb diff --git a/tests/auto/widgets/widgets/qrhiwidget/data/simple.vert b/tests/auto/widgets/widgets/qrhiwidget/data/simple.vert new file mode 100644 index 0000000000..6b954cdaec --- /dev/null +++ b/tests/auto/widgets/widgets/qrhiwidget/data/simple.vert @@ -0,0 +1,8 @@ +#version 440 + +layout(location = 0) in vec4 position; + +void main() +{ + gl_Position = position; +} diff --git a/tests/auto/widgets/widgets/qrhiwidget/data/simple.vert.qsb b/tests/auto/widgets/widgets/qrhiwidget/data/simple.vert.qsb Binary files differnew file mode 100644 index 0000000000..5b7fd39668 --- /dev/null +++ b/tests/auto/widgets/widgets/qrhiwidget/data/simple.vert.qsb diff --git a/tests/auto/widgets/widgets/qrhiwidget/tst_qrhiwidget.cpp b/tests/auto/widgets/widgets/qrhiwidget/tst_qrhiwidget.cpp new file mode 100644 index 0000000000..7a102180e7 --- /dev/null +++ b/tests/auto/widgets/widgets/qrhiwidget/tst_qrhiwidget.cpp @@ -0,0 +1,834 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QtWidgets/QRhiWidget> +#include <QtGui/QPainter> +#include <QTest> +#include <QSignalSpy> +#include <private/qguiapplication_p.h> +#include <qpa/qplatformintegration.h> +#include <rhi/qrhi.h> + +#include <QApplication> +#include <QFile> +#include <QVBoxLayout> +#include <QScrollArea> + +#if QT_CONFIG(vulkan) +#include <private/qvulkandefaultinstance_p.h> +#endif + +class tst_QRhiWidget : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void create_data(); + void create(); + void noCreate(); + void simple_data(); + void simple(); + void msaa_data(); + void msaa(); + void fixedSize_data(); + void fixedSize(); + void autoRt_data(); + void autoRt(); + void reparent_data(); + void reparent(); + void grabFramebufferWhileStillInvisible_data(); + void grabFramebufferWhileStillInvisible(); + void grabViaQWidgetGrab_data(); + void grabViaQWidgetGrab(); + void mirror_data(); + void mirror(); + +private: + void testData(); +}; + +void tst_QRhiWidget::initTestCase() +{ + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RhiBasedRendering)) + QSKIP("RhiBasedRendering capability is reported as unsupported on this platform."); + + qputenv("QT_RHI_LEAK_CHECK", "1"); +} + +void tst_QRhiWidget::testData() +{ + QTest::addColumn<QRhiWidget::Api>("api"); + +#ifndef Q_OS_WEBOS + QTest::newRow("Null") << QRhiWidget::Api::Null; +#endif + +#if QT_CONFIG(opengl) + if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) + QTest::newRow("OpenGL") << QRhiWidget::Api::OpenGL; +#endif + +#if QT_CONFIG(vulkan) + // Have to probe to be sure Vulkan is actually working (the test cases + // themselves will assume QRhi init succeeds). + if (QVulkanDefaultInstance::instance()) { + QRhiVulkanInitParams vulkanInitParams; + vulkanInitParams.inst = QVulkanDefaultInstance::instance(); + if (QRhi::probe(QRhi::Vulkan, &vulkanInitParams)) + QTest::newRow("Vulkan") << QRhiWidget::Api::Vulkan; + } +#endif + +#if QT_CONFIG(metal) + QRhiMetalInitParams metalInitParams; + if (QRhi::probe(QRhi::Metal, &metalInitParams)) + QTest::newRow("Metal") << QRhiWidget::Api::Metal; +#endif + +#ifdef Q_OS_WIN + QTest::newRow("D3D11") << QRhiWidget::Api::Direct3D11; + // D3D12 needs to be probed too due to being disabled if the SDK headers + // are too old (clang, mingw). + QRhiD3D12InitParams d3d12InitParams; + if (QRhi::probe(QRhi::D3D12, &d3d12InitParams)) + QTest::newRow("D3D12") << QRhiWidget::Api::Direct3D12; +#endif +} + +void tst_QRhiWidget::create_data() +{ + testData(); +} + +void tst_QRhiWidget::create() +{ + QFETCH(QRhiWidget::Api, api); + + { + QRhiWidget w; + w.setApi(api); + w.resize(320, 240); + w.show(); + QVERIFY(QTest::qWaitForWindowExposed(&w)); + } + + { + QWidget topLevel; + topLevel.resize(320, 240); + QRhiWidget *w = new QRhiWidget(&topLevel); + w->setApi(api); + w->resize(100, 100); + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + } +} + +void tst_QRhiWidget::noCreate() +{ + // Now try something that is guaranteed to fail. + // E.g. try using Metal on Windows. + // The error signal should be emitted. The frame signal should not. +#ifdef Q_OS_WIN + qDebug("Warnings will be printed below, this is as expected"); + QRhiWidget rhiWidget; + rhiWidget.setApi(QRhiWidget::Api::Metal); + QSignalSpy frameSpy(&rhiWidget, &QRhiWidget::frameSubmitted); + QSignalSpy errorSpy(&rhiWidget, &QRhiWidget::renderFailed); + rhiWidget.resize(320, 240); + rhiWidget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&rhiWidget)); + QTRY_VERIFY(errorSpy.count() > 0); + QCOMPARE(frameSpy.count(), 0); +#endif +} + +static QShader getShader(const QString &name) +{ + QFile f(name); + return f.open(QIODevice::ReadOnly) ? QShader::fromSerialized(f.readAll()) : QShader(); +} + +static bool submitResourceUpdates(QRhi *rhi, QRhiResourceUpdateBatch *batch) +{ + QRhiCommandBuffer *cb = nullptr; + QRhi::FrameOpResult result = rhi->beginOffscreenFrame(&cb); + if (result != QRhi::FrameOpSuccess) { + qWarning("beginOffscreenFrame returned %d", result); + return false; + } + if (!cb) { + qWarning("No command buffer from beginOffscreenFrame"); + return false; + } + cb->resourceUpdate(batch); + rhi->endOffscreenFrame(); + return true; +} + +inline bool imageRGBAEquals(const QImage &a, const QImage &b, int maxFuzz = 1) +{ + if (a.size() != b.size()) + return false; + + const QImage image0 = a.convertToFormat(QImage::Format_RGBA8888_Premultiplied); + const QImage image1 = b.convertToFormat(QImage::Format_RGBA8888_Premultiplied); + + const int width = image0.width(); + const int height = image0.height(); + for (int y = 0; y < height; ++y) { + const quint32 *p0 = reinterpret_cast<const quint32 *>(image0.constScanLine(y)); + const quint32 *p1 = reinterpret_cast<const quint32 *>(image1.constScanLine(y)); + int x = width - 1; + while (x-- >= 0) { + const QRgb c0(*p0++); + const QRgb c1(*p1++); + const int red = qAbs(qRed(c0) - qRed(c1)); + const int green = qAbs(qGreen(c0) - qGreen(c1)); + const int blue = qAbs(qBlue(c0) - qBlue(c1)); + const int alpha = qAbs(qAlpha(c0) - qAlpha(c1)); + if (red > maxFuzz || green > maxFuzz || blue > maxFuzz || alpha > maxFuzz) + return false; + } + } + + return true; +} + +class SimpleRhiWidget : public QRhiWidget +{ +public: + SimpleRhiWidget(int sampleCount = 1, QWidget *parent = nullptr) + : QRhiWidget(parent), + m_sampleCount(sampleCount) + { } + + ~SimpleRhiWidget() + { + delete m_rt; + delete m_rp; + } + + void initialize(QRhiCommandBuffer *cb) override; + void render(QRhiCommandBuffer *cb) override; + void releaseResources() override; + + int m_sampleCount; + QRhi *m_rhi = nullptr; + std::unique_ptr<QRhiBuffer> m_vbuf; + std::unique_ptr<QRhiBuffer> m_ubuf; + std::unique_ptr<QRhiShaderResourceBindings> m_srb; + std::unique_ptr<QRhiGraphicsPipeline> m_pipeline; + QRhiTextureRenderTarget *m_rt = nullptr; // used when autoRenderTarget is off + QRhiRenderPassDescriptor *m_rp = nullptr; // used when autoRenderTarget is off + + friend class tst_QRhiWidget; +}; + +void SimpleRhiWidget::initialize(QRhiCommandBuffer *cb) +{ + if (m_rhi != rhi()) { + m_pipeline.reset(); + m_rhi = rhi(); + } + + if (!m_pipeline) { + if (!isAutoRenderTargetEnabled()) { + delete m_rt; + delete m_rp; + QRhiTextureRenderTargetDescription rtDesc; + if (colorTexture()) { + rtDesc.setColorAttachments({ colorTexture() }); + } else if (msaaColorBuffer()) { + QRhiColorAttachment att; + att.setRenderBuffer(msaaColorBuffer()); + rtDesc.setColorAttachments({ att }); + } + m_rt = m_rhi->newTextureRenderTarget(rtDesc); + m_rp = m_rt->newCompatibleRenderPassDescriptor(); + m_rt->setRenderPassDescriptor(m_rp); + m_rt->create(); + } + + static float vertexData[] = { + 0, 1, + -1, -1, + 1, -1 + }; + + m_vbuf.reset(m_rhi->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, sizeof(vertexData))); + m_vbuf->create(); + + m_ubuf.reset(m_rhi->newBuffer(QRhiBuffer::Dynamic, QRhiBuffer::UniformBuffer, 64)); + m_ubuf->create(); + + m_srb.reset(m_rhi->newShaderResourceBindings()); + m_srb->create(); + + m_pipeline.reset(m_rhi->newGraphicsPipeline()); + m_pipeline->setShaderStages({ + { QRhiShaderStage::Vertex, getShader(QLatin1String(":/data/simple.vert.qsb")) }, + { QRhiShaderStage::Fragment, getShader(QLatin1String(":/data/simple.frag.qsb")) } + }); + QRhiVertexInputLayout inputLayout; + inputLayout.setBindings({ + { 2 * sizeof(float) } + }); + inputLayout.setAttributes({ + { 0, 0, QRhiVertexInputAttribute::Float2, 0 } + }); + m_pipeline->setSampleCount(m_sampleCount); + m_pipeline->setVertexInputLayout(inputLayout); + m_pipeline->setShaderResourceBindings(m_srb.get()); + m_pipeline->setRenderPassDescriptor(renderTarget() ? renderTarget()->renderPassDescriptor() : m_rp); + m_pipeline->create(); + + QRhiResourceUpdateBatch *resourceUpdates = m_rhi->nextResourceUpdateBatch(); + resourceUpdates->uploadStaticBuffer(m_vbuf.get(), vertexData); + cb->resourceUpdate(resourceUpdates); + } +} + +void SimpleRhiWidget::render(QRhiCommandBuffer *cb) +{ + const QSize outputSize = colorTexture() ? colorTexture()->pixelSize() : msaaColorBuffer()->pixelSize(); + if (renderTarget()) { + QCOMPARE(outputSize, renderTarget()->pixelSize()); + if (rhi()->backend() != QRhi::Null && rhi()->supportedSampleCounts().contains(m_sampleCount)) + QCOMPARE(m_sampleCount, renderTarget()->sampleCount()); + } + + const QColor clearColor = QColor::fromRgbF(0.4f, 0.7f, 0.0f, 1.0f); + cb->beginPass(renderTarget() ? renderTarget() : m_rt, clearColor, { 1.0f, 0 }); + cb->setGraphicsPipeline(m_pipeline.get()); + cb->setViewport(QRhiViewport(0, 0, outputSize.width(), outputSize.height())); + cb->setShaderResources(); + const QRhiCommandBuffer::VertexInput vbufBinding(m_vbuf.get(), 0); + cb->setVertexInput(0, 1, &vbufBinding); + cb->draw(3); + cb->endPass(); +} + +void SimpleRhiWidget::releaseResources() +{ + m_pipeline.reset(); + m_srb.reset(); + m_ubuf.reset(); + m_vbuf.reset(); + +} + +void tst_QRhiWidget::simple_data() +{ + testData(); +} + +void tst_QRhiWidget::simple() +{ + QFETCH(QRhiWidget::Api, api); + + SimpleRhiWidget *rhiWidget = new SimpleRhiWidget; + rhiWidget->setApi(api); + QSignalSpy frameSpy(rhiWidget, &QRhiWidget::frameSubmitted); + QSignalSpy errorSpy(rhiWidget, &QRhiWidget::renderFailed); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(rhiWidget); + + QWidget w; + w.setLayout(layout); + w.resize(1280, 720); + w.show(); + QVERIFY(QTest::qWaitForWindowExposed(&w)); + + QTRY_VERIFY(frameSpy.count() > 0); + QCOMPARE(errorSpy.count(), 0); + + QCOMPARE(rhiWidget->sampleCount(), 1); + QCOMPARE(rhiWidget->colorBufferFormat(), QRhiWidget::TextureFormat::RGBA8); + QVERIFY(rhiWidget->isAutoRenderTargetEnabled()); + + // Pull out the QRhiTexture (we know colorTexture() and rhi() and friends + // are all there even outside initialize() and render(), even though this + // is not quite documented), and read it back. + QRhiTexture *backingTexture = rhiWidget->colorTexture(); + QVERIFY(backingTexture); + QCOMPARE(backingTexture->format(), QRhiTexture::RGBA8); + QVERIFY(rhiWidget->depthStencilBuffer()); + QVERIFY(rhiWidget->renderTarget()); + QVERIFY(!rhiWidget->resolveTexture()); + QRhi *rhi = rhiWidget->rhi(); + QVERIFY(rhi); + + switch (api) { + case QRhiWidget::Api::OpenGL: + QCOMPARE(rhi->backend(), QRhi::OpenGLES2); + break; + case QRhiWidget::Api::Metal: + QCOMPARE(rhi->backend(), QRhi::Metal); + break; + case QRhiWidget::Api::Vulkan: + QCOMPARE(rhi->backend(), QRhi::Vulkan); + break; + case QRhiWidget::Api::Direct3D11: + QCOMPARE(rhi->backend(), QRhi::D3D11); + break; + case QRhiWidget::Api::Direct3D12: + QCOMPARE(rhi->backend(), QRhi::D3D12); + break; + case QRhiWidget::Api::Null: + QCOMPARE(rhi->backend(), QRhi::Null); + break; + default: + break; + } + + const int maxFuzz = 1; + QImage resultOne; + if (rhi->backend() != QRhi::Null) { + QRhiReadbackResult readResult; + bool readCompleted = false; + readResult.completed = [&readCompleted] { readCompleted = true; }; + QRhiResourceUpdateBatch *rub = rhi->nextResourceUpdateBatch(); + rub->readBackTexture(backingTexture, &readResult); + QVERIFY(submitResourceUpdates(rhi, rub)); + QVERIFY(readCompleted); + + QImage wrapperImage(reinterpret_cast<const uchar *>(readResult.data.constData()), + readResult.pixelSize.width(), readResult.pixelSize.height(), + QImage::Format_RGBA8888); + if (rhi->isYUpInFramebuffer()) + resultOne = wrapperImage.mirrored(); + else + resultOne = wrapperImage.copy(); + + // result is now a red triangle upon greenish background, where the + // triangle's edges are (0, 1), (-1, -1), and (1, -1). + // It's upside down with Vulkan (Y is not corrected, clipSpaceCorrMatrix() is not used), + // but that won't matter for the test. + + // Check that the center is a red pixel. + QRgb c = resultOne.pixel(resultOne.width() / 2, resultOne.height() / 2); + QVERIFY(qRed(c) >= 255 - maxFuzz); + QVERIFY(qGreen(c) <= maxFuzz); + QVERIFY(qBlue(c) <= maxFuzz); + } + + // Now through grabFramebuffer(). + QImage resultTwo; + if (rhi->backend() != QRhi::Null) { + resultTwo = rhiWidget->grabFramebuffer(); + QCOMPARE(errorSpy.count(), 0); + QVERIFY(!resultTwo.isNull()); + QRgb c = resultTwo.pixel(resultTwo.width() / 2, resultTwo.height() / 2); + QVERIFY(qRed(c) >= 255 - maxFuzz); + QVERIFY(qGreen(c) <= maxFuzz); + QVERIFY(qBlue(c) <= maxFuzz); + } + + // Check we got the same result from our manual readback and when the + // texture was rendered to again and grabFramebuffer() was called. + QVERIFY(imageRGBAEquals(resultOne, resultTwo, maxFuzz)); +} + +void tst_QRhiWidget::msaa_data() +{ + testData(); +} + +void tst_QRhiWidget::msaa() +{ + QFETCH(QRhiWidget::Api, api); + + const int SAMPLE_COUNT = 4; + SimpleRhiWidget *rhiWidget = new SimpleRhiWidget(SAMPLE_COUNT); + rhiWidget->setApi(api); + rhiWidget->setSampleCount(SAMPLE_COUNT); + QSignalSpy frameSpy(rhiWidget, &QRhiWidget::frameSubmitted); + QSignalSpy errorSpy(rhiWidget, &QRhiWidget::renderFailed); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(rhiWidget); + + QWidget w; + w.setLayout(layout); + w.resize(1280, 720); + w.show(); + QVERIFY(QTest::qWaitForWindowExposed(&w)); + + QTRY_VERIFY(frameSpy.count() > 0); + QCOMPARE(errorSpy.count(), 0); + + QCOMPARE(rhiWidget->sampleCount(), 4); + QCOMPARE(rhiWidget->colorBufferFormat(), QRhiWidget::TextureFormat::RGBA8); + QVERIFY(!rhiWidget->colorTexture()); + QVERIFY(rhiWidget->msaaColorBuffer()); + QVERIFY(rhiWidget->depthStencilBuffer()); + QVERIFY(rhiWidget->renderTarget()); + QVERIFY(rhiWidget->resolveTexture()); + QCOMPARE(rhiWidget->resolveTexture()->format(), QRhiTexture::RGBA8); + QRhi *rhi = rhiWidget->rhi(); + QVERIFY(rhi); + + if (rhi->backend() != QRhi::Null) { + QRhiReadbackResult readResult; + QRhiResourceUpdateBatch *rub = rhi->nextResourceUpdateBatch(); + rub->readBackTexture(rhiWidget->resolveTexture(), &readResult); + QVERIFY(submitResourceUpdates(rhi, rub)); + + QImage wrapperImage(reinterpret_cast<const uchar *>(readResult.data.constData()), + readResult.pixelSize.width(), readResult.pixelSize.height(), + QImage::Format_RGBA8888); + QImage result; + if (rhi->isYUpInFramebuffer()) + result = wrapperImage.mirrored(); + else + result = wrapperImage.copy(); + + // Check that the center is a red pixel. + const int maxFuzz = 1; + QRgb c = result.pixel(result.width() / 2, result.height() / 2); + QVERIFY(qRed(c) >= 255 - maxFuzz); + QVERIFY(qGreen(c) <= maxFuzz); + QVERIFY(qBlue(c) <= maxFuzz); + } + + // See if switching back and forth works. + frameSpy.clear(); + rhiWidget->m_pipeline.reset(); + rhiWidget->m_sampleCount = 1; + rhiWidget->setSampleCount(1); + QTRY_VERIFY(frameSpy.count() > 0); + QCOMPARE(errorSpy.count(), 0); + QVERIFY(rhiWidget->colorTexture()); + QVERIFY(!rhiWidget->msaaColorBuffer()); + + frameSpy.clear(); + rhiWidget->m_pipeline.reset(); + rhiWidget->m_sampleCount = SAMPLE_COUNT; + rhiWidget->setSampleCount(SAMPLE_COUNT); + QTRY_VERIFY(frameSpy.count() > 0); + QCOMPARE(errorSpy.count(), 0); + QVERIFY(!rhiWidget->colorTexture()); + QVERIFY(rhiWidget->msaaColorBuffer()); +} + +void tst_QRhiWidget::fixedSize_data() +{ + testData(); +} + +void tst_QRhiWidget::fixedSize() +{ + QFETCH(QRhiWidget::Api, api); + + SimpleRhiWidget *rhiWidget = new SimpleRhiWidget; + rhiWidget->setApi(api); + QSignalSpy frameSpy(rhiWidget, &QRhiWidget::frameSubmitted); + QSignalSpy errorSpy(rhiWidget, &QRhiWidget::renderFailed); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(rhiWidget); + + rhiWidget->setFixedColorBufferSize(QSize(320, 200)); + + QWidget w; + w.setLayout(layout); + w.resize(1280, 720); + w.show(); + QVERIFY(QTest::qWaitForWindowExposed(&w)); + + QTRY_VERIFY(frameSpy.count() > 0); + QCOMPARE(errorSpy.count(), 0); + + QVERIFY(rhiWidget->rhi()); + QVERIFY(rhiWidget->colorTexture()); + QCOMPARE(rhiWidget->colorTexture()->pixelSize(), QSize(320, 200)); + QVERIFY(rhiWidget->depthStencilBuffer()); + QCOMPARE(rhiWidget->depthStencilBuffer()->pixelSize(), QSize(320, 200)); + QVERIFY(rhiWidget->renderTarget()); + QVERIFY(!rhiWidget->resolveTexture()); + + frameSpy.clear(); + rhiWidget->setFixedColorBufferSize(640, 480); // should also trigger update() + QTRY_VERIFY(frameSpy.count() > 0); + + QVERIFY(rhiWidget->colorTexture()); + QCOMPARE(rhiWidget->colorTexture()->pixelSize(), QSize(640, 480)); + QVERIFY(rhiWidget->depthStencilBuffer()); + QCOMPARE(rhiWidget->depthStencilBuffer()->pixelSize(), QSize(640, 480)); + + frameSpy.clear(); + rhiWidget->setFixedColorBufferSize(QSize()); + QTRY_VERIFY(frameSpy.count() > 0); + + QVERIFY(rhiWidget->colorTexture()); + QVERIFY(rhiWidget->colorTexture()->pixelSize() != QSize(640, 480)); + QVERIFY(rhiWidget->depthStencilBuffer()); + QVERIFY(rhiWidget->depthStencilBuffer()->pixelSize() != QSize(640, 480)); +} + +void tst_QRhiWidget::autoRt_data() +{ + testData(); +} + +void tst_QRhiWidget::autoRt() +{ + QFETCH(QRhiWidget::Api, api); + + SimpleRhiWidget *rhiWidget = new SimpleRhiWidget; + rhiWidget->setApi(api); + QVERIFY(rhiWidget->isAutoRenderTargetEnabled()); + rhiWidget->setAutoRenderTarget(false); + QVERIFY(!rhiWidget->isAutoRenderTargetEnabled()); + QSignalSpy frameSpy(rhiWidget, &QRhiWidget::frameSubmitted); + QSignalSpy errorSpy(rhiWidget, &QRhiWidget::renderFailed); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(rhiWidget); + + QWidget w; + w.setLayout(layout); + w.resize(1280, 720); + w.show(); + QVERIFY(QTest::qWaitForWindowExposed(&w)); + + QTRY_VERIFY(frameSpy.count() > 0); + QCOMPARE(errorSpy.count(), 0); + + QVERIFY(rhiWidget->rhi()); + QVERIFY(rhiWidget->colorTexture()); + QVERIFY(!rhiWidget->depthStencilBuffer()); + QVERIFY(!rhiWidget->renderTarget()); + QVERIFY(!rhiWidget->resolveTexture()); + + QVERIFY(rhiWidget->m_rt); + QVERIFY(rhiWidget->m_rp); + QCOMPARE(rhiWidget->m_rt->description().cbeginColorAttachments()->texture(), rhiWidget->colorTexture()); + + frameSpy.clear(); + // do something that triggers creating a new backing texture + rhiWidget->setFixedColorBufferSize(QSize(320, 200)); + QTRY_VERIFY(frameSpy.count() > 0); + + QVERIFY(rhiWidget->colorTexture()); + QCOMPARE(rhiWidget->m_rt->description().cbeginColorAttachments()->texture(), rhiWidget->colorTexture()); +} + +void tst_QRhiWidget::reparent_data() +{ + testData(); +} + +void tst_QRhiWidget::reparent() +{ + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows)) + QSKIP("MultipleWindows capability is reported as unsupported, skipping reparenting test."); + + QFETCH(QRhiWidget::Api, api); + + QWidget *windowOne = new QWidget; + windowOne->resize(1280, 720); + + SimpleRhiWidget *rhiWidget = new SimpleRhiWidget(1); + rhiWidget->setApi(api); + rhiWidget->resize(800, 600); + QSignalSpy frameSpy(rhiWidget, &QRhiWidget::frameSubmitted); + QSignalSpy errorSpy(rhiWidget, &QRhiWidget::renderFailed); + + rhiWidget->show(); + QVERIFY(QTest::qWaitForWindowExposed(rhiWidget)); + QTRY_VERIFY(frameSpy.count() > 0); + QCOMPARE(errorSpy.count(), 0); + + frameSpy.clear(); + rhiWidget->setParent(windowOne); + windowOne->show(); + QVERIFY(QTest::qWaitForWindowExposed(windowOne)); + QTRY_VERIFY(frameSpy.count() > 0); + QCOMPARE(errorSpy.count(), 0); + + frameSpy.clear(); + QWidget windowTwo; + windowTwo.resize(1280, 720); + + rhiWidget->setParent(&windowTwo); + + // There's nothing saying the old top-level parent is going to be around, + // which is interesting wrt to its QRhi and resources created with that; + // exercise this. + delete windowOne; + + windowTwo.show(); + QVERIFY(QTest::qWaitForWindowExposed(&windowTwo)); + QTRY_VERIFY(frameSpy.count() > 0); + QCOMPARE(errorSpy.count(), 0); + + // now reparent after show() has already been called + frameSpy.clear(); + QWidget windowThree; + windowThree.resize(1280, 720); + windowThree.show(); + QVERIFY(QTest::qWaitForWindowExposed(&windowThree)); + + rhiWidget->setParent(&windowThree); + // this case needs a show() on rhiWidget + rhiWidget->show(); + + QTRY_VERIFY(frameSpy.count() > 0); + QCOMPARE(errorSpy.count(), 0); +} + +void tst_QRhiWidget::grabFramebufferWhileStillInvisible_data() +{ + testData(); +} + +void tst_QRhiWidget::grabFramebufferWhileStillInvisible() +{ + QFETCH(QRhiWidget::Api, api); + + const int maxFuzz = 1; + + SimpleRhiWidget w; + w.setApi(api); + w.resize(1280, 720); + QSignalSpy errorSpy(&w, &QRhiWidget::renderFailed); + + QImage image = w.grabFramebuffer(); // creates its own QRhi just to render offscreen + QVERIFY(!image.isNull()); + QVERIFY(w.rhi()); + QVERIFY(w.colorTexture()); + QCOMPARE(errorSpy.count(), 0); + if (api != QRhiWidget::Api::Null) { + QRgb c = image.pixel(image.width() / 2, image.height() / 2); + QVERIFY(qRed(c) >= 255 - maxFuzz); + QVERIFY(qGreen(c) <= maxFuzz); + QVERIFY(qBlue(c) <= maxFuzz); + } + + // Make the window visible, this under the hood drops the QRhiWidget's + // own QRhi and attaches to the backingstore's. + QSignalSpy frameSpy(&w, &QRhiWidget::frameSubmitted); + w.show(); + QVERIFY(QTest::qWaitForWindowExposed(&w)); + QTRY_VERIFY(frameSpy.count() > 0); + + QCOMPARE(errorSpy.count(), 0); + + if (api != QRhiWidget::Api::Null) { + QRhiReadbackResult readResult; + QRhiResourceUpdateBatch *rub = w.rhi()->nextResourceUpdateBatch(); + rub->readBackTexture(w.colorTexture(), &readResult); + QVERIFY(submitResourceUpdates(w.rhi(), rub)); + QImage wrapperImage(reinterpret_cast<const uchar *>(readResult.data.constData()), + readResult.pixelSize.width(), readResult.pixelSize.height(), + QImage::Format_RGBA8888); + if (w.rhi()->isYUpInFramebuffer()) + image = wrapperImage.mirrored(); + else + image = wrapperImage.copy(); + QRgb c = image.pixel(image.width() / 2, image.height() / 2); + QVERIFY(qRed(c) >= 255 - maxFuzz); + QVERIFY(qGreen(c) <= maxFuzz); + QVERIFY(qBlue(c) <= maxFuzz); + } +} + +void tst_QRhiWidget::grabViaQWidgetGrab_data() +{ + testData(); +} + +void tst_QRhiWidget::grabViaQWidgetGrab() +{ + QFETCH(QRhiWidget::Api, api); + + SimpleRhiWidget w; + w.setApi(api); + w.resize(1280, 720); + QSignalSpy frameSpy(&w, &QRhiWidget::frameSubmitted); + w.show(); + QVERIFY(QTest::qWaitForWindowExposed(&w)); + QTRY_VERIFY(frameSpy.count() > 0); + + QImage image = w.grab().toImage(); + + if (w.rhi()->backend() != QRhi::Null) { + // It's upside down with Vulkan (Y is not corrected, clipSpaceCorrMatrix() is not used), + // but that won't matter for the test. + QRgb c = image.pixel(image.width() / 2, image.height() / 2); + const int maxFuzz = 1; + QVERIFY(qRed(c) >= 255 - maxFuzz); + QVERIFY(qGreen(c) <= maxFuzz); + QVERIFY(qBlue(c) <= maxFuzz); + } +} + +void tst_QRhiWidget::mirror_data() +{ + testData(); +} + +void tst_QRhiWidget::mirror() +{ + QFETCH(QRhiWidget::Api, api); + + SimpleRhiWidget *rhiWidget = new SimpleRhiWidget; + rhiWidget->setApi(api); + QVERIFY(!rhiWidget->isMirrorVerticallyEnabled()); + + QSignalSpy frameSpy(rhiWidget, &QRhiWidget::frameSubmitted); + QSignalSpy errorSpy(rhiWidget, &QRhiWidget::renderFailed); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(rhiWidget); + QWidget w; + w.setLayout(layout); + w.resize(1280, 720); + w.show(); + QVERIFY(QTest::qWaitForWindowExposed(&w)); + + QTRY_VERIFY(frameSpy.count() > 0); + QCOMPARE(errorSpy.count(), 0); + + frameSpy.clear(); + rhiWidget->setMirrorVertically(true); + QVERIFY(rhiWidget->isMirrorVerticallyEnabled()); + QTRY_VERIFY(frameSpy.count() > 0); + QCOMPARE(errorSpy.count(), 0); + + if (api != QRhiWidget::Api::Null) { + QRhi *rhi = rhiWidget->rhi(); + QRhiReadbackResult readResult; + QRhiResourceUpdateBatch *rub = rhi->nextResourceUpdateBatch(); + rub->readBackTexture(rhiWidget->colorTexture(), &readResult); + QVERIFY(submitResourceUpdates(rhi, rub)); + QImage wrapperImage(reinterpret_cast<const uchar *>(readResult.data.constData()), + readResult.pixelSize.width(), readResult.pixelSize.height(), + QImage::Format_RGBA8888); + QImage image; + if (rhi->isYUpInFramebuffer()) + image = wrapperImage.mirrored(); + else + image = wrapperImage.copy(); + + const int maxFuzz = 1; + QRgb c = image.pixel(50, 5); + if (api != QRhiWidget::Api::Vulkan) { + // this should be the background (greenish), not the red triangle + QVERIFY(qGreen(c) > qRed(c)); + } else { + // remember that Vulkan is upside down due to not correcting for Y down in NDC + // hence this is red + QVERIFY(qRed(c) >= 255 - maxFuzz); + QVERIFY(qGreen(c) <= maxFuzz); + } + QVERIFY(qBlue(c) <= maxFuzz); + } +} + +QTEST_MAIN(tst_QRhiWidget) + +#include "tst_qrhiwidget.moc" diff --git a/tests/auto/widgets/widgets/qscrollarea/CMakeLists.txt b/tests/auto/widgets/widgets/qscrollarea/CMakeLists.txt index 574437d876..5e84614407 100644 --- a/tests/auto/widgets/widgets/qscrollarea/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qscrollarea/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qscrollarea.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qscrollarea Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qscrollarea LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qscrollarea SOURCES tst_qscrollarea.cpp diff --git a/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp b/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp index edb59b5a7a..87a623b223 100644 --- a/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp +++ b/tests/auto/widgets/widgets/qscrollarea/tst_qscrollarea.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/widgets/qscrollbar/CMakeLists.txt b/tests/auto/widgets/widgets/qscrollbar/CMakeLists.txt index d1e854b875..23e31327e1 100644 --- a/tests/auto/widgets/widgets/qscrollbar/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qscrollbar/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qscrollbar.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qscrollbar Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qscrollbar LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qscrollbar SOURCES tst_qscrollbar.cpp diff --git a/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp b/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp index a6e39bf273..fc836dec4a 100644 --- a/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp +++ b/tests/auto/widgets/widgets/qscrollbar/tst_qscrollbar.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -90,7 +90,7 @@ void tst_QScrollBar::task_209492() QSignalSpy spy(verticalScrollBar, SIGNAL(actionTriggered(int))); QCOMPARE(scrollArea.scrollCount, 0); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); // Simulate a mouse click on the "scroll down button". const QPoint pressPoint(verticalScrollBar->width() / 2, verticalScrollBar->height() - 10); @@ -109,7 +109,7 @@ void tst_QScrollBar::task_209492() QSKIP("The result depends on system setting and is not relevant on Mac"); #endif QCOMPARE(scrollArea.scrollCount, 1); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } #if QT_CONFIG(wheelevent) @@ -159,7 +159,7 @@ void tst_QScrollBar::QTBUG_42871() QSignalSpy spy(&scrollBarWidget, SIGNAL(actionTriggered(int))); QVERIFY(spy.isValid()); QCOMPARE(myHandler.updatesCount, 0); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); // Simulate a mouse click on the "scroll down button". const QPoint pressPoint(scrollBarWidget.width() / 2, scrollBarWidget.height() - 10); @@ -180,7 +180,7 @@ void tst_QScrollBar::QTBUG_42871() } // Check that the action was triggered once. QCOMPARE(myHandler.updatesCount, 1); - QCOMPARE(spy.count(), myHandler.updatesCount); + QCOMPARE(spy.size(), myHandler.updatesCount); } QTEST_MAIN(tst_QScrollBar) diff --git a/tests/auto/widgets/widgets/qsizegrip/CMakeLists.txt b/tests/auto/widgets/widgets/qsizegrip/CMakeLists.txt index f3d1e07811..2de1583233 100644 --- a/tests/auto/widgets/widgets/qsizegrip/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qsizegrip/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qsizegrip.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qsizegrip Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsizegrip LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qsizegrip SOURCES tst_qsizegrip.cpp diff --git a/tests/auto/widgets/widgets/qsizegrip/tst_qsizegrip.cpp b/tests/auto/widgets/widgets/qsizegrip/tst_qsizegrip.cpp index e7a2cd5f42..a543efe44e 100644 --- a/tests/auto/widgets/widgets/qsizegrip/tst_qsizegrip.cpp +++ b/tests/auto/widgets/widgets/qsizegrip/tst_qsizegrip.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/widgets/qslider/CMakeLists.txt b/tests/auto/widgets/widgets/qslider/CMakeLists.txt index e344ac0441..664e9a52af 100644 --- a/tests/auto/widgets/widgets/qslider/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qslider/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qslider.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qslider Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qslider LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qslider SOURCES tst_qslider.cpp diff --git a/tests/auto/widgets/widgets/qslider/tst_qslider.cpp b/tests/auto/widgets/widgets/qslider/tst_qslider.cpp index c5f0b9a812..a70c8c484e 100644 --- a/tests/auto/widgets/widgets/qslider/tst_qslider.cpp +++ b/tests/auto/widgets/widgets/qslider/tst_qslider.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/widgets/qspinbox/BLACKLIST b/tests/auto/widgets/widgets/qspinbox/BLACKLIST deleted file mode 100644 index 96a7732165..0000000000 --- a/tests/auto/widgets/widgets/qspinbox/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[stepModifierPressAndHold] -opensuse-42.3 diff --git a/tests/auto/widgets/widgets/qspinbox/CMakeLists.txt b/tests/auto/widgets/widgets/qspinbox/CMakeLists.txt index b412c61e14..826ce16d64 100644 --- a/tests/auto/widgets/widgets/qspinbox/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qspinbox/CMakeLists.txt @@ -1,16 +1,21 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qspinbox.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qspinbox Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qspinbox LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qspinbox SOURCES tst_qspinbox.cpp LIBRARIES Qt::Gui Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp index 732fdb6515..27343edcde 100644 --- a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp +++ b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qdebug.h> #include <qapplication.h> @@ -29,6 +29,8 @@ #include <QProxyStyle> #include <QScreen> +#include <QtWidgets/private/qapplication_p.h> + #if QT_CONFIG(shortcut) # include <QKeySequence> #endif @@ -925,7 +927,6 @@ void tst_QSpinBox::editingFinished() layout->addWidget(box2); testFocusWidget.show(); - QApplication::setActiveWindow(&testFocusWidget); QVERIFY(QTest::qWaitForWindowActive(&testFocusWidget)); box->activateWindow(); box->setFocus(); @@ -939,45 +940,45 @@ void tst_QSpinBox::editingFinished() QTest::keyClick(box, Qt::Key_Up); QTest::keyClick(box, Qt::Key_Up); - QCOMPARE(editingFinishedSpy1.count(), 0); - QCOMPARE(editingFinishedSpy2.count(), 0); + QCOMPARE(editingFinishedSpy1.size(), 0); + QCOMPARE(editingFinishedSpy2.size(), 0); QTest::keyClick(box2, Qt::Key_Up); QTest::keyClick(box2, Qt::Key_Up); box2->setFocus(); - QCOMPARE(editingFinishedSpy1.count(), 1); + QCOMPARE(editingFinishedSpy1.size(), 1); box->setFocus(); - QCOMPARE(editingFinishedSpy1.count(), 1); - QCOMPARE(editingFinishedSpy2.count(), 1); + QCOMPARE(editingFinishedSpy1.size(), 1); + QCOMPARE(editingFinishedSpy2.size(), 1); QTest::keyClick(box, Qt::Key_Up); - QCOMPARE(editingFinishedSpy1.count(), 1); - QCOMPARE(editingFinishedSpy2.count(), 1); + QCOMPARE(editingFinishedSpy1.size(), 1); + QCOMPARE(editingFinishedSpy2.size(), 1); QTest::keyClick(box, Qt::Key_Enter); - QCOMPARE(editingFinishedSpy1.count(), 2); - QCOMPARE(editingFinishedSpy2.count(), 1); + QCOMPARE(editingFinishedSpy1.size(), 2); + QCOMPARE(editingFinishedSpy2.size(), 1); QTest::keyClick(box, Qt::Key_Return); - QCOMPARE(editingFinishedSpy1.count(), 3); - QCOMPARE(editingFinishedSpy2.count(), 1); + QCOMPARE(editingFinishedSpy1.size(), 3); + QCOMPARE(editingFinishedSpy2.size(), 1); box2->setFocus(); - QCOMPARE(editingFinishedSpy1.count(), 4); - QCOMPARE(editingFinishedSpy2.count(), 1); + QCOMPARE(editingFinishedSpy1.size(), 4); + QCOMPARE(editingFinishedSpy2.size(), 1); QTest::keyClick(box2, Qt::Key_Enter); - QCOMPARE(editingFinishedSpy1.count(), 4); - QCOMPARE(editingFinishedSpy2.count(), 2); + QCOMPARE(editingFinishedSpy1.size(), 4); + QCOMPARE(editingFinishedSpy2.size(), 2); QTest::keyClick(box2, Qt::Key_Return); - QCOMPARE(editingFinishedSpy1.count(), 4); - QCOMPARE(editingFinishedSpy2.count(), 3); + QCOMPARE(editingFinishedSpy1.size(), 4); + QCOMPARE(editingFinishedSpy2.size(), 3); testFocusWidget.hide(); - QCOMPARE(editingFinishedSpy1.count(), 4); - QCOMPARE(editingFinishedSpy2.count(), 4); + QCOMPARE(editingFinishedSpy1.size(), 4); + QCOMPARE(editingFinishedSpy2.size(), 4); //task203285 editingFinishedSpy1.clear(); testFocusWidget.show(); QVERIFY(QTest::qWaitForWindowActive(&testFocusWidget)); box->setKeyboardTracking(false); - qApp->setActiveWindow(&testFocusWidget); + QApplicationPrivate::setActiveWindow(&testFocusWidget); testFocusWidget.activateWindow(); box->setFocus(); QTRY_VERIFY(box->hasFocus()); @@ -987,7 +988,7 @@ void tst_QSpinBox::editingFinished() box2->setFocus(); QTRY_VERIFY(qApp->focusWidget() != box); QCOMPARE(box->text(), QLatin1String("20")); - QCOMPARE(editingFinishedSpy1.count(), 1); + QCOMPARE(editingFinishedSpy1.size(), 1); } void tst_QSpinBox::removeAll() @@ -1104,7 +1105,6 @@ void tst_QSpinBox::specialValue() spin.setValue(50); topWidget.show(); //make sure we have the focus (even if editingFinished fails) - qApp->setActiveWindow(&topWidget); topWidget.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&topWidget)); spin.setFocus(); @@ -1150,33 +1150,32 @@ public: void tst_QSpinBox::sizeHint() { - QWidget *widget = new QWidget; - QHBoxLayout *layout = new QHBoxLayout(widget); + QWidget widget; + QHBoxLayout *layout = new QHBoxLayout(&widget); + sizeHint_SpinBox *spinBox = new sizeHint_SpinBox; layout->addWidget(spinBox); - widget->show(); - QVERIFY(QTest::qWaitForWindowExposed(widget)); + // Make sure all layout requests posted by the QHBoxLayout constructor and addWidget + // are processed before the widget is shown + QCoreApplication::sendPostedEvents(&widget, QEvent::LayoutRequest); + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); // Prefix spinBox->sizeHintRequests = 0; spinBox->setPrefix(QLatin1String("abcdefghij")); - qApp->processEvents(); QTRY_VERIFY(spinBox->sizeHintRequests > 0); // Suffix spinBox->sizeHintRequests = 0; spinBox->setSuffix(QLatin1String("abcdefghij")); - qApp->processEvents(); QTRY_VERIFY(spinBox->sizeHintRequests > 0); // Range spinBox->sizeHintRequests = 0; spinBox->setRange(0, 1234567890); spinBox->setValue(spinBox->maximum()); - qApp->processEvents(); QTRY_VERIFY(spinBox->sizeHintRequests > 0); - - delete widget; } void tst_QSpinBox::taskQTBUG_5008_textFromValueAndValidate() @@ -1209,7 +1208,6 @@ void tst_QSpinBox::taskQTBUG_5008_textFromValueAndValidate() spinbox.show(); spinbox.activateWindow(); spinbox.setFocus(); - QApplication::setActiveWindow(&spinbox); QVERIFY(QTest::qWaitForWindowActive(&spinbox)); QVERIFY(spinbox.hasFocus()); QTRY_COMPARE(static_cast<QWidget *>(&spinbox), QApplication::activeWindow()); @@ -1257,7 +1255,7 @@ void tst_QSpinBox::lineEditReturnPressed() QSignalSpy spyCurrentChanged(spinBox.lineEdit(), SIGNAL(returnPressed())); spinBox.show(); QTest::keyClick(&spinBox, Qt::Key_Return); - QCOMPARE(spyCurrentChanged.count(), 1); + QCOMPARE(spyCurrentChanged.size(), 1); } void tst_QSpinBox::positiveSign() @@ -1829,10 +1827,6 @@ void tst_QSpinBox::stepModifierPressAndHold() spin.setStyle(stepModifierStyle.data()); QSignalSpy spy(&spin, &SpinBox::valueChanged); - // TODO: remove debug output when QTBUG-69492 is fixed - connect(&spin, &SpinBox::valueChanged, [=]() { - qDebug() << QTime::currentTime() << "valueChanged emitted"; - }); spin.show(); QVERIFY(QTest::qWaitForWindowActive(&spin)); @@ -1847,13 +1841,13 @@ void tst_QSpinBox::stepModifierPressAndHold() qDebug() << "QGuiApplication::focusWindow():" << QGuiApplication::focusWindow(); qDebug() << "QGuiApplication::topLevelWindows():" << QGuiApplication::topLevelWindows(); QTest::mousePress(&spin, Qt::LeftButton, modifiers, buttonRect.center()); - QTRY_VERIFY2(spy.length() >= 3, qPrintable(QString::fromLatin1( - "Expected valueChanged() to be emitted 3 or more times, but it was only emitted %1 times").arg(spy.length()))); + QTRY_VERIFY2(spy.size() >= 3, qPrintable(QString::fromLatin1( + "Expected valueChanged() to be emitted 3 or more times, but it was only emitted %1 times").arg(spy.size()))); QTest::mouseRelease(&spin, Qt::LeftButton, modifiers, buttonRect.center()); const auto value = spy.last().at(0); QVERIFY(value.metaType().id() == QMetaType::Int); - QCOMPARE(value.toInt(), spy.length() * expectedStepModifier); + QCOMPARE(value.toInt(), spy.size() * expectedStepModifier); } void tst_QSpinBox::stepSelectAll_data() diff --git a/tests/auto/widgets/widgets/qsplashscreen/CMakeLists.txt b/tests/auto/widgets/widgets/qsplashscreen/CMakeLists.txt index 9a2b651ba5..12602328c3 100644 --- a/tests/auto/widgets/widgets/qsplashscreen/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qsplashscreen/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qsplashscreen.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qsplashscreen Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsplashscreen LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qsplashscreen SOURCES tst_qsplashscreen.cpp diff --git a/tests/auto/widgets/widgets/qsplashscreen/tst_qsplashscreen.cpp b/tests/auto/widgets/widgets/qsplashscreen/tst_qsplashscreen.cpp index f397777065..f57634152a 100644 --- a/tests/auto/widgets/widgets/qsplashscreen/tst_qsplashscreen.cpp +++ b/tests/auto/widgets/widgets/qsplashscreen/tst_qsplashscreen.cpp @@ -1,9 +1,10 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QSplashScreen> +#include <QTimer> class tst_QSplashScreen : public QObject { @@ -11,7 +12,7 @@ class tst_QSplashScreen : public QObject private slots: void checkCloseTime(); - void checkScreenConstructor(); + void checkConstructorAndShow(); }; class CloseEventSplash : public QSplashScreen @@ -20,7 +21,7 @@ public: CloseEventSplash(const QPixmap &pix) : QSplashScreen(pix), receivedCloseEvent(false) {} bool receivedCloseEvent; protected: - void closeEvent(QCloseEvent *event) + void closeEvent(QCloseEvent *event) override { receivedCloseEvent = true; QSplashScreen::closeEvent(event); @@ -35,23 +36,26 @@ void tst_QSplashScreen::checkCloseTime() QVERIFY(!splash.receivedCloseEvent); QWidget w; splash.show(); - QTimer::singleShot(500, &w, SLOT(show())); + QTimer::singleShot(10, &w, &QWidget::show); QVERIFY(!splash.receivedCloseEvent); splash.finish(&w); QVERIFY(splash.receivedCloseEvent); // We check the window handle because if this is not valid, then // it can't have been exposed QVERIFY(w.windowHandle()); - QVERIFY(w.windowHandle()->isExposed()); + QVERIFY(w.windowHandle()->isVisible()); } -void tst_QSplashScreen::checkScreenConstructor() +void tst_QSplashScreen::checkConstructorAndShow() { - for (const auto screen : QGuiApplication::screens()) { - QSplashScreen splash(screen); + QPixmap pix(100, 100); + pix.fill(Qt::red); + for (auto *screen : QGuiApplication::screens()) { + QSplashScreen splash(screen, pix); splash.show(); QCOMPARE(splash.screen(), screen); QVERIFY(splash.windowHandle()); + QVERIFY(splash.windowHandle()->isVisible()); QCOMPARE(splash.windowHandle()->screen(), screen); } } diff --git a/tests/auto/widgets/widgets/qsplitter/CMakeLists.txt b/tests/auto/widgets/widgets/qsplitter/CMakeLists.txt index cf5e984a41..16244c8834 100644 --- a/tests/auto/widgets/widgets/qsplitter/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qsplitter/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qsplitter.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qsplitter Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsplitter LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Collect test data list(APPEND test_data "extradata.txt") list(APPEND test_data "setSizes3.dat") diff --git a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp index 667c6868b7..071e6d4cbc 100644 --- a/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp +++ b/tests/auto/widgets/widgets/qsplitter/tst_qsplitter.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -908,55 +908,56 @@ void tst_QSplitter::rubberBandNotInSplitter() void tst_QSplitter::task187373_addAbstractScrollAreas_data() { - QTest::addColumn<QString>("className"); + QTest::addColumn<QByteArray>("className"); QTest::addColumn<bool>("addInConstructor"); QTest::addColumn<bool>("addOutsideConstructor"); - QStringList classNames; - classNames << QLatin1String("QGraphicsView"); - classNames << QLatin1String("QMdiArea"); - classNames << QLatin1String("QScrollArea"); - classNames << QLatin1String("QTextEdit"); - classNames << QLatin1String("QTreeView"); - - foreach (QString className, classNames) { - QTest::newRow(qPrintable(className + QLatin1String(" 1"))) << className << false << true; - QTest::newRow(qPrintable(className + QLatin1String(" 2"))) << className << true << false; - QTest::newRow(qPrintable(className + QLatin1String(" 3"))) << className << true << true; + QList<QByteArray> classNames{ + "QGraphicsView", + "QMdiArea", + "QScrollArea", + "QTextEdit", + "QTreeView" + }; + + for (const auto &className : std::as_const(classNames)) { + QTest::newRow(qPrintable(className + " 1")) << className << false << true; + QTest::newRow(qPrintable(className + " 2")) << className << true << false; + QTest::newRow(qPrintable(className + " 3")) << className << true << true; } } static QAbstractScrollArea *task187373_createScrollArea( - QSplitter *splitter, const QString &className, bool addInConstructor) + QSplitter *splitter, const QByteArray &className, bool addInConstructor) { - if (className == QLatin1String("QGraphicsView")) + if (className == "QGraphicsView") return new QGraphicsView(addInConstructor ? splitter : 0); - if (className == QLatin1String("QMdiArea")) + if (className == "QMdiArea") return new QMdiArea(addInConstructor ? splitter : 0); - if (className == QLatin1String("QScrollArea")) + if (className == "QScrollArea") return new QScrollArea(addInConstructor ? splitter : 0); - if (className == QLatin1String("QTextEdit")) + if (className == "QTextEdit") return new QTextEdit(addInConstructor ? splitter : 0); - if (className == QLatin1String("QTreeView")) + if (className == "QTreeView") return new QTreeView(addInConstructor ? splitter : 0); return 0; } void tst_QSplitter::task187373_addAbstractScrollAreas() { - QFETCH(QString, className); + QFETCH(QByteArray, className); QFETCH(bool, addInConstructor); QFETCH(bool, addOutsideConstructor); QVERIFY(addInConstructor || addOutsideConstructor); - QSplitter *splitter = new QSplitter; - splitter->show(); - QVERIFY(splitter->isVisible()); + QSplitter splitter; + splitter.show(); + QVERIFY(splitter.isVisible()); - QAbstractScrollArea *w = task187373_createScrollArea(splitter, className, addInConstructor); + QAbstractScrollArea *w = task187373_createScrollArea(&splitter, className, addInConstructor); QVERIFY(w); if (addOutsideConstructor) - splitter->addWidget(w); + splitter.addWidget(w); QTRY_VERIFY(w->isVisible()); QVERIFY(!w->isHidden()); @@ -1031,7 +1032,7 @@ void tst_QSplitter::taskQTBUG_4101_ensureOneNonCollapsedWidget() QFETCH(bool, testingHide); MyFriendlySplitter s; - QLabel *l; + QLabel *l = nullptr; for (int i = 0; i < 5; ++i) { l = new QLabel(QString("Label ") + QChar('A' + i)); l->setAlignment(Qt::AlignCenter); @@ -1062,7 +1063,7 @@ void tst_QSplitter::taskQTBUG_102249_moveNonPressed() Qt::NoButton, Qt::MouseButtons(Qt::LeftButton), Qt::NoModifier); qApp->sendEvent(s.handle(0), &me); - QCOMPARE(spyMove.count(), 0); + QCOMPARE(spyMove.size(), 0); } void tst_QSplitter::setLayout() diff --git a/tests/auto/widgets/widgets/qstackedwidget/CMakeLists.txt b/tests/auto/widgets/widgets/qstackedwidget/CMakeLists.txt index 1ba94e1cc1..0c79cf29f4 100644 --- a/tests/auto/widgets/widgets/qstackedwidget/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qstackedwidget/CMakeLists.txt @@ -1,16 +1,21 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qstackedwidget.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qstackedwidget Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qstackedwidget LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qstackedwidget SOURCES tst_qstackedwidget.cpp LIBRARIES Qt::Gui Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/widgets/qstackedwidget/tst_qstackedwidget.cpp b/tests/auto/widgets/widgets/qstackedwidget/tst_qstackedwidget.cpp index 672e176808..3c28ad324a 100644 --- a/tests/auto/widgets/widgets/qstackedwidget/tst_qstackedwidget.cpp +++ b/tests/auto/widgets/widgets/qstackedwidget/tst_qstackedwidget.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -11,6 +11,8 @@ #include <QHBoxLayout> #include <qlineedit.h> +#include <QtWidgets/private/qapplication_p.h> + class tst_QStackedWidget : public QObject { Q_OBJECT @@ -157,7 +159,6 @@ void tst_QStackedWidget::dynamicPages() le11->setFocus(); // set focus to second widget in the page sw->resize(200, 200); sw->show(); - qApp->setActiveWindow(sw); QVERIFY(QTest::qWaitForWindowActive(sw)); QTRY_COMPARE(QApplication::focusWidget(), le11); diff --git a/tests/auto/widgets/widgets/qstatusbar/CMakeLists.txt b/tests/auto/widgets/widgets/qstatusbar/CMakeLists.txt index 7db2cf9b0d..3bda170936 100644 --- a/tests/auto/widgets/widgets/qstatusbar/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qstatusbar/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qstatusbar.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qstatusbar Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qstatusbar LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qstatusbar SOURCES tst_qstatusbar.cpp diff --git a/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp b/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp index 353c44d6b3..b0a53ba01a 100644 --- a/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp +++ b/tests/auto/widgets/widgets/qstatusbar/tst_qstatusbar.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -23,6 +23,7 @@ private slots: void tempMessage(); void insertWidget(); void insertPermanentWidget(); + void removeWidget(); void setSizeGripEnabled(); void task194017_hiddenWidget(); void QTBUG4334_hiddenOnMaximizedWindow(); @@ -104,6 +105,49 @@ void tst_QStatusBar::insertPermanentWidget() QCOMPARE(sb.insertPermanentWidget(1, new QLabel("foo")), 6); } +void tst_QStatusBar::removeWidget() +{ + QStatusBar sb; + std::vector<std::unique_ptr<QLabel>> widgets; + std::vector<bool> states; + for (int i = 0; i < 10; ++i) { + const QString text = i > 5 ? QString("p_%1").arg(i) : QString::number(i); + widgets.push_back(std::make_unique<QLabel>(text)); + states.push_back(true); + } + + for (auto &&widget : widgets) { + if (widget->text().startsWith("p_")) + sb.addPermanentWidget(widget.get()); + else + sb.addWidget(widget.get()); + } + sb.show(); + QVERIFY(QTest::qWaitForWindowExposed(&sb)); + + auto checkStates = [&]{ + for (size_t index = 0; index < std::size(widgets); ++index) { + if (widgets.at(index)->isVisible() != states.at(index)) { + qCritical("Mismatch for widget at index %zu\n" + "\tActual : %s\n" + "\tExpected: %s", + index, widgets.at(index)->isVisible() ? "true" : "false", + states.at(index) ? "true" : "false"); + return false; + } + } + return true; + }; + + QVERIFY(checkStates()); + // remove every widget except the first to trigger unstable reference + for (size_t i = 2; i < std::size(widgets); ++i) { + sb.removeWidget(widgets[i].get()); + states[i] = false; + QVERIFY2(checkStates(), qPrintable(QString("Failure at index %1").arg(i))); + } +} + void tst_QStatusBar::setSizeGripEnabled() { if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) @@ -272,18 +316,18 @@ void tst_QStatusBar::messageChangedSignal() testWidget->showMessage("Ready", 0); QCOMPARE(testWidget->currentMessage(), QString("Ready")); QCOMPARE(testWidget->currentMessage(), currentMessage); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.takeFirst().at(0).toString(), currentMessage); testWidget->clearMessage(); QCOMPARE(testWidget->currentMessage(), QString()); QCOMPARE(testWidget->currentMessage(), currentMessage); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.takeFirst().at(0).toString(), currentMessage); testWidget->showMessage("Ready", 0); testWidget->showMessage("Ready", 0); QCOMPARE(testWidget->currentMessage(), QString("Ready")); QCOMPARE(testWidget->currentMessage(), currentMessage); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.takeFirst().at(0).toString(), currentMessage); } diff --git a/tests/auto/widgets/widgets/qtabbar/BLACKLIST b/tests/auto/widgets/widgets/qtabbar/BLACKLIST deleted file mode 100644 index 735b044d8b..0000000000 --- a/tests/auto/widgets/widgets/qtabbar/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[sizeHints] -redhatenterpriselinuxworkstation-6.6 diff --git a/tests/auto/widgets/widgets/qtabbar/CMakeLists.txt b/tests/auto/widgets/widgets/qtabbar/CMakeLists.txt index 2ac0d1a8a3..b79e763819 100644 --- a/tests/auto/widgets/widgets/qtabbar/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qtabbar/CMakeLists.txt @@ -1,16 +1,21 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qtabbar.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtabbar Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtabbar LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtabbar SOURCES tst_qtabbar.cpp LIBRARIES Qt::Gui Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp b/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp index 1e19617be9..03131cebe4 100644 --- a/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp +++ b/tests/auto/widgets/widgets/qtabbar/tst_qtabbar.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> #include <QSignalSpy> @@ -14,6 +14,8 @@ #include <QScreen> #include <QWindow> +#include <QtWidgets/private/qtabbar_p.h> + using namespace Qt::StringLiterals; class TabBar; @@ -48,6 +50,7 @@ private slots: void hideTab_data(); void hideTab(); void hideAllTabs(); + void checkHiddenTab(); void setElideMode_data(); void setElideMode(); @@ -94,6 +97,13 @@ private slots: void hoverTab_data(); void hoverTab(); + void resizeKeepsScroll_data(); + void resizeKeepsScroll(); + void changeTabTextKeepsScroll(); + void settingCurrentTabBeforeShowDoesntScroll(); + void checkPositionsAfterShapeChange(); + void checkScrollOffsetAfterTabRemoval(); + private: void checkPositions(const TabBar &tabbar, const QList<int> &positions); }; @@ -209,7 +219,7 @@ void tst_QTabBar::testCurrentChanged() QCOMPARE(tabBar.currentIndex(), 0); tabBar.setCurrentIndex(tabToSet); QCOMPARE(tabBar.currentIndex(), tabToSet); - QCOMPARE(spy.count(), expectedCount); + QCOMPARE(spy.size(), expectedCount); } class TabBar : public QTabBar @@ -283,7 +293,7 @@ void tst_QTabBar::removeTab() tabbar.setCurrentIndex(currentIndex); QSignalSpy spy(&tabbar, SIGNAL(currentChanged(int))); tabbar.removeTab(deleteIndex); - QTEST(int(spy.count()), "spyCount"); + QTEST(int(spy.size()), "spyCount"); QTEST(tabbar.currentIndex(), "finalIndex"); } @@ -314,7 +324,7 @@ void tst_QTabBar::hideTab() tabbar.setCurrentIndex(currentIndex); QSignalSpy spy(&tabbar, &QTabBar::currentChanged); tabbar.setTabVisible(hideIndex, false); - QTEST(int(spy.count()), "spyCount"); + QTEST(int(spy.size()), "spyCount"); QTEST(tabbar.currentIndex(), "finalIndex"); } @@ -360,6 +370,25 @@ void tst_QTabBar::hideAllTabs() QVERIFY(sizeHint.width() < prevSizeHint.width()); } +void tst_QTabBar::checkHiddenTab() +{ + QTabBar tabbar; + + tabbar.addTab("foo"); + tabbar.addTab("bar"); + tabbar.addTab("baz"); + tabbar.setCurrentIndex(0); + tabbar.setTabVisible(1, false); + + QKeyEvent keyRight(QKeyEvent::KeyPress, Qt::Key_Right, Qt::NoModifier); + QVERIFY(QApplication::sendEvent(&tabbar, &keyRight)); + QCOMPARE(tabbar.currentIndex(), 2); + + QKeyEvent keyLeft(QKeyEvent::KeyPress, Qt::Key_Left, Qt::NoModifier); + QVERIFY(QApplication::sendEvent(&tabbar, &keyLeft)); + QCOMPARE(tabbar.currentIndex(), 0); +} + void tst_QTabBar::setElideMode_data() { QTest::addColumn<int>("tabElideMode"); @@ -458,12 +487,12 @@ void tst_QTabBar::removeLastTab() QTabBar tabbar; QSignalSpy spy(&tabbar, SIGNAL(currentChanged(int))); int index = tabbar.addTab("foo"); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toInt(), index); spy.clear(); tabbar.removeTab(index); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toInt(), -1); spy.clear(); } @@ -482,7 +511,7 @@ void tst_QTabBar::removeLastVisibleTab() { QSignalSpy spy(&tabbar, SIGNAL(currentChanged(int))); tabbar.removeTab(visible); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toInt(), -1); QCOMPARE(tabbar.currentIndex(), -1); } @@ -495,7 +524,7 @@ void tst_QTabBar::removeLastVisibleTab() { QSignalSpy spy(&tabbar, SIGNAL(currentChanged(int))); tabbar.removeTab(visible); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toInt(), -1); QCOMPARE(tabbar.currentIndex(), -1); } @@ -519,7 +548,7 @@ void tst_QTabBar::closeButton() QSignalSpy spy(&tabbar, SIGNAL(tabCloseRequested(int))); button->click(); QCOMPARE(tabbar.count(), 1); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } Q_DECLARE_METATYPE(QTabBar::ButtonPosition) @@ -791,36 +820,36 @@ void tst_QTabBar::tabBarClicked() QSignalSpy clickSpy(&tabBar, SIGNAL(tabBarClicked(int))); QSignalSpy doubleClickSpy(&tabBar, SIGNAL(tabBarDoubleClicked(int))); - QCOMPARE(clickSpy.count(), 0); - QCOMPARE(doubleClickSpy.count(), 0); + QCOMPARE(clickSpy.size(), 0); + QCOMPARE(doubleClickSpy.size(), 0); Qt::MouseButton button = Qt::LeftButton; while (button <= Qt::MaxMouseButton) { const QPoint tabPos = tabBar.tabRect(0).center(); QTest::mouseClick(&tabBar, button, {}, tabPos); - QCOMPARE(clickSpy.count(), 1); + QCOMPARE(clickSpy.size(), 1); QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), 0); - QCOMPARE(doubleClickSpy.count(), 0); + QCOMPARE(doubleClickSpy.size(), 0); QTest::mouseDClick(&tabBar, button, {}, tabPos); - QCOMPARE(clickSpy.count(), 1); + QCOMPARE(clickSpy.size(), 1); QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), 0); - QCOMPARE(doubleClickSpy.count(), 1); + QCOMPARE(doubleClickSpy.size(), 1); QCOMPARE(doubleClickSpy.takeFirst().takeFirst().toInt(), 0); QTest::mouseRelease(&tabBar, button, {}, tabPos); const QPoint barPos(tabBar.tabRect(0).right() + 5, tabBar.tabRect(0).center().y()); QTest::mouseClick(&tabBar, button, {}, barPos); - QCOMPARE(clickSpy.count(), 1); + QCOMPARE(clickSpy.size(), 1); QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), -1); - QCOMPARE(doubleClickSpy.count(), 0); + QCOMPARE(doubleClickSpy.size(), 0); QTest::mouseDClick(&tabBar, button, {}, barPos); - QCOMPARE(clickSpy.count(), 1); + QCOMPARE(clickSpy.size(), 1); QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), -1); - QCOMPARE(doubleClickSpy.count(), 1); + QCOMPARE(doubleClickSpy.size(), 1); QCOMPARE(doubleClickSpy.takeFirst().takeFirst().toInt(), -1); QTest::mouseRelease(&tabBar, button, {}, barPos); @@ -1346,5 +1375,226 @@ void tst_QTabBar::hoverTab() QCOMPARE(tabbar.styleOptions[1].state & QStyle::State_MouseOver, QStyle::State_None); } + +void tst_QTabBar::resizeKeepsScroll_data() +{ + QTest::addColumn<QTabBar::Shape>("tabShape"); + QTest::addColumn<bool>("expanding"); + + QTest::addRow("North, expanding") << QTabBar::RoundedNorth << true; + QTest::addRow("East, expanding") << QTabBar::RoundedEast << true; + QTest::addRow("South, expanding") << QTabBar::RoundedSouth << true; + QTest::addRow("West, expanding") << QTabBar::RoundedWest << true; + + QTest::addRow("North, not expanding") << QTabBar::RoundedNorth << false; + QTest::addRow("South, not expanding") << QTabBar::RoundedSouth << false; +} + +void tst_QTabBar::resizeKeepsScroll() +{ + QFETCH(QTabBar::Shape, tabShape); + QFETCH(const bool, expanding); + + QTabBar tabBar; + TabBarScrollingProxyStyle proxyStyle; + tabBar.setStyle(&proxyStyle); + + for (int i = 0; i < 10; ++i) + tabBar.addTab(u"Tab Number %1"_s.arg(i)); + + tabBar.setShape(tabShape); + tabBar.setUsesScrollButtons(true); + tabBar.setExpanding(expanding); + + // resize to half + const QSize fullSize = tabBar.sizeHint(); + const bool horizontal = fullSize.width() > fullSize.height(); + if (horizontal) + tabBar.resize(fullSize.width() / 2, fullSize.height()); + else + tabBar.resize(fullSize.width(), fullSize.height() / 2); + + tabBar.show(); + QVERIFY(QTest::qWaitForWindowExposed(&tabBar)); + + const auto getScrollOffset = [&]() -> int { + return static_cast<QTabBarPrivate *>(QObjectPrivate::get(&tabBar))->scrollOffset; + }; + + // select a tab outside, this will scroll + tabBar.setCurrentIndex(6); + // the first tab is now scrolled out + const int scrollOffset = getScrollOffset(); + QCOMPARE_GT(scrollOffset, 0); + // the current index is now fully visible, with margin on both sides + tabBar.setCurrentIndex(5); + + // make the tab bar a bit larger, by the width of a tab + if (horizontal) + tabBar.resize(tabBar.width() + tabBar.tabRect(5).width(), tabBar.height()); + else + tabBar.resize(tabBar.width(), tabBar.height() + tabBar.tabRect(5).height()); + + // this should not change the scroll + QCOMPARE(getScrollOffset(), scrollOffset); + + // make the tab bar large enough to fit everything with extra space + tabBar.resize(fullSize + QSize(50, 50)); + + // there should be no scroll + QCOMPARE(getScrollOffset(), 0); + + for (int i = 0; i < tabBar.count(); ++i) { + tabBar.setCurrentIndex(i); + QCOMPARE(getScrollOffset(), 0); + } +} + +void tst_QTabBar::changeTabTextKeepsScroll() +{ + QTabBar tabBar; + TabBarScrollingProxyStyle proxyStyle; + tabBar.setStyle(&proxyStyle); + + for (int i = 0; i < 6; ++i) + tabBar.addTab(u"Tab Number %1"_s.arg(i)); + + const QSize fullSize = tabBar.sizeHint(); + tabBar.resize(fullSize.width() / 2, fullSize.height()); + + tabBar.show(); + QVERIFY(QTest::qWaitForWindowExposed(&tabBar)); + + const auto getScrollOffset = [&]() -> int { + return static_cast<QTabBarPrivate *>(QObjectPrivate::get(&tabBar))->scrollOffset; + }; + + tabBar.setCurrentIndex(3); + const int scrollOffset = getScrollOffset(); + tabBar.setTabText(3, "New title"); + QCOMPARE(getScrollOffset(), scrollOffset); +} + +void tst_QTabBar::settingCurrentTabBeforeShowDoesntScroll() +{ + QTabBar tabBar; + TabBarScrollingProxyStyle proxyStyle; + tabBar.setStyle(&proxyStyle); + + for (int i = 0; i < 6; ++i) + tabBar.addTab(u"Tab Number %1"_s.arg(i)); + + const auto getScrollOffset = [&]() -> int { + return static_cast<QTabBarPrivate *>(QObjectPrivate::get(&tabBar))->scrollOffset; + }; + + tabBar.setCurrentIndex(5); + + // changing the current index while the tab bar isn't visible shouldn't scroll yet + QCOMPARE(getScrollOffset(), 0); + + // now show the tab bar with a size that's too small to fit the current index + const QSize fullSize = tabBar.sizeHint(); + tabBar.resize(fullSize.width() / 2, fullSize.height()); + + tabBar.show(); + QVERIFY(QTest::qWaitForWindowExposed(&tabBar)); + + // this should scroll + QCOMPARE_GT(getScrollOffset(), 0); +} + +void tst_QTabBar::checkPositionsAfterShapeChange() +{ + class TabWidget : public QTabWidget + { + public: + using QTabWidget::QTabWidget; + using QTabWidget::setTabBar; + }; + + class TabBar : public QTabBar + { + public: + using QTabBar::initStyleOption; + void resizeEvent(QResizeEvent *e) override + { + QTabBar::resizeEvent(e); + resized = true; + } + bool resized = false; + }; + + TabWidget tabWidget; + auto *tabBar = new TabBar; + tabWidget.setTabBar(tabBar); + for (int i = 0; i < 3; ++i) + tabWidget.addTab(new QWidget, u"Tab %1"_s.arg(i)); + tabWidget.setTabPosition(QTabWidget::North); + tabWidget.setCurrentIndex(2); + tabWidget.resize(300, 300); + tabWidget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&tabWidget)); + + tabBar->resized = false; + tabWidget.setTabPosition(QTabWidget::East); + QVERIFY(QTest::qWaitFor([&]() { return tabBar->resized; })); + QStyleOptionTab opt; + tabBar->initStyleOption(&opt, 2); + QVERIFY(opt.rect.top() > 0); +} + +void tst_QTabBar::checkScrollOffsetAfterTabRemoval() +{ + QTabWidget tabWidget; + QTabBar *tabBar = tabWidget.tabBar(); + for (int i = 0; i < 10; ++i) + tabWidget.addTab(new QWidget, u"Tab %1"_s.arg(i)); + tabWidget.setTabPosition(QTabWidget::North); + tabWidget.resize(300, 300); + tabWidget.setCurrentIndex(0); + tabWidget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&tabWidget)); + + auto *rightButton = tabBar->findChild<QAbstractButton *>(u"ScrollRightButton"_s); + auto *leftButton = tabBar->findChild<QAbstractButton *>(u"ScrollLeftButton"_s); + QVERIFY(leftButton); + QVERIFY(rightButton); + QVERIFY(rightButton->isEnabled()); + QVERIFY(!leftButton->isEnabled()); + // scroll to the right + tabBar->setCurrentIndex(9); + QVERIFY(!rightButton->isEnabled()); + QVERIFY(leftButton->isEnabled()); + // scroll to the center + tabBar->setCurrentIndex(2); + QVERIFY(rightButton->isEnabled()); + QVERIFY(leftButton->isEnabled()); + + const auto getScrollOffset = [&]() -> int { + return static_cast<QTabBarPrivate *>(QObjectPrivate::get(tabBar))->scrollOffset; + }; + // the scroll offset should not change when a tab right outside + // the scroll rect is removed + auto oldOffset = getScrollOffset(); + tabWidget.removeTab(9); + QCOMPARE(getScrollOffset(), oldOffset); + // the scroll offset must change when a tab left outside + // the scroll rect is removed + oldOffset = getScrollOffset(); + tabWidget.removeTab(0); + QVERIFY(getScrollOffset() < oldOffset); + + // the scroll offset must change when there is empty + // place in the right after tab removal + oldOffset = getScrollOffset(); + QVERIFY(oldOffset > 0); + for (int i : { 7, 6, 5, 4, 3 }) + tabWidget.removeTab(i); + QCOMPARE(getScrollOffset(), 0); + QVERIFY(!rightButton->isVisible()); + QVERIFY(!leftButton->isVisible()); +} + QTEST_MAIN(tst_QTabBar) #include "tst_qtabbar.moc" diff --git a/tests/auto/widgets/widgets/qtabwidget/CMakeLists.txt b/tests/auto/widgets/widgets/qtabwidget/CMakeLists.txt index 0cc8aa8fda..a8b48e925c 100644 --- a/tests/auto/widgets/widgets/qtabwidget/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qtabwidget/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qtabwidget.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtabwidget Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtabwidget LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtabwidget SOURCES tst_qtabwidget.cpp diff --git a/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp b/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp index 0cf37ad9d0..d7bfdfaad2 100644 --- a/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp +++ b/tests/auto/widgets/widgets/qtabwidget/tst_qtabwidget.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -60,6 +60,7 @@ private slots: void tabPosition(); void tabEnabled(); void tabHidden(); + void checkHiddenTab(); void tabText(); void tabShape(); void tabTooltip(); @@ -79,6 +80,9 @@ private slots: void moveCurrentTab(); void autoHide(); + void setCurrentBeforeShow_data(); + void setCurrentBeforeShow(); + private: int addPage(); void removePage(int index); @@ -249,6 +253,32 @@ void tst_QTabWidget::tabHidden() } } +void tst_QTabWidget::checkHiddenTab() +{ + tw->addTab(new QWidget(), "foo"); + tw->addTab(new QWidget(), "bar"); + tw->addTab(new QWidget(), "baz"); + QCOMPARE(tw->count(), 3); + tw->setCurrentIndex(0); + tw->setTabVisible(1, false); + + QKeyEvent keyTab(QKeyEvent::KeyPress, Qt::Key_Tab, Qt::ControlModifier); + QVERIFY(QApplication::sendEvent(tw, &keyTab)); + QCOMPARE(tw->currentIndex(), 2); + QVERIFY(QApplication::sendEvent(tw, &keyTab)); + QCOMPARE(tw->currentIndex(), 0); + QVERIFY(QApplication::sendEvent(tw, &keyTab)); + QCOMPARE(tw->currentIndex(), 2); + + QKeyEvent keyBacktab(QKeyEvent::KeyPress, Qt::Key_Backtab, Qt::ControlModifier); + QVERIFY(QApplication::sendEvent(tw, &keyBacktab)); + QCOMPARE(tw->currentIndex(), 0); + QVERIFY(QApplication::sendEvent(tw, &keyBacktab)); + QCOMPARE(tw->currentIndex(), 2); + QVERIFY(QApplication::sendEvent(tw, &keyBacktab)); + QCOMPARE(tw->currentIndex(), 0); +} + void tst_QTabWidget::tabText() { // Test bad arguments @@ -358,12 +388,12 @@ void tst_QTabWidget::currentIndex() QCOMPARE(tw->currentIndex(), -1); tw->setCurrentIndex(-1); QCOMPARE(tw->currentIndex(), -1); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); int firstIndex = addPage(); tw->setCurrentIndex(firstIndex); QCOMPARE(tw->currentIndex(), firstIndex); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QList<QVariant> arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), firstIndex); @@ -371,19 +401,19 @@ void tst_QTabWidget::currentIndex() QCOMPARE(tw->currentIndex(), firstIndex); tw->setCurrentIndex(index); QCOMPARE(tw->currentIndex(), index); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), index); removePage(index); QCOMPARE(tw->currentIndex(), firstIndex); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), firstIndex); removePage(firstIndex); QCOMPARE(tw->currentIndex(), -1); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).toInt(), -1); } @@ -664,8 +694,8 @@ void tst_QTabWidget::tabBarClicked() QSignalSpy clickSpy(&tabWidget, SIGNAL(tabBarClicked(int))); QSignalSpy doubleClickSpy(&tabWidget, SIGNAL(tabBarDoubleClicked(int))); - QCOMPARE(clickSpy.count(), 0); - QCOMPARE(doubleClickSpy.count(), 0); + QCOMPARE(clickSpy.size(), 0); + QCOMPARE(doubleClickSpy.size(), 0); QTabBar &tabBar = *tabWidget.tabBar(); Qt::MouseButton button = Qt::LeftButton; @@ -673,27 +703,27 @@ void tst_QTabWidget::tabBarClicked() const QPoint tabPos = tabBar.tabRect(0).center(); QTest::mouseClick(&tabBar, button, {}, tabPos); - QCOMPARE(clickSpy.count(), 1); + QCOMPARE(clickSpy.size(), 1); QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), 0); - QCOMPARE(doubleClickSpy.count(), 0); + QCOMPARE(doubleClickSpy.size(), 0); QTest::mouseDClick(&tabBar, button, {}, tabPos); - QCOMPARE(clickSpy.count(), 1); + QCOMPARE(clickSpy.size(), 1); QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), 0); - QCOMPARE(doubleClickSpy.count(), 1); + QCOMPARE(doubleClickSpy.size(), 1); QCOMPARE(doubleClickSpy.takeFirst().takeFirst().toInt(), 0); const QPoint barPos(tabBar.tabRect(0).right() + 5, tabBar.tabRect(0).center().y()); QTest::mouseClick(&tabBar, button, {}, barPos); - QCOMPARE(clickSpy.count(), 1); + QCOMPARE(clickSpy.size(), 1); QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), -1); - QCOMPARE(doubleClickSpy.count(), 0); + QCOMPARE(doubleClickSpy.size(), 0); QTest::mouseDClick(&tabBar, button, {}, barPos); - QCOMPARE(clickSpy.count(), 1); + QCOMPARE(clickSpy.size(), 1); QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), -1); - QCOMPARE(doubleClickSpy.count(), 1); + QCOMPARE(doubleClickSpy.size(), 1); QCOMPARE(doubleClickSpy.takeFirst().takeFirst().toInt(), -1); button = Qt::MouseButton(button << 1); @@ -750,5 +780,39 @@ void tst_QTabWidget::autoHide() QVERIFY(heightForWidth1 > tabWidget.heightForWidth(20)); } +void tst_QTabWidget::setCurrentBeforeShow_data() +{ + QTest::addColumn<QTabWidget::TabPosition>("tabPosition"); + QTest::newRow("West") << QTabWidget::West; + QTest::newRow("North") << QTabWidget::North; + QTest::newRow("East") << QTabWidget::East; + QTest::newRow("South") << QTabWidget::South; +} + +void tst_QTabWidget::setCurrentBeforeShow() +{ + QFETCH(QTabWidget::TabPosition, tabPosition); + + QTabWidget tabWidget; + tabWidget.setTabPosition(tabPosition); + + QPixmap pm(50, 50); + pm.fill(Qt::red); + const QIcon icon(pm); + for (int i = 0; i < 4; ++i) + tabWidget.addTab(new QWidget, icon, QString("Tab %1").arg(i)); + + // the tab widget has space for the entire tab bar + tabWidget.resize(tabWidget.tabBar()->sizeHint() + QSize(50, 50)); + tabWidget.setCurrentIndex(2); + tabWidget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&tabWidget)); + + QCOMPARE_GE(tabWidget.tabBar()->tabRect(0).x(), 0); + QCOMPARE_GE(tabWidget.tabBar()->tabRect(0).y(), 0); + + QTest::qWait(2000); +} + QTEST_MAIN(tst_QTabWidget) #include "tst_qtabwidget.moc" diff --git a/tests/auto/widgets/widgets/qtextbrowser/CMakeLists.txt b/tests/auto/widgets/widgets/qtextbrowser/CMakeLists.txt index eef407b704..4a80068d75 100644 --- a/tests/auto/widgets/widgets/qtextbrowser/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qtextbrowser/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qtextbrowser.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtextbrowser Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtextbrowser LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Collect test data file(GLOB_RECURSE test_data_glob RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} @@ -28,6 +32,7 @@ qt_internal_add_test(tst_qtextbrowser LIBRARIES Qt::Gui Qt::Widgets + Qt::WidgetsPrivate TESTDATA ${test_data} ) diff --git a/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp b/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp index ee950fa670..6dfab07fed 100644 --- a/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp +++ b/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -12,12 +12,13 @@ #include <qtextbrowser.h> #include <qtextobject.h> +#include <QtWidgets/private/qapplication_p.h> + class TestBrowser : public QTextBrowser { public: inline TestBrowser() { show(); - QApplication::setActiveWindow(this); activateWindow(); setFocus(); QVERIFY(QTest::qWaitForWindowActive(this)); @@ -220,29 +221,29 @@ void tst_QTextBrowser::relativeLinks() QSignalSpy sourceChangedSpy(browser, SIGNAL(sourceChanged(QUrl))); browser->setSource(QUrl("subdir/../qtextbrowser.html")); QVERIFY(!browser->document()->isEmpty()); - QCOMPARE(sourceChangedSpy.count(), 1); + QCOMPARE(sourceChangedSpy.size(), 1); QCOMPARE(sourceChangedSpy.takeFirst()[0].toUrl(), QUrl("subdir/../qtextbrowser.html")); browser->setSource(QUrl("subdir/index.html")); QVERIFY(!browser->document()->isEmpty()); - QCOMPARE(sourceChangedSpy.count(), 1); + QCOMPARE(sourceChangedSpy.size(), 1); QCOMPARE(sourceChangedSpy.takeFirst()[0].toUrl(), QUrl("subdir/index.html")); browser->setSource(QUrl("anchor.html")); QVERIFY(!browser->document()->isEmpty()); - QCOMPARE(sourceChangedSpy.count(), 1); + QCOMPARE(sourceChangedSpy.size(), 1); QCOMPARE(sourceChangedSpy.takeFirst()[0].toUrl(), QUrl("anchor.html")); browser->setSource(QUrl("subdir/index.html")); QVERIFY(!browser->document()->isEmpty()); - QCOMPARE(sourceChangedSpy.count(), 1); + QCOMPARE(sourceChangedSpy.size(), 1); QCOMPARE(sourceChangedSpy.takeFirst()[0].toUrl(), QUrl("subdir/index.html")); // using QUrl::fromLocalFile() browser->setSource(QUrl::fromLocalFile("anchor.html")); QVERIFY(!browser->document()->isEmpty()); - QCOMPARE(sourceChangedSpy.count(), 1); + QCOMPARE(sourceChangedSpy.size(), 1); QCOMPARE(sourceChangedSpy.takeFirst()[0].toUrl(), QUrl("file:anchor.html")); browser->setSource(QUrl("subdir/../qtextbrowser.html")); QVERIFY(!browser->document()->isEmpty()); - QCOMPARE(sourceChangedSpy.count(), 1); + QCOMPARE(sourceChangedSpy.size(), 1); QCOMPARE(sourceChangedSpy.takeFirst()[0].toUrl(), QUrl("subdir/../qtextbrowser.html")); } @@ -274,9 +275,9 @@ void tst_QTextBrowser::forwardBackwardAvailable() browser->setSource(QUrl::fromLocalFile("anchor.html")); QVERIFY(!browser->isBackwardAvailable()); QVERIFY(!browser->isForwardAvailable()); - QCOMPARE(backwardSpy.count(), 1); + QCOMPARE(backwardSpy.size(), 1); QVERIFY(!backwardSpy.at(0).at(0).toBool()); - QCOMPARE(forwardSpy.count(), 1); + QCOMPARE(forwardSpy.size(), 1); QVERIFY(!forwardSpy.at(0).at(0).toBool()); backwardSpy.clear(); @@ -285,9 +286,9 @@ void tst_QTextBrowser::forwardBackwardAvailable() browser->setSource(QUrl::fromLocalFile("bigpage.html")); QVERIFY(browser->isBackwardAvailable()); QVERIFY(!browser->isForwardAvailable()); - QCOMPARE(backwardSpy.count(), 1); + QCOMPARE(backwardSpy.size(), 1); QVERIFY(backwardSpy.at(0).at(0).toBool()); - QCOMPARE(forwardSpy.count(), 1); + QCOMPARE(forwardSpy.size(), 1); QVERIFY(!forwardSpy.at(0).at(0).toBool()); backwardSpy.clear(); @@ -296,9 +297,9 @@ void tst_QTextBrowser::forwardBackwardAvailable() browser->setSource(QUrl::fromLocalFile("pagewithbg.html")); QVERIFY(browser->isBackwardAvailable()); QVERIFY(!browser->isForwardAvailable()); - QCOMPARE(backwardSpy.count(), 1); + QCOMPARE(backwardSpy.size(), 1); QVERIFY(backwardSpy.at(0).at(0).toBool()); - QCOMPARE(forwardSpy.count(), 1); + QCOMPARE(forwardSpy.size(), 1); QVERIFY(!forwardSpy.at(0).at(0).toBool()); backwardSpy.clear(); @@ -307,9 +308,9 @@ void tst_QTextBrowser::forwardBackwardAvailable() browser->backward(); QVERIFY(browser->isBackwardAvailable()); QVERIFY(browser->isForwardAvailable()); - QCOMPARE(backwardSpy.count(), 1); + QCOMPARE(backwardSpy.size(), 1); QVERIFY(backwardSpy.at(0).at(0).toBool()); - QCOMPARE(forwardSpy.count(), 1); + QCOMPARE(forwardSpy.size(), 1); QVERIFY(forwardSpy.at(0).at(0).toBool()); backwardSpy.clear(); @@ -318,9 +319,9 @@ void tst_QTextBrowser::forwardBackwardAvailable() browser->backward(); QVERIFY(!browser->isBackwardAvailable()); QVERIFY(browser->isForwardAvailable()); - QCOMPARE(backwardSpy.count(), 1); + QCOMPARE(backwardSpy.size(), 1); QVERIFY(!backwardSpy.at(0).at(0).toBool()); - QCOMPARE(forwardSpy.count(), 1); + QCOMPARE(forwardSpy.size(), 1); QVERIFY(forwardSpy.at(0).at(0).toBool()); backwardSpy.clear(); @@ -329,9 +330,9 @@ void tst_QTextBrowser::forwardBackwardAvailable() browser->forward(); QVERIFY(browser->isBackwardAvailable()); QVERIFY(browser->isForwardAvailable()); - QCOMPARE(backwardSpy.count(), 1); + QCOMPARE(backwardSpy.size(), 1); QVERIFY(backwardSpy.at(0).at(0).toBool()); - QCOMPARE(forwardSpy.count(), 1); + QCOMPARE(forwardSpy.size(), 1); QVERIFY(forwardSpy.at(0).at(0).toBool()); backwardSpy.clear(); @@ -340,9 +341,9 @@ void tst_QTextBrowser::forwardBackwardAvailable() browser->forward(); QVERIFY(browser->isBackwardAvailable()); QVERIFY(!browser->isForwardAvailable()); - QCOMPARE(backwardSpy.count(), 1); + QCOMPARE(backwardSpy.size(), 1); QVERIFY(backwardSpy.at(0).at(0).toBool()); - QCOMPARE(forwardSpy.count(), 1); + QCOMPARE(forwardSpy.size(), 1); QVERIFY(!forwardSpy.at(0).at(0).toBool()); backwardSpy.clear(); @@ -360,9 +361,9 @@ void tst_QTextBrowser::clearHistory() browser->clearHistory(); QVERIFY(!browser->isBackwardAvailable()); QVERIFY(!browser->isForwardAvailable()); - QCOMPARE(backwardSpy.count(), 1); + QCOMPARE(backwardSpy.size(), 1); QVERIFY(!backwardSpy.at(0).at(0).toBool()); - QCOMPARE(forwardSpy.count(), 1); + QCOMPARE(forwardSpy.size(), 1); QVERIFY(!forwardSpy.at(0).at(0).toBool()); QVERIFY(browser->historyTitle(-1).isEmpty()); QVERIFY(browser->historyTitle(0).isEmpty()); @@ -374,9 +375,9 @@ void tst_QTextBrowser::clearHistory() browser->setSource(QUrl::fromLocalFile("anchor.html")); QVERIFY(!browser->isBackwardAvailable()); QVERIFY(!browser->isForwardAvailable()); - QCOMPARE(backwardSpy.count(), 1); + QCOMPARE(backwardSpy.size(), 1); QVERIFY(!backwardSpy.at(0).at(0).toBool()); - QCOMPARE(forwardSpy.count(), 1); + QCOMPARE(forwardSpy.size(), 1); QVERIFY(!forwardSpy.at(0).at(0).toBool()); backwardSpy.clear(); @@ -385,9 +386,9 @@ void tst_QTextBrowser::clearHistory() browser->setSource(QUrl::fromLocalFile("bigpage.html")); QVERIFY(browser->isBackwardAvailable()); QVERIFY(!browser->isForwardAvailable()); - QCOMPARE(backwardSpy.count(), 1); + QCOMPARE(backwardSpy.size(), 1); QVERIFY(backwardSpy.at(0).at(0).toBool()); - QCOMPARE(forwardSpy.count(), 1); + QCOMPARE(forwardSpy.size(), 1); QVERIFY(!forwardSpy.at(0).at(0).toBool()); backwardSpy.clear(); @@ -396,9 +397,9 @@ void tst_QTextBrowser::clearHistory() browser->clearHistory(); QVERIFY(!browser->isBackwardAvailable()); QVERIFY(!browser->isForwardAvailable()); - QCOMPARE(backwardSpy.count(), 1); + QCOMPARE(backwardSpy.size(), 1); QVERIFY(!backwardSpy.at(0).at(0).toBool()); - QCOMPARE(forwardSpy.count(), 1); + QCOMPARE(forwardSpy.size(), 1); QVERIFY(!forwardSpy.at(0).at(0).toBool()); QVERIFY(browser->historyTitle(-1).isEmpty()); QVERIFY(browser->historyTitle(1).isEmpty()); @@ -671,7 +672,7 @@ void tst_QTextBrowser::urlEncoding() browser->setEditFocus(true); #endif QTest::keyClick(browser, Qt::Key_Enter); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QUrl url = spy.at(0).at(0).toUrl(); QCOMPARE(url.toEncoded(), QByteArray("http://www.google.com/q=%22")); diff --git a/tests/auto/widgets/widgets/qtextedit/CMakeLists.txt b/tests/auto/widgets/widgets/qtextedit/CMakeLists.txt index efd264d3d3..e406e088ca 100644 --- a/tests/auto/widgets/widgets/qtextedit/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qtextedit/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qtextedit.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtextedit Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtextedit LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + # Collect test data list(APPEND test_data "fullWidthSelection") diff --git a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp index ff5d3ab083..ddf2bcfa85 100644 --- a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp +++ b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -33,6 +33,8 @@ #include "../../../shared/platforminputcontext.h" #include <private/qinputmethod_p.h> +#include <QtWidgets/private/qapplication_p.h> + Q_LOGGING_CATEGORY(lcTests, "qt.widgets.tests") //Used in copyAvailable @@ -196,6 +198,8 @@ private slots: void nextFormatAfterEnterPressed_data(); void nextFormatAfterEnterPressed(); + void dontCrashWithCss(); + private: void createSelection(); int blockCount() const; @@ -517,9 +521,9 @@ void tst_QTextEdit::clearShouldClearExtraSelections() sel.cursor = ed->textCursor(); sel.format.setProperty(QTextFormat::FullWidthSelection, true); ed->setExtraSelections(QList<QTextEdit::ExtraSelection>() << sel); - QCOMPARE(ed->extraSelections().count(), 1); + QCOMPARE(ed->extraSelections().size(), 1); ed->clear(); - QCOMPARE(ed->extraSelections().count(), 0); + QCOMPARE(ed->extraSelections().size(), 0); } void tst_QTextEdit::paragSeparatorOnPlaintextAppend() @@ -719,7 +723,7 @@ void tst_QTextEdit::cursorPositionChanged() spy.clear(); QTest::keyClick(ed, Qt::Key_A); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QTextCursor cursor = ed->textCursor(); cursor.movePosition(QTextCursor::Start); @@ -727,18 +731,18 @@ void tst_QTextEdit::cursorPositionChanged() cursor.movePosition(QTextCursor::End); spy.clear(); cursor.insertText("Test"); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); cursor.movePosition(QTextCursor::End); ed->setTextCursor(cursor); cursor.movePosition(QTextCursor::Start); spy.clear(); cursor.insertText("Test"); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); QTest::keyClick(ed, Qt::Key_Left); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); cursor.movePosition(QTextCursor::Start); ed->setTextCursor(cursor); @@ -747,14 +751,19 @@ void tst_QTextEdit::cursorPositionChanged() QTest::mouseDClick(ed->viewport(), Qt::LeftButton, {}, ed->cursorRect().center()); QVERIFY(ed->textCursor().hasSelection()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); CursorPositionChangedRecorder spy2(ed); QVERIFY(ed->textCursor().position() > 0); ed->setPlainText("Hello World"); - QCOMPARE(spy2.cursorPositions.count(), 1); + QCOMPARE(spy2.cursorPositions.size(), 1); QCOMPARE(spy2.cursorPositions.at(0), 0); QCOMPARE(ed->textCursor().position(), 0); + + ed->selectAll(); + QCOMPARE(spy2.cursorPositions.size(), 2); + QCOMPARE(spy2.cursorPositions.at(1), 11); + QCOMPARE(ed->textCursor().position(), 11); } void tst_QTextEdit::setTextCursor() @@ -769,7 +778,7 @@ void tst_QTextEdit::setTextCursor() spy.clear(); ed->setTextCursor(cursor); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } #ifndef QT_NO_CLIPBOARD @@ -786,7 +795,7 @@ void tst_QTextEdit::undoAvailableAfterPaste() const QString txt("Test"); QApplication::clipboard()->setText(txt); ed->paste(); - QVERIFY(spy.count() >= 1); + QVERIFY(spy.size() >= 1); QCOMPARE(ed->toPlainText(), txt); } #endif @@ -1039,7 +1048,7 @@ void tst_QTextEdit::noPropertiesOnDefaultTextEditCharFormat() // on a text edit. Font properties instead should be taken from the // widget's font (in sync with defaultFont property in document) and the // foreground color should be taken from the palette. - QCOMPARE(ed->currentCharFormat().properties().count(), 0); + QCOMPARE(ed->currentCharFormat().properties().size(), 0); } void tst_QTextEdit::setPlainTextShouldUseCurrentCharFormat() @@ -1061,9 +1070,9 @@ void tst_QTextEdit::setPlainTextShouldEmitTextChangedOnce() { QSignalSpy spy(ed, SIGNAL(textChanged())); ed->setPlainText("Yankee Doodle"); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); ed->setPlainText(""); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); } void tst_QTextEdit::overwriteMode() @@ -1345,7 +1354,7 @@ void tst_QTextEdit::copyAvailable_data() //Tests the copyAvailable slot for several cases void tst_QTextEdit::copyAvailable() { - QFETCH(pairListType,keystrokes); + QFETCH(const pairListType, keystrokes); QFETCH(QList<bool>, copyAvailable); QFETCH(QString, function); @@ -1358,9 +1367,8 @@ void tst_QTextEdit::copyAvailable() QSignalSpy spyCopyAvailabe(ed, SIGNAL(copyAvailable(bool))); //Execute Keystrokes - foreach(keyPairType keyPair, keystrokes) { + for (keyPairType keyPair : keystrokes) QTest::keyClick(ed, keyPair.first, keyPair.second ); - } //Execute ed->"function" if (function == "cut") @@ -1377,8 +1385,8 @@ void tst_QTextEdit::copyAvailable() //Compare spied signals QEXPECT_FAIL("Case7 T,A,A, <- + shift, <- + shift, <- + shift, ctrl + x, undo() | signals: true, false, true", "Wrong undo selection behaviour. Should be fixed in some future release. (See task: 132482)", Abort); - QCOMPARE(spyCopyAvailabe.count(), copyAvailable.count()); - for (int i=0;i<spyCopyAvailabe.count(); i++) { + QCOMPARE(spyCopyAvailabe.size(), copyAvailable.size()); + for (int i=0;i<spyCopyAvailabe.size(); i++) { QVariant variantSpyCopyAvailable = spyCopyAvailabe.at(i).at(0); QVERIFY2(variantSpyCopyAvailable.toBool() == copyAvailable.at(i), QString("Spied singnal: %1").arg(i).toLatin1()); } @@ -1414,10 +1422,10 @@ void tst_QTextEdit::moveCursor() QCOMPARE(ed->textCursor().position(), 0); ed->moveCursor(QTextCursor::NextCharacter); QCOMPARE(ed->textCursor().position(), 1); - QCOMPARE(cursorMovedSpy.count(), 1); + QCOMPARE(cursorMovedSpy.size(), 1); ed->moveCursor(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); QCOMPARE(ed->textCursor().position(), 2); - QCOMPARE(cursorMovedSpy.count(), 2); + QCOMPARE(cursorMovedSpy.size(), 2); QCOMPARE(ed->textCursor().selectedText(), QString("e")); } @@ -1692,7 +1700,7 @@ void tst_QTextEdit::ensureVisibleWithRtl() ed->setLayoutDirection(Qt::RightToLeft); ed->setLineWrapMode(QTextEdit::NoWrap); QString txt(500, QChar(QLatin1Char('a'))); - QCOMPARE(txt.length(), 500); + QCOMPARE(txt.size(), 500); ed->setPlainText(txt); ed->resize(100, 100); ed->show(); @@ -1743,7 +1751,7 @@ void tst_QTextEdit::extraSelections() ed->setExtraSelections(QList<QTextEdit::ExtraSelection>() << sel); QList<QTextEdit::ExtraSelection> selections = ed->extraSelections(); - QCOMPARE(selections.count(), 1); + QCOMPARE(selections.size(), 1); QCOMPARE(selections.at(0).cursor.position(), endPos); QCOMPARE(selections.at(0).cursor.anchor(), wordPos); } @@ -1885,27 +1893,27 @@ void tst_QTextEdit::selectionChanged() QTest::keyClick(ed, Qt::Key_Right); QCOMPARE(ed->textCursor().position(), 1); - QCOMPARE(selectionChangedSpy.count(), 0); + QCOMPARE(selectionChangedSpy.size(), 0); QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier); QCOMPARE(ed->textCursor().position(), 2); - QCOMPARE(selectionChangedSpy.count(), 1); + QCOMPARE(selectionChangedSpy.size(), 1); QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier); QCOMPARE(ed->textCursor().position(), 3); - QCOMPARE(selectionChangedSpy.count(), 2); + QCOMPARE(selectionChangedSpy.size(), 2); QTest::keyClick(ed, Qt::Key_Right, Qt::ShiftModifier); QCOMPARE(ed->textCursor().position(), 4); - QCOMPARE(selectionChangedSpy.count(), 3); + QCOMPARE(selectionChangedSpy.size(), 3); QTest::keyClick(ed, Qt::Key_Right); QCOMPARE(ed->textCursor().position(), 4); - QCOMPARE(selectionChangedSpy.count(), 4); + QCOMPARE(selectionChangedSpy.size(), 4); QTest::keyClick(ed, Qt::Key_Right); QCOMPARE(ed->textCursor().position(), 5); - QCOMPARE(selectionChangedSpy.count(), 4); + QCOMPARE(selectionChangedSpy.size(), 4); } #ifndef QT_NO_CLIPBOARD @@ -2532,12 +2540,11 @@ void tst_QTextEdit::inputMethodEvent() QInputMethodEvent event; event.setCommitString("text"); QApplication::sendEvent(ed, &event); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(ed->toPlainText(), QString("text")); // test that input method gets chance to commit preedit when removing focus ed->setText(""); - QApplication::setActiveWindow(ed); QTRY_VERIFY(QApplication::focusWindow()); QCOMPARE(qApp->focusObject(), ed); @@ -2562,7 +2569,7 @@ void tst_QTextEdit::inputMethodSelection() cursor.setPosition(5, QTextCursor::KeepAnchor); ed->setTextCursor(cursor); - QCOMPARE(selectionSpy.count(), 1); + QCOMPARE(selectionSpy.size(), 1); QCOMPARE(ed->textCursor().selectionStart(), 0); QCOMPARE(ed->textCursor().selectionEnd(), 5); @@ -2571,7 +2578,7 @@ void tst_QTextEdit::inputMethodSelection() QInputMethodEvent event("", attributes); QApplication::sendEvent(ed, &event); - QCOMPARE(selectionSpy.count(), 2); + QCOMPARE(selectionSpy.size(), 2); QCOMPARE(ed->textCursor().selectionStart(), 12); QCOMPARE(ed->textCursor().selectionEnd(), 17); } @@ -2586,7 +2593,7 @@ void tst_QTextEdit::inputMethodQuery() QGuiApplication::sendEvent(ed, &event); int anchor = event.value(Qt::ImAnchorPosition).toInt(); int position = event.value(Qt::ImCursorPosition).toInt(); - QCOMPARE(qAbs(position - anchor), text.length()); + QCOMPARE(qAbs(position - anchor), text.size()); QCOMPARE(event.value(Qt::ImEnabled).toBool(), true); ed->setEnabled(false); @@ -2671,7 +2678,7 @@ void tst_QTextEdit::countTextChangedOnRemove() QKeyEvent event(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier); QCoreApplication::instance()->notify(&edit, &event); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } #if QT_CONFIG(regularexpression) @@ -3058,5 +3065,14 @@ void tst_QTextEdit::nextFormatAfterEnterPressed() QCOMPARE(prevBlockCursor.charFormat().property(it.key()), it.value()); } +void tst_QTextEdit::dontCrashWithCss() +{ + qApp->setStyleSheet("QWidget { font: 10pt; }"); + QTextEdit edit; + edit.show(); + qApp->setStyleSheet(QString()); +} + + QTEST_MAIN(tst_QTextEdit) #include "tst_qtextedit.moc" diff --git a/tests/auto/widgets/widgets/qtoolbar/CMakeLists.txt b/tests/auto/widgets/widgets/qtoolbar/CMakeLists.txt index 3d8b07eaba..e9fb01c3e8 100644 --- a/tests/auto/widgets/widgets/qtoolbar/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qtoolbar/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qtoolbar.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtoolbar Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtoolbar LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtoolbar SOURCES tst_qtoolbar.cpp diff --git a/tests/auto/widgets/widgets/qtoolbar/tst_qtoolbar.cpp b/tests/auto/widgets/widgets/qtoolbar/tst_qtoolbar.cpp index c1d08316f8..8b8c74b1e7 100644 --- a/tests/auto/widgets/widgets/qtoolbar/tst_qtoolbar.cpp +++ b/tests/auto/widgets/widgets/qtoolbar/tst_qtoolbar.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -22,6 +22,8 @@ #include <qlabel.h> #include <private/qtoolbarextension_p.h> +#include <QtWidgets/private/qapplication_p.h> + QT_FORWARD_DECLARE_CLASS(QAction) class tst_QToolBar : public QObject @@ -137,12 +139,12 @@ void tst_QToolBar::allowedAreas() QVERIFY(!tb.isAreaAllowed(Qt::RightToolBarArea)); QVERIFY(!tb.isAreaAllowed(Qt::TopToolBarArea)); QVERIFY(!tb.isAreaAllowed(Qt::BottomToolBarArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()), tb.allowedAreas()); spy.clear(); tb.setAllowedAreas(tb.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setAllowedAreas(Qt::RightToolBarArea); QCOMPARE((int)tb.allowedAreas(), (int)Qt::RightToolBarArea); @@ -150,12 +152,12 @@ void tst_QToolBar::allowedAreas() QVERIFY(tb.isAreaAllowed(Qt::RightToolBarArea)); QVERIFY(!tb.isAreaAllowed(Qt::TopToolBarArea)); QVERIFY(!tb.isAreaAllowed(Qt::BottomToolBarArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()), tb.allowedAreas()); spy.clear(); tb.setAllowedAreas(tb.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setAllowedAreas(Qt::TopToolBarArea); QCOMPARE((int)tb.allowedAreas(), (int)Qt::TopToolBarArea); @@ -163,12 +165,12 @@ void tst_QToolBar::allowedAreas() QVERIFY(!tb.isAreaAllowed(Qt::RightToolBarArea)); QVERIFY(tb.isAreaAllowed(Qt::TopToolBarArea)); QVERIFY(!tb.isAreaAllowed(Qt::BottomToolBarArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()), tb.allowedAreas()); spy.clear(); tb.setAllowedAreas(tb.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setAllowedAreas(Qt::BottomToolBarArea); QCOMPARE((int)tb.allowedAreas(), (int)Qt::BottomToolBarArea); @@ -176,12 +178,12 @@ void tst_QToolBar::allowedAreas() QVERIFY(!tb.isAreaAllowed(Qt::RightToolBarArea)); QVERIFY(!tb.isAreaAllowed(Qt::TopToolBarArea)); QVERIFY(tb.isAreaAllowed(Qt::BottomToolBarArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()), tb.allowedAreas()); spy.clear(); tb.setAllowedAreas(tb.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); // multiple dock window areas tb.setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea); @@ -190,12 +192,12 @@ void tst_QToolBar::allowedAreas() QVERIFY(!tb.isAreaAllowed(Qt::RightToolBarArea)); QVERIFY(tb.isAreaAllowed(Qt::TopToolBarArea)); QVERIFY(tb.isAreaAllowed(Qt::BottomToolBarArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()), tb.allowedAreas()); spy.clear(); tb.setAllowedAreas(tb.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setAllowedAreas(Qt::LeftToolBarArea | Qt::RightToolBarArea); QCOMPARE(tb.allowedAreas(), Qt::LeftToolBarArea | Qt::RightToolBarArea); @@ -203,12 +205,12 @@ void tst_QToolBar::allowedAreas() QVERIFY(tb.isAreaAllowed(Qt::RightToolBarArea)); QVERIFY(!tb.isAreaAllowed(Qt::TopToolBarArea)); QVERIFY(!tb.isAreaAllowed(Qt::BottomToolBarArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()), tb.allowedAreas()); spy.clear(); tb.setAllowedAreas(tb.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setAllowedAreas(Qt::TopToolBarArea | Qt::LeftToolBarArea); QCOMPARE(tb.allowedAreas(), Qt::TopToolBarArea | Qt::LeftToolBarArea); @@ -216,12 +218,12 @@ void tst_QToolBar::allowedAreas() QVERIFY(!tb.isAreaAllowed(Qt::RightToolBarArea)); QVERIFY(tb.isAreaAllowed(Qt::TopToolBarArea)); QVERIFY(!tb.isAreaAllowed(Qt::BottomToolBarArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()), tb.allowedAreas()); spy.clear(); tb.setAllowedAreas(tb.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setAllowedAreas(Qt::BottomToolBarArea | Qt::RightToolBarArea); QCOMPARE(tb.allowedAreas(), Qt::BottomToolBarArea | Qt::RightToolBarArea); @@ -229,12 +231,12 @@ void tst_QToolBar::allowedAreas() QVERIFY(tb.isAreaAllowed(Qt::RightToolBarArea)); QVERIFY(!tb.isAreaAllowed(Qt::TopToolBarArea)); QVERIFY(tb.isAreaAllowed(Qt::BottomToolBarArea)); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::ToolBarAreas *>(spy.at(0).value(0).constData()), tb.allowedAreas()); spy.clear(); tb.setAllowedAreas(tb.allowedAreas()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QToolBar::orientation() @@ -246,48 +248,48 @@ void tst_QToolBar::orientation() tb.setOrientation(Qt::Vertical); QCOMPARE(tb.orientation(), Qt::Vertical); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::Orientation *>(spy.at(0).value(0).constData()), tb.orientation()); spy.clear(); tb.setOrientation(tb.orientation()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setOrientation(Qt::Horizontal); QCOMPARE(tb.orientation(), Qt::Horizontal); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::Orientation *>(spy.at(0).value(0).constData()), tb.orientation()); spy.clear(); tb.setOrientation(tb.orientation()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setOrientation(Qt::Vertical); QCOMPARE(tb.orientation(), Qt::Vertical); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::Orientation *>(spy.at(0).value(0).constData()), tb.orientation()); spy.clear(); tb.setOrientation(tb.orientation()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setOrientation(Qt::Horizontal); QCOMPARE(tb.orientation(), Qt::Horizontal); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::Orientation *>(spy.at(0).value(0).constData()), tb.orientation()); spy.clear(); tb.setOrientation(tb.orientation()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setOrientation(Qt::Vertical); QCOMPARE(tb.orientation(), Qt::Vertical); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(*static_cast<const Qt::Orientation *>(spy.at(0).value(0).constData()), tb.orientation()); spy.clear(); tb.setOrientation(tb.orientation()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QToolBar::addAction() @@ -297,13 +299,13 @@ void tst_QToolBar::addAction() { QAction action(0); - QCOMPARE(tb.actions().count(), 0); + QCOMPARE(tb.actions().size(), 0); tb.addAction(&action); - QCOMPARE(tb.actions().count(), 1); + QCOMPARE(tb.actions().size(), 1); QCOMPARE(tb.actions()[0], &action); tb.clear(); - QCOMPARE(tb.actions().count(), 0); + QCOMPARE(tb.actions().size(), 0); } { @@ -326,14 +328,14 @@ void tst_QToolBar::addAction() QCOMPARE(icon, action4->icon()); QCOMPARE(text, action4->text()); - QCOMPARE(tb.actions().count(), 4); + QCOMPARE(tb.actions().size(), 4); QCOMPARE(tb.actions()[0], action1); QCOMPARE(tb.actions()[1], action2); QCOMPARE(tb.actions()[2], action3); QCOMPARE(tb.actions()[3], action4); tb.clear(); - QCOMPARE(tb.actions().count(), 0); + QCOMPARE(tb.actions().size(), 0); } } @@ -362,19 +364,19 @@ void tst_QToolBar::insertAction() QAction action3(0); QAction action4(0); - QCOMPARE(tb.actions().count(), 0); + QCOMPARE(tb.actions().size(), 0); tb.insertAction(0, &action1); tb.insertAction(&action1, &action2); tb.insertAction(&action2, &action3); tb.insertAction(&action3, &action4); - QCOMPARE(tb.actions().count(), 4); + QCOMPARE(tb.actions().size(), 4); QCOMPARE(tb.actions()[0], &action4); QCOMPARE(tb.actions()[1], &action3); QCOMPARE(tb.actions()[2], &action2); QCOMPARE(tb.actions()[3], &action1); tb.clear(); - QCOMPARE(tb.actions().count(), 0); + QCOMPARE(tb.actions().size(), 0); } void tst_QToolBar::addSeparator() @@ -388,13 +390,13 @@ void tst_QToolBar::addSeparator() QAction *sep = tb.addSeparator(); tb.addAction(&action2); - QCOMPARE(tb.actions().count(), 3); + QCOMPARE(tb.actions().size(), 3); QCOMPARE(tb.actions()[0], &action1); QCOMPARE(tb.actions()[1], sep); QCOMPARE(tb.actions()[2], &action2); tb.clear(); - QCOMPARE(tb.actions().count(), 0); + QCOMPARE(tb.actions().size(), 0); } void tst_QToolBar::insertSeparator() @@ -408,13 +410,13 @@ void tst_QToolBar::insertSeparator() tb.addAction(&action2); QAction *sep = tb.insertSeparator(&action2); - QCOMPARE(tb.actions().count(), 3); + QCOMPARE(tb.actions().size(), 3); QCOMPARE(tb.actions()[0], &action1); QCOMPARE(tb.actions()[1], sep); QCOMPARE(tb.actions()[2], &action2); tb.clear(); - QCOMPARE(tb.actions().count(), 0); + QCOMPARE(tb.actions().size(), 0); } void tst_QToolBar::addWidget() @@ -429,7 +431,7 @@ void tst_QToolBar::addWidget() QAction *widget = tb.addWidget(&w); tb.addAction(&action2); - QCOMPARE(tb.actions().count(), 3); + QCOMPARE(tb.actions().size(), 3); QCOMPARE(tb.actions()[0], &action1); QCOMPARE(tb.actions()[1], widget); QCOMPARE(tb.actions()[2], &action2); @@ -437,18 +439,18 @@ void tst_QToolBar::addWidget() // it should be possible to reuse the action returned by // addWidget() to place the widget somewhere else in the toolbar tb.removeAction(widget); - QCOMPARE(tb.actions().count(), 2); + QCOMPARE(tb.actions().size(), 2); QCOMPARE(tb.actions()[0], &action1); QCOMPARE(tb.actions()[1], &action2); tb.addAction(widget); - QCOMPARE(tb.actions().count(), 3); + QCOMPARE(tb.actions().size(), 3); QCOMPARE(tb.actions()[0], &action1); QCOMPARE(tb.actions()[1], &action2); QCOMPARE(tb.actions()[2], widget); tb.clear(); - QCOMPARE(tb.actions().count(), 0); + QCOMPARE(tb.actions().size(), 0); } void tst_QToolBar::insertWidget() @@ -463,7 +465,7 @@ void tst_QToolBar::insertWidget() tb.addAction(&action2); QAction *widget = tb.insertWidget(&action2, &w); - QCOMPARE(tb.actions().count(), 3); + QCOMPARE(tb.actions().size(), 3); QCOMPARE(tb.actions()[0], &action1); QCOMPARE(tb.actions()[1], widget); QCOMPARE(tb.actions()[2], &action2); @@ -471,18 +473,18 @@ void tst_QToolBar::insertWidget() // it should be possible to reuse the action returned by // addWidget() to place the widget somewhere else in the toolbar tb.removeAction(widget); - QCOMPARE(tb.actions().count(), 2); + QCOMPARE(tb.actions().size(), 2); QCOMPARE(tb.actions()[0], &action1); QCOMPARE(tb.actions()[1], &action2); tb.insertAction(&action1, widget); - QCOMPARE(tb.actions().count(), 3); + QCOMPARE(tb.actions().size(), 3); QCOMPARE(tb.actions()[0], widget); QCOMPARE(tb.actions()[1], &action1); QCOMPARE(tb.actions()[2], &action2); tb.clear(); - QCOMPARE(tb.actions().count(), 0); + QCOMPARE(tb.actions().size(), 0); { QToolBar tb; @@ -624,43 +626,43 @@ void tst_QToolBar::iconSize() QCOMPARE(tb.iconSize(), defaultIconSize); tb.setIconSize(defaultIconSize); QCOMPARE(tb.iconSize(), defaultIconSize); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); tb.setIconSize(largeIconSize); QCOMPARE(tb.iconSize(), largeIconSize); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.first().first().toSize(), largeIconSize); // no-op spy.clear(); tb.setIconSize(largeIconSize); QCOMPARE(tb.iconSize(), largeIconSize); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); tb.setIconSize(defaultIconSize); QCOMPARE(tb.iconSize(), defaultIconSize); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.first().first().toSize(), defaultIconSize); // no-op spy.clear(); tb.setIconSize(defaultIconSize); QCOMPARE(tb.iconSize(), defaultIconSize); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); spy.clear(); tb.setIconSize(smallIconSize); QCOMPARE(tb.iconSize(), smallIconSize); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.first().first().toSize(), smallIconSize); // no-op spy.clear(); tb.setIconSize(smallIconSize); QCOMPARE(tb.iconSize(), smallIconSize); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); // setting the icon size to an invalid QSize will reset the // iconSize property to the default @@ -688,28 +690,28 @@ void tst_QToolBar::iconSize() // explicitly set it to the default tb.setIconSize(defaultIconSize); QCOMPARE(tb.iconSize(), defaultIconSize); - QCOMPARE(tbSpy.count(), 0); + QCOMPARE(tbSpy.size(), 0); mw.addToolBar(&tb); // tb icon size should not change since it has been explicitly set QCOMPARE(tb.iconSize(), defaultIconSize); - QCOMPARE(tbSpy.count(), 0); + QCOMPARE(tbSpy.size(), 0); mw.setIconSize(largeIconSize); QCOMPARE(tb.iconSize(), defaultIconSize); - QCOMPARE(tbSpy.count(), 0); + QCOMPARE(tbSpy.size(), 0); mw.setIconSize(defaultIconSize); QCOMPARE(tb.iconSize(), defaultIconSize); - QCOMPARE(tbSpy.count(), 0); + QCOMPARE(tbSpy.size(), 0); mw.setIconSize(smallIconSize); QCOMPARE(tb.iconSize(), defaultIconSize); - QCOMPARE(tbSpy.count(), 0); + QCOMPARE(tbSpy.size(), 0); // resetting to the default should cause the toolbar to take // on the mainwindow's icon size @@ -732,51 +734,51 @@ void tst_QToolBar::toolButtonStyle() QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly); tb.setToolButtonStyle(Qt::ToolButtonIconOnly); QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setToolButtonStyle(Qt::ToolButtonTextOnly); QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextOnly); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); // no-op tb.setToolButtonStyle(Qt::ToolButtonTextOnly); QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextOnly); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setToolButtonStyle(Qt::ToolButtonIconOnly); QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); // no-op tb.setToolButtonStyle(Qt::ToolButtonIconOnly); QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setToolButtonStyle(Qt::ToolButtonTextBesideIcon); QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextBesideIcon); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); // no-op tb.setToolButtonStyle(Qt::ToolButtonTextBesideIcon); QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextBesideIcon); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setToolButtonStyle(Qt::ToolButtonTextUnderIcon); QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextUnderIcon); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); // no-op tb.setToolButtonStyle(Qt::ToolButtonTextUnderIcon); QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextUnderIcon); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.setToolButtonStyle(Qt::ToolButtonFollowStyle); QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonFollowStyle); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } { @@ -790,28 +792,28 @@ void tst_QToolBar::toolButtonStyle() // explicitly set the tb to the default tb.setToolButtonStyle(Qt::ToolButtonIconOnly); QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly); - QCOMPARE(tbSpy.count(), 0); + QCOMPARE(tbSpy.size(), 0); mw.addToolBar(&tb); // tb icon size should not change since it has been explicitly set QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly); - QCOMPARE(tbSpy.count(), 0); + QCOMPARE(tbSpy.size(), 0); mw.setToolButtonStyle(Qt::ToolButtonIconOnly); QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly); - QCOMPARE(tbSpy.count(), 0); + QCOMPARE(tbSpy.size(), 0); mw.setToolButtonStyle(Qt::ToolButtonTextOnly); QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly); - QCOMPARE(tbSpy.count(), 0); + QCOMPARE(tbSpy.size(), 0); mw.setToolButtonStyle(Qt::ToolButtonTextUnderIcon); QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonIconOnly); - QCOMPARE(tbSpy.count(), 0); + QCOMPARE(tbSpy.size(), 0); // note: there is no way to clear the explicitly set tool // button style... once you explicitly set it, the toolbar @@ -925,25 +927,25 @@ void tst_QToolBar::visibilityChanged() mw.addToolBar(&tb); mw.show(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toBool(), true); spy.clear(); tb.hide(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toBool(), false); spy.clear(); tb.hide(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); tb.show(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QCOMPARE(spy.at(0).at(0).toBool(), true); spy.clear(); tb.show(); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QToolBar::actionOwnership() @@ -1020,12 +1022,11 @@ void tst_QToolBar::accel() QSignalSpy spy(action, SIGNAL(triggered(bool))); mw.show(); - QApplication::setActiveWindow(&mw); QVERIFY(QTest::qWaitForWindowActive(&mw)); QTest::keyClick(&mw, Qt::Key_T, Qt::AltModifier); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); #ifdef Q_OS_MAC qt_set_sequence_auto_mnemonic(false); #endif diff --git a/tests/auto/widgets/widgets/qtoolbox/CMakeLists.txt b/tests/auto/widgets/widgets/qtoolbox/CMakeLists.txt index 84a000b0b6..362fba25a4 100644 --- a/tests/auto/widgets/widgets/qtoolbox/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qtoolbox/CMakeLists.txt @@ -1,12 +1,16 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qtoolbox.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtoolbox Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtoolbox LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtoolbox SOURCES tst_qtoolbox.cpp diff --git a/tests/auto/widgets/widgets/qtoolbox/tst_qtoolbox.cpp b/tests/auto/widgets/widgets/qtoolbox/tst_qtoolbox.cpp index 5fe06707be..fb14ceb79c 100644 --- a/tests/auto/widgets/widgets/qtoolbox/tst_qtoolbox.cpp +++ b/tests/auto/widgets/widgets/qtoolbox/tst_qtoolbox.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> diff --git a/tests/auto/widgets/widgets/qtoolbutton/CMakeLists.txt b/tests/auto/widgets/widgets/qtoolbutton/CMakeLists.txt index 15cd3c2c19..7c8b41b5e6 100644 --- a/tests/auto/widgets/widgets/qtoolbutton/CMakeLists.txt +++ b/tests/auto/widgets/widgets/qtoolbutton/CMakeLists.txt @@ -1,16 +1,21 @@ # Copyright (C) 2022 The Qt Company Ltd. -# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -# Generated from qtoolbutton.pro. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtoolbutton Test: ##################################################################### +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtoolbutton LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + qt_internal_add_test(tst_qtoolbutton SOURCES tst_qtoolbutton.cpp LIBRARIES Qt::Gui Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp b/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp index abccd7bec8..b77a9c0eec 100644 --- a/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp +++ b/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QTest> @@ -15,6 +15,8 @@ #include <qscreen.h> #include <qlabel.h> +#include <QtWidgets/private/qapplication_p.h> + class tst_QToolButton : public QObject { Q_OBJECT @@ -32,6 +34,7 @@ private slots: void qtbug_26956_popupTimerDone(); void qtbug_34759_sizeHintResetWhenSettingMenu(); void defaultActionSynced(); + void deleteInHandler(); protected slots: void sendMouseClick(); @@ -118,11 +121,11 @@ void tst_QToolButton::triggered() toolButton->setDefaultAction(defaultAction); mainWidget.show(); - QApplication::setActiveWindow(&mainWidget); + QApplicationPrivate::setActiveWindow(&mainWidget); QVERIFY(QTest::qWaitForWindowActive(&mainWidget)); defaultAction->trigger(); - QCOMPARE(spy.count(),1); + QCOMPARE(spy.size(),1); QCOMPARE(qvariant_cast<QAction *>(spy.at(0).at(0)), defaultAction); m_menu = menu.data(); @@ -133,7 +136,7 @@ void tst_QToolButton::triggered() timer->start(); QTimer::singleShot(10000, &mainWidget, SLOT(close())); // Emergency bail-out toolButton->showMenu(); - QTRY_COMPARE(spy.count(),2); + QTRY_COMPARE(spy.size(),2); QCOMPARE(qvariant_cast<QAction *>(spy.at(1).at(0)), one); } @@ -179,14 +182,13 @@ void tst_QToolButton::task176137_autoRepeatOfAction() label->move(0, 50); mainWidget.show(); - QApplication::setActiveWindow(&mainWidget); QVERIFY(QTest::qWaitForWindowActive(&mainWidget)); QSignalSpy spy(&action,SIGNAL(triggered())); QTest::mousePress (toolButton, Qt::LeftButton); QTest::qWait(2000); QTest::mouseRelease (toolButton, Qt::LeftButton, {}, {}); - QCOMPARE(spy.count(),1); + QCOMPARE(spy.size(),1); // try again with auto repeat toolButton->setAutoRepeat (true); @@ -196,11 +198,11 @@ void tst_QToolButton::task176137_autoRepeatOfAction() QTest::mouseRelease (toolButton, Qt::LeftButton, {}, {}); const qreal expected = (3000 - toolButton->autoRepeatDelay()) / toolButton->autoRepeatInterval() + 1; //we check that the difference is small (on some systems timers are not super accurate) - qreal diff = (expected - repeatSpy.count()) / expected; + qreal diff = (expected - repeatSpy.size()) / expected; QVERIFY2(qAbs(diff) < 0.2, qPrintable( QString("expected: %1, actual: %2, diff (fraction): %3") .arg(expected) - .arg(repeatSpy.count()) + .arg(repeatSpy.size()) .arg(diff))); } @@ -273,21 +275,21 @@ void tst_QToolButton::defaultActionSynced() tb.setChecked(true); QVERIFY(a.isChecked()); - QCOMPARE(tbSpy.count(), ++tbToggledCount); - QCOMPARE(aSpy.count(), ++aToggledCount); + QCOMPARE(tbSpy.size(), ++tbToggledCount); + QCOMPARE(aSpy.size(), ++aToggledCount); tb.setChecked(false); QVERIFY(!a.isChecked()); - QCOMPARE(tbSpy.count(), ++tbToggledCount); - QCOMPARE(aSpy.count(), ++aToggledCount); + QCOMPARE(tbSpy.size(), ++tbToggledCount); + QCOMPARE(aSpy.size(), ++aToggledCount); a.setChecked(true); QVERIFY(tb.isChecked()); - QCOMPARE(tbSpy.count(), ++tbToggledCount); - QCOMPARE(aSpy.count(), ++aToggledCount); + QCOMPARE(tbSpy.size(), ++tbToggledCount); + QCOMPARE(aSpy.size(), ++aToggledCount); a.setChecked(false); QVERIFY(!tb.isChecked()); - QCOMPARE(tbSpy.count(), ++tbToggledCount); - QCOMPARE(aSpy.count(), ++aToggledCount); + QCOMPARE(tbSpy.size(), ++tbToggledCount); + QCOMPARE(aSpy.size(), ++aToggledCount); QAction b; QSignalSpy bSpy(&b, SIGNAL(toggled(bool))); @@ -301,17 +303,34 @@ void tst_QToolButton::defaultActionSynced() QVERIFY(!a.isChecked()); QVERIFY(b.isChecked()); - QCOMPARE(tbSpy.count(), ++tbToggledCount); - QCOMPARE(aSpy.count(), aToggledCount); - QCOMPARE(bSpy.count(), ++bToggledCount); + QCOMPARE(tbSpy.size(), ++tbToggledCount); + QCOMPARE(aSpy.size(), aToggledCount); + QCOMPARE(bSpy.size(), ++bToggledCount); tb.click(); QVERIFY(!a.isChecked()); QVERIFY(!tb.isChecked()); QVERIFY(!b.isChecked()); - QCOMPARE(tbSpy.count(), ++tbToggledCount); - QCOMPARE(aSpy.count(), aToggledCount); - QCOMPARE(bSpy.count(), ++bToggledCount); + QCOMPARE(tbSpy.size(), ++tbToggledCount); + QCOMPARE(aSpy.size(), aToggledCount); + QCOMPARE(bSpy.size(), ++bToggledCount); +} + +void tst_QToolButton::deleteInHandler() +{ + // Tests that if something deletes the button + // while its event handler is still on the callstack, we don't crash + + QPointer<QToolButton> tb = new QToolButton(); + tb->show(); + QVERIFY(QTest::qWaitForWindowActive(tb)); + + connect(tb, &QToolButton::clicked, this, [tb] { + delete tb; + }); + + QTest::mouseClick(tb, Qt::LeftButton); + QVERIFY(!tb); } QTEST_MAIN(tst_QToolButton) |