File indexing completed on 2024-05-19 05:29:56

0001 /*
0002     SPDX-FileCopyrightText: 2008 Michael Jansen <kde@michael-jansen.biz>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef GLOBALSHORTCUTSREGISTRY_H
0008 #define GLOBALSHORTCUTSREGISTRY_H
0009 
0010 #include "kglobalaccel.h"
0011 
0012 #include "component.h"
0013 #include "kserviceactioncomponent.h"
0014 
0015 #include <KSharedConfig>
0016 
0017 #include <QDBusObjectPath>
0018 #include <QHash>
0019 #include <QKeySequence>
0020 #include <QObject>
0021 
0022 #include "kglobalaccel_export.h"
0023 
0024 class Component;
0025 class GlobalShortcut;
0026 class KGlobalAccelInterface;
0027 
0028 /**
0029  * Global Shortcut Registry.
0030  *
0031  * Shortcuts are registered by component. A component is for example kmail or
0032  * amarok.
0033  *
0034  * A component can have contexts. Currently on plasma is planned to support
0035  * that feature. A context enables plasma to keep track of global shortcut
0036  * settings when switching containments.
0037  *
0038  * A shortcut (WIN+x) can be registered by one component only. The component
0039  * is allowed to register it more than once in different contexts.
0040  *
0041  * @author Michael Jansen <kde@michael-jansen.biz>
0042  */
0043 class KGLOBALACCEL_EXPORT GlobalShortcutsRegistry : public QObject
0044 {
0045     Q_OBJECT
0046 
0047     Q_CLASSINFO("D-Bus Interface", "org.kde.KdedGlobalAccel.GlobalShortcutsRegistry")
0048 
0049 public:
0050     /**
0051      * Use GlobalShortcutsRegistry::self()
0052      *
0053      * @internal
0054      */
0055     GlobalShortcutsRegistry();
0056     ~GlobalShortcutsRegistry() override;
0057 
0058     /**
0059      * Activate all shortcuts having their application present.
0060      */
0061     void activateShortcuts();
0062 
0063     /**
0064      * Returns a list of D-Bus paths of registered Components.
0065      *
0066      * The returned paths are absolute (i.e. no need to prepend anything).
0067      */
0068     QList<QDBusObjectPath> componentsDbusPaths() const;
0069 
0070     /**
0071      * Returns a list of QStringLists (one string list per registered component,
0072      * with each string list containing four strings, one for each enumerator in
0073      * KGlobalAccel::actionIdFields).
0074      */
0075     QList<QStringList> allComponentNames() const;
0076 
0077     /**
0078      * Return the root dbus path for the registry.
0079      */
0080     QDBusObjectPath dbusPath() const;
0081 
0082     /**
0083      * Deactivate all currently active shortcuts.
0084      */
0085     void deactivateShortcuts(bool temporarily = false);
0086 
0087     /**
0088      */
0089     Component *getComponent(const QString &uniqueName);
0090 
0091     /**
0092      * Get the shortcut corresponding to key. Active and inactive shortcuts
0093      * are considered. But if the matching application uses contexts only one
0094      * shortcut is returned.
0095      *
0096      * @see getShortcutsByKey(int key)
0097      */
0098     GlobalShortcut *getShortcutByKey(const QKeySequence &key, KGlobalAccel::MatchType type = KGlobalAccel::MatchType::Equal) const;
0099 
0100     /**
0101      * Get the shortcuts corresponding to key. Active and inactive shortcuts
0102      * are considered.
0103      *
0104      * @see getShortcutsByKey(int key)
0105      */
0106     QList<GlobalShortcut *> getShortcutsByKey(const QKeySequence &key, KGlobalAccel::MatchType type) const;
0107 
0108     /**
0109      * Checks if @p shortcut is available for @p component.
0110      *
0111      * It is available if not used by another component in any context or used
0112      * by @p component only in not active contexts.
0113      */
0114     bool isShortcutAvailable(const QKeySequence &shortcut, const QString &component, const QString &context) const;
0115 
0116     static GlobalShortcutsRegistry *self();
0117 
0118     bool registerKey(const QKeySequence &key, GlobalShortcut *shortcut);
0119 
0120     void setDBusPath(const QDBusObjectPath &path);
0121 
0122     bool unregisterKey(const QKeySequence &key, GlobalShortcut *shortcut);
0123 
0124 public Q_SLOTS:
0125 
0126     void clear();
0127 
0128     void loadSettings();
0129 
0130     void writeSettings();
0131 
0132     // Grab the keys
0133     void grabKeys();
0134 
0135     // Ungrab the keys
0136     void ungrabKeys();
0137 
0138 private:
0139     friend struct KGlobalAccelDPrivate;
0140     friend class Component;
0141     friend class KGlobalAccelInterface;
0142 
0143     Component *createComponent(const QString &uniqueName, const QString &friendlyName);
0144     KServiceActionComponent *createServiceActionComponent(const QString &uniqueName);
0145     KServiceActionComponent *createServiceActionComponent(KService::Ptr service);
0146     void migrateConfig();
0147     void migrateKHotkeys();
0148 
0149     static void unregisterComponent(Component *component);
0150     using ComponentPtr = std::unique_ptr<Component, decltype(&unregisterComponent)>;
0151 
0152     Component *registerComponent(ComponentPtr component);
0153 
0154     // called by the implementation to inform us about key presses
0155     // returns true if the key was handled
0156     bool keyPressed(int keyQt);
0157     bool keyReleased(int keyQt);
0158 
0159     QHash<QKeySequence, GlobalShortcut *> _active_keys;
0160     QKeySequence _active_sequence;
0161     QHash<int, int> _keys_count;
0162 
0163     using ComponentVec = std::vector<ComponentPtr>;
0164     ComponentVec m_components;
0165     ComponentVec::const_iterator findByName(const QString &name) const
0166     {
0167         return std::find_if(m_components.cbegin(), m_components.cend(), [&name](const ComponentPtr &comp) {
0168             return comp->uniqueName() == name;
0169         });
0170     }
0171 
0172     KGlobalAccelInterface *_manager = nullptr;
0173 
0174     mutable KConfig _config;
0175 
0176     QDBusObjectPath _dbusPath;
0177     GlobalShortcut *m_lastShortcut = nullptr;
0178 };
0179 
0180 #endif /* #ifndef GLOBALSHORTCUTSREGISTRY_H */