From 253957b940cf63c035587026b25414261402413c Mon Sep 17 00:00:00 2001 From: Chris Von Bargen Date: Mon, 18 Dec 2023 10:28:34 -0500 Subject: [PATCH] Add parent arg to QFileDialog::getOpenFileContent and saveFileContent This change updates getOpenFileContent to provide a parent when the non-WASM fallback to a QFileDialog is created, which avoids issues where this call is made inside another application. Specifically, if a QDialog is created lacking a parent to the main window, it will prevent interaction with that dialog. This patch addresses that problem with window modality. This change also updates saveFileContent to provide a parent for the fallback mechanism, so that both static APIs that interact with WASM/non-WASM dialogs have comparable behavior. The new parent argument is updated in the documentation. Documentation is clarified in terms of usage outside Qt for WebAssembly. [ChangeLog][QtWidgets][QFileDialog] Adds an overload to the static methods getOpenFileContent and saveFileContent with a new parent argument which always no-ops in the WASM environment. Fixes: QTBUG-118396 Pick-to: 6.6 6.5 Change-Id: Ic59aee386631172d4a29b42fe11e5af318474a1d Reviewed-by: Venugopal Shivashankar (cherry picked from commit 7c5cf8cae054954975a3e262f7fe3cd9897d67f4) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/compat/removed_api.cpp | 21 +++++++++++++++++- src/widgets/dialogs/qfiledialog.cpp | 33 +++++++++++++++++------------ src/widgets/dialogs/qfiledialog.h | 14 +++++++++++- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/widgets/compat/removed_api.cpp b/src/widgets/compat/removed_api.cpp index 691cc2cc7f0..5fcbdba47b4 100644 --- a/src/widgets/compat/removed_api.cpp +++ b/src/widgets/compat/removed_api.cpp @@ -78,7 +78,26 @@ QAction *QMenuBar::addAction(const QString &text, const QObject *receiver, const } #endif +#endif // QT_WIDGETS_REMOVED_SINCE(6, 3) + +#if QT_WIDGETS_REMOVED_SINCE(6, 7) + + +#if QT_CONFIG(filedialog) +#include "qfiledialog.h" + +void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::function &fileOpenCompleted) +{ + QFileDialog::getOpenFileContent(nameFilter, fileOpenCompleted, nullptr); +} + +void QFileDialog::saveFileContent(const QByteArray &fileContent, const QString &fileNameHint) +{ + saveFileContent(fileContent, fileNameHint, nullptr); +} +#endif + // #include // // implement removed functions from qotherheader.h -#endif // QT_WIDGETS_REMOVED_SINCE(6, 3) +#endif // QT_WIDGETS_REMOVED_SINCE(6, 7) diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 6439952abd1..53c26b36194 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -2276,12 +2276,13 @@ QList QFileDialog::getOpenFileUrls(QWidget *parent, This is a convenience static function that returns the content of a file selected by the user. - This function is used to access local files on Qt for WebAssembly, where the web - sandbox places restrictions on how such access can happen. Its implementation will - make the browser display a native file dialog, where the user makes the file selection - based on the parameter \a nameFilter. + Use this function to access local files on Qt for WebAssembly, if the web sandbox + restricts file access. Its implementation enables displaying a native file dialog in + the browser, where the user selects a file based on the \a nameFilter parameter. - It can also be used on other platforms, where it falls back to using QFileDialog. + \a parent is ignored on Qt for WebAssembly. Pass \a parent on other platforms, to make + the popup a child of another widget. If the platform doesn't support native file + dialogs, the function falls back to QFileDialog. The function is asynchronous and returns immediately. The \a fileOpenCompleted callback will be called when a file has been selected and its contents have been @@ -2290,9 +2291,10 @@ QList QFileDialog::getOpenFileUrls(QWidget *parent, \snippet code/src_gui_dialogs_qfiledialog.cpp 15 \since 5.13 */ -void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::function &fileOpenCompleted) +void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::function &fileOpenCompleted, QWidget *parent) { #ifdef Q_OS_WASM + Q_UNUSED(parent); auto openFileImpl = std::make_shared>(); QString fileName; QByteArray fileContent; @@ -2322,9 +2324,10 @@ void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::funct (*openFileImpl)(); #else - QFileDialog *dialog = new QFileDialog(); + QFileDialog *dialog = new QFileDialog(parent); dialog->setFileMode(QFileDialog::ExistingFile); dialog->setNameFilter(nameFilter); + dialog->setAttribute(Qt::WA_DeleteOnClose); auto fileSelected = [=](const QString &fileName) { QByteArray fileContent; @@ -2337,7 +2340,6 @@ void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::funct }; connect(dialog, &QFileDialog::fileSelected, dialog, fileSelected); - dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->show(); #endif } @@ -2347,23 +2349,26 @@ void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::funct a file name and location chosen by the user. \a fileNameHint can be provided to suggest a file name to the user. - This function is used to save files to the local file system on Qt for WebAssembly, where - the web sandbox places restrictions on how such access can happen. Its implementation will - make the browser display a native file dialog, where the user makes the file selection. + Use this function to save content to local files on Qt for WebAssembly, if the web sandbox + restricts file access. Its implementation enables displaying a native file dialog in the + browser, where the user specifies an output file based on the \a fileNameHint argument. - It can also be used on other platforms, where it falls back to using QFileDialog. + \a parent is ignored on Qt for WebAssembly. Pass \a parent on other platforms, to make + the popup a child of another widget. If the platform doesn't support native file + dialogs, the function falls back to QFileDialog. The function is asynchronous and returns immediately. \snippet code/src_gui_dialogs_qfiledialog.cpp 16 \since 5.14 */ -void QFileDialog::saveFileContent(const QByteArray &fileContent, const QString &fileNameHint) +void QFileDialog::saveFileContent(const QByteArray &fileContent, const QString &fileNameHint, QWidget *parent) { #ifdef Q_OS_WASM + Q_UNUSED(parent); QWasmLocalFileAccess::saveFile(fileContent, fileNameHint.toStdString()); #else - QFileDialog *dialog = new QFileDialog(); + QFileDialog *dialog = new QFileDialog(parent); dialog->setAcceptMode(QFileDialog::AcceptSave); dialog->setFileMode(QFileDialog::AnyFile); dialog->selectFile(fileNameHint); diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h index 970bddb3595..7cc798e7a7d 100644 --- a/src/widgets/dialogs/qfiledialog.h +++ b/src/widgets/dialogs/qfiledialog.h @@ -212,9 +212,21 @@ public: Options options = Options(), const QStringList &supportedSchemes = QStringList()); + static void getOpenFileContent(const QString &nameFilter, + const std::function &fileContentsReady, + QWidget *parent); + + static void saveFileContent(const QByteArray &fileContent, + const QString &fileNameHint, + QWidget *parent = nullptr); + +#if QT_WIDGETS_REMOVED_SINCE(6, 7) static void getOpenFileContent(const QString &nameFilter, const std::function &fileContentsReady); - static void saveFileContent(const QByteArray &fileContent, const QString &fileNameHint = QString()); + static void saveFileContent(const QByteArray &fileContent, + const QString &fileNameHint = QString()); +#endif + protected: QFileDialog(const QFileDialogArgs &args);