feat: add PersistentProperties

This commit is contained in:
outfoxxed 2024-02-17 04:24:03 -08:00
parent ed62193978
commit 083fff57be
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
5 changed files with 86 additions and 1 deletions

View file

@ -39,6 +39,7 @@ qt_add_executable(quickshell
src/cpp/qmlscreen.cpp src/cpp/qmlscreen.cpp
src/cpp/watcher.cpp src/cpp/watcher.cpp
src/cpp/region.cpp src/cpp/region.cpp
src/cpp/persistentprops.cpp
) )
qt_add_qml_module(quickshell URI QuickShell) qt_add_qml_module(quickshell URI QuickShell)

View file

@ -9,6 +9,7 @@ headers = [
"proxywindow.hpp", "proxywindow.hpp",
"layershell.hpp", "layershell.hpp",
"region.hpp", "region.hpp",
"persistentprops.hpp",
] ]
----- -----
The core types provided by QuickShell The core types provided by QuickShell

View file

@ -0,0 +1,24 @@
#include "persistentprops.hpp"
#include <qobject.h>
#include <qtmetamacros.h>
void PersistentProperties::onReload(QObject* oldInstance) {
if (qobject_cast<PersistentProperties*>(oldInstance) == nullptr) {
emit this->loaded();
return;
}
const auto* metaObject = this->metaObject();
for (auto i = metaObject->propertyOffset(); i < metaObject->propertyCount(); i++) {
const auto prop = metaObject->property(i);
auto oldProp = oldInstance->property(prop.name());
if (oldProp.isValid()) {
this->setProperty(prop.name(), oldProp);
}
}
emit this->loaded();
emit this->reloaded();
}

View file

@ -0,0 +1,57 @@
#pragma once
#include <qobject.h>
#include <qqmlintegration.h>
#include "reload.hpp"
///! Object that holds properties that can persist across a config reload.
/// PersistentProperties holds properties declated in it across a reload, which is
/// often useful for things like keeping expandable popups open and styling them.
///
/// Below is an example of using `PersistentProperties` to keep track of the state
/// of an expandable panel. When the configuration is reloaded, the `expanderOpen` property
/// will be saved and the expandable panel will stay in the open/closed state.
///
/// ```qml
/// PersistentProperties {
/// id: persist
/// reloadableId: "persistedStates"
///
/// property bool expanderOpen: false
/// }
///
/// Button {
/// id: expanderButton
/// anchors.centerIn: parent
/// text: "toggle expander"
/// onClicked: persist.expanderOpen = !persist.expanderOpen
/// }
///
/// Rectangle {
/// anchors.top: expanderButton.bottom
/// anchors.left: expanderButton.left
/// anchors.right: expanderButton.right
/// height: 100
///
/// color: "lightblue"
/// visible: persist.expanderOpen
/// }
/// ```
class PersistentProperties: public Reloadable {
Q_OBJECT;
QML_ELEMENT;
public:
PersistentProperties(QObject* parent = nullptr): Reloadable(parent) {}
void onReload(QObject* oldInstance) override;
signals:
/// Called every time the reload stage completes.
/// Will be called every time, including when nothing was loaded from an old instance.
void loaded();
/// Called every time the properties are reloaded.
/// Will not be called if no old instance was loaded.
void reloaded();
};

View file

@ -52,7 +52,9 @@ class Reloadable: public QObject, public QQmlParserStatus {
public: public:
explicit Reloadable(QObject* parent = nullptr): QObject(parent) {} explicit Reloadable(QObject* parent = nullptr): QObject(parent) {}
/// called unconditionally in the reload phase, with nullptr if no source could be determined // Called unconditionally in the reload phase, with nullptr if no source could be determined.
// If non null the old instance may or may not be of the same type, and should be checked
// by `onReload`.
virtual void onReload(QObject* oldInstance) = 0; virtual void onReload(QObject* oldInstance) = 0;
// TODO: onReload runs after initialization for reloadable objects created late // TODO: onReload runs after initialization for reloadable objects created late