Developer Documentation

codeeditor.cc
1
2 /*===========================================================================*\
3 * *
4 * OpenFlipper *
5 * Copyright (c) 2001-2015, RWTH-Aachen University *
6 * Department of Computer Graphics and Multimedia *
7 * All rights reserved. *
8 * www.openflipper.org *
9 * *
10 *---------------------------------------------------------------------------*
11 * This file is part of OpenFlipper. *
12 *---------------------------------------------------------------------------*
13 * *
14 * Redistribution and use in source and binary forms, with or without *
15 * modification, are permitted provided that the following conditions *
16 * are met: *
17 * *
18 * 1. Redistributions of source code must retain the above copyright notice, *
19 * this list of conditions and the following disclaimer. *
20 * *
21 * 2. Redistributions in binary form must reproduce the above copyright *
22 * notice, this list of conditions and the following disclaimer in the *
23 * documentation and/or other materials provided with the distribution. *
24 * *
25 * 3. Neither the name of the copyright holder nor the names of its *
26 * contributors may be used to endorse or promote products derived from *
27 * this software without specific prior written permission. *
28 * *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
31 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
32 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
33 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
34 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
35 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
36 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
37 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
38 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
39 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
40 * *
41 \*===========================================================================*/
42
43
44
45
46 #include <QtWidgets>
47
48
49 #include "codeeditor.hh"
50
51
52 CodeEditorWidget::CodeEditorWidget(QWidget *parent) : QPlainTextEdit(parent) {
53 lineNumberArea = new LineNumberArea(this);
54
55 connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
56 connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
57 connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
58
59 updateLineNumberAreaWidth(0);
60 highlightCurrentLine();
61 }
62
63
64
65 int CodeEditorWidget::lineNumberAreaWidth() {
66
67 int digits = 1;
68 int max = qMax(1, blockCount());
69 while (max >= 10) {
70 max /= 10;
71 ++digits;
72 }
73
74 int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;
75
76 return space;
77 }
78
79
80
81 void CodeEditorWidget::updateLineNumberAreaWidth(int /* newBlockCount */) {
82 setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
83 }
84
85
86
87 void CodeEditorWidget::updateLineNumberArea(const QRect &rect, int dy) {
88 if (dy)
89 lineNumberArea->scroll(0, dy);
90 else
91 lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());
92
93 if (rect.contains(viewport()->rect()))
94 updateLineNumberAreaWidth(0);
95 }
96
97
98
99 void CodeEditorWidget::resizeEvent(QResizeEvent *e) {
100 QPlainTextEdit::resizeEvent(e);
101
102 QRect cr = contentsRect();
103 lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
104 }
105
106
107
108 void CodeEditorWidget::highlightCurrentLine() {
109 QList<QTextEdit::ExtraSelection> extraSelections;
110
111 if (!isReadOnly()) {
112 QTextEdit::ExtraSelection selection;
113
114 QColor lineColor = QColor(Qt::yellow).lighter(160);
115
116 selection.format.setBackground(lineColor);
117 selection.format.setProperty(QTextFormat::FullWidthSelection, true);
118 selection.cursor = textCursor();
119 selection.cursor.clearSelection();
120 extraSelections.append(selection);
121 }
122
123 setExtraSelections(extraSelections);
124 }
125
126 void CodeEditorWidget::highLightErrorLine(int _line) {
127 QList<QTextEdit::ExtraSelection> extraSelections;
128
129 if (!isReadOnly()) {
130 QTextEdit::ExtraSelection selection;
131
132 QColor lineColor = QColor(Qt::red).lighter(160);
133
134 selection.format.setBackground(lineColor);
135 selection.format.setProperty(QTextFormat::FullWidthSelection, true);
136 selection.cursor = QTextCursor(document());
137 selection.cursor.movePosition ( QTextCursor::Down, QTextCursor::MoveAnchor, _line - 1 );
138 selection.cursor.clearSelection();
139 extraSelections.append(selection);
140 }
141
142 setExtraSelections(extraSelections);
143 }
144
145
146 void CodeEditorWidget::lineNumberAreaPaintEvent(QPaintEvent *event) {
147
148 QPainter painter(lineNumberArea);
149 painter.fillRect(event->rect(), Qt::lightGray);
150
151
152 QTextBlock block = firstVisibleBlock();
153 int blockNumber = block.blockNumber();
154 int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
155 int bottom = top + (int) blockBoundingRect(block).height();
156
157 while (block.isValid() && top <= event->rect().bottom()) {
158 if (block.isVisible() && bottom >= event->rect().top()) {
159 QString number = QString::number(blockNumber + 1);
160 painter.setPen(Qt::black);
161 painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),Qt::AlignRight, number);
162 }
163
164 block = block.next();
165 top = bottom;
166 bottom = top + (int) blockBoundingRect(block).height();
167 ++blockNumber;
168 }
169
170 }
LineNumberArea
Definition: codeeditor.hh:84