forked from quickshell/quickshell
feat: add Variants type for creating instances
This commit is contained in:
parent
23837e5195
commit
d14258df8e
|
@ -25,6 +25,7 @@ qt_standard_project_setup(REQUIRES 6.6)
|
||||||
qt_add_executable(qtshell
|
qt_add_executable(qtshell
|
||||||
src/cpp/main.cpp
|
src/cpp/main.cpp
|
||||||
src/cpp/shell.cpp
|
src/cpp/shell.cpp
|
||||||
|
src/cpp/variants.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_add_qml_module(qtshell URI QtShell)
|
qt_add_qml_module(qtshell URI QtShell)
|
||||||
|
|
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…
Reference in a new issue