wasm: Fix QFileDialog file filter

File filter was not properly processed when using LocalFileAPI.
The QtFormat->AcceptList conversion was happening twice, resulting
in erronous types. This prevented dialog from appearing on Chrome.
Additionally remove unused debug code.

Fixes: QTBUG-115087
Change-Id: Ie6770e2f1d2aa7c3ad19f9ab105dbec8102d45fc
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
(cherry picked from commit 62caae95784a2e70d46194622e96e0e6bdf13c28)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Piotr Wierciński 2023-08-23 13:03:45 +02:00 committed by Qt Cherry-pick Bot
parent e32b3aeb64
commit 8240f9437e
2 changed files with 11 additions and 71 deletions

View File

@ -12,26 +12,15 @@ std::string qtFilterListToFileInputAccept(const QStringList &filterList)
{ {
QStringList transformed; QStringList transformed;
for (const auto &filter : filterList) { for (const auto &filter : filterList) {
emscripten::val::global("console").call<void>("log", filter.toStdString());
const auto type = Type::fromQt(filter); const auto type = Type::fromQt(filter);
if (type && type->accept()) { if (type && type->accept()) {
const auto &extensions = type->accept()->mimeType().extensions(); const auto &extensions = type->accept()->mimeType().extensions();
for (const auto &ext : extensions) {
emscripten::val::global("console").call<void>("log",
ext.value().toString().toStdString());
}
std::transform(extensions.begin(), extensions.end(), std::back_inserter(transformed), std::transform(extensions.begin(), extensions.end(), std::back_inserter(transformed),
[](const Type::Accept::MimeType::Extension &extension) { [](const Type::Accept::MimeType::Extension &extension) {
return extension.value().toString(); return extension.value().toString();
}); });
} }
} }
for (const QString &tran : transformed) {
emscripten::val::global("console").call<void>("log", tran.toStdString());
}
return transformed.join(QStringLiteral(",")).toStdString(); return transformed.join(QStringLiteral(",")).toStdString();
} }
@ -39,13 +28,12 @@ std::optional<emscripten::val> qtFilterListToTypes(const QStringList &filterList
{ {
using namespace qstdweb; using namespace qstdweb;
using namespace emscripten; using namespace emscripten;
auto types = emscripten::val::array(); auto types = emscripten::val::array();
for (const auto &fileFilter : filterList) { for (const auto &fileFilter : filterList) {
auto type = Type::fromQt(fileFilter); auto type = Type::fromQt(fileFilter);
if (type) { if (type) {
auto jsType = val::object(); auto jsType = emscripten::val::object();
jsType.set("description", type->description().toString().toStdString()); jsType.set("description", type->description().toString().toStdString());
if (type->accept()) { if (type->accept()) {
jsType.set("accept", ([&mimeType = type->accept()->mimeType()]() { jsType.set("accept", ([&mimeType = type->accept()->mimeType()]() {
@ -190,7 +178,7 @@ Type::Accept::MimeType::Extension::fromQt(QStringView qtRepresentation)
emscripten::val makeOpenFileOptions(const QStringList &filterList, bool acceptMultiple) emscripten::val makeOpenFileOptions(const QStringList &filterList, bool acceptMultiple)
{ {
auto options = emscripten::val::object(); auto options = emscripten::val::object();
if (auto typeList = qtFilterListToTypes(filterList)) { if (auto typeList = qtFilterListToTypes(filterList); typeList) {
options.set("types", std::move(*typeList)); options.set("types", std::move(*typeList));
options.set("excludeAcceptAllOption", true); options.set("excludeAcceptAllOption", true);
} }

View File

@ -135,66 +135,18 @@ void readFiles(const qstdweb::FileList &fileList,
(*readFile)(0); (*readFile)(0);
} }
QStringList acceptListFromQtFormat(const std::string &qtAcceptList) QStringList makeFilterList(const std::string &qtAcceptList)
{ {
// copy of qt_make_filter_list() from qfiledialog.cpp // copy of qt_make_filter_list() from qfiledialog.cpp
auto make_filter_list = [](const QString &filter) -> QStringList auto filter = QString::fromStdString(qtAcceptList);
{
if (filter.isEmpty()) if (filter.isEmpty())
return QStringList(); return QStringList();
QString sep(";;"); QString sep(";;");
if (!filter.contains(sep) && filter.contains(u'\n')) if (!filter.contains(sep) && filter.contains(u'\n'))
sep = u'\n'; sep = u'\n';
return filter.split(sep); 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;
} }
} }
void downloadDataAsFile(const char *content, size_t size, const std::string &fileNameHint) void downloadDataAsFile(const char *content, size_t size, const std::string &fileNameHint)
@ -225,7 +177,7 @@ void openFiles(const std::string &accept, FileSelectMode fileSelectMode,
const std::function<char *(uint64_t size, const std::string& name)> &acceptFile, const std::function<char *(uint64_t size, const std::string& name)> &acceptFile,
const std::function<void()> &fileDataReady) const std::function<void()> &fileDataReady)
{ {
FileDialog::showOpen(acceptListFromQtFormat(accept), fileSelectMode, { FileDialog::showOpen(makeFilterList(accept), fileSelectMode, {
.thenFunc = [=](emscripten::val result) { .thenFunc = [=](emscripten::val result) {
auto files = qstdweb::FileList(result); auto files = qstdweb::FileList(result);
fileDialogClosed(files.length()); fileDialogClosed(files.length());