Allow querying capabilities of DBus notification daemon

This commit is contained in:
Martchus 2018-03-31 23:35:39 +02:00
parent 1f66e83209
commit 6727f97ac6
3 changed files with 123 additions and 12 deletions

View File

@ -8,7 +8,7 @@ set(META_APP_AUTHOR "Martchus")
set(META_APP_URL "https://github.com/${META_APP_AUTHOR}/${META_PROJECT_NAME}")
set(META_APP_DESCRIPTION "Common Qt related C++ classes and routines used by my applications such as dialogs, widgets and models")
set(META_VERSION_MAJOR 5)
set(META_VERSION_MINOR 9)
set(META_VERSION_MINOR 10)
set(META_VERSION_PATCH 0)
set(META_APP_VERSION ${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH})

View File

@ -36,7 +36,7 @@ namespace MiscUtils {
/// \cond
static std::map<uint, DBusNotification *> pendingNotifications;
OrgFreedesktopNotificationsInterface *DBusNotification::m_dbusInterface = nullptr;
OrgFreedesktopNotificationsInterface *DBusNotification::s_dbusInterface = nullptr;
/// \endcond
/*!
@ -186,11 +186,11 @@ DBusNotification::DBusNotification(const QString &title, const QString &icon, in
*/
void DBusNotification::initInterface()
{
if (!m_dbusInterface) {
m_dbusInterface = new OrgFreedesktopNotificationsInterface(
if (!s_dbusInterface) {
s_dbusInterface = new OrgFreedesktopNotificationsInterface(
QStringLiteral("org.freedesktop.Notifications"), QStringLiteral("/org/freedesktop/Notifications"), QDBusConnection::sessionBus());
connect(m_dbusInterface, &OrgFreedesktopNotificationsInterface::ActionInvoked, &DBusNotification::handleActionInvoked);
connect(m_dbusInterface, &OrgFreedesktopNotificationsInterface::NotificationClosed, &DBusNotification::handleNotificationClosed);
connect(s_dbusInterface, &OrgFreedesktopNotificationsInterface::ActionInvoked, &DBusNotification::handleActionInvoked);
connect(s_dbusInterface, &OrgFreedesktopNotificationsInterface::NotificationClosed, &DBusNotification::handleNotificationClosed);
}
}
@ -212,7 +212,7 @@ DBusNotification::~DBusNotification()
bool DBusNotification::isAvailable()
{
initInterface();
return m_dbusInterface->isValid();
return s_dbusInterface->isValid();
}
/*!
@ -273,14 +273,14 @@ void DBusNotification::deleteOnCloseOrError()
*/
bool DBusNotification::show()
{
if (!m_dbusInterface->isValid()) {
if (!s_dbusInterface->isValid()) {
emit error();
return false;
}
delete m_watcher;
m_watcher = new QDBusPendingCallWatcher(
m_dbusInterface->Notify(QCoreApplication::applicationName(), m_id, m_icon, m_title, m_msg, m_actions, m_hints, m_timeout), this);
s_dbusInterface->Notify(QCoreApplication::applicationName(), m_id, m_icon, m_title, m_msg, m_actions, m_hints, m_timeout), this);
connect(m_watcher, &QDBusPendingCallWatcher::finished, this, &DBusNotification::handleNotifyResult);
return true;
}
@ -324,15 +324,38 @@ bool DBusNotification::update(const QString &line)
return show();
}
bool DBusNotification::queryCapabilities(const std::function<void(Capabilities &&capabilities)> &callback)
{
// ensure DBus-interface is initialized and valid
initInterface();
if (!s_dbusInterface->isValid()) {
return false;
}
// invoke GetCapabilities() and pass the return value to the callback when available
const auto *const watcher = new QDBusPendingCallWatcher(s_dbusInterface->GetCapabilities());
connect(watcher, &QDBusPendingCallWatcher::finished, [&callback](QDBusPendingCallWatcher *watcher) {
watcher->deleteLater();
const QDBusPendingReply<QStringList> returnValue(*watcher);
if (returnValue.isError()) {
callback(Capabilities());
} else {
callback(Capabilities(move(returnValue.value())));
}
});
return true;
}
/*!
* \brief Hides the notification (if still visible).
* \remarks On success, the signal closed() is emitted with the reason
* NotificationCloseReason::Manually.
* \todo Add return value in v6.
*/
void DBusNotification::hide()
{
if (m_id) {
m_dbusInterface->CloseNotification(m_id);
s_dbusInterface->CloseNotification(m_id);
}
}
@ -389,7 +412,7 @@ void DBusNotification::handleActionInvoked(uint id, const QString &action)
pendingNotifications.erase(i);
// however, lxqt-notificationd does not close the notification
// -> close manually for consistent behaviour
m_dbusInterface->CloseNotification(i->first);
s_dbusInterface->CloseNotification(i->first);
}
}

