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 "scavenge.hpp"
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include <qcontainerfwd.h>
|
#include <qcontainerfwd.h>
|
||||||
#include <qlogging.h>
|
#include <qlogging.h>
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
#include <qqmlcomponent.h>
|
#include <qqmlcomponent.h>
|
||||||
#include <qqmlengine.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
|
QObject* SCAVENGE_PARENT = nullptr; // NOLINT
|
||||||
|
|
||||||
|
@ -44,3 +50,38 @@ QObject* createComponentScavengeable(
|
||||||
|
|
||||||
return instance;
|
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 <qobject.h>
|
||||||
#include <qqmlcomponent.h>
|
#include <qqmlcomponent.h>
|
||||||
|
#include <qqmlintegration.h>
|
||||||
|
#include <qqmllist.h>
|
||||||
#include <qqmlparserstatus.h>
|
#include <qqmlparserstatus.h>
|
||||||
#include <qtmetamacros.h>
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
|
@ -30,7 +32,7 @@ protected:
|
||||||
|
|
||||||
class Scavengeable {
|
class Scavengeable {
|
||||||
public:
|
public:
|
||||||
Scavengeable() = default;
|
explicit Scavengeable() = default;
|
||||||
virtual ~Scavengeable() = default;
|
virtual ~Scavengeable() = default;
|
||||||
|
|
||||||
Scavengeable(Scavengeable&) = delete;
|
Scavengeable(Scavengeable&) = delete;
|
||||||
|
@ -47,3 +49,31 @@ QObject* createComponentScavengeable(
|
||||||
QQmlComponent& component,
|
QQmlComponent& component,
|
||||||
QVariantMap& initialProperties
|
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 "shell.hpp"
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include <qobject.h>
|
|
||||||
#include <qqmllist.h>
|
|
||||||
#include <qtmetamacros.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) {
|
void ShellRoot::setConfig(ShellConfig config) {
|
||||||
this->mConfig = config;
|
this->mConfig = config;
|
||||||
|
|
||||||
|
@ -28,22 +9,3 @@ void ShellRoot::setConfig(ShellConfig config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ShellConfig ShellRoot::config() const { return this->mConfig; }
|
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 <qcontainerfwd.h>
|
||||||
#include <qlist.h>
|
#include <qlist.h>
|
||||||
#include <qobject.h>
|
|
||||||
#include <qqmlengine.h>
|
#include <qqmlengine.h>
|
||||||
#include <qqmllist.h>
|
|
||||||
#include <qtmetamacros.h>
|
#include <qtmetamacros.h>
|
||||||
|
|
||||||
#include "scavenge.hpp"
|
#include "scavenge.hpp"
|
||||||
|
@ -18,35 +16,22 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
///! Root config element
|
///! Root config element
|
||||||
class ShellRoot: public Scavenger, virtual public Scavengeable {
|
class ShellRoot: public ScavengeableScope {
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
/// If `config.watchFiles` is true the configuration will be reloaded whenever it changes.
|
/// If `config.watchFiles` is true the configuration will be reloaded whenever it changes.
|
||||||
/// Defaults to true.
|
/// Defaults to true.
|
||||||
Q_PROPERTY(ShellConfig config READ config WRITE setConfig);
|
Q_PROPERTY(ShellConfig config READ config WRITE setConfig);
|
||||||
Q_PROPERTY(QQmlListProperty<QObject> components READ components);
|
|
||||||
Q_CLASSINFO("DefaultProperty", "components");
|
|
||||||
QML_ELEMENT;
|
QML_ELEMENT;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ShellRoot(QObject* parent = nullptr): Scavenger(parent) {}
|
explicit ShellRoot(QObject* parent = nullptr): ScavengeableScope(parent) {}
|
||||||
|
|
||||||
void earlyInit(QObject* old) override;
|
|
||||||
QObject* scavengeTargetFor(QObject* child) override;
|
|
||||||
|
|
||||||
void setConfig(ShellConfig config);
|
void setConfig(ShellConfig config);
|
||||||
[[nodiscard]] ShellConfig config() const;
|
[[nodiscard]] ShellConfig config() const;
|
||||||
|
|
||||||
QQmlListProperty<QObject> components();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void configChanged();
|
void configChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void appendComponent(QQmlListProperty<QObject>* list, QObject* component);
|
|
||||||
|
|
||||||
ShellConfig mConfig;
|
ShellConfig mConfig;
|
||||||
|
|
||||||
// track only the children assigned to `components` in order
|
|
||||||
QList<QObject*> children;
|
|
||||||
QList<QObject*> scavengeableChildren;
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue