diff --git a/src/core/generation.cpp b/src/core/generation.cpp index 8dbad323..1021566b 100644 --- a/src/core/generation.cpp +++ b/src/core/generation.cpp @@ -265,12 +265,16 @@ void EngineGeneration::assignIncubationController() { this->engine->setIncubationController(controller); } +EngineGeneration* EngineGeneration::findEngineGeneration(QQmlEngine* engine) { + return g_generations.value(engine); +} + EngineGeneration* EngineGeneration::findObjectGeneration(QObject* object) { while (object != nullptr) { auto* context = QQmlEngine::contextForObject(object); if (context != nullptr) { - if (auto* generation = g_generations.value(context->engine())) { + if (auto* generation = EngineGeneration::findEngineGeneration(context->engine())) { return generation; } } diff --git a/src/core/generation.hpp b/src/core/generation.hpp index c077c1bf..f757113e 100644 --- a/src/core/generation.hpp +++ b/src/core/generation.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -15,6 +16,7 @@ #include "singleton.hpp" class RootWrapper; +class QuickshellGlobal; class EngineGeneration: public QObject { Q_OBJECT; @@ -31,6 +33,7 @@ public: void registerIncubationController(QQmlIncubationController* controller); void deregisterIncubationController(QQmlIncubationController* controller); + static EngineGeneration* findEngineGeneration(QQmlEngine* engine); static EngineGeneration* findObjectGeneration(QObject* object); RootWrapper* wrapper = nullptr; @@ -45,6 +48,7 @@ public: QVector deletedWatchedFiles; DelayedQmlIncubationController delayedIncubationController; bool reloadComplete = false; + QuickshellGlobal* qsgInstance = nullptr; void destroy(); diff --git a/src/core/qmlglobal.cpp b/src/core/qmlglobal.cpp index 70d7b416..05197f26 100644 --- a/src/core/qmlglobal.cpp +++ b/src/core/qmlglobal.cpp @@ -187,3 +187,14 @@ QVariant QuickshellGlobal::env(const QString& variable) { // NOLINT return qEnvironmentVariable(vstr.data()); } + +QuickshellGlobal* QuickshellGlobal::create(QQmlEngine* engine, QJSEngine* /*unused*/) { + auto* qsg = new QuickshellGlobal(); + auto* generation = EngineGeneration::findEngineGeneration(engine); + + if (generation->qsgInstance == nullptr) { + generation->qsgInstance = qsg; + } + + return qsg; +} diff --git a/src/core/qmlglobal.hpp b/src/core/qmlglobal.hpp index 83ef68d4..8de55fc2 100644 --- a/src/core/qmlglobal.hpp +++ b/src/core/qmlglobal.hpp @@ -110,8 +110,6 @@ class QuickshellGlobal: public QObject { public: [[nodiscard]] qint32 processId() const; - QuickshellGlobal(QObject* parent = nullptr); - QQmlListProperty screens(); /// Reload the shell from the [ShellRoot]. @@ -133,17 +131,25 @@ public: [[nodiscard]] bool watchFiles() const; void setWatchFiles(bool watchFiles); + static QuickshellGlobal* create(QQmlEngine* engine, QJSEngine* /*unused*/); + signals: /// Sent when the last window is closed. /// /// To make the application exit when the last window is closed run `Qt.quit()`. void lastWindowClosed(); + /// The reload sequence has completed successfully. + void reloadCompleted(); + /// The reload sequence has failed. + void reloadFailed(QString errorString); void screensChanged(); void workingDirectoryChanged(); void watchFilesChanged(); private: + QuickshellGlobal(QObject* parent = nullptr); + static qsizetype screensCount(QQmlListProperty* prop); static QuickshellScreenInfo* screenAt(QQmlListProperty* prop, qsizetype i); }; diff --git a/src/core/rootwrapper.cpp b/src/core/rootwrapper.cpp index ea2adf18..35060bec 100644 --- a/src/core/rootwrapper.cpp +++ b/src/core/rootwrapper.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "generation.hpp" @@ -64,17 +65,28 @@ void RootWrapper::reloadGraph(bool hard) { auto* obj = component.beginCreate(generation->engine->rootContext()); if (obj == nullptr) { - qWarning() << component.errorString().toStdString().c_str(); - qWarning() << "failed to create root component"; + QString error = "failed to create root component\n" + component.errorString(); + qWarning().noquote() << error; delete generation; + + if (this->generation != nullptr && this->generation->qsgInstance != nullptr) { + emit this->generation->qsgInstance->reloadFailed(error); + } + return; } auto* newRoot = qobject_cast(obj); if (newRoot == nullptr) { - qWarning() << "root component was not a Quickshell.ShellRoot"; + QString error = "root component was not a Quickshell.ShellRoot"; + qWarning().noquote() << error; delete obj; delete generation; + + if (this->generation != nullptr && this->generation->qsgInstance != nullptr) { + emit this->generation->qsgInstance->reloadFailed(error); + } + return; } @@ -82,6 +94,7 @@ void RootWrapper::reloadGraph(bool hard) { component.completeCreate(); + auto isReload = this->generation != nullptr; generation->onReload(hard ? nullptr : this->generation); if (hard) delete this->generation; this->generation = generation; @@ -96,6 +109,10 @@ void RootWrapper::reloadGraph(bool hard) { ); this->onWatchFilesChanged(); + + if (isReload && this->generation->qsgInstance != nullptr) { + emit this->generation->qsgInstance->reloadCompleted(); + } } void RootWrapper::onWatchFilesChanged() {