Commit 9a599a94 authored by Waqar Ahmed's avatar Waqar Ahmed
Browse files

External tools: Add "execute on save" option

Allows executing a tool on saving.

Another change with this MR is that the mime-type line edit is now read-
only. To add mimetypes you must use the mimetype chooser dialog instead.
This enforces more correctness.
parent e547c203
......@@ -235,24 +235,26 @@ QVector<KateExternalTool> KateExternalToolsPlugin::defaultTools() const
return m_defaultTools;
}
void KateExternalToolsPlugin::runTool(const KateExternalTool &tool, KTextEditor::View *view)
void KateExternalToolsPlugin::runTool(const KateExternalTool &tool, KTextEditor::View *view, bool executingOnSave)
{
// 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) {
// only save if modified, to avoid unnecessary recompiles
if (view->document()->isModified()) {
view->document()->save();
}
} else if (tool.saveMode == KateExternalTool::SaveMode::AllDocuments) {
const auto guiClients = mw->guiFactory()->clients();
for (KXMLGUIClient *client : guiClients) {
if (QAction *a = client->actionCollection()->action(QStringLiteral("file_save_all"))) {
a->trigger();
break;
if (!executingOnSave) {
if (tool.saveMode == KateExternalTool::SaveMode::CurrentDocument) {
// only save if modified, to avoid unnecessary recompiles
if (view->document()->isModified()) {
view->document()->save();
}
} else if (tool.saveMode == KateExternalTool::SaveMode::AllDocuments) {
const auto guiClients = mw->guiFactory()->clients();
for (KXMLGUIClient *client : guiClients) {
if (QAction *a = client->actionCollection()->action(QStringLiteral("file_save_all"))) {
a->trigger();
break;
}
}
}
}
......
......@@ -91,7 +91,7 @@ public:
/**
* Executes the tool based on the view as current document.
*/
void runTool(const KateExternalTool &tool, KTextEditor::View *view);
void runTool(const KateExternalTool &tool, KTextEditor::View *view, bool executingOnSave = false);
Q_SIGNALS:
/**
......
......@@ -101,7 +101,7 @@ bool KateExternalTool::checkExec() const
bool KateExternalTool::matchesMimetype(const QString &mt) const
{
return mimetypes.isEmpty() || mimetypes.contains(mt);
return mimetypes.contains(mt);
}
void KateExternalTool::load(const KConfigGroup &cg)
......@@ -119,6 +119,7 @@ void KateExternalTool::load(const KConfigGroup &cg)
saveMode = toSaveMode(cg.readEntry("save", "None"));
reload = cg.readEntry("reload", false);
outputMode = toOutputMode(cg.readEntry("output", "Ignore"));
execOnSave = cg.readEntry("execOnSave", false);
hasexec = checkExec();
}
......@@ -148,8 +149,10 @@ void KateExternalTool::save(KConfigGroup &cg) const
writeEntryMaybe(cg, "cmdname", cmdname);
writeEntryMaybe(cg, "save", toString(saveMode));
writeEntryMaybe(cg, "output", toString(outputMode));
// a logical value is never empty
cg.writeEntry("reload", reload);
cg.writeEntry("execOnSave", execOnSave);
}
QString KateExternalTool::translatedName() const
......@@ -166,7 +169,8 @@ bool operator==(const KateExternalTool &lhs, const KateExternalTool &rhs)
{
return lhs.category == rhs.category && lhs.name == rhs.name && lhs.icon == rhs.icon && lhs.executable == rhs.executable && lhs.arguments == rhs.arguments
&& lhs.input == rhs.input && lhs.workingDir == rhs.workingDir && lhs.mimetypes == rhs.mimetypes && lhs.actionName == rhs.actionName
&& lhs.cmdname == rhs.cmdname && lhs.saveMode == rhs.saveMode && lhs.reload == rhs.reload && lhs.outputMode == rhs.outputMode;
&& lhs.cmdname == rhs.cmdname && lhs.saveMode == rhs.saveMode && lhs.reload == rhs.reload && lhs.outputMode == rhs.outputMode
&& lhs.execOnSave == rhs.execOnSave;
}
// kate: space-indent on; indent-width 4; replace-tabs on;
......@@ -73,13 +73,15 @@ public:
bool reload = false;
/// Defines where to redirect the tool's output
OutputMode outputMode = OutputMode::Ignore;
/// Whether to execute tool on document save
bool execOnSave = false;
public:
/// This is set when loading the Tool from disk.
bool hasexec = false;
/**
* @return true if mimetypes is empty, or the @p mimetype matches.
* @return true if the @p mimetype matches.
*/
bool matchesMimetype(const QString &mimetype) const;
......
......@@ -156,6 +156,7 @@ KateExternalToolServiceEditor::KateExternalToolServiceEditor(KateExternalTool *t
ui.edtWorkingDir->setText(m_tool->workingDir);
ui.edtWorkingDir->setMode(KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly);
ui.edtMimeType->setText(m_tool->mimetypes.join(QStringLiteral("; ")));
ui.edtMimeType->setReadOnly(true);
ui.cmbSave->setCurrentIndex(static_cast<int>(m_tool->saveMode));
ui.chkReload->setChecked(m_tool->reload);
ui.cmbOutput->setCurrentIndex(static_cast<int>(m_tool->outputMode));
......@@ -180,6 +181,7 @@ KateExternalToolServiceEditor::KateExternalToolServiceEditor(KateExternalTool *t
ui.chkReload->setChecked(t.reload);
ui.cmbOutput->setCurrentIndex(static_cast<int>(t.outputMode));
ui.edtCommand->setText(t.cmdname);
ui.chkExecSave->setChecked(t.execOnSave);
});
}
......@@ -194,6 +196,12 @@ void KateExternalToolServiceEditor::slotOKClicked()
return;
}
const bool execOnSave = ui.chkExecSave->isChecked();
if (execOnSave && ui.edtMimeType->text().isEmpty()) {
QMessageBox::information(this, i18n("External Tool"), i18n("With 'Execute On Save' enabled, at least one mimetype needs to be specified."));
return;
}
accept();
}
......@@ -206,6 +214,7 @@ void KateExternalToolServiceEditor::showMTDlg()
ui.edtMimeType->setText(d.chooser()->mimeTypes().join(QStringLiteral(";")));
}
}
// END KateExternalToolServiceEditor
// BEGIN KateExternalToolsConfigWidget
......@@ -346,6 +355,7 @@ bool KateExternalToolsConfigWidget::editTool(KateExternalTool *tool)
tool->reload = editor.ui.chkReload->isChecked();
tool->outputMode = static_cast<KateExternalTool::OutputMode>(editor.ui.cmbOutput->currentIndex());
tool->cmdname = editor.ui.edtCommand->text().trimmed();
tool->execOnSave = editor.ui.chkExecSave->isChecked();
tool->executable = editor.ui.edtExecutable->text().trimmed();
tool->hasexec = tool->checkExec();
......
......@@ -134,7 +134,7 @@ void KateExternalToolsMenuAction::updateActionState(KTextEditor::Document *activ
for (QAction *action : actions) {
if (action && action->data().value<KateExternalTool *>()) {
auto tool = action->data().value<KateExternalTool *>();
action->setEnabled(tool->matchesMimetype(mimeType));
action->setEnabled(tool->matchesMimetype(mimeType) || tool->mimetypes.isEmpty());
}
}
}
......@@ -167,6 +167,10 @@ KateExternalToolsPluginView::KateExternalToolsPluginView(KTextEditor::MainWindow
// ESC should close & hide ToolView
connect(m_mainWindow, &KTextEditor::MainWindow::unhandledShortcutOverride, this, &KateExternalToolsPluginView::handleEsc);
connect(m_mainWindow, &KTextEditor::MainWindow::viewChanged, this, &KateExternalToolsPluginView::slotViewChanged);
if (auto view = m_mainWindow->activeView()) {
slotViewChanged(view);
}
}
KateExternalToolsPluginView::~KateExternalToolsPluginView()
......@@ -263,6 +267,25 @@ void KateExternalToolsPluginView::handleEsc(QEvent *event)
}
}
void KateExternalToolsPluginView::slotViewChanged(KTextEditor::View *v)
{
if (m_currentView) {
disconnect(m_currentView->document(), &KTextEditor::Document::documentSavedOrUploaded, this, &KateExternalToolsPluginView::documentSaved);
}
m_currentView = v;
connect(v->document(), &KTextEditor::Document::documentSavedOrUploaded, this, &KateExternalToolsPluginView::documentSaved, Qt::UniqueConnection);
}
void KateExternalToolsPluginView::documentSaved(KTextEditor::Document *doc)
{
const auto tools = m_plugin->tools();
for (KateExternalTool *tool : tools) {
if (tool->execOnSave && tool->matchesMimetype(doc->mimeType())) {
m_plugin->runTool(*tool, m_currentView, tool->execOnSave);
}
}
}
// END KateExternalToolsPluginView
// kate: space-indent on; indent-width 4; replace-tabs on;
......@@ -21,6 +21,8 @@ class View;
#include <KMacroExpander>
#include <KXMLGUIClient>
#include <QPointer>
class QTextDocument;
class KActionCollection;
......@@ -136,6 +138,10 @@ public Q_SLOTS:
*/
void handleEsc(QEvent *event);
private Q_SLOTS:
void slotViewChanged(KTextEditor::View *v);
void documentSaved(KTextEditor::Document *doc);
Q_SIGNALS:
/**
* Signal for outgoing message, the host application will handle them!
......@@ -151,6 +157,7 @@ private:
QWidget *m_toolView = nullptr;
Ui::ToolView *m_ui = nullptr;
QTextDocument *m_outputDoc = nullptr;
QPointer<KTextEditor::View> m_currentView;
};
#endif // KTEXTEDITOR_EXTERNALTOOLS_H
......
......@@ -169,7 +169,7 @@
</property>
</widget>
</item>
<item row="8" column="0">
<item row="9" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>O&amp;utput:</string>
......@@ -179,7 +179,7 @@
</property>
</widget>
</item>
<item row="8" column="1">
<item row="9" column="1">
<widget class="QComboBox" name="cmbOutput">
<item>
<property name="text">
......@@ -223,7 +223,7 @@
</item>
</widget>
</item>
<item row="9" column="0">
<item row="10" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Editor command:</string>
......@@ -233,7 +233,7 @@
</property>
</widget>
</item>
<item row="9" column="1">
<item row="10" column="1">
<widget class="QLineEdit" name="edtCommand">
<property name="whatsThis">
<string>If you specify a name here, you can invoke the command from the view command line with the_name_you_specified_here. Please do not use spaces or tabs in the name.</string>
......@@ -243,7 +243,7 @@
</property>
</widget>
</item>
<item row="10" column="0" colspan="2">
<item row="11" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
......@@ -264,6 +264,13 @@
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QCheckBox" name="chkExecSave">
<property name="text">
<string>Execute on save</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment