forked from quickshell/quickshell
		
	feat: add Variants type for creating instances
This commit is contained in:
		
							parent
							
								
									23837e5195
								
							
						
					
					
						commit
						d14258df8e
					
				
					 3 changed files with 135 additions and 0 deletions
				
			
		
							
								
								
									
										94
									
								
								src/cpp/variants.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								src/cpp/variants.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,94 @@
 | 
			
		|||
#include "variants.hpp"
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
#include <qcontainerfwd.h>
 | 
			
		||||
#include <qlogging.h>
 | 
			
		||||
 | 
			
		||||
void Variants::setVariants(QVariantList variants) {
 | 
			
		||||
	this->mVariants = std::move(variants);
 | 
			
		||||
	qDebug() << "configurations updated:" << this->mVariants;
 | 
			
		||||
 | 
			
		||||
	this->updateVariants();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Variants::componentComplete() {
 | 
			
		||||
	qDebug() << "configure ready";
 | 
			
		||||
 | 
			
		||||
	this->updateVariants();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Variants::updateVariants() {
 | 
			
		||||
	if (this->mComponent == nullptr) {
 | 
			
		||||
		qWarning() << "Variants instance does not have a component specified";
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// clean up removed entries
 | 
			
		||||
	for (auto iter = this->instances.values.begin(); iter < this->instances.values.end();) {
 | 
			
		||||
		if (this->mVariants.contains(iter->first)) {
 | 
			
		||||
			iter++;
 | 
			
		||||
		} else {
 | 
			
		||||
			iter->second->deleteLater();
 | 
			
		||||
			iter = this->instances.values.erase(iter);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (auto iter = this->mVariants.begin(); iter < this->mVariants.end(); iter++) {
 | 
			
		||||
		auto& variantObj = *iter;
 | 
			
		||||
		if (!variantObj.canConvert<QVariantMap>()) {
 | 
			
		||||
			qWarning() << "value passed to Variants is not an object and will be ignored:" << variantObj;
 | 
			
		||||
		} else {
 | 
			
		||||
			auto variant = variantObj.value<QVariantMap>();
 | 
			
		||||
 | 
			
		||||
			for (auto iter2 = this->mVariants.begin(); iter2 < iter; iter2++) {
 | 
			
		||||
				if (*iter2 == variantObj) {
 | 
			
		||||
					qWarning() << "same value specified twice in Variants, duplicates will be ignored:"
 | 
			
		||||
					           << variantObj;
 | 
			
		||||
					goto outer;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (this->instances.contains(variant)) {
 | 
			
		||||
				continue; // we dont need to recreate this one
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			auto* instance = this->mComponent->createWithInitialProperties(variant, nullptr);
 | 
			
		||||
 | 
			
		||||
			if (instance == nullptr) {
 | 
			
		||||
				qWarning() << "failed to create variant with object" << variant;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			instance->setParent(this);
 | 
			
		||||
			this->instances.insert(variant, instance);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	outer:;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename K, typename V>
 | 
			
		||||
bool AwfulMap<K, V>::contains(const K& key) const {
 | 
			
		||||
	return std::ranges::any_of(this->values, [&](const QPair<K, V>& pair) {
 | 
			
		||||
		return pair.first == key;
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename K, typename V>
 | 
			
		||||
void AwfulMap<K, V>::insert(K key, V value) {
 | 
			
		||||
	this->values.push_back(QPair<K, V>(key, value));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename K, typename V>
 | 
			
		||||
bool AwfulMap<K, V>::remove(const K& key) {
 | 
			
		||||
	for (auto iter = this->values.begin(); iter < this->values.end(); iter++) {
 | 
			
		||||
		if (iter->first == key) {
 | 
			
		||||
			this->values.erase(iter);
 | 
			
		||||
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								src/cpp/variants.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/cpp/variants.hpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <qcontainerfwd.h>
 | 
			
		||||
#include <qlist.h>
 | 
			
		||||
#include <qmap.h>
 | 
			
		||||
#include <qobject.h>
 | 
			
		||||
#include <qqmlcomponent.h>
 | 
			
		||||
#include <qqmlparserstatus.h>
 | 
			
		||||
 | 
			
		||||
// extremely inefficient map
 | 
			
		||||
template <typename K, typename V>
 | 
			
		||||
class AwfulMap {
 | 
			
		||||
public:
 | 
			
		||||
	[[nodiscard]] bool contains(const K& key) const;
 | 
			
		||||
	void insert(K key, V value); // assumes no duplicates
 | 
			
		||||
	bool remove(const K& key);   // returns true if anything was removed
 | 
			
		||||
	QList<QPair<K, V>> values;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Variants: public QObject, public QQmlParserStatus {
 | 
			
		||||
	Q_OBJECT;
 | 
			
		||||
	Q_PROPERTY(QQmlComponent* component MEMBER mComponent);
 | 
			
		||||
	Q_PROPERTY(QVariantList variants MEMBER mVariants WRITE setVariants);
 | 
			
		||||
	Q_CLASSINFO("DefaultProperty", "component");
 | 
			
		||||
	QML_ELEMENT;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	explicit Variants(QObject* parent = nullptr): QObject(parent) {}
 | 
			
		||||
 | 
			
		||||
	void classBegin() override {};
 | 
			
		||||
	void componentComplete() override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	void setVariants(QVariantList variants);
 | 
			
		||||
	void updateVariants();
 | 
			
		||||
 | 
			
		||||
	QQmlComponent* mComponent = nullptr;
 | 
			
		||||
	QVariantList mVariants;
 | 
			
		||||
	AwfulMap<QVariantMap, QObject*> instances;
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue