summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorn Potter <[email protected]>2023-10-19 16:33:25 +1000
committerLorn Potter <[email protected]>2023-12-22 08:06:08 +1000
commit1f7d222cec1e8659d7bfa19ec3c1098a2bc00f35 (patch)
treec476f09ec2849c525805b9d6d714fff07b23fee4
parent8cc84a1386b77701ebc9c9d4efbc1b033d0e326b (diff)
wasm: write file to storage on drop
Change-Id: Ibd1b5d623da07ad611cce577929a23ba991b6738 Pick-to: 6.7 Reviewed-by: Morten Johan Sørvig <[email protected]>
-rw-r--r--src/plugins/platforms/wasm/qwasmclipboard.cpp29
-rw-r--r--src/plugins/platforms/wasm/qwasmclipboard.h1
-rw-r--r--src/plugins/platforms/wasm/qwasmdom.cpp62
-rw-r--r--src/plugins/platforms/wasm/qwasmdom.h5
-rw-r--r--src/plugins/platforms/wasm/qwasmdrag.cpp42
5 files changed, 102 insertions, 37 deletions
diff --git a/src/plugins/platforms/wasm/qwasmclipboard.cpp b/src/plugins/platforms/wasm/qwasmclipboard.cpp
index 9c7088067eb..786267277af 100644
--- a/src/plugins/platforms/wasm/qwasmclipboard.cpp
+++ b/src/plugins/platforms/wasm/qwasmclipboard.cpp
@@ -70,16 +70,7 @@ static void qClipboardPasteTo(val event)
{
event.call<void>("preventDefault"); // prevent browser from handling drop event
- static std::shared_ptr<qstdweb::CancellationFlag> readDataCancellation = nullptr;
- dom::DataTransfer transfer(event["clipboardData"]);
- auto data = transfer.toMimeDataWithFile();
- if (data->formats().isEmpty())
- return;
- // Persist clipboard data so that the app can read it when handling the CTRL+V
- QWasmIntegration::get()->clipboard()->QPlatformClipboard::setMimeData(data,
- QClipboard::Clipboard);
- QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, Qt::Key_V,
- Qt::ControlModifier, "V");
+ QWasmIntegration::get()->getWasmClipboard()->sendClipboardData(event);
}
EMSCRIPTEN_BINDINGS(qtClipboardModule) {
@@ -292,4 +283,22 @@ void QWasmClipboard::writeToClipboard()
document.call<val>("execCommand", val("copy"));
}
+void QWasmClipboard::sendClipboardData(emscripten::val event)
+{
+ dom::DataTransfer transfer(event["clipboardData"]);
+ QMimeData *mData;
+ const auto pointerCallback = std::function([&](QMimeData &data) {
+ mData = &data;
+ // Persist clipboard data so that the app can read it when handling the CTRL+V
+ QWasmIntegration::get()->clipboard()->QPlatformClipboard::setMimeData(mData,
+ QClipboard::Clipboard);
+ QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, Qt::Key_V,
+ Qt::ControlModifier, "V");
+ QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyRelease, Qt::Key_V,
+ Qt::ControlModifier, "V");
+ });
+
+ transfer.toMimeDataWithFile(pointerCallback); // mimedata
+
+}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmclipboard.h b/src/plugins/platforms/wasm/qwasmclipboard.h
index 11e7e9f714d..86618dd5604 100644
--- a/src/plugins/platforms/wasm/qwasmclipboard.h
+++ b/src/plugins/platforms/wasm/qwasmclipboard.h
@@ -38,6 +38,7 @@ public:
ProcessKeyboardResult processKeyboard(const KeyEvent &event);
static void installEventHandlers(const emscripten::val &target);
bool hasClipboardApi();
+ void sendClipboardData(emscripten::val event);
private:
void initClipboardPermissions();
diff --git a/src/plugins/platforms/wasm/qwasmdom.cpp b/src/plugins/platforms/wasm/qwasmdom.cpp
index 845aef3bc10..a2a9c129771 100644
--- a/src/plugins/platforms/wasm/qwasmdom.cpp
+++ b/src/plugins/platforms/wasm/qwasmdom.cpp
@@ -3,7 +3,6 @@
#include "qwasmdom.h"
-#include <QMimeData>
#include <QtCore/qpoint.h>
#include <QtCore/qrect.h>
#include <QtGui/qimage.h>
@@ -15,6 +14,9 @@
QT_BEGIN_NAMESPACE
+// this needs to live outside the life of DataTransfer
+Q_GLOBAL_STATIC(QMimeData, resultMimeData);
+
namespace dom {
namespace {
std::string dropActionToDropEffect(Qt::DropAction action)
@@ -36,7 +38,9 @@ std::string dropActionToDropEffect(Qt::DropAction action)
}
} // namespace
-DataTransfer::DataTransfer(emscripten::val webDataTransfer) : webDataTransfer(webDataTransfer) { }
+DataTransfer::DataTransfer(emscripten::val webDataTransfer)
+ : webDataTransfer(webDataTransfer) {
+}
DataTransfer::~DataTransfer() = default;
@@ -78,10 +82,9 @@ void DataTransfer::setDataFromMimeData(const QMimeData &mimeData)
}
}
-QMimeData *DataTransfer::toMimeDataWithFile()
+QMimeData *DataTransfer::toMimeDataWithFile(std::function<void(QMimeData &)> callback)
{
- QMimeData *resultMimeData = new QMimeData(); // QScopedPointer?
-
+ resultMimeData->clear();
enum class ItemKind {
File,
String,
@@ -99,8 +102,43 @@ QMimeData *DataTransfer::toMimeDataWithFile()
case ItemKind::File: {
m_webFile = item.call<emscripten::val>("getAsFile");
qstdweb::File webfile(m_webFile);
- QUrl fileUrl(QStringLiteral("file:///") + QString::fromStdString(webfile.name()));
- uriList.append(fileUrl);
+ if (webfile.size() == 0
+ || webfile.size() > 1e+9) { // limit file size to 1 GB
+ qWarning() << "Something happened, File size is" << webfile.size();
+ continue;
+ }
+ QByteArray fileContent(webfile.size(), Qt::Uninitialized);
+ QString mimeFormat = QString::fromStdString(webfile.type());
+ QString fileName = QString::fromStdString(webfile.name());
+
+ // there's a file, now read it
+ webfile.stream(fileContent.data(), [=]() {
+ QList<QUrl> fileUriList;
+ if (!fileContent.isEmpty()) {
+ if (mimeFormat.contains("image/")) {
+ QImage image;
+ image.loadFromData(fileContent, nullptr);
+ resultMimeData->setImageData(image);
+ } else {
+ QUrl fileUrl(QStringLiteral("file:///") +
+ QString::fromStdString(webfile.name()));
+ fileUriList.append(fileUrl);
+ QFile file(fileName);
+ if (!file.open(QFile::WriteOnly)) {
+ qWarning() << "File was not opened";
+ return;
+ }
+
+ if (file.write(fileContent) < 0)
+ qWarning() << "Write failed";
+
+ file.close();
+ resultMimeData->setUrls(fileUriList);
+ }
+ callback(*resultMimeData);
+ }
+ });
+
break;
}
case ItemKind::String:
@@ -131,9 +169,15 @@ QMimeData *DataTransfer::toMimeDataWithFile()
}
break;
}
- }
- if (!uriList.isEmpty())
+ } // end items
+
+ if (!uriList.isEmpty()) {
resultMimeData->setUrls(uriList);
+ }
+
+ if (resultMimeData->formats().length() > 0)
+ callback(*resultMimeData);
+
return resultMimeData;
}
diff --git a/src/plugins/platforms/wasm/qwasmdom.h b/src/plugins/platforms/wasm/qwasmdom.h
index 3ccafba534c..37c7bc97f13 100644
--- a/src/plugins/platforms/wasm/qwasmdom.h
+++ b/src/plugins/platforms/wasm/qwasmdom.h
@@ -15,13 +15,14 @@
#include <memory>
#include <string>
+#include <QMimeData>
QT_BEGIN_NAMESPACE
namespace qstdweb {
struct CancellationFlag;
}
-class QMimeData;
+
class QPoint;
class QRect;
@@ -35,7 +36,7 @@ struct DataTransfer
DataTransfer &operator=(const DataTransfer &other);
DataTransfer &operator=(DataTransfer &&other);
- QMimeData *toMimeDataWithFile() ;
+ QMimeData *toMimeDataWithFile(std::function<void(QMimeData &)> callback);
QMimeData *toMimeDataPreview();
void setDragImage(emscripten::val element, const QPoint &hotspot);
void setData(std::string format, std::string data);
diff --git a/src/plugins/platforms/wasm/qwasmdrag.cpp b/src/plugins/platforms/wasm/qwasmdrag.cpp
index 82f225158c8..b765fe8268d 100644
--- a/src/plugins/platforms/wasm/qwasmdrag.cpp
+++ b/src/plugins/platforms/wasm/qwasmdrag.cpp
@@ -14,6 +14,7 @@
#include <QtCore/qeventloop.h>
#include <QtCore/qmimedata.h>
#include <QtCore/qtimer.h>
+#include <QFile>
#include <functional>
#include <string>
@@ -152,22 +153,31 @@ void QWasmDrag::onNativeDrop(DragEvent *event)
const QPointF pointInTargetWindowCoords = event->targetWindow->mapFromGlobal(pointInQtScreen);
const Qt::DropActions actions = m_dragState
- ? m_dragState->drag->supportedActions()
- : (Qt::DropAction::CopyAction | Qt::DropAction::MoveAction
- | Qt::DropAction::LinkAction);
-
- auto dropResponse = std::make_shared<QPlatformDropQtResponse>(true, Qt::DropAction::CopyAction);
- QMimeData *data = event->dataTransfer.toMimeDataWithFile();
- *dropResponse = QWindowSystemInterface::handleDrop(event->targetWindow, data,
- pointInTargetWindowCoords.toPoint(), actions,
- event->mouseButton, event->modifiers);
-
- if (dropResponse->isAccepted()) {
- event->acceptDrop();
- event->dataTransfer.setDropAction(dropResponse->acceptedAction());
-
- m_dragState->dropAction = dropResponse->acceptedAction();
- }
+ ? m_dragState->drag->supportedActions()
+ : (Qt::DropAction::CopyAction | Qt::DropAction::MoveAction
+ | Qt::DropAction::LinkAction);
+ Qt::MouseButton mouseButton = event->mouseButton;
+ QFlags<Qt::KeyboardModifier> modifiers = event->modifiers;
+
+ const auto pointerCallback = std::function([&, wasmWindow, pointInTargetWindowCoords,
+ actions, mouseButton, modifiers](QMimeData &data) {
+ if (data.formats().count() == 0)
+ return;
+ auto dropResponse = std::make_shared<QPlatformDropQtResponse>(true, Qt::DropAction::CopyAction);
+
+ *dropResponse = QWindowSystemInterface::handleDrop(wasmWindow->window(), &data,
+ pointInTargetWindowCoords.toPoint(), actions,
+ mouseButton, modifiers);
+
+ if (dropResponse->isAccepted()) {
+// event->acceptDrop(); // boom
+// event->dataTransfer.setDropAction(dropResponse->acceptedAction());
+
+ m_dragState->dropAction = dropResponse->acceptedAction();
+ }
+ });
+
+ event->dataTransfer.toMimeDataWithFile(pointerCallback);
}
void QWasmDrag::onNativeDragFinished(DragEvent *event)