Question

I have main.qml and dynamic.qml files that i want to load dynamic.qml on main.qml using Loader {}.
Content of dynamic.qml file is dynamic and another program may change its content and overwrite it. So i wrote some C++ code for detecting changes on file and fires Signal.
My problem is that I don't know how can i force Loader to reload file.

This is my current work:

MainController {
    id: mainController
    onInstallationHelpChanged: {
        helpLoader.source = "";
        helpLoader.source = "../dynamic.qml";
    }
}

Loader {
    id: helpLoader

    anchors.fill: parent
    anchors.margins: 60
    source: "../dynamic.qml"
}



I think that QML Engine caches dynamic.qml file. So whenever I want to reload Loader, it shows old content. Any suggestion?

Was it helpful?

Solution

You need to call trimComponentCache() on QQmlEngine after you have set the Loaders source property to an empty string. In other words:

helpLoader.source = "";
// call trimComponentCache() here!!!
helpLoader.source = "../dynamic.qml";

In order to do that, you'll need to expose some C++ object to QML which has a reference to your QQmlEngine (lots of examples in Qt and on StackOverflow to help with that).

trimComponentCache tells QML to forget about all the components it's not current using and does just what you want.

Update - explaining in a bit more detail:

For example, somewhere you define a class that takes a pointer to your QQmlEngine and exposes the trimComponentCache method:

class ComponentCacheManager : public QObject {
    Q_OBJECT
public:
    ComponentCacheManager(QQmlEngine *engine) : engine(engine) { }

    Q_INVOKABLE void trim() { engine->trimComponentCache(); }

private:
    QQmlEngine *engine;
};

Then when you create your QQuickView, bind one of the above as a context property:

QQuickView *view = new QQuickView(...);
...
view->rootContext()->setContextProperty(QStringLiteral("componentCache", new ComponentCacheManager(view->engine());

Then in your QML you can do something like:

helpLoader.source = "";
componentCache.trim();
helpLoader.source = "../dynamic.qml";

OTHER TIPS

I was hoping for a pure QML solution. I noticed that loader.source is a url (file:///) and remembered how with HTML, you can avoid HTTP caching using ?t=Date.now() in your requests. Tried adding ?t=1234 to the end of loader.source, and sure enough, it works.

import QtQuick 2.0

Item {
    Loader {
        id: loader
        anchors.fill: parent
        property string filename: "User.qml"
        source: filename

        function reload() {
            source = filename + "?t=" + Date.now()
        }
    }

    Timer {
        id: reloadTimer
        interval: 2000
        repeat: true
        running: true
        onTriggered: {
            loader.reload();
        }
    }
}

I also wrote another example that will check for changes in the file contents before triggering a reload using an XMLHttpRequest.

import QtQuick 2.0

Item {
    Loader {
        id: loader
        anchors.fill: parent
        property string filename: "AppletUser.qml"
        property string fileContents: ""
        source: ""

        function reload() {
            source = filename + "?t=" + Date.now()
        }

        function checkForChange() {
            var req = new XMLHttpRequest();
            req.onreadystatechange = function() {
                if (req.readyState === 4) {
                    if (loader.fileContents != req.responseText) {
                        loader.fileContents = req.responseText;
                        loader.reload();
                    }
                }
            }
            req.open("GET", loader.filename, true);
            req.send();
        }

        onLoaded: {
            console.log(source)
        }

        Timer {
            id: reloadTimer
            interval: 2000
            repeat: true
            running: true
            onTriggered: loader.checkForChange()
        }

        Component.onCompleted: {
            loader.checkForChange()
        }
    }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top