File indexing completed on 2024-09-15 10:32:54
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 "hotkeys_context_menu.h" 0008 #include "hotkeys_export_widget.h" 0009 #include "hotkeys_tree_view.h" 0010 0011 #include "hotkeys_model.h" 0012 0013 #include "action_data/action_data_group.h" 0014 #include "action_data/simple_action_data.h" 0015 0016 #include <QDebug> 0017 0018 #include <QContextMenuEvent> 0019 #include <QFileDialog> 0020 #include <QSignalMapper> 0021 0022 #include <KConfig> 0023 0024 HotkeysTreeViewContextMenu::HotkeysTreeViewContextMenu(const QModelIndex &index, HotkeysTreeView *parent) 0025 : QMenu(parent) 0026 , _index(index) 0027 , _view(parent) 0028 { 0029 setTitle(i18n("Test")); 0030 0031 connect(this, SIGNAL(aboutToShow()), SLOT(slotAboutToShow())); 0032 } 0033 0034 HotkeysTreeViewContextMenu::HotkeysTreeViewContextMenu(HotkeysTreeView *parent) 0035 : QMenu(parent) 0036 , _index() 0037 , _view(parent) 0038 { 0039 setTitle(i18n("Test")); 0040 0041 connect(this, SIGNAL(aboutToShow()), SLOT(slotAboutToShowForCurrent())); 0042 } 0043 0044 HotkeysTreeViewContextMenu::~HotkeysTreeViewContextMenu() 0045 { 0046 } 0047 0048 KHotKeys::Action *HotkeysTreeViewContextMenu::createActionFromType(int actionType, KHotKeys::SimpleActionData *data) const 0049 { 0050 KHotKeys::Action *action = nullptr; 0051 switch (actionType) { 0052 case KHotKeys::Action::CommandUrlActionType: 0053 action = new KHotKeys::CommandUrlAction(data); 0054 break; 0055 0056 case KHotKeys::Action::DBusActionType: 0057 action = new KHotKeys::DBusAction(data); 0058 break; 0059 0060 case KHotKeys::Action::KeyboardInputActionType: 0061 action = new KHotKeys::KeyboardInputAction(data); 0062 break; 0063 0064 case KHotKeys::Action::MenuEntryActionType: 0065 action = new KHotKeys::MenuEntryAction(data); 0066 break; 0067 0068 default: 0069 Q_ASSERT(false); 0070 return nullptr; 0071 } 0072 0073 data->set_action(action); 0074 return action; 0075 } 0076 0077 void HotkeysTreeViewContextMenu::slotAboutToShowForCurrent() 0078 { 0079 _index = _view->currentIndex(); 0080 0081 slotAboutToShow(); 0082 } 0083 0084 void HotkeysTreeViewContextMenu::slotAboutToShow() 0085 { 0086 clear(); 0087 0088 if (_index.isValid()) { 0089 KHotKeys::ActionDataBase *element = _view->model()->indexToActionDataBase(_index); 0090 KHotKeys::ActionDataGroup *group = _view->model()->indexToActionDataGroup(_index); 0091 bool isGroup = group; // Is the current element a group 0092 if (!isGroup) { 0093 group = element->parent(); 0094 } 0095 0096 // Create the create actions 0097 createTriggerMenus(group->allowedTriggerTypes(), group->allowedActionTypes()); 0098 0099 // It is not allowed to create a subgroup for a system group. 0100 if (!group->is_system_group()) { 0101 addAction(i18n("New Group"), this, SLOT(newGroupAction())); 0102 } 0103 0104 // It is not allowed to delete a system group 0105 if (!(isGroup && group->is_system_group())) { 0106 // Item related actions 0107 addAction(i18n("Delete"), this, SLOT(deleteAction())); 0108 } 0109 } else { 0110 createTriggerMenus(KHotKeys::Trigger::AllTypes, KHotKeys::Action::AllTypes); 0111 addAction(i18n("New Group"), this, SLOT(newGroupAction())); 0112 } 0113 0114 addSeparator(); 0115 addAction(i18n("Export Group..."), this, SLOT(exportAction())); 0116 addAction(i18n("Import..."), this, SLOT(importAction())); 0117 } 0118 0119 void HotkeysTreeViewContextMenu::createTriggerMenus(KHotKeys::Trigger::TriggerTypes triggerTypes, KHotKeys::Action::ActionTypes actionTypes) 0120 { 0121 QMenu *newMenu = new QMenu(i18nc("@title:menu create various trigger types", "New")); 0122 0123 if (triggerTypes & KHotKeys::Trigger::ShortcutTriggerType) { 0124 QSignalMapper *mapper = new QSignalMapper(this); 0125 0126 QMenu *menu = new QMenu(i18n("Global Shortcut")); 0127 populateTriggerMenu(menu, mapper, actionTypes); 0128 newMenu->addMenu(menu); 0129 0130 connect(mapper, SIGNAL(mapped(int)), this, SLOT(newGlobalShortcutActionAction(int))); 0131 } 0132 0133 if (triggerTypes & KHotKeys::Trigger::WindowTriggerType) { 0134 QSignalMapper *mapper = new QSignalMapper(this); 0135 0136 QMenu *menu = new QMenu(i18n("Window Action")); 0137 populateTriggerMenu(menu, mapper, actionTypes); 0138 newMenu->addMenu(menu); 0139 0140 connect(mapper, SIGNAL(mapped(int)), this, SLOT(newWindowTriggerActionAction(int))); 0141 } 0142 0143 if (triggerTypes & KHotKeys::Trigger::GestureTriggerType) { 0144 QSignalMapper *mapper = new QSignalMapper(this); 0145 0146 QMenu *menu = new QMenu(i18n("Mouse Gesture Action")); 0147 populateTriggerMenu(menu, mapper, actionTypes); 0148 newMenu->addMenu(menu); 0149 0150 connect(mapper, SIGNAL(mapped(int)), this, SLOT(newMouseGestureTriggerActionAction(int))); 0151 } 0152 0153 addMenu(newMenu); 0154 } 0155 0156 void HotkeysTreeViewContextMenu::importAction() 0157 { 0158 QUrl url = QFileDialog::getOpenFileUrl(this, QString(), QUrl(), QStringLiteral("*.khotkeys")); 0159 if (!url.isEmpty()) { 0160 KConfig config(url.path(QUrl::FullyDecoded), KConfig::SimpleConfig); 0161 _view->model()->importInputActions(_index, config); 0162 } 0163 } 0164 0165 void HotkeysTreeViewContextMenu::exportAction() 0166 { 0167 KHotkeysExportDialog *widget = new KHotkeysExportDialog(this); 0168 0169 KHotKeys::ActionDataGroup *group = _view->model()->indexToActionDataGroup(_index); 0170 if (!group) 0171 group = _view->model()->indexToActionDataBase(_index)->parent(); 0172 0173 widget->setImportId(group->importId()); 0174 widget->setAllowMerging(group->allowMerging()); 0175 0176 if (widget->exec() == QDialog::Accepted) { 0177 KHotKeys::ActionState state; 0178 switch (widget->state()) { 0179 case 0: 0180 state = KHotKeys::Retain; 0181 break; 0182 0183 case 1: 0184 state = KHotKeys::Enabled; 0185 break; 0186 0187 case 2: 0188 state = KHotKeys::Disabled; 0189 break; 0190 0191 default: 0192 // Unknown value fallen to our ui file. Use disabled as a 0193 // default. 0194 Q_ASSERT(false); 0195 state = KHotKeys::Disabled; 0196 break; 0197 } 0198 0199 QString id = widget->importId(); 0200 QUrl url = widget->url(); 0201 bool allowMerging = widget->allowMerging(); 0202 if (!url.isEmpty()) { 0203 KConfig config(url.path(), KConfig::SimpleConfig); 0204 _view->model()->exportInputActions(_index, config, id, state, allowMerging); 0205 } 0206 } 0207 delete widget; 0208 } 0209 0210 void HotkeysTreeViewContextMenu::populateTriggerMenu(QMenu *menu, QSignalMapper *mapper, KHotKeys::Action::ActionTypes types) 0211 { 0212 if (types & KHotKeys::Action::CommandUrlActionType) { 0213 mapper->setMapping(menu->addAction(i18n("Command/URL"), mapper, SLOT(map())), KHotKeys::Action::CommandUrlActionType); 0214 } 0215 0216 if (types & KHotKeys::Action::DBusActionType) { 0217 mapper->setMapping(menu->addAction(i18n("D-Bus Command"), mapper, SLOT(map())), KHotKeys::Action::DBusActionType); 0218 } 0219 0220 if (types & KHotKeys::Action::MenuEntryActionType) { 0221 mapper->setMapping(menu->addAction(i18n("K-Menu Entry"), mapper, SLOT(map())), KHotKeys::Action::MenuEntryActionType); 0222 } 0223 0224 if (types & KHotKeys::Action::KeyboardInputActionType) { 0225 mapper->setMapping(menu->addAction(i18n("Send Keyboard Input"), mapper, SLOT(map())), KHotKeys::Action::KeyboardInputActionType); 0226 } 0227 } 0228 0229 void HotkeysTreeViewContextMenu::newGlobalShortcutActionAction(int actionType) 0230 { 0231 QModelIndex parent; // == root element 0232 if (!_index.isValid() || _view->model()->data(_index.sibling(_index.row(), KHotkeysModel::IsGroupColumn)).toBool()) { 0233 // if the index is invalid (root index) or represents an group use it. 0234 parent = _index; 0235 } else { 0236 // It is an action. Take the parent. 0237 parent = _index.parent(); 0238 } 0239 0240 KHotKeys::SimpleActionData *data = new KHotKeys::SimpleActionData(nullptr, i18n("New Action"), i18n("Comment")); 0241 data->set_trigger(new KHotKeys::ShortcutTrigger(data, QKeySequence())); 0242 data->enable(); 0243 0244 createActionFromType(actionType, data); 0245 0246 QModelIndex newAct = _view->model()->insertActionData(data, parent); 0247 _view->setCurrentIndex(newAct); 0248 _view->edit(newAct); 0249 _view->resizeColumnToContents(KHotkeysModel::NameColumn); 0250 } 0251 0252 void HotkeysTreeViewContextMenu::newMouseGestureTriggerActionAction(int actionType) 0253 { 0254 QModelIndex parent; // == root element 0255 if (!_index.isValid() || _view->model()->data(_index.sibling(_index.row(), KHotkeysModel::IsGroupColumn)).toBool()) { 0256 // if the index is invalid (root index) or represents an group use it. 0257 parent = _index; 0258 } else { 0259 // It is an action. Take the parent. 0260 parent = _index.parent(); 0261 } 0262 0263 KHotKeys::SimpleActionData *data = new KHotKeys::SimpleActionData(nullptr, i18n("New Action"), i18n("Comment")); 0264 data->set_trigger(new KHotKeys::GestureTrigger(data)); 0265 data->enable(); 0266 0267 createActionFromType(actionType, data); 0268 0269 QModelIndex newAct = _view->model()->insertActionData(data, parent); 0270 _view->setCurrentIndex(newAct); 0271 _view->edit(newAct); 0272 _view->resizeColumnToContents(KHotkeysModel::NameColumn); 0273 } 0274 0275 void HotkeysTreeViewContextMenu::newWindowTriggerActionAction(int actionType) 0276 { 0277 QModelIndex parent; // == root element 0278 if (!_index.isValid() || _view->model()->data(_index.sibling(_index.row(), KHotkeysModel::IsGroupColumn)).toBool()) { 0279 // if the index is invalid (root index) or represents an group use it. 0280 parent = _index; 0281 } else { 0282 // It is an action. Take the parent. 0283 parent = _index.parent(); 0284 } 0285 0286 KHotKeys::SimpleActionData *data = new KHotKeys::SimpleActionData(nullptr, i18n("New Action"), i18n("Comment")); 0287 data->set_trigger(new KHotKeys::WindowTrigger(data)); 0288 data->enable(); 0289 0290 createActionFromType(actionType, data); 0291 0292 QModelIndex newAct = _view->model()->insertActionData(data, parent); 0293 _view->setCurrentIndex(newAct); 0294 _view->edit(newAct); 0295 _view->resizeColumnToContents(KHotkeysModel::NameColumn); 0296 } 0297 0298 void HotkeysTreeViewContextMenu::newGroupAction() 0299 { 0300 QModelIndex parent; // == root element 0301 if (!_index.isValid() || _view->model()->data(_index.sibling(_index.row(), KHotkeysModel::IsGroupColumn)).toBool()) { 0302 // if the index is invalid (root index) or represents an group use it. 0303 parent = _index; 0304 } else { 0305 // It is an action. Take the parent. 0306 parent = _index.parent(); 0307 } 0308 0309 QModelIndex newGroup = _view->model()->addGroup(parent); 0310 _view->setCurrentIndex(newGroup); 0311 _view->edit(newGroup); 0312 _view->resizeColumnToContents(KHotkeysModel::NameColumn); 0313 } 0314 0315 void HotkeysTreeViewContextMenu::deleteAction() 0316 { 0317 if (!_index.isValid()) { 0318 Q_ASSERT(_index.isValid()); 0319 return; 0320 } 0321 0322 bool deletionSuccess; 0323 deletionSuccess = _view->model()->removeRow(_index.row(), _index.parent()); 0324 Q_ASSERT(deletionSuccess == true); 0325 0326 _view->setCurrentIndex(QModelIndex()); 0327 } 0328 0329 #include "moc_hotkeys_context_menu.cpp"