1+ #include < utility>
2+
13// QCodeEditor
24#include < QCXXHighlighter>
35#include < QCodeEditor>
1315#include < QAbstractTextDocumentLayout>
1416#include < QCompleter>
1517#include < QCursor>
18+ #include < QDebug>
1619#include < QFontDatabase>
1720#include < QMimeData>
1821#include < QPaintEvent>
2124#include < QTextBlock>
2225#include < QTextCharFormat>
2326#include < QTextStream>
27+ #include < QToolTip>
2428
2529static QVector<QPair<QString, QString>> parentheses = {{" (" , " )" }, {" {" , " }" }, {" [" , " ]" }, {" \" " , " \" " }, {" '" , " '" }};
2630
2731QCodeEditor::QCodeEditor (QWidget *widget)
2832 : QTextEdit(widget), m_highlighter(nullptr ), m_syntaxStyle(nullptr ), m_lineNumberArea(new QLineNumberArea(this )),
2933 m_completer(nullptr ), m_autoIndentation(true ), m_autoParentheses(true ), m_replaceTab(true ),
30- m_autoRemoveParentheses(true ), m_tabReplace(QString(4 , ' ' )), extra1(), extra2()
34+ m_autoRemoveParentheses(true ), m_tabReplace(QString(4 , ' ' )), extra1(), extra2(), extra_squiggles(), m_squiggler()
3135{
3236 initFont ();
3337 performConnections ();
38+ setMouseTracking (true );
3439
3540 setSyntaxStyle (QSyntaxStyle::defaultStyle ());
3641}
@@ -147,7 +152,7 @@ void QCodeEditor::updateExtraSelection1()
147152 highlightCurrentLine ();
148153 highlightParenthesis ();
149154
150- setExtraSelections (extra1 + extra2);
155+ setExtraSelections (extra1 + extra2 + extra_squiggles );
151156}
152157
153158void QCodeEditor::updateExtraSelection2 ()
@@ -156,7 +161,7 @@ void QCodeEditor::updateExtraSelection2()
156161
157162 highlightOccurrences ();
158163
159- setExtraSelections (extra1 + extra2);
164+ setExtraSelections (extra1 + extra2 + extra_squiggles );
160165}
161166
162167void QCodeEditor::indent ()
@@ -421,7 +426,7 @@ void QCodeEditor::highlightParenthesis()
421426 selection.cursor = textCursor ();
422427 selection.cursor .clearSelection ();
423428 selection.cursor .movePosition (directionEnum, QTextCursor::MoveMode::MoveAnchor,
424- std::abs (textCursor ().position () - position));
429+ qAbs (textCursor ().position () - position));
425430
426431 selection.cursor .movePosition (QTextCursor::MoveOperation::Right, QTextCursor::MoveMode::KeepAnchor, 1 );
427432
@@ -473,7 +478,7 @@ void QCodeEditor::highlightOccurrences()
473478 {
474479 QTextEdit::ExtraSelection e;
475480 e.cursor = cursor;
476- e.format .setFontUnderline ( true );
481+ e.format .setBackground (m_syntaxStyle-> getFormat ( " Selection " ). background () );
477482 extra2.push_back (e);
478483 }
479484 cursor = doc->find (text, cursor, QTextDocument::FindWholeWords | QTextDocument::FindCaseSensitively);
@@ -820,6 +825,45 @@ void QCodeEditor::focusInEvent(QFocusEvent *e)
820825 QTextEdit::focusInEvent (e);
821826}
822827
828+ bool QCodeEditor::event (QEvent *event)
829+ {
830+ if (event->type () == QEvent::ToolTip)
831+ {
832+ auto *helpEvent = dynamic_cast <QHelpEvent *>(event);
833+ auto point = helpEvent->pos ();
834+ point.setX (point.x () - m_lineNumberArea->geometry ().right ());
835+ QTextCursor cursor = cursorForPosition (point);
836+
837+ auto lineNumber = cursor.blockNumber () + 1 ;
838+
839+ QTextCursor copyCursor (cursor);
840+ copyCursor.movePosition (QTextCursor::StartOfBlock);
841+
842+ auto blockPositionStart = cursor.positionInBlock () - copyCursor.positionInBlock ();
843+ QPair<int , int > positionOfTooltip{lineNumber, blockPositionStart};
844+
845+ QString text;
846+ for (auto const &e : m_squiggler)
847+ {
848+ if (e.m_startPos <= positionOfTooltip && e.m_stopPos >= positionOfTooltip)
849+ {
850+ if (text.isEmpty ())
851+ text = e.m_tooltipText ;
852+ else
853+ text += " ; " + e.m_tooltipText ;
854+ }
855+ }
856+
857+ if (text.isEmpty ())
858+ QToolTip::hideText ();
859+ else
860+ QToolTip::showText (helpEvent->globalPos (), text);
861+
862+ return true ;
863+ }
864+ return QTextEdit::event (event);
865+ }
866+
823867void QCodeEditor::insertCompletion (QString s)
824868{
825869 if (m_completer->widget () != this )
@@ -838,6 +882,65 @@ QCompleter *QCodeEditor::completer() const
838882 return m_completer;
839883}
840884
885+ void QCodeEditor::squiggle (SeverityLevel level, QPair<int , int > start, QPair<int , int > stop, QString tooltipMessage)
886+ {
887+ if (stop < start)
888+ return ;
889+
890+ SquiggleInformation info (start, stop, tooltipMessage);
891+ m_squiggler.push_back (info);
892+
893+ auto cursor = textCursor ();
894+
895+ cursor.movePosition (QTextCursor::Start);
896+ cursor.movePosition (QTextCursor::NextBlock, QTextCursor::MoveAnchor, start.first - 1 );
897+ cursor.movePosition (QTextCursor::StartOfBlock);
898+ cursor.movePosition (QTextCursor::NextCharacter, QTextCursor::MoveAnchor, start.second );
899+
900+ if (stop.first > start.first )
901+ cursor.movePosition (QTextCursor::NextBlock, QTextCursor::KeepAnchor, stop.first - start.first );
902+
903+ cursor.movePosition (QTextCursor::StartOfBlock, QTextCursor::KeepAnchor);
904+ cursor.movePosition (QTextCursor::NextCharacter, QTextCursor::KeepAnchor, stop.second );
905+
906+ QTextCharFormat newcharfmt = currentCharFormat ();
907+ newcharfmt.setFontUnderline (true );
908+
909+ switch (level)
910+ {
911+ case SeverityLevel::Error:
912+ newcharfmt.setUnderlineColor (m_syntaxStyle->getFormat (" Error" ).underlineColor ());
913+ newcharfmt.setUnderlineStyle (m_syntaxStyle->getFormat (" Error" ).underlineStyle ());
914+ break ;
915+ case SeverityLevel::Warning:
916+ newcharfmt.setUnderlineColor (m_syntaxStyle->getFormat (" Warning" ).underlineColor ());
917+ newcharfmt.setUnderlineStyle (m_syntaxStyle->getFormat (" Warning" ).underlineStyle ());
918+ break ;
919+ case SeverityLevel::Information:
920+ newcharfmt.setUnderlineColor (m_syntaxStyle->getFormat (" Warning" ).underlineColor ());
921+ newcharfmt.setUnderlineStyle (QTextCharFormat::DotLine);
922+ break ;
923+ case SeverityLevel::Hint:
924+ newcharfmt.setUnderlineColor (m_syntaxStyle->getFormat (" Text" ).foreground ().color ());
925+ newcharfmt.setUnderlineStyle (QTextCharFormat::DotLine);
926+ }
927+
928+ extra_squiggles.push_back ({cursor, newcharfmt});
929+
930+ setExtraSelections (extra1 + extra2 + extra_squiggles);
931+ }
932+
933+ void QCodeEditor::clearSquiggle ()
934+ {
935+ if (m_squiggler.empty ())
936+ return ;
937+
938+ m_squiggler.clear ();
939+ extra_squiggles.clear ();
940+
941+ setExtraSelections (extra1 + extra2);
942+ }
943+
841944QChar QCodeEditor::charUnderCursor (int offset) const
842945{
843946 auto block = textCursor ().blockNumber ();
0 commit comments