File indexing completed on 2024-04-21 03:57:38

0001 /*
0002     SPDX-FileCopyrightText: 2010-2018 Dominik Haumann <dhaumann@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "katescriptaction.h"
0008 #include "kateabstractinputmode.h"
0009 #include "katecmd.h"
0010 #include "katedocument.h"
0011 #include "kateglobal.h"
0012 #include "katepartdebug.h"
0013 #include "katescriptmanager.h"
0014 #include "kateview.h"
0015 #include "kateviewhelpers.h"
0016 
0017 #include <QJsonObject>
0018 #include <QMenu>
0019 
0020 #include <KActionCollection>
0021 #include <KLocalizedString>
0022 #include <KXMLGUIFactory>
0023 
0024 // BEGIN KateScriptAction
0025 KateScriptAction::KateScriptAction(const QString &cmd, const QJsonObject &action, KTextEditor::ViewPrivate *view)
0026     : QAction(i18nc("Script command name", action.value(QStringLiteral("name")).toString().toUtf8().data()), view)
0027     , m_view(view)
0028     , m_command(cmd)
0029     , m_interactive(action.value(QStringLiteral("interactive")).toBool())
0030 {
0031     const QString icon = action.value(QStringLiteral("icon")).toString();
0032     if (!icon.isEmpty()) {
0033         setIcon(QIcon::fromTheme(icon));
0034     }
0035 
0036     connect(this, &KateScriptAction::triggered, this, &KateScriptAction::exec);
0037 }
0038 
0039 void KateScriptAction::exec()
0040 {
0041     if (m_interactive) {
0042         m_view->currentInputMode()->launchInteractiveCommand(m_command + QLatin1Char(' '));
0043     } else {
0044         KTextEditor::Command *p = KateCmd::self()->queryCommand(m_command);
0045         if (p) {
0046             QString msg;
0047             p->exec(m_view, m_command, msg);
0048         }
0049     }
0050 }
0051 // END KateScriptAction
0052 
0053 // BEGIN KateScriptActionMenu
0054 KateScriptActionMenu::KateScriptActionMenu(KTextEditor::ViewPrivate *view, const QString &text)
0055     : KActionMenu(QIcon::fromTheme(QStringLiteral("code-context")), text, view)
0056     , m_view(view)
0057 {
0058     repopulate();
0059     setPopupMode(QToolButton::InstantPopup);
0060 
0061     // on script-reload signal, repopulate script menu
0062     connect(KTextEditor::EditorPrivate::self()->scriptManager(), &KateScriptManager::reloaded, this, &KateScriptActionMenu::repopulate);
0063 }
0064 
0065 KateScriptActionMenu::~KateScriptActionMenu()
0066 {
0067     cleanup();
0068 }
0069 
0070 void KateScriptActionMenu::cleanup()
0071 {
0072     // delete menus and actions for real
0073     qDeleteAll(m_menus);
0074     m_menus.clear();
0075 
0076     qDeleteAll(m_actions);
0077     m_actions.clear();
0078 }
0079 
0080 void KateScriptActionMenu::repopulate()
0081 {
0082     // if the view is already hooked into the GUI, first remove it
0083     // now and add it later, so that the changes we do here take effect
0084     KXMLGUIFactory *viewFactory = m_view->factory();
0085     if (viewFactory) {
0086         viewFactory->removeClient(m_view);
0087     }
0088 
0089     // remove existing menu actions
0090     cleanup();
0091 
0092     // now add all command line script commands
0093     QHash<QString, QMenu *> menus;
0094     const auto scripts = KTextEditor::EditorPrivate::self()->scriptManager()->commandLineScripts();
0095     for (KateCommandLineScript *script : scripts) {
0096         // traverse actions
0097         const auto &actions = script->commandHeader().actions();
0098         for (const auto &value : actions) {
0099             // action is a value
0100             const auto action = value.toObject();
0101 
0102             // get command
0103             const QString cmd = action.value(QStringLiteral("function")).toString();
0104 
0105             // show in a category submenu?
0106             QMenu *m = menu();
0107             QString category = action.value(QStringLiteral("category")).toString();
0108             if (!category.isEmpty()) {
0109                 m = menus[category];
0110                 if (!m) {
0111                     m = menu()->addMenu(i18nc("Script command category", category.toUtf8().data()));
0112                     menus.insert(category, m);
0113                     m_menus.append(m);
0114                     m_view->actionCollection()->addAction(QLatin1String("tools_scripts_") + category, m->menuAction());
0115                 }
0116             }
0117 
0118             // create action + add to menu
0119             QAction *a = new KateScriptAction(cmd, action, m_view);
0120             m->addAction(a);
0121             m_view->actionCollection()->addAction(QLatin1String("tools_scripts_") + cmd, a);
0122             const QString shortcut = action.value(QStringLiteral("shortcut")).toString();
0123             if (!shortcut.isEmpty()) {
0124                 m_view->actionCollection()->setDefaultShortcut(a, QKeySequence(shortcut, QKeySequence::PortableText));
0125             }
0126 
0127             m_actions.append(a);
0128         }
0129     }
0130 
0131     // finally add the view to the xml factory again, if it initially was there
0132     if (viewFactory) {
0133         viewFactory->addClient(m_view);
0134     }
0135 }
0136 
0137 // END KateScriptActionMenu