diff options
Diffstat (limited to 'tests/auto/widgets/dialogs')
48 files changed, 1338 insertions, 2124 deletions
diff --git a/tests/auto/widgets/dialogs/CMakeLists.txt b/tests/auto/widgets/dialogs/CMakeLists.txt index 0c52076efe..f46950b6bf 100644 --- a/tests/auto/widgets/dialogs/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/CMakeLists.txt @@ -1,17 +1,18 @@ -# Generated from dialogs.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause add_subdirectory(qcolordialog) add_subdirectory(qdialog) add_subdirectory(qerrormessage) -add_subdirectory(qfiledialog) add_subdirectory(qfiledialog2) add_subdirectory(qfontdialog) add_subdirectory(qinputdialog) -add_subdirectory(qmessagebox) add_subdirectory(qprogressdialog) add_subdirectory(qwizard) -if(NOT MINGW) - add_subdirectory(qfilesystemmodel) +add_subdirectory(qfiledialog) +# QTBUG-101217, qmessagebox hangs on Android +if(NOT ANDROID) + add_subdirectory(qmessagebox) endif() if(QT_FEATURE_private_tests) add_subdirectory(qsidebar) diff --git a/tests/auto/widgets/dialogs/dialogs.pro b/tests/auto/widgets/dialogs/dialogs.pro deleted file mode 100644 index cf548f2dea..0000000000 --- a/tests/auto/widgets/dialogs/dialogs.pro +++ /dev/null @@ -1,20 +0,0 @@ -TEMPLATE=subdirs -SUBDIRS=\ - qcolordialog \ - qdialog \ - qerrormessage \ - qfiledialog \ - qfiledialog2 \ - qfilesystemmodel \ - qfontdialog \ - qinputdialog \ - qmessagebox \ - qprogressdialog \ - qsidebar \ - qwizard \ - -!qtConfig(private_tests): SUBDIRS -= \ - qsidebar \ - -mac:qinputdialog.CONFIG += no_check_target # QTBUG-25496 -mingw: SUBDIRS -= qfilesystemmodel # QTBUG-29403 diff --git a/tests/auto/widgets/dialogs/qcolordialog/CMakeLists.txt b/tests/auto/widgets/dialogs/qcolordialog/CMakeLists.txt index e0c25e381b..2cba18c0f0 100644 --- a/tests/auto/widgets/dialogs/qcolordialog/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qcolordialog/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qcolordialog.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qcolordialog Test: ##################################################################### -qt_add_test(tst_qcolordialog +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 - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui Qt::Widgets ) diff --git a/tests/auto/widgets/dialogs/qcolordialog/qcolordialog.pro b/tests/auto/widgets/dialogs/qcolordialog/qcolordialog.pro deleted file mode 100644 index 563db6e887..0000000000 --- a/tests/auto/widgets/dialogs/qcolordialog/qcolordialog.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qcolordialog -QT += widgets testlib -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 413b865f04..5ae8eaf30d 100644 --- a/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp +++ b/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp @@ -1,35 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// 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) @@ -50,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 @@ -58,7 +39,7 @@ class TestNativeDialog : public QColorDialog public: QWidget *m_activeModalWidget; - TestNativeDialog(QWidget *parent = 0) + TestNativeDialog(QWidget *parent = nullptr) : QColorDialog(parent), m_activeModalWidget(0) { QTimer::singleShot(1, this, SLOT(test_activeModalWidgetSignal())); @@ -102,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 ); @@ -151,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 54bfb2aedb..d69310541d 100644 --- a/tests/auto/widgets/dialogs/qdialog/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qdialog/CMakeLists.txt @@ -1,15 +1,23 @@ -# Generated from qdialog.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qdialog Test: ##################################################################### -qt_add_test(tst_qdialog +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 - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate Qt::Widgets + Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/dialogs/qdialog/qdialog.pro b/tests/auto/widgets/dialogs/qdialog/qdialog.pro deleted file mode 100644 index 0a065b1a87..0000000000 --- a/tests/auto/widgets/dialogs/qdialog/qdialog.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qdialog -QT += widgets testlib gui-private core-private -SOURCES += tst_qdialog.cpp diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp index fa374ee076..13f971f5f0 100644 --- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp +++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp @@ -1,34 +1,10 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "../../../shared/highdpi.h" -#include <QtTest/QtTest> +#include <QTest> +#include <QTestEventLoop> #include <qdialog.h> #include <qapplication.h> @@ -36,7 +12,9 @@ #include <qpushbutton.h> #include <qstyle.h> #include <QVBoxLayout> +#include <QSignalSpy> #include <QSizeGrip> +#include <QTimer> #include <QGraphicsProxyWidget> #include <QGraphicsView> #include <QWindow> @@ -44,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 @@ -67,6 +47,8 @@ private slots: void showMinimized(); void showFullScreen(); void showAsTool(); + void showWithoutActivating_data(); + void showWithoutActivating(); void toolDialogPosition(); void deleteMainDefault(); void deleteInExec(); @@ -79,6 +61,11 @@ private slots: void transientParent_data(); void transientParent(); void dialogInGraphicsView(); + void keepPositionOnClose(); + void virtualsOnClose(); + void deleteOnDone(); + void quitOnDone(); + void focusWidgetAfterOpen(); }; // Testing get/set functions @@ -98,18 +85,20 @@ void tst_QDialog::getSetCheck() class ToolDialog : public QDialog { public: - ToolDialog(QWidget *parent = 0) + ToolDialog(QWidget *parent = nullptr) : QDialog(parent, Qt::Tool), mWasActive(false), mWasModalWindow(false), tId(-1) {} bool wasActive() const { return mWasActive; } bool wasModalWindow() const { return mWasModalWindow; } - int exec() { + int exec() override + { tId = startTimer(300); return QDialog::exec(); } protected: - void timerEvent(QTimerEvent *event) { + void timerEvent(QTimerEvent *event) override + { if (tId == event->timerId()) { killTimer(tId); mWasActive = isActiveWindow(); @@ -146,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); @@ -295,9 +284,12 @@ void tst_QDialog::showFullScreen() void tst_QDialog::showAsTool() { -#if defined(Q_OS_UNIX) - QSKIP("Qt/X11: Skipped since activeWindow() is not respected by all window managers"); -#endif + 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()); @@ -313,6 +305,33 @@ void tst_QDialog::showAsTool() } } +void tst_QDialog::showWithoutActivating_data() +{ + QTest::addColumn<bool>("showWithoutActivating"); + QTest::addColumn<int>("focusInCount"); + + QTest::addRow("showWithoutActivating") << true << 0; + QTest::addRow("showWithActivating") << false << 1; +} + +void tst_QDialog::showWithoutActivating() +{ + QFETCH(bool, showWithoutActivating); + QFETCH(int, focusInCount); + + struct Dialog : public QDialog + { + int focusInCount = 0; + protected: + void focusInEvent(QFocusEvent *) override { ++focusInCount; } + } dialog; + dialog.setAttribute(Qt::WA_ShowWithoutActivating, showWithoutActivating); + + dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + QCOMPARE(dialog.focusInCount, focusInCount); +} + // Verify that pos() returns the same before and after show() // for a dialog with the Tool window type. void tst_QDialog::toolDialogPosition() @@ -321,7 +340,7 @@ void tst_QDialog::toolDialogPosition() dialog.move(QPoint(100,100)); const QPoint beforeShowPosition = dialog.pos(); dialog.show(); - const int fuzz = int(dialog.devicePixelRatioF()); + const int fuzz = int(dialog.devicePixelRatio()); const QPoint afterShowPosition = dialog.pos(); QVERIFY2(HighDpi::fuzzyCompare(afterShowPosition, beforeShowPosition, fuzz), HighDpi::msgPointMismatch(afterShowPosition, beforeShowPosition).constData()); @@ -414,7 +433,7 @@ class TestRejectDialog : public QDialog { public: TestRejectDialog() : cancelReject(false), called(0) {} - void reject() + void reject() override { called++; if (!cancelReject) @@ -465,6 +484,9 @@ void tst_QDialog::snapToDefaultButton() #else if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) QSKIP("This platform does not support setting the cursor position."); +#ifdef Q_OS_ANDROID + QSKIP("Android does not support cursor"); +#endif const QRect dialogGeometry(QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(100, 100), QSize(200, 200)); @@ -540,5 +562,211 @@ void tst_QDialog::dialogInGraphicsView() } } +// QTBUG-79147 (Windows): Closing a dialog by clicking the 'X' in the title +// bar would offset the dialog position when shown next time. +void tst_QDialog::keepPositionOnClose() +{ + QDialog dialog; + dialog.setWindowTitle(QTest::currentTestFunction()); + const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry(); + dialog.resize(availableGeometry.size() / 4); + QPoint pos = availableGeometry.topLeft() + QPoint(100, 100); + dialog.move(pos); + dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + pos = dialog.pos(); + dialog.close(); + dialog.windowHandle()->destroy(); // Emulate a click on close by destroying the window. + QTest::qWait(50); + dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + QTest::qWait(50); + QCOMPARE(dialog.pos(), pos); +} + +/*! + Verify that the virtual functions related to closing a dialog are + called exactly once, no matter how the dialog gets closed. +*/ +void tst_QDialog::virtualsOnClose() +{ + class Dialog : public QDialog + { + public: + using QDialog::QDialog; + int closeEventCount = 0; + int acceptCount = 0; + int rejectCount = 0; + int doneCount = 0; + + void accept() override + { + ++acceptCount; + QDialog::accept(); + } + void reject() override + { + ++rejectCount; + QDialog::reject(); + } + void done(int result) override + { + ++doneCount; + QDialog::done(result); + } + + protected: + void closeEvent(QCloseEvent *e) override + { + ++closeEventCount; + QDialog::closeEvent(e); + } + }; + + { + Dialog dialog; + dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + dialog.accept(); + // we used to only hide the dialog, and we still don't want a + // closeEvent call for application-triggered calls to QDialog::done + QCOMPARE(dialog.closeEventCount, 0); + QCOMPARE(dialog.acceptCount, 1); + QCOMPARE(dialog.rejectCount, 0); + QCOMPARE(dialog.doneCount, 1); + } + + { + Dialog dialog; + dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + dialog.reject(); + QCOMPARE(dialog.closeEventCount, 0); + QCOMPARE(dialog.acceptCount, 0); + QCOMPARE(dialog.rejectCount, 1); + QCOMPARE(dialog.doneCount, 1); + } + + { + Dialog dialog; + dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + dialog.close(); + QCOMPARE(dialog.closeEventCount, 1); + QCOMPARE(dialog.acceptCount, 0); + QCOMPARE(dialog.rejectCount, 1); + QCOMPARE(dialog.doneCount, 1); + } + + { + // user clicks close button in title bar + Dialog dialog; + dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + QWindowSystemInterface::handleCloseEvent(dialog.windowHandle()); + QApplication::processEvents(); + QCOMPARE(dialog.closeEventCount, 1); + QCOMPARE(dialog.acceptCount, 0); + QCOMPARE(dialog.rejectCount, 1); + QCOMPARE(dialog.doneCount, 1); + } + + { + struct EventFilter : QObject { + EventFilter(Dialog *dialog) + { dialog->installEventFilter(this); } + int closeEventCount = 0; + bool eventFilter(QObject *r, QEvent *e) override + { + if (e->type() == QEvent::Close) { + ++closeEventCount; + } + return QObject::eventFilter(r, e); + } + }; + // dialog gets destroyed while shown + Dialog *dialog = new Dialog; + QSignalSpy rejectedSpy(dialog, &QDialog::rejected); + EventFilter filter(dialog); + + dialog->show(); + QVERIFY(QTest::qWaitForWindowExposed(dialog)); + delete dialog; + // 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.size(), 0); + } +} + +/*! + QDialog::done is documented to respect Qt::WA_DeleteOnClose. +*/ +void tst_QDialog::deleteOnDone() +{ + { + std::unique_ptr<QDialog> dialog(new QDialog); + QPointer<QDialog> watcher(dialog.get()); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->show(); + QVERIFY(QTest::qWaitForWindowExposed(dialog.get())); + + dialog->accept(); + QTRY_COMPARE(watcher.isNull(), true); + dialog.release(); // if we get here, the dialog is destroyed + } + + // it is still safe to delete the dialog explicitly as long as events + // have not yet been processed + { + std::unique_ptr<QDialog> dialog(new QDialog); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->show(); + QVERIFY(QTest::qWaitForWindowExposed(dialog.get())); + + dialog->accept(); + dialog.reset(); + QApplication::processEvents(); + } +} + +/*! + QDialog::done is documented to make QApplication emit lastWindowClosed if + the dialog was the last window. +*/ +void tst_QDialog::quitOnDone() +{ + QSignalSpy quitSpy(qApp, &QGuiApplication::lastWindowClosed); + + QDialog dialog; + dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + + // QGuiApplication::lastWindowClosed is documented to only be emitted + // when we are in exec() + QTimer::singleShot(0, &dialog, &QDialog::accept); + // also quit with a timer in case the test fails + QTimer::singleShot(1000, QApplication::instance(), &QApplication::quit); + QApplication::exec(); + QCOMPARE(quitSpy.size(), 1); +} + +void tst_QDialog::focusWidgetAfterOpen() +{ + QDialog dialog; + dialog.setLayout(new QVBoxLayout); + + QPushButton *pb1 = new QPushButton; + QPushButton *pb2 = new QPushButton; + dialog.layout()->addWidget(pb1); + dialog.layout()->addWidget(pb2); + + pb2->setFocus(); + QCOMPARE(dialog.focusWidget(), static_cast<QWidget *>(pb2)); + + dialog.open(); + QCOMPARE(dialog.focusWidget(), static_cast<QWidget *>(pb2)); +} + QTEST_MAIN(tst_QDialog) #include "tst_qdialog.moc" diff --git a/tests/auto/widgets/dialogs/qerrormessage/CMakeLists.txt b/tests/auto/widgets/dialogs/qerrormessage/CMakeLists.txt index 1120c2b53b..a26401c417 100644 --- a/tests/auto/widgets/dialogs/qerrormessage/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qerrormessage/CMakeLists.txt @@ -1,16 +1,21 @@ -# Generated from qerrormessage.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qerrormessage Test: ##################################################################### -qt_add_test(tst_qerrormessage +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 - PUBLIC_LIBRARIES + 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/qerrormessage.pro b/tests/auto/widgets/dialogs/qerrormessage/qerrormessage.pro deleted file mode 100644 index b4cf05e347..0000000000 --- a/tests/auto/widgets/dialogs/qerrormessage/qerrormessage.pro +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG += testcase -TEMPLATE = app -TARGET = tst_qerrormessage - -QT += widgets testlib - -SOURCES += tst_qerrormessage.cpp diff --git a/tests/auto/widgets/dialogs/qerrormessage/tst_qerrormessage.cpp b/tests/auto/widgets/dialogs/qerrormessage/tst_qerrormessage.cpp index a4204da20e..53ade3cbc6 100644 --- a/tests/auto/widgets/dialogs/qerrormessage/tst_qerrormessage.cpp +++ b/tests/auto/widgets/dialogs/qerrormessage/tst_qerrormessage.cpp @@ -1,50 +1,48 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// 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"); QString htmlString = QLatin1String("foo<br>bar"); - QCheckBox *checkBox = 0; + QCheckBox *checkBox = nullptr; QErrorMessage errorMessageDialog(0); @@ -72,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); @@ -92,7 +89,7 @@ void tst_QErrorMessage::dontShowCategoryAgain() { QString htmlString = QLatin1String("foo<br>bar"); QString htmlString2 = QLatin1String("foo2<br>bar2"); - QCheckBox *checkBox = 0; + QCheckBox *checkBox = nullptr; QErrorMessage errorMessageDialog(0); @@ -141,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 new file mode 100644 index 0000000000..38aa416115 --- /dev/null +++ b/tests/auto/widgets/dialogs/qfiledialog/BLACKLIST @@ -0,0 +1,10 @@ +[filesSelectedSignal] +android # QTBUG-101194 +[historyForward] +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 a1f37df137..000d99cdcf 100644 --- a/tests/auto/widgets/dialogs/qfiledialog/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qfiledialog/CMakeLists.txt @@ -1,15 +1,20 @@ -# Generated from qfiledialog.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qfiledialog Test: ##################################################################### -qt_add_test(tst_qfiledialog +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 - DEFINES - SRCDIR=\\\"${CMAKE_CURRENT_SOURCE_DIR}/\\\" - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate diff --git a/tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro b/tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro deleted file mode 100644 index 1cdf10d29a..0000000000 --- a/tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro +++ /dev/null @@ -1,11 +0,0 @@ -############################################################ -# Project file for autotest for file qfiledialog.h -############################################################ - -CONFIG += testcase -TARGET = tst_qfiledialog -QT += widgets widgets-private testlib -QT += core-private gui-private -SOURCES += tst_qfiledialog.cpp - -DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp index 20c0dd993b..6ebf255f31 100644 --- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp @@ -1,33 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> +#include <QStandardPaths> +#include <QSignalSpy> +#include <QTemporaryFile> #include <qcoreapplication.h> #include <qfile.h> @@ -35,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> @@ -60,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 @@ -136,6 +116,7 @@ private slots: void clearLineEdit(); void enableChooseButton(); void selectedFilesWithoutWidgets(); + void selectedFileWithDefaultSuffix(); void trailingDotsAndSpaces(); #ifdef Q_OS_UNIX #ifdef QT_BUILD_INTERNAL @@ -147,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 @@ -160,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(); @@ -201,8 +184,8 @@ class MyAbstractItemDelegate : public QAbstractItemDelegate { public: MyAbstractItemDelegate() : QAbstractItemDelegate() {}; - void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const {} - QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return QSize(); } + void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const override {} + QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const override { return QSize(); } }; // emitted any time the selection model emits current changed @@ -227,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 @@ -249,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 @@ -258,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 @@ -300,7 +283,7 @@ void tst_QFiledialog::filesSelectedSignal() { QFileDialog fd; fd.setViewMode(QFileDialog::List); - QDir testDir(SRCDIR); + QDir testDir(QT_TESTCASE_SOURCEDIR); fd.setDirectory(testDir); QFETCH(QFileDialog::FileMode, fileMode); fd.setFileMode(fileMode); @@ -335,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 @@ -360,12 +343,12 @@ void tst_QFiledialog::filterSelectedSignal() QTest::keyPress(filters, Qt::Key_Down); - QCOMPARE(spyFilterSelected.count(), 1); + QCOMPARE(spyFilterSelected.size(), 1); } void tst_QFiledialog::args() { - QWidget *parent = 0; + QWidget *parent = nullptr; QString caption = "caption"; QString directory = QDir::tempPath(); QString filter = "*.mp3"; @@ -401,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 @@ -439,7 +422,14 @@ void tst_QFiledialog::completer_data() QTest::newRow("goto root") << QString() << rootPath << -1; QTest::newRow("start at root") << rootPath << QString() << -1; - QFileInfoList list = QDir::root().entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + QDir dir = QDir::root(); +#ifdef Q_OS_ANDROID + const auto homePaths = QStandardPaths::standardLocations(QStandardPaths::HomeLocation); + QVERIFY(!homePaths.isEmpty()); + dir = QDir(homePaths.first()); +#endif + + QFileInfoList list = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); QVERIFY(!list.isEmpty()); const QString folder = list.first().absoluteFilePath(); QTest::newRow("start at one below root r") << folder << "r" << -1; @@ -526,10 +516,9 @@ void tst_QFiledialog::completer() } // press 'keys' for the input - for (int i = 0; i < input.count(); ++i) + 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('/'))) @@ -542,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; } @@ -582,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() @@ -671,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; @@ -686,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; @@ -733,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() @@ -772,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() @@ -817,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); } @@ -878,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")) { @@ -888,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 { @@ -936,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(); @@ -945,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); } @@ -993,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); @@ -1128,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)); @@ -1138,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); @@ -1168,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)); @@ -1183,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); } @@ -1221,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)); @@ -1231,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)); @@ -1448,6 +1436,10 @@ void tst_QFiledialog::widgetlessNativeDialog() { 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 window open. Figure out why."); +#endif QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, false); QFileDialog fd; fd.setWindowModality(Qt::ApplicationModal); @@ -1460,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. @@ -1468,6 +1500,21 @@ void tst_QFiledialog::selectedFilesWithoutWidgets() QVERIFY(fd.selectedFiles().size() >= 0); } +void tst_QFiledialog::selectedFileWithDefaultSuffix() +{ + // QTBUG-59401: dot in file path should not prevent default suffix from being added + QTemporaryDir tempDir(QDir::tempPath() + "/abcXXXXXX.def"); + QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString())); + + QFileDialog fd; + fd.setDirectory(tempDir.path()); + fd.setDefaultSuffix(".txt"); + fd.selectFile("xxx"); + const auto selectedFiles = fd.selectedFiles(); + QCOMPARE(selectedFiles.size(), 1); + QVERIFY(selectedFiles.first().endsWith(".txt")); +} + void tst_QFiledialog::trailingDotsAndSpaces() { #ifndef Q_OS_WIN @@ -1549,6 +1596,10 @@ void tst_QFiledialog::rejectModalDialogs() { if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) QSKIP("Wayland: This freezes. Figure out why."); +#ifdef Q_OS_ANDROID + // QTBUG-101194 + QSKIP("Android: This freezes. Figure out why."); +#endif // QTBUG-38672 , static functions should return empty Urls DialogRejecter dr; @@ -1580,6 +1631,12 @@ void tst_QFiledialog::QTBUG49600_nativeIconProviderCrash() { 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 hangs. Figure out why."); +#endif + QFileDialog fd; fd.iconProvider(); } @@ -1611,6 +1668,10 @@ void tst_QFiledialog::focusObjectDuringDestruction() { if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) QSKIP("Wayland: This freezes. Figure out why."); +#ifdef Q_OS_ANDROID + // QTBUG-101194 + QSKIP("Android: This freezes. Figure out why."); +#endif QTRY_VERIFY(QGuiApplication::topLevelWindows().isEmpty()); diff --git a/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST b/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST index 9e14db48d0..fd008abe96 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST +++ b/tests/auto/widgets/dialogs/qfiledialog2/BLACKLIST @@ -1,2 +1,7 @@ [QTBUG4419_lineEditSelectAll] macos +# QTBUG-87393 +[task227930_correctNavigationKeyboardBehavior] +android +[QTBUG4419_lineEditSelectAll] +android diff --git a/tests/auto/widgets/dialogs/qfiledialog2/CMakeLists.txt b/tests/auto/widgets/dialogs/qfiledialog2/CMakeLists.txt index 6fae963999..7db2168a20 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qfiledialog2/CMakeLists.txt @@ -1,15 +1,20 @@ -# Generated from qfiledialog2.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qfiledialog2 Test: ##################################################################### -qt_add_test(tst_qfiledialog2 +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 - DEFINES - SRCDIR=\\\"${CMAKE_CURRENT_SOURCE_DIR}/\\\" - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate diff --git a/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro b/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro deleted file mode 100644 index 1b35b2e4ac..0000000000 --- a/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro +++ /dev/null @@ -1,9 +0,0 @@ -CONFIG += testcase -TARGET = tst_qfiledialog2 - -QT += widgets widgets-private testlib -QT += core-private gui-private - -SOURCES += tst_qfiledialog2.cpp - -DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp index e6130c56b1..c34c8559da 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp @@ -1,39 +1,16 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> +#include <QTemporaryFile> +#include <QSignalSpy> +#include <QStandardPaths> #include <qcoreapplication.h> #include <qdebug.h> #include <qfiledialog.h> #include <qabstractitemdelegate.h> -#include <qitemdelegate.h> #include <qlistview.h> #include <qcombobox.h> #include <qpushbutton.h> @@ -49,7 +26,7 @@ #include <qmenu.h> #include <qrandom.h> #include "../../../../../src/widgets/dialogs/qsidebar_p.h" -#include "../../../../../src/widgets/dialogs/qfilesystemmodel_p.h" +#include "../../../../../src/gui/itemmodels/qfilesystemmodel_p.h" #include "../../../../../src/widgets/dialogs/qfiledialog_p.h" #include <private/qguiapplication_p.h> @@ -57,9 +34,9 @@ #include <qpa/qplatformdialoghelper.h> #include <qpa/qplatformintegration.h> -#if defined(Q_OS_WIN) -#include "../../../network-settings.h" -#endif +#include "../../../../shared/filesystem.h" + +#include <QtWidgets/private/qapplication_p.h> #if defined QT_BUILD_INTERNAL QT_BEGIN_NAMESPACE @@ -130,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(); @@ -278,7 +259,7 @@ void tst_QFileDialog2::unc() { #if defined(Q_OS_WIN) // Only test UNC on Windows./ - QString dir("\\\\" + QtNetworkSettings::winServerName() + "\\testsharewritable"); + QString dir("\\\\" + QTest::uncServerName() + "\\testsharewritable"); #else QString dir(QDir::currentPath()); #endif @@ -330,7 +311,7 @@ static bool openContextMenu(QFileDialog &fd) MenuCloser closer(&fd); QObject::connect(&timer, &QTimer::timeout, &closer, &MenuCloser::close); timer.start(); - QContextMenuEvent cme(QContextMenuEvent::Mouse, QPoint(10, 10)); + QContextMenuEvent cme(QContextMenuEvent::Mouse, QPoint(10, 10), list->viewport()->mapToGlobal(QPoint(10, 10))); qApp->sendEvent(list->viewport(), &cme); // blocks until menu is closed again. return true; } @@ -422,9 +403,9 @@ void tst_QFileDialog2::task180459_lastDirectory_data() QTest::addColumn<bool>("isEnabled"); QTest::addColumn<QString>("result"); - QTest::newRow("path+file") << QDir::homePath() + QDir::separator() + "foo" + QTest::newRow("path+file") << QDir::homePath() + QDir::separator() + "Vugiu1co" << QDir::homePath() << true - << QDir::homePath() + QDir::separator() + "foo" ; + << QDir::homePath() + QDir::separator() + "Vugiu1co" ; QTest::newRow("no path") << "" << tempDir.path() << false << QString(); QTest::newRow("file") << "foo" @@ -470,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 @@ -482,7 +501,7 @@ public: {}; protected: - bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override { QModelIndex parentIndex; parentIndex = source_parent; @@ -515,7 +534,7 @@ public: { } protected: - virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const + virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const override { QFileSystemModel * const model = qobject_cast<QFileSystemModel *>(sourceModel()); const QFileInfo leftInfo(model->fileInfo(left)); @@ -638,7 +657,7 @@ void tst_QFileDialog2::task226366_lowerCaseHardDriveWindows() QLineEdit *edit = fd.findChild<QLineEdit*>("fileNameEdit"); QToolButton *buttonParent = fd.findChild<QToolButton*>("toParentButton"); QTest::qWait(200); - QTest::mouseClick(buttonParent, Qt::LeftButton,0,QPoint(0,0)); + QTest::mouseClick(buttonParent, Qt::LeftButton, {}, QPoint(0, 0)); QTest::qWait(2000); QTest::keyClick(edit, Qt::Key_C); QTest::qWait(200); @@ -649,7 +668,7 @@ void tst_QFileDialog2::task226366_lowerCaseHardDriveWindows() //i clear my previous selection in the completer QTest::keyClick(edit->completer()->popup(), Qt::Key_Down); edit->clear(); - QTest::keyClick(edit, (char)(Qt::Key_C | Qt::SHIFT)); + QTest::keyClick(edit, Qt::Key_C, Qt::ShiftModifier); QTest::qWait(200); QTest::keyClick(edit->completer()->popup(), Qt::Key_Down); QCOMPARE(edit->text(), QString("C:/")); @@ -662,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++) { @@ -678,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; @@ -693,6 +712,17 @@ void tst_QFileDialog2::completionOnLevelAfterRoot() } if (testDir.isEmpty()) QSKIP("This test requires to have a unique directory of at least six ascii characters under c:/"); +#elif defined(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. + const auto homePaths = QStandardPaths::standardLocations(QStandardPaths::HomeLocation); + QVERIFY(!homePaths.isEmpty()); + fd.setFilter(QDir::Hidden | QDir::AllDirs | QDir::Files | QDir::System); + fd.setDirectory(homePaths.first()); + QDir(homePaths.first()).mkdir("etc"); + auto cleanup = qScopeGuard([&]() { + QDir(homePaths.first()).rmdir("etc"); + }); #else fd.setFilter(QDir::Hidden | QDir::AllDirs | QDir::Files | QDir::System); fd.setDirectory("/"); @@ -774,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 @@ -822,7 +852,7 @@ void tst_QFileDialog2::task203703_returnProperSeparator() QVERIFY(button); QTest::keyClick(button, Qt::Key_Return); QString result = fd.selectedFiles().first(); - QVERIFY(result.at(result.count() - 1) != '/'); + QVERIFY(result.at(result.size() - 1) != '/'); QVERIFY(!result.contains('\\')); current.rmdir("aaaaaaaaaaaaaaaaaa"); } @@ -917,9 +947,9 @@ void tst_QFileDialog2::task239706_editableFilterCombo() d.show(); QVERIFY(QTest::qWaitForWindowExposed(&d)); - QList<QComboBox *> comboList = d.findChildren<QComboBox *>(); - QComboBox *filterCombo = 0; - foreach (QComboBox *combo, comboList) { + const QList<QComboBox *> comboList = d.findChildren<QComboBox *>(); + QComboBox *filterCombo = nullptr; + for (QComboBox *combo : comboList) { if (combo->objectName() == QString("fileTypeCombo")) { filterCombo = combo; break; @@ -991,16 +1021,16 @@ void tst_QFileDialog2::task251321_sideBarHiddenEntries() class MyQSideBar : public QSidebar { public : - MyQSideBar(QWidget *parent = 0) : QSidebar(parent) + MyQSideBar(QWidget *parent = nullptr) : QSidebar(parent) {} 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()); } @@ -1080,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); @@ -1102,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(); } @@ -1118,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)); @@ -1223,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(); @@ -1236,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)); @@ -1280,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)); @@ -1296,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)); @@ -1316,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/qfilesystemmodel/.gitignore b/tests/auto/widgets/dialogs/qfilesystemmodel/.gitignore deleted file mode 100644 index 9804e5a3d7..0000000000 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qfilesystemmodel diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST b/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST deleted file mode 100644 index 4119afce84..0000000000 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/BLACKLIST +++ /dev/null @@ -1,5 +0,0 @@ -[sort:QFileDialog usage] -ubuntu -b2qt -[specialFiles] -b2qt diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/CMakeLists.txt b/tests/auto/widgets/dialogs/qfilesystemmodel/CMakeLists.txt deleted file mode 100644 index 595b30bd56..0000000000 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# Generated from qfilesystemmodel.pro. - -##################################################################### -## tst_qfilesystemmodel Test: -##################################################################### - -qt_add_test(tst_qfilesystemmodel - SOURCES - ../../../../shared/emulationdetector.h - tst_qfilesystemmodel.cpp - INCLUDE_DIRECTORIES - ../../../../shared - PUBLIC_LIBRARIES - Qt::CorePrivate - Qt::Gui - Qt::Widgets - Qt::WidgetsPrivate -) - -## Scopes: -##################################################################### - -#### Keys ignored in scope 2:.:.:qfilesystemmodel.pro:WIN32: -# testcase.timeout = "900" - -#### Keys ignored in scope 3:.:.:qfilesystemmodel.pro:MACOS: -# testcase.timeout = "900" diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro b/tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro deleted file mode 100644 index db8cf7de3f..0000000000 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/qfilesystemmodel.pro +++ /dev/null @@ -1,13 +0,0 @@ -INCLUDEPATH += ../../../../shared -HEADERS += ../../../../shared/emulationdetector.h - -CONFIG += testcase -# This testcase can be slow on Windows and OS X, and may interfere with other file system tests. -win32:testcase.timeout = 900 -macx:testcase.timeout = 900 - -QT += widgets widgets-private -QT += core-private testlib - -SOURCES += tst_qfilesystemmodel.cpp -TARGET = tst_qfilesystemmodel diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp deleted file mode 100644 index e814e79dbe..0000000000 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ /dev/null @@ -1,1207 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <emulationdetector.h> -#include <QtTest/QtTest> -#ifdef QT_BUILD_INTERNAL -#include <private/qfilesystemmodel_p.h> -#endif -#include <QFileSystemModel> -#include <QFileIconProvider> -#include <QTreeView> -#include <QHeaderView> -#include <QStandardPaths> -#include <QTime> -#include <QStyle> -#include <QtGlobal> -#include <QTemporaryDir> -#if defined(Q_OS_WIN) -# include <qt_windows.h> // for SetFileAttributes -#endif -#include <private/qfilesystemengine_p.h> - -#include <algorithm> - -#define WAITTIME 1000 - -// Will try to wait for the condition while allowing event processing -// for a maximum of 5 seconds. -#define TRY_WAIT(expr, timedOut) \ - do { \ - *timedOut = true; \ - const int step = 50; \ - for (int __i = 0; __i < 5000; __i += step) { \ - if (expr) { \ - *timedOut = false; \ - break; \ - } \ - QTest::qWait(step); \ - } \ - } while(0) - -Q_DECLARE_METATYPE(QDir::Filters) -Q_DECLARE_METATYPE(QFileDevice::Permissions) - -Q_LOGGING_CATEGORY(lcFileSystemModel, "qt.widgets.tests.qfilesystemmodel") - -class tst_QFileSystemModel : public QObject { - Q_OBJECT - -private slots: - void initTestCase(); - void cleanup(); - - void indexPath(); - - void rootPath(); - void readOnly(); - void iconProvider(); - - void rowCount(); - - void rowsInserted_data(); - void rowsInserted(); - - void rowsRemoved_data(); - void rowsRemoved(); - - void dataChanged_data(); - void dataChanged(); - - void filters_data(); - void filters(); - - void nameFilters(); - - void setData_data(); - void setData(); - - void sortPersistentIndex(); - void sort_data(); - void sort(); - - void mkdir(); - void deleteFile(); - void deleteDirectory(); - - void caseSensitivity(); - - void drives_data(); - void drives(); - void dirsBeforeFiles(); - - void roleNames_data(); - void roleNames(); - - void permissions_data(); - void permissions(); - - void doNotUnwatchOnFailedRmdir(); - void specialFiles(); - - void fileInfo(); - -protected: - bool createFiles(QFileSystemModel *model, const QString &test_path, - const QStringList &initial_files, int existingFileCount = 0, - const QStringList &initial_dirs = QStringList()); - QModelIndex prepareTestModelRoot(QFileSystemModel *model, const QString &test_path, - QSignalSpy **spy2 = nullptr, QSignalSpy **spy3 = nullptr); - -private: - QString flatDirTestPath; - QTemporaryDir m_tempDir; -}; - -void tst_QFileSystemModel::cleanup() -{ - QDir dir(flatDirTestPath); - if (dir.exists()) { - const QDir::Filters filters = QDir::AllEntries | QDir::System | QDir::Hidden | QDir::NoDotAndDotDot; - const QFileInfoList list = dir.entryInfoList(filters); - for (const QFileInfo &fi : list) { - if (fi.isDir()) { - QVERIFY(dir.rmdir(fi.fileName())); - } else { - QFile dead(fi.absoluteFilePath()); - dead.setPermissions(QFile::ReadUser | QFile::ReadOwner | QFile::ExeOwner | QFile::ExeUser | QFile::WriteUser | QFile::WriteOwner | QFile::WriteOther); - QVERIFY(dead.remove()); - } - } - QVERIFY(dir.entryInfoList(filters).isEmpty()); - } -} - -void tst_QFileSystemModel::initTestCase() -{ - QVERIFY2(m_tempDir.isValid(), qPrintable(m_tempDir.errorString())); - flatDirTestPath = m_tempDir.path(); -} - -void tst_QFileSystemModel::indexPath() -{ -#if !defined(Q_OS_WIN) - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - int depth = QDir::currentPath().count('/'); - model->setRootPath(QDir::currentPath()); - QString backPath; - for (int i = 0; i <= depth * 2 + 1; ++i) { - backPath += "../"; - QModelIndex idx = model->index(backPath); - QVERIFY(i != depth - 1 ? idx.isValid() : !idx.isValid()); - } -#endif -} - -void tst_QFileSystemModel::rootPath() -{ - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QCOMPARE(model->rootPath(), QString(QDir().path())); - - QSignalSpy rootChanged(model.data(), &QFileSystemModel::rootPathChanged); - QModelIndex root = model->setRootPath(model->rootPath()); - root = model->setRootPath("this directory shouldn't exist"); - QCOMPARE(rootChanged.count(), 0); - - QString oldRootPath = model->rootPath(); - const QStringList documentPaths = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); - QVERIFY(!documentPaths.isEmpty()); - QString documentPath = documentPaths.front(); - // In particular on Linux, ~/Documents (the first - // DocumentsLocation) may not exist, so choose ~ in that case: - if (!QFile::exists(documentPath)) { - documentPath = QDir::homePath(); - qWarning("%s: first documentPath \"%s\" does not exist. Using ~ (\"%s\") instead.", - Q_FUNC_INFO, qPrintable(documentPaths.front()), qPrintable(documentPath)); - } - root = model->setRootPath(documentPath); - - QTRY_VERIFY(model->rowCount(root) >= 0); - QCOMPARE(model->rootPath(), QString(documentPath)); - QCOMPARE(rootChanged.count(), oldRootPath == model->rootPath() ? 0 : 1); - QCOMPARE(model->rootDirectory().absolutePath(), documentPath); - - model->setRootPath(QDir::rootPath()); - int oldCount = rootChanged.count(); - oldRootPath = model->rootPath(); - root = model->setRootPath(documentPath + QLatin1String("/.")); - QTRY_VERIFY(model->rowCount(root) >= 0); - QCOMPARE(model->rootPath(), documentPath); - QCOMPARE(rootChanged.count(), oldRootPath == model->rootPath() ? oldCount : oldCount + 1); - QCOMPARE(model->rootDirectory().absolutePath(), documentPath); - - QDir newdir = documentPath; - if (newdir.cdUp()) { - oldCount = rootChanged.count(); - oldRootPath = model->rootPath(); - root = model->setRootPath(documentPath + QLatin1String("/..")); - QTRY_VERIFY(model->rowCount(root) >= 0); - QCOMPARE(model->rootPath(), newdir.path()); - QCOMPARE(rootChanged.count(), oldCount + 1); - QCOMPARE(model->rootDirectory().absolutePath(), newdir.path()); - } -} - -void tst_QFileSystemModel::readOnly() -{ - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QCOMPARE(model->isReadOnly(), true); - QTemporaryFile file(flatDirTestPath + QStringLiteral("/XXXXXX.dat")); - QVERIFY2(file.open(), qPrintable(file.errorString())); - const QString fileName = file.fileName(); - file.close(); - - const QFileInfo fileInfo(fileName); - QTRY_VERIFY(QDir(flatDirTestPath).entryInfoList().contains(fileInfo)); - QModelIndex root = model->setRootPath(flatDirTestPath); - - QTRY_VERIFY(model->rowCount(root) > 0); - QVERIFY(!(model->flags(model->index(fileName)) & Qt::ItemIsEditable)); - model->setReadOnly(false); - QCOMPARE(model->isReadOnly(), false); - QVERIFY(model->flags(model->index(fileName)) & Qt::ItemIsEditable); -} - -class CustomFileIconProvider : public QFileIconProvider -{ -public: - CustomFileIconProvider() : QFileIconProvider() - { - auto style = QApplication::style(); - mb = style->standardIcon(QStyle::SP_MessageBoxCritical); - dvd = style->standardIcon(QStyle::SP_DriveDVDIcon); - } - - QIcon icon(const QFileInfo &info) const override - { - if (info.isDir()) - return mb; - - return QFileIconProvider::icon(info); - } - QIcon icon(IconType type) const override - { - if (type == QFileIconProvider::Folder) - return dvd; - - return QFileIconProvider::icon(type); - } -private: - QIcon mb; - QIcon dvd; -}; - -void tst_QFileSystemModel::iconProvider() -{ - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QVERIFY(model->iconProvider()); - QScopedPointer<QFileIconProvider> provider(new QFileIconProvider); - model->setIconProvider(provider.data()); - QCOMPARE(model->iconProvider(), provider.data()); - model->setIconProvider(nullptr); - provider.reset(); - - QScopedPointer<QFileSystemModel> myModel(new QFileSystemModel); - const QStringList documentPaths = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); - QVERIFY(!documentPaths.isEmpty()); - myModel->setRootPath(documentPaths.constFirst()); - //We change the provider, icons must be updated - provider.reset(new CustomFileIconProvider); - myModel->setIconProvider(provider.data()); - - QPixmap mb = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical).pixmap(50, 50); - QCOMPARE(myModel->fileIcon(myModel->index(QDir::homePath())).pixmap(50, 50), mb); -} - -bool tst_QFileSystemModel::createFiles(QFileSystemModel *model, const QString &test_path, - const QStringList &initial_files, int existingFileCount, - const QStringList &initial_dirs) -{ - qCDebug(lcFileSystemModel) << (model->rowCount(model->index(test_path))) << existingFileCount << initial_files; - bool timedOut = false; - TRY_WAIT((model->rowCount(model->index(test_path)) == existingFileCount), &timedOut); - if (timedOut) - return false; - - QDir dir(test_path); - if (!dir.exists()) { - qWarning() << "error" << test_path << "doesn't exist"; - return false; - } - for (const auto &initial_dir : initial_dirs) { - if (!dir.mkdir(initial_dir)) { - qWarning() << "error" << "failed to make" << initial_dir; - return false; - } - qCDebug(lcFileSystemModel) << test_path + '/' + initial_dir << (QFile::exists(test_path + '/' + initial_dir)); - } - for (const auto &initial_file : initial_files) { - QFile file(test_path + '/' + initial_file); - if (!file.open(QIODevice::WriteOnly | QIODevice::Append)) { - qDebug() << "failed to open file" << initial_file; - return false; - } - if (!file.resize(1024 + file.size())) { - qDebug() << "failed to resize file" << initial_file; - return false; - } - if (!file.flush()) { - qDebug() << "failed to flush file" << initial_file; - return false; - } - file.close(); -#if defined(Q_OS_WIN) - if (initial_file[0] == '.') { - const QString hiddenFile = QDir::toNativeSeparators(file.fileName()); - const auto nativeHiddenFile = reinterpret_cast<const wchar_t *>(hiddenFile.utf16()); - DWORD currentAttributes = ::GetFileAttributes(nativeHiddenFile); - if (currentAttributes == 0xFFFFFFFF) { - qErrnoWarning("failed to get file attributes: %s", qPrintable(hiddenFile)); - return false; - } - if (!::SetFileAttributes(nativeHiddenFile, currentAttributes | FILE_ATTRIBUTE_HIDDEN)) { - qErrnoWarning("failed to set file hidden: %s", qPrintable(hiddenFile)); - return false; - } - } -#endif - qCDebug(lcFileSystemModel) << test_path + '/' + initial_file << (QFile::exists(test_path + '/' + initial_file)); - } - return true; -} - -QModelIndex tst_QFileSystemModel::prepareTestModelRoot(QFileSystemModel *model, const QString &test_path, - QSignalSpy **spy2, QSignalSpy **spy3) -{ - if (model->rowCount(model->index(test_path)) != 0) - return QModelIndex(); - - if (spy2) - *spy2 = new QSignalSpy(model, &QFileSystemModel::rowsInserted); - if (spy3) - *spy3 = new QSignalSpy(model, &QFileSystemModel::rowsAboutToBeInserted); - - QStringList files = { "b", "d", "f", "h", "j", ".a", ".c", ".e", ".g" }; - - if (!createFiles(model, test_path, files)) - return QModelIndex(); - - QModelIndex root = model->setRootPath(test_path); - if (!root.isValid()) - return QModelIndex(); - - bool timedOut = false; - TRY_WAIT(model->rowCount(root) == 5, &timedOut); - if (timedOut) - return QModelIndex(); - - return root; -} - -void tst_QFileSystemModel::rowCount() -{ - QSignalSpy *spy2 = nullptr; - QSignalSpy *spy3 = nullptr; - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QModelIndex root = prepareTestModelRoot(model.data(), flatDirTestPath, &spy2, &spy3); - QVERIFY(root.isValid()); - - QVERIFY(spy2 && spy2->count() > 0); - QVERIFY(spy3 && spy3->count() > 0); -} - -void tst_QFileSystemModel::rowsInserted_data() -{ - QTest::addColumn<int>("count"); - QTest::addColumn<Qt::SortOrder>("ascending"); - for (int i = 0; i < 4; ++i) { - const QByteArray iB = QByteArray::number(i); - QTest::newRow(("Qt::AscendingOrder " + iB).constData()) << i << Qt::AscendingOrder; - QTest::newRow(("Qt::DescendingOrder " + iB).constData()) << i << Qt::DescendingOrder; - } -} - -static inline QString lastEntry(const QModelIndex &root) -{ - const QAbstractItemModel *model = root.model(); - return model->index(model->rowCount(root) - 1, 0, root).data().toString(); -} - -void tst_QFileSystemModel::rowsInserted() -{ - const QString tmp = flatDirTestPath; - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QModelIndex root = prepareTestModelRoot(model.data(), tmp); - QVERIFY(root.isValid()); - - QFETCH(Qt::SortOrder, ascending); - QFETCH(int, count); - model->sort(0, ascending); - - QSignalSpy spy0(model.data(), &QAbstractItemModel::rowsInserted); - QSignalSpy spy1(model.data(), &QAbstractItemModel::rowsAboutToBeInserted); - int oldCount = model->rowCount(root); - QStringList files; - for (int i = 0; i < count; ++i) - files.append(QLatin1Char('c') + QString::number(i)); - QVERIFY(createFiles(model.data(), tmp, files, 5)); - QTRY_COMPARE(model->rowCount(root), oldCount + count); - int totalRowsInserted = 0; - for (int i = 0; i < spy0.count(); ++i) { - int start = spy0[i].value(1).toInt(); - int end = spy0[i].value(2).toInt(); - totalRowsInserted += end - start + 1; - } - QCOMPARE(totalRowsInserted, count); - const QString expected = ascending == Qt::AscendingOrder ? QStringLiteral("j") : QStringLiteral("b"); - QTRY_COMPARE(lastEntry(root), expected); - - if (spy0.count() > 0) { - if (count == 0) - QCOMPARE(spy0.count(), 0); - else - QVERIFY(spy0.count() >= 1); - } - if (count == 0) QCOMPARE(spy1.count(), 0); else QVERIFY(spy1.count() >= 1); - - QVERIFY(createFiles(model.data(), tmp, QStringList(".hidden_file"), 5 + count)); - - if (count != 0) - QTRY_VERIFY(spy0.count() >= 1); - else - QTRY_COMPARE(spy0.count(), 0); - if (count != 0) - QTRY_VERIFY(spy1.count() >= 1); - else - QTRY_COMPARE(spy1.count(), 0); -} - -void tst_QFileSystemModel::rowsRemoved_data() -{ - rowsInserted_data(); -} - -void tst_QFileSystemModel::rowsRemoved() -{ - const QString tmp = flatDirTestPath; - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QModelIndex root = prepareTestModelRoot(model.data(), tmp); - QVERIFY(root.isValid()); - - QFETCH(int, count); - QFETCH(Qt::SortOrder, ascending); - model->sort(0, ascending); - - QSignalSpy spy0(model.data(), &QAbstractItemModel::rowsRemoved); - QSignalSpy spy1(model.data(), &QAbstractItemModel::rowsAboutToBeRemoved); - int oldCount = model->rowCount(root); - for (int i = count - 1; i >= 0; --i) { - const QString fileName = model->index(i, 0, root).data().toString(); - qCDebug(lcFileSystemModel) << "removing" << fileName; - QVERIFY(QFile::remove(tmp + QLatin1Char('/') + fileName)); - } - for (int i = 0 ; i < 10; ++i) { - if (count != 0) { - if (i == 10 || spy0.count() != 0) { - QVERIFY(spy0.count() >= 1); - QVERIFY(spy1.count() >= 1); - } - } else { - if (i == 10 || spy0.count() == 0) { - QCOMPARE(spy0.count(), 0); - QCOMPARE(spy1.count(), 0); - } - } - QStringList lst; - for (int i = 0; i < model->rowCount(root); ++i) - lst.append(model->index(i, 0, root).data().toString()); - if (model->rowCount(root) == oldCount - count) - break; - qCDebug(lcFileSystemModel) << "still have:" << lst << QFile::exists(tmp + QLatin1String("/.a")); - QDir tmpLister(tmp); - qCDebug(lcFileSystemModel) << tmpLister.entryList(); - } - QTRY_COMPARE(model->rowCount(root), oldCount - count); - - QVERIFY(QFile::exists(tmp + QLatin1String("/.a"))); - QVERIFY(QFile::remove(tmp + QLatin1String("/.a"))); - QVERIFY(QFile::remove(tmp + QLatin1String("/.c"))); - - if (count != 0) { - QVERIFY(spy0.count() >= 1); - QVERIFY(spy1.count() >= 1); - } else { - QCOMPARE(spy0.count(), 0); - QCOMPARE(spy1.count(), 0); - } -} - -void tst_QFileSystemModel::dataChanged_data() -{ - rowsInserted_data(); -} - -void tst_QFileSystemModel::dataChanged() -{ - QSKIP("This can't be tested right now since we don't watch files, only directories."); - - const QString tmp = flatDirTestPath; - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QModelIndex root = prepareTestModelRoot(model.data(), tmp); - QVERIFY(root.isValid()); - - QFETCH(int, count); - QFETCH(Qt::SortOrder, ascending); - model->sort(0, ascending); - - QSignalSpy spy(model.data(), &QAbstractItemModel::dataChanged); - QStringList files; - for (int i = 0; i < count; ++i) - files.append(model->index(i, 0, root).data().toString()); - createFiles(model.data(), tmp, files); - - QTest::qWait(WAITTIME); - - if (count != 0) QVERIFY(spy.count() >= 1); else QCOMPARE(spy.count(), 0); -} - -void tst_QFileSystemModel::filters_data() -{ - QTest::addColumn<QStringList>("files"); - QTest::addColumn<QStringList>("dirs"); - QTest::addColumn<QDir::Filters>("dirFilters"); - QTest::addColumn<QStringList>("nameFilters"); - QTest::addColumn<int>("rowCount"); - - const QStringList abcList{QLatin1String("a"), QLatin1String("b"), QLatin1String("c")}; - const QStringList zList{QLatin1String("Z")}; - - QTest::newRow("no dirs") << abcList << QStringList() << QDir::Filters(QDir::Dirs) << QStringList() << 2; - QTest::newRow("no dirs - dot") << abcList << QStringList() << (QDir::Dirs | QDir::NoDot) << QStringList() << 1; - QTest::newRow("no dirs - dotdot") << abcList << QStringList() << (QDir::Dirs | QDir::NoDotDot) << QStringList() << 1; - QTest::newRow("no dirs - dotanddotdot") << abcList << QStringList() << (QDir::Dirs | QDir::NoDotAndDotDot) << QStringList() << 0; - QTest::newRow("one dir - dot") << abcList << zList << (QDir::Dirs | QDir::NoDot) << QStringList() << 2; - QTest::newRow("one dir - dotdot") << abcList << zList << (QDir::Dirs | QDir::NoDotDot) << QStringList() << 2; - QTest::newRow("one dir - dotanddotdot") << abcList << zList << (QDir::Dirs | QDir::NoDotAndDotDot) << QStringList() << 1; - QTest::newRow("one dir") << abcList << zList << QDir::Filters(QDir::Dirs) << QStringList() << 3; - QTest::newRow("no dir + hidden") << abcList << QStringList() << (QDir::Dirs | QDir::Hidden) << QStringList() << 2; - QTest::newRow("dir+hid+files") << abcList << QStringList() << - (QDir::Dirs | QDir::Files | QDir::Hidden) << QStringList() << 5; - QTest::newRow("dir+file+hid-dot .A") << abcList << QStringList{QLatin1String(".A")} << - (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot) << QStringList() << 4; - QTest::newRow("dir+files+hid+dot A") << abcList << QStringList{QLatin1String("AFolder")} << - (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot) << QStringList{QLatin1String("A*")} << 2; - QTest::newRow("dir+files+hid+dot+cas1") << abcList << zList << - (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive) << zList << 1; - QTest::newRow("dir+files+hid+dot+cas2") << abcList << zList << - (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive) << QStringList{QLatin1String("a")} << 1; - QTest::newRow("dir+files+hid+dot+cas+alldir") << abcList << zList << - (QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot | QDir::CaseSensitive | QDir::AllDirs) << zList << 1; - - QTest::newRow("case sensitive") << QStringList{QLatin1String("Antiguagdb"), QLatin1String("Antiguamtd"), - QLatin1String("Antiguamtp"), QLatin1String("afghanistangdb"), QLatin1String("afghanistanmtd")} - << QStringList() << QDir::Filters(QDir::Files) << QStringList() << 5; -} - -void tst_QFileSystemModel::filters() -{ - QString tmp = flatDirTestPath; - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QVERIFY(createFiles(model.data(), tmp, QStringList())); - QModelIndex root = model->setRootPath(tmp); - QFETCH(QStringList, files); - QFETCH(QStringList, dirs); - QFETCH(QDir::Filters, dirFilters); - QFETCH(QStringList, nameFilters); - QFETCH(int, rowCount); - - if (nameFilters.count() > 0) - model->setNameFilters(nameFilters); - model->setNameFilterDisables(false); - model->setFilter(dirFilters); - - QVERIFY(createFiles(model.data(), tmp, files, 0, dirs)); - QTRY_COMPARE(model->rowCount(root), rowCount); - - // Make sure that we do what QDir does - QDir xFactor(tmp); - QStringList dirEntries; - - if (nameFilters.count() > 0) - dirEntries = xFactor.entryList(nameFilters, dirFilters); - else - dirEntries = xFactor.entryList(dirFilters); - - QCOMPARE(dirEntries.count(), rowCount); - - QStringList modelEntries; - - for (int i = 0; i < rowCount; ++i) - modelEntries.append(model->data(model->index(i, 0, root), QFileSystemModel::FileNameRole).toString()); - - std::sort(dirEntries.begin(), dirEntries.end()); - std::sort(modelEntries.begin(), modelEntries.end()); - QCOMPARE(dirEntries, modelEntries); - -#ifdef Q_OS_LINUX - if (files.count() >= 3 && rowCount >= 3 && rowCount != 5) { - QString fileName1 = (tmp + '/' + files.at(0)); - QString fileName2 = (tmp + '/' + files.at(1)); - QString fileName3 = (tmp + '/' + files.at(2)); - QFile::Permissions originalPermissions = QFile::permissions(fileName1); - QVERIFY(QFile::setPermissions(fileName1, QFile::WriteOwner)); - QVERIFY(QFile::setPermissions(fileName2, QFile::ReadOwner)); - QVERIFY(QFile::setPermissions(fileName3, QFile::ExeOwner)); - - model->setFilter((QDir::Files | QDir::Readable)); - QTRY_COMPARE(model->rowCount(root), 1); - - model->setFilter((QDir::Files | QDir::Writable)); - QTRY_COMPARE(model->rowCount(root), 1); - - model->setFilter((QDir::Files | QDir::Executable)); - QTRY_COMPARE(model->rowCount(root), 1); - - // reset permissions - QVERIFY(QFile::setPermissions(fileName1, originalPermissions)); - QVERIFY(QFile::setPermissions(fileName2, originalPermissions)); - QVERIFY(QFile::setPermissions(fileName3, originalPermissions)); - } -#endif -} - -void tst_QFileSystemModel::nameFilters() -{ - QStringList list; - list << "a" << "b" << "c"; - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - model->setNameFilters(list); - model->setNameFilterDisables(false); - QCOMPARE(model->nameFilters(), list); - - QString tmp = flatDirTestPath; - QVERIFY(createFiles(model.data(), tmp, list)); - QModelIndex root = model->setRootPath(tmp); - QTRY_COMPARE(model->rowCount(root), 3); - - QStringList filters; - filters << "a" << "b"; - model->setNameFilters(filters); - QTRY_COMPARE(model->rowCount(root), 2); -} -void tst_QFileSystemModel::setData_data() -{ - QTest::addColumn<QString>("subdirName"); - QTest::addColumn<QStringList>("files"); - QTest::addColumn<QString>("oldFileName"); - QTest::addColumn<QString>("newFileName"); - QTest::addColumn<bool>("success"); - /*QTest::newRow("outside current dir") << (QStringList() << "a" << "b" << "c") - << flatDirTestPath + '/' + "a" - << QDir::temp().absolutePath() + '/' + "a" - << false; - */ - - const QStringList abcList{QLatin1String("a"), QLatin1String("b"), QLatin1String("c")}; - QTest::newRow("in current dir") - << QString() - << abcList - << "a" - << "d" - << true; - QTest::newRow("in subdir") - << "s" - << abcList - << "a" - << "d" - << true; -} - -void tst_QFileSystemModel::setData() -{ - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QSignalSpy spy(model.data(), &QFileSystemModel::fileRenamed); - QFETCH(QString, subdirName); - QFETCH(QStringList, files); - QFETCH(QString, oldFileName); - QFETCH(QString, newFileName); - QFETCH(bool, success); - - QString tmp = flatDirTestPath; - if (!subdirName.isEmpty()) { - QDir dir(tmp); - QVERIFY(dir.mkdir(subdirName)); - tmp.append('/' + subdirName); - } - QVERIFY(createFiles(model.data(), tmp, files)); - QModelIndex tmpIdx = model->setRootPath(flatDirTestPath); - if (!subdirName.isEmpty()) { - tmpIdx = model->index(tmp); - model->fetchMore(tmpIdx); - } - QTRY_COMPARE(model->rowCount(tmpIdx), files.count()); - - QModelIndex idx = model->index(tmp + '/' + oldFileName); - QCOMPARE(idx.isValid(), true); - QCOMPARE(model->setData(idx, newFileName), false); - - model->setReadOnly(false); - QCOMPARE(model->setData(idx, newFileName), success); - model->setReadOnly(true); - if (success) { - QCOMPARE(spy.count(), 1); - QList<QVariant> arguments = spy.takeFirst(); - QCOMPARE(model->data(idx, QFileSystemModel::FileNameRole).toString(), newFileName); - QCOMPARE(model->fileInfo(idx).filePath(), tmp + '/' + newFileName); - QCOMPARE(model->index(arguments.at(0).toString()), model->index(tmp)); - QCOMPARE(arguments.at(1).toString(), oldFileName); - QCOMPARE(arguments.at(2).toString(), newFileName); - QCOMPARE(QFile::rename(tmp + '/' + newFileName, tmp + '/' + oldFileName), true); - } - QTRY_COMPARE(model->rowCount(tmpIdx), files.count()); - // cleanup - if (!subdirName.isEmpty()) - QVERIFY(QDir(tmp).removeRecursively()); -} - -void tst_QFileSystemModel::sortPersistentIndex() -{ - QTemporaryFile file(flatDirTestPath + QStringLiteral("/XXXXXX.dat")); - QVERIFY2(file.open(), qPrintable(file.errorString())); - const QFileInfo fileInfo(file.fileName()); - file.close(); - QTRY_VERIFY(QDir(flatDirTestPath).entryInfoList().contains(fileInfo)); - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QModelIndex root = model->setRootPath(flatDirTestPath); - QTRY_VERIFY(model->rowCount(root) > 0); - - QPersistentModelIndex idx = model->index(0, 1, root); - model->sort(0, Qt::AscendingOrder); - model->sort(0, Qt::DescendingOrder); - QVERIFY(idx.column() != 0); -} - -class MyFriendFileSystemModel : public QFileSystemModel -{ - friend class tst_QFileSystemModel; - Q_DECLARE_PRIVATE(QFileSystemModel) -}; - -void tst_QFileSystemModel::sort_data() -{ - QTest::addColumn<bool>("fileDialogMode"); - QTest::newRow("standard usage") << false; - QTest::newRow("QFileDialog usage") << true; -} - -void tst_QFileSystemModel::sort() -{ - QFETCH(bool, fileDialogMode); - - QScopedPointer<MyFriendFileSystemModel> myModel(new MyFriendFileSystemModel); - QTreeView tree; - tree.setWindowTitle(QTest::currentTestFunction()); - - if (fileDialogMode && EmulationDetector::isRunningArmOnX86()) - QSKIP("Crashes in QEMU. QTBUG-70572"); - -#ifdef QT_BUILD_INTERNAL - if (fileDialogMode) - myModel->d_func()->disableRecursiveSort = true; -#endif - - QDir dir(flatDirTestPath); - const QString dirPath = dir.absolutePath(); - - //Create a file that will be at the end when sorting by name (For Mac, the default) - //but if we sort by size descending it will be the first - QFile tempFile(dirPath + "/plop2.txt"); - tempFile.open(QIODevice::WriteOnly | QIODevice::Text); - QTextStream out(&tempFile); - out << "The magic number is: " << 49 << "\n"; - tempFile.close(); - - QFile tempFile2(dirPath + "/plop.txt"); - tempFile2.open(QIODevice::WriteOnly | QIODevice::Text); - QTextStream out2(&tempFile2); - out2 << "The magic number is : " << 49 << " but i write some stuff in the file \n"; - tempFile2.close(); - - myModel->setRootPath(""); - myModel->setFilter(QDir::AllEntries | QDir::System | QDir::Hidden); - tree.setSortingEnabled(true); - tree.setModel(myModel.data()); - tree.show(); - tree.resize(800, 800); - QVERIFY(QTest::qWaitForWindowExposed(&tree)); - tree.header()->setSortIndicator(1, Qt::DescendingOrder); - tree.header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); - QStringList dirsToOpen; - do { - dirsToOpen << dir.absolutePath(); - } while (dir.cdUp()); - - for (int i = dirsToOpen.size() -1 ; i > 0 ; --i) { - QString path = dirsToOpen[i]; - tree.expand(myModel->index(path, 0)); - } - tree.expand(myModel->index(dirPath, 0)); - QModelIndex parent = myModel->index(dirPath, 0); - QList<QString> expectedOrder; - expectedOrder << tempFile2.fileName() << tempFile.fileName() << dirPath + QChar('/') + ".." << dirPath + QChar('/') + "."; - - if (fileDialogMode) { - QTRY_COMPARE(myModel->rowCount(parent), expectedOrder.count()); - // File dialog Mode means sub trees are not sorted, only the current root. - // There's no way we can check that the sub tree is "not sorted"; just check if it - // has the same contents of the expected list - QList<QString> actualRows; - for(int i = 0; i < myModel->rowCount(parent); ++i) - { - actualRows << dirPath + QChar('/') + myModel->index(i, 1, parent).data(QFileSystemModel::FileNameRole).toString(); - } - - std::sort(expectedOrder.begin(), expectedOrder.end()); - std::sort(actualRows.begin(), actualRows.end()); - - QCOMPARE(actualRows, expectedOrder); - } else { - for(int i = 0; i < myModel->rowCount(parent); ++i) - { - QTRY_COMPARE(dirPath + QChar('/') + myModel->index(i, 1, parent).data(QFileSystemModel::FileNameRole).toString(), expectedOrder.at(i)); - } - } -} - -void tst_QFileSystemModel::mkdir() -{ - QString tmp = flatDirTestPath; - QString newFolderPath = QDir::toNativeSeparators(tmp + '/' + "NewFoldermkdirtest4"); - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QModelIndex tmpDir = model->index(tmp); - QVERIFY(tmpDir.isValid()); - QDir bestatic(newFolderPath); - if (bestatic.exists()) { - if (!bestatic.rmdir(newFolderPath)) - qWarning() << "unable to remove" << newFolderPath; - QTest::qWait(WAITTIME); - } - model->mkdir(tmpDir, "NewFoldermkdirtest3"); - model->mkdir(tmpDir, "NewFoldermkdirtest5"); - QModelIndex idx = model->mkdir(tmpDir, "NewFoldermkdirtest4"); - QVERIFY(idx.isValid()); - int oldRow = idx.row(); - idx = model->index(newFolderPath); - QVERIFY(idx.isValid()); - QVERIFY(model->remove(idx)); - QVERIFY(!bestatic.exists()); - QVERIFY(0 != idx.row()); - QCOMPARE(oldRow, idx.row()); -} - -void tst_QFileSystemModel::deleteFile() -{ - QString newFilePath = QDir::temp().filePath("NewFileDeleteTest"); - QFile newFile(newFilePath); - if (newFile.exists()) { - if (!newFile.remove()) - qWarning() << "unable to remove" << newFilePath; - QTest::qWait(WAITTIME); - } - if (!newFile.open(QIODevice::WriteOnly | QIODevice::Text)) { - qWarning() << "unable to create" << newFilePath; - } - newFile.close(); - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QModelIndex idx = model->index(newFilePath); - QVERIFY(idx.isValid()); - QVERIFY(model->remove(idx)); - QVERIFY(!newFile.exists()); -} - -void tst_QFileSystemModel::deleteDirectory() -{ - // QTBUG-65683: Verify that directories can be removed recursively despite - // file system watchers being active on them or their sub-directories (Windows). - // Create a temporary directory, a nested directory and expand a treeview - // to show them to ensure watcher creation. Then delete the directory. - QTemporaryDir dirToBeDeleted(flatDirTestPath + QStringLiteral("/deleteDirectory-XXXXXX")); - QVERIFY(dirToBeDeleted.isValid()); - const QString dirToBeDeletedPath = dirToBeDeleted.path(); - const QString nestedTestDir = QStringLiteral("test"); - QVERIFY(QDir(dirToBeDeletedPath).mkpath(nestedTestDir)); - const QString nestedTestDirPath = dirToBeDeletedPath + QLatin1Char('/') + nestedTestDir; - QFile testFile(nestedTestDirPath + QStringLiteral("/test.txt")); - QVERIFY(testFile.open(QIODevice::WriteOnly | QIODevice::Text)); - testFile.write("Hello\n"); - testFile.close(); - - QFileSystemModel model; - const QModelIndex rootIndex = model.setRootPath(flatDirTestPath); - QTreeView treeView; - treeView.setWindowTitle(QTest::currentTestFunction()); - treeView.setModel(&model); - treeView.setRootIndex(rootIndex); - - const QModelIndex dirToBeDeletedPathIndex = model.index(dirToBeDeletedPath); - QVERIFY(dirToBeDeletedPathIndex.isValid()); - treeView.setExpanded(dirToBeDeletedPathIndex, true); - const QModelIndex nestedTestDirIndex = model.index(nestedTestDirPath); - QVERIFY(nestedTestDirIndex.isValid()); - treeView.setExpanded(nestedTestDirIndex, true); - - treeView.show(); - QVERIFY(QTest::qWaitForWindowExposed(&treeView)); - - QVERIFY(model.remove(dirToBeDeletedPathIndex)); - dirToBeDeleted.setAutoRemove(false); -} - -static QString flipCase(QString s) -{ - for (int i = 0, size = s.size(); i < size; ++i) { - const QChar c = s.at(i); - if (c.isUpper()) - s[i] = c.toLower(); - else if (c.isLower()) - s[i] = c.toUpper(); - } - return s; -} - -void tst_QFileSystemModel::caseSensitivity() -{ - QString tmp = flatDirTestPath; - QStringList files; - files << "a" << "c" << "C"; - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QVERIFY(createFiles(model.data(), tmp, files)); - QModelIndex root = model->index(tmp); - QStringList paths; - QModelIndexList indexes; - QCOMPARE(model->rowCount(root), 0); - for (int i = 0; i < files.count(); ++i) { - const QString path = tmp + '/' + files.at(i); - const QModelIndex index = model->index(path); - QVERIFY(index.isValid()); - paths.append(path); - indexes.append(index); - } - - if (!QFileSystemEngine::isCaseSensitive()) { - // QTBUG-31103, QTBUG-64147: Verify that files can be accessed by paths with fLipPeD case. - for (int i = 0; i < paths.count(); ++i) { - const QModelIndex flippedCaseIndex = model->index(flipCase(paths.at(i))); - QCOMPARE(indexes.at(i), flippedCaseIndex); - } - } -} - -void tst_QFileSystemModel::drives_data() -{ - QTest::addColumn<QString>("path"); - QTest::newRow("current") << QDir::currentPath(); - QTest::newRow("slash") << "/"; - QTest::newRow("My Computer") << "My Computer"; -} - -void tst_QFileSystemModel::drives() -{ - QFETCH(QString, path); - QFileSystemModel model; - model.setRootPath(path); - model.fetchMore(QModelIndex()); - QFileInfoList drives = QDir::drives(); - int driveCount = 0; - foreach(const QFileInfo& driveRoot, drives) - if (driveRoot.exists()) - driveCount++; - QTRY_COMPARE(model.rowCount(), driveCount); -} - -void tst_QFileSystemModel::dirsBeforeFiles() -{ - auto diagnosticMsg = [](int row, const QFileInfo &left, const QFileInfo &right) -> QByteArray { - QString message; - QDebug(&message).noquote() << "Unexpected sort order at #" << row << ':' << left << right; - return message.toLocal8Bit(); - }; - QTemporaryDir testDir(flatDirTestPath); - QVERIFY2(testDir.isValid(), qPrintable(testDir.errorString())); - QDir dir(testDir.path()); - - const int itemCount = 3; - for (int i = 0; i < itemCount; ++i) { - QLatin1Char c('a' + char(i)); - QVERIFY(dir.mkdir(c + QLatin1String("-dir"))); - QFile file(dir.filePath(c + QLatin1String("-file"))); - QVERIFY(file.open(QIODevice::ReadWrite)); - file.close(); - } - - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QModelIndex root = model->setRootPath(dir.absolutePath()); - // Wait for model to be notified by the file system watcher - QTRY_COMPARE(model->rowCount(root), 2 * itemCount); - // sort explicitly - dirs before files (except on macOS), and then by name - model->sort(0); - // Ensure that no file occurs before any directory (see QFileSystemModelSorter): - for (int i = 1, count = model->rowCount(root); i < count; ++i) { - const QFileInfo previous = model->fileInfo(model->index(i - 1, 0, root)); - const QFileInfo current = model->fileInfo(model->index(i, 0, root)); -#ifndef Q_OS_MAC - QVERIFY2(!(previous.isFile() && current.isDir()), diagnosticMsg(i, previous, current).constData()); -#else - QVERIFY2(previous.fileName() < current.fileName(), diagnosticMsg(i, previous, current).constData()); -#endif - } -} - -void tst_QFileSystemModel::roleNames_data() -{ - QTest::addColumn<int>("role"); - QTest::addColumn<QByteArray>("roleName"); - QTest::newRow("decoration") << int(Qt::DecorationRole) << QByteArray("fileIcon"); - QTest::newRow("display") << int(Qt::DisplayRole) << QByteArray("display"); - QTest::newRow("fileIcon") << int(QFileSystemModel::FileIconRole) << QByteArray("fileIcon"); - QTest::newRow("filePath") << int(QFileSystemModel::FilePathRole) << QByteArray("filePath"); - QTest::newRow("fileName") << int(QFileSystemModel::FileNameRole) << QByteArray("fileName"); - QTest::newRow("filePermissions") << int(QFileSystemModel::FilePermissions) << QByteArray("filePermissions"); -} - -void tst_QFileSystemModel::roleNames() -{ - QFileSystemModel model; - QHash<int, QByteArray> roles = model.roleNames(); - - QFETCH(int, role); - QVERIFY(roles.contains(role)); - - QFETCH(QByteArray, roleName); - QCOMPARE(roles.contains(role), true); - QCOMPARE(roles.value(role), roleName); -} - -static inline QByteArray permissionRowName(bool readOnly, int permission) -{ - QByteArray result = readOnly ? QByteArrayLiteral("ro") : QByteArrayLiteral("rw"); - result += QByteArrayLiteral("-0"); - result += QByteArray::number(permission, 16); - return result; -} - -void tst_QFileSystemModel::permissions_data() -{ - QTest::addColumn<QFileDevice::Permissions>("permissions"); - QTest::addColumn<bool>("readOnly"); - - static const int permissions[] = { - QFile::WriteOwner, - QFile::ReadOwner, - QFile::WriteOwner|QFile::ReadOwner, - }; - for (int permission : permissions) { - QTest::newRow(permissionRowName(false, permission).constData()) << QFileDevice::Permissions(permission) << false; - QTest::newRow(permissionRowName(true, permission).constData()) << QFileDevice::Permissions(permission) << true; - } -} - -void tst_QFileSystemModel::permissions() // checks QTBUG-20503 -{ - QFETCH(QFileDevice::Permissions, permissions); - QFETCH(bool, readOnly); - - const QString tmp = flatDirTestPath; - const QString file = tmp + QLatin1String("/f"); - QScopedPointer<QFileSystemModel> model(new QFileSystemModel); - QVERIFY(createFiles(model.data(), tmp, QStringList{QLatin1String("f")})); - - QVERIFY(QFile::setPermissions(file, permissions)); - - const QModelIndex root = model->setRootPath(tmp); - - model->setReadOnly(readOnly); - - QCOMPARE(model->isReadOnly(), readOnly); - - QTRY_COMPARE(model->rowCount(root), 1); - - const QFile::Permissions modelPermissions = model->permissions(model->index(0, 0, root)); - const QFile::Permissions modelFileInfoPermissions = model->fileInfo(model->index(0, 0, root)).permissions(); - const QFile::Permissions fileInfoPermissions = QFileInfo(file).permissions(); - - QCOMPARE(modelPermissions, modelFileInfoPermissions); - QCOMPARE(modelFileInfoPermissions, fileInfoPermissions); - QCOMPARE(fileInfoPermissions, modelPermissions); -} - -void tst_QFileSystemModel::doNotUnwatchOnFailedRmdir() -{ - const QString tmp = flatDirTestPath; - - QFileSystemModel model; - - const QTemporaryDir tempDir(tmp + '/' + QStringLiteral("doNotUnwatchOnFailedRmdir-XXXXXX")); - QVERIFY(tempDir.isValid()); - - const QModelIndex rootIndex = model.setRootPath(tempDir.path()); - - // create a file in the directory so to prevent it from deletion - { - QFile file(tempDir.path() + '/' + QStringLiteral("file1")); - QVERIFY(file.open(QIODevice::WriteOnly)); - } - - QCOMPARE(model.rmdir(rootIndex), false); - - // create another file - { - QFile file(tempDir.path() + '/' + QStringLiteral("file2")); - QVERIFY(file.open(QIODevice::WriteOnly)); - } - - // the model must now detect this second file - QTRY_COMPARE(model.rowCount(rootIndex), 2); -} - -static QSet<QString> fileListUnderIndex(const QFileSystemModel *model, const QModelIndex &parent) -{ - QSet<QString> fileNames; - const int rowCount = model->rowCount(parent); - for (int i = 0; i < rowCount; ++i) - fileNames.insert(model->index(i, 0, parent).data(QFileSystemModel::FileNameRole).toString()); - return fileNames; -} - -void tst_QFileSystemModel::specialFiles() -{ -#ifndef Q_OS_UNIX - QSKIP("Not implemented"); -#endif - - QFileSystemModel model; - - model.setFilter(QDir::AllEntries | QDir::System | QDir::Hidden); - - // Can't simply verify if the model returns a valid model index for a special file - // as it will always return a valid index for existing files, - // even if the file is not visible with the given filter. - - const QModelIndex rootIndex = model.setRootPath(QStringLiteral("/dev/")); - const QString testFileName = QStringLiteral("null"); - - QTRY_VERIFY(fileListUnderIndex(&model, rootIndex).contains(testFileName)); - - model.setFilter(QDir::AllEntries | QDir::Hidden); - - QTRY_VERIFY(!fileListUnderIndex(&model, rootIndex).contains(testFileName)); -} - -void tst_QFileSystemModel::fileInfo() -{ - QFileSystemModel model; - QModelIndex idx; - - QVERIFY(model.fileInfo(idx).filePath().isEmpty()); - - const QString dirPath = flatDirTestPath; - QDir dir(dirPath); - const QString subdir = QStringLiteral("subdir"); - QVERIFY(dir.mkdir(subdir)); - const QString subdirPath = dir.absoluteFilePath(subdir); - - idx = model.setRootPath(subdirPath); - QCOMPARE(model.fileInfo(idx), QFileInfo(subdirPath)); - idx = model.setRootPath(dirPath); - QCOMPARE(model.fileInfo(idx), QFileInfo(dirPath)); -} - -QTEST_MAIN(tst_QFileSystemModel) -#include "tst_qfilesystemmodel.moc" - diff --git a/tests/auto/widgets/dialogs/qfontdialog/CMakeLists.txt b/tests/auto/widgets/dialogs/qfontdialog/CMakeLists.txt index e8a6d368b8..b1bbf62cc7 100644 --- a/tests/auto/widgets/dialogs/qfontdialog/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qfontdialog/CMakeLists.txt @@ -1,19 +1,15 @@ -# Generated from qfontdialog.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qfontdialog Test: ##################################################################### -qt_add_test(tst_qfontdialog - SOURCES - tst_qfontdialog.cpp - PUBLIC_LIBRARIES - Qt::CorePrivate - Qt::Gui - Qt::GuiPrivate - Qt::Widgets - Qt::WidgetsPrivate -) +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" @@ -27,13 +23,18 @@ set(testfonts_resource_files "../../../shared/resources/testfont.ttf" ) -qt_add_resource(tst_qfontdialog "testfonts" - PREFIX - "/" - FILES - ${testfonts_resource_files} +qt_internal_add_test(tst_qfontdialog + SOURCES + tst_qfontdialog.cpp + LIBRARIES + Qt::CorePrivate + Qt::Gui + Qt::GuiPrivate + Qt::Widgets + Qt::WidgetsPrivate + TESTDATA ${testfonts_resource_files} + BUILTIN_TESTDATA ) - ## Scopes: ##################################################################### diff --git a/tests/auto/widgets/dialogs/qfontdialog/qfontdialog.pro b/tests/auto/widgets/dialogs/qfontdialog/qfontdialog.pro deleted file mode 100644 index 320d6ee3b5..0000000000 --- a/tests/auto/widgets/dialogs/qfontdialog/qfontdialog.pro +++ /dev/null @@ -1,16 +0,0 @@ -CONFIG += testcase -TARGET = tst_qfontdialog - -QT += widgets widgets-private testlib -QT += core-private gui-private - -SOURCES += tst_qfontdialog.cpp - -RESOURCES += testfonts.qrc - -osx { -# ### fixme -# OBJECTIVE_SOURCES += tst_qfontdialog_mac_helpers.mm -# LIBS += -framework AppKit -} - diff --git a/tests/auto/widgets/dialogs/qfontdialog/testfonts.qrc b/tests/auto/widgets/dialogs/qfontdialog/testfonts.qrc deleted file mode 100644 index cdfa287b39..0000000000 --- a/tests/auto/widgets/dialogs/qfontdialog/testfonts.qrc +++ /dev/null @@ -1,6 +0,0 @@ -<RCC> - <qresource prefix="/"> - <file alias="test.ttf">../../../shared/resources/test.ttf</file> - <file alias="testfont.ttf">../../../shared/resources/testfont.ttf</file> - </qresource> -</RCC> diff --git a/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp b/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp index 628af91674..01f3e7ec95 100644 --- a/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp +++ b/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp @@ -1,33 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> #include <qapplication.h> @@ -70,6 +45,7 @@ private slots: void qtbug_41513_stylesheetStyle(); #endif + void hideNativeByDestruction(); private: void runSlotWithFailsafeTimer(const char *member); @@ -101,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 ); @@ -182,7 +158,6 @@ void tst_QFontDialog::task256466_wrongStyle() if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) QSKIP("Wayland: This freezes. Figure out why."); - QFontDatabase fdb; FriendlyFontDialog dialog; dialog.setOption(QFontDialog::DontUseNativeDialog); QListView *familyList = reinterpret_cast<QListView*>(dialog.d_func()->familyList); @@ -193,7 +168,7 @@ void tst_QFontDialog::task256466_wrongStyle() familyList->setCurrentIndex(currentFamily); int expectedSize = sizeList->currentIndex().data().toInt(); const QFont current = dialog.currentFont(), - expected = fdb.font(currentFamily.data().toString(), + expected = QFontDatabase::font(currentFamily.data().toString(), styleList->currentIndex().data().toString(), expectedSize); QCOMPARE(current.family(), expected.family()); QCOMPARE(current.style(), expected.style()); @@ -241,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."); @@ -261,7 +236,34 @@ void tst_QFontDialog::testNonStandardFontSize() if (accepted) QCOMPARE(testFont.pointSize(), resultFont.pointSize()); else - QWARN("Fail using a non-standard font size."); + 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) 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 00cc6a879f..0000000000 --- a/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog_mac_helpers.mm +++ /dev/null @@ -1,53 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#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 9cd73ef4f1..528493a66b 100644 --- a/tests/auto/widgets/dialogs/qinputdialog/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qinputdialog/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qinputdialog.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qinputdialog Test: ##################################################################### -qt_add_test(tst_qinputdialog +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 - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui Qt::WidgetsPrivate ) diff --git a/tests/auto/widgets/dialogs/qinputdialog/qinputdialog.pro b/tests/auto/widgets/dialogs/qinputdialog/qinputdialog.pro deleted file mode 100644 index 9cb14c5350..0000000000 --- a/tests/auto/widgets/dialogs/qinputdialog/qinputdialog.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qinputdialog -QT += widgets-private testlib -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 877784041b..136c789abd 100644 --- a/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp +++ b/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp @@ -1,39 +1,16 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> #include <QString> #include <QSpinBox> #include <QPushButton> #include <QLineEdit> #include <QComboBox> #include <QDialogButtonBox> +#include <QTimer> + #include <qinputdialog.h> #include <QtWidgets/private/qdialog_p.h> @@ -48,7 +25,7 @@ class tst_QInputDialog : public QObject static void testFuncGetText(QInputDialog *dialog); static void testFuncGetItem(QInputDialog *dialog); static void testFuncSingleStepDouble(QInputDialog *dialog); - void timerEvent(QTimerEvent *event); + void timerEvent(QTimerEvent *event) override; private slots: void getInt_data(); void getInt(); diff --git a/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST b/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST deleted file mode 100644 index 8d8a7c2105..0000000000 --- a/tests/auto/widgets/dialogs/qmessagebox/BLACKLIST +++ /dev/null @@ -1,4 +0,0 @@ -[defaultButton] -opensuse-leap -rhel-7.6 -ubuntu diff --git a/tests/auto/widgets/dialogs/qmessagebox/CMakeLists.txt b/tests/auto/widgets/dialogs/qmessagebox/CMakeLists.txt index f26171f08a..53fd8a61c6 100644 --- a/tests/auto/widgets/dialogs/qmessagebox/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qmessagebox/CMakeLists.txt @@ -1,18 +1,22 @@ -# Generated from qmessagebox.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qmessagebox Test: ##################################################################### -qt_add_test(tst_qmessagebox +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 - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate Qt::Widgets ) - -#### Keys ignored in scope 1:.:.:qmessagebox.pro:<TRUE>: -# TEMPLATE = "app" diff --git a/tests/auto/widgets/dialogs/qmessagebox/qmessagebox.pro b/tests/auto/widgets/dialogs/qmessagebox/qmessagebox.pro deleted file mode 100644 index 91848fee24..0000000000 --- a/tests/auto/widgets/dialogs/qmessagebox/qmessagebox.pro +++ /dev/null @@ -1,6 +0,0 @@ -TEMPLATE = app -TARGET = tst_qmessagebox -QT += gui-private core-private widgets testlib -CONFIG += testcase - -SOURCES += tst_qmessagebox.cpp diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp index 3169a9cb4e..94afff6e40 100644 --- a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp +++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp @@ -1,40 +1,19 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// 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> #include <QTimer> #include <QApplication> #include <QPushButton> #include <QDialogButtonBox> +#include <QSignalSpy> + #include <qpa/qplatformtheme.h> #include <private/qguiapplication_p.h> @@ -43,9 +22,14 @@ class tst_QMessageBox : public QObject Q_OBJECT private slots: + void initTestCase_data(); + void init(); + void sanityTest(); + void baseClassSetVisible(); void defaultButton(); void escapeButton(); + void clickedButton(); void button(); void statics(); void about(); @@ -53,6 +37,9 @@ private slots: void detailsButtonText(); void expandDetailsWithoutMoving(); + void optionsEmptyByDefault(); + void changeNativeOption(); + #ifndef Q_OS_MAC void shortcut(); #endif @@ -70,6 +57,13 @@ private slots: void acceptedRejectedSignals(); void acceptedRejectedSignals_data(); + void overrideDone_data(); + void overrideDone(); + + void hideNativeByDestruction(); + + void explicitDoneAfterButtonClicked(); + void cleanup(); }; @@ -80,7 +74,8 @@ public: bool resized; protected: - void resizeEvent ( QResizeEvent * event ) { + void resizeEvent ( QResizeEvent * event ) override + { resized = true; QMessageBox::resizeEvent(event); } @@ -121,11 +116,20 @@ void ExecCloseHelper::timerEvent(QTimerEvent *te) return; QWidget *modalWidget = QApplication::activeModalWidget(); - if (!m_testCandidate && modalWidget) m_testCandidate = modalWidget; - if (m_testCandidate && m_testCandidate == modalWidget) { + QWidget *activeWindow = QApplication::activeWindow(); + if (!m_testCandidate && activeWindow) + m_testCandidate = activeWindow; + + if (!m_testCandidate) + return; + + bool shouldHelp = (m_testCandidate->isModal() && m_testCandidate == modalWidget) + || (!m_testCandidate->isModal() && m_testCandidate == activeWindow); + + if (shouldHelp) { if (m_key == CloseWindow) { m_testCandidate->close(); } else { @@ -138,6 +142,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 @@ -164,6 +222,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; @@ -297,6 +364,28 @@ void tst_QMessageBox::escapeButton() QVERIFY(msgBox3.clickedButton() == msgBox3.button(QMessageBox::Ok)); // auto detected } +void tst_QMessageBox::clickedButton() +{ + QMessageBox msgBox; + msgBox.addButton(QMessageBox::Yes); + msgBox.addButton(QMessageBox::No); + msgBox.addButton(QMessageBox::Retry); + + QVERIFY(!msgBox.clickedButton()); + + for (int i = 0; i < 2; ++i) { + QAbstractButton *clickedButtonAfterExex = nullptr; + QTimer::singleShot(100, [&] { + clickedButtonAfterExex = msgBox.clickedButton(); + msgBox.close(); + }); + msgBox.exec(); + + QVERIFY(!clickedButtonAfterExex); + QVERIFY(msgBox.clickedButton()); + } +} + void tst_QMessageBox::statics() { QMessageBox::StandardButton (*statics[4])(QWidget *, const QString &, @@ -350,7 +439,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 @@ -383,69 +472,63 @@ void tst_QMessageBox::staticSourceCompat() int ret; // 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, 3); // Custom button opaque result 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() { - 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); @@ -456,15 +539,19 @@ void tst_QMessageBox::instanceSourceCompat() QCOMPARE(mb.exec(), int(QMessageBox::Cancel)); #ifndef Q_OS_MAC // mnemonics are not used on OS X - closeHelper.start(Qt::ALT + Qt::Key_R, &mb); - QCOMPARE(mb.exec(), 0); - closeHelper.start(Qt::ALT + Qt::Key_Z, &mb); - QCOMPARE(mb.exec(), 1); + closeHelper.start(QKeyCombination(Qt::ALT | Qt::Key_R).toCombined(), &mb); + QCOMPARE(mb.exec(), 2); + closeHelper.start(QKeyCombination(Qt::ALT | Qt::Key_Z).toCombined(), &mb); + QCOMPARE(mb.exec(), 3); #endif } 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); @@ -478,6 +565,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(); @@ -499,6 +590,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(); @@ -524,6 +619,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; @@ -538,12 +647,17 @@ 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"); +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED //do not crash here -> call old function of QMessageBox in this case 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() @@ -593,6 +707,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); @@ -614,7 +732,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()); } @@ -672,5 +790,78 @@ 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); +} + 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 f3d7fc365b..4861f3af25 100644 --- a/tests/auto/widgets/dialogs/qprogressdialog/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qprogressdialog/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qprogressdialog.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qprogressdialog Test: ##################################################################### -qt_add_test(tst_qprogressdialog +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 - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui Qt::Widgets ) diff --git a/tests/auto/widgets/dialogs/qprogressdialog/qprogressdialog.pro b/tests/auto/widgets/dialogs/qprogressdialog/qprogressdialog.pro deleted file mode 100644 index 10aeaace71..0000000000 --- a/tests/auto/widgets/dialogs/qprogressdialog/qprogressdialog.pro +++ /dev/null @@ -1,8 +0,0 @@ -############################################################ -# Project file for autotest for file qprogressdialog.h -############################################################ - -CONFIG += testcase -TARGET = tst_qprogressdialog -QT += widgets testlib -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 6f527e7b6b..baf727d766 100644 --- a/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp +++ b/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp @@ -1,33 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> #include <qapplication.h> #include <qdebug.h> @@ -51,8 +26,10 @@ private Q_SLOTS: void getSetCheck(); void task198202(); void QTBUG_31046(); + void QTBUG_19983(); void settingCustomWidgets(); void i18n(); + void setValueReentrancyGuard(); }; void tst_QProgressDialog::cleanup() @@ -107,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); } @@ -116,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()); } @@ -204,11 +181,34 @@ 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()); } +void tst_QProgressDialog::QTBUG_19983() +{ + QProgressDialog tempDlg; + tempDlg.setRange(0, 0); + tempDlg.setLabelText("This is a test."); + + QPushButton *btnOne = new QPushButton("Cancel", &tempDlg); + tempDlg.setCancelButton(btnOne); + tempDlg.show(); + QVERIFY(QTest::qWaitForWindowExposed(&tempDlg)); + const auto btnOneGeometry = btnOne->geometry(); + QVERIFY(QPoint(0,0) != btnOneGeometry.topLeft()); + + tempDlg.cancel(); + QVERIFY(!tempDlg.isVisible()); + + QPushButton *btnTwo = new QPushButton("Cancel", &tempDlg); + tempDlg.setCancelButton(btnTwo); + tempDlg.show(); + QVERIFY(QTest::qWaitForWindowExposed(&tempDlg)); + QCOMPARE(btnOneGeometry, btnTwo->geometry()); +} + void tst_QProgressDialog::settingCustomWidgets() { QPointer<QLabel> l = new QLabel; @@ -291,5 +291,28 @@ void tst_QProgressDialog::i18n() QVERIFY(!btn->text().startsWith(xxx)); } +void tst_QProgressDialog::setValueReentrancyGuard() +{ + // Tests setValue() of window modal QProgressBar with + // Qt::QueuedConnection: + // This test crashes with a stack overflow if the boolean + // guard "processingEvents" that prevents reentranct calls + // to QCoreApplication::processEvents() within setValue() + // has not been implemented + + constexpr int steps = 100; // Should be at least 50 to test for crash + + QProgressDialog dlg("Testing setValue reentrancy guard...", QString(), 0, steps); + dlg.setWindowModality(Qt::WindowModal); + dlg.setMinimumDuration(0); + dlg.setAutoReset(false); + + // Simulate a quick work loop + for (int i = 0; i <= steps; ++i) + QMetaObject::invokeMethod(&dlg, "setValue", Qt::QueuedConnection, Q_ARG(int, i)); + + QTRY_COMPARE(dlg.value(), steps); +} + QTEST_MAIN(tst_QProgressDialog) #include "tst_qprogressdialog.moc" diff --git a/tests/auto/widgets/dialogs/qsidebar/CMakeLists.txt b/tests/auto/widgets/dialogs/qsidebar/CMakeLists.txt index d92fac5253..bf9513bb69 100644 --- a/tests/auto/widgets/dialogs/qsidebar/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qsidebar/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qsidebar.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qsidebar Test: ##################################################################### -qt_add_test(tst_qsidebar +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 - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::Widgets diff --git a/tests/auto/widgets/dialogs/qsidebar/qsidebar.pro b/tests/auto/widgets/dialogs/qsidebar/qsidebar.pro deleted file mode 100644 index 18e637199a..0000000000 --- a/tests/auto/widgets/dialogs/qsidebar/qsidebar.pro +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG += testcase - -QT += core-private -QT += widgets widgets-private testlib -SOURCES += tst_qsidebar.cpp -TARGET = tst_qsidebar diff --git a/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp b/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp index 146a9e262d..cdbf2011a4 100644 --- a/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp +++ b/tests/auto/widgets/dialogs/qsidebar/tst_qsidebar.cpp @@ -1,35 +1,13 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> +#include <QSignalSpy> + #include <QtWidgets/private/qsidebar_p.h> -#include <QtWidgets/private/qfilesystemmodel_p.h> +#include <QtGui/private/qfilesystemmodel_p.h> +#include <QtWidgets/qfileiconprovider.h> class tst_QSidebar : public QObject { Q_OBJECT @@ -40,12 +18,16 @@ private slots: void addUrls(); void goToUrl(); + +private: + QFileIconProvider defaultIconProvider; }; void tst_QSidebar::setUrls() { QList<QUrl> urls; QFileSystemModel fsmodel; + fsmodel.setIconProvider(&defaultIconProvider); QSidebar qsidebar; qsidebar.setModelAndUrls(&fsmodel, urls); QAbstractItemModel *model = qsidebar.model(); @@ -56,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() @@ -67,24 +49,26 @@ void tst_QSidebar::selectUrls() urls << QUrl::fromLocalFile(QDir::rootPath()) << QUrl::fromLocalFile(QDir::temp().absolutePath()); QFileSystemModel fsmodel; + fsmodel.setIconProvider(&defaultIconProvider); QSidebar qsidebar; qsidebar.setModelAndUrls(&fsmodel, urls); QSignalSpy spy(&qsidebar, SIGNAL(goToUrl(QUrl))); qsidebar.selectUrl(urls.at(0)); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); } void tst_QSidebar::addUrls() { QList<QUrl> emptyUrls; QFileSystemModel fsmodel; + fsmodel.setIconProvider(&defaultIconProvider); QSidebar qsidebar; qsidebar.setModelAndUrls(&fsmodel, emptyUrls); QAbstractItemModel *model = qsidebar.model(); QDir testDir = QDir::home(); -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) +#ifdef Q_OS_ANDROID // temp and home is the same directory on Android testDir.mkdir(QStringLiteral("test")); QVERIFY(testDir.cd(QStringLiteral("test"))); @@ -179,6 +163,7 @@ void tst_QSidebar::goToUrl() urls << QUrl::fromLocalFile(QDir::rootPath()) << QUrl::fromLocalFile(QDir::temp().absolutePath()); QFileSystemModel fsmodel; + fsmodel.setIconProvider(&defaultIconProvider); QSidebar qsidebar; qsidebar.setModelAndUrls(&fsmodel, urls); qsidebar.show(); @@ -186,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/BLACKLIST b/tests/auto/widgets/dialogs/qwizard/BLACKLIST new file mode 100644 index 0000000000..41b49ec112 --- /dev/null +++ b/tests/auto/widgets/dialogs/qwizard/BLACKLIST @@ -0,0 +1,3 @@ +# QTBUG-87394 +[setOption_IgnoreSubTitles] +android diff --git a/tests/auto/widgets/dialogs/qwizard/CMakeLists.txt b/tests/auto/widgets/dialogs/qwizard/CMakeLists.txt index f385812b40..d863126560 100644 --- a/tests/auto/widgets/dialogs/qwizard/CMakeLists.txt +++ b/tests/auto/widgets/dialogs/qwizard/CMakeLists.txt @@ -1,17 +1,15 @@ -# Generated from qwizard.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qwizard Test: ##################################################################### -qt_add_test(tst_qwizard - SOURCES - tst_qwizard.cpp - tst_qwizard_2.cpp - PUBLIC_LIBRARIES - Qt::Gui - Qt::Widgets -) +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 @@ -21,10 +19,15 @@ set(qwizard_resource_files "images/watermark.png" ) -qt_add_resource(tst_qwizard "qwizard" - PREFIX - "/" - FILES - ${qwizard_resource_files} +qt_internal_add_test(tst_qwizard + SOURCES + tst_qwizard.cpp + tst_qwizard_2.cpp + LIBRARIES + Qt::Gui + Qt::Widgets + Qt::WidgetsPrivate + TESTDATA ${qwizard_resource_files} + BUILTIN_TESTDATA ) diff --git a/tests/auto/widgets/dialogs/qwizard/qwizard.pro b/tests/auto/widgets/dialogs/qwizard/qwizard.pro deleted file mode 100644 index c6e5bcea7a..0000000000 --- a/tests/auto/widgets/dialogs/qwizard/qwizard.pro +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG += testcase -TARGET = tst_qwizard -QT += widgets testlib -SOURCES += tst_qwizard.cpp tst_qwizard_2.cpp -RESOURCES = qwizard.qrc diff --git a/tests/auto/widgets/dialogs/qwizard/qwizard.qrc b/tests/auto/widgets/dialogs/qwizard/qwizard.qrc deleted file mode 100644 index 471da9def6..0000000000 --- a/tests/auto/widgets/dialogs/qwizard/qwizard.qrc +++ /dev/null @@ -1,8 +0,0 @@ -<!DOCTYPE RCC><RCC version="1.0"> -<qresource> - <file>images/background.png</file> - <file>images/banner.png</file> - <file>images/logo.png</file> - <file>images/watermark.png</file> -</qresource> -</RCC> diff --git a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp index e9bf14b1e6..c0afed6919 100644 --- a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp +++ b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QFont> -#include <QtTest/QtTest> +#include <QTest> #include <QCheckBox> #include <QLabel> #include <QLineEdit> @@ -39,6 +14,12 @@ #include <QWizard> #include <QTreeWidget> #include <QScreen> +#include <QSignalSpy> +#include <QOperatingSystemVersion> + +#include <QtWidgets/private/qapplication_p.h> + +#include <memory> Q_DECLARE_METATYPE(QWizard::WizardButton); @@ -87,6 +68,7 @@ private slots: void sideWidget(); void objectNames_data(); void objectNames(); + void changePages(); // task-specific tests below me: void task177716_disableCommitButton(); @@ -372,11 +354,11 @@ void tst_QWizard::setButton() QVERIFY(qobject_cast<QCheckBox *>(wizard.button(QWizard::CustomButton2))); QVERIFY(qobject_cast<QPushButton *>(wizard.button(QWizard::CustomButton1))); - QVERIFY(toolButton != 0); + QVERIFY(toolButton != nullptr); // resetting the same button does nothing wizard.setButton(QWizard::NextButton, toolButton); - QVERIFY(toolButton != 0); + QVERIFY(toolButton != nullptr); // revert to default button wizard.setButton(QWizard::NextButton, 0); @@ -418,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()); @@ -426,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()); @@ -470,8 +452,8 @@ public: } void registerField(const QString &name, QWidget *widget, - const char *property = 0, - const char *changedSignal = 0) + const char *property = nullptr, + const char *changedSignal = nullptr) { QWizardPage::registerField(name, widget, property, changedSignal); } QLineEdit *edit1; @@ -544,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); } @@ -557,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) @@ -606,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)); @@ -618,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); @@ -631,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); @@ -652,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); @@ -671,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); @@ -742,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; } @@ -821,9 +803,9 @@ struct MyPage2 : public QWizardPage public: MyPage2() : init(0), cleanup(0), validate(0) {} - void initializePage() { ++init; QWizardPage::initializePage(); } - void cleanupPage() { ++cleanup; QWizardPage::cleanupPage(); } - bool validatePage() { ++validate; return QWizardPage::validatePage(); } + void initializePage() override { ++init; QWizardPage::initializePage(); } + void cleanupPage() override { ++cleanup; QWizardPage::cleanupPage(); } + bool validatePage() override { ++validate; return QWizardPage::validatePage(); } bool sanityCheck(int init, int cleanup) { @@ -1000,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); @@ -1592,18 +1574,18 @@ protected: class SetPage : public Operation { - void apply(QWizard *wizard) const + void apply(QWizard *wizard) const override { wizard->restart(); for (int j = 0; j < page; ++j) wizard->next(); } - QString describe() const { return QLatin1String("set page ") + QString::number(page); } + 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; } @@ -1611,13 +1593,13 @@ public: class SetStyle : public Operation { - void apply(QWizard *wizard) const { wizard->setWizardStyle(style); } - QString describe() const { return QLatin1String("set style ") + QString::number(style); } + void apply(QWizard *wizard) const override { wizard->setWizardStyle(style); } + 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; } @@ -1625,14 +1607,14 @@ public: class SetOption : public Operation { - void apply(QWizard *wizard) const { wizard->setOption(option, on); } - QString describe() const; + void apply(QWizard *wizard) const override { wizard->setOption(option, on); } + QString describe() const override; 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; @@ -1661,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_; } @@ -1670,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() { @@ -1679,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(); } }; @@ -1690,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 { @@ -1707,7 +1689,7 @@ public: combinations.clear(); } - QList<QSharedPointer<Operation>> &add() + QList<std::shared_ptr<Operation>> &add() { combinations.resize(combinations.size() + 1); return combinations.last(); @@ -1715,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_; @@ -1728,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 @@ -1805,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(") "); @@ -1834,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); } @@ -1909,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; @@ -1926,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; @@ -1949,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; @@ -1972,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; @@ -1991,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; @@ -2001,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; @@ -2064,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) @@ -2117,8 +2108,8 @@ class WizardPage : public QWizardPage { Q_OBJECT bool shown_; - void showEvent(QShowEvent *) { shown_ = true; } - void hideEvent(QHideEvent *) { shown_ = false; } + void showEvent(QShowEvent *) override { shown_ = true; } + void hideEvent(QHideEvent *) override { shown_ = false; } public: WizardPage() : shown_(false) {} bool shown() const { return shown_; } @@ -2133,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; @@ -2151,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()); } @@ -2295,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)); @@ -2334,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); @@ -2347,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); @@ -2363,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); @@ -2377,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); @@ -2387,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); @@ -2397,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()); @@ -2409,7 +2400,7 @@ void tst_QWizard::sideWidget() { QWizard wizard; - wizard.setSideWidget(0); + wizard.setSideWidget(nullptr); QVERIFY(!wizard.sideWidget()); QScopedPointer<QWidget> w1(new QWidget(&wizard)); wizard.setSideWidget(w1.data()); @@ -2417,11 +2408,11 @@ void tst_QWizard::sideWidget() QWidget *w2 = new QWidget(&wizard); wizard.setSideWidget(w2); QCOMPARE(wizard.sideWidget(), w2); - QVERIFY(w1->parent() != 0); + QVERIFY(w1->parent() != nullptr); QCOMPARE(w1->window(), static_cast<QWidget *>(&wizard)); QCOMPARE(w2->window(), static_cast<QWidget *>(&wizard)); - w1->setParent(0); - wizard.setSideWidget(0); + w1->setParent(nullptr); + wizard.setSideWidget(nullptr); QVERIFY(!wizard.sideWidget()); } @@ -2498,7 +2489,7 @@ void tst_QWizard::task177716_disableCommitButton() class WizardPage_task183550 : public QWizardPage { public: - WizardPage_task183550(QWidget *parent = 0) + WizardPage_task183550(QWidget *parent = nullptr) : QWizardPage(parent) , treeWidget(new QTreeWidget) , verticalPolicy(QSizePolicy::MinimumExpanding) {} @@ -2511,7 +2502,7 @@ private: QTreeWidget *treeWidget; QSizePolicy::Policy verticalPolicy; - void initializePage() + void initializePage() override { if (layout()) delete layout(); @@ -2585,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()); @@ -2718,6 +2710,45 @@ void tst_QWizard::taskQTBUG_46894_nextButtonShortcut() } } +/* setCurrentId(int) method was added in QTBUG99488 */ +void tst_QWizard::changePages() +{ + QWizard wizard; + + QList<QWizardPage*> pages; + for (int i = 0; i < 4; ++i) { + QWizardPage *page = new QWizardPage; + wizard.addPage(page); + pages.append(page); + } + + wizard.show(); + QVERIFY(QTest::qWaitForWindowExposed(&wizard)); + + // Verify default page + QCOMPARE(wizard.currentPage(), pages.at(0)); + + wizard.next(); + QVERIFY(wizard.currentId() == 1); + wizard.back(); + QVERIFY(wizard.currentId() == 0); + + // Test illegal page + QTest::ignoreMessage(QtMsgType::QtWarningMsg, "QWizard::setCurrentId: No such page: 5"); + wizard.setCurrentId(5); + QCOMPARE(wizard.currentId(), 0); + + for (int i = 0; i < 4; ++i) { + wizard.setCurrentId(i); + QCOMPARE(wizard.currentPage(), pages.at(i)); + } + + for (int i = 3; i >= 0; --i) { + wizard.setCurrentId(i); + QCOMPARE(wizard.currentPage(), pages.at(i)); + } +} + #endif // QT_CONFIG(shortcut) QTEST_MAIN(tst_QWizard) diff --git a/tests/auto/widgets/dialogs/qwizard/tst_qwizard_2.cpp b/tests/auto/widgets/dialogs/qwizard/tst_qwizard_2.cpp index 0969cecc45..8eef99ff38 100644 --- a/tests/auto/widgets/dialogs/qwizard/tst_qwizard_2.cpp +++ b/tests/auto/widgets/dialogs/qwizard/tst_qwizard_2.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QComboBox> @@ -35,13 +10,13 @@ #include <QWizard> #include <QWizardPage> -#include <QtTest/QtTest> +#include <QTest> class taskQTBUG_25691 : public QWizard { Q_OBJECT public: - taskQTBUG_25691( QWidget * parent = 0 ); + taskQTBUG_25691( QWidget * parent = nullptr ); ~taskQTBUG_25691(void); }; @@ -50,7 +25,7 @@ class taskQTBUG_25691Page1 : public QWizardPage { Q_OBJECT public: - taskQTBUG_25691Page1( QWidget * parent = 0 ); + taskQTBUG_25691Page1( QWidget * parent = nullptr ); ~taskQTBUG_25691Page1(void); }; @@ -59,9 +34,9 @@ class taskQTBUG_25691Page2 : public QWizardPage { Q_OBJECT public: - taskQTBUG_25691Page2( QWidget * parent = 0 ); + taskQTBUG_25691Page2( QWidget * parent = nullptr ); - virtual void initializePage(void); + virtual void initializePage(void) override; ~taskQTBUG_25691Page2(void); |