34 : QSyntaxHighlighter(parent)
35 , m_markCaseSensitivity(Qt::CaseInsensitive)
242 QList<int> bracketPositions;
244 int blockState = previousBlockState();
245 int bracketLevel = blockState >> 4;
246 int state = blockState & 15;
247 if (blockState < 0) {
254 while (i <= text.length()) {
255 QChar ch = (i < text.length()) ? text.at(i) : QChar();
256 QChar next = (i < text.length() - 1) ? text.at(i + 1) : QChar();
264 }
else if (ch.isDigit()) {
267 }
else if (ch.isLetter() || ch ==
'_') {
270 }
else if (ch ==
'\'' || ch ==
'\"') {
273 }
else if (ch ==
'/' && next ==
'*') {
277 }
else if (ch ==
'/' && next ==
'/') {
280 }
else if (ch ==
'/' && next !=
'*') {
284 if (!QString(
"(){}[]").contains(ch))
286 if (ch ==
'{' || ch ==
'}') {
287 bracketPositions += i;
299 if (ch.isSpace() || !ch.isDigit()) {
308 if (ch.isSpace() || !(ch.isDigit() || ch.isLetter() || ch ==
'_')) {
309 QString token = text.mid(start, i - start).trimmed();
321 if (ch == text.at(start)) {
322 QChar prev = (i > 0) ? text.at(i - 1) : QChar();
336 if (ch ==
'*' && next ==
'/') {
348 QChar prev = (i > 0) ? text.at(i - 1) : QChar();
367 if (state == Comment)
375 QTextCharFormat markerFormat;
382 setFormat(pos, len, markerFormat);
387 if (!bracketPositions.isEmpty()) {
391 currentBlock().setUserData(blockData);
396 blockState = (state & 15) | (bracketLevel << 4);
397 setCurrentBlockState(blockState);
447 , foldIndicatorWidth(0)
460 int fh = fontMetrics().lineSpacing();
461 int ys =
event->pos().y();
462 if (event->pos().x() > xofs) {
471 JSEdit *editor = qobject_cast<JSEdit*>(parent());
484 int fh = QFontMetrics(
font).height();
494 QPainter iconPainter;
502 polygon << QPointF(dim * 0.4, dim * 0.25);
503 polygon << QPointF(dim * 0.4, dim * 0.75);
504 polygon << QPointF(dim * 0.8, dim * 0.5);
506 iconPainter.setRenderHint(QPainter::Antialiasing);
507 iconPainter.setPen(Qt::NoPen);
509 iconPainter.drawPolygon(polygon);
513 polygon << QPointF(dim * 0.25, dim * 0.4);
514 polygon << QPointF(dim * 0.75, dim * 0.4);
515 polygon << QPointF(dim * 0.5, dim * 0.8);
517 iconPainter.setRenderHint(QPainter::Antialiasing);
518 iconPainter.setPen(Qt::NoPen);
520 iconPainter.drawPolygon(polygon);
536 QTextBlock block = doc->findBlock(cursorPosition);
540 while (block.isValid()) {
541 blockData =
reinterpret_cast<JSBlockData*
>(block.userData());
545 if (absPos <= cursorPosition)
547 if (doc->characterAt(absPos) ==
'{')
555 block = block.next();
563 QTextBlock block = doc->findBlock(cursorPosition);
567 while (block.isValid()) {
568 blockData =
reinterpret_cast<JSBlockData*
>(block.userData());
572 if (absPos >= cursorPosition - 1)
574 if (doc->characterAt(absPos) ==
'}')
582 block = block.previous();
596 : QPlainTextDocumentLayout(doc)
602 emit documentSizeChanged(documentSize());
624 : QPlainTextEdit(parent)
627 d_ptr->editor =
this;
631 d_ptr->showLineNumbers =
true;
632 d_ptr->textWrap =
true;
633 d_ptr->bracketsMatching =
true;
634 d_ptr->cursorColor = QColor(255, 255, 192);
635 d_ptr->bracketMatchColor = QColor(180, 238, 180);
636 d_ptr->bracketErrorColor = QColor(224, 128, 128);
637 d_ptr->codeFolding =
true;
639 document()->setDocumentLayout(
d_ptr->layout);
641 connect(
this, SIGNAL(cursorPositionChanged()),
this, SLOT(
updateCursor()));
642 connect(
this, SIGNAL(blockCountChanged(
int)),
this, SLOT(
updateSidebar()));
643 connect(
this, SIGNAL(updateRequest(QRect,
int)),
this, SLOT(
updateSidebar(QRect,
int)));
645 #if defined(Q_OS_MAC)
646 QFont textFont = font();
647 textFont.setPointSize(12);
648 textFont.setFamily(
"Monaco");
650 #elif defined(Q_OS_UNIX)
651 QFont textFont = font();
652 textFont.setFamily(
"Monospace");
659 delete d_ptr->layout;
667 QPalette pal = palette();
668 pal.setColor(QPalette::Base, color);
670 d->sidebar->indicatorColor = color;
672 }
else if (component ==
Normal) {
673 QPalette pal = palette();
674 pal.setColor(QPalette::Text, color);
676 }
else if (component ==
Sidebar) {
677 d->sidebar->backgroundColor = color;
680 d->sidebar->lineNumberColor = color;
682 }
else if (component ==
Cursor) {
683 d->cursorColor = color;
686 d->bracketMatchColor = color;
689 d->bracketErrorColor = color;
692 d->sidebar->foldIndicatorColor = color;
695 d->highlighter->setColor(component, color);
702 return d_ptr->highlighter->keywords();
712 return d_ptr->showLineNumbers;
717 d_ptr->showLineNumbers = visible;
723 return d_ptr->textWrap;
728 d_ptr->textWrap = enable;
729 setLineWrapMode(enable ? WidgetWidth : NoWrap);
734 return d_ptr->bracketsMatching;
739 d_ptr->bracketsMatching = enable;
745 return d_ptr->codeFolding;
750 d_ptr->codeFolding = enable;
756 if (!block.isValid())
763 const QTextDocument *doc = block.document();
764 int offset = block.position();
766 int absPos = offset + pos;
767 if (doc->characterAt(absPos) ==
'{') {
780 QTextBlock matchBlock = document()->findBlock(matchPos);
781 if (matchBlock.isValid() && matchBlock.blockNumber() > line)
789 QTextBlock block = document()->findBlockByNumber(line - 1);
790 if (!block.isValid())
792 block = block.next();
793 if (!block.isValid())
795 return !block.isVisible();
800 QTextBlock startBlock = document()->findBlockByNumber(line - 1);
804 QTextBlock endBlock = document()->findBlock(endPos);
806 QTextBlock block = startBlock.next();
807 while (block.isValid() && block != endBlock) {
808 block.setVisible(
false);
809 block.setLineCount(0);
810 block = block.next();
813 document()->markContentsDirty(startBlock.position(), endPos - startBlock.position() + 1);
823 QTextBlock startBlock = document()->findBlockByNumber(line - 1);
826 QTextBlock block = startBlock.next();
827 while (block.isValid() && !block.isVisible()) {
828 block.setVisible(
true);
829 block.setLineCount(block.layout()->lineCount());
830 endPos = block.position() + block.length();
831 block = block.next();
834 document()->markContentsDirty(startBlock.position(), endPos - startBlock.position() + 1);
852 QPlainTextEdit::resizeEvent(e);
858 if (e->modifiers() == Qt::ControlModifier) {
859 int steps = e->delta() / 20;
860 steps = qBound(-3, steps, 3);
861 QFont textFont = font();
862 int pointSize = textFont.pointSize() + steps;
863 pointSize = qBound(10, pointSize, 40);
864 textFont.setPointSize(pointSize);
870 QPlainTextEdit::wheelEvent(e);
879 setExtraSelections(QList<QTextEdit::ExtraSelection>());
882 d->matchPositions.clear();
883 d->errorPositions.clear();
885 if (d->bracketsMatching && textCursor().block().userData()) {
886 QTextCursor cursor = textCursor();
887 int cursorPosition = cursor.position();
889 if (document()->characterAt(cursorPosition) ==
'{') {
892 d->errorPositions += cursorPosition;
894 d->matchPositions += cursorPosition;
895 d->matchPositions += matchPos;
899 if (document()->characterAt(cursorPosition - 1) ==
'}') {
902 d->errorPositions += cursorPosition - 1;
904 d->matchPositions += cursorPosition - 1;
905 d->matchPositions += matchPos;
910 QTextEdit::ExtraSelection highlight;
911 highlight.format.setBackground(d->cursorColor);
912 highlight.format.setProperty(QTextFormat::FullWidthSelection,
true);
913 highlight.cursor = textCursor();
914 highlight.cursor.clearSelection();
916 QList<QTextEdit::ExtraSelection> extraSelections;
917 extraSelections.append(highlight);
919 for (
int i = 0; i < d->matchPositions.count(); ++i) {
920 int pos = d->matchPositions.at(i);
921 QTextEdit::ExtraSelection matchHighlight;
922 matchHighlight.format.setBackground(d->bracketMatchColor);
923 matchHighlight.cursor = textCursor();
924 matchHighlight.cursor.setPosition(pos);
925 matchHighlight.cursor.setPosition(pos + 1, QTextCursor::KeepAnchor);
926 extraSelections.append(matchHighlight);
929 for (
int i = 0; i < d->errorPositions.count(); ++i) {
930 int pos = d->errorPositions.at(i);
931 QTextEdit::ExtraSelection errorHighlight;
932 errorHighlight.format.setBackground(d->bracketErrorColor);
933 errorHighlight.cursor = textCursor();
934 errorHighlight.cursor.setPosition(pos);
935 errorHighlight.cursor.setPosition(pos + 1, QTextCursor::KeepAnchor);
936 extraSelections.append(errorHighlight);
939 setExtraSelections(extraSelections);
954 if (!d->showLineNumbers && !d->codeFolding) {
956 setViewportMargins(0, 0, 0, 0);
957 d->sidebar->setGeometry(3, 0, 0, height());
961 d->sidebar->foldIndicatorWidth = 0;
962 d->sidebar->font = this->font();
966 if (d->showLineNumbers) {
968 int maxLines = blockCount();
969 for (
int number = 10; number < maxLines; number *= 10)
971 sw += fontMetrics().width(
'w') * digits;
973 if (d->codeFolding) {
974 int fh = fontMetrics().lineSpacing();
975 int fw = fontMetrics().width(
'w');
976 d->sidebar->foldIndicatorWidth = qMax(fw, fh);
977 sw += d->sidebar->foldIndicatorWidth;
979 setViewportMargins(sw, 0, 0, 0);
981 d->sidebar->setGeometry(0, 0, sw, height());
982 QRectF sidebarRect(0, 0, sw, height());
984 QTextBlock block = firstVisibleBlock();
986 while (block.isValid()) {
987 if (block.isVisible()) {
988 QRectF rect = blockBoundingGeometry(block).translated(contentOffset());
989 if (sidebarRect.intersects(rect)) {
990 if (d->sidebar->lineNumbers.count() >= index)
991 d->sidebar->lineNumbers.resize(index + 1);
992 d->sidebar->lineNumbers[index].position = rect.top();
993 d->sidebar->lineNumbers[index].number = block.blockNumber() + 1;
994 d->sidebar->lineNumbers[index].foldable = d->codeFolding ?
isFoldable(block.blockNumber() + 1) :
false;
995 d->sidebar->lineNumbers[index].folded = d->codeFolding ?
isFolded(block.blockNumber() + 1) :
false;
998 if (rect.top() > sidebarRect.bottom())
1001 block = block.next();
1003 d->sidebar->lineNumbers.resize(index);
1004 d->sidebar->update();
1009 d_ptr->highlighter->mark(str, sens);