Close QDialog via QWidget::close()
By going via QWidget::close() we ensure that if there's a QWidgetWindow backing the dialog (which is almost always the case), we will plumb down to QWindow::close(), resulting in QEvent::Close events to the QWindow. Since we don't want QDialog subclasses to receive a call to a closeEvent override that they didn't receive before (and which they might interpret as rejection or cancellation), install a temporary event filter that eats the QCloseEvent resulting from the call to close(). Task-number: QTBUG-53286 Change-Id: Ie8f6f0cb3160acfd5865dc74f0a7b6d87f838724 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
8aa1fc6f12
commit
0246bfd40a
@ -146,16 +146,33 @@ bool QDialogPrivate::canBeNativeDialog() const
|
|||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
|
|
||||||
Properly hides dialog and sets the \a resultCode.
|
Properly closes dialog and sets the \a resultCode.
|
||||||
*/
|
*/
|
||||||
void QDialogPrivate::hide(int resultCode)
|
void QDialogPrivate::close(int resultCode)
|
||||||
{
|
{
|
||||||
Q_Q(QDialog);
|
Q_Q(QDialog);
|
||||||
|
|
||||||
q->setResult(resultCode);
|
q->setResult(resultCode);
|
||||||
q->hide();
|
q->hide();
|
||||||
|
if (!data.is_closing) {
|
||||||
|
// Until Qt 6.3 we didn't close dialogs, so they didn't receive a QCloseEvent.
|
||||||
|
// It is likely that subclasses implement closeEvent and handle them as rejection
|
||||||
|
// (like QMessageBox and QProgressDialog do), so eat those events.
|
||||||
|
struct CloseEventEater : QObject
|
||||||
|
{
|
||||||
|
using QObject::QObject;
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *o, QEvent *e) override
|
||||||
|
{
|
||||||
|
if (e->type() == QEvent::Close)
|
||||||
|
return true;
|
||||||
|
return QObject::eventFilter(o, e);
|
||||||
|
}
|
||||||
|
} closeEventEater;
|
||||||
|
q->installEventFilter(&closeEventEater);
|
||||||
|
QWidgetPrivate::close();
|
||||||
|
}
|
||||||
|
|
||||||
handleClose(QWidgetPrivate::CloseNoEvent);
|
|
||||||
resetModalitySetByOpen();
|
resetModalitySetByOpen();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -632,7 +649,7 @@ int QDialog::exec()
|
|||||||
void QDialog::done(int r)
|
void QDialog::done(int r)
|
||||||
{
|
{
|
||||||
Q_D(QDialog);
|
Q_D(QDialog);
|
||||||
d->hide(r);
|
d->close(r);
|
||||||
d->finalize(r, r);
|
d->finalize(r, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ public:
|
|||||||
QPlatformDialogHelper *platformHelper() const;
|
QPlatformDialogHelper *platformHelper() const;
|
||||||
virtual bool canBeNativeDialog() const;
|
virtual bool canBeNativeDialog() const;
|
||||||
|
|
||||||
void hide(int resultCode);
|
void close(int resultCode);
|
||||||
void finalize(int resultCode, int dialogCode);
|
void finalize(int resultCode, int dialogCode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -518,7 +518,7 @@ void QMessageBoxPrivate::setClickedButton(QAbstractButton *button)
|
|||||||
emit q->buttonClicked(clickedButton);
|
emit q->buttonClicked(clickedButton);
|
||||||
|
|
||||||
auto resultCode = execReturnCode(button);
|
auto resultCode = execReturnCode(button);
|
||||||
hide(resultCode);
|
close(resultCode);
|
||||||
finalize(resultCode, dialogCodeForButton(button));
|
finalize(resultCode, dialogCodeForButton(button));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1420,8 +1420,10 @@ void QMessageBox::closeEvent(QCloseEvent *e)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QDialog::closeEvent(e);
|
QDialog::closeEvent(e);
|
||||||
d->clickedButton = d->detectedEscapeButton;
|
if (!d->clickedButton) {
|
||||||
setResult(d->execReturnCode(d->detectedEscapeButton));
|
d->clickedButton = d->detectedEscapeButton;
|
||||||
|
setResult(d->execReturnCode(d->detectedEscapeButton));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -615,7 +615,9 @@ void tst_QDialog::virtualsOnClose()
|
|||||||
dialog.show();
|
dialog.show();
|
||||||
QVERIFY(QTest::qWaitForWindowExposed(&dialog));
|
QVERIFY(QTest::qWaitForWindowExposed(&dialog));
|
||||||
dialog.accept();
|
dialog.accept();
|
||||||
QCOMPARE(dialog.closeEventCount, 0); // we only hide the dialog
|
// 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.acceptCount, 1);
|
||||||
QCOMPARE(dialog.rejectCount, 0);
|
QCOMPARE(dialog.rejectCount, 0);
|
||||||
QCOMPARE(dialog.doneCount, 1);
|
QCOMPARE(dialog.doneCount, 1);
|
||||||
@ -626,7 +628,7 @@ void tst_QDialog::virtualsOnClose()
|
|||||||
dialog.show();
|
dialog.show();
|
||||||
QVERIFY(QTest::qWaitForWindowExposed(&dialog));
|
QVERIFY(QTest::qWaitForWindowExposed(&dialog));
|
||||||
dialog.reject();
|
dialog.reject();
|
||||||
QCOMPARE(dialog.closeEventCount, 0); // we only hide the dialog
|
QCOMPARE(dialog.closeEventCount, 0);
|
||||||
QCOMPARE(dialog.acceptCount, 0);
|
QCOMPARE(dialog.acceptCount, 0);
|
||||||
QCOMPARE(dialog.rejectCount, 1);
|
QCOMPARE(dialog.rejectCount, 1);
|
||||||
QCOMPARE(dialog.doneCount, 1);
|
QCOMPARE(dialog.doneCount, 1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user