Skip to content

Commit 2e5e19c

Browse files
committed
feat(keyboard): wire custom shortcut CRUD on Wayland
Wire the control center's add/modify/delete custom shortcut flows to the new dde-services Keybinding1 custom CRUD methods on Wayland, replacing the previous early-return stubs. Each Wayland call is observed with a QDBusPendingCallWatcher so failures trigger refreshShortcut()/onAdded/ onShortcutChanged instead of mutating the local model optimistically. Fetch a custom shortcut's command via the new GetShortcutCommand D-Bus method: requestShortcutCommand fires one async call per custom shortcut after ListAllShortcuts/SearchShortcuts/GetShortcut/ShortcutChanged, and onGetShortcutCommandFinished overlays the Exec field onto the already- built JSON object and re-emits shortcutQueried. The whole ShortcutInfo JSON is stashed on the watcher so the handler needs no field-by-field reconstruction. ShortcutModel::onKeyBindingChanged now handles insert-on-change for new ids arriving via ShortcutChanged: section-bearing configs are grouped into m_groupInfos, sectionless Custom configs get the legacy "Custom" group, and a dead unreachable tail (invalidateSystemShortcutNamesCache + addCustomInfo after two returning branches) is removed. Extract KeyboardWorker::callModifyCustomShortcut() so the Wayland modify path (modifyCustomShortcut and setNewCustomShortcut) shares one watcher/id/type/connect setup. setNewCustomShortcut keeps the X11 fallback calling ModifyCustomShortcut directly, since on X11 it is also invoked from onCustomConflictCleanFinished after conflict cleanup. 将控制中心自定义快捷键的增删改流程在 Wayland 下接入新的 dde-services Keybinding1 自定义增删改方法,替换原先的提前 return 桩。每次 Wayland 调用 均用 QDBusPendingCallWatcher 观察结果,失败时触发 refreshShortcut()/ onAdded/onShortcutChanged,而不再乐观地修改本地模型。 通过新增的 GetShortcutCommand D-Bus 方法获取自定义快捷键命令: requestShortcutCommand 在 ListAllShortcuts/SearchShortcuts/GetShortcut/ ShortcutChanged 之后对每个自定义快捷键发起一次异步调用, onGetShortcutCommandFinished 将 Exec 字段叠加到已构建好的 JSON 对象上并 重新发射 shortcutQueried。整个 ShortcutInfo JSON 暂存在 watcher 上,处理 函数无需逐字段重建。 ShortcutModel::onKeyBindingChanged 现支持通过 ShortcutChanged 到达的新 id 的"变更即插入":带 Section 的配置归入 m_groupInfos,无 Section 的 Custom 配置归入传统"Custom"分组,并删除了两个 return 分支之后不可达的死代码尾段。 抽取 KeyboardWorker::callModifyCustomShortcut(),让 Wayland 修改路径 (modifyCustomShortcut 与 setNewCustomShortcut)共用一份 watcher/id/type/ connect 设置。setNewCustomShortcut 保留 X11 直接调用 ModifyCustomShortcut 的兜底,因为 X11 下它也会在冲突清理完成后由 onCustomConflictCleanFinished 调用。 Log: feat(keyboard): wire custom shortcut CRUD on Wayland Change-Id: I793aa520968c92d03bb603721f00b1c7ac252fa5
1 parent 806d2ae commit 2e5e19c

9 files changed

Lines changed: 310 additions & 53 deletions

src/plugin-keyboard/operation/keyboardcontroller.cpp

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ KeyboardController::KeyboardController(QObject *parent)
4545
connect(m_model, &KeyboardModel::userLayoutChanged, this, &KeyboardController::layoutCountChanged);
4646
connect(m_model, &KeyboardModel::curLayoutChanged, this, &KeyboardController::currentLayoutChanged);
4747
connect(m_model, &KeyboardModel::keyboardEnabledChanged, this, &KeyboardController::keyboardEnabledChanged);
48+
connect(m_worker, &KeyboardWorker::shortcutCommandReady,
49+
this, &KeyboardController::shortcutCommandReady);
4850

