/* * * Notification DBus Service implementation * * Copyright (C) 2021 Emanoil Kotsev * * * This file is part of kdbusnotification. * * kdbusnotification is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * kdbusnotification is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with kdbusnotification; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #include #include "NotificationsService.h" #define IMAGE_SIZE 48 #define SRV_VERSION "1.2" #define SPEC_VERSION "1.2" #define NOTIFICATIONS_NAME "Notification Daemon" #define TRINITY_DESKTOP_PROJECT "Trinity Desktop Project" NotificationsService::NotificationsService(TQT_DBusConnection &conn) : org::freedesktop::NotificationsInterface(), mConnection(&conn), mNotificationId(0) { } NotificationsService::~NotificationsService() { notificationMap.clear(); } void NotificationsService::closeNotifyWidget(TQ_UINT32 id, TQ_UINT32 reason) { if (notificationMap[id]) { notificationMap[id]->close(); notificationMap.remove(id); } if ( !emitNotificationClosed(id, reason) ) { tqWarning("Failed to emit DBus signal NotificationClosed"); } } bool NotificationsService::handleSignalSend(const TQT_DBusMessage& reply) { mConnection->send(reply); return true; } TQString NotificationsService::objectPath() const { return TQString(NOTIFICATIONS_DBUS_PATH); } bool NotificationsService::GetCapabilities(TQStringList& return_caps, TQT_DBusError& error) { return_caps.clear(); // action-icons, actions are not implemented // hints are partially implemented (see Capabilities in the docs) // - persistence and sound return_caps << "body" << "body-hyperlinks" << "body-images" << "body-markup" << "icon-static" << "persistence" << "sound"; return true; } void NotificationsService::CloseNotificationAsync(int asyncCallId, TQ_UINT32 id) { closeNotifyWidget(id, 3); // The notification was closed by a call to CloseNotification. CloseNotificationAsyncReply(asyncCallId); } bool NotificationsService::ReloadSettings(TQT_DBusError& error) { // Do nothing return true; } bool NotificationsService::GetServerInformation(TQString& return_name, TQString& return_vendor, TQString& return_version, TQString& return_spec_version, TQT_DBusError& error) { return_name = TQString(NOTIFICATIONS_NAME); return_vendor = TQString(TRINITY_DESKTOP_PROJECT); return_version = TQString(SRV_VERSION); return_spec_version = TQString(SPEC_VERSION); return true; } void NotificationsService::NotifyAsync( int asyncCallId, const TQString& app_name, TQ_UINT32 id, const TQString& icon, const TQString& summary, const TQString& body, const TQStringList& actions, const TQMap& hints, TQ_INT32 timeout) { TQ_UINT32 nId=id; // if (nId != 0 && !notificationMap.contains(nId)) // tqDebug("Requested id %i is not valid", nId); bool found = notificationMap.contains(nId); if (nId == 0 || !notificationMap.contains(nId)) // new notification { nId = ++mNotificationId; notificationMap[nId] = new NotifyWidget(0, app_name.ascii(), this, nId); notificationMap[nId]->setMinimumSize(200, 40); } if(!hints.empty()) { TQString errStr; TQMap::const_iterator it; for ( it = hints.begin(); it != hints.end(); ++it ) { bool ok = true; if(it.key().latin1()=="category") { notificationMap[nId]->setCategory(it.data().value.toString(&ok)); if(!ok) errStr += " category"; } else if (it.key().latin1()=="image-path") { notificationMap[nId]->setImage(it.data().value.toString(&ok)); if(!ok) errStr += " image-path"; } else if (it.key().latin1()=="image-data" || it.key().latin1()=="image_data" || it.key().latin1()=="icon_data") { notificationMap[nId]->setImageData(it.data().value.toTQValueList(&ok)); if(!ok) errStr += " image-data"; } else if (it.key().latin1()=="sound-file") { notificationMap[nId]->setSoundFile(it.data().value.toString(&ok)); if(!ok) errStr += " sound-file"; } else if (it.key().latin1()=="sound-name") { notificationMap[nId]->setSoundName(it.data().value.toString(&ok)); if(!ok) errStr += " sound-name"; } else if (it.key().latin1()=="suppress-sound") { notificationMap[nId]->setSuppressSound(it.data().value.toBool(&ok)); if(!ok) errStr += " suppress-sound"; } else if (it.key().latin1()=="transient") { notificationMap[nId]->setTransient(it.data().value.toBool(&ok)); if(!ok) errStr += " transient"; } else if (it.key().latin1()=="urgency") { notificationMap[nId]->setUrgency(it.data().value.toUInt16(&ok)); if(!ok) errStr += " urgency"; } else if (it.key().latin1()=="sender-pid") { notificationMap[nId]->setSenderPid(it.data().value.toUInt64(&ok)); if(!ok) errStr += " sender-pid"; } } if(! errStr.isNull() ) tqDebug("There was an error converting some of the hint values:" + errStr); } notificationMap[nId]->setFrameStyle( TQFrame::NoFrame ); // notificationMap[nId]->setPaletteBackgroundColor(TQt::black); // notificationMap[nId]->setPaletteForegroundColor(TQt::white); if (icon.isEmpty() || ! notificationMap[nId]->setIcon(icon)) { notificationMap[nId]->setTextFormat(TQt::RichText); notificationMap[nId]->setText("" + app_name + ": " + summary + "

" + body + "

"); } notificationMap[nId]->setActions(actions); notificationMap[nId]->setTimeout(timeout); notificationMap[nId]->adjustSize(); notificationMap[nId]->raise(); notificationMap[nId]->show(); notificationMap[nId]->setActiveWindow(); // make sure we display the new notification above the older one // and if we reach the top of the screen we start at the bottom TQDesktopWidget *d = TQApplication::desktop(); if (notificationMap.contains(nId-1) && notificationMap[nId-1] != 0) { TQPoint pos = notificationMap[nId-1]->pos(); if(pos.y()-notificationMap[nId-1]->height() < 0) pos.setY(d->height()-notificationMap[nId]->height()); pos.setX(d->width()-notificationMap[nId]->width()); notificationMap[nId]->move(pos.x(),pos.y()-notificationMap[nId-1]->height()); } else { notificationMap[nId]->move( d->width()-notificationMap[nId]->width(), d->height()-notificationMap[nId]->height()); } NotifyAsyncReply(asyncCallId, nId); } void NotificationsService::handleMethodReply(const TQT_DBusMessage& reply) { mConnection->send(reply); }