forked from quickshell/quickshell
		
	feat: abstract out scavenger scopes
This commit is contained in:
		
							parent
							
								
									82aa7d45d3
								
							
						
					
					
						commit
						d6ed717c39
					
				
					 4 changed files with 74 additions and 56 deletions
				
			
		| 
						 | 
				
			
			@ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue