diff options
Diffstat (limited to 'src/gui/platform/wasm/qwasmlocalfileaccess.cpp')
-rw-r--r-- | src/gui/platform/wasm/qwasmlocalfileaccess.cpp | 103 |
1 files changed, 40 insertions, 63 deletions
diff --git a/src/gui/platform/wasm/qwasmlocalfileaccess.cpp b/src/gui/platform/wasm/qwasmlocalfileaccess.cpp index 762d5e1a40..051e2b1a04 100644 --- a/src/gui/platform/wasm/qwasmlocalfileaccess.cpp +++ b/src/gui/platform/wasm/qwasmlocalfileaccess.cpp @@ -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(); - - 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; + auto filter = QString::fromStdString(qtAcceptList); + if (filter.isEmpty()) + return QStringList(); + QString sep(";;"); + if (!filter.contains(sep) && filter.contains(u'\n')) + sep = u'\n'; + + 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()); @@ -258,6 +210,11 @@ void saveDataToFileInChunks(emscripten::val fileHandle, const QByteArray &data) std::function<void(val result)> continuation; }; + static constexpr size_t desiredChunkSize = 1024u; +#if defined(__EMSCRIPTEN_SHARED_MEMORY__) + qstdweb::Uint8Array chunkArray(desiredChunkSize); +#endif + auto state = std::make_shared<State>(); state->written = 0u; state->continuation = [=](val) mutable { @@ -267,11 +224,30 @@ void saveDataToFileInChunks(emscripten::val fileHandle, const QByteArray &data) state.reset(); return; } - static constexpr size_t desiredChunkSize = 1024u; + const auto currentChunkSize = std::min(remaining, desiredChunkSize); - Promise::make(writable, QStringLiteral("write"), { - .thenFunc = state->continuation, - }, val(typed_memory_view(currentChunkSize, data.constData() + state->written))); + +#if defined(__EMSCRIPTEN_SHARED_MEMORY__) + // If shared memory is used, WebAssembly.Memory is instantiated with the 'shared' + // option on. Passing a typed_memory_view to SharedArrayBuffer to + // FileSystemWritableFileStream.write is disallowed by security policies, so we + // need to make a copy of the data to a chunk array buffer. + Promise::make( + writable, QStringLiteral("write"), + { + .thenFunc = state->continuation, + }, + chunkArray.copyFrom(data.constData() + state->written, currentChunkSize) + .val() + .call<emscripten::val>("subarray", emscripten::val(0), + emscripten::val(currentChunkSize))); +#else + Promise::make(writable, QStringLiteral("write"), + { + .thenFunc = state->continuation, + }, + val(typed_memory_view(currentChunkSize, data.constData() + state->written))); +#endif state->written += currentChunkSize; }; @@ -301,9 +277,10 @@ void saveFile(const char *content, size_t size, const std::string &fileNameHint) return; } + QByteArray data(content, size); FileDialog::showSave(fileNameHint, { .thenFunc = [=](emscripten::val result) { - saveDataToFileInChunks(result, QByteArray(content, size)); + saveDataToFileInChunks(result, data); }, }); } |