diff --git a/addons/CMakeLists.txt b/addons/CMakeLists.txt
--- a/addons/CMakeLists.txt
+++ b/addons/CMakeLists.txt
@@ -49,6 +49,9 @@
# pipe text through some external command
ecm_optional_add_subdirectory (textfilter)
+# external tools
+ecm_optional_add_subdirectory (externaltools)
+
# Rust complection plugin
ecm_optional_add_subdirectory (rustcompletion)
diff --git a/addons/externaltools/CMakeLists.txt b/addons/externaltools/CMakeLists.txt
new file mode 100644
--- /dev/null
+++ b/addons/externaltools/CMakeLists.txt
@@ -0,0 +1,32 @@
+project(externaltoolsplugin)
+add_definitions(-DTRANSLATION_DOMAIN=\"externaltoolsplugin\")
+
+include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
+
+set(externaltoolsplugin_PART_SRCS
+ externaltoolsplugin.cpp
+ externaltools.cpp
+)
+
+# resource for ui file and stuff
+qt5_add_resources(externaltoolsplugin_PART_SRCS plugin.qrc)
+
+set(externaltoolsplugin_PART_UI
+ configwidget.ui
+ tooldialog.ui
+)
+ki18n_wrap_ui(externaltoolsplugin_PART_SRCS ${externaltoolsplugin_PART_UI} )
+add_library(externaltoolsplugin MODULE ${externaltoolsplugin_PART_SRCS})
+
+# we compile in the .desktop file
+kcoreaddons_desktop_to_json (externaltoolsplugin externaltoolsplugin.desktop)
+
+target_link_libraries(externaltoolsplugin
+ KF5::CoreAddons
+ KF5::IconThemes
+ KF5::TextEditor
+ KF5::I18n
+)
+
+########### install files ###############
+install(TARGETS externaltoolsplugin DESTINATION ${PLUGIN_INSTALL_DIR}/ktexteditor )
diff --git a/addons/externaltools/Messages.sh b/addons/externaltools/Messages.sh
new file mode 100644
--- /dev/null
+++ b/addons/externaltools/Messages.sh
@@ -0,0 +1,3 @@
+#! /bin/sh
+$EXTRACTRC *.rc *.ui >> rc.cpp
+$XGETTEXT *.cpp -o $podir/externaltoolsplugin.pot
diff --git a/addons/externaltools/configwidget.ui b/addons/externaltools/configwidget.ui
new file mode 100644
--- /dev/null
+++ b/addons/externaltools/configwidget.ui
@@ -0,0 +1,118 @@
+
+
+ ExternalToolsConfigWidget
+
+
+
+ 0
+ 0
+ 504
+ 296
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
-
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 98
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 17
+ 108
+
+
+
+
+ -
+
+
-
+
+
+ New...
+
+
+
+ -
+
+
+ Edit...
+
+
+
+ -
+
+
+ Remove
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Insert Separator
+
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ This list shows all the configured tools, represented by their menu text.
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/externaltools/externaltools b/addons/externaltools/externaltools
new file mode 100644
--- /dev/null
+++ b/addons/externaltools/externaltools
@@ -0,0 +1,23 @@
+[Global]
+tools=externaltool_RunScript,---,externaltool_GoogleSelection
+version=1
+
+[externaltool_GoogleSelection]
+acname=externaltool_GoogleSelection
+cmdname=google-selection
+command=[ -n "%selection" ] && kfmclient openURL "gg:%selection"
+executable=kfmclient
+icon=globe
+mimetypes=
+name=Google Selection
+save=0
+
+[externaltool_RunScript]
+acname=externaltool_RunScript
+cmdname=runscript
+command=konsole -e sh -c "cd %directory && pwd && chmod -vc a+x %filename && ./%filename ; echo Press any key to continue. && read -n 1"
+executable=konsole
+icon=run
+mimetypes=
+name=Run Script
+save=1
diff --git a/addons/externaltools/externaltools.h b/addons/externaltools/externaltools.h
new file mode 100644
--- /dev/null
+++ b/addons/externaltools/externaltools.h
@@ -0,0 +1,248 @@
+/*
+ This file is part of the Kate text editor of the KDE project.
+ It describes a "external tools" action for kate and provides a dialog
+ page to configure that.
+
+ 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.
+
+ ---
+ Copyright (C) 2004 Anders Lund
+ Copyright (C) 2019 Dominik Haumann
+*/
+
+#ifndef KTEXTEDITOR_EXTERNALTOOLS_H
+#define KTEXTEDITOR_EXTERNALTOOLS_H
+
+#include "ui_configwidget.h"
+#include "ui_tooldialog.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+class KateExternalToolsPlugin;
+
+/**
+ * The external tools action
+ * This action creates a menu, in which each item will launch a process
+ * with the provided arguments, which may include the following macros:
+ * - %URLS: the URLs of all open documents.
+ * - %URL: The URL of the active document.
+ * - %filedir: The directory of the current document, if that is a local file.
+ * - %selection: The selection of the active document.
+ * - %text: The text of the active document.
+ * - %line: The line number of the cursor in the active view.
+ * - %column: The column of the cursor in the active view.
+ *
+ * Each item has the following properties:
+ * - Name: The friendly text for the menu
+ * - Exec: The command to execute, including arguments.
+ * - TryExec: the name of the executable, if not available, the
+ * item will not be displayed.
+ * - MimeTypes: An optional list of mimetypes. The item will be disabled or
+ * hidden if the current file is not of one of the indicated types.
+ *
+ */
+class KateExternalToolsMenuAction : public KActionMenu
+{
+ friend class KateExternalToolAction;
+
+ Q_OBJECT
+public:
+ KateExternalToolsMenuAction(const QString& text, class KActionCollection* collection, QObject* parent,
+ class KTextEditor::MainWindow* mw = nullptr);
+ virtual ~KateExternalToolsMenuAction();
+
+ /**
+ * This will load all the configured services.
+ */
+ void reload();
+
+ class KActionCollection* actionCollection() { return m_actionCollection; }
+
+private Q_SLOTS:
+ void slotViewChanged(KTextEditor::View* view);
+
+private:
+ class KActionCollection* m_actionCollection;
+ KTextEditor::MainWindow* mainwindow; // for the actions to access view/doc managers
+};
+
+/**
+ * This Action contains a KateExternalTool
+ */
+class KateExternalToolAction : public QAction, public KWordMacroExpander
+{
+ Q_OBJECT
+public:
+ KateExternalToolAction(QObject* parent, class KateExternalTool* t);
+ ~KateExternalToolAction();
+
+protected:
+ bool expandMacro(const QString& str, QStringList& ret) override;
+
+private Q_SLOTS:
+ void slotRun();
+
+public:
+ class KateExternalTool* tool;
+};
+
+/**
+ * This class defines a single external tool.
+ */
+class KateExternalTool
+{
+public:
+ explicit KateExternalTool(const QString& name = QString(), const QString& command = QString(),
+ const QString& icon = QString(), const QString& executable = QString(),
+ const QStringList& mimetypes = QStringList(), const QString& acname = QString(),
+ const QString& cmdname = QString(), int save = 0);
+ ~KateExternalTool() {}
+
+ QString name; ///< The name used in the menu.
+ QString executable; ///< The name or path of the executable.
+ QString arguments; ///< The command line arguments.
+ QString command; ///< The command to execute.
+ QString icon; ///< the icon to use in the menu.
+ QStringList mimetypes; ///< Optional list of mimetypes for which this action is valid.
+ bool hasexec; ///< This is set by the constructor by calling checkExec(), if a
+ ///< value is present.
+ QString acname; ///< The name for the action. This is generated first time the
+ ///< action is is created.
+ QString cmdname; ///< The name for the commandline.
+ int save; ///< We can save documents prior to activating the tool command: 0 =
+ ///< nothing, 1 = current document, 2 = all documents.
+
+ /**
+ * @return true if mimetypes is empty, or the @p mimetype matches.
+ */
+ bool valid(const QString& mimetype) const;
+ /**
+ * @return true if "executable" exists and has the executable bit set, or is
+ * empty.
+ * This is run at least once, and the tool is disabled if it fails.
+ */
+ bool checkExec();
+
+private:
+ QString m_exec; ///< The fully qualified path of the executable.
+};
+
+/**
+ * The config widget.
+ * The config widget allows the user to view a list of services of the type
+ * "Kate/ExternalTool" and add, remove or edit them.
+ */
+class KateExternalToolsConfigWidget : public KTextEditor::ConfigPage, public Ui::ExternalToolsConfigWidget
+{
+ Q_OBJECT
+public:
+ KateExternalToolsConfigWidget(QWidget* parent, KateExternalToolsPlugin* plugin);
+ virtual ~KateExternalToolsConfigWidget();
+
+ QString name() const override;
+ QString fullName() const override;
+ QIcon icon() const override;
+
+public Q_SLOTS:
+ void apply() override;
+ void reset() override;
+ void defaults() override { reset(); } // double sigh
+
+private Q_SLOTS:
+ void slotNew();
+ void slotEdit();
+ void slotRemove();
+ void slotInsertSeparator();
+
+ void slotMoveUp();
+ void slotMoveDown();
+
+ void slotSelectionChanged();
+
+private:
+ QPixmap blankIcon();
+
+ QStringList m_removed;
+
+ class KConfig* config;
+
+ bool m_changed;
+ KateExternalToolsPlugin* m_plugin;
+};
+
+/**
+ * A Singleton class for invoking external tools with the view command line
+ */
+class KateExternalToolsCommand : public KTextEditor::Command
+{
+public:
+ KateExternalToolsCommand(KateExternalToolsPlugin* plugin);
+ virtual ~KateExternalToolsCommand() {}
+ void reload();
+
+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;
+ KateExternalToolsPlugin* m_plugin;
+};
+
+/**
+ * A Dialog to edit a single KateExternalTool object
+ */
+class KateExternalToolServiceEditor : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit KateExternalToolServiceEditor(KateExternalTool* tool = nullptr, QWidget* parent = nullptr);
+
+private Q_SLOTS:
+ /**
+ * Run when the OK button is clicked, to ensure critical values are provided.
+ */
+ void slotOKClicked();
+
+ /**
+ * show a mimetype chooser dialog
+ */
+ void showMTDlg();
+
+public:
+ Ui::ToolDialog * ui;
+private:
+ KateExternalTool* tool;
+};
+
+#endif // KTEXTEDITOR_EXTERNALTOOLS_H
+
+// kate: space-indent on; indent-width 4; replace-tabs on;
diff --git a/addons/externaltools/externaltools.cpp b/addons/externaltools/externaltools.cpp
new file mode 100644
--- /dev/null
+++ b/addons/externaltools/externaltools.cpp
@@ -0,0 +1,720 @@
+/*
+ This file is part of the Kate text editor of the KDE project.
+
+ 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.
+
+ ---
+ Copyright (C) 2004, Anders Lund
+ Copyright (C) 2019 Dominik Haumann
+*/
+// TODO
+// Icons
+// Direct shortcut setting
+#include "externaltools.h"
+#include "externaltoolsplugin.h"
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+// BEGIN KateExternalTool
+KateExternalTool::KateExternalTool(const QString& name, const QString& command, const QString& icon,
+ const QString& executable, const QStringList& mimetypes, const QString& acname,
+ const QString& cmdname, int save)
+ : name(name)
+ , command(command)
+ , icon(icon)
+ , executable(executable)
+ , mimetypes(mimetypes)
+ , acname(acname)
+ , cmdname(cmdname)
+ , save(save)
+{
+ // if ( ! executable.isEmpty() )
+ hasexec = checkExec();
+}
+
+bool KateExternalTool::checkExec()
+{
+ m_exec = QStandardPaths::findExecutable(executable);
+ return !m_exec.isEmpty();
+}
+
+bool KateExternalTool::valid(const QString& mt) const
+{
+ return mimetypes.isEmpty() || mimetypes.contains(mt);
+}
+// END KateExternalTool
+
+// BEGIN KateExternalToolsCommand
+KateExternalToolsCommand::KateExternalToolsCommand(KateExternalToolsPlugin* plugin)
+ : KTextEditor::Command({/* FIXME */})
+ , m_plugin(plugin)
+{
+ reload();
+}
+
+// FIXME
+// const QStringList& KateExternalToolsCommand::cmds()
+// {
+// return m_list;
+// }
+
+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
+ = KateExternalTool(config.readEntry(QStringLiteral("name"), ""), config.readEntry("command", ""),
+ config.readEntry(QStringLiteral("icon"), ""), config.readEntry("executable", ""),
+ config.readEntry(QStringLiteral("mimetypes"), QStringList()),
+ config.readEntry(QStringLiteral("acname"), ""), config.readEntry("cmdname", ""));
+ // 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.acname);
+ m_name.insert(QStringLiteral("exttool-") + t.cmdname, t.name);
+ }
+ }
+}
+
+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;
+ }
+
+ // 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;
+}
+
+bool KateExternalToolsCommand::help(KTextEditor::View*, const QString&, QString&)
+{
+ return false;
+}
+// END KateExternalToolsCommand
+
+// BEGIN KateExternalToolAction
+KateExternalToolAction::KateExternalToolAction(QObject* parent, KateExternalTool* t)
+ : QAction(QIcon::fromTheme(t->icon), t->name, parent)
+ , tool(t)
+{
+ setText(t->name);
+ if (!t->icon.isEmpty())
+ setIcon(QIcon::fromTheme(t->icon));
+
+ connect(this, SIGNAL(triggered(bool)), SLOT(slotRun()));
+}
+
+bool KateExternalToolAction::expandMacro(const QString& str, QStringList& ret)
+{
+ KTextEditor::MainWindow* mw = qobject_cast(parent()->parent());
+ Q_ASSERT(mw);
+
+ KTextEditor::View* view = mw->activeView();
+ if (!view)
+ return false;
+
+ KTextEditor::Document* doc = view->document();
+ QUrl url = doc->url();
+
+ if (str == QStringLiteral("URL"))
+ ret += url.url();
+ else if (str == QStringLiteral("directory")) // directory of current doc
+ ret += url.toString(QUrl::RemoveScheme | QUrl::RemoveFilename);
+ else if (str == QStringLiteral("filename"))
+ ret += url.fileName();
+ else if (str == QStringLiteral("line")) // cursor line of current doc
+ ret += QString::number(view->cursorPosition().line());
+ else if (str == QStringLiteral("col")) // cursor col of current doc
+ ret += QString::number(view->cursorPosition().column());
+ else if (str == QStringLiteral("selection")) // selection of current doc if any
+ ret += view->selectionText();
+ else if (str == QStringLiteral("text")) // text of current doc
+ ret += doc->text();
+ else if (str == QStringLiteral("URLs")) {
+ foreach (KTextEditor::Document* it, KTextEditor::Editor::instance()->application()->documents())
+ if (!it->url().isEmpty())
+ ret += it->url().url();
+ } else
+ return false;
+
+ return true;
+}
+
+KateExternalToolAction::~KateExternalToolAction()
+{
+ delete (tool);
+}
+
+void KateExternalToolAction::slotRun()
+{
+ // expand the macros in command if any,
+ // and construct a command with an absolute path
+ QString cmd = tool->command;
+
+ auto mw = qobject_cast(parent()->parent());
+ if (!expandMacrosShellQuote(cmd)) {
+ KMessageBox::sorry(mw->window(), i18n("Failed to expand the command '%1'.", cmd), i18n("Kate External Tools"));
+ return;
+ }
+ qDebug() << "externaltools: Running command: " << cmd;
+
+ // save documents if requested
+ if (tool->save == 1)
+ mw->activeView()->document()->save();
+ else if (tool->save == 2) {
+ foreach (KXMLGUIClient* client, mw->guiFactory()->clients()) {
+ if (QAction* a = client->actionCollection()->action(QStringLiteral("file_save_all"))) {
+ a->trigger();
+ break;
+ }
+ }
+ }
+
+ KRun::runCommand(cmd, tool->executable, tool->icon, mw->window());
+}
+// END KateExternalToolAction
+
+// BEGIN KateExternalToolsMenuAction
+KateExternalToolsMenuAction::KateExternalToolsMenuAction(const QString& text, KActionCollection* collection,
+ QObject* parent, KTextEditor::MainWindow* mw)
+ : KActionMenu(text, parent)
+ , mainwindow(mw)
+{
+
+ m_actionCollection = collection;
+
+ // connect to view changed...
+ connect(mw, &KTextEditor::MainWindow::viewChanged, this, &KateExternalToolsMenuAction::slotViewChanged);
+
+ reload();
+}
+
+KateExternalToolsMenuAction::~KateExternalToolsMenuAction()
+{
+ // kDebug() << "deleted KateExternalToolsMenuAction";
+}
+
+void KateExternalToolsMenuAction::reload()
+{
+ bool needs_readd = (m_actionCollection->takeAction(this) != nullptr);
+ m_actionCollection->clear();
+ if (needs_readd)
+ m_actionCollection->addAction(QStringLiteral("tools_external"), this);
+ menu()->clear();
+
+ // load all the tools, and create a action for each of them
+ KSharedConfig::Ptr pConfig = KSharedConfig::openConfig(QStringLiteral("externaltools"), KConfig::NoGlobals,
+ QStandardPaths::ApplicationsLocation);
+ KConfigGroup config(pConfig, "Global");
+ QStringList tools = config.readEntry("tools", QStringList());
+
+ // if there are tools that are present but not explicitly removed,
+ // add them to the end of the list
+ pConfig->setReadDefaults(true);
+ QStringList dtools = config.readEntry("tools", QStringList());
+ int gver = config.readEntry("version", 1);
+ pConfig->setReadDefaults(false);
+
+ int ver = config.readEntry("version", 0);
+ if (ver <= gver) {
+ QStringList removed = config.readEntry("removed", QStringList());
+ bool sepadded = false;
+ for (QStringList::iterator itg = dtools.begin(); itg != dtools.end(); ++itg) {
+ if (!tools.contains(*itg) && !removed.contains(*itg)) {
+ if (!sepadded) {
+ tools << QStringLiteral("---");
+ sepadded = true;
+ }
+ tools << *itg;
+ }
+ }
+
+ config.writeEntry("tools", tools);
+ config.sync();
+ config.writeEntry("version", gver);
+ }
+
+ for (QStringList::const_iterator it = tools.constBegin(); it != tools.constEnd(); ++it) {
+ if (*it == QStringLiteral("---")) {
+ menu()->addSeparator();
+ // a separator
+ continue;
+ }
+
+ config = KConfigGroup(pConfig, *it);
+
+ KateExternalTool* t = new KateExternalTool(
+ config.readEntry("name", ""), config.readEntry("command", ""), config.readEntry("icon", ""),
+ config.readEntry("executable", ""), config.readEntry("mimetypes", QStringList()),
+ config.readEntry("acname", ""), config.readEntry("cmdname", ""), config.readEntry("save", 0));
+
+ if (t->hasexec) {
+ QAction* a = new KateExternalToolAction(this, t);
+ m_actionCollection->addAction(t->acname, a);
+ addAction(a);
+ } else
+ delete t;
+ }
+
+ config = KConfigGroup(pConfig, "Shortcuts");
+ m_actionCollection->readSettings(&config);
+ slotViewChanged(mainwindow->activeView());
+}
+
+void KateExternalToolsMenuAction::slotViewChanged(KTextEditor::View* view)
+{
+ // no active view, oh oh
+ if (!view) {
+ return;
+ }
+
+ // try to enable/disable to match current mime type
+ KTextEditor::Document* doc = view->document();
+ if (doc) {
+ const QString mimeType = doc->mimeType();
+ foreach (QAction* kaction, m_actionCollection->actions()) {
+ KateExternalToolAction* action = dynamic_cast(kaction);
+ if (action) {
+ const QStringList l = action->tool->mimetypes;
+ const bool b = (!l.count() || l.contains(mimeType));
+ action->setEnabled(b);
+ }
+ }
+ }
+}
+// END KateExternalToolsMenuAction
+
+// BEGIN ToolItem
+/**
+ * This is a QListBoxItem, that has a KateExternalTool. The text is the Name
+ * of the tool.
+ */
+class ToolItem : public QListWidgetItem
+{
+public:
+ ToolItem(QListWidget* lb, const QPixmap& icon, KateExternalTool* tool)
+ : QListWidgetItem(icon, tool->name, lb)
+ , tool(tool)
+ {
+ }
+
+ ~ToolItem() {}
+
+ KateExternalTool* tool;
+};
+// END ToolItem
+
+// BEGIN KateExternalToolServiceEditor
+KateExternalToolServiceEditor::KateExternalToolServiceEditor(KateExternalTool* tool, QWidget* parent)
+ : QDialog(parent)
+ , tool(tool)
+{
+ setWindowTitle(i18n("Edit External Tool"));
+
+ ui = new Ui::ToolDialog();
+ ui->setupUi(this);
+ ui->btnIcon->setIconSize(KIconLoader::SizeSmall);
+
+ connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &KateExternalToolServiceEditor::slotOKClicked);
+ connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
+ connect(ui->btnMimeType, &QToolButton::clicked, this, &KateExternalToolServiceEditor::showMTDlg);
+
+ if (tool) {
+ ui->edtName->setText(tool->name);
+ if (!tool->icon.isEmpty())
+ ui->btnIcon->setIcon(tool->icon);
+
+ ui->edtExecutable->setText(tool->executable);
+ ui->edtInput->setText(tool->command);
+ ui->edtMimeType->setText(tool->mimetypes.join(QStringLiteral("; ")));
+ ui->cmbSave->setCurrentIndex(tool->save);
+ ui->edtCommand->setText(tool->cmdname);
+ }
+}
+
+void KateExternalToolServiceEditor::slotOKClicked()
+{
+ if (ui->edtName->text().isEmpty() || ui->edtInput->document()->isEmpty()) {
+ QMessageBox::information(this, i18n("External Tool"), i18n("You must specify at least a name and a command"));
+ return;
+ }
+ accept();
+}
+
+void KateExternalToolServiceEditor::showMTDlg()
+{
+ QString text = i18n("Select the MimeTypes for which to enable this tool.");
+ QStringList list = ui->edtMimeType->text().split(QRegExp(QStringLiteral("\\s*;\\s*")), QString::SkipEmptyParts);
+ KMimeTypeChooserDialog d(i18n("Select Mime Types"), text, list, QStringLiteral("text"), this);
+ if (d.exec() == QDialog::Accepted) {
+ ui->edtMimeType->setText(d.chooser()->mimeTypes().join(QStringLiteral(";")));
+ }
+}
+// END KateExternalToolServiceEditor
+
+// BEGIN KateExternalToolsConfigWidget
+KateExternalToolsConfigWidget::KateExternalToolsConfigWidget(QWidget* parent, KateExternalToolsPlugin* plugin)
+ : KTextEditor::ConfigPage(parent)
+ , m_changed(false)
+ , m_plugin(plugin)
+{
+ setupUi(this);
+
+ btnMoveUp->setIcon(QIcon::fromTheme(QStringLiteral("go-up")));
+ btnMoveDown->setIcon(QIcon::fromTheme(QStringLiteral("go-down")));
+
+ connect(lbTools, &QListWidget::itemSelectionChanged, this, &KateExternalToolsConfigWidget::slotSelectionChanged);
+ connect(lbTools, &QListWidget::itemDoubleClicked, this, &KateExternalToolsConfigWidget::slotEdit);
+ connect(btnNew, &QPushButton::clicked, this, &KateExternalToolsConfigWidget::slotNew);
+ connect(btnRemove, &QPushButton::clicked, this, &KateExternalToolsConfigWidget::slotRemove);
+ connect(btnEdit, &QPushButton::clicked, this, &KateExternalToolsConfigWidget::slotEdit);
+ connect(btnSeparator, &QPushButton::clicked, this, &KateExternalToolsConfigWidget::slotInsertSeparator);
+ connect(btnMoveUp, &QPushButton::clicked, this, &KateExternalToolsConfigWidget::slotMoveUp);
+ connect(btnMoveDown, &QPushButton::clicked, this, &KateExternalToolsConfigWidget::slotMoveDown);
+
+ config = new KConfig(QStringLiteral("externaltools"), KConfig::NoGlobals, QStandardPaths::ApplicationsLocation);
+ reset();
+ slotSelectionChanged();
+}
+
+KateExternalToolsConfigWidget::~KateExternalToolsConfigWidget()
+{
+ delete config;
+}
+
+QString KateExternalToolsConfigWidget::name() const
+{
+ return i18n("External Tools");
+}
+
+QString KateExternalToolsConfigWidget::fullName() const
+{
+ return i18n("External Tools");
+}
+
+QIcon KateExternalToolsConfigWidget::icon() const
+{
+ return QIcon();
+}
+
+void KateExternalToolsConfigWidget::reset()
+{
+ // m_tools.clear();
+ lbTools->clear();
+
+ // load the files from a KConfig
+ const QStringList tools = config->group("Global").readEntry("tools", QStringList());
+
+ for (QStringList::const_iterator it = tools.begin(); it != tools.end(); ++it) {
+ if (*it == QStringLiteral("---")) {
+ new QListWidgetItem(QStringLiteral("---"), lbTools);
+ } else {
+ KConfigGroup cg(config, *it);
+
+ KateExternalTool* t
+ = new KateExternalTool(cg.readEntry("name", ""), cg.readEntry("command", ""), cg.readEntry("icon", ""),
+ cg.readEntry("executable", ""), cg.readEntry("mimetypes", QStringList()),
+ cg.readEntry("acname"), cg.readEntry("cmdname"), cg.readEntry("save", 0));
+
+ if (t->hasexec) // we only show tools that are also in the menu.
+ new ToolItem(lbTools, t->icon.isEmpty() ? blankIcon() : SmallIcon(t->icon), t);
+ else
+ delete t;
+ }
+ }
+ m_changed = false;
+}
+
+QPixmap KateExternalToolsConfigWidget::blankIcon()
+{
+ QPixmap pm(KIconLoader::SizeSmall, KIconLoader::SizeSmall);
+ pm.fill();
+ pm.setMask(pm.createHeuristicMask());
+ return pm;
+}
+
+void KateExternalToolsConfigWidget::apply()
+{
+ if (!m_changed)
+ return;
+ m_changed = false;
+
+ // save a new list
+ // save each item
+ QStringList tools;
+ for (int i = 0; i < lbTools->count(); i++) {
+ if (lbTools->item(i)->text() == QStringLiteral("---")) {
+ tools << QStringLiteral("---");
+ continue;
+ }
+ KateExternalTool* t = static_cast(lbTools->item(i))->tool;
+ // qDebug()<<"adding tool: "<name;
+ tools << t->acname;
+
+ KConfigGroup cg(config, t->acname);
+
+ cg.writeEntry("name", t->name);
+ cg.writeEntry("command", t->command);
+ cg.writeEntry("icon", t->icon);
+ cg.writeEntry("executable", t->executable);
+ cg.writeEntry("mimetypes", t->mimetypes);
+ cg.writeEntry("acname", t->acname);
+ cg.writeEntry("cmdname", t->cmdname);
+ cg.writeEntry("save", t->save);
+ }
+
+ config->group("Global").writeEntry("tools", tools);
+
+ // if any tools was removed, try to delete their groups, and
+ // add the group names to the list of removed items.
+ if (m_removed.count()) {
+ for (QStringList::iterator it = m_removed.begin(); it != m_removed.end(); ++it) {
+ if (config->hasGroup(*it))
+ config->deleteGroup(*it);
+ }
+ QStringList removed = config->group("Global").readEntry("removed", QStringList());
+ removed += m_removed;
+
+ // clean up the list of removed items, so that it does not contain
+ // non-existing groups (we can't remove groups from a non-owned global file).
+ config->sync();
+ QStringList::iterator it1 = removed.begin();
+ while (it1 != removed.end()) {
+ if (!config->hasGroup(*it1))
+ it1 = removed.erase(it1);
+ else
+ ++it1;
+ }
+ config->group("Global").writeEntry("removed", removed);
+ }
+
+ config->sync();
+ m_plugin->reload();
+}
+
+void KateExternalToolsConfigWidget::slotSelectionChanged()
+{
+ // update button state
+ bool hs = lbTools->currentItem() != nullptr;
+ btnEdit->setEnabled(hs && dynamic_cast(lbTools->currentItem()));
+ btnRemove->setEnabled(hs);
+ btnMoveUp->setEnabled((lbTools->currentRow() > 0) && hs);
+ btnMoveDown->setEnabled((lbTools->currentRow() < (int)lbTools->count() - 1) && hs);
+}
+
+void KateExternalToolsConfigWidget::slotNew()
+{
+ // display a editor, and if it is OK'd, create a new tool and
+ // create a listbox item for it
+ KateExternalToolServiceEditor editor(nullptr, this);
+
+ if (editor.exec() == QDialog::Accepted) {
+ KateExternalTool* t = new KateExternalTool(
+ editor.ui->edtName->text(), editor.ui->edtInput->toPlainText(), editor.ui->btnIcon->icon(), editor.ui->edtExecutable->text(),
+ editor.ui->edtMimeType->text().split(QRegExp(QStringLiteral("\\s*;\\s*")), QString::SkipEmptyParts));
+
+ // This is sticky, it does not change again, so that shortcuts sticks
+ // TODO check for dups
+ t->acname = QStringLiteral("externaltool_") + QString(t->name).remove(QRegExp(QStringLiteral("\\W+")));
+
+ new ToolItem(lbTools, t->icon.isEmpty() ? blankIcon() : SmallIcon(t->icon), t);
+
+ emit changed();
+ m_changed = true;
+ }
+}
+
+void KateExternalToolsConfigWidget::slotRemove()
+{
+ // add the tool action name to a list of removed items,
+ // remove the current listbox item
+ if (lbTools->currentRow() > -1) {
+ ToolItem* i = dynamic_cast(lbTools->currentItem());
+ if (i)
+ m_removed << i->tool->acname;
+
+ delete lbTools->takeItem(lbTools->currentRow());
+ emit changed();
+ m_changed = true;
+ }
+}
+
+void KateExternalToolsConfigWidget::slotEdit()
+{
+ if (!dynamic_cast(lbTools->currentItem()))
+ return;
+ // show the item in an editor
+ KateExternalTool* t = static_cast(lbTools->currentItem())->tool;
+ KateExternalToolServiceEditor editor(t, this);
+ editor.resize(config->group("Editor").readEntry("Size", QSize()));
+ if (editor.exec() /*== KDialog::Ok*/) {
+
+ bool elementChanged = ((editor.ui->btnIcon->icon() != t->icon) || (editor.ui->edtName->text() != t->name));
+
+ t->name = editor.ui->edtName->text();
+ t->cmdname = editor.ui->edtCommand->text();
+ t->command = editor.ui->edtInput->toPlainText();
+ t->icon = editor.ui->btnIcon->icon();
+ t->executable = editor.ui->edtExecutable->text();
+ t->mimetypes = editor.ui->edtMimeType->text().split(QRegExp(QStringLiteral("\\s*;\\s*")), QString::SkipEmptyParts);
+ t->save = editor.ui->cmbSave->currentIndex();
+
+ // if the icon has changed or name changed, I have to renew the listbox item :S
+ if (elementChanged) {
+ int idx = lbTools->row(lbTools->currentItem());
+ delete lbTools->takeItem(idx);
+ lbTools->insertItem(idx, new ToolItem(nullptr, t->icon.isEmpty() ? blankIcon() : SmallIcon(t->icon), t));
+ }
+
+ emit changed();
+ m_changed = true;
+ }
+
+ config->group("Editor").writeEntry("Size", editor.size());
+ config->sync();
+}
+
+void KateExternalToolsConfigWidget::slotInsertSeparator()
+{
+ lbTools->insertItem(lbTools->currentRow() + 1, QStringLiteral("---"));
+ emit changed();
+ m_changed = true;
+}
+
+void KateExternalToolsConfigWidget::slotMoveUp()
+{
+ // move the current item in the listbox upwards if possible
+ QListWidgetItem* item = lbTools->currentItem();
+ if (!item)
+ return;
+
+ int idx = lbTools->row(item);
+
+ if (idx < 1)
+ return;
+
+ if (dynamic_cast(item)) {
+ KateExternalTool* tool = static_cast(item)->tool;
+ delete lbTools->takeItem(idx);
+ lbTools->insertItem(idx - 1,
+ new ToolItem(nullptr, tool->icon.isEmpty() ? blankIcon() : SmallIcon(tool->icon), tool));
+ } else // a separator!
+ {
+ delete lbTools->takeItem(idx);
+ lbTools->insertItem(idx - 1, new QListWidgetItem(QStringLiteral("---")));
+ }
+
+ lbTools->setCurrentRow(idx - 1);
+ slotSelectionChanged();
+ emit changed();
+ m_changed = true;
+}
+
+void KateExternalToolsConfigWidget::slotMoveDown()
+{
+ // move the current item in the listbox downwards if possible
+ QListWidgetItem* item = lbTools->currentItem();
+ if (!item)
+ return;
+
+ int idx = lbTools->row(item);
+
+ if (idx > lbTools->count() - 1)
+ return;
+
+ if (dynamic_cast(item)) {
+ KateExternalTool* tool = static_cast(item)->tool;
+ delete lbTools->takeItem(idx);
+ lbTools->insertItem(idx + 1,
+ new ToolItem(nullptr, tool->icon.isEmpty() ? blankIcon() : SmallIcon(tool->icon), tool));
+ } else // a separator!
+ {
+ delete lbTools->takeItem(idx);
+ lbTools->insertItem(idx + 1, new QListWidgetItem(QStringLiteral("---")));
+ }
+
+ lbTools->setCurrentRow(idx + 1);
+ slotSelectionChanged();
+ emit changed();
+ m_changed = true;
+}
+// END KateExternalToolsConfigWidget
+// kate: space-indent on; indent-width 4; replace-tabs on;
diff --git a/addons/externaltools/externaltoolsplugin.h b/addons/externaltools/externaltoolsplugin.h
new file mode 100644
--- /dev/null
+++ b/addons/externaltools/externaltoolsplugin.h
@@ -0,0 +1,87 @@
+/* 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 "externaltools.h"
+
+class KateExternalToolsPluginView;
+
+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);
+
+private:
+ QList m_views;
+ 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/externaltoolsplugin.cpp b/addons/externaltools/externaltoolsplugin.cpp
new file mode 100644
--- /dev/null
+++ b/addons/externaltools/externaltoolsplugin.cpp
@@ -0,0 +1,153 @@
+/* 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
+#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);
+ }
+}
+
+KateExternalToolsPlugin::~KateExternalToolsPlugin()
+{
+ if (KAuthorized::authorizeAction(QStringLiteral("shell_access"))) {
+ if (m_command) {
+ delete m_command;
+ }
+ }
+}
+
+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()
+{
+ if (KAuthorized::authorizeAction(QStringLiteral("shell_access"))) {
+ if (m_command)
+ m_command->reload();
+ }
+ foreach (KateExternalToolsPluginView* view, m_views) {
+ view->rebuildMenu();
+ }
+}
+
+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.desktop b/addons/externaltools/externaltoolsplugin.desktop
new file mode 100644
--- /dev/null
+++ b/addons/externaltools/externaltoolsplugin.desktop
@@ -0,0 +1,6 @@
+[Desktop Entry]
+Type=Service
+ServiceTypes=KTextEditor/Plugin
+X-KDE-Library=externaltoolsplugin
+Name=External Tools
+Comment=External Tools
diff --git a/addons/externaltools/plugin.qrc b/addons/externaltools/plugin.qrc
new file mode 100644
--- /dev/null
+++ b/addons/externaltools/plugin.qrc
@@ -0,0 +1,6 @@
+
+
+
+ ui.rc
+
+
diff --git a/addons/externaltools/tooldialog.ui b/addons/externaltools/tooldialog.ui
new file mode 100644
--- /dev/null
+++ b/addons/externaltools/tooldialog.ui
@@ -0,0 +1,353 @@
+
+
+ ToolDialog
+
+
+
+ 0
+ 0
+ 470
+ 491
+
+
+
+ Edit Tool
+
+
+ -
+
+
+ Name:
+
+
+
+ -
+
+
-
+
+
+ The name will be displayed in the 'Tools->External Tools' menu.
+
+
+ Short name of the tool
+
+
+
+ -
+
+
+
+
+ -
+
+
+ Executable:
+
+
+
+ -
+
+
-
+
+
+ The executable used by the command. This is used to check if a tool should be displayed; if not set, the first word of <em>command</em> will be used.
+
+
+ Application or interpreter
+
+
+
+ -
+
+
+
+ ../../../../../../../../.designer/backup../../../../../../../../.designer/backup
+
+
+ QToolButton::InstantPopup
+
+
+
+
+
+ -
+
+
+ Arguments:
+
+
+
+ -
+
+
+ Input:
+
+
+
+ -
+
+
-
+
+
+ <p>The script to execute to invoke the tool. The script is passed to /bin/sh for execution. The following macros will be expanded:</p><ul><li><code>%URL</code> - the URL of the current document.</li><li><code>%URLs</code> - a list of the URLs of all open documents.</li><li><code>%directory</code> - the URL of the directory containing the current document.</li><li><code>%filename</code> - the filename of the current document.</li><li><code>%line</code> - the current line of the text cursor in the current view.</li><li><code>%column</code> - the column of the text cursor in the current view.</li><li><code>%selection</code> - the selected text in the current view.</li><li><code>%text</code> - the text of the current document.</li></ul>
+
+
+ Optional standard input
+
+
+
+ -
+
+
+
+ ../../../../../../../../.designer/backup../../../../../../../../.designer/backup
+
+
+ QToolButton::InstantPopup
+
+
+
+
+
+ -
+
+
+ Mime types:
+
+
+
+ -
+
+
-
+
+
+ A semicolon-separated list of mime types for which this tool should be available; if this is left empty, the tool is always available. To choose from known mimetypes, press the button on the right.
+
+
+ Show tool only for given mime types
+
+
+
+ -
+
+
+ Click for a dialog that can help you create a list of mimetypes.
+
+
+
+ ../../../../../../../../.designer/backup../../../../../../../../.designer/backup
+
+
+
+
+
+ -
+
+
+ Save:
+
+
+
+ -
+
+
+ You can choose to save the current or all [modified] documents prior to running the command. This is helpful if you want to pass URLs to an application like, for example, an FTP client.
+
+
-
+
+ None
+
+
+ -
+
+ Current Document
+
+
+ -
+
+ All Documents
+
+
+
+
+ -
+
+
+ Reload current document after execution
+
+
+
+ -
+
+
+ Output:
+
+
+
+ -
+
+
-
+
+ Ignore
+
+
+ -
+
+ Insert at Cursor Position
+
+
+ -
+
+ Replace Selected Text
+
+
+ -
+
+ Replace Current Document
+
+
+ -
+
+ Append to Current Document
+
+
+ -
+
+ Insert in New Document
+
+
+ -
+
+ Display in Pane
+
+
+ -
+
+ Embedded Console
+
+
+
+
+ -
+
+
+ Editor command:
+
+
+
+ -
+
+
+ If you specify a name here, you can invoke the command from the view command line with exttool-the_name_you_specified_here. Please do not use spaces or tabs in the name.
+
+
+ Optional command bar name
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+ -
+
+
+ Working directory:
+
+
+
+ -
+
+
-
+
+
+ Uses current document path if empty
+
+
+
+ -
+
+
+
+ ../../../../../../../../.designer/backup../../../../../../../../.designer/backup
+
+
+ QToolButton::InstantPopup
+
+
+
+
+
+ -
+
+
-
+
+
+ Command line arguments
+
+
+
+ -
+
+
+
+ ../../../../../../../../.designer/backup../../../../../../../../.designer/backup
+
+
+ QToolButton::InstantPopup
+
+
+
+
+
+
+
+
+
+ KIconButton
+ QPushButton
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ ToolDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ ToolDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/addons/externaltools/ui.rc b/addons/externaltools/ui.rc
new file mode 100644
--- /dev/null
+++ b/addons/externaltools/ui.rc
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+