2 #include <QLineNumberArea>
3 #include <QSyntaxStyle>
5 #include <QStyleSyntaxHighlighter>
6 #include <QFramedTextAttribute>
7 #include <QCXXHighlighter>
12 #include <QPaintEvent>
13 #include <QFontDatabase>
15 #include <QAbstractTextDocumentLayout>
16 #include <QTextCharFormat>
19 #include <QAbstractItemView>
38 m_autoIndentation(true),
39 m_autoParentheses(true),
41 m_tabReplace(QString(4,
' '))
62 auto fnt = QFontDatabase::systemFont(QFontDatabase::FixedFont);
63 fnt.setFixedPitch(
true);
73 &QTextDocument::blockCountChanged,
80 &QScrollBar::valueChanged,
86 &QTextEdit::cursorPositionChanged,
93 &QTextEdit::selectionChanged,
139 auto currentPalette = palette();
142 currentPalette.setColor(
143 QPalette::ColorRole::Text,
148 currentPalette.setColor(
154 currentPalette.setColor(
159 setPalette(currentPalette);
167 auto selected = textCursor().selectedText();
169 auto cursor = textCursor();
178 cursor.select(QTextCursor::SelectionType::WordUnderCursor);
180 QSignalBlocker blocker(
this);
183 if (selected.size() > 1 &&
184 cursor.selectedText() == selected)
186 auto backup = textCursor();
191 setTextCursor(backup);
197 QTextEdit::resizeEvent(e);
204 QRect cr = contentsRect();
229 if (rect.contains(viewport()->rect()))
238 auto searchIterator = cursor;
239 searchIterator.movePosition(QTextCursor::Start);
240 searchIterator = document()->find(cursor.selectedText(), searchIterator);
241 while (searchIterator.hasSelection())
245 searchIterator = document()->find(cursor.selectedText(), searchIterator);
256 setExtraSelections(extra);
270 auto position = textCursor().position();
272 if (pair.first == currentSymbol)
275 counterSymbol = pair.second[0];
276 activeSymbol = currentSymbol;
278 else if (pair.second == prevSymbol)
281 counterSymbol = pair.first[0];
282 activeSymbol = prevSymbol;
292 while (counter != 0 &&
294 position < (document()->characterCount() - 1))
297 position += direction;
299 auto character = document()->characterAt(position);
301 if (character == activeSymbol)
305 else if (character == counterSymbol)
316 ExtraSelection selection{};
324 selection.format =
format;
325 selection.cursor = textCursor();
326 selection.cursor.clearSelection();
327 selection.cursor.movePosition(
329 QTextCursor::MoveMode::MoveAnchor,
330 std::abs(textCursor().position() - position)
333 selection.cursor.movePosition(
335 QTextCursor::MoveMode::KeepAnchor,
339 extraSelection.append(selection);
341 selection.cursor = textCursor();
342 selection.cursor.clearSelection();
343 selection.cursor.movePosition(
345 QTextCursor::MoveMode::KeepAnchor,
349 extraSelection.append(selection);
360 QTextEdit::ExtraSelection selection{};
363 selection.format.setForeground(QBrush());
364 selection.format.setProperty(QTextFormat::FullWidthSelection,
true);
365 selection.cursor = textCursor();
366 selection.cursor.clearSelection();
368 extraSelection.append(selection);
375 QTextEdit::paintEvent(e);
386 QTextCursor curs = QTextCursor(document());
387 curs.movePosition(QTextCursor::Start);
388 for(
int i=0; i < document()->blockCount(); ++i)
390 QTextBlock
block = curs.block();
392 QRect r1 = viewport()->geometry();
393 QRect r2 = document()
395 ->blockBoundingRect(
block)
397 viewport()->geometry().
x(),
398 viewport()->geometry().
y() - verticalScrollBar()->sliderPosition()
401 if (r1.intersects(r2))
406 curs.movePosition(QTextCursor::NextBlock);
423 case Qt::Key_Backtab:
432 auto isShortcut = ((e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_Space);
440 auto ctrlOrShift = e->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier);
443 (ctrlOrShift && e->text().isEmpty()) ||
444 e->key() == Qt::Key_Delete)
449 static QString eow(R
"(~!@#$%^&*()_+{}|:"<>?,./;'[]\-=)");
451 auto isShortcut = ((e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_Space);
455 (e->text().isEmpty() ||
456 completionPrefix.length() < 2 ||
457 eow.contains(e->text().right(1))))
463 if (completionPrefix !=
m_completer->completionPrefix())
465 m_completer->setCompletionPrefix(completionPrefix);
469 auto cursRect = cursorRect();
472 m_completer->popup()->verticalScrollBar()->sizeHint().width()
479 #if QT_VERSION >= 0x050A00
480 const int defaultIndent = tabStopDistance() / fontMetrics().averageCharWidth();
482 const int defaultIndent = tabStopWidth() / fontMetrics().averageCharWidth();
487 if (!completerSkip) {
489 e->modifiers() == Qt::NoModifier) {
497 #if QT_VERSION >= 0x050A00
499 indentationLevel * fontMetrics().averageCharWidth() / tabStopDistance();
502 indentationLevel * fontMetrics().averageCharWidth() / tabStopWidth();
508 (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) &&
512 insertPlainText(
"\n");
515 insertPlainText(QString(indentationLevel + defaultIndent,
' '));
517 insertPlainText(QString(tabCounts + 1,
'\t'));
519 insertPlainText(
"\n");
524 insertPlainText(QString(indentationLevel,
' '));
525 charsBack += indentationLevel;
529 insertPlainText(QString(tabCounts,
'\t'));
530 charsBack += tabCounts;
540 indentationLevel = std::min(indentationLevel,
m_tabReplace.size());
542 auto cursor = textCursor();
544 cursor.movePosition(QTextCursor::MoveOperation::StartOfLine);
546 QTextCursor::MoveMode::KeepAnchor, indentationLevel);
548 cursor.removeSelectedText();
552 QTextEdit::keyPressEvent(e);
554 if (
m_autoIndentation && (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter)) {
556 insertPlainText(QString(indentationLevel,
' '));
558 insertPlainText(QString(tabCounts,
'\t'));
566 if (el.first == e->text())
568 insertPlainText(el.second);
574 if (el.second == e->text())
578 if (symbol == el.second)
580 textCursor().deletePreviousChar();
650 m_completer->setCompletionMode(QCompleter::CompletionMode::PopupCompletion);
654 QOverload<const QString&>::of(&QCompleter::activated),
667 QTextEdit::focusInEvent(e);
677 auto tc = textCursor();
678 tc.select(QTextCursor::SelectionType::WordUnderCursor);
690 auto block = textCursor().blockNumber();
691 auto index = textCursor().positionInBlock();
692 auto text = document()->findBlockByNumber(
block).text();
696 if (index < 0 || index >=
text.size())
706 auto tc = textCursor();
707 tc.select(QTextCursor::WordUnderCursor);
708 return tc.selectedText();
713 insertPlainText(
source->text());
718 auto blockText = textCursor().block().text();
720 int indentationLevel = 0;
723 i < blockText.size() && QString(
"\t ").contains(blockText[i]);
726 if (blockText[i] ==
' ')
732 #if QT_VERSION >= 0x050A00
733 indentationLevel += tabStopDistance() / fontMetrics().averageCharWidth();
735 indentationLevel += tabStopWidth() / fontMetrics().averageCharWidth();
740 return indentationLevel;