forked from quickshell/quickshell
all: replace list properties with ObjectModels
This commit is contained in:
parent
6326f60ce2
commit
5016dbf0d4
|
@ -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",
|
||||
]
|
||||
-----
|
||||
|
|
|
@ -4,14 +4,12 @@
|
|||
#include <qdbusconnection.h>
|
||||
#include <qdbusconnectioninterface.h>
|
||||
#include <qdbusservicewatcher.h>
|
||||
#include <qlist.h>
|
||||
#include <qlogging.h>
|
||||
#include <qloggingcategory.h>
|
||||
#include <qobject.h>
|
||||
#include <qqmllist.h>
|
||||
#include <qtmetamacros.h>
|
||||
#include <qtypes.h>
|
||||
|
||||
#include "../../core/model.hpp"
|
||||
#include "player.hpp"
|
||||
|
||||
namespace qs::service::mpris {
|
||||
|
@ -74,34 +72,15 @@ void MprisWatcher::onServiceUnregistered(const QString& service) {
|
|||
|
||||
void MprisWatcher::onPlayerReady() {
|
||||
auto* player = qobject_cast<MprisPlayer*>(this->sender());
|
||||
this->readyPlayers.push_back(player);
|
||||
emit this->playersChanged();
|
||||
this->readyPlayers.insertObject(player);
|
||||
}
|
||||
|
||||
void MprisWatcher::onPlayerDestroyed(QObject* object) {
|
||||
auto* player = static_cast<MprisPlayer*>(object); // NOLINT
|
||||
|
||||
if (this->readyPlayers.removeOne(player)) {
|
||||
emit this->playersChanged();
|
||||
}
|
||||
this->readyPlayers.removeObject(player);
|
||||
}
|
||||
|
||||
QQmlListProperty<MprisPlayer> MprisWatcher::players() {
|
||||
return QQmlListProperty<MprisPlayer>(
|
||||
this,
|
||||
nullptr,
|
||||
&MprisWatcher::playersCount,
|
||||
&MprisWatcher::playerAt
|
||||
);
|
||||
}
|
||||
|
||||
qsizetype MprisWatcher::playersCount(QQmlListProperty<MprisPlayer>* property) {
|
||||
return static_cast<MprisWatcher*>(property->object)->readyPlayers.count(); // NOLINT
|
||||
}
|
||||
|
||||
MprisPlayer* MprisWatcher::playerAt(QQmlListProperty<MprisPlayer>* property, qsizetype index) {
|
||||
return static_cast<MprisWatcher*>(property->object)->readyPlayers.at(index); // NOLINT
|
||||
}
|
||||
ObjectModel<MprisPlayer>* MprisWatcher::players() { return &this->readyPlayers; }
|
||||
|
||||
void MprisWatcher::registerPlayer(const QString& address) {
|
||||
if (this->mPlayers.contains(address)) {
|
||||
|
|
|
@ -4,14 +4,13 @@
|
|||
#include <qdbusinterface.h>
|
||||
#include <qdbusservicewatcher.h>
|
||||
#include <qhash.h>
|
||||
#include <qlist.h>
|
||||
#include <qloggingcategory.h>
|
||||
#include <qobject.h>
|
||||
#include <qqmlintegration.h>
|
||||
#include <qqmllist.h>
|
||||
#include <qtmetamacros.h>
|
||||
#include <qtypes.h>
|
||||
|
||||
#include "../../core/model.hpp"
|
||||
#include "player.hpp"
|
||||
|
||||
namespace qs::service::mpris {
|
||||
|
@ -22,15 +21,12 @@ class MprisWatcher: public QObject {
|
|||
QML_NAMED_ELEMENT(Mpris);
|
||||
QML_SINGLETON;
|
||||
/// All connected MPRIS players.
|
||||
Q_PROPERTY(QQmlListProperty<MprisPlayer> players READ players NOTIFY playersChanged);
|
||||
Q_PROPERTY(ObjectModel<MprisPlayer>* players READ players CONSTANT);
|
||||
|
||||
public:
|
||||
explicit MprisWatcher(QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] QQmlListProperty<MprisPlayer> players();
|
||||
|
||||
signals:
|
||||
void playersChanged();
|
||||
[[nodiscard]] ObjectModel<MprisPlayer>* players();
|
||||
|
||||
private slots:
|
||||
void onServiceRegistered(const QString& service);
|
||||
|
@ -39,15 +35,12 @@ private slots:
|
|||
void onPlayerDestroyed(QObject* object);
|
||||
|
||||
private:
|
||||
static qsizetype playersCount(QQmlListProperty<MprisPlayer>* property);
|
||||
static MprisPlayer* playerAt(QQmlListProperty<MprisPlayer>* property, qsizetype index);
|
||||
|
||||
void registerExisting();
|
||||
void registerPlayer(const QString& address);
|
||||
|
||||
QDBusServiceWatcher serviceWatcher;
|
||||
QHash<QString, MprisPlayer*> mPlayers;
|
||||
QList<MprisPlayer*> readyPlayers;
|
||||
ObjectModel<MprisPlayer> readyPlayers {this};
|
||||
};
|
||||
|
||||
} // namespace qs::service::mpris
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <qtypes.h>
|
||||
#include <qvariant.h>
|
||||
|
||||
#include "../../core/model.hpp"
|
||||
#include "connection.hpp"
|
||||
#include "link.hpp"
|
||||
#include "metadata.hpp"
|
||||
|
@ -65,88 +66,43 @@ Pipewire::Pipewire(QObject* parent): QObject(parent) {
|
|||
// clang-format on
|
||||
}
|
||||
|
||||
QQmlListProperty<PwNodeIface> Pipewire::nodes() {
|
||||
return QQmlListProperty<PwNodeIface>(this, nullptr, &Pipewire::nodesCount, &Pipewire::nodeAt);
|
||||
}
|
||||
|
||||
qsizetype Pipewire::nodesCount(QQmlListProperty<PwNodeIface>* property) {
|
||||
return static_cast<Pipewire*>(property->object)->mNodes.count(); // NOLINT
|
||||
}
|
||||
|
||||
PwNodeIface* Pipewire::nodeAt(QQmlListProperty<PwNodeIface>* property, qsizetype index) {
|
||||
return static_cast<Pipewire*>(property->object)->mNodes.at(index); // NOLINT
|
||||
}
|
||||
ObjectModel<PwNodeIface>* Pipewire::nodes() { return &this->mNodes; }
|
||||
|
||||
void Pipewire::onNodeAdded(PwNode* node) {
|
||||
auto* iface = PwNodeIface::instance(node);
|
||||
QObject::connect(iface, &QObject::destroyed, this, &Pipewire::onNodeRemoved);
|
||||
|
||||
this->mNodes.push_back(iface);
|
||||
emit this->nodesChanged();
|
||||
this->mNodes.insertObject(iface);
|
||||
}
|
||||
|
||||
void Pipewire::onNodeRemoved(QObject* object) {
|
||||
auto* iface = static_cast<PwNodeIface*>(object); // NOLINT
|
||||
this->mNodes.removeOne(iface);
|
||||
emit this->nodesChanged();
|
||||
this->mNodes.removeObject(iface);
|
||||
}
|
||||
|
||||
QQmlListProperty<PwLinkIface> Pipewire::links() {
|
||||
return QQmlListProperty<PwLinkIface>(this, nullptr, &Pipewire::linksCount, &Pipewire::linkAt);
|
||||
}
|
||||
|
||||
qsizetype Pipewire::linksCount(QQmlListProperty<PwLinkIface>* property) {
|
||||
return static_cast<Pipewire*>(property->object)->mLinks.count(); // NOLINT
|
||||
}
|
||||
|
||||
PwLinkIface* Pipewire::linkAt(QQmlListProperty<PwLinkIface>* property, qsizetype index) {
|
||||
return static_cast<Pipewire*>(property->object)->mLinks.at(index); // NOLINT
|
||||
}
|
||||
ObjectModel<PwLinkIface>* Pipewire::links() { return &this->mLinks; }
|
||||
|
||||
void Pipewire::onLinkAdded(PwLink* link) {
|
||||
auto* iface = PwLinkIface::instance(link);
|
||||
QObject::connect(iface, &QObject::destroyed, this, &Pipewire::onLinkRemoved);
|
||||
|
||||
this->mLinks.push_back(iface);
|
||||
emit this->linksChanged();
|
||||
this->mLinks.insertObject(iface);
|
||||
}
|
||||
|
||||
void Pipewire::onLinkRemoved(QObject* object) {
|
||||
auto* iface = static_cast<PwLinkIface*>(object); // NOLINT
|
||||
this->mLinks.removeOne(iface);
|
||||
emit this->linksChanged();
|
||||
this->mLinks.removeObject(iface);
|
||||
}
|
||||
|
||||
QQmlListProperty<PwLinkGroupIface> Pipewire::linkGroups() {
|
||||
return QQmlListProperty<PwLinkGroupIface>(
|
||||
this,
|
||||
nullptr,
|
||||
&Pipewire::linkGroupsCount,
|
||||
&Pipewire::linkGroupAt
|
||||
);
|
||||
}
|
||||
|
||||
qsizetype Pipewire::linkGroupsCount(QQmlListProperty<PwLinkGroupIface>* property) {
|
||||
return static_cast<Pipewire*>(property->object)->mLinkGroups.count(); // NOLINT
|
||||
}
|
||||
|
||||
PwLinkGroupIface*
|
||||
Pipewire::linkGroupAt(QQmlListProperty<PwLinkGroupIface>* property, qsizetype index) {
|
||||
return static_cast<Pipewire*>(property->object)->mLinkGroups.at(index); // NOLINT
|
||||
}
|
||||
ObjectModel<PwLinkGroupIface>* Pipewire::linkGroups() { return &this->mLinkGroups; }
|
||||
|
||||
void Pipewire::onLinkGroupAdded(PwLinkGroup* linkGroup) {
|
||||
auto* iface = PwLinkGroupIface::instance(linkGroup);
|
||||
QObject::connect(iface, &QObject::destroyed, this, &Pipewire::onLinkGroupRemoved);
|
||||
|
||||
this->mLinkGroups.push_back(iface);
|
||||
emit this->linkGroupsChanged();
|
||||
this->mLinkGroups.insertObject(iface);
|
||||
}
|
||||
|
||||
void Pipewire::onLinkGroupRemoved(QObject* object) {
|
||||
auto* iface = static_cast<PwLinkGroupIface*>(object); // NOLINT
|
||||
this->mLinkGroups.removeOne(iface);
|
||||
emit this->linkGroupsChanged();
|
||||
this->mLinkGroups.removeObject(iface);
|
||||
}
|
||||
|
||||
PwNodeIface* Pipewire::defaultAudioSink() const { // NOLINT
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <qtmetamacros.h>
|
||||
#include <qtypes.h>
|
||||
|
||||
#include "../../core/model.hpp"
|
||||
#include "link.hpp"
|
||||
#include "node.hpp"
|
||||
#include "registry.hpp"
|
||||
|
@ -52,11 +53,11 @@ class Pipewire: public QObject {
|
|||
Q_OBJECT;
|
||||
// clang-format off
|
||||
/// All pipewire nodes.
|
||||
Q_PROPERTY(QQmlListProperty<PwNodeIface> nodes READ nodes NOTIFY nodesChanged);
|
||||
Q_PROPERTY(ObjectModel<PwNodeIface>* nodes READ nodes CONSTANT);
|
||||
/// All pipewire links.
|
||||
Q_PROPERTY(QQmlListProperty<PwLinkIface> links READ links NOTIFY linksChanged);
|
||||
Q_PROPERTY(ObjectModel<PwLinkIface>* links READ links CONSTANT);
|
||||
/// All pipewire link groups.
|
||||
Q_PROPERTY(QQmlListProperty<PwLinkGroupIface> linkGroups READ linkGroups NOTIFY linkGroupsChanged);
|
||||
Q_PROPERTY(ObjectModel<PwLinkGroupIface>* linkGroups READ linkGroups CONSTANT);
|
||||
/// The default audio sink or `null`.
|
||||
Q_PROPERTY(PwNodeIface* defaultAudioSink READ defaultAudioSink NOTIFY defaultAudioSinkChanged);
|
||||
/// The default audio source or `null`.
|
||||
|
@ -68,16 +69,13 @@ class Pipewire: public QObject {
|
|||
public:
|
||||
explicit Pipewire(QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] QQmlListProperty<PwNodeIface> nodes();
|
||||
[[nodiscard]] QQmlListProperty<PwLinkIface> links();
|
||||
[[nodiscard]] QQmlListProperty<PwLinkGroupIface> linkGroups();
|
||||
[[nodiscard]] ObjectModel<PwNodeIface>* nodes();
|
||||
[[nodiscard]] ObjectModel<PwLinkIface>* links();
|
||||
[[nodiscard]] ObjectModel<PwLinkGroupIface>* linkGroups();
|
||||
[[nodiscard]] PwNodeIface* defaultAudioSink() const;
|
||||
[[nodiscard]] PwNodeIface* defaultAudioSource() const;
|
||||
|
||||
signals:
|
||||
void nodesChanged();
|
||||
void linksChanged();
|
||||
void linkGroupsChanged();
|
||||
void defaultAudioSinkChanged();
|
||||
void defaultAudioSourceChanged();
|
||||
|
||||
|
@ -90,17 +88,9 @@ private slots:
|
|||
void onLinkGroupRemoved(QObject* object);
|
||||
|
||||
private:
|
||||
static qsizetype nodesCount(QQmlListProperty<PwNodeIface>* property);
|
||||
static PwNodeIface* nodeAt(QQmlListProperty<PwNodeIface>* property, qsizetype index);
|
||||
static qsizetype linksCount(QQmlListProperty<PwLinkIface>* property);
|
||||
static PwLinkIface* linkAt(QQmlListProperty<PwLinkIface>* property, qsizetype index);
|
||||
static qsizetype linkGroupsCount(QQmlListProperty<PwLinkGroupIface>* property);
|
||||
static PwLinkGroupIface*
|
||||
linkGroupAt(QQmlListProperty<PwLinkGroupIface>* property, qsizetype index);
|
||||
|
||||
QVector<PwNodeIface*> mNodes;
|
||||
QVector<PwLinkIface*> mLinks;
|
||||
QVector<PwLinkGroupIface*> mLinkGroups;
|
||||
ObjectModel<PwNodeIface> mNodes {this};
|
||||
ObjectModel<PwLinkIface> mLinks {this};
|
||||
ObjectModel<PwLinkGroupIface> mLinkGroups {this};
|
||||
};
|
||||
|
||||
///! Tracks all link connections to a given node.
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <qtmetamacros.h>
|
||||
#include <qtypes.h>
|
||||
|
||||
#include "../../core/model.hpp"
|
||||
#include "../../dbus/dbusmenu/dbusmenu.hpp"
|
||||
#include "../../dbus/properties.hpp"
|
||||
#include "host.hpp"
|
||||
|
@ -106,46 +107,25 @@ SystemTray::SystemTray(QObject* parent): QObject(parent) {
|
|||
// clang-format on
|
||||
|
||||
for (auto* item: host->items()) {
|
||||
this->mItems.push_back(new SystemTrayItem(item, this));
|
||||
this->mItems.insertObject(new SystemTrayItem(item, this));
|
||||
}
|
||||
}
|
||||
|
||||
void SystemTray::onItemRegistered(StatusNotifierItem* item) {
|
||||
this->mItems.push_back(new SystemTrayItem(item, this));
|
||||
emit this->itemsChanged();
|
||||
this->mItems.insertObject(new SystemTrayItem(item, this));
|
||||
}
|
||||
|
||||
void SystemTray::onItemUnregistered(StatusNotifierItem* item) {
|
||||
SystemTrayItem* trayItem = nullptr;
|
||||
|
||||
this->mItems.removeIf([item, &trayItem](SystemTrayItem* testItem) {
|
||||
if (testItem->item == item) {
|
||||
trayItem = testItem;
|
||||
return true;
|
||||
} else return false;
|
||||
});
|
||||
|
||||
emit this->itemsChanged();
|
||||
|
||||
delete trayItem;
|
||||
for (const auto* storedItem: this->mItems.valueList()) {
|
||||
if (storedItem->item == item) {
|
||||
this->mItems.removeObject(storedItem);
|
||||
delete storedItem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QQmlListProperty<SystemTrayItem> SystemTray::items() {
|
||||
return QQmlListProperty<SystemTrayItem>(
|
||||
this,
|
||||
nullptr,
|
||||
&SystemTray::itemsCount,
|
||||
&SystemTray::itemAt
|
||||
);
|
||||
}
|
||||
|
||||
qsizetype SystemTray::itemsCount(QQmlListProperty<SystemTrayItem>* property) {
|
||||
return reinterpret_cast<SystemTray*>(property->object)->mItems.count(); // NOLINT
|
||||
}
|
||||
|
||||
SystemTrayItem* SystemTray::itemAt(QQmlListProperty<SystemTrayItem>* property, qsizetype index) {
|
||||
return reinterpret_cast<SystemTray*>(property->object)->mItems.at(index); // NOLINT
|
||||
}
|
||||
ObjectModel<SystemTrayItem>* SystemTray::items() { return &this->mItems; }
|
||||
|
||||
SystemTrayItem* SystemTrayMenuWatcher::trayItem() const { return this->item; }
|
||||
|
||||
|
|
|
@ -2,10 +2,9 @@
|
|||
|
||||
#include <qobject.h>
|
||||
#include <qqmlintegration.h>
|
||||
#include <qqmllist.h>
|
||||
#include <qtmetamacros.h>
|
||||
#include <qtypes.h>
|
||||
|
||||
#include "../../core/model.hpp"
|
||||
#include "item.hpp"
|
||||
|
||||
namespace SystemTrayStatus { // NOLINT
|
||||
|
@ -108,27 +107,21 @@ signals:
|
|||
class SystemTray: public QObject {
|
||||
Q_OBJECT;
|
||||
/// List of all system tray icons.
|
||||
Q_PROPERTY(QQmlListProperty<SystemTrayItem> items READ items NOTIFY itemsChanged);
|
||||
Q_PROPERTY(ObjectModel<SystemTrayItem>* items READ items CONSTANT);
|
||||
QML_ELEMENT;
|
||||
QML_SINGLETON;
|
||||
|
||||
public:
|
||||
explicit SystemTray(QObject* parent = nullptr);
|
||||
|
||||
[[nodiscard]] QQmlListProperty<SystemTrayItem> items();
|
||||
|
||||
signals:
|
||||
void itemsChanged();
|
||||
[[nodiscard]] ObjectModel<SystemTrayItem>* items();
|
||||
|
||||
private slots:
|
||||
void onItemRegistered(qs::service::sni::StatusNotifierItem* item);
|
||||
void onItemUnregistered(qs::service::sni::StatusNotifierItem* item);
|
||||
|
||||
private:
|
||||
static qsizetype itemsCount(QQmlListProperty<SystemTrayItem>* property);
|
||||
static SystemTrayItem* itemAt(QQmlListProperty<SystemTrayItem>* property, qsizetype index);
|
||||
|
||||
QList<SystemTrayItem*> mItems;
|
||||
ObjectModel<SystemTrayItem> mItems {this};
|
||||
};
|
||||
|
||||
///! Accessor for SystemTrayItem menus.
|
||||
|
|
Loading…
Reference in a new issue