Qaterial icon indicating copy to clipboard operation
Qaterial copied to clipboard

Qaterial Online - Import "externalFile.qml"

Open jetrotal opened this issue 2 years ago • 2 comments

Hi, Is there a good way to import external QML files into Qaterial/QML Online environments? the Import "http://fileaddress/filename.qml" syntax freezes the page.

I wrote those functions that work on QML Online, but not on Qaterial Online:

 property var importedObjects:({})
    property var timeStamp: "?"+new Date().getTime() // timestamp is helpful to avoid clearing the browser's cache every time a file is edited

    function _Timer() {
        return Qt.createQmlObject("import QtQuick 2.0; Timer {}", app);
    }

    function injectQML(target, name, file, properties) {
        file = file + timeStamp

        var i = 0
        var newComponent = Qt.createComponent(file);

        var timer = new _Timer(); timer.interval = 1, timer.repeat = true, timer.start();

        timer.triggered.connect(function () {
            i++;
            var status = isOBJloaded(newComponent, target,i);

            if (status !=="loading") {
                timer.destroy();

                importedObjects[name] = status;
                for (var a in properties) importedObjects[name][a] = properties[a];
            };
        })
    }


    function isOBJloaded(obj, target,i=0) {
        if (obj.status !== Component.Ready) return "loading";

        console.log("it took "+i+ (i === 1 ? " try ":" tries ") +"to load")
        return obj.createObject(target)
    }

    function destroyLastObject() {
        var lastObjectName = Object.keys(importedObjects)[Object.keys(importedObjects).length - 1]

        if (!importedObjects[lastObjectName]) return

        importedObjects[lastObjectName].destroy()
        delete importedObjects[lastObjectName]
    }

I call them like this:

Button {
            text:"run injectQML( parent, name, file, {properties} )"

            onPressed: {
                var randomColor = Math.floor(16777215 * Math.random()).toString(16)
                var newObject = {
                    name:"rectangle_"+ randomColor,
                    source:"https://jetrotal.github.io/easyRPG_UI/scripts/qml/components/rectangleTest.qml",
                    parent:headerMainContainer
                }

                newObject.properties = {
                    "color": "#" + randomColor,
                    "text": newObject.name
                }

                app.injectQML(newObject.parent, newObject.name,newObject.source ,newObject.properties);
            }
        }

        Button {
            text:"Destroy Last Imported Object"

            onPressed: destroyLastObject();
        }

It kinda do it's job, but the code is too messy, and i'd have to place the same lines of code on every file that depends on an external QML.

Thanks in advance, BTW you made some amazing fixes on Qaterial Online Issues, would be nice to push them into the Official QML Online Repo, on GitLabs too.

jetrotal avatar Jan 06 '22 15:01 jetrotal

I guess this might have something to do with the emscripten version used? or threading support? I have to admit this is quite obscur to me and I never really digged much in qt for wasm. Docker used for building : https://github.com/OlivierLDff/QtWasmCMakeDocker/blob/main/Dockerfile So you can see I'm using madmanfred/qt-webassembly/qt5.15-em1.39.8 and qmlonline seems to use madmanfred/qt-webassembly:qt5.15-em1.39.10-remoteobjects. Maybe difference is coming from there.

OlivierLDff avatar Jan 06 '22 15:01 OlivierLDff

the Ideal scenario would be to have the syntax Import "http://fileaddress/filename.qml"
working out of the box with both editors. Since it works on neither

People have been speculating if this is a CORS policy issue, since the Import works with internal libraries, Like Import Qaterial or Import Kirigami

jetrotal avatar Jan 06 '22 15:01 jetrotal