forked from quickshell/quickshell
feat: abstract out scavenger scopes
This commit is contained in:
parent
82aa7d45d3
commit
d6ed717c39
|
@ -1,10 +1,16 @@
|
|||
#include "scavenge.hpp"
|
||||
#include <utility>
|
||||
|
||||
#include <qcontainerfwd.h>
|
||||
#include <qlogging.h>
|
||||
#include <qobject.h>
|
||||
#include <qqmlcomponent.h>
|
||||
#include <qqmlengine.h>
|
||||
#include <qqmllist.h>
|
||||
|
||||
// FIXME: there are core problems with SCAVENGE_PARENT due to the qml engine liking to set parents really late.
|
||||
// this should instead be handled by proxying all property values until a possible target is ready or definitely not coming.
|
||||
// The parent should probably be stable in componentComplete() but should be tested.
|
||||
|
||||
QObject* SCAVENGE_PARENT = nullptr; // NOLINT
|
||||
|
||||
|
@ -44,3 +50,38 @@ QObject* createComponentScavengeable(
|
|||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void ScavengeableScope::earlyInit(QObject* old) {
|
||||
auto* oldshell = qobject_cast<ScavengeableScope*>(old);
|
||||
|
||||
if (oldshell != nullptr) {
|
||||
this->scavengeableData = std::move(oldshell->mData);
|
||||
}
|
||||
}
|
||||
|
||||
QObject* ScavengeableScope::scavengeTargetFor(QObject* /* child */) {
|
||||
if (this->scavengeableData.length() > this->mData.length()) {
|
||||
return this->scavengeableData[this->mData.length()];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QQmlListProperty<QObject> ScavengeableScope::data() {
|
||||
return QQmlListProperty<QObject>(
|
||||
this,
|
||||
nullptr,
|
||||
&ScavengeableScope::appendComponent,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
|
||||
void ScavengeableScope::appendComponent(QQmlListProperty<QObject>* list, QObject* component) {
|
||||
auto* self = static_cast<ScavengeableScope*>(list->object); // NOLINT
|
||||
component->setParent(self);
|
||||
self->mData.append(component);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <qobject.h>
|
||||
#include <qqmlcomponent.h>
|
||||
#include <qqmlintegration.h>
|
||||
#include <qqmllist.h>
|
||||
#include <qqmlparserstatus.h>
|
||||
#include <qtmetamacros.h>
|
||||
|
||||
|
@ -30,7 +32,7 @@ protected:
|
|||
|
||||
class Scavengeable {
|
||||
public:
|
||||
Scavengeable() = default;
|
||||
explicit Scavengeable() = default;
|
||||
virtual ~Scavengeable() = default;
|
||||
|
||||
Scavengeable(Scavengeable&) = delete;
|
||||
|
@ -47,3 +49,31 @@ QObject* createComponentScavengeable(
|
|||
QQmlComponent& component,
|
||||
QVariantMap& initialProperties
|
||||
);
|
||||
|
||||
///! Reloader connection scope
|
||||
/// Attempts to maintain scavengeable connections.
|
||||
/// This is mostly useful to split a scavengeable component slot (e.g. `Variants`)
|
||||
/// into multiple slots.
|
||||
///
|
||||
/// If you don't know what that means you probably don't need it.
|
||||
class ScavengeableScope: public Scavenger, virtual public Scavengeable {
|
||||
Q_OBJECT;
|
||||
Q_PROPERTY(QQmlListProperty<QObject> data READ data);
|
||||
Q_CLASSINFO("DefaultProperty", "data");
|
||||
QML_ELEMENT;
|
||||
|
||||
public:
|
||||
explicit ScavengeableScope(QObject* parent = nullptr): Scavenger(parent) {}
|
||||
|
||||
void earlyInit(QObject* old) override;
|
||||
QObject* scavengeTargetFor(QObject* child) override;
|
||||
|
||||
QQmlListProperty<QObject> data();
|
||||
|
||||
private:
|
||||
static void appendComponent(QQmlListProperty<QObject>* list, QObject* component);
|
||||
|
||||
// track only the children assigned to `data` in order
|
||||
QList<QObject*> mData;
|
||||
QList<QObject*> scavengeableData;
|
||||
};
|
||||
|
|
|
@ -1,26 +1,7 @@
|
|||
#include "shell.hpp"
|
||||
#include <utility>
|
||||
|
||||
#include <qobject.h>
|
||||
#include <qqmllist.h>
|
||||
#include <qtmetamacros.h>
|
||||
|
||||
void ShellRoot::earlyInit(QObject* old) {
|
||||
auto* oldshell = qobject_cast<ShellRoot*>(old);
|
||||
|
||||
if (oldshell != nullptr) {
|
||||
this->scavengeableChildren = std::move(oldshell->children);
|
||||
}
|
||||
}
|
||||
|
||||
QObject* ShellRoot::scavengeTargetFor(QObject* /* child */) {
|
||||
if (this->scavengeableChildren.length() > this->children.length()) {
|
||||
return this->scavengeableChildren[this->children.length()];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ShellRoot::setConfig(ShellConfig config) {
|
||||
this->mConfig = config;
|
||||
|
||||
|
@ -28,22 +9,3 @@ void ShellRoot::setConfig(ShellConfig config) {
|
|||
}
|
||||
|
||||
ShellConfig ShellRoot::config() const { return this->mConfig; }
|
||||
|
||||
QQmlListProperty<QObject> ShellRoot::components() {
|
||||
return QQmlListProperty<QObject>(
|
||||
this,
|
||||
nullptr,
|
||||
&ShellRoot::appendComponent,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
|
||||
void ShellRoot::appendComponent(QQmlListProperty<QObject>* list, QObject* component) {
|
||||
auto* shell = static_cast<ShellRoot*>(list->object); // NOLINT
|
||||
component->setParent(shell);
|
||||
shell->children.append(component);
|
||||
}
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
#include <qcontainerfwd.h>
|
||||
#include <qlist.h>
|
||||
#include <qobject.h>
|
||||
#include <qqmlengine.h>
|
||||
#include <qqmllist.h>
|
||||
#include <qtmetamacros.h>
|
||||
|
||||
#include "scavenge.hpp"
|
||||
|
@ -18,35 +16,22 @@ public:
|
|||
};
|
||||
|
||||
///! Root config element
|
||||
class ShellRoot: public Scavenger, virtual public Scavengeable {
|
||||
class ShellRoot: public ScavengeableScope {
|
||||
Q_OBJECT;
|
||||
/// If `config.watchFiles` is true the configuration will be reloaded whenever it changes.
|
||||
/// Defaults to true.
|
||||
Q_PROPERTY(ShellConfig config READ config WRITE setConfig);
|
||||
Q_PROPERTY(QQmlListProperty<QObject> components READ components);
|
||||
Q_CLASSINFO("DefaultProperty", "components");
|
||||
QML_ELEMENT;
|
||||
|
||||
public:
|
||||
explicit ShellRoot(QObject* parent = nullptr): Scavenger(parent) {}
|
||||
|
||||
void earlyInit(QObject* old) override;
|
||||
QObject* scavengeTargetFor(QObject* child) override;
|
||||
explicit ShellRoot(QObject* parent = nullptr): ScavengeableScope(parent) {}
|
||||
|
||||
void setConfig(ShellConfig config);
|
||||
[[nodiscard]] ShellConfig config() const;
|
||||
|
||||
QQmlListProperty<QObject> components();
|
||||
|
||||
signals:
|
||||
void configChanged();
|
||||
|
||||
private:
|
||||
static void appendComponent(QQmlListProperty<QObject>* list, QObject* component);
|
||||
|
||||
ShellConfig mConfig;
|
||||
|
||||
// track only the children assigned to `components` in order
|
||||
QList<QObject*> children;
|
||||
QList<QObject*> scavengeableChildren;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue