forked from OpenAtom-Linyaps/linyaps
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdbus_notifier.cpp
More file actions
198 lines (163 loc) · 6.94 KB
/
Copy pathdbus_notifier.cpp
File metadata and controls
198 lines (163 loc) · 6.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "dbus_notifier.h"
#include "linglong/utils/log/log.h"
#include <QDBusReply>
#include <QEventLoop>
#include <QTimer>
namespace linglong::driver::detect {
DBusNotifier::DBusNotifier(QObject *parent)
: QObject(parent)
, dbusInterface_("org.freedesktop.Notifications",
"/org/freedesktop/Notifications",
"org.freedesktop.Notifications")
{
}
utils::error::Result<void> DBusNotifier::init()
{
LINGLONG_TRACE("init dbus notifier")
auto connection = dbusInterface_.connection();
if (!connection.connect(dbusInterface_.service(),
dbusInterface_.path(),
dbusInterface_.interface(),
"ActionInvoked",
this,
SLOT(forwardActionInvoked(quint32, QString)))) {
return LINGLONG_ERR("couldn't connect to signal ActionInvoked:"
+ connection.lastError().message());
}
if (!connection.connect(dbusInterface_.service(),
dbusInterface_.path(),
dbusInterface_.interface(),
"NotificationClosed",
this,
SLOT(forwardNotificationClosed(quint32, quint32)))) {
return LINGLONG_ERR("couldn't connect to signal NotificationClosed:"
+ connection.lastError().message());
}
return LINGLONG_OK;
}
utils::error::Result<DBusNotifier::NotificationResult>
DBusNotifier::sendInteractiveNotification(const NotificationRequest &request)
{
LINGLONG_TRACE("send request through dbus notification")
quint32 notificationID{ 0 };
QString choice;
bool userInteracted = false;
QEventLoop loop;
struct SignalGuard
{
QMetaObject::Connection closeConn;
QMetaObject::Connection actionConn;
~SignalGuard()
{
QObject::disconnect(closeConn);
QObject::disconnect(actionConn);
}
} signalGuard{ {}, {} };
// 连接信号处理函数
signalGuard.closeConn =
QObject::connect(this,
&DBusNotifier::notificationClosed,
[&](quint32 id, quint32 closeReason) {
if (notificationID != 0 && id == notificationID) {
LogD("Notification {} closed with reason: {}", id, closeReason);
loop.quit();
}
});
signalGuard.actionConn = QObject::connect(
this,
&DBusNotifier::actionInvoked,
[&](quint32 id, const QString &actionKey) {
if (notificationID != 0 && id == notificationID) {
LogD("Notification {} action invoked: {}", id, actionKey.toStdString());
choice = actionKey;
userInteracted = true;
}
});
// 检查信号连接是否成功
if (!signalGuard.closeConn || !signalGuard.actionConn) {
return LINGLONG_ERR("Failed to connect notification signals");
}
// 发送通知
auto reply = sendDBusNotification(request.appName,
0, // replaceId
request.icon, // icon
request.summary,
request.body,
request.actions,
QVariantMap(), // hints
request.timeout);
if (!reply) {
return LINGLONG_ERR(reply.error().message());
}
notificationID = *reply;
LogD("Interactive notification sent with ID: {}", notificationID);
// 设置事件循环超时处理
QTimer::singleShot(request.timeout, &loop, &QEventLoop::quit);
// 运行事件循环等待用户交互
loop.exec();
// 根据用户是否交互返回相应的结果
if (userInteracted) {
LogD("User selected action: {}", choice.toStdString());
return NotificationResult(choice, true);
} else {
LogD("Notification closed without user interaction");
return NotificationResult(choice, false);
}
}
utils::error::Result<void> DBusNotifier::sendSimpleNotification(const NotificationRequest &request)
{
LINGLONG_TRACE("sendSimpleNotification");
// 发送通知(无动作,简单通知)
auto notificationId = sendDBusNotification(request.appName,
0, // replaceId
request.icon, // icon
request.summary,
request.body,
QStringList(), // no actions
QVariantMap(), // hints
request.timeout);
if (!notificationId) {
return LINGLONG_ERR(notificationId.error().message());
}
LogD("Simple notification sent with ID: {}", *notificationId);
return LINGLONG_OK;
}
utils::error::Result<quint32> DBusNotifier::sendDBusNotification(const QString &appName,
quint32 replaceId,
const QString &icon,
const QString &summary,
const QString &body,
const QStringList &actions,
const QVariantMap &hints,
qint32 timeout)
{
LINGLONG_TRACE("sendDBusNotification");
if (!dbusInterface_.isValid()) {
return LINGLONG_ERR("DBus interface is not valid");
}
// 调用Notify方法
QDBusMessage message =
dbusInterface_
.call("Notify", appName, replaceId, icon, summary, body, actions, hints, timeout);
if (message.type() == QDBusMessage::ErrorMessage) {
return LINGLONG_ERR(QString("Failed to send notification: %1").arg(message.errorMessage()));
}
if (message.arguments().isEmpty()) {
return LINGLONG_ERR("No notification ID returned");
}
quint32 notificationId = message.arguments().first().toUInt();
LogD("Notification sent with ID: {}", notificationId);
return notificationId;
}
void DBusNotifier::forwardActionInvoked(quint32 ID, QString action)
{
Q_EMIT actionInvoked(ID, action, QPrivateSignal{});
}
void DBusNotifier::forwardNotificationClosed(quint32 ID, quint32 reason)
{
Q_EMIT notificationClosed(ID, reason, QPrivateSignal{});
}
} // namespace linglong::driver::detect