forked from quickshell/quickshell
		
	service/notifications: adopt bindable properties
This commit is contained in:
		
							parent
							
								
									abb900b7ff
								
							
						
					
					
						commit
						a13c9d91b5
					
				
					 2 changed files with 81 additions and 112 deletions
				
			
		| 
						 | 
				
			
			@ -3,14 +3,16 @@
 | 
			
		|||
 | 
			
		||||
#include <qcontainerfwd.h>
 | 
			
		||||
#include <qdbusargument.h>
 | 
			
		||||
#include <qlist.h>
 | 
			
		||||
#include <qlogging.h>
 | 
			
		||||
#include <qloggingcategory.h>
 | 
			
		||||
#include <qobject.h>
 | 
			
		||||
#include <qproperty.h>
 | 
			
		||||
#include <qtmetamacros.h>
 | 
			
		||||
#include <qtypes.h>
 | 
			
		||||
 | 
			
		||||
#include "../../core/desktopentry.hpp"
 | 
			
		||||
#include "../../core/iconimageprovider.hpp"
 | 
			
		||||
#include "../../core/util.hpp"
 | 
			
		||||
#include "dbusimage.hpp"
 | 
			
		||||
#include "server.hpp"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -84,34 +86,51 @@ void Notification::updateProperties(
 | 
			
		|||
    QVariantMap hints,
 | 
			
		||||
    qint32 expireTimeout
 | 
			
		||||
) {
 | 
			
		||||
	auto urgency = hints.contains("urgency") ? hints.value("urgency").value<quint8>()
 | 
			
		||||
	                                         : static_cast<quint8>(NotificationUrgency::Normal);
 | 
			
		||||
	Qt::beginPropertyUpdateGroup();
 | 
			
		||||
 | 
			
		||||
	auto hasActionIcons = hints.value("action-icons").value<bool>();
 | 
			
		||||
	auto resident = hints.value("resident").value<bool>();
 | 
			
		||||
	auto transient = hints.value("transient").value<bool>();
 | 
			
		||||
	auto desktopEntry = hints.value("desktop-entry").value<QString>();
 | 
			
		||||
	this->bExpireTimeout = expireTimeout;
 | 
			
		||||
	this->bAppName = appName;
 | 
			
		||||
	this->bSummary = summary;
 | 
			
		||||
	this->bBody = body;
 | 
			
		||||
	this->bHasActionIcons = hints.value("action-icons").toBool();
 | 
			
		||||
	this->bResident = hints.value("resident").toBool();
 | 
			
		||||
	this->bTransient = hints.value("transient").toBool();
 | 
			
		||||
	this->bDesktopEntry = hints.value("desktop-entry").toString();
 | 
			
		||||
 | 
			
		||||
	this->bUrgency = hints.contains("urgency")
 | 
			
		||||
	                   ? hints.value("urgency").value<NotificationUrgency::Enum>()
 | 
			
		||||
	                   : NotificationUrgency::Normal;
 | 
			
		||||
 | 
			
		||||
	if (appIcon.isEmpty() && !this->bDesktopEntry.value().isEmpty()) {
 | 
			
		||||
		if (auto* entry = DesktopEntryManager::instance()->byId(this->bDesktopEntry.value())) {
 | 
			
		||||
			appIcon = entry->mIcon;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this->bAppIcon = appIcon;
 | 
			
		||||
 | 
			
		||||
	QString imageDataName;
 | 
			
		||||
	if (hints.contains("image-data")) imageDataName = "image-data";
 | 
			
		||||
	else if (hints.contains("image_data")) imageDataName = "image_data";
 | 
			
		||||
	else if (hints.contains("icon_data")) imageDataName = "icon_data";
 | 
			
		||||
 | 
			
		||||
	NotificationImage* imagePixmap = nullptr;
 | 
			
		||||
	QString imagePath;
 | 
			
		||||
 | 
			
		||||
	if (!imageDataName.isEmpty()) {
 | 
			
		||||
		auto value = hints.value(imageDataName).value<QDBusArgument>();
 | 
			
		||||
		DBusNotificationImage image;
 | 
			
		||||
		value >> image;
 | 
			
		||||
		imagePixmap = new NotificationImage(std::move(image), this);
 | 
			
		||||
		if (this->mImagePixmap) this->mImagePixmap->deleteLater();
 | 
			
		||||
		this->mImagePixmap = new NotificationImage(std::move(image), this);
 | 
			
		||||
		imagePath = this->mImagePixmap->url();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// don't store giant byte arrays more than necessary
 | 
			
		||||
	// don't store giant byte arrays longer than necessary
 | 
			
		||||
	hints.remove("image-data");
 | 
			
		||||
	hints.remove("image_data");
 | 
			
		||||
	hints.remove("icon_data");
 | 
			
		||||
 | 
			
		||||
	QString imagePath;
 | 
			
		||||
	if (!imagePixmap) {
 | 
			
		||||
	if (!this->mImagePixmap) {
 | 
			
		||||
		QString imagePathName;
 | 
			
		||||
		if (hints.contains("image-path")) imagePathName = "image-path";
 | 
			
		||||
		else if (hints.contains("image_path")) imagePathName = "image_path";
 | 
			
		||||
| 
						 | 
				
			
			@ -125,32 +144,10 @@ void Notification::updateProperties(
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (appIcon.isEmpty() && !desktopEntry.isEmpty()) {
 | 
			
		||||
		if (auto* entry = DesktopEntryManager::instance()->byId(desktopEntry)) {
 | 
			
		||||
			appIcon = entry->mIcon;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	this->bImage = imagePath;
 | 
			
		||||
	this->bHints = hints;
 | 
			
		||||
 | 
			
		||||
	auto expireTimeoutChanged = this->setExpireTimeout(expireTimeout);
 | 
			
		||||
	auto appNameChanged = this->setAppName(appName);
 | 
			
		||||
	auto appIconChanged = this->setAppIcon(appIcon);
 | 
			
		||||
	auto summaryChanged = this->setSummary(summary);
 | 
			
		||||
	auto bodyChanged = this->setBody(body);
 | 
			
		||||
	auto urgencyChanged = this->setUrgency(static_cast<NotificationUrgency::Enum>(urgency));
 | 
			
		||||
	auto hasActionIconsChanged = this->setHasActionIcons(hasActionIcons);
 | 
			
		||||
	auto residentChanged = this->setResident(resident);
 | 
			
		||||
	auto transientChanged = this->setTransient(transient);
 | 
			
		||||
	auto desktopEntryChanged = this->setDesktopEntry(desktopEntry);
 | 
			
		||||
	DEFINE_DROP_EMIT_IF(imagePixmap || imagePath != this->mImagePath, this, imageChanged);
 | 
			
		||||
	auto hintsChanged = this->setHints(hints);
 | 
			
		||||
 | 
			
		||||
	NotificationImage* oldImage = nullptr;
 | 
			
		||||
 | 
			
		||||
	if (imageChanged) {
 | 
			
		||||
		oldImage = this->mImagePixmap;
 | 
			
		||||
		this->mImagePixmap = imagePixmap;
 | 
			
		||||
		this->mImagePath = imagePath;
 | 
			
		||||
	}
 | 
			
		||||
	Qt::endPropertyUpdateGroup();
 | 
			
		||||
 | 
			
		||||
	bool actionsChanged = false;
 | 
			
		||||
	auto deletedActions = QVector<NotificationAction*>();
 | 
			
		||||
| 
						 | 
				
			
			@ -191,32 +188,16 @@ void Notification::updateProperties(
 | 
			
		|||
		                            << "sent an action set of an invalid length.";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DropEmitter::call(
 | 
			
		||||
	    expireTimeoutChanged,
 | 
			
		||||
	    appNameChanged,
 | 
			
		||||
	    appIconChanged,
 | 
			
		||||
	    summaryChanged,
 | 
			
		||||
	    bodyChanged,
 | 
			
		||||
	    urgencyChanged,
 | 
			
		||||
	    hasActionIconsChanged,
 | 
			
		||||
	    residentChanged,
 | 
			
		||||
	    transientChanged,
 | 
			
		||||
	    desktopEntryChanged,
 | 
			
		||||
	    imageChanged,
 | 
			
		||||
	    hintsChanged
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	if (actionsChanged) emit this->actionsChanged();
 | 
			
		||||
 | 
			
		||||
	for (auto* action: deletedActions) {
 | 
			
		||||
		delete action;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	delete oldImage;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
quint32 Notification::id() const { return this->mId; }
 | 
			
		||||
bool Notification::isTracked() const { return this->mCloseReason == 0; }
 | 
			
		||||
QList<NotificationAction*> Notification::actions() const { return this->mActions; }
 | 
			
		||||
NotificationCloseReason::Enum Notification::closeReason() const { return this->mCloseReason; }
 | 
			
		||||
 | 
			
		||||
void Notification::setTracked(bool tracked) {
 | 
			
		||||
| 
						 | 
				
			
			@ -228,26 +209,4 @@ void Notification::setTracked(bool tracked) {
 | 
			
		|||
bool Notification::isLastGeneration() const { return this->mLastGeneration; }
 | 
			
		||||
void Notification::setLastGeneration() { this->mLastGeneration = true; }
 | 
			
		||||
 | 
			
		||||
DEFINE_MEMBER_GETSET(Notification, expireTimeout, setExpireTimeout);
 | 
			
		||||
DEFINE_MEMBER_GETSET(Notification, appName, setAppName);
 | 
			
		||||
DEFINE_MEMBER_GETSET(Notification, appIcon, setAppIcon);
 | 
			
		||||
DEFINE_MEMBER_GETSET(Notification, summary, setSummary);
 | 
			
		||||
DEFINE_MEMBER_GETSET(Notification, body, setBody);
 | 
			
		||||
DEFINE_MEMBER_GETSET(Notification, urgency, setUrgency);
 | 
			
		||||
DEFINE_MEMBER_GET(Notification, actions);
 | 
			
		||||
DEFINE_MEMBER_GETSET(Notification, hasActionIcons, setHasActionIcons);
 | 
			
		||||
DEFINE_MEMBER_GETSET(Notification, resident, setResident);
 | 
			
		||||
DEFINE_MEMBER_GETSET(Notification, transient, setTransient);
 | 
			
		||||
DEFINE_MEMBER_GETSET(Notification, desktopEntry, setDesktopEntry);
 | 
			
		||||
 | 
			
		||||
QString Notification::image() const {
 | 
			
		||||
	if (this->mImagePixmap) {
 | 
			
		||||
		return this->mImagePixmap->url();
 | 
			
		||||
	} else {
 | 
			
		||||
		return this->mImagePath;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFINE_MEMBER_GETSET(Notification, hints, setHints);
 | 
			
		||||
 | 
			
		||||
} // namespace qs::service::notifications
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
#include <utility>
 | 
			
		||||
 | 
			
		||||
#include <qcontainerfwd.h>
 | 
			
		||||
#include <qlist.h>
 | 
			
		||||
#include <qmap.h>
 | 
			
		||||
#include <qobject.h>
 | 
			
		||||
#include <qqmlintegration.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -80,18 +81,18 @@ class Notification
 | 
			
		|||
	/// if @@NotificationServer.keepOnReload is true.
 | 
			
		||||
	Q_PROPERTY(bool lastGeneration READ isLastGeneration CONSTANT);
 | 
			
		||||
	/// Time in seconds the notification should be valid for
 | 
			
		||||
	Q_PROPERTY(qreal expireTimeout READ expireTimeout NOTIFY expireTimeoutChanged);
 | 
			
		||||
	Q_PROPERTY(qreal expireTimeout READ expireTimeout NOTIFY expireTimeoutChanged BINDABLE bindableExpireTimeout);
 | 
			
		||||
	/// The sending application's name.
 | 
			
		||||
	Q_PROPERTY(QString appName READ appName NOTIFY appNameChanged);
 | 
			
		||||
	Q_PROPERTY(QString appName READ appName NOTIFY appNameChanged BINDABLE bindableAppName);
 | 
			
		||||
	/// The sending application's icon. If none was provided, then the icon from an associated
 | 
			
		||||
	/// desktop entry will be retrieved. If none was found then "".
 | 
			
		||||
	Q_PROPERTY(QString appIcon READ appIcon NOTIFY appIconChanged);
 | 
			
		||||
	Q_PROPERTY(QString appIcon READ appIcon NOTIFY appIconChanged BINDABLE bindableAppIcon);
 | 
			
		||||
	/// The image associated with this notification, or "" if none.
 | 
			
		||||
	Q_PROPERTY(QString summary READ summary NOTIFY summaryChanged);
 | 
			
		||||
	Q_PROPERTY(QString body READ body NOTIFY bodyChanged);
 | 
			
		||||
	Q_PROPERTY(qs::service::notifications::NotificationUrgency::Enum urgency READ urgency NOTIFY urgencyChanged);
 | 
			
		||||
	Q_PROPERTY(QString summary READ summary NOTIFY summaryChanged BINDABLE bindableSummary);
 | 
			
		||||
	Q_PROPERTY(QString body READ body NOTIFY bodyChanged BINDABLE bindableBody);
 | 
			
		||||
	Q_PROPERTY(qs::service::notifications::NotificationUrgency::Enum urgency READ urgency NOTIFY urgencyChanged BINDABLE bindableUrgency);
 | 
			
		||||
	/// Actions that can be taken for this notification.
 | 
			
		||||
	Q_PROPERTY(QVector<qs::service::notifications::NotificationAction*> actions READ actions NOTIFY actionsChanged);
 | 
			
		||||
	Q_PROPERTY(QList<qs::service::notifications::NotificationAction*> actions READ actions NOTIFY actionsChanged);
 | 
			
		||||
	/// If actions associated with this notification have icons available.
 | 
			
		||||
	///
 | 
			
		||||
	/// See @@NotificationAction.identifier for details.
 | 
			
		||||
| 
						 | 
				
			
			@ -136,15 +137,29 @@ public:
 | 
			
		|||
	void close(NotificationCloseReason::Enum reason);
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] quint32 id() const;
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] bool isTracked() const;
 | 
			
		||||
	[[nodiscard]] NotificationCloseReason::Enum closeReason() const;
 | 
			
		||||
	void setTracked(bool tracked);
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] bool isLastGeneration() const;
 | 
			
		||||
	void setLastGeneration();
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] QString image() const;
 | 
			
		||||
	QS_BINDABLE_GETTER(qreal, bExpireTimeout, expireTimeout, bindableExpireTimeout);
 | 
			
		||||
	QS_BINDABLE_GETTER(QString, bAppName, appName, bindableAppName);
 | 
			
		||||
	QS_BINDABLE_GETTER(QString, bAppIcon, appIcon, bindableAppIcon);
 | 
			
		||||
	QS_BINDABLE_GETTER(QString, bSummary, summary, bindableSummary);
 | 
			
		||||
	QS_BINDABLE_GETTER(QString, bBody, body, bindableBody);
 | 
			
		||||
	QS_BINDABLE_GETTER(NotificationUrgency::Enum, bUrgency, urgency, bindableUrgency);
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] QList<NotificationAction*> actions() const;
 | 
			
		||||
 | 
			
		||||
	QS_BINDABLE_GETTER(bool, bHasActionIcons, hasActionIcons, bindableHasActionIcons);
 | 
			
		||||
	QS_BINDABLE_GETTER(bool, bResident, resident, bindableResident);
 | 
			
		||||
	QS_BINDABLE_GETTER(bool, bTransient, transient, bindableTransient);
 | 
			
		||||
	QS_BINDABLE_GETTER(QString, bDesktopEntry, desktopEntry, bindableDesktopEntry);
 | 
			
		||||
	QS_BINDABLE_GETTER(QString, bImage, image, bindableImage);
 | 
			
		||||
	QS_BINDABLE_GETTER(QVariantMap, bHints, hints, bindableHints);
 | 
			
		||||
 | 
			
		||||
	[[nodiscard]] NotificationCloseReason::Enum closeReason() const;
 | 
			
		||||
	void setTracked(bool tracked);
 | 
			
		||||
 | 
			
		||||
signals:
 | 
			
		||||
	/// Sent when a notification has been closed.
 | 
			
		||||
| 
						 | 
				
			
			@ -171,35 +186,30 @@ private:
 | 
			
		|||
	quint32 mId;
 | 
			
		||||
	NotificationCloseReason::Enum mCloseReason = NotificationCloseReason::Dismissed;
 | 
			
		||||
	bool mLastGeneration = false;
 | 
			
		||||
	qreal mExpireTimeout = 0;
 | 
			
		||||
	QString mAppName;
 | 
			
		||||
	QString mAppIcon;
 | 
			
		||||
	QString mSummary;
 | 
			
		||||
	QString mBody;
 | 
			
		||||
	NotificationUrgency::Enum mUrgency = NotificationUrgency::Normal;
 | 
			
		||||
	QVector<NotificationAction*> mActions;
 | 
			
		||||
	bool mHasActionIcons = false;
 | 
			
		||||
	bool mResident = false;
 | 
			
		||||
	bool mTransient = false;
 | 
			
		||||
	QString mImagePath;
 | 
			
		||||
	NotificationImage* mImagePixmap = nullptr;
 | 
			
		||||
	QString mDesktopEntry;
 | 
			
		||||
	QVariantMap mHints;
 | 
			
		||||
	QList<NotificationAction*> mActions;
 | 
			
		||||
 | 
			
		||||
	// clang-format off
 | 
			
		||||
	DECLARE_PRIVATE_MEMBER(Notification, expireTimeout, setExpireTimeout, mExpireTimeout, expireTimeoutChanged);
 | 
			
		||||
	DECLARE_PRIVATE_MEMBER(Notification, appName, setAppName, mAppName, appNameChanged);
 | 
			
		||||
	DECLARE_PRIVATE_MEMBER(Notification, appIcon, setAppIcon, mAppIcon, appIconChanged);
 | 
			
		||||
	DECLARE_PRIVATE_MEMBER(Notification, summary, setSummary, mSummary, summaryChanged);
 | 
			
		||||
	DECLARE_PRIVATE_MEMBER(Notification, body, setBody, mBody, bodyChanged);
 | 
			
		||||
	DECLARE_PRIVATE_MEMBER(Notification, urgency, setUrgency, mUrgency, urgencyChanged);
 | 
			
		||||
	DECLARE_MEMBER_WITH_GET(Notification, actions, mActions, actionsChanged);
 | 
			
		||||
	DECLARE_PRIVATE_MEMBER(Notification, hasActionIcons, setHasActionIcons, mHasActionIcons, hasActionIconsChanged);
 | 
			
		||||
	DECLARE_PRIVATE_MEMBER(Notification, resident, setResident, mResident, residentChanged);
 | 
			
		||||
	DECLARE_PRIVATE_MEMBER(Notification, transient, setTransient, mTransient, transientChanged);
 | 
			
		||||
	DECLARE_PRIVATE_MEMBER(Notification, desktopEntry, setDesktopEntry, mDesktopEntry, desktopEntryChanged);
 | 
			
		||||
	DECLARE_PRIVATE_MEMBER(Notification, hints, setHints, mHints, hintsChanged);
 | 
			
		||||
	Q_OBJECT_BINDABLE_PROPERTY(Notification, qreal, bExpireTimeout, &Notification::expireTimeoutChanged);
 | 
			
		||||
	Q_OBJECT_BINDABLE_PROPERTY(Notification, QString, bAppName, &Notification::appNameChanged);
 | 
			
		||||
	Q_OBJECT_BINDABLE_PROPERTY(Notification, QString, bAppIcon, &Notification::appIconChanged);
 | 
			
		||||
	Q_OBJECT_BINDABLE_PROPERTY(Notification, QString, bSummary, &Notification::summaryChanged);
 | 
			
		||||
	Q_OBJECT_BINDABLE_PROPERTY(Notification, QString, bBody, &Notification::bodyChanged);
 | 
			
		||||
	Q_OBJECT_BINDABLE_PROPERTY(Notification, bool, bHasActionIcons, &Notification::hasActionIconsChanged);
 | 
			
		||||
	Q_OBJECT_BINDABLE_PROPERTY(Notification, bool, bResident, &Notification::residentChanged);
 | 
			
		||||
	Q_OBJECT_BINDABLE_PROPERTY(Notification, bool, bTransient, &Notification::transientChanged);
 | 
			
		||||
	Q_OBJECT_BINDABLE_PROPERTY(Notification, QString, bDesktopEntry, &Notification::desktopEntryChanged);
 | 
			
		||||
	Q_OBJECT_BINDABLE_PROPERTY(Notification, QString, bImage, &Notification::imageChanged);
 | 
			
		||||
	Q_OBJECT_BINDABLE_PROPERTY(Notification, QVariantMap, bHints, &Notification::hintsChanged);
 | 
			
		||||
	// clang-format on
 | 
			
		||||
 | 
			
		||||
	Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(
 | 
			
		||||
	    Notification,
 | 
			
		||||
	    NotificationUrgency::Enum,
 | 
			
		||||
	    bUrgency,
 | 
			
		||||
	    NotificationUrgency::Normal,
 | 
			
		||||
	    &Notification::urgencyChanged
 | 
			
		||||
	);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
///! An action associated with a Notification.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue