File indexing completed on 2024-04-21 16:12:52

0001 /*
0002     SPDX-License-Identifier: GPL-2.0-only
0003     SPDX-FileCopyrightText: 1999-2001 Lubos Lunak <l.lunak@kde.org>
0004  */
0005 
0006 #include "kded.h"
0007 
0008 #include "action_data/action_data_group.h"
0009 #include "action_data/menuentry_shortcut_action_data.h"
0010 #include "actions/actions.h"
0011 
0012 #include "shortcuts_handler.h"
0013 
0014 #include "triggers/gestures.h"
0015 
0016 #include <QDebug>
0017 #include <kglobalaccel.h>
0018 #include <kpluginfactory.h>
0019 #include <kpluginloader.h>
0020 
0021 #include <unistd.h>
0022 
0023 #define COMPONENT_NAME "khotkeys"
0024 
0025 K_PLUGIN_FACTORY_WITH_JSON(KHotKeysModuleFactory, "khotkeys.json", registerPlugin<KHotKeysModule>();)
0026 
0027 using namespace KHotKeys;
0028 
0029 // KhotKeysModule
0030 
0031 KHotKeysModule::KHotKeysModule(QObject *parent, const QList<QVariant> &)
0032     : KDEDModule(parent)
0033     , actions_root(nullptr)
0034     , _settingsDirty(false)
0035     , _settings()
0036     , _initialized(false)
0037 {
0038     // initialize
0039     qDebug() << "Installing the delayed initialization callback.";
0040     QMetaObject::invokeMethod(this, "initialize", Qt::QueuedConnection);
0041 }
0042 
0043 void KHotKeysModule::initialize()
0044 {
0045     if (_initialized) {
0046         return;
0047     }
0048 
0049     qDebug() << "Delayed initialization.";
0050     _initialized = true;
0051 
0052     // Initialize the global data, grab keys
0053     KHotKeys::init_global_data(true, this);
0054 
0055     // If a shortcut was changed (global shortcuts kcm), save
0056     connect(keyboard_handler.data(), SIGNAL(shortcutChanged()), this, SLOT(scheduleSave()));
0057 
0058     // Read the configuration from file khotkeysrc
0059     reread_configuration();
0060 
0061     KGlobalAccel::cleanComponent(COMPONENT_NAME);
0062 
0063     if (_settings.update()) {
0064         save();
0065     }
0066 }
0067 
0068 KHotKeysModule::~KHotKeysModule()
0069 {
0070     // actions_root belongs to _settings.
0071     actions_root = nullptr;
0072 }
0073 
0074 void KHotKeysModule::reread_configuration()
0075 {
0076     qDebug() << "Reloading the khotkeys configuration";
0077 
0078     // Stop listening
0079     actions_root = nullptr; // Disables the dbus interface effectively
0080     KHotKeys::khotkeys_set_active(false);
0081 
0082     // Load the settings
0083     _settings.reread_settings(true);
0084 
0085     KHotKeys::gesture_handler->set_mouse_button(_settings.gestureMouseButton());
0086     KHotKeys::gesture_handler->set_timeout(_settings.gestureTimeOut());
0087     qDebug() << _settings.areGesturesDisabled();
0088     KHotKeys::gesture_handler->enable(!_settings.areGesturesDisabled());
0089     KHotKeys::gesture_handler->set_exclude(_settings.gesturesExclude());
0090     actions_root = _settings.actions();
0091     KHotKeys::khotkeys_set_active(true);
0092 }
0093 
0094 SimpleActionData *KHotKeysModule::menuentry_action(const QString &storageId)
0095 {
0096     ActionDataGroup *menuentries = _settings.get_system_group(ActionDataGroup::SYSTEM_MENUENTRIES);
0097 
0098     // Now try to find the action
0099     Q_FOREACH (ActionDataBase *element, menuentries->children()) {
0100         SimpleActionData *actionData = dynamic_cast<SimpleActionData *>(element);
0101 
0102         if (actionData && actionData->action()) {
0103             MenuEntryAction *action = dynamic_cast<MenuEntryAction *>(actionData->action());
0104             if (action && action->service() && (action->service()->storageId() == storageId)) {
0105                 return actionData;
0106             }
0107         }
0108     }
0109 
0110     return nullptr;
0111 }
0112 
0113 QString KHotKeysModule::get_menuentry_shortcut(const QString &storageId)
0114 {
0115     SimpleActionData *actionData = menuentry_action(storageId);
0116 
0117     // No action found
0118     if (actionData == nullptr)
0119         return "";
0120 
0121     // The action must have a shortcut trigger. but don't assume to much
0122     ShortcutTrigger *shortcutTrigger = dynamic_cast<ShortcutTrigger *>(actionData->trigger());
0123 
0124     Q_ASSERT(shortcutTrigger);
0125     if (shortcutTrigger == nullptr)
0126         return "";
0127 
0128     qDebug() << shortcutTrigger->primaryShortcut();
0129 
0130     return shortcutTrigger->primaryShortcut();
0131 }
0132 
0133 QString KHotKeysModule::register_menuentry_shortcut(const QString &storageId, const QString &sequence)
0134 {
0135     qDebug() << storageId << "(" << sequence << ")";
0136 
0137     // Check the service we got. If it is invalid there is no need to
0138     // continue.
0139     KService::Ptr wantedService = KService::serviceByStorageId(storageId);
0140     if (!wantedService) {
0141         qCritical() << "Storage Id " << storageId << "not valid";
0142         return "";
0143     }
0144 
0145     // Look for the action
0146     SimpleActionData *actionData = menuentry_action(storageId);
0147 
0148     // No action found. Create on if sequence is != ""
0149     if (actionData == nullptr) {
0150         qDebug() << "No action found";
0151 
0152         // If the sequence is empty there is no need to create a action.
0153         if (sequence.isEmpty())
0154             return "";
0155 
0156         qDebug() << "Creating a new action";
0157 
0158         // Create the action
0159         ActionDataGroup *menuentries = _settings.get_system_group(ActionDataGroup::SYSTEM_MENUENTRIES);
0160 
0161         MenuEntryShortcutActionData *newAction =
0162             new MenuEntryShortcutActionData(menuentries, wantedService->name(), storageId, QKeySequence(sequence), storageId);
0163 
0164         newAction->enable();
0165 
0166         _settings.write();
0167 
0168         // Return the real shortcut
0169         return newAction->trigger()->primaryShortcut();
0170     }
0171     // We found a action
0172     else {
0173         if (sequence.isEmpty()) {
0174             qDebug() << "Deleting the action";
0175             actionData->aboutToBeErased();
0176             delete actionData;
0177             _settings.write();
0178             return "";
0179         } else {
0180             qDebug() << "Changing the action";
0181             // The action must have a shortcut trigger. but don't assume to much
0182             ShortcutTrigger *shortcutTrigger = dynamic_cast<ShortcutTrigger *>(actionData->trigger());
0183             Q_ASSERT(shortcutTrigger);
0184             if (shortcutTrigger == nullptr)
0185                 return "";
0186 
0187             // Change the actionData
0188             shortcutTrigger->set_key_sequence(sequence);
0189             _settings.write();
0190 
0191             // Remove the resulting real shortcut
0192             return shortcutTrigger->primaryShortcut();
0193         }
0194     }
0195 
0196     Q_ASSERT(false);
0197     return "";
0198 }
0199 
0200 void KHotKeysModule::quit()
0201 {
0202     deleteLater();
0203 }
0204 
0205 void KHotKeysModule::scheduleSave()
0206 {
0207     if (!_settingsDirty) {
0208         _settingsDirty = true;
0209         QMetaObject::invokeMethod(this, "save", Qt::QueuedConnection);
0210     }
0211 }
0212 
0213 void KHotKeysModule::save()
0214 {
0215     _settingsDirty = false;
0216     KHotKeys::khotkeys_set_active(false);
0217     _settings.write();
0218     KHotKeys::khotkeys_set_active(true);
0219 }
0220 
0221 void KHotKeysModule::declareConfigOutdated()
0222 {
0223     Settings::isOutdated = true;
0224 }
0225 
0226 #include "kded.moc"