summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/platform/wasm/qlocalfileapi.cpp108
-rw-r--r--src/gui/platform/wasm/qlocalfileapi_p.h22
-rw-r--r--src/gui/platform/wasm/qwasmlocalfileaccess.cpp2
-rw-r--r--tests/auto/wasm/tst_localfileapi.cpp113
4 files changed, 157 insertions, 88 deletions
diff --git a/src/gui/platform/wasm/qlocalfileapi.cpp b/src/gui/platform/wasm/qlocalfileapi.cpp
index b56490eba4..bfcb5a5866 100644
--- a/src/gui/platform/wasm/qlocalfileapi.cpp
+++ b/src/gui/platform/wasm/qlocalfileapi.cpp
@@ -8,6 +8,33 @@
QT_BEGIN_NAMESPACE
namespace LocalFileApi {
namespace {
+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();
+}
+
std::optional<emscripten::val> qtFilterListToTypes(const QStringList &filterList)
{
using namespace qstdweb;
@@ -17,20 +44,38 @@ std::optional<emscripten::val> qtFilterListToTypes(const QStringList &filterList
for (const auto &fileFilter : filterList) {
auto type = Type::fromQt(fileFilter);
- if (type)
- types.call<void>("push", type->asVal());
+ if (type) {
+ auto jsType = val::object();
+ jsType.set("description", type->description().toString().toStdString());
+ if (type->accept()) {
+ jsType.set("accept", ([&mimeType = type->accept()->mimeType()]() {
+ val acceptDict = val::object();
+
+ QList<emscripten::val> extensions;
+ extensions.reserve(mimeType.extensions().size());
+ std::transform(
+ mimeType.extensions().begin(), mimeType.extensions().end(),
+ std::back_inserter(extensions),
+ [](const Type::Accept::MimeType::Extension &extension) {
+ return val(extension.value().toString().toStdString());
+ });
+ acceptDict.set("application/octet-stream",
+ emscripten::val::array(extensions.begin(),
+ extensions.end()));
+ return acceptDict;
+ })());
+ }
+ types.call<void>("push", std::move(jsType));
+ }
}
return types["length"].as<int>() == 0 ? std::optional<emscripten::val>() : types;
}
-}
+} // namespace
Type::Type(QStringView description, std::optional<Accept> accept)
- : m_storage(emscripten::val::object())
+ : m_description(description.trimmed()), m_accept(std::move(accept))
{
- m_storage.set("description", description.trimmed().toString().toStdString());
- if (accept)
- m_storage.set("accept", accept->asVal());
}
Type::~Type() = default;
@@ -69,12 +114,7 @@ std::optional<Type> Type::fromQt(QStringView type)
return Type(description, std::move(*accept));
}
-emscripten::val Type::asVal() const
-{
- return m_storage;
-}
-
-Type::Accept::Accept() : m_storage(emscripten::val::object()) { }
+Type::Accept::Accept() = default;
Type::Accept::~Accept() = default;
@@ -100,39 +140,25 @@ std::optional<Type::Accept> Type::Accept::fromQt(QStringView qtRepresentation)
internalMatch = internalRegex.matchView(qtRepresentation, internalMatch.capturedEnd());
}
- accept.addMimeType(mimeType);
+ accept.setMimeType(mimeType);
return accept;
}
-void Type::Accept::addMimeType(MimeType mimeType)
-{
- // The mime type provided here does not seem to have any effect at the result at all.
- m_storage.set("application/octet-stream", mimeType.asVal());
-}
-
-emscripten::val Type::Accept::asVal() const
+void Type::Accept::setMimeType(MimeType mimeType)
{
- return m_storage;
+ m_mimeType = std::move(mimeType);
}
-Type::Accept::MimeType::MimeType() : m_storage(emscripten::val::array()) { }
+Type::Accept::MimeType::MimeType() = default;
Type::Accept::MimeType::~MimeType() = default;
void Type::Accept::MimeType::addExtension(Extension extension)
{
- m_storage.call<void>("push", extension.asVal());
+ m_extensions.push_back(std::move(extension));
}
-emscripten::val Type::Accept::MimeType::asVal() const
-{
- return m_storage;
-}
-
-Type::Accept::MimeType::Extension::Extension(QStringView extension)
- : m_storage(extension.toString().toStdString())
-{
-}
+Type::Accept::MimeType::Extension::Extension(QStringView extension) : m_value(extension) { }
Type::Accept::MimeType::Extension::~Extension() = default;
@@ -161,15 +187,10 @@ Type::Accept::MimeType::Extension::fromQt(QStringView qtRepresentation)
return std::nullopt;
}
-emscripten::val Type::Accept::MimeType::Extension::asVal() const
-{
- return m_storage;
-}
-
emscripten::val makeOpenFileOptions(const QStringList &filterList, bool acceptMultiple)
{
auto options = emscripten::val::object();
- if (auto typeList = LocalFileApi::qtFilterListToTypes(filterList)) {
+ if (auto typeList = qtFilterListToTypes(filterList)) {
options.set("types", std::move(*typeList));
options.set("excludeAcceptAllOption", true);
}
@@ -186,12 +207,17 @@ emscripten::val makeSaveFileOptions(const QStringList &filterList, const std::st
if (!suggestedName.empty())
options.set("suggestedName", emscripten::val(suggestedName));
- if (auto typeList = LocalFileApi::qtFilterListToTypes(filterList))
+ if (auto typeList = qtFilterListToTypes(filterList))
options.set("types", emscripten::val(std::move(*typeList)));
return options;
}
-} // namespace LocalFileApi
+std::string makeFileInputAccept(const QStringList &filterList)
+{
+ return qtFilterListToFileInputAccept(filterList);
+}
+
+} // namespace LocalFileApi
QT_END_NAMESPACE
diff --git a/src/gui/platform/wasm/qlocalfileapi_p.h b/src/gui/platform/wasm/qlocalfileapi_p.h
index a8e7f666f9..b8fa6adb99 100644
--- a/src/gui/platform/wasm/qlocalfileapi_p.h
+++ b/src/gui/platform/wasm/qlocalfileapi_p.h
@@ -36,12 +36,12 @@ public:
~Extension();
- emscripten::val asVal() const;
+ const QStringView &value() const { return m_value; }
private:
explicit Extension(QStringView extension);
- emscripten::val m_storage;
+ QStringView m_value;
};
MimeType();
@@ -49,38 +49,42 @@ public:
void addExtension(Extension type);
- emscripten::val asVal() const;
+ const std::vector<Extension> &extensions() const { return m_extensions; }
private:
- emscripten::val m_storage;
+ std::vector<Extension> m_extensions;
};
static std::optional<Accept> fromQt(QStringView type);
~Accept();
- void addMimeType(MimeType mimeType);
+ void setMimeType(MimeType mimeType);
- emscripten::val asVal() const;
+ const MimeType &mimeType() const { return m_mimeType; }
private:
Accept();
- emscripten::val m_storage;
+ MimeType m_mimeType;
};
Type(QStringView description, std::optional<Accept> accept);
~Type();
static std::optional<Type> fromQt(QStringView type);
- emscripten::val asVal() const;
+ const QStringView &description() const { return m_description; }
+ const std::optional<Accept> &accept() const { return m_accept; }
private:
- emscripten::val m_storage;
+ QStringView m_description;
+ std::optional<Accept> m_accept;
};
Q_CORE_EXPORT emscripten::val makeOpenFileOptions(const QStringList &filterList, bool acceptMultiple);
Q_CORE_EXPORT emscripten::val makeSaveFileOptions(const QStringList &filterList, const std::string& suggestedName);
+Q_AUTOTEST_EXPORT std::string makeFileInputAccept(const QStringList &filterList);
+
} // namespace LocalFileApi
QT_END_NAMESPACE
diff --git a/src/gui/platform/wasm/qwasmlocalfileaccess.cpp b/src/gui/platform/wasm/qwasmlocalfileaccess.cpp
index 72f1dcc339..762d5e1a40 100644
--- a/src/gui/platform/wasm/qwasmlocalfileaccess.cpp
+++ b/src/gui/platform/wasm/qwasmlocalfileaccess.cpp
@@ -31,7 +31,7 @@ void showOpenViaHTMLPolyfill(const QStringList &accept, FileSelectMode fileSelec
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", LocalFileApi::makeFileInputAccept(accept));
Q_UNUSED(accept);
input.set("multiple", emscripten::val(fileSelectMode == FileSelectMode::MultipleFiles));
diff --git a/tests/auto/wasm/tst_localfileapi.cpp b/tests/auto/wasm/tst_localfileapi.cpp
index 0d17202d4b..95bdbcffb2 100644
--- a/tests/auto/wasm/tst_localfileapi.cpp
+++ b/tests/auto/wasm/tst_localfileapi.cpp
@@ -11,14 +11,16 @@ class tst_LocalFileApi : public QObject
Q_OBJECT
private:
- emscripten::val makeAccept(std::vector<emscripten::val> types) {
+ emscripten::val makeAccept(std::vector<emscripten::val> types)
+ {
auto accept = emscripten::val::object();
accept.set("application/octet-stream",
emscripten::val::array(std::move(types)));
return accept;
}
- emscripten::val makeType(QString description, std::vector<emscripten::val> acceptExtensions) {
+ emscripten::val makeType(QString description, std::vector<emscripten::val> acceptExtensions)
+ {
using namespace emscripten;
auto type = val::object();
@@ -65,6 +67,8 @@ private Q_SLOTS:
void openFileOptions();
void saveFileOptions_data();
void saveFileOptions();
+ void fileInputAccept_data();
+ void fileInputAccept();
};
bool valDeepEquals(emscripten::val lhs, emscripten::val rhs)
@@ -79,24 +83,27 @@ bool valDeepEquals(emscripten::val lhs, emscripten::val rhs)
void tst_LocalFileApi::fileExtensionFilterTransformation_data()
{
QTest::addColumn<QString>("qtFileFilter");
- QTest::addColumn<std::optional<std::string>>("expectedWebExtensionFilter");
-
- QTest::newRow("PNG extension with an asterisk") << QString("*.png") << std::make_optional<std::string>(".png");
- QTest::newRow("Long extension with an asterisk") << QString("*.someotherfile") << std::make_optional<std::string>(".someotherfile");
- QTest::newRow(".dat with no asterisk") << QString(".dat") << std::make_optional<std::string>(".dat");
- QTest::newRow("Multiple asterisks") << QString("*ot*.abc") << std::optional<std::string>();
- QTest::newRow("Filename") << QString("abcd.abc") << std::optional<std::string>();
- QTest::newRow("match all") << QString("*.*") << std::optional<std::string>();
+ QTest::addColumn<std::optional<QString>>("expectedWebExtensionFilter");
+
+ QTest::newRow("PNG extension with an asterisk")
+ << QString("*.png") << std::make_optional<QString>(".png");
+ QTest::newRow("Long extension with an asterisk")
+ << QString("*.someotherfile") << std::make_optional<QString>(".someotherfile");
+ QTest::newRow(".dat with no asterisk")
+ << QString(".dat") << std::make_optional<QString>(".dat");
+ QTest::newRow("Multiple asterisks") << QString("*ot*.abc") << std::optional<QString>();
+ QTest::newRow("Filename") << QString("abcd.abc") << std::optional<QString>();
+ QTest::newRow("match all") << QString("*.*") << std::optional<QString>();
}
void tst_LocalFileApi::fileExtensionFilterTransformation()
{
QFETCH(QString, qtFileFilter);
- QFETCH(std::optional<std::string>, expectedWebExtensionFilter);
+ QFETCH(std::optional<QString>, expectedWebExtensionFilter);
auto result = LocalFileApi::Type::Accept::MimeType::Extension::fromQt(qtFileFilter);
if (expectedWebExtensionFilter) {
- QCOMPARE_EQ(expectedWebExtensionFilter, result->asVal().as<std::string>());
+ QCOMPARE_EQ(expectedWebExtensionFilter, result->value());
} else {
QVERIFY(!result.has_value());
}
@@ -107,34 +114,37 @@ void tst_LocalFileApi::acceptTransformation_data()
using namespace emscripten;
QTest::addColumn<QString>("qtFilterList");
- QTest::addColumn<emscripten::val>("expectedWebType");
+ QTest::addColumn<QStringList>("expectedExtensionList");
- QTest::newRow("Multiple types") << QString("*.png *.other *.txt")
- << makeAccept(std::vector<val> { val(".png"), val(".other"), val(".txt") });
+ QTest::newRow("Multiple types")
+ << QString("*.png *.other *.txt") << QStringList{ ".png", ".other", ".txt" };
- QTest::newRow("Single type") << QString("*.png")
- << makeAccept(std::vector<val> { val(".png") });
+ QTest::newRow("Single type") << QString("*.png") << QStringList{ ".png" };
- QTest::newRow("No filter when accepts all") << QString("*.*")
- << val::undefined();
+ QTest::newRow("No filter when accepts all") << QString("*.*") << QStringList();
- QTest::newRow("No filter when one filter accepts all") << QString("*.* *.jpg")
- << val::undefined();
+ QTest::newRow("No filter when one filter accepts all") << QString("*.* *.jpg") << QStringList();
QTest::newRow("Weird spaces") << QString(" *.jpg *.png *.icon ")
- << makeAccept(std::vector<val> { val(".jpg"), val(".png"), val(".icon") });
+ << QStringList{ ".jpg", ".png", ".icon" };
}
void tst_LocalFileApi::acceptTransformation()
{
QFETCH(QString, qtFilterList);
- QFETCH(emscripten::val, expectedWebType);
+ QFETCH(QStringList, expectedExtensionList);
auto result = LocalFileApi::Type::Accept::fromQt(qtFilterList);
- if (!expectedWebType.isUndefined()) {
- QVERIFY(valDeepEquals(result->asVal(), expectedWebType));
- } else {
+ if (expectedExtensionList.isEmpty()) {
QVERIFY(!result.has_value());
+ } else {
+ QStringList transformed;
+ std::transform(result->mimeType().extensions().begin(),
+ result->mimeType().extensions().end(), std::back_inserter(transformed),
+ [](const LocalFileApi::Type::Accept::MimeType::Extension &extension) {
+ return extension.value().toString();
+ });
+ QCOMPARE_EQ(expectedExtensionList, transformed);
}
}
@@ -143,26 +153,31 @@ void tst_LocalFileApi::typeTransformation_data()
using namespace emscripten;
QTest::addColumn<QString>("qtFilterList");
- QTest::addColumn<emscripten::val>("expectedWebType");
+ QTest::addColumn<QString>("expectedDescription");
+ QTest::addColumn<QStringList>("expectedExtensions");
- QTest::newRow("With description") << QString("Text files (*.txt)")
- << makeType("Text files", std::vector<val> { val(".txt") });
+ QTest::newRow("With description")
+ << QString("Text files (*.txt)") << QString("Text files") << QStringList{ ".txt" };
- QTest::newRow("No description") << QString("*.jpg")
- << makeType("", std::vector<val> { val(".jpg") });
+ QTest::newRow("No description") << QString("*.jpg") << QString("") << QStringList{ ".jpg" };
}
void tst_LocalFileApi::typeTransformation()
{
QFETCH(QString, qtFilterList);
- QFETCH(emscripten::val, expectedWebType);
+ QFETCH(QString, expectedDescription);
+ QFETCH(QStringList, expectedExtensions);
auto result = LocalFileApi::Type::fromQt(qtFilterList);
- if (!expectedWebType.isUndefined()) {
- QVERIFY(valDeepEquals(result->asVal(), expectedWebType));
- } else {
- QVERIFY(!result.has_value());
- }
+ QCOMPARE_EQ(result->description(), expectedDescription);
+
+ QStringList transformed;
+ std::transform(result->accept()->mimeType().extensions().begin(),
+ result->accept()->mimeType().extensions().end(), std::back_inserter(transformed),
+ [](const LocalFileApi::Type::Accept::MimeType::Extension &extension) {
+ return extension.value().toString();
+ });
+ QCOMPARE_EQ(expectedExtensions, transformed);
}
void tst_LocalFileApi::openFileOptions_data()
@@ -217,5 +232,29 @@ void tst_LocalFileApi::saveFileOptions()
QVERIFY(valDeepEquals(result, expectedWebType));
}
+void tst_LocalFileApi::fileInputAccept_data()
+{
+ using namespace emscripten;
+
+ QTest::addColumn<QStringList>("qtFilterList");
+ QTest::addColumn<QString>("expectedAccept");
+
+ QTest::newRow("Multiple files")
+ << QStringList{ "Text files (*.txt)", "Images (*.jpg *.png)", "*.bat" }
+ << ".txt,.jpg,.png,.bat";
+ QTest::newRow("Spaces") << QStringList{ " Documents (*.doc)", "Everything (*.*)",
+ " Stuff ( *.stf *.tng)", " *.exe" }
+ << ".doc,.stf,.tng,.exe";
+}
+
+void tst_LocalFileApi::fileInputAccept()
+{
+ QFETCH(QStringList, qtFilterList);
+ QFETCH(QString, expectedAccept);
+
+ auto result = LocalFileApi::makeFileInputAccept(qtFilterList);
+ QCOMPARE_EQ(expectedAccept, QString::fromStdString(result));
+}
+
QTEST_APPLESS_MAIN(tst_LocalFileApi)
#include "tst_localfileapi.moc"