74 for (
const auto &format : mimeData.formats()) {
75 auto data = mimeData.data(format);
77 auto encoded = format.startsWith(
"text/")
78 ? QString::fromLocal8Bit(data).toStdString()
79 :
"QB64" + QString::fromLocal8Bit(data.toBase64()).toStdString();
81 setData(format.toStdString(), std::move(encoded));
98 MimeContext(
int itemCount, std::function<
void(QMimeData *)> callback)
99 :m_remainingItemCount(itemCount), m_callback(callback)
105 if (--m_remainingItemCount > 0)
109 allUrls.append(mimeData->urls());
110 allUrls.append(fileUrls);
111 mimeData->setUrls(allUrls);
113 m_callback(mimeData);
118 for (QUrl fileUrl: fileUrls)
119 QFile(fileUrl.toLocalFile()).remove();
124 QMimeData *mimeData =
new QMimeData();
125 QList<QUrl> fileUrls;
128 int m_remainingItemCount;
129 std::function<
void(QMimeData *)> m_callback;
132 const auto items = webDataTransfer[
"items"];
133 const int itemCount = items[
"length"].as<
int>();
134 const int fileCount = webDataTransfer[
"files"][
"length"].as<
int>();
135 MimeContext *mimeContext =
new MimeContext(itemCount, callback);
137 for (
int i = 0; i < itemCount; ++i) {
138 const auto item = items[i];
139 const auto itemKind =
140 item[
"kind"].as<
std::string>() ==
"string" ? ItemKind::String : ItemKind::File;
141 const auto itemMimeType = QString::fromStdString(item[
"type"].as<std::string>());
144 case ItemKind::File: {
145 qstdweb::File webfile(item.call<emscripten::val>(
"getAsFile"));
147 if (webfile.size() > 1e+9) {
148 qWarning() <<
"File is too large (> 1GB) and will be skipped. File size is" << webfile.size();
149 mimeContext->deref();
153 QString mimeFormat = QString::fromStdString(webfile.type());
154 QString fileName = QString::fromStdString(webfile.name());
157 QByteArray fileContent(webfile.size(), Qt::Uninitialized);
158 webfile.stream(fileContent.data(), [=]() {
167 if (fileCount == 1 && mimeFormat.contains(
"image/")) {
169 if (image.loadFromData(fileContent))
170 mimeContext->mimeData->setImageData(image);
173 QDir qtTmpDir(
"/qt/tmp/");
174 qtTmpDir.mkpath(qtTmpDir.path());
176 QUrl fileUrl = QUrl::fromLocalFile(qtTmpDir.filePath(QString::fromStdString(webfile.name())));
177 mimeContext->fileUrls.append(fileUrl);
179 QFile file(fileUrl.toLocalFile());
180 if (!file.open(QFile::WriteOnly)) {
181 qWarning() <<
"File was not opened";
182 mimeContext->deref();
185 if (file.write(fileContent) < 0)
186 qWarning() <<
"Write failed";
188 mimeContext->deref();
192 case ItemKind::String:
193 if (itemMimeType.contains(
"STRING", Qt::CaseSensitive)
194 || itemMimeType.contains(
"TEXT", Qt::CaseSensitive)) {
195 mimeContext->deref();
199 QString data = QString::fromEcmaString(webDataTransfer.call<emscripten::val>(
200 "getData", emscripten::val(itemMimeType.toStdString())));
202 if (!data.isEmpty()) {
203 if (itemMimeType ==
"text/html")
204 mimeContext->mimeData->setHtml(data);
205 else if (itemMimeType.isEmpty() || itemMimeType ==
"text/plain")
206 mimeContext->mimeData->setText(data);
207 else if (itemMimeType.isEmpty() || itemMimeType ==
"text/uri-list") {
210 mimeContext->mimeData->setUrls(urls);
213 if (data.startsWith(
"QB64")) {
215 mimeContext->mimeData->setData(itemMimeType,
216 QByteArray::fromBase64(QByteArray::fromStdString(
217 data.toStdString())));
219 mimeContext->mimeData->setData(itemMimeType, data.toLocal8Bit());
223 mimeContext->deref();
268void drawImageToWebImageDataArray(
const QImage &sourceImage, emscripten::val destinationImageData,
269 const QRect &sourceRect)
271 Q_ASSERT_X(destinationImageData[
"constructor"][
"name"].as<std::string>() ==
"ImageData",
272 Q_FUNC_INFO,
"The destination should be an ImageData instance");
274 constexpr int BytesPerColor = 4;
275 if (sourceRect.width() == sourceImage.width()) {
282 auto imageMemory = emscripten::typed_memory_view(sourceRect.width() * sourceRect.height()
284 sourceImage.constScanLine(sourceRect.y()));
285 destinationImageData[
"data"].call<
void>(
286 "set", imageMemory, sourceRect.y() * sourceImage.width() * BytesPerColor);
295 for (
int row = 0; row < sourceRect.height(); ++row) {
296 auto scanlineMemory =
297 emscripten::typed_memory_view(sourceRect.width() * BytesPerColor,
298 sourceImage.constScanLine(row + sourceRect.y())
299 + BytesPerColor * sourceRect.x());
300 destinationImageData[
"data"].call<
void>(
"set", scanlineMemory,
301 (sourceRect.y() + row) * sourceImage.width()
303 + sourceRect.x() * BytesPerColor);