77 for (
const auto &format : mimeData.formats()) {
78 if (format.startsWith(
"text/")) {
79 auto data = mimeData.data(format);
80 setData(format.toStdString(), QString::fromLocal8Bit(data).toStdString());
81 }
else if (format ==
"application/x-qt-image") {
82 auto image = qvariant_cast<QImage>(mimeData.imageData());
84 QBuffer buffer(&byteArray);
85 buffer.open(QIODevice::WriteOnly);
86 image.save(&buffer,
"PNG");
89 setData(format.toStdString(),
"QB64" + QString::fromLocal8Bit(byteArray.toBase64()).toStdString());
91 auto data = mimeData.data(format);
92 auto encoded =
"QB64" + QString::fromLocal8Bit(data.toBase64()).toStdString();
93 setData(format.toStdString(), std::move(encoded));
103 enum class ItemKind {
111 MimeContext(
int itemCount, std::function<
void(QMimeData *)> callback)
112 :m_remainingItemCount(itemCount), m_callback(callback)
118 if (--m_remainingItemCount > 0)
122 allUrls.append(mimeData->urls());
123 allUrls.append(fileUrls);
124 mimeData->setUrls(allUrls);
126 m_callback(mimeData);
132 for (QUrl fileUrl: fileUrls) {
133 if (!QWasmFileEngineHandler::isWasmFileName(fileUrl.toString()))
134 QFile(fileUrl.toLocalFile()).remove();
140 QMimeData *mimeData =
new QMimeData();
141 QList<QUrl> fileUrls;
144 int m_remainingItemCount;
145 std::function<
void(QMimeData *)> m_callback;
148 const auto items = webDataTransfer[
"items"];
149 const int itemCount = items[
"length"].as<
int>();
150 const int fileCount = webDataTransfer[
"files"][
"length"].as<
int>();
151 MimeContext *mimeContext =
new MimeContext(itemCount, callback);
153 for (
int i = 0; i < itemCount; ++i) {
154 const auto item = items[i];
155 const auto itemKind =
156 item[
"kind"].as<
std::string>() ==
"string" ? ItemKind::String : ItemKind::File;
157 const auto itemMimeType = QString::fromStdString(item[
"type"].as<std::string>());
160 case ItemKind::File: {
161 qstdweb::File webfile(item.call<emscripten::val>(
"getAsFile"));
166 if (qstdweb::haveAsyncify()) {
167 QUrl fileUrl(QWasmFileEngineHandler::addFile(webfile));
168 mimeContext->fileUrls.append(fileUrl);
169 mimeContext->deref();
172 if (webfile.size() > 1e+9) {
173 qWarning() <<
"File is too large (> 1GB) and will be skipped. File size is" << webfile.size();
174 mimeContext->deref();
179 QByteArray fileContent(webfile.size(), Qt::Uninitialized);
180 webfile.stream(fileContent.data(), [=]() {
181 QDir qtTmpDir(
"/qt/tmp/");
182 qtTmpDir.mkpath(qtTmpDir.path());
184 QUrl fileUrl = QUrl::fromLocalFile(qtTmpDir.filePath(QString::fromStdString(webfile.name())));
185 mimeContext->fileUrls.append(fileUrl);
187 QFile file(fileUrl.toLocalFile());
188 if (!file.open(QFile::WriteOnly)) {
189 qWarning() <<
"File was not opened";
190 mimeContext->deref();
193 if (file.write(fileContent) < 0)
194 qWarning() <<
"Write failed";
196 mimeContext->deref();
206 QString mimeFormat = QString::fromStdString(webfile.type());
207 if (fileCount == 1 && mimeFormat.contains(
"image/")) {
209 if (image.loadFromData(fileContent))
210 mimeContext->mimeData->setImageData(image);
215 case ItemKind::String:
216 if (itemMimeType.contains(
"STRING", Qt::CaseSensitive)
217 || itemMimeType.contains(
"TEXT", Qt::CaseSensitive)) {
218 mimeContext->deref();
222 QString data = QString::fromEcmaString(webDataTransfer.call<emscripten::val>(
223 "getData", emscripten::val(itemMimeType.toStdString())));
225 if (!data.isEmpty()) {
226 if (itemMimeType ==
"text/html")
227 mimeContext->mimeData->setHtml(data);
228 else if (itemMimeType.isEmpty() || itemMimeType ==
"text/plain")
229 mimeContext->mimeData->setText(data);
230 else if (itemMimeType.isEmpty() || itemMimeType ==
"text/uri-list") {
233 mimeContext->mimeData->setUrls(urls);
234 }
else if (itemMimeType ==
"application/x-qt-image") {
235 if (data.startsWith(
"QB64")) {
237 auto ba = QByteArray::fromBase64(QByteArray::fromStdString(data.toStdString()));
239 image.loadFromData(ba);
240 mimeContext->mimeData->setImageData(image);
244 if (data.startsWith(
"QB64")) {
246 mimeContext->mimeData->setData(itemMimeType,
247 QByteArray::fromBase64(QByteArray::fromStdString(
248 data.toStdString())));
250 mimeContext->mimeData->setData(itemMimeType, data.toLocal8Bit());
254 mimeContext->deref();
305void drawImageToWebImageDataArray(
const QImage &sourceImage, emscripten::val destinationImageData,
306 const QRect &sourceRect)
308 Q_ASSERT_X(destinationImageData[
"constructor"][
"name"].as<
std::string>() ==
"ImageData",
309 Q_FUNC_INFO,
"The destination should be an ImageData instance");
311 constexpr int BytesPerColor = 4;
312 if (sourceRect.width() == sourceImage.width()) {
319 auto imageMemory = emscripten::typed_memory_view(sourceRect.width() * sourceRect.height()
321 sourceImage.constScanLine(sourceRect.y()));
322 destinationImageData[
"data"].call<
void>(
323 "set", imageMemory, sourceRect.y() * sourceImage.width() * BytesPerColor);
332 for (
int row = 0; row < sourceRect.height(); ++row) {
333 auto scanlineMemory =
334 emscripten::typed_memory_view(sourceRect.width() * BytesPerColor,
335 sourceImage.constScanLine(row + sourceRect.y())
336 + BytesPerColor * sourceRect.x());
337 destinationImageData[
"data"].call<
void>(
"set", scanlineMemory,
338 (sourceRect.y() + row) * sourceImage.width()
340 + sourceRect.x() * BytesPerColor);