summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/widgets/dialogs/qcolordialog.cpp34
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp48
-rw-r--r--src/widgets/dialogs/qfiledialog_p.h1
-rw-r--r--src/widgets/dialogs/qfontdialog.cpp29
-rw-r--r--src/widgets/dialogs/qfontdialog_p.h1
-rw-r--r--tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp17
-rw-r--r--tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp29
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp48
-rw-r--r--tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp28
-rw-r--r--tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp29
10 files changed, 224 insertions, 40 deletions
diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp
index 8b3fb28c7d..5ec2424b5c 100644
--- a/src/widgets/dialogs/qcolordialog.cpp
+++ b/src/widgets/dialogs/qcolordialog.cpp
@@ -120,6 +120,7 @@ public:
bool handleColorPickingKeyPress(QKeyEvent *e);
bool canBeNativeDialog() const override;
+ void setVisible(bool visible) override;
QWellArray *custom;
QWellArray *standard;
@@ -2139,30 +2140,42 @@ QColorDialog::ColorDialogOptions QColorDialog::options() const
*/
void QColorDialog::setVisible(bool visible)
{
- Q_D(QColorDialog);
+ // will call QColorDialogPrivate::setVisible override
+ QDialog::setVisible(visible);
+}
+/*!
+ \internal
+
+ The implementation of QColorDialog::setVisible() has to live here so that the call
+ to hide() in ~QDialog calls this function; it wouldn't call the override of
+ QDialog::setVisible().
+*/
+void QColorDialogPrivate::setVisible(bool visible)
+{
+ Q_Q(QColorDialog);
if (visible){
- if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
+ if (q->testAttribute(Qt::WA_WState_ExplicitShowHide) && !q->testAttribute(Qt::WA_WState_Hidden))
return;
- } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
+ } else if (q->testAttribute(Qt::WA_WState_ExplicitShowHide) && q->testAttribute(Qt::WA_WState_Hidden))
return;
if (visible)
- d->selectedQColor = QColor();
+ selectedQColor = QColor();
- if (d->nativeDialogInUse) {
- if (d->setNativeDialogVisible(visible)) {
+ if (nativeDialogInUse) {
+ if (setNativeDialogVisible(visible)) {
// Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
// updates the state correctly, but skips showing the non-native version:
- setAttribute(Qt::WA_DontShowOnScreen);
+ q->setAttribute(Qt::WA_DontShowOnScreen);
} else {
- d->initWidgets();
+ initWidgets();
}
} else {
- setAttribute(Qt::WA_DontShowOnScreen, false);
+ q->setAttribute(Qt::WA_DontShowOnScreen, false);
}
- QDialog::setVisible(visible);
+ QDialogPrivate::setVisible(visible);
}
/*!
@@ -2210,7 +2223,6 @@ QColor QColorDialog::getColor(const QColor &initial, QWidget *parent, const QStr
QColorDialog::~QColorDialog()
{
-
}
/*!
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index a07cc33711..e985baa3af 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -835,41 +835,53 @@ void QFileDialog::open(QObject *receiver, const char *member)
*/
void QFileDialog::setVisible(bool visible)
{
- Q_D(QFileDialog);
+ // will call QFileDialogPrivate::setVisible override
+ QDialog::setVisible(visible);
+}
+
+/*!
+ \internal
+
+ The logic has to live here so that the call to hide() in ~QDialog calls
+ this function; it wouldn't call an override of QDialog::setVisible().
+*/
+void QFileDialogPrivate::setVisible(bool visible)
+{
+ Q_Q(QFileDialog);
if (visible){
- if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden))
+ if (q->testAttribute(Qt::WA_WState_ExplicitShowHide) && !q->testAttribute(Qt::WA_WState_Hidden))
return;
- } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden))
+ } else if (q->testAttribute(Qt::WA_WState_ExplicitShowHide) && q->testAttribute(Qt::WA_WState_Hidden))
return;
- if (d->canBeNativeDialog()){
- if (d->setNativeDialogVisible(visible)){
- // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
+ if (canBeNativeDialog()){
+ if (setNativeDialogVisible(visible)){
+ // Set WA_DontShowOnScreen so that QDialogPrivate::setVisible(visible) below
// updates the state correctly, but skips showing the non-native version:
- setAttribute(Qt::WA_DontShowOnScreen);
+ q->setAttribute(Qt::WA_DontShowOnScreen);
#if QT_CONFIG(fscompleter)
// So the completer doesn't try to complete and therefore show a popup
- if (!d->nativeDialogInUse)
- d->completer->setModel(nullptr);
+ if (!nativeDialogInUse)
+ completer->setModel(nullptr);
#endif
} else {
- d->createWidgets();
- setAttribute(Qt::WA_DontShowOnScreen, false);
+ createWidgets();
+ q->setAttribute(Qt::WA_DontShowOnScreen, false);
#if QT_CONFIG(fscompleter)
- if (!d->nativeDialogInUse) {
- if (d->proxyModel != nullptr)
- d->completer->setModel(d->proxyModel);
+ if (!nativeDialogInUse) {
+ if (proxyModel != nullptr)
+ completer->setModel(proxyModel);
else
- d->completer->setModel(d->model);
+ completer->setModel(model);
}
#endif
}
}
- if (visible && d->usingWidgets())
- d->qFileDialogUi->fileNameEdit->setFocus();
+ if (visible && usingWidgets())
+ qFileDialogUi->fileNameEdit->setFocus();
- QDialog::setVisible(visible);
+ QDialogPrivate::setVisible(visible);
}
/*!
diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h
index dc5e33d7e4..0067a90061 100644
--- a/src/widgets/dialogs/qfiledialog_p.h
+++ b/src/widgets/dialogs/qfiledialog_p.h
@@ -221,6 +221,7 @@ public:
// dialog. Returning false means that a non-native dialog must be
// used instead.
bool canBeNativeDialog() const override;
+ void setVisible(bool visible) override;
inline bool usingWidgets() const;
inline void setDirectory_sys(const QUrl &directory);
diff --git a/src/widgets/dialogs/qfontdialog.cpp b/src/widgets/dialogs/qfontdialog.cpp
index 45853e153f..855376292b 100644
--- a/src/widgets/dialogs/qfontdialog.cpp
+++ b/src/widgets/dialogs/qfontdialog.cpp
@@ -960,19 +960,32 @@ void QFontDialog::open(QObject *receiver, const char *member)
*/
void QFontDialog::setVisible(bool visible)
{
- if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) != visible)
+ // will call QFontDialogPrivate::setVisible
+ QDialog::setVisible(visible);
+}
+
+/*!
+ \internal
+
+ The implementation of QFontDialog::setVisible() has to live here so that the call
+ to hide() in ~QDialog calls this function; it wouldn't call the override of
+ QDialog::setVisible().
+*/
+void QFontDialogPrivate::setVisible(bool visible)
+{
+ Q_Q(QFontDialog);
+ if (q->testAttribute(Qt::WA_WState_ExplicitShowHide) && q->testAttribute(Qt::WA_WState_Hidden) != visible)
return;
- Q_D(QFontDialog);
- if (d->canBeNativeDialog())
- d->setNativeDialogVisible(visible);
- if (d->nativeDialogInUse) {
+ if (canBeNativeDialog())
+ setNativeDialogVisible(visible);
+ if (nativeDialogInUse) {
// Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
// updates the state correctly, but skips showing the non-native version:
- setAttribute(Qt::WA_DontShowOnScreen, true);
+ q->setAttribute(Qt::WA_DontShowOnScreen, true);
} else {
- setAttribute(Qt::WA_DontShowOnScreen, false);
+ q->setAttribute(Qt::WA_DontShowOnScreen, false);
}
- QDialog::setVisible(visible);
+ QDialogPrivate::setVisible(visible);
}
/*!
diff --git a/src/widgets/dialogs/qfontdialog_p.h b/src/widgets/dialogs/qfontdialog_p.h
index 4b3b45a9be..d46d1986e8 100644
--- a/src/widgets/dialogs/qfontdialog_p.h
+++ b/src/widgets/dialogs/qfontdialog_p.h
@@ -105,6 +105,7 @@ public:
QByteArray memberToDisconnectOnClose;
bool canBeNativeDialog() const override;
+ void setVisible(bool visible) override;
void _q_runNativeAppModalPanel();
private:
diff --git a/tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp b/tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp
index 377226d5ac..535972e52d 100644
--- a/tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp
+++ b/tests/auto/printsupport/dialogs/qabstractprintdialog/tst_qabstractprintdialog.cpp
@@ -146,9 +146,26 @@ void tst_QAbstractPrintDialog::hideNativeByDestruction()
QWidget window;
QWidget *child = new QWidget(&window);
QPointer<QPrintDialog> dialog = new QPrintDialog(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));
}
#endif
diff --git a/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp b/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp
index c7c9d3d359..aa7bddd81a 100644
--- a/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp
+++ b/tests/auto/widgets/dialogs/qcolordialog/tst_qcolordialog.cpp
@@ -29,6 +29,8 @@ private slots:
void QTBUG_43548_initialColor();
void hexColor_data();
void hexColor();
+
+ void hideNativeByDestruction();
};
class TestNativeDialog : public QColorDialog
@@ -179,5 +181,32 @@ void tst_QColorDialog::hexColor()
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/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
index 4424ecec62..23390dc04c 100644
--- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
@@ -128,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
@@ -141,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();
@@ -1437,7 +1439,7 @@ void tst_QFiledialog::widgetlessNativeDialog()
QSKIP("This platform always uses widgets to realize its QFileDialog, instead of the native file dialog.");
#ifdef Q_OS_ANDROID
// QTBUG-101194
- QSKIP("Android: This keeeps the window open. Figure out why.");
+ QSKIP("Android: This keeps the window open. Figure out why.");
#endif
QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, false);
QFileDialog fd;
@@ -1451,6 +1453,46 @@ void tst_QFiledialog::widgetlessNativeDialog()
QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, true);
}
+void tst_QFiledialog::hideNativeByDestruction()
+{
+ if (!QGuiApplicationPrivate::platformTheme()->usePlatformNativeDialog(QPlatformTheme::FileDialog))
+ QSKIP("This platform always uses widgets to realize its QFileDialog, instead of the native file dialog.");
+
+#ifdef Q_OS_ANDROID
+ // QTBUG-101194
+ QSKIP("Android: This keeps the native window open. Figure out why.");
+#endif
+
+ QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, false);
+ auto resetAttribute = qScopeGuard([]{
+ QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, true);
+ });
+
+ QWidget window;
+ QWidget *child = new QWidget(&window);
+ QPointer<QFileDialog> dialog = new QFileDialog(child);
+ // Make it application modal so that we don't end up with a sheet on macOS
+ dialog->setWindowModality(Qt::ApplicationModal);
+ window.show();
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+ dialog->open();
+
+ // We test that the dialog opens and closes by watching the activation of the
+ // transient parent window. If it doesn't deactivate, then we have to skip.
+ const auto windowActive = [&window]{ return window.isActiveWindow(); };
+ const auto windowInactive = [&window]{ return !window.isActiveWindow(); };
+ if (!QTest::qWaitFor(windowInactive, 2000))
+ QSKIP("Dialog didn't activate");
+
+ // This should destroy the dialog and close the native window
+ child->deleteLater();
+ QTRY_VERIFY(!dialog);
+ // If the native window is still open, then the transient parent can't become
+ // active
+ window.activateWindow();
+ QVERIFY(QTest::qWaitFor(windowActive, 2000));
+}
+
void tst_QFiledialog::selectedFilesWithoutWidgets()
{
// Test for a crash when widgets are not instantiated yet.
diff --git a/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp b/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp
index 0a77bc3808..fa808712ac 100644
--- a/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp
+++ b/tests/auto/widgets/dialogs/qfontdialog/tst_qfontdialog.cpp
@@ -45,6 +45,7 @@ private slots:
void qtbug_41513_stylesheetStyle();
#endif
+ void hideNativeByDestruction();
private:
void runSlotWithFailsafeTimer(const char *member);
@@ -238,5 +239,32 @@ void tst_QFontDialog::testNonStandardFontSize()
qWarning("Fail using a non-standard font size.");
}
+void tst_QFontDialog::hideNativeByDestruction()
+{
+ QWidget window;
+ QWidget *child = new QWidget(&window);
+ QPointer<QFontDialog> dialog = new QFontDialog(child);
+ // Make it application modal so that we don't end up with a sheet on macOS
+ dialog->setWindowModality(Qt::ApplicationModal);
+ window.show();
+ QVERIFY(QTest::qWaitForWindowActive(&window));
+ dialog->open();
+
+ // We test that the dialog opens and closes by watching the activation of the
+ // transient parent window. If it doesn't deactivate, then we have to skip.
+ const auto windowActive = [&window]{ return window.isActiveWindow(); };
+ const auto windowInactive = [&window]{ return !window.isActiveWindow(); };
+ if (!QTest::qWaitFor(windowInactive, 2000))
+ QSKIP("Dialog didn't activate");
+
+ // This should destroy the dialog and close the native window
+ child->deleteLater();
+ QTRY_VERIFY(!dialog);
+ // If the native window is still open, then the transient parent can't become
+ // active
+ window.activateWindow();
+ QVERIFY(QTest::qWaitFor(windowActive));
+}
+
QTEST_MAIN(tst_QFontDialog)
#include "tst_qfontdialog.moc"
diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
index 3679a9367d..8985243e36 100644
--- a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
+++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
@@ -60,6 +60,8 @@ private slots:
void overrideDone_data();
void overrideDone();
+ void hideNativeByDestruction();
+
void cleanup();
};
@@ -798,5 +800,32 @@ 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::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_QMessageBox)
#include "tst_qmessagebox.moc"