diff --git a/src/core/qmlglobal.cpp b/src/core/qmlglobal.cpp index fdcf0da..2ef4a44 100644 --- a/src/core/qmlglobal.cpp +++ b/src/core/qmlglobal.cpp @@ -18,7 +18,40 @@ #include "qmlscreen.hpp" #include "rootwrapper.hpp" +QuickshellSettings* QuickshellSettings::instance() { + static QuickshellSettings* instance = nullptr; // NOLINT + if (instance == nullptr) { + QJSEngine::setObjectOwnership(instance, QJSEngine::CppOwnership); + instance = new QuickshellSettings(); + } + return instance; +} + +void QuickshellSettings::reset() { QuickshellSettings::instance()->mWatchFiles = true; } + +QString QuickshellSettings::workingDirectory() const { // NOLINT + return QDir::current().absolutePath(); +} + +void QuickshellSettings::setWorkingDirectory(QString workingDirectory) { // NOLINT + QDir::setCurrent(workingDirectory); + emit this->workingDirectoryChanged(); +} + +bool QuickshellSettings::watchFiles() const { return this->mWatchFiles; } + +void QuickshellSettings::setWatchFiles(bool watchFiles) { + if (watchFiles == this->mWatchFiles) return; + this->mWatchFiles = watchFiles; + emit this->watchFilesChanged(); +} + QuickshellGlobal::QuickshellGlobal(QObject* parent): QObject(parent) { + // clang-format off + QObject::connect(QuickshellSettings::instance(), &QuickshellSettings::workingDirectoryChanged, this, &QuickshellGlobal::workingDirectoryChanged); + QObject::connect(QuickshellSettings::instance(), &QuickshellSettings::watchFilesChanged, this, &QuickshellGlobal::watchFilesChanged); + // clang-format on + auto* app = QCoreApplication::instance(); auto* guiApp = qobject_cast(app); @@ -63,6 +96,22 @@ void QuickshellGlobal::reload(bool hard) { root->reloadGraph(hard); } +QString QuickshellGlobal::workingDirectory() const { // NOLINT + return QuickshellSettings::instance()->workingDirectory(); +} + +void QuickshellGlobal::setWorkingDirectory(QString workingDirectory) { // NOLINT + QuickshellSettings::instance()->setWorkingDirectory(std::move(workingDirectory)); +} + +bool QuickshellGlobal::watchFiles() const { // NOLINT + return QuickshellSettings::instance()->watchFiles(); +} + +void QuickshellGlobal::setWatchFiles(bool watchFiles) { // NOLINT + QuickshellSettings::instance()->setWatchFiles(watchFiles); +} + void QuickshellGlobal::updateScreens() { auto screens = QGuiApplication::screens(); this->mScreens.resize(screens.size()); @@ -85,29 +134,3 @@ QVariant QuickshellGlobal::env(const QString& variable) { // NOLINT return qEnvironmentVariable(vstr.data()); } - -QString QuickshellGlobal::workingDirectory() const { // NOLINT - return QDir::current().absolutePath(); -} - -void QuickshellGlobal::setWorkingDirectory(const QString& workingDirectory) { // NOLINT - QDir::setCurrent(workingDirectory); - emit this->workingDirectoryChanged(); -} - -static QuickshellGlobal* g_instance = nullptr; // NOLINT - -QuickshellGlobal* QuickshellGlobal::create(QQmlEngine* /*unused*/, QJSEngine* /*unused*/) { - return QuickshellGlobal::instance(); -} - -QuickshellGlobal* QuickshellGlobal::instance() { - if (g_instance == nullptr) g_instance = new QuickshellGlobal(); - QJSEngine::setObjectOwnership(g_instance, QJSEngine::CppOwnership); - return g_instance; -} - -void QuickshellGlobal::deleteInstance() { - delete g_instance; - g_instance = nullptr; -} diff --git a/src/core/qmlglobal.hpp b/src/core/qmlglobal.hpp index ceb8673..72a4e37 100644 --- a/src/core/qmlglobal.hpp +++ b/src/core/qmlglobal.hpp @@ -12,6 +12,37 @@ #include "qmlscreen.hpp" +///! Accessor for some options under the Quickshell type. +class QuickshellSettings: public QObject { + Q_OBJECT; + // clang-format off + /// Quickshell's working directory. Defaults to whereever quickshell was launched from. + Q_PROPERTY(QString workingDirectory READ workingDirectory WRITE setWorkingDirectory NOTIFY workingDirectoryChanged); + /// If true then the configuration will be reloaded whenever any files change. + /// Defaults to true. + Q_PROPERTY(bool watchFiles READ watchFiles WRITE setWatchFiles NOTIFY watchFilesChanged); + // clang-format on + QML_ELEMENT; + QML_UNCREATABLE("singleton"); + +public: + [[nodiscard]] QString workingDirectory() const; + void setWorkingDirectory(QString workingDirectory); + + [[nodiscard]] bool watchFiles() const; + void setWatchFiles(bool watchFiles); + + static QuickshellSettings* instance(); + static void reset(); + +signals: + void workingDirectoryChanged(); + void watchFilesChanged(); + +private: + bool mWatchFiles = true; +}; + class QuickshellGlobal: public QObject { Q_OBJECT; // clang-format off @@ -38,6 +69,9 @@ class QuickshellGlobal: public QObject { Q_PROPERTY(QQmlListProperty screens READ screens NOTIFY screensChanged); /// Quickshell's working directory. Defaults to whereever quickshell was launched from. Q_PROPERTY(QString workingDirectory READ workingDirectory WRITE setWorkingDirectory NOTIFY workingDirectoryChanged); + /// If true then the configuration will be reloaded whenever any files change. + /// Defaults to true. + Q_PROPERTY(bool watchFiles READ watchFiles WRITE setWatchFiles NOTIFY watchFilesChanged); // clang-format on QML_SINGLETON; QML_NAMED_ELEMENT(Quickshell); @@ -61,15 +95,15 @@ public: Q_INVOKABLE QVariant env(const QString& variable); [[nodiscard]] QString workingDirectory() const; - void setWorkingDirectory(const QString& workingDirectory); + void setWorkingDirectory(QString workingDirectory); - static QuickshellGlobal* create(QQmlEngine* /*unused*/, QJSEngine* /*unused*/); - static QuickshellGlobal* instance(); - static void deleteInstance(); + [[nodiscard]] bool watchFiles() const; + void setWatchFiles(bool watchFiles); signals: void screensChanged(); void workingDirectoryChanged(); + void watchFilesChanged(); public slots: void updateScreens(); diff --git a/src/core/rootwrapper.cpp b/src/core/rootwrapper.cpp index 6fe9273..16941f5 100644 --- a/src/core/rootwrapper.cpp +++ b/src/core/rootwrapper.cpp @@ -27,6 +27,10 @@ RootWrapper::RootWrapper(QString rootPath) QObject::connect(&this->engine, &QQmlEngine::quit, app, &QCoreApplication::quit); QObject::connect(&this->engine, &QQmlEngine::exit, app, &QCoreApplication::exit); + // clang-format off + QObject::connect(QuickshellSettings::instance(), &QuickshellSettings::watchFilesChanged, this, &RootWrapper::onWatchFilesChanged); + // clang-format on + this->reloadGraph(true); if (this->root == nullptr) { @@ -37,13 +41,12 @@ RootWrapper::RootWrapper(QString rootPath) RootWrapper::~RootWrapper() { // event loop may no longer be running so deleteLater is not an option - QuickshellGlobal::deleteInstance(); delete this->root; } void RootWrapper::reloadGraph(bool hard) { if (this->root != nullptr) { - QuickshellGlobal::deleteInstance(); + QuickshellSettings::reset(); this->engine.clearComponentCache(); } @@ -87,25 +90,23 @@ void RootWrapper::reloadGraph(bool hard) { QuickshellPlugin::runOnReload(); } - this->onConfigChanged(); + this->onWatchFilesChanged(); } -void RootWrapper::onConfigChanged() { - auto config = this->root->config(); +void RootWrapper::onWatchFilesChanged() { + auto watchFiles = QuickshellSettings::instance()->watchFiles(); - if (config.mWatchFiles && this->configWatcher == nullptr) { + if (watchFiles && this->configWatcher == nullptr) { this->configWatcher = new FiletreeWatcher(); this->configWatcher->addPath(QFileInfo(this->rootPath).dir().path()); - QObject::connect(this->root, &ShellRoot::configChanged, this, &RootWrapper::onConfigChanged); - QObject::connect( this->configWatcher, &FiletreeWatcher::fileChanged, this, &RootWrapper::onWatchedFilesChanged ); - } else if (!config.mWatchFiles && this->configWatcher != nullptr) { + } else if (!watchFiles && this->configWatcher != nullptr) { this->configWatcher->deleteLater(); this->configWatcher = nullptr; } diff --git a/src/core/rootwrapper.hpp b/src/core/rootwrapper.hpp index 2a09c68..6174c7b 100644 --- a/src/core/rootwrapper.hpp +++ b/src/core/rootwrapper.hpp @@ -20,7 +20,7 @@ public: void reloadGraph(bool hard); private slots: - void onConfigChanged(); + void onWatchFilesChanged(); void onWatchedFilesChanged(); private: diff --git a/src/core/shell.cpp b/src/core/shell.cpp index 59a678f..a88bfec 100644 --- a/src/core/shell.cpp +++ b/src/core/shell.cpp @@ -1,16 +1,7 @@ #include "shell.hpp" -#include -#include +#include "qmlglobal.hpp" -void ShellRoot::setConfig(ShellConfig config) { - this->mConfig = config; - - emit this->configChanged(); -} - -ShellConfig ShellRoot::config() const { return this->mConfig; } - -void ShellConfig::setWorkingDirectory(const QString& workingDirectory) { // NOLINT - QDir::setCurrent(workingDirectory); +QuickshellSettings* ShellRoot::settings() const { // NOLINT + return QuickshellSettings::instance(); } diff --git a/src/core/shell.hpp b/src/core/shell.hpp index 1c62bd9..807f027 100644 --- a/src/core/shell.hpp +++ b/src/core/shell.hpp @@ -5,38 +5,17 @@ #include #include +#include "qmlglobal.hpp" #include "reload.hpp" -class ShellConfig { - Q_GADGET; - Q_PROPERTY(bool watchFiles MEMBER mWatchFiles); - Q_PROPERTY(QString workingDirectory WRITE setWorkingDirectory); - -public: - bool mWatchFiles = true; - - void setWorkingDirectory(const QString& workingDirectory); -}; - ///! Root config element class ShellRoot: public ReloadPropagator { Q_OBJECT; - /// If `config.watchFiles` is true the configuration will be reloaded whenever it changes. - /// Defaults to true. - /// - /// `config.workingDirectory` corrosponds to [Quickshell.workingDirectory](../quickshell#prop.workingDirectory). - Q_PROPERTY(ShellConfig config READ config WRITE setConfig NOTIFY configChanged); + Q_PROPERTY(QuickshellSettings* settings READ settings CONSTANT); QML_ELEMENT; public: explicit ShellRoot(QObject* parent = nullptr): ReloadPropagator(parent) {} - void setConfig(ShellConfig config); - [[nodiscard]] ShellConfig config() const; - -signals: - void configChanged(); - -private: - ShellConfig mConfig; + [[nodiscard]] QuickshellSettings* settings() const; }; diff --git a/src/core/windowinterface.hpp b/src/core/windowinterface.hpp index 49ae561..4f20d9c 100644 --- a/src/core/windowinterface.hpp +++ b/src/core/windowinterface.hpp @@ -30,6 +30,7 @@ class WindowInterface: public Reloadable { /// > Using a colored content item over a transparent window is the recommended way to work around this: /// > ```qml /// > ProxyWindow { + /// > color: "transparent" /// > Rectangle { /// > anchors.fill: parent /// > color: "#20ffffff" diff --git a/src/io/process.cpp b/src/io/process.cpp index d6c5585..b202f72 100644 --- a/src/io/process.cpp +++ b/src/io/process.cpp @@ -21,8 +21,8 @@ static DisownedProcessContext* disownedCtx; // NOLINT Process::Process(QObject* parent): QObject(parent) { QObject::connect( - QuickshellGlobal::instance(), - &QuickshellGlobal::workingDirectoryChanged, + QuickshellSettings::instance(), + &QuickshellSettings::workingDirectoryChanged, this, &Process::onGlobalWorkingDirectoryChanged );