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>
This commit is contained in:
parent
688eee2821
commit
315a5e3257
@ -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.
|
||||
|
@ -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)();
|
||||
|
Loading…
x
Reference in New Issue
Block a user