#pragma once #include #include #include #include #include #include #include #include #include #include #include "doc.hpp" #include "reload.hpp" // extremely inefficient map template class AwfulMap { public: [[nodiscard]] bool contains(const K& key) const; [[nodiscard]] V* get(const K& key); void insert(K key, V value); // assumes no duplicates bool remove(const K& key); // returns true if anything was removed QList> values; }; ///! Creates instances of a component based on a given model. /// Creates and destroys instances of the given component when the given property changes. /// /// `Variants` is similar to [Repeater] except it is for *non Item* objects, and acts as /// a reload scope. /// /// Each non duplicate value passed to [model](#prop.model) will create a new instance of /// [delegate](#prop.delegate) with its `modelData` property set to that value. /// /// See [Quickshell.screens] for an example of using `Variants` to create copies of a window per /// screen. /// /// > [!WARNING] BUG: Variants currently fails to reload children if the variant set is changed as /// > it is instantiated. (usually due to a mutation during variant creation) /// /// [Repeater]: https://doc.qt.io/qt-6/qml-qtquick-repeater.html /// [Quickshell.screens]: ../quickshell#prop.screens class Variants: public Reloadable { Q_OBJECT; /// The component to create instances of. /// /// The delegate should define a `modelData` property that will be popuplated with a value /// from the [model](#prop.model). Q_PROPERTY(QQmlComponent* delegate MEMBER mDelegate); /// The list of sets of properties to create instances with. /// Each set creates an instance of the component, which are updated when the input sets update. QSDOC_PROPERTY_OVERRIDE(QList model READ model WRITE setModel NOTIFY modelChanged); QSDOC_HIDE Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged); /// Current instances of the delegate. Q_PROPERTY(QQmlListProperty instances READ instances NOTIFY instancesChanged); Q_CLASSINFO("DefaultProperty", "delegate"); QML_ELEMENT; public: explicit Variants(QObject* parent = nullptr): Reloadable(parent) {} void onReload(QObject* oldInstance) override; void componentComplete() override; [[nodiscard]] QVariant model() const; void setModel(const QVariant& model); QQmlListProperty instances(); signals: void modelChanged(); void instancesChanged(); private: static qsizetype instanceCount(QQmlListProperty* prop); static QObject* instanceAt(QQmlListProperty* prop, qsizetype i); void updateVariants(); QQmlComponent* mDelegate = nullptr; QVariantList mModel; AwfulMap mInstances; bool loaded = false; };