inline-problems.diff

File Metadata

Author
brauch
Created
Aug 14 2018, 11:43 AM

inline-problems.diff

diff --git a/plugins/problemreporter/problemhighlighter.cpp b/plugins/problemreporter/problemhighlighter.cpp
index a4f3718e9e..bf0b341daf 100644
--- a/plugins/problemreporter/problemhighlighter.cpp
+++ b/plugins/problemreporter/problemhighlighter.cpp
@@ -24,6 +24,7 @@
#include <KTextEditor/Document>
#include <KTextEditor/MarkInterface>
+#include <KTextEditor/InlineNoteInterface>
#include <ktexteditor/view.h>
#include <ktexteditor/movinginterface.h>
@@ -39,12 +40,16 @@
#include <language/editor/documentrange.h>
#include <kcolorscheme.h>
+#include <QPainter>
+#include <QRegularExpression>
#include <shell/problem.h>
using namespace KTextEditor;
using namespace KDevelop;
+const int margin = 4;
+
namespace
{
@@ -61,6 +66,7 @@ QColor colorForSeverity(IProblem::Severity severity)
return scheme.foreground(KColorScheme::PositiveText).color();
}
}
+
}
ProblemHighlighter::ProblemHighlighter(KTextEditor::Document* document)
@@ -78,6 +84,22 @@ ProblemHighlighter::ProblemHighlighter(KTextEditor::Document* document)
}
connect(m_document, SIGNAL(aboutToRemoveText(KTextEditor::Range)), this,
SLOT(aboutToRemoveText(KTextEditor::Range)));
+ connect(m_document, &KTextEditor::Document::viewCreated,
+ this, &ProblemHighlighter::highlightProblemsInView);
+
+ for ( auto view: m_document->views() ) {
+ highlightProblemsInView(m_document, view);
+ }
+}
+
+void ProblemHighlighter::highlightProblemsInView(KTextEditor::Document* /*document*/, KTextEditor::View* view)
+{
+ auto iface = qobject_cast<KTextEditor::InlineNoteInterface*>(view);
+ if (!iface) {
+ return;
+ }
+ iface->registerInlineNoteProvider(this);
+ Q_EMIT reset();
}
void ProblemHighlighter::settingsChanged()
@@ -94,12 +116,82 @@ ProblemHighlighter::~ProblemHighlighter()
qDeleteAll(m_topHLRanges);
}
+namespace {
+ QFont scaledFont(const QFont& font) {
+ QFont small = font;
+ small.setPointSizeF(font.pointSizeF() * 0.80);
+ return small;
+ }
+
+ QString shortTextForProblem(const IProblem::Ptr& problem) {
+ auto expr = QRegularExpression("(.*?)(\\[\\-W.*\\])?$");
+ return expr.match(problem->description()).captured(1);
+ }
+}
+
+int ProblemHighlighter::problemIndexForLine(int line) const
+{
+ for ( int i = 0; i < m_problems.size(); i++ ) {
+ auto location = m_topHLRanges.at(i)->end().line();
+ if ( location == line ) {
+ return i; // only one note per line
+ }
+ }
+ return -1;
+}
+
+QVector<int> ProblemHighlighter::inlineNotes(int line) const
+{
+ auto index = problemIndexForLine(line);
+ if ( index == -1 ) {
+ return {};
+ }
+ auto range = m_topHLRanges.at(index);
+ if ( range->isEmpty() ) {
+ // it disappeared
+ return {};
+ }
+ return {m_document->lineLength(range->end().line()) + 1};
+}
+
+QSize ProblemHighlighter::inlineNoteSize(const KTextEditor::InlineNote& note, qreal /*height*/, QFont font) const
+{
+ auto index = problemIndexForLine(note.location.line());
+ if ( index == -1 ) {
+ return {};
+ }
+ const auto problem = m_problems.at(index);
+ const auto text = shortTextForProblem(problem);
+ return QFontMetrics(scaledFont(font)).boundingRect(text).adjusted(-margin/2, 0, margin/2, 0).size();
+}
+
+void ProblemHighlighter::paintInlineNote(const KTextEditor::InlineNote& note, qreal height, QFont font, QPainter& painter) const
+{
+ auto index = problemIndexForLine(note.location.line());
+ if ( index == -1 ) {
+ return;
+ }
+ auto problem = m_problems.at(index);
+
+ qreal textWidth = inlineNoteSize(note, height, font).width();
+
+ QRectF rectangle(margin / 2.0, 0.5, textWidth, height - 1);
+ painter.setPen(Qt::NoPen);
+ painter.setBrush(colorForSeverity(problem->severity()));
+ painter.drawRoundedRect(rectangle, 2, 2);
+ painter.setPen(Qt::white);
+
+ painter.setFont(scaledFont(font));
+ QFontMetrics metrics(font);
+ painter.drawText(margin, metrics.ascent(), shortTextForProblem(problem));
+}
+
void ProblemHighlighter::setProblems(const QVector<IProblem::Ptr>& problems)
{
if (!m_document)
return;
- if (m_problems == problems)
+ if (problems == m_problems)
return;
const bool hadProblems = !m_problems.isEmpty();
@@ -137,6 +229,7 @@ void ProblemHighlighter::setProblems(const QVector<IProblem::Ptr>& problems)
KTextEditor::MovingInterface* iface = dynamic_cast<KTextEditor::MovingInterface*>(m_document.data());
Q_ASSERT(iface);
+ QSet<int> seenLines;
foreach (const IProblem::Ptr& problem, problems) {
if (problem->finalLocation().document != url || !problem->finalLocation().isValid())
continue;
@@ -203,23 +296,8 @@ void ProblemHighlighter::setProblems(const QVector<IProblem::Ptr>& problems)
markIface->addMark(problem->finalLocation().start().line(), mark);
}
}
-}
-
-void ProblemHighlighter::aboutToRemoveText(const KTextEditor::Range& range)
-{
- if (range.onSingleLine()) { // no need to optimize this
- return;
- }
- QList<MovingRange*>::iterator it = m_topHLRanges.begin();
- while (it != m_topHLRanges.end()) {
- if (range.contains((*it)->toRange())) {
- delete (*it);
- it = m_topHLRanges.erase(it);
- } else {
- ++it;
- }
- }
+ Q_EMIT reset();
}
void ProblemHighlighter::clearProblems()
diff --git a/plugins/problemreporter/problemhighlighter.h b/plugins/problemreporter/problemhighlighter.h
index 21f7cb3f31..107c5ca4a4 100644
--- a/plugins/problemreporter/problemhighlighter.h
+++ b/plugins/problemreporter/problemhighlighter.h
@@ -28,19 +28,30 @@
#include <ktexteditor/movingrange.h>
#include <interfaces/iproblem.h>
-class ProblemHighlighter : public QObject
+#include <KTextEditor/InlineNoteInterface>
+
+class ProblemHighlighter : public KTextEditor::InlineNoteProvider
{
Q_OBJECT
public:
+
explicit ProblemHighlighter(KTextEditor::Document* document);
~ProblemHighlighter() override;
void setProblems(const QVector<KDevelop::IProblem::Ptr>& problems);
+ QVector<int> inlineNotes(int line) const override;
+ QSize inlineNoteSize(const KTextEditor::InlineNote& note, qreal height, QFont font) const override;
+ void paintInlineNote(const KTextEditor::InlineNote& note, qreal height, QFont font, QPainter& painter) const override;
+
private Q_SLOTS:
- void aboutToRemoveText(const KTextEditor::Range& range);
void clearProblems();
+ void highlightProblemsInView(KTextEditor::Document*, KTextEditor::View* view);
+
+private:
+ int problemIndexForLine(int line) const;
+
private:
QPointer<KTextEditor::Document> m_document;
QList<KTextEditor::MovingRange*> m_topHLRanges;