2 This file is part of the Ofi Labs X2 project.
4 Copyright (C) 2010 Ariya Hidayat <ariya.hidayat@gmail.com>
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 * Neither the name of the <organization> nor the
15 names of its contributors may be used to endorse or promote products
16 derived from this software without specific prior written permission.
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 class GLSLBlockData: public QTextBlockUserData
37 QList<int> bracketPositions;
40 class GLSLHighlighter : public QSyntaxHighlighter
43 GLSLHighlighter(QTextDocument *parent = 0);
44 void setColor(GLSLEdit::ColorComponent component, const QColor &color);
45 void mark(const QString &str, Qt::CaseSensitivity caseSensitivity);
48 void highlightBlock(const QString &text);
51 QSet<QString> m_keywords;
52 QSet<QString> m_types;
53 QSet<QString> m_builtins;
54 QHash<GLSLEdit::ColorComponent, QColor> m_colors;
56 Qt::CaseSensitivity m_markCaseSensitivity;
59 GLSLHighlighter::GLSLHighlighter(QTextDocument *parent)
60 : QSyntaxHighlighter(parent)
61 , m_markCaseSensitivity(Qt::CaseInsensitive)
63 // default color scheme
64 m_colors[GLSLEdit::Normal] = QColor("#000000");
65 m_colors[GLSLEdit::Comment] = QColor("#808080");
66 m_colors[GLSLEdit::Number] = QColor("#008000");
67 m_colors[GLSLEdit::String] = QColor("#800000");
68 m_colors[GLSLEdit::Operator] = QColor("#808000");
69 m_colors[GLSLEdit::Identifier] = QColor("#000020");
70 m_colors[GLSLEdit::Keyword] = QColor("#000080");
71 m_colors[GLSLEdit::BuiltIn] = QColor("#008080");
72 m_colors[GLSLEdit::Marker] = QColor("#ffff00");
74 m_keywords << "attribute";
75 m_keywords << "const";
76 m_keywords << "uniform";
77 m_keywords << "varying";
78 m_keywords << "layout";
79 m_keywords << "centroid";
81 m_keywords << "smooth";
82 m_keywords << "noperspective";
83 m_keywords << "patch";
84 m_keywords << "sample";
85 m_keywords << "break";
86 m_keywords << "continue";
89 m_keywords << "while";
90 m_keywords << "switch";
92 m_keywords << "default";
95 m_keywords << "subroutine";
98 m_keywords << "inout";
100 m_keywords << "false";
101 m_keywords << "invariant";
102 m_keywords << "discard";
103 m_keywords << "return";
104 m_keywords << "lowp";
105 m_keywords << "mediump";
106 m_keywords << "highp";
107 m_keywords << "precision";
108 m_keywords << "struct";
124 m_types << "dmat2x2";
125 m_types << "dmat2x3";
126 m_types << "dmat2x4";
130 m_types << "dmat3x2";
131 m_types << "dmat3x3";
132 m_types << "dmat3x4";
136 m_types << "dmat4x2";
137 m_types << "dmat4x3";
138 m_types << "dmat4x4";
155 m_types << "sampler1D";
156 m_types << "sampler2D";
157 m_types << "sampler3D";
158 m_types << "samplerCube";
159 m_types << "sampler1DShadow";
160 m_types << "sampler2DShadow";
161 m_types << "samplerCubeShadow";
162 m_types << "sampler1DArray";
163 m_types << "sampler2DArray";
164 m_types << "sampler1DArrayShadow";
165 m_types << "sampler2DArrayShadow";
166 m_types << "isampler1D";
167 m_types << "isampler2D";
168 m_types << "isampler3D";
169 m_types << "isamplerCube";
170 m_types << "isampler1DArray";
171 m_types << "isampler2DArray";
172 m_types << "usampler1D";
173 m_types << "usampler2D";
174 m_types << "usampler3D";
175 m_types << "usamplerCube";
176 m_types << "usampler1DArray";
177 m_types << "usampler2DArray";
178 m_types << "sampler2DRect";
179 m_types << "sampler2DRectShadow";
180 m_types << "isampler2DRect";
181 m_types << "usampler2DRect";
182 m_types << "samplerBuffer";
183 m_types << "isamplerBuffer";
184 m_types << "usamplerBuffer";
185 m_types << "sampler2DMS";
186 m_types << "isampler2DMS";
187 m_types << "usampler2DMS";
188 m_types << "sampler2DMSArray";
189 m_types << "isampler2DMSArray";
190 m_types << "usampler2DMSArray";
191 m_types << "samplerCubeArray";
192 m_types << "samplerCubeArrayShadow";
193 m_types << "isamplerCubeArray";
194 m_types << "usamplerCubeArray";
197 void GLSLHighlighter::setColor(GLSLEdit::ColorComponent component, const QColor &color)
199 m_colors[component] = color;
203 void GLSLHighlighter::highlightBlock(const QString &text)
215 QList<int> bracketPositions;
217 int blockState = previousBlockState();
218 int bracketLevel = blockState >> 4;
219 int state = blockState & 15;
220 if (blockState < 0) {
227 while (i <= text.length()) {
228 QChar ch = (i < text.length()) ? text.at(i) : QChar();
229 QChar next = (i < text.length() - 1) ? text.at(i + 1) : QChar();
237 } else if (ch.isDigit()) {
240 } else if (ch.isLetter() || ch == '_') {
243 } else if (ch == '\'' || ch == '\"') {
246 } else if (ch == '/' && next == '*') {
250 } else if (ch == '/' && next == '/') {
252 setFormat(start, text.length(), m_colors[GLSLEdit::Comment]);
253 } else if (ch == '/' && next != '*') {
257 if (!QString("(){}[]").contains(ch))
258 setFormat(start, 1, m_colors[GLSLEdit::Operator]);
259 if (ch =='{' || ch == '}') {
260 bracketPositions += i;
272 if (ch.isSpace() || !ch.isDigit()) {
273 setFormat(start, i - start, m_colors[GLSLEdit::Number]);
281 if (ch.isSpace() || !(ch.isDigit() || ch.isLetter() || ch == '_')) {
282 QString token = text.mid(start, i - start).trimmed();
283 if (m_keywords.contains(token))
284 setFormat(start, i - start, m_colors[GLSLEdit::Keyword]);
285 else if (m_types.contains(token) || m_builtins.contains(token))
286 setFormat(start, i - start, m_colors[GLSLEdit::BuiltIn]);
294 if (ch == text.at(start)) {
295 QChar prev = (i > 0) ? text.at(i - 1) : QChar();
298 setFormat(start, i - start, m_colors[GLSLEdit::String]);
309 if (ch == '*' && next == '/') {
312 setFormat(start, i - start, m_colors[GLSLEdit::Comment]);
321 QChar prev = (i > 0) ? text.at(i - 1) : QChar();
324 setFormat(start, i - start, m_colors[GLSLEdit::String]);
340 if (state == Comment)
341 setFormat(start, text.length(), m_colors[GLSLEdit::Comment]);
345 if (!m_markString.isEmpty()) {
347 int len = m_markString.length();
348 QTextCharFormat markerFormat;
349 markerFormat.setBackground(m_colors[GLSLEdit::Marker]);
350 markerFormat.setForeground(m_colors[GLSLEdit::Normal]);
352 pos = text.indexOf(m_markString, pos, m_markCaseSensitivity);
355 setFormat(pos, len, markerFormat);
360 if (!bracketPositions.isEmpty()) {
361 GLSLBlockData *blockData = reinterpret_cast<GLSLBlockData*>(currentBlock().userData());
363 blockData = new GLSLBlockData;
364 currentBlock().setUserData(blockData);
366 blockData->bracketPositions = bracketPositions;
369 blockState = (state & 15) | (bracketLevel << 4);
370 setCurrentBlockState(blockState);
373 void GLSLHighlighter::mark(const QString &str, Qt::CaseSensitivity caseSensitivity)
376 m_markCaseSensitivity = caseSensitivity;
387 Q_DECLARE_TYPEINFO(BlockInfo, Q_PRIMITIVE_TYPE);
389 class SidebarWidget : public QWidget
392 SidebarWidget(GLSLEdit *editor);
393 QVector<BlockInfo> lineNumbers;
394 QColor backgroundColor;
395 QColor lineNumberColor;
396 QColor indicatorColor;
397 QColor foldIndicatorColor;
399 int foldIndicatorWidth;
400 QPixmap rightArrowIcon;
401 QPixmap downArrowIcon;
403 void mousePressEvent(QMouseEvent *event);
404 void paintEvent(QPaintEvent *event);
407 SidebarWidget::SidebarWidget(GLSLEdit *editor)
409 , foldIndicatorWidth(0)
411 backgroundColor = Qt::lightGray;
412 lineNumberColor = Qt::black;
413 indicatorColor = Qt::white;
414 foldIndicatorColor = Qt::lightGray;
417 void SidebarWidget::mousePressEvent(QMouseEvent *event)
419 if (foldIndicatorWidth > 0) {
420 int xofs = width() - foldIndicatorWidth;
422 int fh = fontMetrics().lineSpacing();
423 int ys = event->pos().y();
424 if (event->pos().x() > xofs) {
425 foreach (BlockInfo ln, lineNumbers)
426 if (ln.position < ys && (ln.position + fh) > ys) {
433 GLSLEdit *editor = qobject_cast<GLSLEdit*>(parent());
435 editor->toggleFold(lineNo);
440 void SidebarWidget::paintEvent(QPaintEvent *event)
443 p.fillRect(event->rect(), backgroundColor);
444 p.setPen(lineNumberColor);
446 int fh = QFontMetrics(font).height();
447 foreach (BlockInfo ln, lineNumbers)
448 p.drawText(0, ln.position, width() - 4 - foldIndicatorWidth, fh, Qt::AlignRight, QString::number(ln.number));
450 if (foldIndicatorWidth > 0) {
451 int xofs = width() - foldIndicatorWidth;
452 p.fillRect(xofs, 0, foldIndicatorWidth, height(), indicatorColor);
454 // initialize (or recreate) the arrow icons whenever necessary
455 if (foldIndicatorWidth != rightArrowIcon.width()) {
456 QPainter iconPainter;
459 int dim = foldIndicatorWidth;
460 rightArrowIcon = QPixmap(dim, dim);
461 rightArrowIcon.fill(Qt::transparent);
462 downArrowIcon = rightArrowIcon;
464 polygon << QPointF(dim * 0.4, dim * 0.25);
465 polygon << QPointF(dim * 0.4, dim * 0.75);
466 polygon << QPointF(dim * 0.8, dim * 0.5);
467 iconPainter.begin(&rightArrowIcon);
468 iconPainter.setRenderHint(QPainter::Antialiasing);
469 iconPainter.setPen(Qt::NoPen);
470 iconPainter.setBrush(foldIndicatorColor);
471 iconPainter.drawPolygon(polygon);
475 polygon << QPointF(dim * 0.25, dim * 0.4);
476 polygon << QPointF(dim * 0.75, dim * 0.4);
477 polygon << QPointF(dim * 0.5, dim * 0.8);
478 iconPainter.begin(&downArrowIcon);
479 iconPainter.setRenderHint(QPainter::Antialiasing);
480 iconPainter.setPen(Qt::NoPen);
481 iconPainter.setBrush(foldIndicatorColor);
482 iconPainter.drawPolygon(polygon);
486 foreach (BlockInfo ln, lineNumbers)
489 p.drawPixmap(xofs, ln.position, rightArrowIcon);
491 p.drawPixmap(xofs, ln.position, downArrowIcon);
496 static int findClosingMatch(const QTextDocument *doc, int cursorPosition)
498 QTextBlock block = doc->findBlock(cursorPosition);
499 GLSLBlockData *blockData = reinterpret_cast<GLSLBlockData*>(block.userData());
500 if (!blockData->bracketPositions.isEmpty()) {
502 while (block.isValid()) {
503 blockData = reinterpret_cast<GLSLBlockData*>(block.userData());
504 if (blockData && !blockData->bracketPositions.isEmpty()) {
505 for (int c = 0; c < blockData->bracketPositions.count(); ++c) {
506 int absPos = block.position() + blockData->bracketPositions.at(c);
507 if (absPos <= cursorPosition)
509 if (doc->characterAt(absPos) == '{')
517 block = block.next();
523 static int findOpeningMatch(const QTextDocument *doc, int cursorPosition)
525 QTextBlock block = doc->findBlock(cursorPosition);
526 GLSLBlockData *blockData = reinterpret_cast<GLSLBlockData*>(block.userData());
527 if (!blockData->bracketPositions.isEmpty()) {
529 while (block.isValid()) {
530 blockData = reinterpret_cast<GLSLBlockData*>(block.userData());
531 if (blockData && !blockData->bracketPositions.isEmpty()) {
532 for (int c = blockData->bracketPositions.count() - 1; c >= 0; --c) {
533 int absPos = block.position() + blockData->bracketPositions.at(c);
534 if (absPos >= cursorPosition - 1)
536 if (doc->characterAt(absPos) == '}')
544 block = block.previous();
550 class GLSLDocLayout: public QPlainTextDocumentLayout
553 GLSLDocLayout(QTextDocument *doc);
557 GLSLDocLayout::GLSLDocLayout(QTextDocument *doc)
558 : QPlainTextDocumentLayout(doc)
562 void GLSLDocLayout::forceUpdate()
564 emit documentSizeChanged(documentSize());
567 class GLSLEditPrivate
571 GLSLDocLayout *layout;
572 GLSLHighlighter *highlighter;
573 SidebarWidget *sidebar;
574 bool showLineNumbers;
577 bool bracketsMatching;
578 QList<int> matchPositions;
579 QColor bracketMatchColor;
580 QList<int> errorPositions;
581 QColor bracketErrorColor;
582 bool codeFolding : 1;
585 GLSLEdit::GLSLEdit(QWidget *parent)
586 : QPlainTextEdit(parent)
587 , d_ptr(new GLSLEditPrivate)
589 d_ptr->editor = this;
590 d_ptr->layout = new GLSLDocLayout(document());
591 d_ptr->highlighter = new GLSLHighlighter(document());
592 d_ptr->sidebar = new SidebarWidget(this);
593 d_ptr->showLineNumbers = true;
594 d_ptr->textWrap = true;
595 d_ptr->bracketsMatching = true;
596 d_ptr->cursorColor = QColor(255, 255, 192);
597 d_ptr->bracketMatchColor = QColor(180, 238, 180);
598 d_ptr->bracketErrorColor = QColor(224, 128, 128);
599 d_ptr->codeFolding = true;
601 document()->setDocumentLayout(d_ptr->layout);
603 connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(updateCursor()));
604 connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateSidebar()));
605 connect(this, SIGNAL(updateRequest(QRect, int)), this, SLOT(updateSidebar(QRect, int)));
607 #if defined(Q_OS_MAC)
608 QFont textFont = font();
609 textFont.setPointSize(12);
610 textFont.setFamily("Monaco");
612 #elif defined(Q_OS_UNIX)
613 QFont textFont = font();
614 textFont.setFamily("Monospace");
619 GLSLEdit::~GLSLEdit()
621 delete d_ptr->layout;
624 void GLSLEdit::setColor(ColorComponent component, const QColor &color)
628 if (component == Background) {
629 QPalette pal = palette();
630 pal.setColor(QPalette::Base, color);
632 d->sidebar->indicatorColor = color;
634 } else if (component == Normal) {
635 QPalette pal = palette();
636 pal.setColor(QPalette::Text, color);
638 } else if (component == Sidebar) {
639 d->sidebar->backgroundColor = color;
641 } else if (component == LineNumber) {
642 d->sidebar->lineNumberColor = color;
644 } else if (component == Cursor) {
645 d->cursorColor = color;
647 } else if (component == BracketMatch) {
648 d->bracketMatchColor = color;
650 } else if (component == BracketError) {
651 d->bracketErrorColor = color;
653 } else if (component == FoldIndicator) {
654 d->sidebar->foldIndicatorColor = color;
657 d->highlighter->setColor(component, color);
662 bool GLSLEdit::isLineNumbersVisible() const
664 return d_ptr->showLineNumbers;
667 void GLSLEdit::setLineNumbersVisible(bool visible)
669 d_ptr->showLineNumbers = visible;
673 bool GLSLEdit::isTextWrapEnabled() const
675 return d_ptr->textWrap;
678 void GLSLEdit::setTextWrapEnabled(bool enable)
680 d_ptr->textWrap = enable;
681 setLineWrapMode(enable ? WidgetWidth : NoWrap);
684 bool GLSLEdit::isBracketsMatchingEnabled() const
686 return d_ptr->bracketsMatching;
689 void GLSLEdit::setBracketsMatchingEnabled(bool enable)
691 d_ptr->bracketsMatching = enable;
695 bool GLSLEdit::isCodeFoldingEnabled() const
697 return d_ptr->codeFolding;
700 void GLSLEdit::setCodeFoldingEnabled(bool enable)
702 d_ptr->codeFolding = enable;
706 static int findClosingConstruct(const QTextBlock &block)
708 if (!block.isValid())
710 GLSLBlockData *blockData = reinterpret_cast<GLSLBlockData*>(block.userData());
713 if (blockData->bracketPositions.isEmpty())
715 const QTextDocument *doc = block.document();
716 int offset = block.position();
717 foreach (int pos, blockData->bracketPositions) {
718 int absPos = offset + pos;
719 if (doc->characterAt(absPos) == '{') {
720 int matchPos = findClosingMatch(doc, absPos);
728 bool GLSLEdit::isFoldable(int line) const
730 int matchPos = findClosingConstruct(document()->findBlockByNumber(line - 1));
732 QTextBlock matchBlock = document()->findBlock(matchPos);
733 if (matchBlock.isValid() && matchBlock.blockNumber() > line)
739 bool GLSLEdit::isFolded(int line) const
741 QTextBlock block = document()->findBlockByNumber(line - 1);
742 if (!block.isValid())
744 block = block.next();
745 if (!block.isValid())
747 return !block.isVisible();
750 void GLSLEdit::fold(int line)
752 QTextBlock startBlock = document()->findBlockByNumber(line - 1);
753 int endPos = findClosingConstruct(startBlock);
756 QTextBlock endBlock = document()->findBlock(endPos);
758 QTextBlock block = startBlock.next();
759 while (block.isValid() && block != endBlock) {
760 block.setVisible(false);
761 block.setLineCount(0);
762 block = block.next();
765 document()->markContentsDirty(startBlock.position(), endPos - startBlock.position() + 1);
769 GLSLDocLayout *layout = reinterpret_cast<GLSLDocLayout*>(document()->documentLayout());
770 layout->forceUpdate();
773 void GLSLEdit::unfold(int line)
775 QTextBlock startBlock = document()->findBlockByNumber(line - 1);
776 int endPos = findClosingConstruct(startBlock);
778 QTextBlock block = startBlock.next();
779 while (block.isValid() && !block.isVisible()) {
780 block.setVisible(true);
781 block.setLineCount(block.layout()->lineCount());
782 endPos = block.position() + block.length();
783 block = block.next();
786 document()->markContentsDirty(startBlock.position(), endPos - startBlock.position() + 1);
790 GLSLDocLayout *layout = reinterpret_cast<GLSLDocLayout*>(document()->documentLayout());
791 layout->forceUpdate();
794 void GLSLEdit::toggleFold(int line)
802 void GLSLEdit::resizeEvent(QResizeEvent *e)
804 QPlainTextEdit::resizeEvent(e);
808 void GLSLEdit::wheelEvent(QWheelEvent *e)
810 if (e->modifiers() == Qt::ControlModifier) {
811 int steps = e->delta() / 20;
812 steps = qBound(-3, steps, 3);
813 QFont textFont = font();
814 int pointSize = textFont.pointSize() + steps;
815 pointSize = qBound(10, pointSize, 40);
816 textFont.setPointSize(pointSize);
822 QPlainTextEdit::wheelEvent(e);
826 void GLSLEdit::updateCursor()
831 setExtraSelections(QList<QTextEdit::ExtraSelection>());
834 d->matchPositions.clear();
835 d->errorPositions.clear();
837 if (d->bracketsMatching && textCursor().block().userData()) {
838 QTextCursor cursor = textCursor();
839 int cursorPosition = cursor.position();
841 if (document()->characterAt(cursorPosition) == '{') {
842 int matchPos = findClosingMatch(document(), cursorPosition);
844 d->errorPositions += cursorPosition;
846 d->matchPositions += cursorPosition;
847 d->matchPositions += matchPos;
851 if (document()->characterAt(cursorPosition - 1) == '}') {
852 int matchPos = findOpeningMatch(document(), cursorPosition);
854 d->errorPositions += cursorPosition - 1;
856 d->matchPositions += cursorPosition - 1;
857 d->matchPositions += matchPos;
862 QTextEdit::ExtraSelection highlight;
863 highlight.format.setBackground(d->cursorColor);
864 highlight.format.setProperty(QTextFormat::FullWidthSelection, true);
865 highlight.cursor = textCursor();
866 highlight.cursor.clearSelection();
868 QList<QTextEdit::ExtraSelection> extraSelections;
869 extraSelections.append(highlight);
871 for (int i = 0; i < d->matchPositions.count(); ++i) {
872 int pos = d->matchPositions.at(i);
873 QTextEdit::ExtraSelection matchHighlight;
874 matchHighlight.format.setBackground(d->bracketMatchColor);
875 matchHighlight.cursor = textCursor();
876 matchHighlight.cursor.setPosition(pos);
877 matchHighlight.cursor.setPosition(pos + 1, QTextCursor::KeepAnchor);
878 extraSelections.append(matchHighlight);
881 for (int i = 0; i < d->errorPositions.count(); ++i) {
882 int pos = d->errorPositions.at(i);
883 QTextEdit::ExtraSelection errorHighlight;
884 errorHighlight.format.setBackground(d->bracketErrorColor);
885 errorHighlight.cursor = textCursor();
886 errorHighlight.cursor.setPosition(pos);
887 errorHighlight.cursor.setPosition(pos + 1, QTextCursor::KeepAnchor);
888 extraSelections.append(errorHighlight);
891 setExtraSelections(extraSelections);
895 void GLSLEdit::updateSidebar(const QRect &rect, int d)
902 void GLSLEdit::updateSidebar()
906 if (!d->showLineNumbers && !d->codeFolding) {
908 setViewportMargins(0, 0, 0, 0);
909 d->sidebar->setGeometry(3, 0, 0, height());
913 d->sidebar->foldIndicatorWidth = 0;
914 d->sidebar->font = this->font();
918 if (d->showLineNumbers) {
920 int maxLines = blockCount();
921 for (int number = 10; number < maxLines; number *= 10)
923 sw += fontMetrics().width('w') * digits;
925 if (d->codeFolding) {
926 int fh = fontMetrics().lineSpacing();
927 int fw = fontMetrics().width('w');
928 d->sidebar->foldIndicatorWidth = qMax(fw, fh);
929 sw += d->sidebar->foldIndicatorWidth;
931 setViewportMargins(sw, 0, 0, 0);
933 d->sidebar->setGeometry(0, 0, sw, height());
934 QRectF sidebarRect(0, 0, sw, height());
936 QTextBlock block = firstVisibleBlock();
938 while (block.isValid()) {
939 if (block.isVisible()) {
940 QRectF rect = blockBoundingGeometry(block).translated(contentOffset());
941 if (sidebarRect.intersects(rect)) {
942 if (d->sidebar->lineNumbers.count() >= index)
943 d->sidebar->lineNumbers.resize(index + 1);
944 d->sidebar->lineNumbers[index].position = rect.top();
945 d->sidebar->lineNumbers[index].number = block.blockNumber() + 1;
946 d->sidebar->lineNumbers[index].foldable = d->codeFolding ? isFoldable(block.blockNumber() + 1) : false;
947 d->sidebar->lineNumbers[index].folded = d->codeFolding ? isFolded(block.blockNumber() + 1) : false;
950 if (rect.top() > sidebarRect.bottom())
953 block = block.next();
955 d->sidebar->lineNumbers.resize(index);
956 d->sidebar->update();
959 void GLSLEdit::mark(const QString &str, Qt::CaseSensitivity sens)
961 d_ptr->highlighter->mark(str, sens);
964 #include "glsledit.moc"