diff options
-rw-r--r-- | src/gui/kernel/qplatformdialoghelper.cpp | 24 | ||||
-rw-r--r-- | src/gui/kernel/qplatformdialoghelper.h | 10 | ||||
-rw-r--r-- | src/widgets/dialogs/qmessagebox.cpp | 98 | ||||
-rw-r--r-- | src/widgets/dialogs/qmessagebox.h | 16 | ||||
-rw-r--r-- | tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp | 17 |
5 files changed, 163 insertions, 2 deletions
diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp index 7038954ea0..c14c0f0142 100644 --- a/src/gui/kernel/qplatformdialoghelper.cpp +++ b/src/gui/kernel/qplatformdialoghelper.cpp @@ -778,6 +778,7 @@ public: QPixmap iconPixmap; QString checkBoxLabel; Qt::CheckState checkBoxState = Qt::Unchecked; + QMessageDialogOptions::Options options; }; QMessageDialogOptions::QMessageDialogOptions(QMessageDialogOptionsPrivate *dd) @@ -924,6 +925,29 @@ Qt::CheckState QMessageDialogOptions::checkBoxState() const return d->checkBoxState; } +void QMessageDialogOptions::setOption(QMessageDialogOptions::Option option, bool on) +{ + if (!(d->options & option) != !on) + setOptions(d->options ^ option); +} + +bool QMessageDialogOptions::testOption(QMessageDialogOptions::Option option) const +{ + return d->options & option; +} + +void QMessageDialogOptions::setOptions(QMessageDialogOptions::Options options) +{ + if (options != d->options) + d->options = options; +} + +QMessageDialogOptions::Options QMessageDialogOptions::options() const +{ + return d->options; +} + + QPlatformDialogHelper::ButtonRole QPlatformDialogHelper::buttonRole(QPlatformDialogHelper::StandardButton button) { switch (button) { diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h index 25543a70b8..fabc4985a3 100644 --- a/src/gui/kernel/qplatformdialoghelper.h +++ b/src/gui/kernel/qplatformdialoghelper.h @@ -403,6 +403,11 @@ protected: ~QMessageDialogOptions(); public: + // Keep in sync with QMessageBox Option + enum class Option : quint8 { DontUseNativeDialog = 0x00000001 }; + Q_DECLARE_FLAGS(Options, Option); + Q_FLAG(Options); + // Keep in sync with QMessageBox::Icon enum StandardIcon { NoIcon, Information, Warning, Critical, Question }; Q_ENUM(StandardIcon) @@ -428,6 +433,11 @@ public: void setDetailedText(const QString &text); QString detailedText() const; + void setOption(Option option, bool on = true); + bool testOption(Option option) const; + void setOptions(Options options); + Options options() const; + void setStandardButtons(QPlatformDialogHelper::StandardButtons buttons); QPlatformDialogHelper::StandardButtons standardButtons() const; diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index cb985ff145..58e846b16b 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -189,6 +189,7 @@ public: void retranslateStrings(); void setVisible(bool visible) override; + bool canBeNativeDialog() const override; static int showOldMessageBox(QWidget *parent, QMessageBox::Icon icon, const QString &title, const QString &text, @@ -770,6 +771,12 @@ void QMessageBoxPrivate::_q_clicked(QPlatformDialogHelper::StandardButton button */ /*! + \enum QMessageBox::Option + \since 6.6 + \value DontUseNativeDialog Don't use the native message dialog. +*/ + +/*! \fn void QMessageBox::buttonClicked(QAbstractButton *button) This signal is emitted whenever a button is clicked inside the QMessageBox. @@ -1225,6 +1232,78 @@ QCheckBox* QMessageBox::checkBox() const } /*! + \since 6.6 + Sets the given \a option to be enabled if \a on is true; otherwise, + clears the given \a option. + + Options (particularly the DontUseNativeDialogs option) should be set + before showing the dialog. + + Setting options while the dialog is visible is not guaranteed to have + an immediate effect on the dialog. + + Setting options after changing other properties may cause these + values to have no effect. + + \sa options, testOption() +*/ +void QMessageBox::setOption(QMessageBox::Option option, bool on) +{ + const QMessageBox::Options previousOptions = options(); + if (!(previousOptions & option) != !on) + setOptions(previousOptions ^ option); +} + +/*! + \since 6.6 + + Returns \c true if the given \a option is enabled; otherwise, returns + false. + + \sa options, setOption() +*/ +bool QMessageBox::testOption(QMessageBox::Option option) const +{ + Q_D(const QMessageBox); + return d->options->testOption(static_cast<QMessageDialogOptions::Option>(option)); +} + +void QMessageBox::setOptions(QMessageBox::Options options) +{ + Q_D(QMessageBox); + + if (QMessageBox::options() == options) + return; + + d->options->setOptions(QMessageDialogOptions::Option(int(options))); +} + +QMessageBox::Options QMessageBox::options() const +{ + Q_D(const QMessageBox); + return QMessageBox::Options(int(d->options->options())); +} + +/*! + \property QMessageBox::options + \brief options that affect the look and feel of the dialog + \since 6.6. + + By default, these options are disabled. + + The option DontUseNativeDialog should be set + before changing dialog properties or showing the dialog. + + Setting options while the dialog is visible is not guaranteed to have + an immediate effect on the dialog. + + Setting options after changing other properties may cause these + values to have no effect. + + \sa setOption(), testOption() +*/ + +/*! \property QMessageBox::text \brief the message box text to be displayed. @@ -2717,6 +2796,25 @@ static QPlatformDialogHelper::StandardButtons helperStandardButtons(QMessageBox return buttons; } +bool QMessageBoxPrivate::canBeNativeDialog() const +{ + // Don't use Q_Q here! This function is called from ~QDialog, + // so Q_Q calling q_func() invokes undefined behavior (invalid cast in q_func()). + const QDialog * const q = static_cast<const QMessageBox*>(q_ptr); + if (nativeDialogInUse) + return true; + if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs) + || q->testAttribute(Qt::WA_DontShowOnScreen) + || (options->options() & QMessageDialogOptions::Option::DontUseNativeDialog)) { + return false; + } + + if (strcmp(QMessageBox::staticMetaObject.className(), q->metaObject()->className()) != 0) + return false; + + return QDialogPrivate::canBeNativeDialog(); +} + void QMessageBoxPrivate::helperPrepareShow(QPlatformDialogHelper *) { Q_Q(QMessageBox); diff --git a/src/widgets/dialogs/qmessagebox.h b/src/widgets/dialogs/qmessagebox.h index cf8821bbd0..72f0840e80 100644 --- a/src/widgets/dialogs/qmessagebox.h +++ b/src/widgets/dialogs/qmessagebox.h @@ -31,8 +31,14 @@ class Q_WIDGETS_EXPORT QMessageBox : public QDialog Q_PROPERTY(QString informativeText READ informativeText WRITE setInformativeText) Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags) - + Q_PROPERTY(Options options READ options WRITE setOptions) public: + // Keep in sync with MessageBoxOption in qplatformdialoghelper.h + enum class Option : quint8 { + DontUseNativeDialog = 0x00000001 + }; + Q_FLAG(Option) + enum Icon { // keep this in sync with QMessageDialogOptions::StandardIcon NoIcon = 0, @@ -95,8 +101,9 @@ public: #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) typedef StandardButton Button; #endif - + Q_DECLARE_FLAGS(Options, Option) Q_DECLARE_FLAGS(StandardButtons, StandardButton) + Q_FLAG(StandardButtons) explicit QMessageBox(QWidget *parent = nullptr); @@ -149,6 +156,11 @@ public: void setCheckBox(QCheckBox *cb); QCheckBox* checkBox() const; + void setOption(Option option, bool on = true); + bool testOption(Option option) const; + void setOptions(Options options); + Options options() const; + static StandardButton information(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton); diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp index 122170e91d..afdf18fedc 100644 --- a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp +++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp @@ -38,6 +38,9 @@ private slots: void detailsButtonText(); void expandDetailsWithoutMoving(); + void optionsEmptyByDefault(); + void changeNativeOption(); + #ifndef Q_OS_MAC void shortcut(); #endif @@ -584,6 +587,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; |