#include "rootwrapper.hpp" #include #include #include #include #include #include #include #include #include #include #include "generation.hpp" #include "qmlglobal.hpp" #include "scan.hpp" #include "shell.hpp" RootWrapper::RootWrapper(QString rootPath) : QObject(nullptr) , rootPath(std::move(rootPath)) , originalWorkingDirectory(QDir::current().absolutePath()) { // clang-format off QObject::connect(QuickshellSettings::instance(), &QuickshellSettings::watchFilesChanged, this, &RootWrapper::onWatchFilesChanged); // clang-format on this->reloadGraph(true); if (this->generation == nullptr) { qCritical() << "could not create scene graph, exiting"; exit(-1); // NOLINT } } RootWrapper::~RootWrapper() { // event loop may no longer be running so deleteLater is not an option if (this->generation != nullptr) { delete this->generation->root; this->generation->root = nullptr; } delete this->generation; } void RootWrapper::reloadGraph(bool hard) { auto rootPath = QFileInfo(this->rootPath).dir(); auto scanner = QmlScanner(rootPath); scanner.scanQmlFile(this->rootPath); auto* generation = new EngineGeneration(rootPath, std::move(scanner)); generation->wrapper = this; // todo: move into EngineGeneration if (this->generation != nullptr) { QuickshellSettings::reset(); } QDir::setCurrent(this->originalWorkingDirectory); auto url = QUrl::fromLocalFile(this->rootPath); // unless the original file comes from the qsintercept scheme url.setScheme("qsintercept"); auto component = QQmlComponent(generation->engine, url); auto* obj = component.beginCreate(generation->engine->rootContext()); if (obj == nullptr) { const QString error = "failed to create root component\n" + component.errorString(); qWarning().noquote() << error; generation->destroy(); if (this->generation != nullptr && this->generation->qsgInstance != nullptr) { emit this->generation->qsgInstance->reloadFailed(error); } return; } auto* newRoot = qobject_cast(obj); if (newRoot == nullptr) { const QString error = "root component was not a Quickshell.ShellRoot"; qWarning().noquote() << error; delete obj; generation->destroy(); if (this->generation != nullptr && this->generation->qsgInstance != nullptr) { emit this->generation->qsgInstance->reloadFailed(error); } return; } generation->root = newRoot; component.completeCreate(); auto isReload = this->generation != nullptr; generation->onReload(hard ? nullptr : this->generation); if (hard && this->generation != nullptr) { this->generation->destroy(); } this->generation = generation; qInfo() << "Configuration Loaded"; QObject::connect( this->generation, &EngineGeneration::filesChanged, this, &RootWrapper::onWatchedFilesChanged ); this->onWatchFilesChanged(); if (isReload && this->generation->qsgInstance != nullptr) { emit this->generation->qsgInstance->reloadCompleted(); } } void RootWrapper::onWatchFilesChanged() { auto watchFiles = QuickshellSettings::instance()->watchFiles(); if (this->generation != nullptr) { this->generation->setWatchingFiles(watchFiles); } } void RootWrapper::onWatchedFilesChanged() { this->reloadGraph(false); }