File indexing completed on 2024-05-12 17:07:18

0001 /*
0002     SPDX-FileCopyrightText: 2020 David Redondo <kde@david-redondo.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include "keysdata.h"
0008 
0009 #include <KGlobalAccel>
0010 #include <KGlobalShortcutInfo>
0011 #include <KPluginFactory>
0012 #include <KStandardShortcut>
0013 #include <kglobalaccel_component_interface.h>
0014 #include <kglobalaccel_interface.h>
0015 
0016 KeysData::KeysData(QObject *parent, const QVariantList &args)
0017     : KCModuleData(parent, args)
0018 {
0019     for (int i = KStandardShortcut::AccelNone + 1; i < KStandardShortcut::StandardShortcutCount; ++i) {
0020         const auto id = static_cast<KStandardShortcut::StandardShortcut>(i);
0021         const QList<QKeySequence> activeShortcuts = KStandardShortcut::shortcut(id);
0022         const QList<QKeySequence> defaultShortcuts = KStandardShortcut::hardcodedDefaultShortcut(id);
0023         if (activeShortcuts != defaultShortcuts) {
0024             m_isDefault = false;
0025             return;
0026         }
0027     }
0028 
0029     KGlobalAccelInterface globalAccelInterface(QStringLiteral("org.kde.kglobalaccel"), QStringLiteral("/kglobalaccel"), QDBusConnection::sessionBus());
0030     if (!globalAccelInterface.isValid()) {
0031         return;
0032     }
0033 
0034     // Default behavior of KCModuleData is to Q_EMIT the 'aboutToLoad' after construction which
0035     // triggers the 'loaded' signal. Because we query the data in an async way we Q_EMIT 'loaded'
0036     // manually when were are done.
0037     disconnect(this, &KCModuleData::aboutToLoad, this, &KCModuleData::loaded);
0038 
0039     auto componentsWatcher = new QDBusPendingCallWatcher(globalAccelInterface.allComponents());
0040     connect(componentsWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
0041         QDBusPendingReply<QList<QDBusObjectPath>> componentsReply = *watcher;
0042         if (componentsReply.isError() || componentsReply.value().isEmpty()) {
0043             Q_EMIT loaded();
0044             return;
0045         }
0046         const auto components = componentsReply.value();
0047         for (const auto &componentPath : components) {
0048             KGlobalAccelComponentInterface component(QStringLiteral("org.kde.kglobalaccel"), componentPath.path(), QDBusConnection::sessionBus());
0049             ++m_pendingComponentCalls;
0050             auto shortcutsWatcher = new QDBusPendingCallWatcher(component.allShortcutInfos());
0051             connect(shortcutsWatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
0052                 QDBusPendingReply<QList<KGlobalShortcutInfo>> shortcutsReply = *watcher;
0053                 if (shortcutsReply.isValid()) {
0054                     const auto allShortcuts = shortcutsReply.value();
0055                     bool isNotDefault = std::any_of(allShortcuts.cbegin(), allShortcuts.cend(), [](const KGlobalShortcutInfo &info) {
0056                         return info.defaultKeys() != info.keys();
0057                     });
0058                     m_isDefault &= isNotDefault;
0059                 }
0060                 if (--m_pendingComponentCalls == 0) {
0061                     Q_EMIT loaded();
0062                 }
0063             });
0064         }
0065     });
0066 }
0067 
0068 bool KeysData::isDefaults() const
0069 {
0070     return m_isDefault;
0071 }