summaryrefslogtreecommitdiff
path: root/src/lib/xdgstatusnotifierhost.cpp
diff options
context:
space:
mode:
authorFabien Proriol <fabien.proriol@kazoe.org>2025-05-25 12:13:31 +0200
committerFabien Proriol <fabien.proriol@kazoe.org>2025-05-25 12:13:31 +0200
commit1dbc0e3c88ba271ba35bc3f82e7864c4f35e1236 (patch)
tree8c491cd196e2eff4c59f8c23f566f7ff26981586 /src/lib/xdgstatusnotifierhost.cpp
Initial Commit
Diffstat (limited to 'src/lib/xdgstatusnotifierhost.cpp')
-rw-r--r--src/lib/xdgstatusnotifierhost.cpp187
1 files changed, 187 insertions, 0 deletions
diff --git a/src/lib/xdgstatusnotifierhost.cpp b/src/lib/xdgstatusnotifierhost.cpp
new file mode 100644
index 0000000..49a17b1
--- /dev/null
+++ b/src/lib/xdgstatusnotifierhost.cpp
@@ -0,0 +1,187 @@
+#include "xdgstatusnotifierhost.h"
+#include "XdgStatusNotifierItemIface.h"
+#include "XdgStatusNotifierWatcherIface.h"
+#include <QDBusConnection>
+#include "debug.h"
+
+using namespace org::kde;
+
+namespace xdg {
+ class StatusNotifierHostPrivate {
+ Q_DISABLE_COPY(StatusNotifierHostPrivate)
+ Q_DECLARE_PUBLIC(StatusNotifierHost)
+ StatusNotifierHost * const q_ptr;
+ StatusNotifierHostPrivate(StatusNotifierHost *parent)
+ : q_ptr(parent)
+ , m_bus(QDBusConnection::sessionBus())
+ {};
+
+ QMap<QString, StatusNotifierItem*> m_items;
+ QList<QString> m_itemsorder;
+ StatusNotifierWatcher *m_watcher;
+ QDBusConnection m_bus;
+ QString m_serviceName;
+
+ void addNotifier(QString item)
+ {
+ StatusNotifierItem *stat = new StatusNotifierItem(item.split("/").first(), "/StatusNotifierItem", m_bus, q_ptr);
+ int index = m_itemsorder.size();
+ q_ptr->beginInsertRows(QModelIndex(), index, index);
+ m_itemsorder.append(item);
+ m_items[item] = stat;
+
+ QObject::connect(stat, &StatusNotifierItem::NewAttentionIcon, [index, this](){
+ QVector<int> r;
+ r.append(StatusNotifierHost::AttentionIconNameRole);
+ emit q_ptr->dataChanged(q_ptr->index(index), q_ptr->index(index), r);
+ });
+
+ QObject::connect(stat, &StatusNotifierItem::NewIcon, [index, this](){
+ QVector<int> r;
+ r.append(StatusNotifierHost::IconNameRole);
+ emit q_ptr->dataChanged(q_ptr->index(index), q_ptr->index(index), r);
+ });
+
+ QObject::connect(stat, &StatusNotifierItem::NewOverlayIcon, [index, this](){
+ QVector<int> r;
+ r.append(StatusNotifierHost::OverlayIconNameRole);
+ emit q_ptr->dataChanged(q_ptr->index(index), q_ptr->index(index), r);
+ });
+
+ QObject::connect(stat, &StatusNotifierItem::NewStatus, [index, this](){
+ QVector<int> r;
+ r.append(StatusNotifierHost::StatusRole);
+ emit q_ptr->dataChanged(q_ptr->index(index), q_ptr->index(index), r);
+ });
+
+ QObject::connect(stat, &StatusNotifierItem::NewTitle, [index, this](){
+ QVector<int> r;
+ r.append(StatusNotifierHost::TitleRole);
+ emit q_ptr->dataChanged(q_ptr->index(index), q_ptr->index(index), r);
+ });
+
+ q_ptr->endInsertRows();
+ }
+
+ void removeNotifier(QString item)
+ {
+ int index = m_itemsorder.indexOf(item);
+ q_ptr->beginRemoveRows(QModelIndex(), index, index);
+ m_itemsorder.removeAll(item);
+ m_items[item]->deleteLater();
+ m_items.remove(item);
+ q_ptr->endRemoveRows();
+ }
+ };
+};
+
+using namespace xdg;
+
+StatusNotifierHost::StatusNotifierHost(QObject *parent)
+ : QAbstractListModel{parent}
+ , d_ptr(new StatusNotifierHostPrivate(this))
+{
+ Q_D(StatusNotifierHost);
+
+ d->m_serviceName = "org.kde.StatusNotifierHost-";
+ d->m_serviceName.append(QString::number(QCoreApplication::applicationPid()));
+ qCDebug(SYSTEM_TRAY) << "Register Host service" << d->m_serviceName << ":" << d->m_bus.registerService(d->m_serviceName);
+
+ d->m_watcher = new StatusNotifierWatcher("org.kde.StatusNotifierWatcher", "/StatusNotifierWatcher", d->m_bus, this);
+ qCDebug(SYSTEM_TRAY) << "Find Watcher " << d->m_watcher->isValid() << " with protocol " << d->m_watcher->protocolVersion();
+
+ if(!d->m_watcher->isValid())
+ {
+ qCWarning(SYSTEM_TRAY) << "Can't find watcher org.kde.StatusNotifierWatcher/StatusNotifierWatcher";
+ }
+
+
+ d->m_watcher->RegisterStatusNotifierHost(d->m_serviceName);
+
+ QObject::connect(d->m_watcher, &StatusNotifierWatcher::StatusNotifierItemRegistered, [this](QString in0){
+ Q_D(StatusNotifierHost);
+ d->addNotifier(in0);
+ });
+
+ QObject::connect(d->m_watcher, &StatusNotifierWatcher::StatusNotifierItemUnregistered, [this](QString in0){
+ Q_D(StatusNotifierHost);
+ d->removeNotifier(in0);
+ });
+
+ for(QString item: d->m_watcher->registeredStatusNotifierItems())
+ {
+ d->addNotifier(item);
+ }
+}
+
+StatusNotifierHost::~StatusNotifierHost() = default;
+
+int StatusNotifierHost::rowCount(const QModelIndex &parent) const
+{
+ Q_D(const StatusNotifierHost);
+ return d->m_items.size();
+}
+
+QVariant StatusNotifierHost::data(const QModelIndex &index, int role) const
+{
+ Q_D(const StatusNotifierHost);
+
+ if(index.row() > d->m_itemsorder.count())
+ return QVariant();
+
+ const StatusNotifierItem *stat = d->m_items[d->m_itemsorder[index.row()]];
+
+ switch(role) {
+ case CategoryRole:
+ return stat->category();
+ case IdRole:
+ return stat->id();
+ case TitleRole:
+ return stat->title();
+ case StatusRole:
+ return stat->status();
+ case WindowIdRole:
+ return stat->windowId();
+ case IconNameRole:
+ return stat->iconName();
+ case OverlayIconNameRole:
+ return stat->overlayIconName();
+ case AttentionIconNameRole:
+ return stat->attentionIconName();
+ case AttentionMovieNameRole:
+ return stat->attentionMovieName();
+ }
+
+ return QVariant();
+}
+
+QHash<int, QByteArray> StatusNotifierHost::roleNames() const
+{
+ QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
+ roles[CategoryRole] = "category";
+ roles[IdRole] = "idItem";
+ roles[TitleRole] = "title";
+ roles[StatusRole] = "status";
+ roles[WindowIdRole] = "windowId";
+ roles[IconNameRole] = "iconName";
+ roles[OverlayIconNameRole] = "overlayIconName";
+ roles[AttentionIconNameRole] = "attentionIconName";
+ roles[AttentionMovieNameRole] = "attentionMovieName";
+ return roles;
+}
+
+void StatusNotifierHost::activate(int x, int y, QString id, int mode)
+{
+ Q_D(const StatusNotifierHost);
+ for(const QString &key: d->m_itemsorder)
+ {
+ if(d->m_items[key]->id() == id)
+ {
+ if(mode == 1)
+ d->m_items[key]->SecondaryActivate(x, y);
+ else
+ d->m_items[key]->Activate(x, y);
+ return;
+ }
+ }
+}