Changeset View
Changeset View
Standalone View
Standalone View
plugins/problemreporter/problemhighlighter.cpp
Show All 18 Lines | |||||
19 | * Free Software Foundation, Inc., | 19 | * Free Software Foundation, Inc., | ||
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
21 | */ | 21 | */ | ||
22 | 22 | | |||
23 | #include "problemhighlighter.h" | 23 | #include "problemhighlighter.h" | ||
24 | 24 | | |||
25 | #include <KTextEditor/Document> | 25 | #include <KTextEditor/Document> | ||
26 | #include <KTextEditor/MarkInterface> | 26 | #include <KTextEditor/MarkInterface> | ||
27 | #include <ktexteditor/texthintinterface.h> | | |||
28 | #include <ktexteditor/view.h> | 27 | #include <ktexteditor/view.h> | ||
29 | #include <ktexteditor/movinginterface.h> | 28 | #include <ktexteditor/movinginterface.h> | ||
30 | 29 | | |||
31 | #include <serialization/indexedstring.h> | 30 | #include <serialization/indexedstring.h> | ||
32 | #include <language/duchain/navigation/abstractnavigationwidget.h> | 31 | #include <language/duchain/navigation/abstractnavigationwidget.h> | ||
33 | #include <language/util/navigationtooltip.h> | 32 | #include <language/util/navigationtooltip.h> | ||
34 | #include <interfaces/icore.h> | 33 | #include <interfaces/icore.h> | ||
35 | #include <interfaces/ilanguagecontroller.h> | 34 | #include <interfaces/ilanguagecontroller.h> | ||
Show All 26 Lines | 53 | { | |||
62 | default: | 61 | default: | ||
63 | return scheme.foreground(KColorScheme::PositiveText).color(); | 62 | return scheme.foreground(KColorScheme::PositiveText).color(); | ||
64 | } | 63 | } | ||
65 | } | 64 | } | ||
66 | } | 65 | } | ||
67 | 66 | | |||
68 | ProblemHighlighter::ProblemHighlighter(KTextEditor::Document* document) | 67 | ProblemHighlighter::ProblemHighlighter(KTextEditor::Document* document) | ||
69 | : m_document(document) | 68 | : m_document(document) | ||
70 | , m_textHintProvider(this) | | |||
71 | { | 69 | { | ||
72 | Q_ASSERT(m_document); | 70 | Q_ASSERT(m_document); | ||
73 | 71 | | |||
74 | foreach (KTextEditor::View* view, m_document->views()) | | |||
75 | viewCreated(document, view); | | |||
76 | | ||||
77 | connect(m_document.data(), &Document::viewCreated, this, &ProblemHighlighter::viewCreated); | | |||
78 | connect(ICore::self()->languageController()->completionSettings(), &ICompletionSettings::settingsChanged, this, | 72 | connect(ICore::self()->languageController()->completionSettings(), &ICompletionSettings::settingsChanged, this, | ||
79 | &ProblemHighlighter::settingsChanged); | 73 | &ProblemHighlighter::settingsChanged); | ||
80 | connect(m_document.data(), &Document::aboutToReload, this, &ProblemHighlighter::clearProblems); | 74 | connect(m_document.data(), &Document::aboutToReload, this, &ProblemHighlighter::clearProblems); | ||
81 | if (qobject_cast<MovingInterface*>(m_document)) { | 75 | if (qobject_cast<MovingInterface*>(m_document)) { | ||
82 | // can't use new signal/slot syntax here, MovingInterface is not a QObject | 76 | // can't use new signal/slot syntax here, MovingInterface is not a QObject | ||
83 | connect(m_document, SIGNAL(aboutToInvalidateMovingInterfaceContent(KTextEditor::Document*)), this, | 77 | connect(m_document, SIGNAL(aboutToInvalidateMovingInterfaceContent(KTextEditor::Document*)), this, | ||
84 | SLOT(clearProblems())); | 78 | SLOT(clearProblems())); | ||
85 | } | 79 | } | ||
86 | connect(m_document, SIGNAL(aboutToRemoveText(KTextEditor::Range)), this, | 80 | connect(m_document, SIGNAL(aboutToRemoveText(KTextEditor::Range)), this, | ||
87 | SLOT(aboutToRemoveText(KTextEditor::Range))); | 81 | SLOT(aboutToRemoveText(KTextEditor::Range))); | ||
88 | } | 82 | } | ||
89 | 83 | | |||
90 | void ProblemHighlighter::settingsChanged() | 84 | void ProblemHighlighter::settingsChanged() | ||
91 | { | 85 | { | ||
92 | // Re-highlight | 86 | // Re-highlight | ||
93 | setProblems(m_problems); | 87 | setProblems(m_problems); | ||
94 | } | 88 | } | ||
95 | 89 | | |||
96 | void ProblemHighlighter::viewCreated(Document*, View* view) | | |||
97 | { | | |||
98 | KTextEditor::TextHintInterface* iface = dynamic_cast<KTextEditor::TextHintInterface*>(view); | | |||
99 | if (!iface) | | |||
100 | return; | | |||
101 | | ||||
102 | iface->registerTextHintProvider(&m_textHintProvider); | | |||
103 | } | | |||
104 | | ||||
105 | ProblemTextHintProvider::ProblemTextHintProvider(ProblemHighlighter* highlighter) | | |||
106 | : m_highlighter(highlighter) | | |||
107 | { | | |||
108 | } | | |||
109 | | ||||
110 | QString ProblemTextHintProvider::textHint(View* view, const Cursor& pos) | | |||
111 | { | | |||
112 | KTextEditor::MovingInterface* moving = dynamic_cast<KTextEditor::MovingInterface*>(view->document()); | | |||
113 | if (moving) { | | |||
114 | ///@todo Sort the ranges when writing them, and do binary search instead of linear | | |||
115 | foreach (MovingRange* range, m_highlighter->m_topHLRanges) { | | |||
116 | if (m_highlighter->m_problemsForRanges.contains(range) && range->contains(pos)) { | | |||
117 | // There is a problem which's range contains the cursor | | |||
118 | IProblem::Ptr problem = m_highlighter->m_problemsForRanges[range]; | | |||
119 | if (problem->source() == IProblem::ToDo) { | | |||
120 | continue; | | |||
121 | } | | |||
122 | | ||||
123 | if (m_currentHintRange == range->toRange()) { | | |||
124 | continue; | | |||
125 | } | | |||
126 | m_currentHintRange = range->toRange(); | | |||
127 | | ||||
128 | KDevelop::AbstractNavigationWidget* widget = new KDevelop::AbstractNavigationWidget; | | |||
129 | widget->setContext(NavigationContextPointer(new ProblemNavigationContext(problem))); | | |||
130 | | ||||
131 | KDevelop::NavigationToolTip* tooltip | | |||
132 | = new KDevelop::NavigationToolTip(view, QCursor::pos() + QPoint(20, 40), widget); | | |||
133 | | ||||
134 | tooltip->resize(widget->sizeHint() + QSize(10, 10)); | | |||
135 | tooltip->setHandleRect(KTextEditorHelpers::getItemBoundingRect(view, m_currentHintRange)); | | |||
136 | tooltip->connect(tooltip, &ActiveToolTip::destroyed, [&] () { m_currentHintRange = {}; }); | | |||
137 | ActiveToolTip::showToolTip(tooltip, 99, QStringLiteral("problem-tooltip")); | | |||
138 | return QString(); | | |||
139 | } | | |||
140 | } | | |||
141 | } | | |||
142 | return QString(); | | |||
143 | } | | |||
144 | | ||||
145 | ProblemHighlighter::~ProblemHighlighter() | 90 | ProblemHighlighter::~ProblemHighlighter() | ||
146 | { | 91 | { | ||
147 | if (m_topHLRanges.isEmpty() || !m_document) | 92 | if (m_topHLRanges.isEmpty() || !m_document) | ||
148 | return; | 93 | return; | ||
149 | 94 | | |||
150 | qDeleteAll(m_topHLRanges); | 95 | qDeleteAll(m_topHLRanges); | ||
151 | } | 96 | } | ||
152 | 97 | | |||
153 | void ProblemHighlighter::setProblems(const QVector<IProblem::Ptr>& problems) | 98 | void ProblemHighlighter::setProblems(const QVector<IProblem::Ptr>& problems) | ||
154 | { | 99 | { | ||
100 | qDebug() << "updating problem highlight"; | ||||
155 | if (!m_document) | 101 | if (!m_document) | ||
156 | return; | 102 | return; | ||
157 | 103 | | |||
158 | const bool hadProblems = !m_problems.isEmpty(); | 104 | const bool hadProblems = !m_problems.isEmpty(); | ||
159 | m_problems = problems; | 105 | m_problems = problems; | ||
160 | 106 | | |||
161 | qDeleteAll(m_topHLRanges); | 107 | qDeleteAll(m_topHLRanges); | ||
162 | m_topHLRanges.clear(); | 108 | m_topHLRanges.clear(); | ||
▲ Show 20 Lines • Show All 98 Lines • Show Last 20 Lines |