Support setting image and image path of DBus notifications

This commit is contained in:
Martchus 2018-03-18 03:07:03 +01:00
parent ccca2f123a
commit f76d4044aa
3 changed files with 179 additions and 2 deletions

View File

@ -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_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 8)
set(META_VERSION_PATCH 3)
set(META_VERSION_MINOR 9)
set(META_VERSION_PATCH 0)
set(META_APP_VERSION ${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH})
# add project files

View File

@ -4,6 +4,7 @@
#include <QCoreApplication>
#include <QDBusConnection>
#include <QDBusPendingReply>
#include <QImage>
#include <map>
@ -38,6 +39,120 @@ static std::map<uint, DBusNotification *> pendingNotifications;
OrgFreedesktopNotificationsInterface *DBusNotification::m_dbusInterface = nullptr;
/// \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).
*/
@ -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
* been closed or an error occured.

View File

@ -39,12 +39,18 @@ public:
const QString &icon() const;
void setIcon(const QString &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;
void setTimeout(int timeout);
const QStringList &actions() const;
void setActions(const QStringList &actions);
const QVariantMap &hints() const;
QVariantMap &hints();
QVariant hint(const QString &name) const;
QVariant hint(const QString &name, const QString &fallbackNames...) const;
bool isVisible() const;
void deleteOnCloseOrError();
@ -123,6 +129,42 @@ inline void DBusNotification::setIcon(const QString &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
{
return m_timeout;