summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp82
-rw-r--r--src/widgets/dialogs/qfiledialog.h4
-rw-r--r--src/widgets/doc/snippets/code/src_gui_dialogs_qfiledialog.cpp11
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]