diff --git a/addons/externaltools/externaltoolsplugin.cpp b/addons/externaltools/externaltoolsplugin.cpp index 26f6170aa..29acc310e 100644 --- a/addons/externaltools/externaltoolsplugin.cpp +++ b/addons/externaltools/externaltoolsplugin.cpp @@ -1,153 +1,230 @@ /* This file is part of the KDE project Copyright (C) 2001 Christoph Cullmann Copyright (C) 2002 Joseph Wenninger Copyright (C) 2002 Anders Lund Copyright (C) 2019 Dominik Haumann This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "externaltoolsplugin.h" +#include "kateexternaltool.h" +#include "katemacroexpander.h" +#include "katetoolrunner.h" + #include #include #include #include #include #include #include #include #include #include #include +#include +#include #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON(KateExternalToolsFactory, "externaltoolsplugin.json", registerPlugin();) KateExternalToolsPlugin::KateExternalToolsPlugin(QObject* parent, const QList&) : KTextEditor::Plugin(parent) { - if (KAuthorized::authorizeAction(QStringLiteral("shell_access"))) { - m_command = new KateExternalToolsCommand(this); - } + reload(); } KateExternalToolsPlugin::~KateExternalToolsPlugin() { - if (KAuthorized::authorizeAction(QStringLiteral("shell_access"))) { - if (m_command) { - delete m_command; - } - } + delete m_command; + m_command = nullptr; } QObject* KateExternalToolsPlugin::createView(KTextEditor::MainWindow* mainWindow) { KateExternalToolsPluginView* view = new KateExternalToolsPluginView(mainWindow); connect(view, SIGNAL(destroyed(QObject*)), this, SLOT(viewDestroyed(QObject*))); m_views.append(view); return view; } KateExternalToolsPluginView* KateExternalToolsPlugin::extView(QWidget* widget) { foreach (KateExternalToolsPluginView* view, m_views) { if (view->mainWindow()->window() == widget) return view; } return nullptr; } void KateExternalToolsPlugin::viewDestroyed(QObject* view) { m_views.removeAll(dynamic_cast(view)); } void KateExternalToolsPlugin::reload() { + m_commands.clear(); + + KConfig _config(QStringLiteral("externaltools"), KConfig::NoGlobals, QStandardPaths::ApplicationsLocation); + KConfigGroup config(&_config, "Global"); + const QStringList tools = config.readEntry("tools", QStringList()); + + for (QStringList::const_iterator it = tools.begin(); it != tools.end(); ++it) { + if (*it == QStringLiteral("---")) + continue; + + config = KConfigGroup(&_config, *it); + + KateExternalTool t; + t.load(config); + m_tools.push_back(t); + + // FIXME test for a command name first! + if (t.hasexec && (!t.cmdname.isEmpty())) { + m_commands.push_back(t.cmdname); + } + } + if (KAuthorized::authorizeAction(QStringLiteral("shell_access"))) { -// if (m_command) -// m_command->reload(); + delete m_command; + m_command = new KateExternalToolsCommand(this); } foreach (KateExternalToolsPluginView* view, m_views) { view->rebuildMenu(); } } +QStringList KateExternalToolsPlugin::commands() const +{ + return m_commands; +} + +const KateExternalTool * KateExternalToolsPlugin::toolForCommand(const QString & cmd) const +{ + for (auto & tool : m_tools) { + if (tool.cmdname == cmd) { + return &tool; + } + } + return nullptr; +} + +void KateExternalToolsPlugin::runTool(const KateExternalTool & tool, KTextEditor::View * view) +{ + // expand the macros in command if any, + // and construct a command with an absolute path + auto mw = view->mainWindow(); + + // save documents if requested + if (tool.saveMode == KateExternalTool::SaveMode::CurrentDocument) { + view->document()->save(); + } else if (tool.saveMode == KateExternalTool::SaveMode::AllDocuments) { + foreach (KXMLGUIClient* client, mw->guiFactory()->clients()) { + if (QAction* a = client->actionCollection()->action(QStringLiteral("file_save_all"))) { + a->trigger(); + break; + } + } + } + + // copy tool + auto copy = new KateExternalTool(tool); + + MacroExpander macroExpander(view); + if (!macroExpander.expandMacrosShellQuote(copy->arguments)) { + KMessageBox::sorry(view, i18n("Failed to expand the arguments '%1'.", copy->arguments), i18n("Kate External Tools")); + return; + } + + if (!macroExpander.expandMacrosShellQuote(copy->workingDir)) { + KMessageBox::sorry(view, i18n("Failed to expand the working directory '%1'.", copy->workingDir), i18n("Kate External Tools")); + return; + } + + // FIXME: The tool runner must live as long as the child process is running. + // --> it must be allocated on the heap, and deleted with a ->deleteLater() call. + KateToolRunner runner(copy); + runner.run(); + runner.waitForFinished(); +} + int KateExternalToolsPlugin::configPages() const { return 1; } KTextEditor::ConfigPage* KateExternalToolsPlugin::configPage(int number, QWidget* parent) { if (number == 0) { return new KateExternalToolsConfigWidget(parent, this); } return nullptr; } KateExternalToolsPluginView::KateExternalToolsPluginView(KTextEditor::MainWindow* mainWindow) : QObject(mainWindow) , m_mainWindow(mainWindow) { KXMLGUIClient::setComponentName(QLatin1String("externaltools"), i18n("External Tools")); setXMLFile(QLatin1String("ui.rc")); if (KAuthorized::authorizeAction(QStringLiteral("shell_access"))) { externalTools = new KateExternalToolsMenuAction(i18n("External Tools"), actionCollection(), mainWindow, mainWindow); actionCollection()->addAction(QStringLiteral("tools_external"), externalTools); externalTools->setWhatsThis(i18n("Launch external helper applications")); } mainWindow->guiFactory()->addClient(this); } void KateExternalToolsPluginView::rebuildMenu() { if (externalTools) { KXMLGUIFactory* f = factory(); f->removeClient(this); reloadXML(); externalTools->reload(); qDebug() << "has just returned from externalTools->reload()"; f->addClient(this); } } KateExternalToolsPluginView::~KateExternalToolsPluginView() { m_mainWindow->guiFactory()->removeClient(this); delete externalTools; externalTools = nullptr; } KTextEditor::MainWindow* KateExternalToolsPluginView::mainWindow() const { return m_mainWindow; } #include "externaltoolsplugin.moc" // kate: space-indent on; indent-width 4; replace-tabs on; diff --git a/addons/externaltools/externaltoolsplugin.h b/addons/externaltools/externaltoolsplugin.h index a4a310e47..c6b3b17fe 100644 --- a/addons/externaltools/externaltoolsplugin.h +++ b/addons/externaltools/externaltoolsplugin.h @@ -1,87 +1,96 @@ /* This file is part of the KDE project Copyright (C) 2001 Christoph Cullmann Copyright (C) 2002 Joseph Wenninger Copyright (C) 2002 Anders Lund Copyright (C) 2019 Dominik Haumann This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KTEXTEDITOR_EXTERNALTOOLS_PLUGIN_H #define KTEXTEDITOR_EXTERNALTOOLS_PLUGIN_H -#include #include +#include +#include #include #include "externaltools.h" +#include "kateexternaltool.h" class KateExternalToolsPluginView; +class KateExternalTool; class KateExternalToolsPlugin : public KTextEditor::Plugin { Q_OBJECT public: explicit KateExternalToolsPlugin(QObject* parent = nullptr, const QList& = QList()); virtual ~KateExternalToolsPlugin(); int configPages() const override; KTextEditor::ConfigPage* configPage(int number = 0, QWidget* parent = nullptr) override; - void reload(); - QObject* createView(KTextEditor::MainWindow* mainWindow) override; KateExternalToolsPluginView* extView(QWidget* widget); + void reload(); + QStringList commands() const; + const KateExternalTool * toolForCommand(const QString & cmd) const; + + void runTool(const KateExternalTool & tool, KTextEditor::View * view); + private: QList m_views; + QVector m_tools; + QStringList m_commands; KateExternalToolsCommand* m_command = nullptr; private Q_SLOT: void viewDestroyed(QObject* view); }; class KateExternalToolsPluginView : public QObject, public KXMLGUIClient { Q_OBJECT public: /** * Constructor. */ KateExternalToolsPluginView(KTextEditor::MainWindow* mainWindow); /** * Virtual destructor. */ ~KateExternalToolsPluginView(); /** * Returns the associated mainWindow */ KTextEditor::MainWindow* mainWindow() const; void rebuildMenu(); KateExternalToolsMenuAction* externalTools = nullptr; private: KTextEditor::MainWindow* m_mainWindow; }; #endif // kate: space-indent on; indent-width 4; replace-tabs on; diff --git a/addons/externaltools/kateexternaltoolscommand.cpp b/addons/externaltools/kateexternaltoolscommand.cpp index 0c04f56eb..6b148fbea 100644 --- a/addons/externaltools/kateexternaltoolscommand.cpp +++ b/addons/externaltools/kateexternaltoolscommand.cpp @@ -1,107 +1,49 @@ /* This file is part of the KDE project * * Copyright 2019 Dominik Haumann * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "externaltools.h" #include "externaltoolsplugin.h" -#include -#include -#include -#include - KateExternalToolsCommand::KateExternalToolsCommand(KateExternalToolsPlugin* plugin) - : KTextEditor::Command({/* FIXME */}) + : KTextEditor::Command(plugin->commands()) , m_plugin(plugin) { -// reload(); } -// FIXME -// const QStringList& KateExternalToolsCommand::cmds() -// { -// return m_list; -// } -#if 0 -void KateExternalToolsCommand::reload() -{ - m_list.clear(); - m_map.clear(); - m_name.clear(); - - KConfig _config(QStringLiteral("externaltools"), KConfig::NoGlobals, QStandardPaths::ApplicationsLocation); - KConfigGroup config(&_config, "Global"); - const QStringList tools = config.readEntry("tools", QStringList()); - - for (QStringList::const_iterator it = tools.begin(); it != tools.end(); ++it) { - if (*it == QStringLiteral("---")) - continue; - - config = KConfigGroup(&_config, *it); - - KateExternalTool t; - t.load(config); - // FIXME test for a command name first! - if (t.hasexec && (!t.cmdname.isEmpty())) { - m_list.append(QStringLiteral("exttool-") + t.cmdname); - m_map.insert(QStringLiteral("exttool-") + t.cmdname, t.actionName); - m_name.insert(QStringLiteral("exttool-") + t.cmdname, t.name); - } - } -} -#endif bool KateExternalToolsCommand::exec(KTextEditor::View* view, const QString& cmd, QString& msg, const KTextEditor::Range& range) { Q_UNUSED(msg) Q_UNUSED(range) - auto wv = dynamic_cast(view); - if (!wv) { - // qDebug()<<"KateExternalToolsCommand::exec: Could not get view widget"; - return false; + const QString command = cmd.trimmed(); + const auto tool = m_plugin->toolForCommand(command); + if (tool) { + m_plugin->runTool(*tool, view); + return true; } - - // qDebug()<<"cmd="<(dmw->action("tools_external")); - if (!a) return false;*/ - KateExternalToolsPluginView* extview = m_plugin->extView(wv->window()); - if (!extview) - return false; - if (!extview->externalTools) - return false; - // qDebug()<<"trying to find action"; - QAction* a1 = extview->externalTools->actionCollection()->action(actionName); - if (!a1) - return false; - // qDebug()<<"activating action"; - a1->trigger(); - return true; + return false; } bool KateExternalToolsCommand::help(KTextEditor::View*, const QString&, QString&) { return false; } // kate: space-indent on; indent-width 4; replace-tabs on; diff --git a/addons/externaltools/kateexternaltoolscommand.h b/addons/externaltools/kateexternaltoolscommand.h index b555b2f00..a49011490 100644 --- a/addons/externaltools/kateexternaltoolscommand.h +++ b/addons/externaltools/kateexternaltoolscommand.h @@ -1,51 +1,52 @@ /* This file is part of the KDE project * * Copyright 2019 Dominik Haumann * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KTEXTEDITOR_KATE_EXTERNALTOOLS_COMMAND_H #define KTEXTEDITOR_KATE_EXTERNALTOOLS_COMMAND_H #include class KateExternalToolsPlugin; +class KateExternalTool; /** * Helper class that registers and executes the respective external tool. */ class KateExternalToolsCommand : public KTextEditor::Command { public: KateExternalToolsCommand(KateExternalToolsPlugin* plugin); virtual ~KateExternalToolsCommand() = default; public: // const QStringList& cmds() override; // FIXME bool exec(KTextEditor::View* view, const QString& cmd, QString& msg, const KTextEditor::Range& range = KTextEditor::Range::invalid()) override; bool help(KTextEditor::View* view, const QString& cmd, QString& msg) override; private: - QStringList m_list; - QHash m_map; - QHash m_name; + void runTool(KateExternalTool & tool, KTextEditor::View * view); + +private: KateExternalToolsPlugin* m_plugin; }; #endif // KTEXTEDITOR_KATE_EXTERNALTOOLS_COMMAND_H // kate: space-indent on; indent-width 4; replace-tabs on;