summaryrefslogtreecommitdiffstats
path: root/examples/widgets
diff options
context:
space:
mode:
authorMikolaj Boc <mikolaj.boc@qt.io>2022-09-08 15:26:00 +0200
committerMikolaj Boc <mikolaj.boc@qt.io>2023-06-20 07:28:42 +0100
commit7022d0e22364b7c075a20670d023fc590a0a7ac4 (patch)
tree5a1912281fc4f78e6bc77c5ff938bd7ed9a0f6f3 /examples/widgets
parenta6059cebe85c4ba8dd43df8aae146799c8bb6cb0 (diff)
Replace QDialog::exec() with open() in text edit example
On WASM, the shortcut triggering the dialog in textedit example seemingly lets the event invoke the default action. What really happens is that the dialog's exec() does not return and WASM does not have a chance to set preventDefault() on the keyboard event it receives. This masks other problems with keyboards shortcuts. Uses of exec() on message boxes were replaced, too. Closing operation is now performed in two steps, first the event is ignored and maybeSave is called to query for potential changes of the text document. If there are no changes or the file is discarded, the close continues with a second event, now accepted. PrintDialog::exec(), QPrintPreviewDialog::exec(), QFileDialog::exec() were also eliminated in favor of open(). Finally, indirect calls to exec() via QColorDialog::getColor were removed. Task-number: QTBUG-76587 Change-Id: Ia90fad46ec3f94244723512be3ec93b64df9d9ef Reviewed-by: MikoĊ‚aj Boc <Mikolaj.Boc@qt.io>
Diffstat (limited to 'examples/widgets')
-rw-r--r--examples/widgets/richtext/textedit/textedit.cpp227
-rw-r--r--examples/widgets/richtext/textedit/textedit.h13
2 files changed, 149 insertions, 91 deletions
diff --git a/examples/widgets/richtext/textedit/textedit.cpp b/examples/widgets/richtext/textedit/textedit.cpp
index 51a8f54bd5..5f9e8d87b7 100644
--- a/examples/widgets/richtext/textedit/textedit.cpp
+++ b/examples/widgets/richtext/textedit/textedit.cpp
@@ -21,6 +21,7 @@
#include <QTextCursor>
#include <QTextDocumentWriter>
#include <QTextList>
+#include <QTimer>
#include <QtDebug>
#include <QCloseEvent>
#include <QMessageBox>
@@ -119,10 +120,13 @@ TextEdit::TextEdit(QWidget *parent)
//! [closeevent]
void TextEdit::closeEvent(QCloseEvent *e)
{
- if (maybeSave())
+ if (closeAccepted) {
e->accept();
- else
- e->ignore();
+ return;
+ }
+
+ e->ignore();
+ maybeSave(SaveContinuation::Close);
}
//! [closeevent]
@@ -145,12 +149,13 @@ void TextEdit::setupFileActions()
menu->addSeparator();
const QIcon saveIcon = QIcon::fromTheme("document-save", QIcon(rsrcPath + "/filesave.png"));
- actionSave = menu->addAction(saveIcon, tr("&Save"), this, &TextEdit::fileSave);
+ actionSave = menu->addAction(saveIcon, tr("&Save"), this,
+ [this]() { fileSave(SaveContinuation::None); });
actionSave->setShortcut(QKeySequence::Save);
actionSave->setEnabled(false);
tb->addAction(actionSave);
- a = menu->addAction(tr("Save &As..."), this, &TextEdit::fileSaveAs);
+ a = menu->addAction(tr("Save &As..."), this, [this]() { fileSaveAs(SaveContinuation::None); });
a->setPriority(QAction::LowPriority);
menu->addSeparator();
@@ -398,21 +403,31 @@ bool TextEdit::load(const QString &f)
return true;
}
-bool TextEdit::maybeSave()
+void TextEdit::maybeSave(SaveContinuation continuation)
{
- if (!textEdit->document()->isModified())
- return true;
+ if (!textEdit->document()->isModified()) {
+ // Execute continuation as soon as control has returned to the event loop so that existing
+ // dialogs do not get in the way of closing the window.
+ QTimer::singleShot(0, [this, continuation]() { fileSaveComplete(continuation); });
+ return;
+ }
- const QMessageBox::StandardButton ret =
- QMessageBox::warning(this, QCoreApplication::applicationName(),
- tr("The document has been modified.\n"
- "Do you want to save your changes?"),
- QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
- if (ret == QMessageBox::Save)
- return fileSave();
- if (ret == QMessageBox::Cancel)
- return false;
- return true;
+ QMessageBox *msgBox =
+ new QMessageBox(QMessageBox::Icon::Warning, QCoreApplication::applicationName(),
+ tr("The document has been modified.\n"
+ "Do you want to save your changes?"),
+ QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, this);
+
+ connect(msgBox, &QMessageBox::finished, [=](int result) {
+ if (result == QMessageBox::Save) {
+ fileSave(continuation);
+ return;
+ }
+ fileSaveComplete(result == QMessageBox::Discard ? continuation : SaveContinuation::None);
+ });
+
+ msgBox->setAttribute(Qt::WA_DeleteOnClose);
+ msgBox->open();
}
void TextEdit::setCurrentFileName(const QString &fileName)
@@ -432,18 +447,15 @@ void TextEdit::setCurrentFileName(const QString &fileName)
void TextEdit::fileNew()
{
- if (maybeSave()) {
- textEdit->clear();
- setCurrentFileName({});
- }
+ maybeSave(SaveContinuation::Clear);
}
void TextEdit::fileOpen()
{
- QFileDialog fileDialog(this, tr("Open File..."));
- fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
- fileDialog.setFileMode(QFileDialog::ExistingFile);
- fileDialog.setMimeTypeFilters({
+ QFileDialog *fileDialog = new QFileDialog(this, tr("Open File..."));
+ fileDialog->setAcceptMode(QFileDialog::AcceptOpen);
+ fileDialog->setFileMode(QFileDialog::ExistingFile);
+ fileDialog->setMimeTypeFilters({
#if QT_CONFIG(texthtmlparser)
"text/html",
#endif
@@ -452,19 +464,20 @@ void TextEdit::fileOpen()
"text/markdown",
#endif
"text/plain"});
- if (fileDialog.exec() != QDialog::Accepted)
- return;
- const QString fn = fileDialog.selectedFiles().constFirst();
- if (load(fn))
- statusBar()->showMessage(tr("Opened \"%1\"").arg(QDir::toNativeSeparators(fn)));
- else
- statusBar()->showMessage(tr("Could not open \"%1\"").arg(QDir::toNativeSeparators(fn)));
+
+ connect(fileDialog, &QFileDialog::fileSelected, [=](const QString &file) {
+ statusBar()->showMessage(
+ load(file) ? tr(R"(Opened "%1")").arg(QDir::toNativeSeparators(file))
+ : tr(R"(Could not open "%1")").arg(QDir::toNativeSeparators(file)));
+ });
+ fileDialog->setAttribute(Qt::WA_DeleteOnClose);
+ fileDialog->open();
}
-bool TextEdit::fileSave()
+void TextEdit::fileSave(SaveContinuation continuation)
{
if (fileName.isEmpty() || fileName.startsWith(u":/"))
- return fileSaveAs();
+ return fileSaveAs(continuation);
QTextDocumentWriter writer(fileName);
bool success = writer.write(textEdit->document());
@@ -475,13 +488,13 @@ bool TextEdit::fileSave()
statusBar()->showMessage(tr("Could not write to file \"%1\"")
.arg(QDir::toNativeSeparators(fileName)));
}
- return success;
+ fileSaveComplete(success ? continuation : SaveContinuation::None);
}
-bool TextEdit::fileSaveAs()
+void TextEdit::fileSaveAs(SaveContinuation continuation)
{
- QFileDialog fileDialog(this, tr("Save as..."));
- fileDialog.setAcceptMode(QFileDialog::AcceptSave);
+ QFileDialog *fileDialog = new QFileDialog(this, tr("Save as..."));
+ fileDialog->setAcceptMode(QFileDialog::AcceptSave);
QStringList mimeTypes{"text/plain",
#if QT_CONFIG(textodfwriter)
"application/vnd.oasis.opendocument.text",
@@ -490,58 +503,82 @@ bool TextEdit::fileSaveAs()
"text/markdown",
#endif
"text/html"};
- fileDialog.setMimeTypeFilters(mimeTypes);
+ fileDialog->setMimeTypeFilters(mimeTypes);
#if QT_CONFIG(textodfwriter)
- fileDialog.setDefaultSuffix("odt");
+ fileDialog->setDefaultSuffix("odt");
#endif
- if (fileDialog.exec() != QDialog::Accepted)
- return false;
- const QString fn = fileDialog.selectedFiles().constFirst();
- setCurrentFileName(fn);
- return fileSave();
+ connect(fileDialog, &QFileDialog::finished, [this, continuation, fileDialog](int result) {
+ if (result != QDialog::Accepted)
+ return;
+ setCurrentFileName(fileDialog->selectedFiles().constFirst());
+ fileSave(continuation);
+ });
+ fileDialog->setAttribute(Qt::WA_DeleteOnClose);
+ fileDialog->open();
+}
+
+void TextEdit::fileSaveComplete(SaveContinuation continuation)
+{
+ switch (continuation) {
+ case SaveContinuation::Clear:
+ textEdit->clear();
+ setCurrentFileName({});
+ return;
+ case SaveContinuation::Close:
+ closeAccepted = true;
+ close();
+ return;
+ case SaveContinuation::None:
+ // NOOP as promised
+ return;
+ }
}
void TextEdit::filePrint()
{
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog)
- QPrinter printer(QPrinter::HighResolution);
- QPrintDialog dlg(&printer, this);
+ auto printer = std::make_shared<QPrinter>(QPrinter::HighResolution);
+ QPrintDialog *dlg = new QPrintDialog(printer.get(), this);
if (textEdit->textCursor().hasSelection())
- dlg.setOption(QAbstractPrintDialog::PrintSelection);
- dlg.setWindowTitle(tr("Print Document"));
- if (dlg.exec() == QDialog::Accepted)
- textEdit->print(&printer);
+ dlg->setOption(QAbstractPrintDialog::PrintSelection);
+ dlg->setWindowTitle(tr("Print Document"));
+ dlg->setAttribute(Qt::WA_DeleteOnClose);
+ connect(dlg, qOverload<QPrinter *>(&QPrintDialog::accepted),
+ [this](QPrinter *printer) { textEdit->print(printer); });
+ connect(dlg, &QPrintDialog::finished, [printer]() mutable { printer.reset(); });
+ dlg->open();
#endif
}
void TextEdit::filePrintPreview()
{
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printpreviewdialog)
- QPrinter printer(QPrinter::HighResolution);
- QPrintPreviewDialog preview(&printer, this);
- connect(&preview, &QPrintPreviewDialog::paintRequested, textEdit, &QTextEdit::print);
- preview.exec();
+ auto printer = std::make_shared<QPrinter>(QPrinter::HighResolution);
+ QPrintPreviewDialog *preview = new QPrintPreviewDialog(printer.get(), this);
+ preview->setAttribute(Qt::WA_DeleteOnClose);
+ connect(preview, &QPrintPreviewDialog::paintRequested, textEdit, &QTextEdit::print);
+ connect(preview, &QPrintPreviewDialog::finished, [printer]() mutable { printer.reset(); });
+ preview->open();
#endif
}
void TextEdit::filePrintPdf()
{
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
-//! [0]
- QFileDialog fileDialog(this, tr("Export PDF"));
- fileDialog.setAcceptMode(QFileDialog::AcceptSave);
- fileDialog.setMimeTypeFilters(QStringList("application/pdf"));
- fileDialog.setDefaultSuffix("pdf");
- if (fileDialog.exec() != QDialog::Accepted)
- return;
- QString pdfFileName = fileDialog.selectedFiles().constFirst();
- QPrinter printer(QPrinter::HighResolution);
- printer.setOutputFormat(QPrinter::PdfFormat);
- printer.setOutputFileName(pdfFileName);
- textEdit->document()->print(&printer);
- statusBar()->showMessage(tr("Exported \"%1\"")
- .arg(QDir::toNativeSeparators(pdfFileName)));
-//! [0]
+ QFileDialog *fileDialog = new QFileDialog(this, tr("Export PDF"));
+ fileDialog->setAcceptMode(QFileDialog::AcceptSave);
+ fileDialog->setMimeTypeFilters(QStringList("application/pdf"));
+ fileDialog->setDefaultSuffix("pdf");
+ fileDialog->setAttribute(Qt::WA_DeleteOnClose);
+ connect(fileDialog, &QFileDialog::fileSelected, [this](const QString &file) {
+ QPrinter printer(QPrinter::HighResolution);
+ printer.setOutputFormat(QPrinter::PdfFormat);
+ printer.setOutputFileName(file);
+ textEdit->document()->print(&printer);
+ statusBar()->showMessage(tr("Exported \"%1\"").arg(QDir::toNativeSeparators(file)));
+ });
+
+ fileDialog->open();
#endif
}
@@ -669,24 +706,34 @@ void TextEdit::textStyle(int styleIndex)
void TextEdit::textColor()
{
- QColor col = QColorDialog::getColor(textEdit->textColor(), this);
- if (!col.isValid())
- return;
- QTextCharFormat fmt;
- fmt.setForeground(col);
- mergeFormatOnWordOrSelection(fmt);
- colorChanged(col);
+ QColorDialog *dlg = new QColorDialog(this);
+ dlg->setCurrentColor(textEdit->textColor());
+ connect(dlg, &QColorDialog::colorSelected, [this](const QColor &color) {
+ if (!color.isValid())
+ return;
+ QTextCharFormat fmt;
+ fmt.setForeground(color);
+ mergeFormatOnWordOrSelection(fmt);
+ colorChanged(color);
+ });
+ dlg->setAttribute(Qt::WA_DeleteOnClose);
+ dlg->open();
}
void TextEdit::underlineColor()
{
- QColor col = QColorDialog::getColor(Qt::black, this);
- if (!col.isValid())
- return;
- QTextCharFormat fmt;
- fmt.setUnderlineColor(col);
- mergeFormatOnWordOrSelection(fmt);
- colorChanged(col);
+ QColorDialog *dlg = new QColorDialog(this);
+ dlg->setCurrentColor(textEdit->textColor());
+ connect(dlg, &QColorDialog::colorSelected, [this](const QColor &color) {
+ if (!color.isValid())
+ return;
+ QTextCharFormat fmt;
+ fmt.setUnderlineColor(color);
+ mergeFormatOnWordOrSelection(fmt);
+ colorChanged(color);
+ });
+ dlg->setAttribute(Qt::WA_DeleteOnClose);
+ dlg->open();
}
void TextEdit::textAlign(QAction *a)
@@ -809,9 +856,13 @@ void TextEdit::clipboardDataChanged()
void TextEdit::about()
{
- QMessageBox::about(this, tr("About"), tr("This example demonstrates Qt's "
- "rich text editing facilities in action, providing an example "
- "document for you to experiment with."));
+ QMessageBox *msgBox =
+ new QMessageBox(QMessageBox::Icon::Information, tr("About"),
+ tr("This example demonstrates Qt's rich text editing facilities in "
+ "action, providing an example document for you to experiment with."),
+ QMessageBox::NoButton, this);
+ msgBox->setAttribute(Qt::WA_DeleteOnClose);
+ msgBox->open();
}
void TextEdit::mergeFormatOnWordOrSelection(const QTextCharFormat &format)
diff --git a/examples/widgets/richtext/textedit/textedit.h b/examples/widgets/richtext/textedit/textedit.h
index 2184863edc..f0f4abb827 100644
--- a/examples/widgets/richtext/textedit/textedit.h
+++ b/examples/widgets/richtext/textedit/textedit.h
@@ -31,10 +31,11 @@ public slots:
protected:
void closeEvent(QCloseEvent *e) override;
+private:
+ enum class SaveContinuation { None, Close, Clear };
+
private slots:
void fileOpen();
- bool fileSave();
- bool fileSaveAs();
void filePrint();
void filePrintPreview();
void filePrintPdf();
@@ -62,7 +63,7 @@ private:
void setupFileActions();
void setupEditActions();
void setupTextActions();
- bool maybeSave();
+ void maybeSave(SaveContinuation saveContinuation);
void setCurrentFileName(const QString &fileName);
void modifyIndentation(int amount);
@@ -71,6 +72,10 @@ private:
void colorChanged(const QColor &c);
void alignmentChanged(Qt::Alignment a);
+ void fileSave(SaveContinuation continuation);
+ void fileSaveAs(SaveContinuation continuation);
+ void fileSaveComplete(SaveContinuation continuation);
+
QAction *actionSave;
QAction *actionTextBold;
QAction *actionTextUnderline;
@@ -98,6 +103,8 @@ private:
QString fileName;
QTextEdit *textEdit;
+
+ bool closeAccepted = false;
};
#endif // TEXTEDIT_H