4951
connect(m_shortcutModel, &ShortcutModel::keyEvent, this, [this](bool press, const QString &shortcut){
5052
ShortcutInfo *current = m_shortcutModel->currentInfo();
@@ -279,12 +281,7 @@ QString KeyboardController::checkDesktopCmd(const QString &cmd)
279281
void KeyboardController::addCustomShortcut(const QString &name, const QString &cmd, const QString &accels)
280282
{
281283
if (m_worker->isWayland()) {
282-
// dde-services' Keybinding1 has no AddCustomShortcut yet (the service's
283-
// own CONTROL_CENTER_INTEGRATION.md marks custom-shortcut CRUD as 服务侧需补齐).
284-
// Bail out before any side effect (the conflict Disable below, the
285-
// optimistic model insert in the worker) so the row doesn't flicker.
286-
// TODO: wire up once AddCustomShortcut/ModifyCustomShortcut/DeleteCustomShortcut land.
287-
qWarning() << "[Wayland] addCustomShortcut not yet supported by dde-services; ignoring";
284+
m_worker->addCustomShortcut(name, checkDesktopCmd(cmd), accels);
288285
return;
289286
}
290287

@@ -300,21 +297,21 @@ void KeyboardController::addCustomShortcut(const QString &name, const QString &c
300297

301298
void KeyboardController::modifyCustomShortcut(const QString &id, const QString &name, const QString &cmd, const QString &accels)
302299
{
303-
if (m_worker->isWayland()) {
304-
// No ModifyCustomShortcut on the Wayland service yet — return before
305-
// mutating the local model or triggering the conflict Disable below,
306-
// so the UI is unchanged rather than showing an edit that won't persist.
307-
// TODO: wire up once dde-services implements custom-shortcut CRUD.
308-
qWarning() << "[Wayland] modifyCustomShortcut not yet supported by dde-services; ignoring";
309-
return;
310-
}
311-
312300
ShortcutInfo *shortcut = m_shortcutModel->findInfoIf([id](ShortcutInfo *info){ return id == info->id; });
313301
if (!shortcut) {
314302
qWarning() << "shortcut not found..." << id << name;
315303
return;
316304
}
317305

306+
if (m_worker->isWayland()) {
307+
ShortcutInfo updated = *shortcut;
308+
updated.name = name;
309+
updated.command = checkDesktopCmd(cmd);
310+
updated.accels = accels;
311+
m_worker->modifyCustomShortcut(&updated);
312+
return;
313+
}
314+
318315
// Clear conflicting shortcuts when modifying
319316
if (auto conflict = m_shortcutModel->getInfo(accels)) {
320317
m_worker->onDisableShortcut(conflict);
@@ -327,17 +324,14 @@ void KeyboardController::modifyCustomShortcut(const QString &id, const QString &
327324
m_worker->modifyCustomShortcut(shortcut);
328325
}
329326

330-
void KeyboardController::deleteCustomShortcut(const QString &id)
327+
void KeyboardController::requestShortcutCommand(const QString &id)
331328
{
332-
if (m_worker->isWayland()) {
333-
// No DeleteCustomShortcut on the Wayland service yet. Return before
334-
// delShortcut's optimistic delInfo() (which removes + deletes the row);
335-
// otherwise the row would vanish then reappear on the next refresh.
336-
// TODO: wire up once dde-services implements custom-shortcut CRUD.
337-
qWarning() << "[Wayland] deleteCustomShortcut not yet supported by dde-services; ignoring";
338-
return;
339-
}
329+
if (m_worker)
330+
m_worker->requestShortcutCommand(id);
331+
}
340332

333+
void KeyboardController::deleteCustomShortcut(const QString &id)
334+
{
341335
ShortcutInfo *shortcut = m_shortcutModel->findInfoIf([id](ShortcutInfo *info){ return id == info->id; });
342336
if (!shortcut) {
343337
qWarning() << "shortcut not found..." << id;

src/plugin-keyboard/operation/keyboardcontroller.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ public Q_SLOTS:
9696

9797
void addCustomShortcut(const QString &name, const QString &cmd, const QString &accels);
9898
void modifyCustomShortcut(const QString &id, const QString &name, const QString &cmd, const QString &accels);
99+
Q_INVOKABLE void requestShortcutCommand(const QString &id);
99100
void modifyShortcut(const QString &id, const QString &accels, const int &type);
100101
void deleteCustomShortcut(const QString &id);
101102
void clearShortcut(const QString &id, const int &type);
@@ -130,6 +131,7 @@ public Q_SLOTS:
130131

131132
void waylandKeyCaptureFinished(const QString &id, int type, const QString &accels);
132133
void waylandKeyCaptureFailed(const QString &id, int type, int reason);
134+
void shortcutCommandReady(const QString &id, const QString &command, bool available);
133135

134136
void conflictTextChanged();
135137
void keyboardEnabledChanged();

src/plugin-keyboard/operation/keyboarddbusproxy.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ void KeyboardDBusProxy::onListAllShortcutsNewFinished(QDBusPendingCallWatcher *w
293293
{
294294
QDBusPendingReply<QList<ShortcutInfoNew>> reply = *w;
295295
if (!reply.isError()) {
296-
QString json = convertShortcutListToJson(reply.value());
296+
const QList<ShortcutInfoNew> shortcuts = reply.value();
297+
QString json = convertShortcutListToJson(shortcuts);
297298
Q_EMIT AllShortcutsReady(json);
298299
} else {
299300
qWarning() << "Wayland ListAllShortcuts failed:" << reply.error();
@@ -354,7 +355,8 @@ void KeyboardDBusProxy::onGetShortcutNewFinished(QDBusPendingCallWatcher *w)
354355
{
355356
QDBusPendingReply<ShortcutInfoNew> reply = *w;
356357
if (!reply.isError()) {
357-
QString json = convertShortcutToJson(reply.value());
358+
const ShortcutInfoNew info = reply.value();
359+
QString json = convertShortcutToJson(info);
358360
Q_EMIT shortcutQueried(json);
359361
}
360362
w->deleteLater();
@@ -462,27 +464,34 @@ QDBusPendingReply<> KeyboardDBusProxy::AddShortcutKeystroke(const QString &in0,
462464
return m_dBusKeybingdingInter->asyncCallWithArgumentList(QStringLiteral("AddShortcutKeystroke"), argumentList);
463465
}
464466

465-
QDBusPendingReply<> KeyboardDBusProxy::AddCustomShortcut(const QString &in0, const QString &in1, const QString &in2)
467+
QDBusPendingReply<QString> KeyboardDBusProxy::AddCustomShortcut(const QString &in0, const QString &in1, const QString &in2)
466468
{
467469
QList<QVariant> argumentList;
468470
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2);
469471
return m_dBusKeybingdingInter->asyncCallWithArgumentList(QStringLiteral("AddCustomShortcut"), argumentList);
470472
}
471473

472-
QDBusPendingReply<> KeyboardDBusProxy::ModifyCustomShortcut(const QString &in0, const QString &in1, const QString &in2, const QString &in3)
474+
QDBusPendingReply<bool> KeyboardDBusProxy::ModifyCustomShortcut(const QString &in0, const QString &in1, const QString &in2, const QString &in3)
473475
{
474476
QList<QVariant> argumentList;
475477
argumentList << QVariant::fromValue(in0) << QVariant::fromValue(in1) << QVariant::fromValue(in2) << QVariant::fromValue(in3);
476478
return m_dBusKeybingdingInter->asyncCallWithArgumentList(QStringLiteral("ModifyCustomShortcut"), argumentList);
477479
}
478480

479-
QDBusPendingReply<> KeyboardDBusProxy::DeleteCustomShortcut(const QString &in0)
481+
QDBusPendingReply<bool> KeyboardDBusProxy::DeleteCustomShortcut(const QString &in0)
480482
{
481483
QList<QVariant> argumentList;
482484
argumentList << QVariant::fromValue(in0);
483485
return m_dBusKeybingdingInter->asyncCallWithArgumentList(QStringLiteral("DeleteCustomShortcut"), argumentList);
484486
}
485487

488+
QDBusPendingReply<QString> KeyboardDBusProxy::GetShortcutCommand(const QString &in0)
489+
{
490+
QList<QVariant> argumentList;
491+
argumentList << QVariant::fromValue(in0);
492+
return m_dBusKeybingdingInter->asyncCallWithArgumentList(QStringLiteral("GetShortcutCommand"), argumentList);
493+
}
494+
486495
QDBusPendingReply<> KeyboardDBusProxy::GrabScreen()
487496
{
488497
QList<QVariant> argumentList;
@@ -505,7 +514,8 @@ void KeyboardDBusProxy::onSearchShortcutsNewFinished(QDBusPendingCallWatcher *w)
505514
{
506515
QDBusPendingReply<QList<ShortcutInfoNew>> reply = *w;
507516
if (!reply.isError()) {
508-
QString json = convertShortcutListToJson(reply.value());
517+
const QList<ShortcutInfoNew> shortcuts = reply.value();
518+
QString json = convertShortcutListToJson(shortcuts);
509519
Q_EMIT searchShortcutsReady(json);
510520
}
511521
w->deleteLater();

src/plugin-keyboard/operation/keyboarddbusproxy.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,10 @@ public slots:
247247
QDBusPendingReply<bool> callModifyHotkeys(const QString &id, const QStringList &hotkeys);
248248
// Wayland: replace hotkey — remove newHotkey from conflictId, add to targetId.
249249
QDBusPendingReply<bool> callReplaceHotkey(const QString &targetId, const QString &newHotkey, const QString &conflictId);
250-
QDBusPendingReply<> AddCustomShortcut(const QString &in0, const QString &in1, const QString &in2);
251-
QDBusPendingReply<> ModifyCustomShortcut(const QString &in0, const QString &in1, const QString &in2, const QString &in3);
252-
QDBusPendingReply<> DeleteCustomShortcut(const QString &in0);
250+
QDBusPendingReply<QString> AddCustomShortcut(const QString &in0, const QString &in1, const QString &in2);
251+
QDBusPendingReply<bool> ModifyCustomShortcut(const QString &in0, const QString &in1, const QString &in2, const QString &in3);
252+
QDBusPendingReply<bool> DeleteCustomShortcut(const QString &in0);
253+
QDBusPendingReply<QString> GetShortcutCommand(const QString &in0);
253254
QDBusPendingReply<> GrabScreen();
254255
void SetNumLockState(int in0);
255256
QDBusPendingReply<QString> GetShortcut(const QString &in0, int in1);

src/plugin-keyboard/operation/keyboardwork.cpp

Lines changed: 120 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -348,21 +348,61 @@ void KeyboardWorker::modifyShortcutEdit(ShortcutInfo *info) {
348348

349349
void KeyboardWorker::addCustomShortcut(const QString &name, const QString &command, const QString &accels)
350350
{
351-
m_keyboardDBusProxy->AddCustomShortcut(name, command, accels);
351+
QDBusPendingReply<QString> reply = m_keyboardDBusProxy->AddCustomShortcut(name, command, accels);
352+
if (!m_keyboardDBusProxy->isWayland())
353+
return;
354+
355+
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
356+
connect(watcher, &QDBusPendingCallWatcher::finished,
357+
this, &KeyboardWorker::onAddCustomShortcutFinished);
358+
}
359+
360+
void KeyboardWorker::callModifyCustomShortcut(const QString &id, const QString &name,
361+
const QString &command, const QString &accels,
362+
int type)
363+
{
364+
QDBusPendingReply<bool> reply = m_keyboardDBusProxy->ModifyCustomShortcut(id, name, command, accels);
365+
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
366+
watcher->setProperty("id", id);
367+
watcher->setProperty("type", type);
368+
connect(watcher, &QDBusPendingCallWatcher::finished,
369+
this, &KeyboardWorker::onModifyCustomShortcutFinished);
370+
}
371+
372+
void KeyboardWorker::requestShortcutCommand(const QString &id)
373+
{
374+
ShortcutInfo *shortcut = m_shortcutModel ? m_shortcutModel->findInfoIf([&id](ShortcutInfo *info) {
375+
return info->id == id;
376+
}) : nullptr;
377+
const QString fallbackCommand = shortcut ? shortcut->command : QString();
378+
379+
if (id.isEmpty() || !m_keyboardDBusProxy->isWayland()) {
380+
Q_EMIT shortcutCommandReady(id, fallbackCommand, !id.isEmpty());
381+
return;
382+
}
383+
384+
QDBusPendingReply<QString> reply = m_keyboardDBusProxy->GetShortcutCommand(id);
385+
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
386+
watcher->setProperty("id", id);
387+
watcher->setProperty("fallbackCommand", fallbackCommand);
388+
connect(watcher, &QDBusPendingCallWatcher::finished,
389+
this, &KeyboardWorker::onGetShortcutCommandFinished);
352390
}
353391

354392
void KeyboardWorker::modifyCustomShortcut(ShortcutInfo *info)
355393
{
394+
if (m_keyboardDBusProxy->isWayland()) {
395+
callModifyCustomShortcut(info->id, info->name, info->command, info->accels, info->type);
396+
return;
397+
}
398+
356399
if (info->replace) {
357400
onDisableShortcut(info->replace);
358401
}
359402

360403
// reset replace shortcut
361404
info->replace = nullptr;
362405

363-
// Wayland custom-shortcut CRUD is stubbed at the controller layer
364-
// (KeyboardController::modifyCustomShortcut early-returns) until
365-
// dde-services implements ModifyCustomShortcut, so this body is X11-only.
366406
const QString &result = m_keyboardDBusProxy->LookupConflictingShortcut(info->accels);
367407

368408
if (!result.isEmpty()) {
@@ -406,7 +446,16 @@ QString KeyboardWorker::lookupConflictingShortcut(const QString &key)
406446

407447
void KeyboardWorker::delShortcut(ShortcutInfo* info)
408448
{
409-
m_keyboardDBusProxy->DeleteCustomShortcut(info->id);
449+
QDBusPendingReply<bool> reply = m_keyboardDBusProxy->DeleteCustomShortcut(info->id);
450+
if (m_keyboardDBusProxy->isWayland()) {
451+
QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
452+
watcher->setProperty("id", info->id);
453+
watcher->setProperty("type", info->type);
454+
connect(watcher, &QDBusPendingCallWatcher::finished,
455+
this, &KeyboardWorker::onDeleteCustomShortcutFinished);
456+
return;
457+
}
458+
410459
if (m_shortcutModel)
411460
m_shortcutModel->delInfo(info);
412461
}
@@ -929,6 +978,11 @@ void KeyboardWorker::cleanShortcutSlef(const QString &id, const int type, const
929978

930979
void KeyboardWorker::setNewCustomShortcut(const QString &id, const QString &name, const QString &command, const QString &accles)
931980
{
981+
if (m_keyboardDBusProxy->isWayland()) {
982+
callModifyCustomShortcut(id, name, command, accles, ShortcutModel::Custom);
983+
return;
984+
}
985+
932986
m_keyboardDBusProxy->ModifyCustomShortcut(id, name, command, accles);
933987
}
934988

@@ -1090,6 +1144,67 @@ void KeyboardWorker::onCustomConflictCleanFinished(QDBusPendingCallWatcher *w)
10901144
w->deleteLater();
10911145
}
10921146

1147+
void KeyboardWorker::onAddCustomShortcutFinished(QDBusPendingCallWatcher *watch)
1148+
{
1149+
QDBusPendingReply<QString> reply = *watch;
1150+
if (reply.isError() || reply.value().isEmpty()) {
1151+
qWarning() << "AddCustomShortcut failed:"
1152+
<< (reply.isError() ? reply.error().message() : QStringLiteral("server returned empty id"));
1153+
refreshShortcut();
1154+
} else {
1155+
onAdded(reply.value(), ShortcutModel::Custom);
1156+
}
1157+
1158+
watch->deleteLater();
1159+
}
1160+
1161+
void KeyboardWorker::onModifyCustomShortcutFinished(QDBusPendingCallWatcher *watch)
1162+
{
1163+
QDBusPendingReply<bool> reply = *watch;
1164+
const QString id = watch->property("id").toString();
1165+
const int type = watch->property("type").toInt();
1166+
const bool success = (!reply.isError() && reply.value());
1167+
if (!success) {
1168+
qWarning() << "ModifyCustomShortcut failed for" << id
1169+
<< (reply.isError() ? reply.error().message() : QStringLiteral("server returned false"));
1170+
refreshShortcut();
1171+
} else if (!id.isEmpty()) {
1172+
onShortcutChanged(id, type);
1173+
}
1174+
1175+
watch->deleteLater();
1176+
}
1177+
1178+
void KeyboardWorker::onDeleteCustomShortcutFinished(QDBusPendingCallWatcher *watch)
1179+
{
1180+
QDBusPendingReply<bool> reply = *watch;
1181+
const QString id = watch->property("id").toString();
1182+
const bool success = (!reply.isError() && reply.value());
1183+
if (!success) {
1184+
qWarning() << "DeleteCustomShortcut failed for" << id
1185+
<< (reply.isError() ? reply.error().message() : QStringLiteral("server returned false"));
1186+
}
1187+
refreshShortcut();
1188+
1189+
watch->deleteLater();
1190+
}
1191+
1192+
void KeyboardWorker::onGetShortcutCommandFinished(QDBusPendingCallWatcher *watch)
1193+
{
1194+
QDBusPendingReply<QString> reply = *watch;
1195+
const QString id = watch->property("id").toString();
1196+
QString command = watch->property("fallbackCommand").toString();
1197+
1198+
if (reply.isError()) {
1199+
qWarning() << "GetShortcutCommand failed for" << id << reply.error().message();
1200+
} else {
1201+
command = reply.value();
1202+
}
1203+
1204+
Q_EMIT shortcutCommandReady(id, command, !reply.isError() || !command.isEmpty());
1205+
watch->deleteLater();
1206+
}
1207+
10931208
QString KeyboardWorker::makeShortcutKey(const QString &id, int type)
10941209
{
10951210
return id + "_" + QString::number(type);

src/plugin-keyboard/operation/keyboardwork.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ class KeyboardWorker : public QObject
4949
void modifyShortcutEdit(ShortcutInfo* info);
5050
void addCustomShortcut(const QString& name, const QString& command, const QString& accels);
5151
void modifyCustomShortcut(ShortcutInfo *info);
52+
void requestShortcutCommand(const QString &id);
53+
// Fire ModifyCustomShortcut on the Wayland service and wire the reply to
54+
// onModifyCustomShortcutFinished. Shared by modifyCustomShortcut (Wayland
55+
// branch) and setNewCustomShortcut so the watcher/id/type setup stays in
56+
// one place.
57+
void callModifyCustomShortcut(const QString &id, const QString &name,
58+
const QString &command, const QString &accels,
59+
int type);
5260

5361
void grabScreen();
5462
bool checkAvaliable(const QString& key);
@@ -85,6 +93,7 @@ class KeyboardWorker : public QObject
8593
void onLettersChanged(QList<QString> letters);
8694
// 快捷键恢复默认完成
8795
void onResetFinished();
96+
void shortcutCommandReady(const QString &id, const QString &command, bool available);
8897

8998
public Q_SLOTS:
9099
void setLang(const QString &value);
@@ -122,6 +131,10 @@ public Q_SLOTS:
122131
void onLookupConflictForShortcutFinished(QDBusPendingCallWatcher *watch);
123132
void onShortcutCleanFinished(QDBusPendingCallWatcher *watch);
124133
void onCustomConflictCleanFinished(QDBusPendingCallWatcher *w);
134+
void onAddCustomShortcutFinished(QDBusPendingCallWatcher *watch);
135+
void onModifyCustomShortcutFinished(QDBusPendingCallWatcher *watch);
136+
void onDeleteCustomShortcutFinished(QDBusPendingCallWatcher *watch);
137+
void onGetShortcutCommandFinished(QDBusPendingCallWatcher *watch);
125138

126139
private:
127140
static QString makeShortcutKey(const QString &id, int type);

0 commit comments

Comments
 (0)