1 | /* |
2 | SPDX-FileCopyrightText: 2010-2018 Dominik Haumann <dhaumann@kde.org> |
3 | |
4 | SPDX-License-Identifier: LGPL-2.0-or-later |
5 | */ |
6 | |
7 | #include "katescriptaction.h" |
8 | #include "kateabstractinputmode.h" |
9 | #include "katecmd.h" |
10 | #include "katecmds.h" |
11 | #include "katedocument.h" |
12 | #include "kateglobal.h" |
13 | #include "katepartdebug.h" |
14 | #include "katescriptmanager.h" |
15 | #include "kateview.h" |
16 | #include "kateviewhelpers.h" |
17 | |
18 | #include <QJsonObject> |
19 | #include <QMenu> |
20 | |
21 | #include <KActionCollection> |
22 | #include <KLocalizedString> |
23 | #include <KXMLGUIFactory> |
24 | |
25 | // BEGIN KateScriptAction |
26 | KateScriptAction::KateScriptAction(const QString &cmd, const QJsonObject &action, KTextEditor::ViewPrivate *view) |
27 | : QAction(i18nc("Script command name" , action.value(QStringLiteral("name" )).toString().toUtf8().data()), view) |
28 | , m_view(view) |
29 | , m_command(cmd) |
30 | , m_interactive(action.value(QStringLiteral("interactive" )).toBool()) |
31 | { |
32 | const QString icon = action.value(QStringLiteral("icon" )).toString(); |
33 | if (!icon.isEmpty()) { |
34 | setIcon(QIcon::fromTheme(name: icon)); |
35 | } |
36 | |
37 | connect(sender: this, signal: &KateScriptAction::triggered, context: this, slot: &KateScriptAction::exec); |
38 | } |
39 | |
40 | void KateScriptAction::exec() |
41 | { |
42 | if (m_interactive) { |
43 | m_view->currentInputMode()->launchInteractiveCommand(command: m_command + QLatin1Char(' ')); |
44 | } else { |
45 | KTextEditor::Command *p = KateCmd::self()->queryCommand(cmd: m_command); |
46 | if (p) { |
47 | QString msg; |
48 | p->exec(view: m_view, cmd: m_command, msg); |
49 | } |
50 | } |
51 | } |
52 | // END KateScriptAction |
53 | |
54 | // BEGIN KateScriptActionMenu |
55 | KateScriptActionMenu::(KTextEditor::ViewPrivate *view, const QString &text) |
56 | : KActionMenu(QIcon::fromTheme(QStringLiteral("code-context" )), text, view) |
57 | , m_view(view) |
58 | { |
59 | repopulate(); |
60 | setPopupMode(QToolButton::InstantPopup); |
61 | |
62 | // on script-reload signal, repopulate script menu |
63 | connect(sender: KTextEditor::EditorPrivate::self()->scriptManager(), signal: &KateScriptManager::reloaded, context: this, slot: &KateScriptActionMenu::repopulate); |
64 | } |
65 | |
66 | KateScriptActionMenu::() |
67 | { |
68 | cleanup(); |
69 | } |
70 | |
71 | void KateScriptActionMenu::() |
72 | { |
73 | // delete menus and actions for real |
74 | qDeleteAll(c: m_menus); |
75 | m_menus.clear(); |
76 | |
77 | qDeleteAll(c: m_actions); |
78 | m_actions.clear(); |
79 | } |
80 | |
81 | void KateScriptActionMenu::() |
82 | { |
83 | // if the view is already hooked into the GUI, first remove it |
84 | // now and add it later, so that the changes we do here take effect |
85 | KXMLGUIFactory *viewFactory = m_view->factory(); |
86 | if (viewFactory) { |
87 | viewFactory->removeClient(client: m_view); |
88 | } |
89 | |
90 | // remove existing menu actions |
91 | cleanup(); |
92 | |
93 | // now add all command line script commands |
94 | QHash<QString, QMenu *> ; |
95 | const auto scripts = KTextEditor::EditorPrivate::self()->scriptManager()->commandLineScripts(); |
96 | for (KateCommandLineScript *script : scripts) { |
97 | // traverse actions |
98 | const auto &actions = script->commandHeader().actions(); |
99 | for (const auto &value : actions) { |
100 | // action is a value |
101 | const auto action = value.toObject(); |
102 | |
103 | // get command |
104 | const QString cmd = action.value(QStringLiteral("function" )).toString(); |
105 | |
106 | // show in a category submenu? |
107 | QMenu *m = menu(); |
108 | QString category = action.value(QStringLiteral("category" )).toString(); |
109 | if (!category.isEmpty()) { |
110 | m = menus[category]; |
111 | if (!m) { |
112 | m = menu()->addMenu(i18nc("Script command category" , category.toUtf8().data())); |
113 | menus.insert(key: category, value: m); |
114 | m_menus.append(t: m); |
115 | m_view->actionCollection()->addAction(name: QLatin1String("tools_scripts_" ) + category, action: m->menuAction()); |
116 | } |
117 | } |
118 | |
119 | // create action + add to menu |
120 | QAction *a = new KateScriptAction(cmd, action, m_view); |
121 | m->addAction(action: a); |
122 | m_view->actionCollection()->addAction(name: QLatin1String("tools_scripts_" ) + cmd, action: a); |
123 | const QString shortcut = action.value(QStringLiteral("shortcut" )).toString(); |
124 | if (!shortcut.isEmpty()) { |
125 | // Ctrl-Cmd-Up/Down |
126 | #ifdef Q_OS_MACOS |
127 | if (cmd == u"moveLinesUp" && !shortcut.isEmpty()) { |
128 | m_view->actionCollection()->setDefaultShortcut(a, QKeySequence(Qt::CTRL | Qt::META | Qt::Key_Up)); |
129 | } else if (cmd == u"moveLinesDown" && !shortcut.isEmpty()) { |
130 | m_view->actionCollection()->setDefaultShortcut(a, QKeySequence(Qt::CTRL | Qt::META | Qt::Key_Down)); |
131 | } else { |
132 | m_view->actionCollection()->setDefaultShortcut(a, QKeySequence(shortcut, QKeySequence::PortableText)); |
133 | } |
134 | #else |
135 | m_view->actionCollection()->setDefaultShortcut(action: a, shortcut: QKeySequence(shortcut, QKeySequence::PortableText)); |
136 | #endif |
137 | } |
138 | |
139 | m_actions.append(t: a); |
140 | } |
141 | } |
142 | |
143 | KateCommands::EditingCommands editingCmds; |
144 | QMenu *m = m_view->actionCollection()->action(QStringLiteral("tools_scripts_Editing" ))->menu(); |
145 | for (const auto &cmd : editingCmds.allCommands()) { |
146 | auto a = new QAction(cmd.name); |
147 | connect(sender: a, signal: &QAction::triggered, context: this, slot: [cmd = cmd.cmd, this] { |
148 | KTextEditor::Command *p = KateCmd::self()->queryCommand(cmd); |
149 | if (p) { |
150 | QString msg; |
151 | p->exec(view: m_view, cmd, msg); |
152 | } |
153 | }); |
154 | m->addAction(action: a); |
155 | m_actions.append(t: a); |
156 | m_view->actionCollection()->addAction(name: QLatin1String("tools_scripts_" ) + cmd.cmd, action: a); |
157 | } |
158 | |
159 | // finally add the view to the xml factory again, if it initially was there |
160 | if (viewFactory) { |
161 | viewFactory->addClient(client: m_view); |
162 | } |
163 | } |
164 | |
165 | // END KateScriptActionMenu |
166 | |