11#include " item.hpp"
2- #include < utility>
32
3+ #include < qdbuserror.h>
44#include < qdbusextratypes.h>
55#include < qdbusmetatype.h>
66#include < qdbuspendingcall.h>
1616#include < qrect.h>
1717#include < qsize.h>
1818#include < qstring.h>
19+ #include < qstringliteral.h>
1920#include < qtmetamacros.h>
2021#include < qtypes.h>
2122
@@ -58,59 +59,80 @@ StatusNotifierItem::StatusNotifierItem(const QString& address, QObject* parent)
5859 }
5960
6061 // clang-format off
61- QObject::connect (this ->item , &DBusStatusNotifierItem::NewTitle, &this ->pTitle , &AbstractDBusProperty::update);
62- QObject::connect (this ->item , &DBusStatusNotifierItem::NewIcon, &this ->pIconName , &AbstractDBusProperty::update);
63- QObject::connect (this ->item , &DBusStatusNotifierItem::NewIcon, &this ->pIconPixmaps , &AbstractDBusProperty::update);
64- QObject::connect (this ->item , &DBusStatusNotifierItem::NewIcon, &this ->pIconThemePath , &AbstractDBusProperty::update);
65- QObject::connect (this ->item , &DBusStatusNotifierItem::NewOverlayIcon, &this ->pOverlayIconName , &AbstractDBusProperty::update);
66- QObject::connect (this ->item , &DBusStatusNotifierItem::NewOverlayIcon, &this ->pOverlayIconPixmaps , &AbstractDBusProperty::update);
67- QObject::connect (this ->item , &DBusStatusNotifierItem::NewOverlayIcon, &this ->pIconThemePath , &AbstractDBusProperty::update);
68- QObject::connect (this ->item , &DBusStatusNotifierItem::NewAttentionIcon, &this ->pAttentionIconName , &AbstractDBusProperty::update);
69- QObject::connect (this ->item , &DBusStatusNotifierItem::NewAttentionIcon, &this ->pAttentionIconPixmaps , &AbstractDBusProperty::update);
70- QObject::connect (this ->item , &DBusStatusNotifierItem::NewAttentionIcon, &this ->pIconThemePath , &AbstractDBusProperty::update);
71- QObject::connect (this ->item , &DBusStatusNotifierItem::NewToolTip, &this ->pTooltip , &AbstractDBusProperty::update);
72-
73- QObject::connect (&this ->pIconThemePath , &AbstractDBusProperty::changed, this , &StatusNotifierItem::updateIcon);
74- QObject::connect (&this ->pIconName , &AbstractDBusProperty::changed, this , &StatusNotifierItem::updateIcon);
75- QObject::connect (&this ->pAttentionIconName , &AbstractDBusProperty::changed, this , &StatusNotifierItem::updateIcon);
76- QObject::connect (&this ->pOverlayIconName , &AbstractDBusProperty::changed, this , &StatusNotifierItem::updateIcon);
77- QObject::connect (&this ->pIconPixmaps , &AbstractDBusProperty::changed, this , &StatusNotifierItem::updateIcon);
78- QObject::connect (&this ->pAttentionIconPixmaps , &AbstractDBusProperty::changed, this , &StatusNotifierItem::updateIcon);
79- QObject::connect (&this ->pOverlayIconPixmaps , &AbstractDBusProperty::changed, this , &StatusNotifierItem::updateIcon);
62+ QObject::connect (this ->item , &DBusStatusNotifierItem::NewTitle, this , [this ]() {
63+ this ->pTitle .requestUpdate ();
64+ });
65+
66+ QObject::connect (this ->item , &DBusStatusNotifierItem::NewIcon, this , [this ]() {
67+ this ->pIconName .requestUpdate ();
68+ this ->pIconPixmaps .requestUpdate ();
69+ this ->pIconThemePath .requestUpdate ();
70+ });
71+
72+ QObject::connect (this ->item , &DBusStatusNotifierItem::NewOverlayIcon, this , [this ]() {
73+ this ->pOverlayIconName .requestUpdate ();
74+ this ->pOverlayIconPixmaps .requestUpdate ();
75+ this ->pIconThemePath .requestUpdate ();
76+ });
77+
78+ QObject::connect (this ->item , &DBusStatusNotifierItem::NewAttentionIcon, this , [this ]() {
79+ this ->pAttentionIconName .requestUpdate ();
80+ this ->pAttentionIconPixmaps .requestUpdate ();
81+ this ->pIconThemePath .requestUpdate ();
82+ });
83+
84+ QObject::connect (this ->item , &DBusStatusNotifierItem::NewToolTip, this , [this ]() {
85+ this ->pTooltip .requestUpdate ();
86+ });
8087
8188 QObject::connect (&this ->properties , &DBusPropertyGroup::getAllFinished, this , &StatusNotifierItem::onGetAllFinished);
8289 QObject::connect (&this ->properties , &DBusPropertyGroup::getAllFailed, this , &StatusNotifierItem::onGetAllFailed);
83- QObject::connect (&this ->pMenuPath , &AbstractDBusProperty::changed, this , &StatusNotifierItem::onMenuPathChanged);
8490 // clang-format on
8591
86- QObject::connect (this ->item , &DBusStatusNotifierItem::NewStatus, this , [this ](QString value) {
87- qCDebug (logStatusNotifierItem) << " Received update for" << this ->pStatus .toString () << value;
88- this ->pStatus .set (std::move (value));
92+ this ->bIcon .setBinding ([this ]() -> QString {
93+ if (this ->bStatus .value () == Status::NeedsAttention) {
94+ auto name = this ->bAttentionIconName .value ();
95+ if (!name.isEmpty ())
96+ return IconImageProvider::requestString (name, this ->bIconThemePath .value ());
97+ } else {
98+ auto name = this ->bIconName .value ();
99+ auto overlayName = this ->bOverlayIconName .value ();
100+ if (!name.isEmpty () && overlayName.isEmpty ())
101+ return IconImageProvider::requestString (name, this ->bIconThemePath .value ());
102+ }
103+
104+ return this ->imageHandle .url () % " /" % QString::number (this ->pixmapIndex );
89105 });
90106
107+ this ->bHasMenu .setBinding ([this ]() { return !this ->bMenuPath .value ().path ().isEmpty (); });
108+
109+ QObject::connect (
110+ this ->item ,
111+ &DBusStatusNotifierItem::NewStatus,
112+ this ,
113+ [this ](const QString& value) {
114+ auto result = DBusDataTransform<Status::Enum>::fromWire (value);
115+
116+ if (result.isValid ()) {
117+ this ->bStatus = result.value ;
118+ qCDebug (logStatusNotifierItem)
119+ << " Received status update for" << this ->properties .toString () << result.value ;
120+ } else {
121+ qCWarning (logStatusNotifierItem)
122+ << " Received invalid status update for" << this ->properties .toString () << value;
123+ }
124+ }
125+ );
126+
91127 this ->properties .setInterface (this ->item );
92128 this ->properties .updateAllViaGetAll ();
93129}
94130
95131bool StatusNotifierItem::isValid () const { return this ->item ->isValid (); }
96132bool StatusNotifierItem::isReady () const { return this ->mReady ; }
97133
98- QString StatusNotifierItem::iconId () const {
99- if (this ->pStatus .get () == " NeedsAttention" ) {
100- auto name = this ->pAttentionIconName .get ();
101- if (!name.isEmpty ()) return IconImageProvider::requestString (name, this ->pIconThemePath .get ());
102- } else {
103- auto name = this ->pIconName .get ();
104- auto overlayName = this ->pOverlayIconName .get ();
105- if (!name.isEmpty () && overlayName.isEmpty ())
106- return IconImageProvider::requestString (name, this ->pIconThemePath .get ());
107- }
108-
109- return this ->imageHandle .url () + " /" + QString::number (this ->iconIndex );
110- }
111-
112134QPixmap StatusNotifierItem::createPixmap (const QSize& size) const {
113- auto needsAttention = this ->pStatus . get () == " NeedsAttention" ;
135+ auto needsAttention = this ->bStatus . value () == Status:: NeedsAttention;
114136
115137 auto closestPixmap = [](const QSize& size, const DBusSniIconPixmapList& pixmaps) {
116138 const DBusSniIconPixmap* ret = nullptr ;
@@ -135,11 +157,11 @@ QPixmap StatusNotifierItem::createPixmap(const QSize& size) const {
135157
136158 QPixmap pixmap;
137159 if (needsAttention) {
138- if (!this ->pAttentionIconName . get ().isEmpty ()) {
139- auto icon = QIcon::fromTheme (this ->pAttentionIconName . get ());
160+ if (!this ->bAttentionIconName . value ().isEmpty ()) {
161+ auto icon = QIcon::fromTheme (this ->bAttentionIconName . value ());
140162 pixmap = icon.pixmap (size.width (), size.height ());
141163 } else {
142- const auto * icon = closestPixmap (size, this ->pAttentionIconPixmaps . get ());
164+ const auto * icon = closestPixmap (size, this ->bAttentionIconPixmaps . value ());
143165
144166 if (icon != nullptr ) {
145167 const auto image =
@@ -149,11 +171,11 @@ QPixmap StatusNotifierItem::createPixmap(const QSize& size) const {
149171 }
150172 }
151173 } else {
152- if (!this ->pIconName . get ().isEmpty ()) {
153- auto icon = QIcon::fromTheme (this ->pIconName . get ());
174+ if (!this ->bIconName . value ().isEmpty ()) {
175+ auto icon = QIcon::fromTheme (this ->bIconName . value ());
154176 pixmap = icon.pixmap (size.width (), size.height ());
155177 } else {
156- const auto * icon = closestPixmap (size, this ->pIconPixmaps . get ());
178+ const auto * icon = closestPixmap (size, this ->bIconPixmaps . value ());
157179
158180 if (icon != nullptr ) {
159181 const auto image =
@@ -164,11 +186,11 @@ QPixmap StatusNotifierItem::createPixmap(const QSize& size) const {
164186 }
165187
166188 QPixmap overlay;
167- if (!this ->pOverlayIconName . get ().isEmpty ()) {
168- auto icon = QIcon::fromTheme (this ->pOverlayIconName . get ());
189+ if (!this ->bOverlayIconName . value ().isEmpty ()) {
190+ auto icon = QIcon::fromTheme (this ->bOverlayIconName . value ());
169191 overlay = icon.pixmap (pixmap.width (), pixmap.height ());
170192 } else {
171- const auto * icon = closestPixmap (pixmap.size (), this ->pOverlayIconPixmaps . get ());
193+ const auto * icon = closestPixmap (pixmap.size (), this ->bOverlayIconPixmaps . value ());
172194
173195 if (icon != nullptr ) {
174196 const auto image =
@@ -231,17 +253,14 @@ void StatusNotifierItem::scroll(qint32 delta, bool horizontal) const {
231253 this ->item ->Scroll (delta, horizontal ? " horizontal" : " vertical" );
232254}
233255
234- void StatusNotifierItem::updateIcon () {
235- this ->iconIndex ++;
236- emit this ->iconChanged ();
237- }
256+ void StatusNotifierItem::updatePixmapIndex () { this ->pixmapIndex = this ->pixmapIndex + 1 ; }
238257
239258DBusMenuHandle* StatusNotifierItem::menuHandle () {
240- return this ->pMenuPath . get ().path ().isEmpty () ? nullptr : &this ->mMenuHandle ;
259+ return this ->bMenuPath . value ().path ().isEmpty () ? nullptr : &this ->mMenuHandle ;
241260}
242261
243262void StatusNotifierItem::onMenuPathChanged () {
244- this ->mMenuHandle .setAddress (this ->item ->service (), this ->pMenuPath . get ().path ());
263+ this ->mMenuHandle .setAddress (this ->item ->service (), this ->bMenuPath . value ().path ());
245264}
246265
247266void StatusNotifierItem::onGetAllFinished () {
@@ -282,41 +301,6 @@ TrayImageHandle::requestPixmap(const QString& /*unused*/, QSize* size, const QSi
282301 return pixmap;
283302}
284303
285- QString StatusNotifierItem::id () const { return this ->pId .get (); }
286- QString StatusNotifierItem::title () const { return this ->pTitle .get (); }
287-
288- Status::Enum StatusNotifierItem::status () const {
289- auto status = this ->pStatus .get ();
290-
291- if (status == " Passive" ) return Status::Passive;
292- if (status == " Active" ) return Status::Active;
293- if (status == " NeedsAttention" ) return Status::NeedsAttention;
294-
295- qCWarning (logStatusNotifierItem) << " Nonconformant StatusNotifierItem status" << status
296- << " returned for" << this ->properties .toString ();
297-
298- return Status::Passive;
299- }
300-
301- Category::Enum StatusNotifierItem::category () const {
302- auto category = this ->pCategory .get ();
303-
304- if (category == " ApplicationStatus" ) return Category::ApplicationStatus;
305- if (category == " SystemServices" ) return Category::SystemServices;
306- if (category == " Hardware" ) return Category::Hardware;
307-
308- qCWarning (logStatusNotifierItem) << " Nonconformant StatusNotifierItem category" << category
309- << " returned for" << this ->properties .toString ();
310-
311- return Category::ApplicationStatus;
312- }
313-
314- QString StatusNotifierItem::tooltipTitle () const { return this ->pTooltip .get ().title ; }
315- QString StatusNotifierItem::tooltipDescription () const { return this ->pTooltip .get ().description ; }
316-
317- bool StatusNotifierItem::hasMenu () const { return !this ->pMenuPath .get ().path ().isEmpty (); }
318- bool StatusNotifierItem::onlyMenu () const { return this ->pIsMenu .get (); }
319-
320304void StatusNotifierItem::display (QObject* parentWindow, qint32 relativeX, qint32 relativeY) {
321305 if (!this ->menuHandle ()) {
322306 qCritical () << " No menu present for" << this ;
@@ -352,3 +336,30 @@ void StatusNotifierItem::display(QObject* parentWindow, qint32 relativeX, qint32
352336}
353337
354338} // namespace qs::service::sni
339+
340+ namespace qs ::dbus {
341+ using namespace qs ::service::sni;
342+
343+ DBusResult<Status::Enum> DBusDataTransform<Status::Enum>::fromWire(const QString& wire) {
344+ if (wire == QStringLiteral (" Passive" )) return DBusResult (Status::Passive);
345+ if (wire == QStringLiteral (" Active" )) return DBusResult (Status::Active);
346+ if (wire == QStringLiteral (" NeedsAttention" )) return DBusResult (Status::NeedsAttention);
347+
348+ return DBusResult<Status::Enum>(QDBusError (
349+ QDBusError::InvalidArgs,
350+ QString (" Nonconformant StatusNotifierItem Status: %1" ).arg (wire)
351+ ));
352+ }
353+
354+ DBusResult<Category::Enum> DBusDataTransform<Category::Enum>::fromWire(const QString& wire) {
355+ if (wire == " ApplicationStatus" ) return DBusResult (Category::ApplicationStatus);
356+ if (wire == " SystemServices" ) return DBusResult (Category::SystemServices);
357+ if (wire == " Hardware" ) return DBusResult (Category::Hardware);
358+
359+ return DBusResult<Category::Enum>(QDBusError (
360+ QDBusError::InvalidArgs,
361+ QString (" Nonconformant StatusNotifierItem Category: %1" ).arg (wire)
362+ ));
363+ }
364+
365+ } // namespace qs::dbus
0 commit comments