Teach QErrorMessage to use native dialog helper if available
And implement for macOS. The default modality of the QErrorMessage on macOS now depends on whether the dialog has a parent or not. The QErrorMessage must be hidden and re-shown again after each message, so that the native dialog has a chance to recreate itself. Change-Id: I474ed35d6271118834fac8e97f6f540a6fb89b8c Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
8a18466e38
commit
31973f3ff3
@ -776,6 +776,7 @@ public:
|
||||
QList<QMessageDialogOptions::CustomButton> customButtons;
|
||||
int nextCustomButtonId;
|
||||
QPixmap iconPixmap;
|
||||
bool enableSupressionCheckBox = false;
|
||||
};
|
||||
|
||||
QMessageDialogOptions::QMessageDialogOptions(QMessageDialogOptionsPrivate *dd)
|
||||
@ -906,6 +907,16 @@ const QMessageDialogOptions::CustomButton *QMessageDialogOptions::customButton(i
|
||||
return (i < 0 ? nullptr : &d->customButtons.at(i));
|
||||
}
|
||||
|
||||
void QMessageDialogOptions::setSupressionCheckBoxEnabled(bool enabled)
|
||||
{
|
||||
d->enableSupressionCheckBox = enabled;
|
||||
}
|
||||
|
||||
bool QMessageDialogOptions::supressionCheckBoxEnabled() const
|
||||
{
|
||||
return d->enableSupressionCheckBox;
|
||||
}
|
||||
|
||||
QPlatformDialogHelper::ButtonRole QPlatformDialogHelper::buttonRole(QPlatformDialogHelper::StandardButton button)
|
||||
{
|
||||
switch (button) {
|
||||
|
@ -451,6 +451,9 @@ public:
|
||||
const QList<CustomButton> &customButtons();
|
||||
const CustomButton *customButton(int id);
|
||||
|
||||
void setSupressionCheckBoxEnabled(bool enabled);
|
||||
bool supressionCheckBoxEnabled() const;
|
||||
|
||||
private:
|
||||
QMessageDialogOptionsPrivate *d;
|
||||
};
|
||||
@ -464,6 +467,7 @@ public:
|
||||
|
||||
Q_SIGNALS:
|
||||
void clicked(QPlatformDialogHelper::StandardButton button, QPlatformDialogHelper::ButtonRole role);
|
||||
void supressionCheckBoxChanged(bool checked);
|
||||
|
||||
private:
|
||||
QSharedPointer<QMessageDialogOptions> m_options;
|
||||
|
@ -54,6 +54,9 @@ bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags,
|
||||
if (!opt.data())
|
||||
return false;
|
||||
|
||||
if (opt->supressionCheckBoxEnabled())
|
||||
return false; // Can't support
|
||||
|
||||
m_javaMessageDialog.callMethod<void>("setIcon", "(I)V", opt->icon());
|
||||
|
||||
QString str = htmlText(opt->windowTitle());
|
||||
|
@ -180,6 +180,8 @@ bool QCocoaMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality w
|
||||
StandardButton::Ok, ButtonRole::AcceptRole);
|
||||
}
|
||||
|
||||
m_alert.showsSuppressionButton = options()->supressionCheckBoxEnabled();
|
||||
|
||||
qCDebug(lcQpaDialogs) << "Showing" << m_alert;
|
||||
|
||||
if (windowModality == Qt::WindowModal) {
|
||||
@ -230,6 +232,15 @@ void QCocoaMessageDialog::processResponse(NSModalResponse response)
|
||||
{
|
||||
qCDebug(lcQpaDialogs) << "Processing response" << response << "for" << m_alert;
|
||||
|
||||
// We can't re-use the same dialog for the next show() anyways,
|
||||
// since the options may have changed, so get rid of it now,
|
||||
// before we emit anything that might recurse back to hide/show/etc.
|
||||
auto alert = std::exchange(m_alert, nil);
|
||||
[alert autorelease];
|
||||
|
||||
if (alert.showsSuppressionButton)
|
||||
emit supressionCheckBoxChanged(alert.suppressionButton.state == NSControlStateValueOn);
|
||||
|
||||
if (response >= NSAlertFirstButtonReturn) {
|
||||
// Safe range for user-defined modal responses
|
||||
if (response == kModalResponseDialogHidden) {
|
||||
@ -270,11 +281,6 @@ void QCocoaMessageDialog::processResponse(NSModalResponse response)
|
||||
|
||||
if (m_eventLoop)
|
||||
m_eventLoop->exit(response);
|
||||
|
||||
// We can't re-use the same dialog for the next show() anyways,
|
||||
// since the options may have changed, so get rid of it now.
|
||||
[m_alert release];
|
||||
m_alert = nil;
|
||||
}
|
||||
|
||||
void QCocoaMessageDialog::hide()
|
||||
|
@ -92,6 +92,9 @@ bool QIOSMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality win
|
||||
|| windowModality == Qt::NonModal) // We can only do modal dialogs
|
||||
return false;
|
||||
|
||||
if (options()->supressionCheckBoxEnabled())
|
||||
return false; // Can't support
|
||||
|
||||
m_alertController = [[UIAlertController
|
||||
alertControllerWithTitle:options()->windowTitle().toNSString()
|
||||
message:messageTextPlain().toNSString()
|
||||
|
@ -52,8 +52,44 @@ public:
|
||||
bool isMessageToBeShown(const QString &message, const QString &type) const;
|
||||
bool nextPending();
|
||||
void retranslateStrings();
|
||||
|
||||
private:
|
||||
void initHelper(QPlatformDialogHelper *) override;
|
||||
void helperPrepareShow(QPlatformDialogHelper *) override;
|
||||
};
|
||||
|
||||
|
||||
void QErrorMessagePrivate::initHelper(QPlatformDialogHelper *helper)
|
||||
{
|
||||
Q_Q(QErrorMessage);
|
||||
auto *messageDialogHelper = static_cast<QPlatformMessageDialogHelper *>(helper);
|
||||
QObject::connect(messageDialogHelper, &QPlatformMessageDialogHelper::supressionCheckBoxChanged, q,
|
||||
[this](bool supressionChecked) {
|
||||
again->setChecked(!supressionChecked);
|
||||
}
|
||||
);
|
||||
QObject::connect(messageDialogHelper, &QPlatformMessageDialogHelper::clicked, q,
|
||||
[this](QPlatformDialogHelper::StandardButton, QPlatformDialogHelper::ButtonRole) {
|
||||
Q_Q(QErrorMessage);
|
||||
q->accept();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void QErrorMessagePrivate::helperPrepareShow(QPlatformDialogHelper *helper)
|
||||
{
|
||||
Q_Q(QErrorMessage);
|
||||
auto *messageDialogHelper = static_cast<QPlatformMessageDialogHelper *>(helper);
|
||||
QSharedPointer<QMessageDialogOptions> options = QMessageDialogOptions::create();
|
||||
options->setText(currentMessage);
|
||||
options->setWindowTitle(q->windowTitle());
|
||||
options->setText(QErrorMessage::tr("An error occurred"));
|
||||
options->setInformativeText(currentMessage);
|
||||
options->setIcon(QMessageDialogOptions::Critical);
|
||||
options->setSupressionCheckBoxEnabled(true);
|
||||
messageDialogHelper->setOptions(options);
|
||||
}
|
||||
|
||||
namespace {
|
||||
class QErrorMessageTextView : public QTextEdit
|
||||
{
|
||||
@ -190,6 +226,10 @@ static void jump(QtMsgType t, const QMessageLogContext &context, const QString &
|
||||
/*!
|
||||
Constructs and installs an error handler window with the given \a
|
||||
parent.
|
||||
|
||||
The default \l{Qt::WindowModality} {window modality} of the dialog
|
||||
depends on the platform. The window modality can be overridden via
|
||||
setWindowModality() before calling showMessage().
|
||||
*/
|
||||
|
||||
QErrorMessage::QErrorMessage(QWidget * parent)
|
||||
@ -197,6 +237,10 @@ QErrorMessage::QErrorMessage(QWidget * parent)
|
||||
{
|
||||
Q_D(QErrorMessage);
|
||||
|
||||
#if defined(Q_OS_MACOS)
|
||||
setWindowModality(parent ? Qt::WindowModal : Qt::ApplicationModal);
|
||||
#endif
|
||||
|
||||
d->icon = new QLabel(this);
|
||||
d->errors = new QErrorMessageTextView(this);
|
||||
d->again = new QCheckBox(this);
|
||||
@ -256,8 +300,12 @@ void QErrorMessage::done(int a)
|
||||
}
|
||||
d->currentMessage.clear();
|
||||
d->currentType.clear();
|
||||
if (!d->nextPending()) {
|
||||
QDialog::done(a);
|
||||
|
||||
QDialog::done(a);
|
||||
|
||||
if (d->nextPending()) {
|
||||
show();
|
||||
} else {
|
||||
if (this == qtMessageHandler && metFatal)
|
||||
exit(1);
|
||||
}
|
||||
@ -355,6 +403,23 @@ void QErrorMessage::showMessage(const QString &message, const QString &type)
|
||||
show();
|
||||
}
|
||||
|
||||
void QErrorMessage::setVisible(bool visible)
|
||||
{
|
||||
if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) != visible)
|
||||
return;
|
||||
|
||||
Q_D(QErrorMessage);
|
||||
if (d->canBeNativeDialog())
|
||||
d->setNativeDialogVisible(visible);
|
||||
|
||||
// Update WA_DontShowOnScreen based on whether the native dialog was shown,
|
||||
// so that QDialog::setVisible(visible) below updates the QWidget state correctly,
|
||||
// but skips showing the non-native version.
|
||||
setAttribute(Qt::WA_DontShowOnScreen, d->nativeDialogInUse);
|
||||
|
||||
QDialog::setVisible(visible);
|
||||
}
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
|
@ -28,6 +28,8 @@ public Q_SLOTS:
|
||||
void showMessage(const QString &message);
|
||||
void showMessage(const QString &message, const QString &type);
|
||||
|
||||
void setVisible(bool) override;
|
||||
|
||||
protected:
|
||||
void done(int) override;
|
||||
void changeEvent(QEvent *e) override;
|
||||
|
Loading…
Reference in New Issue
Block a user