File indexing completed on 2024-04-28 11:37:12
0001 /* 0002 SPDX-FileCopyrightText: 2008 Michael Jansen <kde@michael-jansen.biz> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "globalshortcut.h" 0008 0009 #include "kglobalshortcutinfo_p.h" 0010 0011 #include "component.h" 0012 #include "globalshortcutcontext.h" 0013 #include "globalshortcutsregistry.h" 0014 #include "logging_p.h" 0015 0016 #include <QKeySequence> 0017 0018 GlobalShortcut::GlobalShortcut() 0019 : GlobalShortcut(QString{}, QString{}, nullptr) 0020 { 0021 } 0022 0023 GlobalShortcut::GlobalShortcut(const QString &uniqueName, const QString &friendlyName, GlobalShortcutContext *context) 0024 : _isPresent(false) 0025 , _isRegistered(false) 0026 , _isFresh(true) 0027 , _registry(GlobalShortcutsRegistry::self()) 0028 , _context(context) 0029 , _uniqueName(uniqueName) 0030 , _friendlyName(friendlyName) 0031 { 0032 if (_context) { 0033 _context->addShortcut(this); 0034 } 0035 } 0036 0037 GlobalShortcut::~GlobalShortcut() 0038 { 0039 setInactive(); 0040 } 0041 0042 GlobalShortcut::operator KGlobalShortcutInfo() const 0043 { 0044 KGlobalShortcutInfo info; 0045 info.d->uniqueName = _uniqueName; 0046 info.d->friendlyName = _friendlyName; 0047 info.d->contextUniqueName = context()->uniqueName(); 0048 info.d->contextFriendlyName = context()->friendlyName(); 0049 info.d->componentUniqueName = context()->component()->uniqueName(); 0050 info.d->componentFriendlyName = context()->component()->friendlyName(); 0051 for (const QKeySequence &key : std::as_const(_keys)) { 0052 info.d->keys.append(key); 0053 } 0054 for (const QKeySequence &key : std::as_const(_defaultKeys)) { 0055 info.d->defaultKeys.append(key); 0056 } 0057 return info; 0058 } 0059 0060 bool GlobalShortcut::isActive() const 0061 { 0062 return _isRegistered; 0063 } 0064 0065 bool GlobalShortcut::isFresh() const 0066 { 0067 return _isFresh; 0068 } 0069 0070 bool GlobalShortcut::isPresent() const 0071 { 0072 return _isPresent; 0073 } 0074 0075 bool GlobalShortcut::isSessionShortcut() const 0076 { 0077 return uniqueName().startsWith(QLatin1String("_k_session:")); 0078 } 0079 0080 void GlobalShortcut::setIsFresh(bool value) 0081 { 0082 _isFresh = value; 0083 } 0084 0085 void GlobalShortcut::setIsPresent(bool value) 0086 { 0087 // (de)activate depending on old/new value 0088 _isPresent = value; 0089 if (_isPresent) { 0090 setActive(); 0091 } else { 0092 setInactive(); 0093 } 0094 } 0095 0096 GlobalShortcutContext *GlobalShortcut::context() 0097 { 0098 return _context; 0099 } 0100 0101 GlobalShortcutContext const *GlobalShortcut::context() const 0102 { 0103 return _context; 0104 } 0105 0106 QString GlobalShortcut::uniqueName() const 0107 { 0108 return _uniqueName; 0109 } 0110 0111 void GlobalShortcut::unRegister() 0112 { 0113 return _context->component()->unregisterShortcut(uniqueName()); 0114 } 0115 0116 QString GlobalShortcut::friendlyName() const 0117 { 0118 return _friendlyName; 0119 } 0120 0121 void GlobalShortcut::setFriendlyName(const QString &name) 0122 { 0123 _friendlyName = name; 0124 } 0125 0126 QList<QKeySequence> GlobalShortcut::keys() const 0127 { 0128 return _keys; 0129 } 0130 0131 void GlobalShortcut::setKeys(const QList<QKeySequence> &newKeys) 0132 { 0133 bool active = _isRegistered; 0134 if (active) { 0135 setInactive(); 0136 } 0137 0138 _keys.clear(); 0139 0140 auto getKey = [this](const QKeySequence &key) { 0141 if (key.isEmpty()) { 0142 qCDebug(KGLOBALACCELD) << _uniqueName << "skipping because key is empty"; 0143 return QKeySequence{}; 0144 } 0145 0146 if (_registry->getShortcutByKey(key) // 0147 || _registry->getShortcutByKey(key, KGlobalAccel::MatchType::Shadowed) // 0148 || _registry->getShortcutByKey(key, KGlobalAccel::MatchType::Shadows) // 0149 ) { 0150 qCDebug(KGLOBALACCELD) << _uniqueName << "skipping because key" << QKeySequence(key).toString() << "is already taken"; 0151 return QKeySequence{}; 0152 } 0153 0154 return key; 0155 }; 0156 0157 std::transform(newKeys.cbegin(), newKeys.cend(), std::back_inserter(_keys), getKey); 0158 0159 if (active) { 0160 setActive(); 0161 } 0162 } 0163 0164 QList<QKeySequence> GlobalShortcut::defaultKeys() const 0165 { 0166 return _defaultKeys; 0167 } 0168 0169 void GlobalShortcut::setDefaultKeys(const QList<QKeySequence> &newKeys) 0170 { 0171 _defaultKeys = newKeys; 0172 } 0173 0174 void GlobalShortcut::setActive() 0175 { 0176 if (!_isPresent || _isRegistered) { 0177 // The corresponding application is not present or the keys are 0178 // already grabbed 0179 return; 0180 } 0181 0182 for (const QKeySequence &key : std::as_const(_keys)) { 0183 if (!key.isEmpty() && !_registry->registerKey(key, this)) { 0184 qCDebug(KGLOBALACCELD) << uniqueName() << ": Failed to register " << QKeySequence(key).toString(); 0185 } 0186 } 0187 0188 _isRegistered = true; 0189 } 0190 0191 void GlobalShortcut::setInactive() 0192 { 0193 if (!_isRegistered) { 0194 // The keys are not grabbed currently 0195 return; 0196 } 0197 0198 for (const QKeySequence &key : std::as_const(_keys)) { 0199 if (!key.isEmpty() && !_registry->unregisterKey(key, this)) { 0200 qCDebug(KGLOBALACCELD) << uniqueName() << ": Failed to unregister " << QKeySequence(key).toString(); 0201 } 0202 } 0203 0204 _isRegistered = false; 0205 }