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