Bitcoin Core 32.99.0
P2P Digital Currency
Loading...
Searching...
No Matches
notificator.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-present The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <bitcoin-build-config.h> // IWYU pragma: keep
6
7#include <qt/notificator.h>
8
9#include <attributes.h>
10
11#include <QApplication>
12#include <QByteArray>
13#include <QImageWriter>
14#include <QMessageBox>
15#include <QMetaType>
16#include <QStyle>
17#include <QSystemTrayIcon>
18#include <QTemporaryFile>
19#include <QVariant>
20#ifdef USE_DBUS
21#include <QDBusMetaType>
22#include <QtDBus>
23#include <cstdint>
24#endif
25#ifdef Q_OS_MACOS
27#endif
28
29
30#ifdef USE_DBUS
31// https://wiki.ubuntu.com/NotificationDevelopmentGuidelines recommends at least 128
33#endif
34
36 QObject(_parent),
37 parent(_parent),
38 programName(_programName),
39 trayIcon(_trayIcon)
40{
41 if(_trayIcon && _trayIcon->supportsMessages())
42 {
44 }
45#ifdef USE_DBUS
46 interface = new QDBusInterface("org.freedesktop.Notifications",
47 "/org/freedesktop/Notifications", "org.freedesktop.Notifications");
48 if(interface->isValid())
49 {
51 }
52#endif
53#ifdef Q_OS_MACOS
54 // check if users OS has support for NSUserNotification
55 if( MacNotificationHandler::instance()->hasUserNotificationCenterSupport()) {
57 }
58#endif
59}
60
62{
63#ifdef USE_DBUS
64 delete interface;
65#endif
66}
67
68#ifdef USE_DBUS
69
70// Loosely based on https://www.qtcentre.org/archive/index.php/t-25879.html
72{
73public:
74 FreedesktopImage() = default;
75 explicit FreedesktopImage(const QImage &img);
76
77 // Image to variant that can be marshalled over DBus
78 static QVariant toVariant(const QImage &img);
79
80private:
81 int width, height, stride;
82 bool hasAlpha;
83 int channels;
84 int bitsPerSample;
86
89};
90
92
93// Image configuration settings
94const int CHANNELS = 4;
95const int BYTES_PER_PIXEL = 4;
96const int BITS_PER_SAMPLE = 8;
97
98FreedesktopImage::FreedesktopImage(const QImage &img):
99 width(img.width()),
100 height(img.height()),
102 hasAlpha(true),
105{
106 // Convert 00xAARRGGBB to RGBA bytewise (endian-independent) format
107 QImage tmp = img.convertToFormat(QImage::Format_ARGB32);
108 const uint32_t *data = reinterpret_cast<const uint32_t*>(tmp.bits());
109
110 unsigned int num_pixels = width * height;
112
113 for(unsigned int ptr = 0; ptr < num_pixels; ++ptr)
114 {
115 image[ptr * BYTES_PER_PIXEL + 0] = char(data[ptr] >> 16); // R
116 image[ptr * BYTES_PER_PIXEL + 1] = char(data[ptr] >> 8); // G
117 image[ptr * BYTES_PER_PIXEL + 2] = char(data[ptr]); // B
118 image[ptr * BYTES_PER_PIXEL + 3] = char(data[ptr] >> 24); // A
119 }
120}
121
123{
124 a.beginStructure();
125 a << i.width << i.height << i.stride << i.hasAlpha << i.bitsPerSample << i.channels << i.image;
126 a.endStructure();
127 return a;
128}
129
131{
132 a.beginStructure();
133 a >> i.width >> i.height >> i.stride >> i.hasAlpha >> i.bitsPerSample >> i.channels >> i.image;
134 a.endStructure();
135 return a;
136}
137
138QVariant FreedesktopImage::toVariant(const QImage &img)
139{
142}
143
144void Notificator::notifyDBus(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
145{
146 // Arguments for DBus "Notify" call:
148
149 // Program Name:
150 args.append(programName);
151
152 // Replaces ID; A value of 0 means that this notification won't replace any existing notifications:
153 args.append(0U);
154
155 // Application Icon, empty string
156 args.append(QString());
157
158 // Summary
159 args.append(title);
160
161 // Body
162 args.append(text);
163
164 // Actions (none, actions are deprecated)
165 QStringList actions;
166 args.append(actions);
167
168 // Hints
170
171 // If no icon specified, set icon based on class
173 if(icon.isNull())
174 {
175 QStyle::StandardPixmap sicon = QStyle::SP_MessageBoxQuestion;
176 switch(cls)
177 {
178 case Information: sicon = QStyle::SP_MessageBoxInformation; break;
179 case Warning: sicon = QStyle::SP_MessageBoxWarning; break;
180 case Critical: sicon = QStyle::SP_MessageBoxCritical; break;
181 } // no default case, so the compiler can warn about missing cases
182 tmpicon = QApplication::style()->standardIcon(sicon);
183 }
184 else
185 {
186 tmpicon = icon;
187 }
188 hints["icon_data"] = FreedesktopImage::toVariant(tmpicon.pixmap(FREEDESKTOP_NOTIFICATION_ICON_SIZE).toImage());
189 args.append(hints);
190
191 // Timeout (in msec)
192 args.append(millisTimeout);
193
194 // "Fire and forget"
195 interface->callWithArgumentList(QDBus::NoBlock, "Notify", args);
196}
197#endif
198
200{
201 QSystemTrayIcon::MessageIcon sicon = QSystemTrayIcon::NoIcon;
202 switch(cls) // Set icon based on class
203 {
204 case Information: sicon = QSystemTrayIcon::Information; break;
205 case Warning: sicon = QSystemTrayIcon::Warning; break;
206 case Critical: sicon = QSystemTrayIcon::Critical; break;
207 }
208 trayIcon->showMessage(title, text, sicon, millisTimeout);
209}
210
211#ifdef Q_OS_MACOS
212void Notificator::notifyMacUserNotificationCenter(const QString &title, const QString &text)
213{
214 // icon is not supported by the user notification center yet. OSX will use the app icon.
216}
217#endif
218
219void Notificator::notify(Class cls, const QString &title, const QString &text, const QIcon &icon, int millisTimeout)
220{
221 switch(mode)
222 {
223#ifdef USE_DBUS
224 case Freedesktop:
225 notifyDBus(cls, title, text, icon, millisTimeout);
226 break;
227#endif
228 case QSystemTray:
229 notifySystray(cls, title, text, millisTimeout);
230 break;
231#ifdef Q_OS_MACOS
234 break;
235#endif
236 default:
237 if(cls == Critical)
238 {
239 // Fall back to old fashioned pop-up dialog if critical and no other notification available
240 QMessageBox::critical(parent, title, text, QMessageBox::Ok, QMessageBox::Ok);
241 }
242 break;
243 }
244}
#define LIFETIMEBOUND
Definition attributes.h:12
ArgsManager & args
Definition bitcoind.cpp:280
QDataStream & operator>>(QDataStream &in, BitcoinUnit &unit)
static MacNotificationHandler * instance()
void showNotification(const QString &title, const QString &text)
shows a macOS 10.8+ UserNotification in the UserNotificationCenter
QString programName
Definition notificator.h:61
QWidget * parent
Definition notificator.h:54
@ Information
Informational message.
Definition notificator.h:36
@ Critical
An error occurred.
Definition notificator.h:38
@ Warning
Notify user of potential problem.
Definition notificator.h:37
@ UserNotificationCenter
Use the 10.8+ User Notification Center (Mac only)
Definition notificator.h:59
@ QSystemTray
Use QSystemTrayIcon::showMessage()
Definition notificator.h:58
@ Freedesktop
Use DBus org.freedesktop.Notifications.
Definition notificator.h:57
void notifySystray(Class cls, const QString &title, const QString &text, int millisTimeout)
Notificator(const QString &programName, QSystemTrayIcon *trayIcon, QWidget *parent)
Create a new notificator.
QSystemTrayIcon * trayIcon
Definition notificator.h:63
void notify(Class cls, const QString &title, const QString &text, const QIcon &icon=QIcon(), int millisTimeout=10000)
Show notification message.
static const PrecomputedData data
Precomputed COutPoint and CCoins values.
static OutputStream & operator<<(OutputStream &os, const Array &array)
Definition gen.cpp:97
constexpr auto Ticks(Dur2 d)
Helper to count the seconds of a duration/time_point.
Definition time.h:82