6#include <private/qstdweb_p.h>
8#include <emscripten/bind.h>
9#include <emscripten/html5.h>
10#include <emscripten/val.h>
12#include <QtCore/qregularexpression.h>
19bool hasLocalFilesApi()
30 emscripten::val document = emscripten::val::global(
"document");
31 emscripten::val
input = document.call<emscripten::val>(
"createElement", std::string(
"input"));
32 input.set(
"type",
"file");
33 input.set(
"style",
"display:none");
39 static std::unique_ptr<qstdweb::EventCallback> changeEvent;
40 auto callback = [=](emscripten::val) { onFilesSelected.
thenFunc(
input[
"files"]); };
41 changeEvent = std::make_unique<qstdweb::EventCallback>(
input,
"change", callback);
44 emscripten::val body = document[
"body"];
45 body.call<
void>(
"appendChild",
input);
46 input.call<
void>(
"click");
47 body.call<
void>(
"removeChild",
input);
60 .thenFunc = [=](emscripten::val fileHandles)
mutable {
61 std::vector<emscripten::val> filePromises;
62 filePromises.reserve(fileHandles[
"length"].as<int>());
63 for (
int i = 0;
i < fileHandles[
"length"].as<
int>(); ++
i)
64 filePromises.push_back(fileHandles[
i].call<emscripten::val>(
"getFile"));
65 Promise::all(std::move(filePromises),
callbacks);
69 }, std::move(options));
81 std::move(
callbacks), std::move(options));
89 showOpenViaLocalFileApi(accept, fileSelectMode, std::move(
callbacks)) :
90 showOpenViaHTMLPolyfill(accept, fileSelectMode, std::move(
callbacks));
95 return hasLocalFilesApi();
101 showSaveViaLocalFileApi(fileNameHint, std::move(
callbacks));
107 const std::function<
char *(uint64_t
size,
const std::string
name)> &acceptFile,
108 const std::function<
void ()> &fileDataReady)
110 auto readFile = std::make_shared<std::function<
void(
int)>>();
112 *readFile = [=](
int fileIndex)
mutable {
114 if (fileIndex >= fileList.
length()) {
124 (*readFile)(fileIndex + 1);
129 file.stream(
buffer, [readFile = readFile.get(), fileIndex, fileDataReady]() {
131 (*readFile)(fileIndex + 1);
138QStringList acceptListFromQtFormat(
const std::string &qtAcceptList)
155 for (
const auto &element : fileFilter) {
165 const auto match = regex.match(element);
167 if (!
match.hasMatch())
170 constexpr size_t FilterListFromParensIndex = 2;
171 constexpr size_t PlainFilterListIndex = 3;
173 ? FilterListFromParensIndex
174 : PlainFilterListIndex);
181 if (qtAcceptAllRegex.match(singleExtension).hasMatch())
190 auto extensionMatch = qtFilenameMatcherRegex.match(singleExtension);
191 if (extensionMatch.hasMatch())
192 transformed.append(extensionMatch.captured(2));
207 emscripten::val document = emscripten::val::global(
"document");
209 emscripten::val contentUrl =
window[
"URL"].call<emscripten::val>(
"createObjectURL", contentBlob.
val());
210 emscripten::val contentLink = document.call<emscripten::val>(
"createElement", std::string(
"a"));
211 contentLink.set(
"href", contentUrl);
212 contentLink.set(
"download", fileNameHint);
213 contentLink.set(
"style",
"display:none");
215 emscripten::val body = document[
"body"];
216 body.call<
void>(
"appendChild", contentLink);
217 contentLink.call<
void>(
"click");
218 body.call<
void>(
"removeChild", contentLink);
220 window[
"URL"].call<emscripten::val>(
"revokeObjectURL", contentUrl);
224 const std::function<
void (
int fileCount)> &fileDialogClosed,
225 const std::function<
char *(uint64_t
size,
const std::string&
name)> &acceptFile,
226 const std::function<
void()> &fileDataReady)
229 .thenFunc = [=](emscripten::val
result) {
231 fileDialogClosed(
files.length());
232 readFiles(
files, acceptFile, fileDataReady);
234 .catchFunc = [=](emscripten::val) {
241 const std::function<
void (
bool fileSelected)> &fileDialogClosed,
242 const std::function<
char *(uint64_t
size,
const std::string&
name)> &acceptFile,
243 const std::function<
void()> &fileDataReady)
245 auto fileDialogClosedWithInt = [=](
int fileCount) { fileDialogClosed(fileCount != 0); };
255 .thenFunc = [=](
val writable) {
261 static constexpr size_t desiredChunkSize = 1024u;
262#if defined(__EMSCRIPTEN_SHARED_MEMORY__)
266 auto state = std::make_shared<State>();
268 state->continuation = [=](
val)
mutable {
269 const size_t remaining =
data.size() -
state->written;
270 if (remaining == 0) {
276 const auto currentChunkSize = std::min(remaining, desiredChunkSize);
278#if defined(__EMSCRIPTEN_SHARED_MEMORY__)
286 .thenFunc =
state->continuation,
290 .call<emscripten::val>(
"subarray", emscripten::val(0),
291 emscripten::val(currentChunkSize)));
295 .thenFunc =
state->continuation,
297 val(typed_memory_view(currentChunkSize,
data.constData() +
state->written)));
299 state->written += currentChunkSize;
302 state->continuation(val::undefined());
315 .thenFunc = [=](emscripten::val
result) {
321void saveFile(
const char *content,
size_t size,
const std::string &fileNameHint)
329 .thenFunc = [=](emscripten::val
result) {
qint64 size() const override
\reimp
\inmodule QtCore \reentrant
static QString anchoredPattern(const QString &expression)
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromStdString(const std::string &s)
static Blob copyFrom(const char *buffer, uint32_t size, std::string mimeType)
static Uint8Array copyFrom(const char *buffer, uint32_t size)
std::string makeFileInputAccept(const QStringList &filterList)
emscripten::val makeOpenFileOptions(const QStringList &filterList, bool acceptMultiple)
emscripten::val makeSaveFileOptions(const QStringList &filterList, const std::string &suggestedName)
Combined button and popup list for selecting options.
void showSave(const std::string &fileNameHint, qstdweb::PromiseCallbacks callbacks)
void showOpen(const QStringList &accept, FileSelectMode fileSelectMode, qstdweb::PromiseCallbacks callbacks)
void saveFile(const QByteArray &data, const std::string &fileNameHint)
void saveDataToFileInChunks(emscripten::val fileHandle, const QByteArray &data)
void openFile(const std::string &accept, const std::function< void(bool fileSelected)> &fileDialogClosed, const std::function< char *(uint64_t size, const std::string &name)> &acceptFile, const std::function< void()> &fileDataReady)
void downloadDataAsFile(const char *content, size_t size, const std::string &fileNameHint)
void openFiles(const std::string &accept, FileSelectMode fileSelectMode, const std::function< void(int fileCount)> &fileDialogClosed, const std::function< char *(uint64_t size, const std::string &name)> &acceptFile, const std::function< void()> &fileDataReady)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLenum input
static void split(QT_FT_Vector *b)
static constexpr QChar sep
PromiseCallbacks callbacks
#define QStringLiteral(str)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
std::function< void(emscripten::val)> thenFunc