summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorten Sørvig <morten.sorvig@qt.io>2022-10-07 16:56:37 +0200
committerMikołaj Boc <Mikolaj.Boc@qt.io>2022-10-28 12:57:43 +0000
commit315a5e3257ba2a3258f78a9a5387c07304479dbb (patch)
treef4f181fc61dfd6e933b914d3678740e073f5fccd
parent688eee28212b4918a46e0d965e19137bba3586d7 (diff)
wasm: convert and propagate filetype accept list
Backport the LocalFileApi::Type::fromQt() function from the dev branch, and adapt it for use with the <input type=file> file dialog API, which expects an accept string in a certain format (see code). A similar change will be made for the dev, with adaptions suitable for that branch. Change-Id: I11585ae3d445634e123ce6394cada7b34af4d85a Fixes: QTBUG-105472 Reviewed-by: Mikołaj Boc <Mikolaj.Boc@qt.io> Reviewed-by: David Skoland <david.skoland@qt.io> Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
-rw-r--r--src/gui/platform/wasm/qwasmlocalfileaccess.cpp66
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp9
2 files changed, 67 insertions, 8 deletions
diff --git a/src/gui/platform/wasm/qwasmlocalfileaccess.cpp b/src/gui/platform/wasm/qwasmlocalfileaccess.cpp
index 172c8f6814..521aa7513b 100644
--- a/src/gui/platform/wasm/qwasmlocalfileaccess.cpp
+++ b/src/gui/platform/wasm/qwasmlocalfileaccess.cpp
@@ -8,8 +8,12 @@
#include <emscripten/html5.h>
#include <emscripten/val.h>
+#include <QtCore/qregularexpression.h>
+
QT_BEGIN_NAMESPACE
+using namespace Qt::Literals::StringLiterals;
+
namespace QWasmLocalFileAccess {
void readFiles(const qstdweb::FileList &fileList,
@@ -44,6 +48,66 @@ void readFiles(const qstdweb::FileList &fileList,
(*readFile)(0);
}
+std::string acceptListFromQtFormat(const std::string &qtAcceptList)
+{
+ // copy of qt_make_filter_list() from qfiledialog.cpp
+ auto make_filter_list = [](const QString &filter) -> QStringList
+ {
+ if (filter.isEmpty())
+ return QStringList();
+
+ QString sep(";;"_L1);
+ if (!filter.contains(sep) && filter.contains(u'\n'))
+ sep = u'\n';
+
+ return filter.split(sep);
+ };
+
+ const QStringList fileFilter = make_filter_list(QString::fromStdString(qtAcceptList));
+ QStringList transformed;
+ for (const auto &element : fileFilter) {
+ // Accepts either a string in format:
+ // GROUP3
+ // or in this format:
+ // GROUP1 (GROUP2)
+ // Group 1 is treated as the description, whereas group 2 or 3 are treated as the filter
+ // list.
+ static QRegularExpression regex(
+ QString(QStringLiteral("(?:([^(]*)\\(([^()]+)\\)[^)]*)|([^()]+)")));
+ static QRegularExpression wordCharacterRegex(QString(QStringLiteral("\\w")));
+ const auto match = regex.match(element);
+
+ if (!match.hasMatch())
+ continue;
+
+ constexpr size_t FilterListFromParensIndex = 2;
+ constexpr size_t PlainFilterListIndex = 3;
+ QString filterList = match.captured(match.hasCaptured(FilterListFromParensIndex)
+ ? FilterListFromParensIndex
+ : PlainFilterListIndex);
+ for (auto singleExtension : filterList.split(QStringLiteral(" "), Qt::SkipEmptyParts)) {
+ // Checks for a filter that matches everything:
+ // Any number of asterisks or any number of asterisks with a '.' between them.
+ // The web filter does not support wildcards.
+ static QRegularExpression qtAcceptAllRegex(QRegularExpression::anchoredPattern(
+ QString(QStringLiteral("[*]+|[*]+\\.[*]+"))));
+ if (qtAcceptAllRegex.match(singleExtension).hasMatch())
+ continue;
+
+ // Checks for correctness. The web filter only allows filename extensions and does not
+ // filter the actual filenames, therefore we check whether the filter provided only
+ // filters for the extension.
+ static QRegularExpression qtFilenameMatcherRegex(QRegularExpression::anchoredPattern(
+ QString(QStringLiteral("(\\*?)(\\.[^*]+)"))));
+
+ auto extensionMatch = qtFilenameMatcherRegex.match(singleExtension);
+ if (extensionMatch.hasMatch())
+ transformed.append(extensionMatch.captured(2));
+ }
+ }
+ return transformed.join(QStringLiteral(",")).toStdString();
+}
+
typedef std::function<void (const qstdweb::FileList &fileList)> OpenFileDialogCallback;
void openFileDialog(const std::string &accept, FileSelectMode fileSelectMode,
const OpenFileDialogCallback &filesSelected)
@@ -55,7 +119,7 @@ void openFileDialog(const std::string &accept, FileSelectMode fileSelectMode,
emscripten::val input = document.call<emscripten::val>("createElement", std::string("input"));
input.set("type", "file");
input.set("style", "display:none");
- input.set("accept", emscripten::val(accept));
+ input.set("accept", acceptListFromQtFormat(accept));
input.set("multiple", emscripten::val(fileSelectMode == MultipleFiles));
// Note: there is no event in case the user cancels the file dialog.
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index 59ac84ced0..3f4deaac1e 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -2304,13 +2304,8 @@ void QFileDialog::getOpenFileContent(const QString &nameFilter, const std::funct
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);
+ QWasmLocalFileAccess::openFile(nameFilter.toStdString(), fileDialogClosed,
+ acceptFile, fileContentReady);
};
(*openFileImpl)();