View File

@ -4,6 +4,7 @@
#include "../global.h"
#include <QObject>
#include <QSet>
#include <QVariantMap>
QT_FORWARD_DECLARE_CLASS(QDBusPendingCallWatcher)
@ -26,6 +27,26 @@ class QT_UTILITIES_EXPORT DBusNotification : public QObject {
Q_PROPERTY(bool visible READ isVisible)
public:
class QT_UTILITIES_EXPORT Capabilities : public QSet<QString> {
public:
explicit Capabilities();
explicit Capabilities(const QStringList &capabilities);
bool isValid() const;
bool supportsBody() const;
bool supportsLinks() const;
bool supportsMarkup() const;
bool supportsImages() const;
bool supportsIcon() const;
bool supportsActions() const;
bool supportsAnimatedIcon() const;
bool supportsActionIcons() const;
bool supportsSound() const;
bool supportsPercistence() const;
private:
bool m_valid;
};
explicit DBusNotification(
const QString &title, NotificationIcon icon = NotificationIcon::Information, int timeout = 10000, QObject *parent = nullptr);
explicit DBusNotification(const QString &title, const QString &icon, int timeout = 10000, QObject *parent = nullptr);
@ -53,6 +74,7 @@ public:
QVariant hint(const QString &name, const QString &fallbackNames...) const;
bool isVisible() const;
void deleteOnCloseOrError();
static bool queryCapabilities(const std::function<void(Capabilities &&capabilities)> &callback);
public Q_SLOTS:
bool show();
@ -86,9 +108,75 @@ private:
int m_timeout;
QStringList m_actions;
QVariantMap m_hints;
static OrgFreedesktopNotificationsInterface *m_dbusInterface;
static OrgFreedesktopNotificationsInterface *s_dbusInterface;
};
inline DBusNotification::Capabilities::Capabilities()
: m_valid(false)
{
}
inline DBusNotification::Capabilities::Capabilities(const QStringList &capabilities)
: QSet<QString>(capabilities.toSet())
, m_valid(true)
{
}
inline bool DBusNotification::Capabilities::isValid() const
{
return m_valid;
}
inline bool DBusNotification::Capabilities::supportsBody() const
{
return contains(QStringLiteral("body"));
}
inline bool DBusNotification::Capabilities::supportsLinks() const
{
return contains(QStringLiteral("body-hyperlinks"));
}
inline bool DBusNotification::Capabilities::supportsMarkup() const
{
return contains(QStringLiteral("body-markup"));
}
inline bool DBusNotification::Capabilities::supportsImages() const
{
return contains(QStringLiteral("body-images"));
}
inline bool DBusNotification::Capabilities::supportsIcon() const
{
return contains(QStringLiteral("icon-static")) || supportsAnimatedIcon();
}
inline bool DBusNotification::Capabilities::supportsActions() const
{
return contains(QStringLiteral("actions"));
}
inline bool DBusNotification::Capabilities::supportsAnimatedIcon() const
{
return contains(QStringLiteral("icon-multi"));
}
inline bool DBusNotification::Capabilities::supportsActionIcons() const
{
return contains(QStringLiteral("action-icons"));
}
inline bool DBusNotification::Capabilities::supportsSound() const
{
return contains(QStringLiteral("sound"));
}
inline bool DBusNotification::Capabilities::supportsPercistence() const
{
return contains(QStringLiteral("persistence"));
}
inline const QString &DBusNotification::title() const
{
return m_title;