1 /*
2 SPDX-FileCopyrightText: 2020 David Redondo <kde@david-redondo.de>
3
4 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
5 */
6
7 #include "keysdata.h"
8
9 #include <KGlobalAccel>
10 #include <KGlobalShortcutInfo>
11 #include <KPluginFactory>
12 #include <KStandardShortcut>
13 #include <kglobalaccel_component_interface.h>
14 #include <kglobalaccel_interface.h>
15
KeysData(QObject * parent,const QVariantList & args)16 KeysData::KeysData(QObject *parent, const QVariantList &args)
17 : KCModuleData(parent, args)
18 {
19 for (int i = KStandardShortcut::AccelNone + 1; i < KStandardShortcut::StandardShortcutCount; ++i) {
20 const auto id = static_cast<KStandardShortcut::StandardShortcut>(i);
21 const QList<QKeySequence> activeShortcuts = KStandardShortcut::shortcut(id);
22 const QList<QKeySequence> defaultShortcuts = KStandardShortcut::hardcodedDefaultShortcut(id);
23 if (activeShortcuts != defaultShortcuts) {
24 m_isDefault = false;
25 return;
26 }
27 }
28
29 KGlobalAccelInterface globalAccelInterface(QStringLiteral("org.kde.kglobalaccel"), QStringLiteral("/kglobalaccel"), QDBusConnection::sessionBus());
30 if (!globalAccelInterface.isValid()) {
31 return;
32 }
33
34 // Default behavior of KCModuleData is to Q_EMIT the 'aboutToLoad' after construction which
35 // triggers the 'loaded' signal. Because we query the data in an async way we Q_EMIT 'loaded'
36 // manually when were are done.
37 disconnect(this, &KCModuleData::aboutToLoad, this, &KCModuleData::loaded);
38
39 auto componentsWatcher = new QDBusPendingCallWatcher(globalAccelInterface.allComponents());
40 connect(componentsWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
41 QDBusPendingReply<QList<QDBusObjectPath>> componentsReply = *watcher;
42 if (componentsReply.isError() || componentsReply.value().isEmpty()) {
43 Q_EMIT loaded();
44 return;
45 }
46 const auto components = componentsReply.value();
47 for (const auto &componentPath : components) {
48 KGlobalAccelComponentInterface component(QStringLiteral("org.kde.kglobalaccel"), componentPath.path(), QDBusConnection::sessionBus());
49 ++m_pendingComponentCalls;
50 auto shortcutsWatcher = new QDBusPendingCallWatcher(component.allShortcutInfos());
51 connect(shortcutsWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
52 QDBusPendingReply<QList<KGlobalShortcutInfo>> shortcutsReply = *watcher;
53 if (shortcutsReply.isValid()) {
54 const auto allShortcuts = shortcutsReply.value();
55 bool isNotDefault = std::any_of(allShortcuts.cbegin(), allShortcuts.cend(), [](const KGlobalShortcutInfo &info) {
56 return info.defaultKeys() != info.keys();
57 });
58 m_isDefault &= isNotDefault;
59 }
60 if (--m_pendingComponentCalls == 0) {
61 Q_EMIT loaded();
62 }
63 });
64 }
65 });
66 }
67
isDefaults() const68 bool KeysData::isDefaults() const
69 {
70 return m_isDefault;
71 }
72