| 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 | |