File indexing completed on 2024-04-28 15:30:41

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