forked from quickshell/quickshell
all: replace list properties with ObjectModels
This commit is contained in:
parent
6326f60ce2
commit
5016dbf0d4
11 changed files with 201 additions and 152 deletions
|
@ -26,6 +26,7 @@ qt_add_library(quickshell-core STATIC
|
|||
imageprovider.cpp
|
||||
transformwatcher.cpp
|
||||
boundcomponent.cpp
|
||||
model.cpp
|
||||
)
|
||||
|
||||
set_source_files_properties(main.cpp PROPERTIES COMPILE_DEFINITIONS GIT_REVISION="${GIT_REVISION}")
|
||||
|
|
|
@ -10,5 +10,8 @@
|
|||
#define QSDOC_ELEMENT
|
||||
#define QSDOC_NAMED_ELEMENT(name)
|
||||
|
||||
// change the cname used for this type
|
||||
#define QSDOC_CNAME(name)
|
||||
|
||||
// overridden properties
|
||||
#define QSDOC_PROPERTY_OVERRIDE(...)
|
||||
|
|
67
src/core/model.cpp
Normal file
67
src/core/model.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
#include "model.hpp"
|
||||
|
||||
#include <qabstractitemmodel.h>
|
||||
#include <qhash.h>
|
||||
#include <qobject.h>
|
||||
#include <qqmllist.h>
|
||||
#include <qtmetamacros.h>
|
||||
#include <qtypes.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
qint32 UntypedObjectModel::rowCount(const QModelIndex& parent) const {
|
||||
if (parent != QModelIndex()) return 0;
|
||||
return static_cast<qint32>(this->valuesList.length());
|
||||
}
|
||||
|
||||
QVariant UntypedObjectModel::data(const QModelIndex& index, qint32 role) const {
|
||||
if (role != 0) return QVariant();
|
||||
return QVariant::fromValue(this->valuesList.at(index.row()));
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> UntypedObjectModel::roleNames() const { return {{0, "modelData"}}; }
|
||||
|
||||
QQmlListProperty<QObject> UntypedObjectModel::values() {
|
||||
return QQmlListProperty<QObject>(
|
||||
this,
|
||||
nullptr,
|
||||
&UntypedObjectModel::valuesCount,
|
||||
&UntypedObjectModel::valueAt
|
||||
);
|
||||
}
|
||||
|
||||
qsizetype UntypedObjectModel::valuesCount(QQmlListProperty<QObject>* property) {
|
||||
return static_cast<UntypedObjectModel*>(property->object)->valuesList.count(); // NOLINT
|
||||
}
|
||||
|
||||
QObject* UntypedObjectModel::valueAt(QQmlListProperty<QObject>* property, qsizetype index) {
|
||||
return static_cast<UntypedObjectModel*>(property->object)->valuesList.at(index); // NOLINT
|
||||
}
|
||||
|
||||
void UntypedObjectModel::insertObject(QObject* object, qsizetype index) {
|
||||
auto iindex = index == -1 ? this->valuesList.length() : index;
|
||||
auto intIndex = static_cast<qint32>(iindex);
|
||||
|
||||
this->beginInsertRows(QModelIndex(), intIndex, intIndex);
|
||||
this->valuesList.insert(iindex, object);
|
||||
this->endInsertRows();
|
||||
emit this->valuesChanged();
|
||||
}
|
||||
|
||||
void UntypedObjectModel::removeAt(qsizetype index) {
|
||||
auto intIndex = static_cast<qint32>(index);
|
||||
|
||||
this->beginRemoveRows(QModelIndex(), intIndex, intIndex);
|
||||
this->valuesList.removeAt(index);
|
||||
this->endRemoveRows();
|
||||
emit this->valuesChanged();
|
||||
}
|
||||
|
||||
bool UntypedObjectModel::removeObject(const QObject* object) {
|
||||
auto index = this->valuesList.indexOf(object);
|
||||
if (index == -1) return false;
|
||||
|
||||
this->removeAt(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
qsizetype UntypedObjectModel::indexOf(QObject* object) { return this->valuesList.indexOf(object); }
|
86
src/core/model.hpp
Normal file
86
src/core/model.hpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
#pragma once
|
||||
|
||||
#include <qabstractitemmodel.h>
|
||||
#include <qcontainerfwd.h>
|
||||
#include <qobject.h>
|
||||
#include <qqmlintegration.h>
|
||||
#include <qqmllist.h>
|
||||
#include <qtmetamacros.h>
|
||||
#include <qtypes.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
#include "doc.hpp"
|
||||
|
||||
///! View into a list of objets
|
||||
/// Typed view into a list of objects.
|
||||
///
|
||||
/// An ObjectModel works as a QML [Data Model], allowing efficient interaction with
|
||||
/// components that act on models. It has a single role named `modelData`, to match the
|
||||
/// behavior of lists.
|
||||
/// The same information contained in the list model is available as a normal list
|
||||
/// via the `values` property.
|
||||
///
|
||||
/// #### Differences from a list
|
||||
/// Unlike with a list, the following property binding will never be updated when `model[3]` changes.
|
||||
/// ```qml
|
||||
/// // will not update reactively
|
||||
/// property var foo: model[3]
|
||||
/// ```
|
||||
///
|
||||
/// You can work around this limitation using the `values` property of the model to view it as a list.
|
||||
/// ```qml
|
||||
/// // will update reactively
|
||||
/// property var foo: model.values[3]
|
||||
/// ```
|
||||
///
|
||||
/// [Data Model]: https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.html#qml-data-models
|
||||
class UntypedObjectModel: public QAbstractListModel {
|
||||
QSDOC_CNAME(ObjectModel);
|
||||
Q_OBJECT;
|
||||
/// The content of the object model, as a QML list.
|
||||
/// The values of this property will always be of the type of the model.
|
||||
Q_PROPERTY(QQmlListProperty<QObject> values READ values NOTIFY valuesChanged);
|
||||
QML_NAMED_ELEMENT(ObjectModel);
|
||||
QML_UNCREATABLE("ObjectModels cannot be created directly.");
|
||||
|
||||
public:
|
||||
explicit UntypedObjectModel(QObject* parent): QAbstractListModel(parent) {}
|
||||
|
||||
[[nodiscard]] qint32 rowCount(const QModelIndex& parent) const override;
|
||||
[[nodiscard]] QVariant data(const QModelIndex& index, qint32 role) const override;
|
||||
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
[[nodiscard]] QQmlListProperty<QObject> values();
|
||||
void removeAt(qsizetype index);
|
||||
|
||||
Q_INVOKABLE qsizetype indexOf(QObject* object);
|
||||
|
||||
signals:
|
||||
void valuesChanged();
|
||||
|
||||
protected:
|
||||
void insertObject(QObject* object, qsizetype index = -1);
|
||||
bool removeObject(const QObject* object);
|
||||
|
||||
QVector<QObject*> valuesList;
|
||||
|
||||
private:
|
||||
static qsizetype valuesCount(QQmlListProperty<QObject>* property);
|
||||
static QObject* valueAt(QQmlListProperty<QObject>* property, qsizetype index);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ObjectModel: public UntypedObjectModel {
|
||||
public:
|
||||
explicit ObjectModel(QObject* parent): UntypedObjectModel(parent) {}
|
||||
|
||||
[[nodiscard]] const QVector<T*>& valueList() const {
|
||||
return *reinterpret_cast<const QVector<T*>*>(&this->valuesList); // NOLINT
|
||||
}
|
||||
|
||||
void insertObject(T* object, qsizetype index = -1) {
|
||||
this->UntypedObjectModel::insertObject(object, index);
|
||||
}
|
||||
|
||||
void removeObject(const T* object) { this->UntypedObjectModel::removeObject(object); }
|
||||
};
|
|
@ -18,5 +18,6 @@ headers = [
|
|||
"easingcurve.hpp",
|
||||
"transformwatcher.hpp",
|
||||
"boundcomponent.hpp",
|
||||
"model.hpp",
|
||||
]
|
||||
-----
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue