Skip to content

Instantly share code, notes, and snippets.

@nrbnlulu
Last active May 27, 2024 16:50
Show Gist options
  • Save nrbnlulu/195bdf87138bfc57b99a56ee63a53277 to your computer and use it in GitHub Desktop.
Save nrbnlulu/195bdf87138bfc57b99a56ee63a53277 to your computer and use it in GitHub Desktop.
QML live-reload
#include <QFileSystemWatcher>
#include <QQmlApplicationEngine>
#include <QTimer>
#include <QUrl>
#include <QDirIterator>
void init_live_reload(QQmlApplicationEngine *engine, const QString &path) {
auto *fs_watcher = new QFileSystemWatcher(engine);
QDirIterator it(path, QDirIterator::Subdirectories);
while (it.hasNext()) {
it.next();
auto i = it.fileInfo();
if (i.isFile())
fs_watcher->addPath(i.absoluteFilePath());
}
QObject::connect(fs_watcher, &QFileSystemWatcher::fileChanged, [=](const QString &file) {
QTimer::singleShot(50, [=] {
static QQuickItem *previousItem = nullptr;
auto window = qobject_cast<QQuickWindow *>(engine->rootObjects().first());
fs_watcher->addPath(file);
auto loader = window->findChild<QObject*>("AppLoader");
auto prev_source = loader->property("source");
loader->setProperty("source", "");
engine->clearComponentCache();
loader->setProperty("source", prev_source);
});
});
}
#include <QtGui>
#include <QtQuick>
#include <filesystem>
#include <QQmlComponent>
#include "hotreload.hpp"
namespace fs = std::filesystem;
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
init_live_reload(&engine, "path/to/root/qml");
QUrl url((fs::path(__FILE__).parent_path() / "qml" / "mainwindow.qml").c_str());
engine.load(url);
return QGuiApplication::exec();
}
// every time this file is edited the loader will refresh it.
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Material
import DogModule
Pane {
anchors.fill: parent;
Rectangle{
width:234;
height: 234;
}
}
import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Material
ApplicationWindow {
id: root
width: 500
height: 400
visible: true
Material.theme: Material.Dark
Material.accent: Material.Orange
Loader{objectName: "AppLoader"
source: "./Main.qml"
}
}
@Foaly
Copy link

Foaly commented May 23, 2024

Hello!
I tried this out with Qt 6.5.3, as it looked very promissing, but unfortunatelly it does not work... The reload seems to happen as planned, but it seems to me as if the old item is still cached. No change is visible. Do you have any idea why this is happening?

@nrbnlulu
Copy link
Author

Make sure the engine shows the qml files that you are editing (and the fs watcher is wathing) and not the build copies.

@Foaly
Copy link

Foaly commented May 27, 2024

Wow thanks for the hint! That really was the problem...
I was not able to get your code passing a QUrl to work. I fixed it like this:

    const auto path = std::filesystem::path(__FILE__).parent_path().parent_path() / "resources" / "qml" / "main.qml";
    m_qmlEngine.load(QString::fromStdString(path.string()));

@nrbnlulu
Copy link
Author

nrbnlulu commented May 27, 2024

Yeah QML tooling's are awful...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment