diff options
-rw-r--r-- | src/widgets/dialogs/qfiledialog.cpp | 82 | ||||
-rw-r--r-- | src/widgets/dialogs/qfiledialog.h | 4 | ||||
-rw-r--r-- | src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp | 11 |
3 files changed, 97 insertions, 0 deletions
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index f42cf89708..3e756da505 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -73,6 +73,9 @@ #elif defined(Q_OS_WIN) # include <QtCore/qt_windows.h> #endif +#if defined(Q_OS_WASM) +#include <private/qwasmlocalfileaccess_p.h> +#endif QT_BEGIN_NAMESPACE @@ -2348,6 +2351,85 @@ QList<QUrl> QFileDialog::getOpenFileUrls(QWidget *parent, } /*! + This is a convenience static function that will return 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 may happen. Its implementation will + make the browser display a native file dialog, where the user makes the file selection. + + It can also be used on other platforms, where it will fall back to using QFileDialog. + + The function is asynchronous and returns immediately. The \a fileOpenCompleted + callback will be called when a file has been selected and its contents has been + read into memory. + + \snippet code/src_gui_dialogs_qfiledialog.cpp 14 + \since 5.13 +*/ +void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::function<void(const QString &, const QByteArray &)> &fileOpenCompleted) +{ +#ifdef Q_OS_WASM + auto openFileImpl = std::make_shared<std::function<void(void)>>(); + QString fileName; + QByteArray fileContent; + *openFileImpl = [=]() mutable { + auto fileDialogClosed = [&](bool fileSelected) { + if (!fileSelected) { + fileOpenCompleted(fileName, fileContent); + openFileImpl.reset(); + } + }; + auto acceptFile = [&](uint64_t size, const std::string name) -> char * { + const uint64_t twoGB = 1ULL << 31; // QByteArray limit + if (size > twoGB) + return nullptr; + + fileName = QString::fromStdString(name); + fileContent.resize(size); + return fileContent.data(); + }; + auto fileContentReady = [&]() mutable { + fileOpenCompleted(fileName, fileContent); + openFileImpl.reset(); + }; + + auto qtFilterStringToWebAcceptString = [](const QString &qtString) { + // The Qt and Web name filter string formats are similar, but + // not identical. + return qtString.toStdString(); // ### TODO + }; + + QWasmLocalFileAccess::openFile(qtFilterStringToWebAcceptString(nameFilter), fileDialogClosed, acceptFile, fileContentReady); + }; + + (*openFileImpl)(); +#else + QFileDialog *dialog = new QFileDialog(); + dialog->selectNameFilter(nameFilter); + + auto fileSelected = [=](const QString &fileName) { + QByteArray fileContent; + if (!fileName.isNull()) { + QFile selectedFile(fileName); + selectedFile.open(QIODevice::ReadOnly); + fileContent = selectedFile.readAll(); + } + fileOpenCompleted(fileName, fileContent); + }; + + auto dialogClosed = [=](int code) { + Q_UNUSED(code); + delete dialog; + }; + + connect(dialog, &QFileDialog::fileSelected, fileSelected); + connect(dialog, &QFileDialog::finished, dialogClosed); + dialog->show(); +#endif +} + +/*! This is a convenience static function that will return a file name selected by the user. The file does not have to exist. diff --git a/src/widgets/dialogs/qfiledialog.h b/src/widgets/dialogs/qfiledialog.h index 8a99112081..c75795fd77 100644 --- a/src/widgets/dialogs/qfiledialog.h +++ b/src/widgets/dialogs/qfiledialog.h @@ -46,6 +46,8 @@ #include <QtCore/qurl.h> #include <QtWidgets/qdialog.h> +#include <functional> + QT_REQUIRE_CONFIG(filedialog); QT_BEGIN_NAMESPACE @@ -273,6 +275,8 @@ public: Options options = Options(), const QStringList &supportedSchemes = QStringList()); + static void getOpenFileContent(const QString &nameFilter, + const std::function<void(const QString &, const QByteArray &)> &fileContentsReady); protected: QFileDialog(const QFileDialogArgs &args); diff --git a/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp b/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp index 06cca37111..1e9daf824b 100644 --- a/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp +++ b/src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp @@ -144,3 +144,14 @@ dialog.exec(); //! [14] "Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)" //! [14] + +//! [14] +auto fileOpenCompleted = [](const QSting &fileName, const QByteArray &fileContent) { + if (fileName.isEmpty()) { + // No file was selected + } else { + // Use fileName and fileContent + } +} +QFileDialog::getOpenFileContent("Images (*.png *.xpm *.jpg)", fileContentReady); +//! [14] |