File indexing completed on 2024-04-14 14:20:57

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