File indexing completed on 2025-04-20 10:56:04
0001 /* 0002 SPDX-FileCopyrightText: 1999-2001 Lubos Lunak <l.lunak@kde.org> 0003 SPDX-FileCopyrightText: 2008 Michael Jansen <kde@michael-jansen.biz> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "action_data/action_data.h" 0009 #include "triggers/triggers.h" 0010 #include "windows_handler.h" 0011 0012 #include <KConfigGroup> 0013 #include <KGlobalAccel> 0014 #include <QDebug> 0015 0016 #include <QAction> 0017 0018 #include "shortcuts_handler.h" 0019 0020 namespace KHotKeys 0021 { 0022 ShortcutTriggerVisitor::~ShortcutTriggerVisitor() 0023 { 0024 } 0025 0026 ShortcutTrigger::ShortcutTrigger(ActionData *data_P, const QKeySequence &shortcut, const QUuid &uuid) 0027 : Trigger(data_P) 0028 , _uuid(uuid) 0029 , _active(false) 0030 , _shortcut(shortcut) 0031 { 0032 } 0033 0034 ShortcutTrigger::~ShortcutTrigger() 0035 { 0036 keyboard_handler->removeAction(_uuid.toString()); 0037 } 0038 0039 void ShortcutTrigger::accept(TriggerVisitor &visitor) 0040 { 0041 if (ShortcutTriggerVisitor *v = dynamic_cast<ShortcutTriggerVisitor *>(&visitor)) { 0042 v->visit(*this); 0043 } else { 0044 qDebug() << "Visitor error"; 0045 } 0046 } 0047 0048 void ShortcutTrigger::aboutToBeErased() 0049 { 0050 disable(); 0051 } 0052 0053 void ShortcutTrigger::activate(bool newState) 0054 { 0055 #ifdef KHOTKEYS_TRACE 0056 qDebug() << "new:" << newState << "old:" << _active; 0057 #endif 0058 // If there is no change in state just return. 0059 if (newState == _active) 0060 return; 0061 0062 _active = newState; 0063 0064 if (_active) { 0065 QString name = data ? data->name() : "TODO"; 0066 0067 // FIXME: The following workaround tries to prevent having two actions with 0068 // the same uuid. That happens wile exporting/importing actions. The uuid 0069 // is exported too. 0070 QAction *act = keyboard_handler->addAction(_uuid.toString(), name, _shortcut); 0071 // addAction can change the uuid. That's why we store the uuid from the 0072 // action 0073 _uuid = act->objectName(); 0074 0075 connect(act, SIGNAL(triggered(bool)), this, SLOT(trigger())); 0076 } else { 0077 // Disable the trigger. Delete the action. 0078 QAction *action = keyboard_handler->getAction(_uuid.toString()); 0079 if (action) { 0080 // In case the shortcut was changed from the kcm. 0081 auto shortcuts = KGlobalAccel::self()->shortcut(action); 0082 if (!shortcuts.isEmpty()) { 0083 _shortcut = QKeySequence(shortcuts.first()); 0084 } else { 0085 _shortcut = QKeySequence(); 0086 } 0087 keyboard_handler->removeAction(_uuid.toString()); 0088 } 0089 } 0090 } 0091 0092 QString ShortcutTrigger::shortcuts() const 0093 { 0094 const auto shortcuts = shortcut(); 0095 QString shortcutString; 0096 for (auto it = shortcuts.constBegin(); it != shortcuts.constEnd(); ++it) { 0097 if (it != shortcuts.constBegin()) { 0098 shortcutString.append(QStringLiteral(";")); 0099 } 0100 shortcutString.append((*it).toString()); 0101 } 0102 return shortcutString; 0103 } 0104 0105 void ShortcutTrigger::cfg_write(KConfigGroup &cfg_P) const 0106 { 0107 base::cfg_write(cfg_P); 0108 cfg_P.writeEntry("Key", shortcuts()); 0109 cfg_P.writeEntry("Type", "SHORTCUT"); // overwrites value set in base::cfg_write() 0110 cfg_P.writeEntry("Uuid", _uuid.toString()); 0111 } 0112 0113 ShortcutTrigger *ShortcutTrigger::copy(ActionData *data_P) const 0114 { 0115 return new ShortcutTrigger(data_P ? data_P : data, shortcut().first(), QUuid::createUuid()); 0116 } 0117 0118 const QString ShortcutTrigger::description() const 0119 { 0120 return i18n("Shortcut trigger: ") + shortcuts(); 0121 } 0122 0123 void ShortcutTrigger::disable() 0124 { 0125 activate(false); 0126 0127 // Unregister the shortcut with kglobalaccel 0128 QAction *action = keyboard_handler->getAction(_uuid.toString()); 0129 if (action) { 0130 // In case the shortcut was changed from the kcm. 0131 auto shortcuts = KGlobalAccel::self()->shortcut(action); 0132 if (!shortcuts.isEmpty()) { 0133 _shortcut = QKeySequence(shortcuts.first()); 0134 } else { 0135 _shortcut = QKeySequence(); 0136 } 0137 0138 // Unregister the global shortcut. 0139 KGlobalAccel::self()->removeAllShortcuts(action); 0140 keyboard_handler->removeAction(_uuid.toString()); 0141 } 0142 } 0143 0144 void ShortcutTrigger::enable() 0145 { 0146 // To enable the shortcut we have to just register it once with 0147 // kglobalaccel and deactivate it immediately 0148 activate(true); 0149 activate(false); 0150 } 0151 0152 void ShortcutTrigger::set_key_sequence(const QKeySequence &seq) 0153 { 0154 // Get the action from the keyboard handler 0155 QAction *action = keyboard_handler->getAction(_uuid.toString()); 0156 if (!action) { 0157 _shortcut = seq; 0158 } else { 0159 KGlobalAccel::self()->setShortcut(action, QList<QKeySequence>() << seq, KGlobalAccel::KGlobalAccel::NoAutoloading); 0160 } 0161 } 0162 0163 QList<QKeySequence> ShortcutTrigger::shortcut() const 0164 { 0165 // Get the action from the keyboard handler 0166 QAction *action = keyboard_handler->getAction(_uuid.toString()); 0167 if (!action) { 0168 // Not active! 0169 return {_shortcut}; 0170 } 0171 0172 return KGlobalAccel::self()->shortcut(action); 0173 } 0174 0175 QString ShortcutTrigger::primaryShortcut() const 0176 { 0177 const auto shortcuts = shortcut(); 0178 if (!shortcuts.isEmpty()) { 0179 return shortcuts.first().toString(); 0180 } else { 0181 return QString(); 0182 } 0183 } 0184 0185 void ShortcutTrigger::trigger() 0186 { 0187 if (khotkeys_active()) { 0188 windows_handler->set_action_window(0); // use active window 0189 data->execute(); 0190 } 0191 } 0192 0193 } // namespace KHotKeys