diff options
Diffstat (limited to 'src/corelib')
| -rw-r--r-- | src/corelib/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/corelib/Qt6AndroidGradleHelpers.cmake | 2 | ||||
| -rw-r--r-- | src/corelib/doc/images/modelindex-no-parent.svg | 99 | ||||
| -rw-r--r-- | src/corelib/doc/src/cmake/cmake-properties.qdoc | 4 | ||||
| -rw-r--r-- | src/corelib/itemmodels/qabstractitemmodel.cpp | 2 | ||||
| -rw-r--r-- | src/corelib/kernel/qeventdispatcher_wasm.cpp | 12 | ||||
| -rw-r--r-- | src/corelib/kernel/qeventdispatcher_wasm_p.h | 2 | ||||
| -rw-r--r-- | src/corelib/platform/wasm/qwasmlocalfileengine.cpp | 422 | ||||
| -rw-r--r-- | src/corelib/platform/wasm/qwasmlocalfileengine_p.h | 102 | ||||
| -rw-r--r-- | src/corelib/platform/wasm/qwasmsuspendresumecontrol.cpp | 7 | ||||
| -rw-r--r-- | src/corelib/platform/wasm/qwasmsuspendresumecontrol_p.h | 10 |
11 files changed, 656 insertions, 7 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index 539ad753ca6..e50838730cb 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -1533,6 +1533,7 @@ qt_internal_extend_target(Core CONDITION WASM platform/wasm/qstdweb.cpp platform/wasm/qstdweb_p.h platform/wasm/qwasmsocket.cpp platform/wasm/qwasmsocket_p.h platform/wasm/qwasmsuspendresumecontrol.cpp platform/wasm/qwasmsuspendresumecontrol_p.h + platform/wasm/qwasmlocalfileengine.cpp platform/wasm/qwasmlocalfileengine_p.h kernel/qeventdispatcher_wasm.cpp kernel/qeventdispatcher_wasm_p.h ) diff --git a/src/corelib/Qt6AndroidGradleHelpers.cmake b/src/corelib/Qt6AndroidGradleHelpers.cmake index f71bac4e08a..fc8e009b9da 100644 --- a/src/corelib/Qt6AndroidGradleHelpers.cmake +++ b/src/corelib/Qt6AndroidGradleHelpers.cmake @@ -193,7 +193,7 @@ function(_qt_internal_android_generate_target_build_gradle target) QT_ANDROID_MIN_SDK_VERSION "28") _qt_internal_android_get_gradle_property(target_sdk_version ${target} - QT_ANDROID_TARGET_SDK_VERSION "34") + QT_ANDROID_TARGET_SDK_VERSION "36") set(target_abis "$<TARGET_PROPERTY:${target},_qt_android_abis>") set(target_abi_list "$<JOIN:${target_abis};${CMAKE_ANDROID_ARCH_ABI},'$<COMMA> '>") diff --git a/src/corelib/doc/images/modelindex-no-parent.svg b/src/corelib/doc/images/modelindex-no-parent.svg new file mode 100644 index 00000000000..4ce4b86b1f2 --- /dev/null +++ b/src/corelib/doc/images/modelindex-no-parent.svg @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="300" + height="160" + version="1.1" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg"> + +<style> + svg .line-style { stroke: black; fill: none } + svg .fill-style { stroke: black; fill: #c0c0c0 } + svg .text-style { font: 12px arial; fill: black } + svg .italic-style { font: 12px arial; fill: black; font-style: italic } + svg .bold-style { font: 12px arial; fill: black; font-weight: bold } + + svg.dark .line-style { stroke: #f2f2f2; fill: none } + svg.dark .fill-style { stroke: #f2f2f2; fill: #606060 } + svg.dark .text-style { font: 12px arial; fill: #f2f2f2 } + svg.dark .italic-style { font: 12px arial; fill: #f2f2f2; font-style: italic } + svg.dark .bold-style { font: 12px arial; fill: #f2f2f2; font-weight: bold } + + [data-theme="dark"] svg .line-style { stroke: #f2f2f2; fill: none } + [data-theme="dark"] svg .fill-style { stroke: #f2f2f2; fill: #606060 } + [data-theme="dark"] svg .text-style { font: 12px arial; fill: #f2f2f2 } + [data-theme="dark"] svg .italic-style { font: 12px arial; fill: #f2f2f2; font-style: italic } + [data-theme="dark"] svg .bold-style { font: 12px arial; fill: #f2f2f2; font-weight: bold } + + [data-theme="light"] svg .line-style { stroke: black; fill: none } + [data-theme="light"] svg .fill-style { stroke: black; fill: #c0c0c0 } + [data-theme="light"] svg .text-style { font: 12px arial; fill: black } + [data-theme="light"] svg .italic-style { font: 12px arial; fill: black; font-style: italic } + [data-theme="light"] svg .bold-style { font: 12px arial; fill: black; font-weight: bold } +</style> + +<text x="25" y="49" font-family="arial" font-size="12px" + class="text-style">0</text> +<text x="25" y="79" font-family="arial" font-size="12px" + class="text-style">1</text> +<text x="25" y="109" font-family="arial" font-size="12px" + class="text-style">2</text> +<g transform="translate(30,139)"> +<text x="0" y="0" font-family="arial" font-size="12px" + class="text-style" transform="rotate(270)">...</text> +</g> + +<path d="m 40.5,30.5 h 30 v 30 h -30 z" stroke="black" fill="none" + class="line-style" /> +<path d="m 70.5,30.5 h 30 v 30 h -30 z" stroke="black" fill="none" + class="line-style" /> +<path d="m 100.5,30.5 h 30 v 30 h -30 z" stroke="black" fill="none" + class="line-style" /> +<path d="m 130.5,30.5 h 30 v 30" stroke="black" fill="none" + class="line-style" stroke-dasharray="3, 3" /> +<path d="m 40.5,60.5 h 30 v 30 h -30 z" stroke="black" fill="none" + class="line-style" /> +<path d="m 70.5,60.5 h 30 v 30 h -30 z" stroke="black" fill="none" + class="line-style" /> +<path d="m 100.5,60.5 h 30 v 30 h -30 z" stroke="black" fill="#c0c0c0" + class="fill-style" /> +<path d="m 130.5,60.5 h 30 v 30 h -30 z" stroke="black" fill="none" + class="line-style" stroke-dasharray="3, 3" /> +<path d="m 40.5,90.5 h 30 v 30 h -30 z" stroke="black" fill="none" + class="line-style" /> +<path d="m 70.5,90.5 h 30 v 30 h -30 z" stroke="black" fill="none" + class="line-style" /> +<path d="m 100.5,90.5 h 30 v 30 h -30 z" stroke="black" fill="none" + class="line-style" /> +<path d="m 70.5,120.5 h 30 v 30 h -30 z" stroke="black" fill="none" + class="line-style" stroke-dasharray="3, 3" /> +<path d="m 40.5,120.5 v 30 h 30" stroke="black" fill="none" + class="line-style" stroke-dasharray="3, 3" /> +<path d="m 100.5,150.5 h 30" stroke="black" + class="line-style" stroke-dasharray="3, 3" /> +<path d="m 130.5,120.5 h 30 v 30 h -30 z" stroke="black" fill="none" + class="line-style" stroke-dasharray="3, 3" /> +<path d="m 160.5,90.5 v 30" stroke="black" + class="line-style" stroke-dasharray="3, 3" /> + +<text x="50" y="20" font-family="arial" font-size="12px" + class="text-style">0</text> +<text x="80" y="20" font-family="arial" font-size="12px" + class="text-style">1</text> +<text x="110" y="20" font-family="arial" font-size="12px" + class="text-style">2</text> +<text x="140" y="20" font-family="arial" font-size="12px" + class="text-style">...</text> + +<text x="190" y="55" font-family="arial" font-size="12px" font-weight="bold" + class="bold-style">Model index</text> +<rect x="185.5" y="60.5" width="77" height="37" stroke="black" fill="none" + class="line-style" /> +<text x="190" y="75" font-family="arial" font-size="12px" + class="text-style">row = 1</text> +<text x="190" y="92" font-family="arial" font-size="12px" + class="text-style">column = 2</text> + +<path d="m 185.5,85.5 c -35,0 -35,-10 -70,-10" stroke="black" fill="none" + stroke-dasharray="2, 2" class="line-style" /> +</svg> diff --git a/src/corelib/doc/src/cmake/cmake-properties.qdoc b/src/corelib/doc/src/cmake/cmake-properties.qdoc index c7b1a27a4b4..310debf7edc 100644 --- a/src/corelib/doc/src/cmake/cmake-properties.qdoc +++ b/src/corelib/doc/src/cmake/cmake-properties.qdoc @@ -239,7 +239,7 @@ precedence over this CMake property. \badcode set_target_properties(${target} PROPERTIES - QT_ANDROID_COMPILE_SDK_VERSION 35 + QT_ANDROID_COMPILE_SDK_VERSION 36 ) \endcode @@ -247,7 +247,7 @@ The following format also works: \badcode set_target_properties(${target} PROPERTIES - QT_ANDROID_COMPILE_SDK_VERSION "android-35" + QT_ANDROID_COMPILE_SDK_VERSION "android-36" ) \endcode diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index 58a057009ff..8b0a05ee6ed 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -1390,7 +1390,7 @@ void QAbstractItemModel::resetInternalData() simple table of rows and columns. Each item has a unique index specified by a QModelIndex. - \image modelindex-no-parent.png {Screenshot showing a 3x3 grid with numbered + \image modelindex-no-parent.svg {Diagram showing a 3x3 grid with numbered rows and columns that shows the cell at row 1, column 2 highlighted.} Every item of data that can be accessed via a model has an associated model diff --git a/src/corelib/kernel/qeventdispatcher_wasm.cpp b/src/corelib/kernel/qeventdispatcher_wasm.cpp index f7edf3285f8..25a27a0c22b 100644 --- a/src/corelib/kernel/qeventdispatcher_wasm.cpp +++ b/src/corelib/kernel/qeventdispatcher_wasm.cpp @@ -150,6 +150,18 @@ bool QEventDispatcherWasm::isValidEventDispatcherPointer(QEventDispatcherWasm *e bool QEventDispatcherWasm::processEvents(QEventLoop::ProcessEventsFlags flags) { + // Accept the current event if event handling recurses / event loop is reentered, + // to prevent the browser from propagating it to other event handlers. + if (useAsyncify() && isMainThreadEventDispatcher()) { + auto control = QWasmSuspendResumeControl::get(); + auto currentEvent = control->currentEvent(); + if (!currentEvent.isUndefined() && currentEvent.instanceof(emscripten::val::global("Event"))) { + currentEvent.call<void>("preventDefault"); + currentEvent.call<void>("stopPropagation"); + control->setCurrentEvent(emscripten::val::undefined()); + } + } + emit awake(); if (!useAsyncify() && isMainThreadEventDispatcher()) diff --git a/src/corelib/kernel/qeventdispatcher_wasm_p.h b/src/corelib/kernel/qeventdispatcher_wasm_p.h index 674af85dac2..1946bf63ede 100644 --- a/src/corelib/kernel/qeventdispatcher_wasm_p.h +++ b/src/corelib/kernel/qeventdispatcher_wasm_p.h @@ -40,7 +40,6 @@ public: ~QEventDispatcherWasm(); bool processEvents(QEventLoop::ProcessEventsFlags flags) override; - bool sendAllEvents(QEventLoop::ProcessEventsFlags flag); void registerTimer(Qt::TimerId timerId, Duration interval, Qt::TimerType timerType, QObject *object) override final; @@ -69,6 +68,7 @@ protected: virtual bool sendPostedEvents(); private: + bool sendAllEvents(QEventLoop::ProcessEventsFlags flag); bool isMainThreadEventDispatcher(); bool isSecondaryThreadEventDispatcher(); bool isValidEventDispatcher(); diff --git a/src/corelib/platform/wasm/qwasmlocalfileengine.cpp b/src/corelib/platform/wasm/qwasmlocalfileengine.cpp new file mode 100644 index 00000000000..58e662d5fde --- /dev/null +++ b/src/corelib/platform/wasm/qwasmlocalfileengine.cpp @@ -0,0 +1,422 @@ +// Copyright (C) 2025 Qt Group +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#include "qwasmlocalfileengine_p.h" +#include <QtCore/QDebug> +#include <QtCore/QUrl> + +QT_BEGIN_NAMESPACE + +using namespace Qt::StringLiterals; + +// Custom URL scheme for files handled by this file engine. A complete file URL can +// look like +// +// "weblocalfile:/n/file.ext" +// +// where n is a counter to ensure uniqueness, needed since web platform gives us the file name only +// and does not provide the file path. +// +// The scheme may be visible to end users if the application displays it, so +// we avoid using "wasm" and instead say "web", which should be more recognizable. +static constexpr QLatin1StringView wasmlocalfileScheme = "weblocalfile"_L1; + +// Instantiate the engine, the system will pick it up automatically +// Never destroy it to avoid problems with static destruction. +// The OS will reclaim the memory anyway, +// TODO: cleanup on QApplication destruction and re-init on QApplication re-creation. +static QWasmFileEngineHandler *singleton = new QWasmFileEngineHandler(); + +QWasmFileEngineHandler::QWasmFileEngineHandler() +{ +} + +QWasmFileEngineHandler::~QWasmFileEngineHandler() +{ +} + +std::unique_ptr<QAbstractFileEngine> QWasmFileEngineHandler::create(const QString &fileName) const +{ + if (!QWasmFileEngineHandler::isWasmFileName(fileName)) + return {}; + + // Check if it's a File or FileSystemFileHandle + if (singleton->m_files.contains(fileName)) { + qstdweb::File file = singleton->m_files.value(fileName); + return std::make_unique<QWasmFileEngine>(fileName, file); + } else if (singleton->m_fileSystemFiles.contains(fileName)) { + qstdweb::FileSystemFileHandle file = singleton->m_fileSystemFiles.value(fileName); + return std::make_unique<QWasmFileEngine>(fileName, file); + } + + // Not an error, this function will be called with partial paths like "weblocalfile:/1/" + return {}; +} + +// Check if this is a wasm filename by checking the URL scheme. +bool QWasmFileEngineHandler::isWasmFileName(const QString& fileName) +{ + return QUrl(fileName).scheme() == wasmlocalfileScheme; +} + +// Creates a wasm filename using the custom URL scheme and a counter. +QString QWasmFileEngineHandler::makeWasmFileName(const QString &nativeFileName) +{ + static std::atomic<uint64_t> sid = 0; + const uint64_t id = ++sid; + return wasmlocalfileScheme + QStringLiteral(":/%1/%2").arg(id).arg(nativeFileName); +} + +// Extracts the native filename from the custom URL (removes scheme and counter). +QString QWasmFileEngineHandler::nativeFileName(const QString &wasmFileName) +{ + QUrl url(wasmFileName); + if (url.scheme() == wasmlocalfileScheme) { + QString path = url.path(); + // Path is "/n/filename", find the second '/' and extract the filename + const qsizetype idx = path.indexOf(u'/', 1); + if (idx != -1) + return path.mid(idx + 1); + } + return wasmFileName; +} + +// Adds a File to the set of open files. Returns a prefixed wasm file name. +QString QWasmFileEngineHandler::addFile(qstdweb::File file) +{ + QString nativeFileName = QString::fromStdString(file.name()); + QString wasmFileName = makeWasmFileName(nativeFileName); + singleton->m_files.insert(wasmFileName, file); + return wasmFileName; +} + +// Adds a FileSystemFileHandle to the set of open files. Returns a prefixed wasm file name. +QString QWasmFileEngineHandler::addFile(qstdweb::FileSystemFileHandle file) +{ + QString nativeFileName = QString::fromStdString(file.name()); + QString wasmFileName = makeWasmFileName(nativeFileName); + singleton->m_fileSystemFiles.insert(wasmFileName, file); + return wasmFileName; +} + +// Removes a File or FileSystemFileHandle from the set of open file handlers +void QWasmFileEngineHandler::removeFile(const QString fileName) +{ + singleton->m_files.remove(fileName); + singleton->m_fileSystemFiles.remove(fileName); +} + +qstdweb::File QWasmFileEngineHandler::getFile(const QString fileName) +{ + return singleton->m_files.value(fileName); +} + +qstdweb::FileSystemFileHandle QWasmFileEngineHandler::getFileSystemFile(const QString fileName) +{ + return singleton->m_fileSystemFiles.value(fileName); +} + +/*! + \class QWasmFileEngine + \brief The QWasmFileEngine class provides a QAbstractFileEngine + for files that has the prefix ':weblocalfile/'. +*/ + +// Constructs a QWasmFileEngine with a File for read-only access +QWasmFileEngine::QWasmFileEngine(const QString &fileName, qstdweb::File file) + : m_fileName(fileName), + m_blobDevice(std::make_unique<qstdweb::BlobIODevice>(file.slice(0, file.size()))) +{ + // TODO use m_blobDevice in unbuffered mode? if there is already a buffer higher up. +} + +// Constructs a QWasmFileEngine with a FileSystemFileHandle for read-write access +QWasmFileEngine::QWasmFileEngine(const QString &fileName, qstdweb::FileSystemFileHandle file) + : m_fileName(fileName), + m_fileDevice(std::make_unique<qstdweb::FileSystemFileIODevice>(file)) +{ + +} + +QWasmFileEngine::~QWasmFileEngine() +{ + close(); +} + +bool QWasmFileEngine::open(QIODevice::OpenMode openMode, std::optional<QFile::Permissions> permissions) +{ + Q_UNUSED(permissions); + m_openMode = openMode; + + if (m_fileDevice) + return m_fileDevice->open(openMode); + else if (m_blobDevice) + return m_blobDevice->open(openMode); + + return false; +} + +bool QWasmFileEngine::close() +{ + if (m_openMode == QIODevice::NotOpen) + return false; + + bool success = true; + if (m_fileDevice) { + m_fileDevice->close(); + } + if (m_blobDevice) { + m_blobDevice->close(); + } + + m_openMode = QIODevice::NotOpen; + return success; +} + +bool QWasmFileEngine::flush() +{ + return true; +} + +bool QWasmFileEngine::syncToDisk() +{ + return true; +} + +qint64 QWasmFileEngine::size() const +{ + if (m_fileDevice) + return m_fileDevice->size(); + if (m_blobDevice) + return m_blobDevice->size(); + return 0; +} + +qint64 QWasmFileEngine::pos() const +{ + if (m_fileDevice) + return m_fileDevice->pos(); + if (m_blobDevice) + return m_blobDevice->pos(); + return 0; +} + +bool QWasmFileEngine::seek(qint64 pos) +{ + if (m_fileDevice) + return m_fileDevice->seek(pos); + if (m_blobDevice) + return m_blobDevice->seek(pos); + return false; +} + +bool QWasmFileEngine::isSequential() const +{ + return false; +} + +bool QWasmFileEngine::remove() +{ + return false; +} + +bool QWasmFileEngine::copy(const QString &newName) +{ + Q_UNUSED(newName); + return false; +} + +bool QWasmFileEngine::rename(const QString &newName) +{ + Q_UNUSED(newName); + return false; +} + +bool QWasmFileEngine::renameOverwrite(const QString &newName) +{ + Q_UNUSED(newName); + return false; +} + +bool QWasmFileEngine::link(const QString &newName) +{ + Q_UNUSED(newName); + return false; +} + +bool QWasmFileEngine::mkdir(const QString &dirName, bool createParentDirectories, + std::optional<QFile::Permissions> permissions) const +{ + Q_UNUSED(dirName); + Q_UNUSED(createParentDirectories); + Q_UNUSED(permissions); + return false; +} + +bool QWasmFileEngine::rmdir(const QString &dirName, bool recurseParentDirectories) const +{ + Q_UNUSED(dirName); + Q_UNUSED(recurseParentDirectories); + return false; +} + +bool QWasmFileEngine::setSize(qint64 size) +{ + Q_UNUSED(size); + return false; +} + +bool QWasmFileEngine::caseSensitive() const +{ + return true; +} + +bool QWasmFileEngine::isRelativePath() const +{ + return false; +} + + +QAbstractFileEngine::FileFlags QWasmFileEngine::fileFlags(FileFlags type) const +{ + return type & (QAbstractFileEngine::FileFlag::ExistsFlag | + QAbstractFileEngine::FileFlag::FileType | + QAbstractFileEngine::FileFlag::ReadOwnerPerm | + QAbstractFileEngine::FileFlag::WriteOwnerPerm); +} + +bool QWasmFileEngine::setPermissions(uint perms) +{ + Q_UNUSED(perms); + return false; +} + +QByteArray QWasmFileEngine::id() const +{ + return {}; +} + +QString QWasmFileEngine::fileName(FileName file) const +{ + switch (file) { + case DefaultName: + case AbsoluteName: + case CanonicalName: + return m_fileName; + case BaseName: { + QString native = QWasmFileEngineHandler::nativeFileName(m_fileName); + QFileInfo info(native); + return info.fileName(); + } + case PathName: + case AbsolutePathName: + case CanonicalPathName: { + QString native = QWasmFileEngineHandler::nativeFileName(m_fileName); + QFileInfo info(native); + QString path = info.path(); + return path.isEmpty() ? "."_L1 : path; + } + default: + return QString(); + } +} + +uint QWasmFileEngine::ownerId(FileOwner) const +{ + return 0; +} + +QString QWasmFileEngine::owner(FileOwner) const +{ + return {}; +} + +bool QWasmFileEngine::setFileTime(const QDateTime &newDate, QFile::FileTime time) +{ + Q_UNUSED(newDate); + Q_UNUSED(time); + return false; +} + +QDateTime QWasmFileEngine::fileTime(QFile::FileTime time) const +{ + Q_UNUSED(time); + return {}; +} + +void QWasmFileEngine::setFileName(const QString &file) +{ + if (m_fileName == file) + return; + close(); + m_fileName = file; +} + +int QWasmFileEngine::handle() const +{ + return -1; +} + +QAbstractFileEngine::TriStateResult QWasmFileEngine::cloneTo(QAbstractFileEngine *target) +{ + Q_UNUSED(target); + return QAbstractFileEngine::TriStateResult::NotSupported; +} + +QAbstractFileEngine::IteratorUniquePtr QWasmFileEngine::beginEntryList(const QString &path, QDirListing::IteratorFlags filters, + const QStringList &filterNames) +{ + Q_UNUSED(path); + Q_UNUSED(filters); + Q_UNUSED(filterNames); + return nullptr; +} + +qint64 QWasmFileEngine::read(char *data, qint64 maxlen) +{ + if (!(m_openMode & QIODevice::ReadOnly)) + return -1; + + if (m_fileDevice) + return m_fileDevice->read(data, maxlen); + if (m_blobDevice) + return m_blobDevice->read(data, maxlen); + return -1; +} + +qint64 QWasmFileEngine::readLine(char *data, qint64 maxlen) +{ + if (!(m_openMode & QIODevice::ReadOnly)) + return -1; + + if (m_fileDevice) + return m_fileDevice->readLine(data, maxlen); + if (m_blobDevice) + return m_blobDevice->readLine(data, maxlen); + return -1; +} + +qint64 QWasmFileEngine::write(const char *data, qint64 len) +{ + if (!(m_openMode & QIODevice::WriteOnly)) + return -1; + + if (m_fileDevice) + return m_fileDevice->write(data, len); + return -1; +} + +bool QWasmFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output) +{ + Q_UNUSED(extension); + Q_UNUSED(option); + Q_UNUSED(output); + return false; +} + +bool QWasmFileEngine::supportsExtension(Extension extension) const +{ + Q_UNUSED(extension); + return false; +} + +QT_END_NAMESPACE diff --git a/src/corelib/platform/wasm/qwasmlocalfileengine_p.h b/src/corelib/platform/wasm/qwasmlocalfileengine_p.h new file mode 100644 index 00000000000..dd82788dd90 --- /dev/null +++ b/src/corelib/platform/wasm/qwasmlocalfileengine_p.h @@ -0,0 +1,102 @@ +// Copyright (C) 2024 Qt Group +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#ifndef QWASMLOCALFILEENGINE_P_H +#define QWASMLOCALFILEENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/private/qabstractfileengine_p.h> +#include <QtCore/private/qstdweb_p.h> + +QT_BEGIN_NAMESPACE + +class QWasmFileEngine; + +class QWasmFileEngineHandler: public QAbstractFileEngineHandler +{ +public: + Q_DISABLE_COPY_MOVE(QWasmFileEngineHandler) + + QWasmFileEngineHandler(); + virtual ~QWasmFileEngineHandler() override; + virtual std::unique_ptr<QAbstractFileEngine> create(const QString &fileName) const override; + + static bool isWasmFileName(const QString& fileName); + static QString makeWasmFileName(const QString &fileName); + static QString nativeFileName(const QString &wasmFileName); + + static QString addFile(qstdweb::File file); + static QString addFile(qstdweb::FileSystemFileHandle file); + static void removeFile(const QString fileName); + qstdweb::File getFile(const QString fileName); + qstdweb::FileSystemFileHandle getFileSystemFile(const QString fileName); + +private: + QHash<QString, qstdweb::File> m_files; + QHash<QString, qstdweb::FileSystemFileHandle> m_fileSystemFiles; +}; + +class QWasmFileEngine: public QAbstractFileEngine +{ +public: + explicit QWasmFileEngine(const QString &fileName, qstdweb::File file); + explicit QWasmFileEngine(const QString &fileName, qstdweb::FileSystemFileHandle file); + ~QWasmFileEngine() override; + + virtual bool open(QIODevice::OpenMode openMode, std::optional<QFile::Permissions> permissions) override; + virtual bool close() override; + virtual bool flush() override; + virtual bool syncToDisk() override; + virtual qint64 size() const override; + virtual qint64 pos() const override; + virtual bool seek(qint64 pos) override; + virtual bool isSequential() const override; + virtual bool remove() override; + virtual bool copy(const QString &newName) override; + virtual bool rename(const QString &newName) override; + virtual bool renameOverwrite(const QString &newName) override; + virtual bool link(const QString &newName) override; + virtual bool mkdir(const QString &dirName, bool createParentDirectories, + std::optional<QFile::Permissions> permissions = std::nullopt) const override; + virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const override; + virtual bool setSize(qint64 size) override; + virtual bool caseSensitive() const override; + virtual bool isRelativePath() const override; + virtual FileFlags fileFlags(FileFlags type=FileInfoAll) const override; + virtual bool setPermissions(uint perms) override; + virtual QByteArray id() const override; + virtual QString fileName(FileName file = DefaultName) const override; + virtual uint ownerId(FileOwner) const override; + virtual QString owner(FileOwner) const override; + virtual bool setFileTime(const QDateTime &newDate, QFile::FileTime time) override; + virtual QDateTime fileTime(QFile::FileTime time) const override; + virtual void setFileName(const QString &file) override; + virtual int handle() const override; + virtual TriStateResult cloneTo(QAbstractFileEngine *target) override; + virtual IteratorUniquePtr beginEntryList(const QString &path, QDirListing::IteratorFlags filters, + const QStringList &filterNames) override; + virtual qint64 read(char *data, qint64 maxlen) override; + virtual qint64 readLine(char *data, qint64 maxlen) override; + virtual qint64 write(const char *data, qint64 len) override; + virtual bool extension(Extension extension, const ExtensionOption *option = nullptr, + ExtensionReturn *output = nullptr) override; + virtual bool supportsExtension(Extension extension) const override; + +private: + QString m_fileName; + QIODevice::OpenMode m_openMode = QIODevice::NotOpen; + std::unique_ptr<qstdweb::BlobIODevice> m_blobDevice; + std::unique_ptr<qstdweb::FileSystemFileIODevice> m_fileDevice; +}; + +QT_END_NAMESPACE +#endif // QWASMFILEENGINEHANDLER_H diff --git a/src/corelib/platform/wasm/qwasmsuspendresumecontrol.cpp b/src/corelib/platform/wasm/qwasmsuspendresumecontrol.cpp index a4bc7843380..85358d1daf4 100644 --- a/src/corelib/platform/wasm/qwasmsuspendresumecontrol.cpp +++ b/src/corelib/platform/wasm/qwasmsuspendresumecontrol.cpp @@ -225,8 +225,11 @@ int QWasmSuspendResumeControl::sendPendingEvents() pendingEvents.call<void>("splice", i, 1); auto it = m_eventHandlers.find(event["index"].as<int>()); - if (it != m_eventHandlers.end()) - it->second(event["arg"]); + if (it != m_eventHandlers.end()) { + setCurrentEvent(event["arg"]); + it->second(currentEvent()); + setCurrentEvent(emscripten::val::undefined()); + } ++count; } } diff --git a/src/corelib/platform/wasm/qwasmsuspendresumecontrol_p.h b/src/corelib/platform/wasm/qwasmsuspendresumecontrol_p.h index ff97ff3d7ea..4e75d5674be 100644 --- a/src/corelib/platform/wasm/qwasmsuspendresumecontrol_p.h +++ b/src/corelib/platform/wasm/qwasmsuspendresumecontrol_p.h @@ -42,12 +42,22 @@ public: void suspendExclusive(QList<uint32_t> eventHandlerIndices); int sendPendingEvents(); + emscripten::val currentEvent() const + { + return m_currentEvent; + } + void setCurrentEvent(emscripten::val currentEvent) + { + m_currentEvent = currentEvent; + } + private: friend void qtSendPendingEvents(); static QWasmSuspendResumeControl *s_suspendResumeControl; std::map<int, std::function<void(emscripten::val)>> m_eventHandlers; std::function<bool(int)> m_eventFilter = [](int) { return true; }; + emscripten::val m_currentEvent = emscripten::val::undefined(); }; class Q_CORE_EXPORT QWasmEventHandler |
