Support setting image and image path of DBus notifications
This commit is contained in:
parent
ccca2f123a
commit
f76d4044aa
|
@ -8,8 +8,8 @@ set(META_APP_AUTHOR "Martchus")
|
||||||
set(META_APP_URL "https://github.com/${META_APP_AUTHOR}/${META_PROJECT_NAME}")
|
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_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_MAJOR 5)
|
||||||
set(META_VERSION_MINOR 8)
|
set(META_VERSION_MINOR 9)
|
||||||
set(META_VERSION_PATCH 3)
|
set(META_VERSION_PATCH 0)
|
||||||
set(META_APP_VERSION ${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH})
|
set(META_APP_VERSION ${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH})
|
||||||
|
|
||||||
# add project files
|
# add project files
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDBusConnection>
|
#include <QDBusConnection>
|
||||||
#include <QDBusPendingReply>
|
#include <QDBusPendingReply>
|
||||||
|
#include <QImage>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
@ -38,6 +39,120 @@ static std::map<uint, DBusNotification *> pendingNotifications;
|
||||||
OrgFreedesktopNotificationsInterface *DBusNotification::m_dbusInterface = nullptr;
|
OrgFreedesktopNotificationsInterface *DBusNotification::m_dbusInterface = nullptr;
|
||||||
/// \endcond
|
/// \endcond
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The SwappedImage struct represents RGB-interved version of the image specified on construction.
|
||||||
|
*/
|
||||||
|
struct SwappedImage : public QImage {
|
||||||
|
SwappedImage(const QImage &image);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline SwappedImage::SwappedImage(const QImage &image)
|
||||||
|
: QImage(image.rgbSwapped())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief The ImageData struct is a raw data image format.
|
||||||
|
*
|
||||||
|
* It describes the width, height, rowstride, has alpha, bits per sample, channels and image data respectively.
|
||||||
|
*/
|
||||||
|
struct NotificationImage {
|
||||||
|
NotificationImage();
|
||||||
|
NotificationImage(const QVariant &imageData);
|
||||||
|
NotificationImage(SwappedImage image);
|
||||||
|
QImage toQImage() const;
|
||||||
|
QVariant toDBusArgument() const;
|
||||||
|
|
||||||
|
qint32 width;
|
||||||
|
qint32 height;
|
||||||
|
qint32 rowstride;
|
||||||
|
bool hasAlpha;
|
||||||
|
qint32 channels;
|
||||||
|
qint32 bitsPerSample;
|
||||||
|
QByteArray data;
|
||||||
|
bool isValid;
|
||||||
|
|
||||||
|
private:
|
||||||
|
NotificationImage(const QImage &image);
|
||||||
|
};
|
||||||
|
|
||||||
|
QDBusArgument &operator<<(QDBusArgument &argument, const NotificationImage &img)
|
||||||
|
{
|
||||||
|
argument.beginStructure();
|
||||||
|
argument << img.width;
|
||||||
|
argument << img.height;
|
||||||
|
argument << img.rowstride;
|
||||||
|
argument << img.hasAlpha;
|
||||||
|
argument << img.bitsPerSample;
|
||||||
|
argument << img.channels;
|
||||||
|
argument << img.data;
|
||||||
|
argument.endStructure();
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QDBusArgument &operator>>(const QDBusArgument &argument, NotificationImage &img)
|
||||||
|
{
|
||||||
|
argument.beginStructure();
|
||||||
|
argument >> img.width;
|
||||||
|
argument >> img.height;
|
||||||
|
argument >> img.rowstride;
|
||||||
|
argument >> img.hasAlpha;
|
||||||
|
argument >> img.bitsPerSample;
|
||||||
|
argument >> img.channels;
|
||||||
|
argument >> img.data;
|
||||||
|
argument.endStructure();
|
||||||
|
return argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline NotificationImage::NotificationImage()
|
||||||
|
: isValid(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline NotificationImage::NotificationImage(const QVariant &imageData)
|
||||||
|
: isValid(imageData.canConvert<QDBusArgument>())
|
||||||
|
{
|
||||||
|
if (isValid) {
|
||||||
|
imageData.value<QDBusArgument>() >> *this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationImage::NotificationImage(SwappedImage image)
|
||||||
|
: NotificationImage(static_cast<const QImage &>(image))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline NotificationImage::NotificationImage(const QImage &image)
|
||||||
|
: width(image.width())
|
||||||
|
, height(image.height())
|
||||||
|
, rowstride(image.bytesPerLine())
|
||||||
|
, hasAlpha(image.hasAlphaChannel())
|
||||||
|
, channels(image.isGrayscale() ? 1 : hasAlpha ? 4 : 3)
|
||||||
|
, bitsPerSample(image.depth() / channels)
|
||||||
|
, data(reinterpret_cast<const char *>(image.bits()), image.byteCount())
|
||||||
|
, isValid(!image.isNull())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QImage NotificationImage::toQImage() const
|
||||||
|
{
|
||||||
|
return isValid ? QImage(reinterpret_cast<const uchar *>(data.constData()), width, height, hasAlpha ? QImage::Format_ARGB32 : QImage::Format_RGB32)
|
||||||
|
.rgbSwapped()
|
||||||
|
: QImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QVariant NotificationImage::toDBusArgument() const
|
||||||
|
{
|
||||||
|
QDBusArgument arg;
|
||||||
|
return QVariant::fromValue(isValid ? arg << *this : arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace MiscUtils
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(MiscUtils::NotificationImage);
|
||||||
|
|
||||||
|
namespace MiscUtils {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Creates a new notification (which is *not* shown instantly).
|
* \brief Creates a new notification (which is *not* shown instantly).
|
||||||
*/
|
*/
|
||||||
|
@ -119,6 +234,26 @@ void DBusNotification::setIcon(NotificationIcon icon)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the image.
|
||||||
|
* \sa setImage() for more details
|
||||||
|
*/
|
||||||
|
const QImage DBusNotification::image() const
|
||||||
|
{
|
||||||
|
return NotificationImage(hint(QStringLiteral("image-data"), QStringLiteral("image_data"))).toQImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets the image.
|
||||||
|
* \remarks
|
||||||
|
* \a image is a raw data image format which describes the width, height, rowstride,
|
||||||
|
* has alpha, bits per sample, channels and image data respectively.
|
||||||
|
*/
|
||||||
|
void DBusNotification::setImage(const QImage &image)
|
||||||
|
{
|
||||||
|
m_hints[QStringLiteral("image-data")] = NotificationImage(SwappedImage(image)).toDBusArgument();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Makes the notification object delete itself when the notification has
|
* \brief Makes the notification object delete itself when the notification has
|
||||||
* been closed or an error occured.
|
* been closed or an error occured.
|
||||||
|
|
|
@ -39,12 +39,18 @@ public:
|
||||||
const QString &icon() const;
|
const QString &icon() const;
|
||||||
void setIcon(const QString &icon);
|
void setIcon(const QString &icon);
|
||||||
void setIcon(NotificationIcon icon);
|
void setIcon(NotificationIcon icon);
|
||||||
|
const QImage image() const;
|
||||||
|
void setImage(const QImage &image);
|
||||||
|
const QString imagePath() const;
|
||||||
|
void setImagePath(const QString &imagePath);
|
||||||
int timeout() const;
|
int timeout() const;
|
||||||
void setTimeout(int timeout);
|
void setTimeout(int timeout);
|
||||||
const QStringList &actions() const;
|
const QStringList &actions() const;
|
||||||
void setActions(const QStringList &actions);
|
void setActions(const QStringList &actions);
|
||||||
const QVariantMap &hints() const;
|
const QVariantMap &hints() const;
|
||||||
QVariantMap &hints();
|
QVariantMap &hints();
|
||||||
|
QVariant hint(const QString &name) const;
|
||||||
|
QVariant hint(const QString &name, const QString &fallbackNames...) const;
|
||||||
bool isVisible() const;
|
bool isVisible() const;
|
||||||
void deleteOnCloseOrError();
|
void deleteOnCloseOrError();
|
||||||
|
|
||||||
|
@ -123,6 +129,42 @@ inline void DBusNotification::setIcon(const QString &icon)
|
||||||
m_icon = icon;
|
m_icon = icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the hint with the specified \a name.
|
||||||
|
*/
|
||||||
|
inline QVariant DBusNotification::hint(const QString &name) const
|
||||||
|
{
|
||||||
|
return m_hints[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the hint with the specified \a name. If no hint is present, the \a fallbackNames are tried in the specified order.
|
||||||
|
*/
|
||||||
|
inline QVariant DBusNotification::hint(const QString &name, const QString &fallbackNames...) const
|
||||||
|
{
|
||||||
|
const auto variant(m_hints[name]);
|
||||||
|
return variant.isNull() ? this->hint(fallbackNames) : variant;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Returns the image path.
|
||||||
|
* \sa setImagePath() for more details
|
||||||
|
*/
|
||||||
|
inline const QString DBusNotification::imagePath() const
|
||||||
|
{
|
||||||
|
return hint(QStringLiteral("image-data"), QStringLiteral("image_path")).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets the image path.
|
||||||
|
* \remarks
|
||||||
|
* Alternative way to define the notification image; setImage() precedes.
|
||||||
|
*/
|
||||||
|
inline void DBusNotification::setImagePath(const QString &imagePath)
|
||||||
|
{
|
||||||
|
m_hints[QStringLiteral("image-path")] = imagePath;
|
||||||
|
}
|
||||||
|
|
||||||
inline int DBusNotification::timeout() const
|
inline int DBusNotification::timeout() const
|
||||||
{
|
{
|
||||||
return m_timeout;
|
return m_timeout;
|
||||||
|
|
Loading…
Reference in New Issue