Skip to content
Snippets Groups Projects
Verified Commit f8d8353c authored by Burak Hançerli's avatar Burak Hançerli :headphones:
Browse files

fix: trying to migrate qt6.6

parent 62c89ac7
No related branches found
No related tags found
1 merge request!10QDS-11148 Test with Qt 6.6 and EMSKD 3.1.37
Pipeline #65150 passed
......@@ -8,62 +8,19 @@ Qt Design Viewer works in a variety of web browsers which support WebAssembly, o
## Prerequisites
* CMake 3.16 or newer
* Android
* Qt6.5.0 or newer
* OpenSSL (<https://github.com/KDAB/android_openssl>)
* Android SDK and NDK (<https://developer.android.com/studio>)
* WebAssembly
* Qt6.4.3 or newer
* EMSDK (<https://emscripten.org/docs/getting_started/downloads.html>)
## Building
Build instructions are provided for Linux, macOS hosts and for Android and WebAssembly targets. Windows should work as well but is not tested.
> Note:
> Note 1:
> Build instructions are provided for Linux, macOS hosts and for WebAssembly target. Windows should work as well but is not tested.
>
> Note 2:
> If you're building in a Docker container and you've mounted the source directory into the container, you may need to change the build path pointing out somewhere out of the source directory. Otherwise you may get errors like the following;
> `CMake Error at /opt/qt-v.6.5.0/android-arm64-v8a/lib/cmake/Qt6/QtSyncQtHelpers.cmake:235 (message): syncqt.cpp failed for module QtQuickStudioApplication: Unable to remove file ...`
### Android
> Note:
> Android build instructions can also be used on desktop (or host) for testing purposes. Just replace the `CMAKE_TOOLCHAIN_FILE` path with the path to your Qt host installation.
First build and install QtQuickDesigner Components for Android:
```bash
cd qtquickdesigner-components
cmake \
-S . \
-B build \
-G Ninja \
-DCMAKE_TOOLCHAIN_FILE=<qt-android-path>/lib/cmake/Qt6/qt.toolchain.cmake \
-DCMAKE_INSTALL_PREFIX=<qt-android-path> \
-DANDROID_SDK_ROOT=<android-sdk-path> \
-DANDROID_NDK_ROOT=<android-sdk-path>/ndk/<ndk-version> \
-DANDROID_OPENSSL_PATH=<openssl-path>
cmake --build build
cmake --install build
cd ..
```
Then build the Qt Design Viewer:
```bash
cmake \
-S . \
-B build \
-G Ninja \
-DCMAKE_TOOLCHAIN_FILE=<qt-android-path>/lib/cmake/Qt6/qt.toolchain.cmake \
-DANDROID_SDK_ROOT=<android-sdk-path> \
-DANDROID_NDK_ROOT=<android-sdk-path>/ndk/<ndk-version> \
-DANDROID_OPENSSL_PATH=<openssl-path>
cmake --build build
```
### WebAssembly
First activate the correct EMSDK version:
```bash
......@@ -82,8 +39,9 @@ cmake \
-S . \
-B build \
-G Ninja \
-DCMAKE_TOOLCHAIN_FILE=<qt-wasm-path>/wasm/lib/cmake/Qt6/qt.toolchain.cmake \
-DCMAKE_INSTALL_PREFIX=<qt-wasm-path>
-DCMAKE_PREFIX_PATH=<qt-wasm-path> \
-DCMAKE_INSTALL_PREFIX=<qt-wasm-path> \
-DCMAKE_TOOLCHAIN_FILE=<qt-wasm-path>/wasm/lib/cmake/Qt6/qt.toolchain.cmake
cmake --build build
cmake --install build
......@@ -97,6 +55,8 @@ cmake \
-S . \
-B build \
-G Ninja \
-DCMAKE_PREFIX_PATH=<qt-wasm-path> \
-DCMAKE_INSTALL_PREFIX=<qt-wasm-path> \
-DCMAKE_TOOLCHAIN_FILE=<qt-wasm-path>/wasm/lib/cmake/Qt6/qt.toolchain.cmake
cmake --build build
......
Subproject commit 0e457477d54b068abc89cf124daedefe0436dd89
Subproject commit 55dfd50975935efbe67ea8cdb77ac01e4640db88
resources/dvicon-new.png

39 KiB

......@@ -24,9 +24,9 @@
****************************************************************************/
#include "designviewer.h"
#if defined(Q_OS_WASM)
#include <emscripten.h>
#include <emscripten/val.h>
#include <functional>
#include <QBuffer>
......@@ -38,6 +38,7 @@
#include <QResource>
#include <QTemporaryDir>
#include <QTemporaryFile>
#include <QTimer>
#include <QtCore/private/qzipreader_p.h>
#define printErr(x) printError(x, __FILE_NAME__, __LINE__)
......@@ -56,55 +57,29 @@ extern "C" EMSCRIPTEN_KEEPALIVE void qt_callSetFileData(char *content,
DesignViewer::DesignViewer()
{
printLog("DesignViewer constructor");
QString projectFileName;
QByteArray projectData;
printLog("Fetching project");
fetchProject(&projectData, &projectFileName);
if (!runProject(projectData, projectFileName))
printError("Failed to run project", projectFileName, 0);
printLog("Running project");
if (!runProject(projectData, projectFileName)) {
printErr("Failed to run project");
}
printLog("DesignViewer constructor done");
}
void DesignViewer::fetchProject(QByteArray *data, QString *fileName)
{
// Call qt_callSetFileData to make sure the emscripten linker does not
// optimize it away, which may happen if the function is called from JavaScript
// only. Set g_setFileDataCallback to null to make it a no-op.
::g_setFileDataCallback = nullptr;
::qt_callSetFileData(nullptr, 0, nullptr);
auto setFileDataCallback =
[data, fileName](char *content, size_t contentSize, char *projectFilename)
{
data->setRawData(content, contentSize);
*fileName = QString::fromUtf8(projectFilename);
};
g_setFileDataCallback = setFileDataCallback;
EM_ASM_({
// Copy the file file content to the C++ heap.
// Note: this could be simplified by passing the content as an
// "array" type to ccall and then let it copy to C++ memory.
// However, this built-in solution does not handle files larger
// than ~15M (Chrome). Instead, allocate memory manually and
// pass a pointer to the C++ side (which will free() it when done).
// TODO: consider slice()ing the file to read it picewise and
// then assembling it in a QByteArray on the C++ side.
const contentSize = contentArray.byteLength;
const heapPointer = _malloc(contentSize);
const heapBytes = new Uint8Array(Module.HEAPU8.buffer, heapPointer, contentSize);
heapBytes.set(contentArray);
// Null out the first data copy to enable GC
reader = null;
contentArray = null;
// Call the C++ file data ready callback
ccall("qt_callSetFileData",
null,
[ "number", "number", "string" ],
[ heapPointer, contentSize, projectfileName ]);
});
printLog("Init project data");
// Access global variables set by index.html
emscripten::val jsData = emscripten::val::global("contentArray");
emscripten::val jsFileName = emscripten::val::global("projectfileName");
printLog("Copying project data");
// Copy project data to the C++ heap and convert string
*data = QByteArray::fromEcmaUint8Array(jsData);
*fileName = QString::fromStdString(jsFileName.as<std::string>());
}
QString DesignViewer::unpackProject(const QByteArray &project, bool extractZip)
......@@ -385,10 +360,27 @@ void DesignViewer::showAppWindow()
{
printLog("Resizing the QML app window");
const QSize size;
const QString command = QString::fromLatin1("setScreenSize(%1, %2);").arg(size.width()).arg(size.height());
emscripten_run_script(command.toUtf8());
emscripten::val qtContainer = emscripten::val::global("container"); // global from index.html
emscripten::val qtContainerStyle = qtContainer["style"];
if (size.isEmpty()) {
qtContainerStyle.set("width", std::string("100%"));
qtContainerStyle.set("height",
std::string(
"100%")); // ### FIXME: 100% height gives 0px height for some reason
} else {
qtContainerStyle.set("width", QString("%1px").arg(size.width()).toStdString());
qtContainerStyle.set("height", QString("%1px").arg(size.height()).toStdString());
}
// Make Qt pick up the new container size by calling the resizeCanvasElement()
// qtloader API. This needs to be done on delay after initial setup to make
// sure qtloader is initialized.
QTimer::singleShot(0, [qtContainer]() {
emscripten::val qtLoader = emscripten::val::global("qtLoader");
qtLoader.call<void>("resizeCanvasElement", qtContainer);
});
printLog("Showing the QML app window");
m_quickWindow->show();
}
#endif // Q_OS_WASM
......@@ -55,6 +55,7 @@
<div id="title">Qt Design Viewer</div>
<div id="subtitle" class="subtitleclass">Powered by WebAssembly</div>
<div id="qtstatus"></div>
<div id="screen"></div>
<noscript
>JavaScript is disabled. Please enable JavaScript to use this
application.</noscript
......@@ -119,10 +120,11 @@
</div>
<canvas
id="qtcanvas"
id="qtcontainer"
oncontextmenu="event.preventDefault()"
contenteditable="true"
></canvas>
<!-- <div id="qtcontainer"></div> -->
<div id="footer">
<div id="alertBox" class="alert">
<span
......@@ -148,7 +150,7 @@
</p>
<p id="versioninfo_main">Version: 1.0.0</p>
</div>
<script src="qtdesignviewer.js"></script>
<script src="scripts/script.js" type="text/javascript"></script>
<script src="qtloader.js" type="text/javascript"></script>
</body>
......
var contentArray;
var projectfileName;
var reader;
var spinner = document.querySelector("#qtspinner");
var canvas = document.querySelector("#qtcanvas");
var canvas = document.querySelector("#qtcontainer");
var uploadform = document.querySelector("#uploadform");
var fileinput = document.querySelector("#fileinput");
var dropzone = document.querySelector("#dropzone");
......@@ -210,46 +210,57 @@ function restart() {
qtLoader.loadEmscriptenModule("qtdesignviewer");
}
function loadProjector() {
qtLoader = QtLoader({
canvasElements: [canvas],
showLoader: function (loaderStatus) {
spinner.style.display = "block";
canvas.style.display = "none";
if (loaderStatus === "Downloading/Compiling")
loaderStatus = "Starting";
launchstatustext.innerHTML = loaderStatus;
},
showError: function (errorText) {
launchstatustext.innerHTML = errorText;
spinner.style.display = "block";
canvas.style.display = "none";
},
showExit: function () {
launchstatustext.innerHTML = "Application exit";
if (qtLoader.exitCode !== undefined)
launchstatustext.innerHTML += " with code " + qtLoader.exitCode;
if (qtLoader.exitText !== undefined)
launchstatustext.innerHTML += " (" + qtLoader.exitText + ")";
spinner.style.display = "block";
canvas.style.display = "none";
},
showCanvas: function () {
spinner.style.display = "none";
canvas.style.display = "block";
launchstatus.style.display = "none";
appheader.style.display = "block";
},
});
async function loadProjector() {
// workaround for making sure that self.module is set up before
// running setScreenSize
self.moduleConfig = {};
self.moduleConfig.preRun = [];
self.moduleConfig.preRun.push(function (module) {
self.module = module;
});
qtLoader.loadEmscriptenModule("qtdesignviewer");
const spinner = document.querySelector("#qtspinner");
const screen = document.querySelector('#screen');
const status = document.querySelector('#qtstatus');
const showUi = (ui) => {
[spinner, screen].forEach(element => element.style.display = 'none');
if (screen === ui)
screen.style.position = 'default';
ui.style.display = 'block';
console.log("showUi", ui);
}
try {
showUi(spinner);
status.innerHTML = 'Loading...';
const instance = await qtLoad({
qt: {
onLoaded: () => showUi(screen),
onExit: exitData => {
status.innerHTML = 'Application exit';
status.innerHTML +=
exitData.code !== undefined ? ` with code ` : '';
status.innerHTML +=
exitData.text !== undefined ? ` ()` : '';
showUi(spinner);
},
entryFunction: window.createQtAppInstance,
containerElements: [screen]
}
}).then((result) => {
qtLoader = result;
console.log("qtLoader", qtLoader);
setScreenSize(window.innerWidth, window.innerHeight);
}).catch((err) => {
console.error(err);
console.error(err.stack);
});
} catch (e) {
console.error(e);
console.error(e.stack);
}
}
function setScreenSize(width, height) {
......@@ -264,5 +275,7 @@ function setScreenSize(width, height) {
document.documentElement.style.overflow =
document.body.style.overflow = "hidden";
}
console.log("setScreenSize", width, height);
console.log("current qtloader object:", qtLoader);
qtLoader.resizeCanvasElement(canvas);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment