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;
for (const auto &filter : filterList) {
emscripten::val::global("console").call<void>("log", filter.toStdString());
const auto type = Type::fromQt(filter);
if (type && type->accept()) {
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),
[](const Type::Accept::MimeType::Extension &extension) {
return extension.value().toString();
});
}
}
for (const QString &tran : transformed) {
emscripten::val::global("console").call<void>("log", tran.toStdString());
}
return transformed.join(QStringLiteral(",")).toStdString();
}
@ -39,13 +28,12 @@ std::optional<emscripten::val> qtFilterListToTypes(const QStringList &filterList
{
using namespace qstdweb;
using namespace emscripten;
auto types = emscripten::val::array();
for (const auto &fileFilter : filterList) {
auto type = Type::fromQt(fileFilter);
if (type) {
auto jsType = val::object();
auto jsType = emscripten::val::object();
jsType.set("description", type->description().toString().toStdString());
if (type->accept()) {
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)
{
auto options = emscripten::val::object();
if (auto typeList = qtFilterListToTypes(filterList)) {
if (auto typeList = qtFilterListToTypes(filterList); typeList) {
options.set("types", std::move(*typeList));
options.set("excludeAcceptAllOption", true);
}

View File

@ -135,66 +135,18 @@ void readFiles(const qstdweb::FileList &fileList,
(*readFile)(0);
}
QStringList acceptListFromQtFormat(const std::string &qtAcceptList)
QStringList makeFilterList(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();
auto filter = QString::fromStdString(qtAcceptList);
if (filter.isEmpty())
return QStringList();
QString sep(";;");
if (!filter.contains(sep) && filter.contains(u'\n'))
sep = u'\n';
QString sep(";;");
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;
return filter.split(sep);
}
}
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<void()> &fileDataReady)
{
FileDialog::showOpen(acceptListFromQtFormat(accept), fileSelectMode, {
FileDialog::showOpen(makeFilterList(accept), fileSelectMode, {
.thenFunc = [=](emscripten::val result) {
auto files = qstdweb::FileList(result);
fileDialogClosed(files.length());