Commit f0d97baa authored by Mark Nauwelaerts's avatar Mark Nauwelaerts

build-plugin: optionally add marks for build errors and warnings

parent a483a872
......@@ -38,6 +38,7 @@
#include <QFileInfo>
#include <QDir>
#include <QFileDialog>
#include <QIcon>
#include <QAction>
......@@ -52,6 +53,8 @@
#include <kpluginloader.h>
#include <kaboutdata.h>
#include <ktexteditor/markinterface.h>
#include "SelectTargetView.h"
......@@ -63,6 +66,25 @@ static const QString DefTargetName = QStringLiteral("all");
static const QString DefBuildCmd = QStringLiteral("make");
static const QString DefCleanCmd = QStringLiteral("make clean");
static QIcon messageIcon(KateBuildView::ErrorCategory severity)
{
#define RETURN_CACHED_ICON(name) \
{ \
static QIcon icon(QIcon::fromTheme(QStringLiteral(name))); \
return icon; \
}
switch (severity)
{
case KateBuildView::CategoryError:
RETURN_CACHED_ICON("dialog-error")
case KateBuildView::CategoryWarning:
RETURN_CACHED_ICON("dialog-warning")
default:
break;
}
return QIcon();
}
/******************************************************************/
KateBuildPlugin::KateBuildPlugin(QObject *parent, const VariantList&):
......@@ -133,6 +155,10 @@ KateBuildView::KateBuildView(KTextEditor::Plugin *plugin, KTextEditor::MainWindo
actionCollection()->setDefaultShortcut(a, Qt::SHIFT+Qt::ALT+Qt::Key_Left);
connect(a, &QAction::triggered, this, &KateBuildView::slotPrev);
m_showMarks = a = actionCollection()->addAction(QStringLiteral("show_marks"));
a->setText(i18n("Show Marks"));
a->setCheckable(true);
connect(a, &QAction::triggered, this, &KateBuildView::slotDisplayOption);
m_buildWidget = new QWidget(m_toolView);
m_buildUi.setupUi(m_buildWidget);
......@@ -179,6 +205,7 @@ KateBuildView::KateBuildView(KTextEditor::Plugin *plugin, KTextEditor::MainWindo
connect(&m_proc, &KProcess::readyReadStandardOutput, this, &KateBuildView::slotReadReadyStdOut);
connect(m_win, &KTextEditor::MainWindow::unhandledShortcutOverride, this, &KateBuildView::handleEsc);
connect(m_win, &KTextEditor::MainWindow::viewChanged, this, &KateBuildView::slotViewChanged);
m_toolView->installEventFilter(this);
......@@ -262,6 +289,9 @@ void KateBuildView::readSessionConfig(const KConfigGroup& cg)
QModelIndex cmdIndex = m_targetsUi->targetsModel.index(tmpCmd, 0, root);
m_targetsUi->targetsView->setCurrentIndex(cmdIndex);
auto showMarks = cg.readEntry(QStringLiteral("Show Marks"), false);
m_showMarks->setChecked(showMarks);
// Add project targets, if any
slotAddProjectTarget();
}
......@@ -304,6 +334,7 @@ void KateBuildView::writeSessionConfig(KConfigGroup& cg)
cg.writeEntry(QStringLiteral("Active Target Index"), set);
cg.writeEntry(QStringLiteral("Active Target Command"), setRow);
cg.writeEntry(QStringLiteral("Show Marks"), m_showMarks->isChecked());
// Restore project targets, if any
slotAddProjectTarget();
......@@ -451,6 +482,120 @@ void KateBuildView::addError(const QString &filename, const QString &line,
item->setData(2, Qt::ToolTipRole, QStringLiteral("<qt>%1</qt>").arg(message));
}
void KateBuildView::clearMarks()
{
for (auto& doc: m_markedDocs) {
if (!doc) {
continue;
}
KTextEditor::MarkInterface* iface = qobject_cast<KTextEditor::MarkInterface*>(doc);
if (iface) {
const QHash<int, KTextEditor::Mark*> marks = iface->marks();
QHashIterator<int, KTextEditor::Mark*> i(marks);
while (i.hasNext()) {
i.next();
auto markType = KTextEditor::MarkInterface::Error | KTextEditor::MarkInterface::Warning;
if (i.value()->type & markType) {
iface->removeMark(i.value()->line, markType);
}
}
}
}
m_markedDocs.clear();
}
void KateBuildView::addMarks(KTextEditor::Document *doc)
{
KTextEditor::MarkInterface* iface = qobject_cast<KTextEditor::MarkInterface*>(doc);
if (!iface || m_markedDocs.contains(doc))
return;
QTreeWidgetItemIterator it(m_buildUi.errTreeWidget, QTreeWidgetItemIterator::All);
while (*it) {
QTreeWidgetItem *item = *it;
++it;
auto filename = item->data(0, Qt::UserRole).toString();
auto url = QUrl::fromLocalFile(filename);
if (url != doc->url())
continue;
auto line = item->data(1, Qt::UserRole).toInt();
ErrorCategory category = (ErrorCategory)item->data(0, ErrorRole).toInt();
KTextEditor::MarkInterface::MarkTypes markType {};
switch (category) {
case CategoryError: {
markType = KTextEditor::MarkInterface::Error;
iface->setMarkDescription(markType, i18n("Error"));
break;
}
case CategoryWarning: {
markType = KTextEditor::MarkInterface::Warning;
iface->setMarkDescription(markType, i18n("Warning"));
break;
}
default:
break;
}
if (markType) {
const int ps = 32;
iface->setMarkPixmap(markType, messageIcon(category).pixmap(ps, ps));
iface->addMark(line - 1, markType);
}
}
connect(doc, SIGNAL(markClicked(KTextEditor::Document*, KTextEditor::Mark, bool&)),
this, SLOT(slotMarkClicked(KTextEditor::Document*,KTextEditor::Mark, bool&)), Qt::UniqueConnection);
m_markedDocs.insert(doc, doc);
}
void KateBuildView::slotMarkClicked(KTextEditor::Document *doc, KTextEditor::Mark mark, bool &handled)
{
auto tree = m_buildUi.errTreeWidget;
QTreeWidgetItemIterator it(tree, QTreeWidgetItemIterator::All);
while (*it) {
QTreeWidgetItem *item = *it;
++it;
auto filename = item->data(0, Qt::UserRole).toString();
auto line = item->data(1, Qt::UserRole).toInt();
if (line - 1 == mark.line && QUrl::fromLocalFile(filename) == doc->url()) {
tree->blockSignals(true);
tree->setCurrentItem(item);
tree->scrollToItem(item, QAbstractItemView::PositionAtCenter);
tree->blockSignals(false);
handled = true;
break;
}
}
}
void KateBuildView::slotViewChanged()
{
KTextEditor::View *activeView = m_win->activeView();
auto doc = activeView ? activeView->document() : nullptr;
if (doc && m_showMarks->isChecked()) {
addMarks(doc);
}
}
void KateBuildView::slotDisplayOption()
{
if (m_showMarks) {
if (!m_showMarks->isChecked()) {
clearMarks();
} else {
slotViewChanged();
}
}
}
/******************************************************************/
QUrl KateBuildView::docUrl()
{
......@@ -484,6 +629,7 @@ bool KateBuildView::checkLocal(const QUrl &dir)
/******************************************************************/
void KateBuildView::clearBuildResults()
{
clearMarks();
m_buildUi.plainTextEdit->clear();
m_buildUi.errTreeWidget->clear();
m_stdOut.clear();
......@@ -714,6 +860,8 @@ void KateBuildView::slotProcExited(int exitCode, QProcess::ExitStatus)
m_buildUi.buildStatusLabel->setText(buildStatus);
m_buildUi.buildStatusLabel2->setText(buildStatus);
m_buildCancelled = false;
// add marks
slotViewChanged();
}
}
......
......@@ -29,6 +29,7 @@
#include <QString>
#include <QStack>
#include <QPointer>
#include <QHash>
#include <KProcess>
#include <KTextEditor/MainWindow>
......@@ -37,6 +38,7 @@
#include <KTextEditor/View>
#include <KTextEditor/SessionConfigInterface>
#include <KTextEditor/Message>
#include <KTextEditor/MarkInterface>
#include <KXMLGUIClient>
#include <KConfigGroup>
......@@ -111,6 +113,10 @@ class KateBuildView : public QObject, public KXMLGUIClient, public KTextEditor::
void handleEsc(QEvent *e);
void slotViewChanged();
void slotDisplayOption();
void slotMarkClicked(KTextEditor::Document *doc, KTextEditor::Mark mark, bool &handled);
/**
* keep track if the project plugin is alive and if the project map did change
*/
......@@ -132,6 +138,9 @@ class KateBuildView : public QObject, public KXMLGUIClient, public KTextEditor::
void displayBuildResult(const QString &message, KTextEditor::Message::MessageType level);
void clearMarks();
void addMarks(KTextEditor::Document *doc);
KTextEditor::MainWindow *m_win;
QWidget *m_toolView;
Ui::build m_buildUi;
......@@ -155,6 +164,8 @@ class KateBuildView : public QObject, public KXMLGUIClient, public KTextEditor::
QString m_prevItemContent;
QModelIndex m_previousIndex;
QPointer<KTextEditor::Message> m_infoMessage;
QPointer<QAction> m_showMarks;
QHash<KTextEditor::Document*, QPointer<KTextEditor::Document>> m_markedDocs;
/**
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE kpartgui>
<gui name="katebuild-plugin" library="katebuildplugin" version="10" translationDomain="katebuild-plugin">
<gui name="katebuild-plugin" library="katebuildplugin" version="11" translationDomain="katebuild-plugin">
<MenuBar>
<Menu name="Build Menubar">
<text>&amp;Build</text>
......@@ -11,6 +11,8 @@
<Separator/>
<Action name="goto_prev"/>
<Action name="goto_next"/>
<Separator/>
<Action name="show_marks"/>
</Menu>
</MenuBar>
</gui>
......
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