From 211f454de98252e6ccb7b57ee2de34558df2aa56 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Wed, 13 Mar 2024 00:57:03 -0700 Subject: [PATCH] singleton: add reloadable Singleton type --- CMakeLists.txt | 10 +++---- src/core/CMakeLists.txt | 1 + src/core/module.md | 1 + src/core/rootwrapper.cpp | 2 ++ src/core/singleton.cpp | 64 ++++++++++++++++++++++++++++++++++++++++ src/core/singleton.hpp | 35 ++++++++++++++++++++++ 6 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 src/core/singleton.cpp create mode 100644 src/core/singleton.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 86b9fd38..ccdb5a81 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,13 +65,13 @@ find_package(Qt6 REQUIRED COMPONENTS ${QT_FPDEPS}) qt_standard_project_setup(REQUIRES 6.6) set(QT_QML_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/qml_modules) -file(GENERATE - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/pchstub.cpp - CONTENT "" -) - # pch breaks clang-tidy..... somehow if (NOT NO_PCH) + file(GENERATE + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/pchstub.cpp + CONTENT "" + ) + add_library(qt-pch ${CMAKE_CURRENT_BINARY_DIR}/pchstub.cpp) target_link_libraries(qt-pch PRIVATE ${QT_DEPS}) target_precompile_headers(qt-pch PUBLIC diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 0ddd7251..4ce42b92 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -16,6 +16,7 @@ qt_add_library(quickshell-core STATIC floatingwindow.cpp panelinterface.cpp popupwindow.cpp + singleton.cpp ) set_source_files_properties(main.cpp PROPERTIES COMPILE_DEFINITIONS GIT_REVISION="${GIT_REVISION}") diff --git a/src/core/module.md b/src/core/module.md index 73ecbb8b..a5aea16e 100644 --- a/src/core/module.md +++ b/src/core/module.md @@ -13,5 +13,6 @@ headers = [ "panelinterface.hpp", "floatingwindow.hpp", "popupwindow.hpp", + "singleton.hpp", ] ----- diff --git a/src/core/rootwrapper.cpp b/src/core/rootwrapper.cpp index 68c11de9..382bf73a 100644 --- a/src/core/rootwrapper.cpp +++ b/src/core/rootwrapper.cpp @@ -16,6 +16,7 @@ #include "qmlglobal.hpp" #include "reload.hpp" #include "shell.hpp" +#include "singleton.hpp" #include "watcher.hpp" RootWrapper::RootWrapper(QString rootPath) @@ -49,6 +50,7 @@ void RootWrapper::reloadGraph(bool hard) { if (this->root != nullptr) { QuickshellSettings::reset(); + SingletonRegistry::instance()->flip(); } QDir::setCurrent(this->originalWorkingDirectory); diff --git a/src/core/singleton.cpp b/src/core/singleton.cpp new file mode 100644 index 00000000..61d2e068 --- /dev/null +++ b/src/core/singleton.cpp @@ -0,0 +1,64 @@ +#include "singleton.hpp" + +#include +#include +#include +#include +#include +#include + +#include "reload.hpp" + +void Singleton::componentComplete() { + auto* context = QQmlEngine::contextForObject(this); + + if (context == nullptr) { + qWarning() << "not registering singleton not created in the qml context:" << this; + return; + } + + auto url = context->baseUrl(); + + if (this->parent() != nullptr || context->contextObject() != this) { + qWarning() << "tried to register singleton" << this + << "which is not the root component of its file" << url; + return; + } + + SingletonRegistry::instance()->install(url, this); + this->ReloadPropagator::componentComplete(); +} + +SingletonRegistry::~SingletonRegistry() { + delete this->previousRegistry; + delete this->currentRegistry; +} + +void SingletonRegistry::install(const QUrl& url, Singleton* singleton) { + QObject* old = nullptr; + + if (this->previousRegistry != nullptr) { + old = this->previousRegistry->value(url); + } + + if (this->currentRegistry == nullptr) { + this->currentRegistry = new QMap(); + } + + this->currentRegistry->insert(url, singleton); + singleton->onReload(old); +} + +void SingletonRegistry::flip() { + delete this->previousRegistry; + this->previousRegistry = this->currentRegistry; + this->currentRegistry = nullptr; +} + +SingletonRegistry* SingletonRegistry::instance() { + static SingletonRegistry* instance = nullptr; // NOLINT + if (instance == nullptr) { + instance = new SingletonRegistry(); + } + return instance; +} diff --git a/src/core/singleton.hpp b/src/core/singleton.hpp new file mode 100644 index 00000000..2b9e8e75 --- /dev/null +++ b/src/core/singleton.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "reload.hpp" + +///! The root component for reloadable singletons. +/// All singletons should inherit from this type. +class Singleton: public ReloadPropagator { + Q_OBJECT; + QML_ELEMENT; + +public: + void componentComplete() override; +}; + +class SingletonRegistry { +public: + SingletonRegistry() = default; + ~SingletonRegistry(); + Q_DISABLE_COPY_MOVE(SingletonRegistry); + + void install(const QUrl& url, Singleton* singleton); + void flip(); + + static SingletonRegistry* instance(); + +private: + QMap* previousRegistry = nullptr; + QMap* currentRegistry = nullptr; +};