1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the documentation of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:FDL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and Digia. For licensing terms and
14
** conditions see http://qt.digia.com/licensing. For further information
15
** use the contact form at http://qt.digia.com/contact-us.
17
** GNU Free Documentation License Usage
18
** Alternatively, this file may be used under the terms of the GNU Free
19
** Documentation License version 1.3 as published by the Free Software
20
** Foundation and appearing in the file included in the packaging of
21
** this file. Please review the following information to ensure
22
** the GNU Free Documentation License version 1.3 requirements
23
** will be met: http://www.gnu.org/copyleft/fdl.html.
26
****************************************************************************/
29
\example widgets/codeeditor
30
\title Code Editor Example
31
\ingroup examples-widgets
32
\brief The Code Editor example shows how to create a simple editor that
33
has line numbers and that highlights the current line.
35
\image codeeditor-example.png
37
As can be seen from the image, the editor displays the line
38
numbers in an area to the left of the area for editing. The editor
39
will highlight the line containing the cursor.
41
We implement the editor in \c CodeEditor, which is a widget that
42
inherits QPlainTextEdit. We keep a separate widget in \c
43
CodeEditor (\c LineNumberArea) onto which we draw the line
46
QPlainTextEdit inherits from QAbstractScrollArea, and editing
47
takes place within its \l{QAbstractScrollArea::}{viewport()}'s
48
margins. We make room for our line number area by setting the left
49
margin of the viewport to the size we need to draw the line
52
When it comes to editing code, we prefer QPlainTextEdit over
53
QTextEdit because it is optimized for handling plain text. See
54
the QPlainTextEdit class description for details.
56
QPlainTextEdit lets us add selections in addition to the
57
selection the user can make with the mouse or keyboard. We use
58
this functionality to highlight the current line. More on this
61
We will now move on to the definitions and implementations of \c
62
CodeEditor and \c LineNumberArea. Let's start with the \c
65
\section1 The LineNumberArea Class
67
We paint the line numbers on this widget, and place it over the \c
68
CodeEditor's \l{QAbstractScrollArea::}{viewport()}'s left margin
71
We need to use protected functions in QPlainTextEdit while
72
painting the area. So to keep things simple, we paint the area in
73
the \c CodeEditor class. The area also asks the editor to
74
calculate its size hint.
76
Note that we could simply paint the line numbers directly on the
77
code editor, and drop the LineNumberArea class. However, the
78
QWidget class helps us to \l{QWidget::}{scroll()} its contents.
79
Also, having a separate widget is the right choice if we wish to
80
extend the editor with breakpoints or other code editor features.
81
The widget would then help in the handling of mouse events.
83
\snippet widgets/codeeditor/codeeditor.h extraarea
85
\section1 CodeEditor Class Definition
87
Here is the code editor's class definition:
89
\snippet widgets/codeeditor/codeeditor.h codeeditordefinition
91
In the editor we resize and draw the line numbers on the \c
92
LineNumberArea. We need to do this when the number of lines in the
93
editor changes, and when the editor's viewport() is scrolled. Of
94
course, it is also done when the editor's size changes. We do
95
this in \c updateLineNumberWidth() and \c updateLineNumberArea().
97
Whenever, the cursor's position changes, we highlight the current
98
line in \c highlightCurrentLine().
100
\section1 CodeEditor Class Implementation
102
We will now go through the code editors implementation, starting
103
off with the constructor.
105
\snippet widgets/codeeditor/codeeditor.cpp constructor
107
In the constructor we connect our slots to signals in
108
QPlainTextEdit. It is necessary to calculate the line number area
109
width and highlight the first line when the editor is created.
111
\snippet widgets/codeeditor/codeeditor.cpp extraAreaWidth
113
The \c lineNumberAreaWidth() function calculates the width of the
114
\c LineNumberArea widget. We take the number of digits in the last
115
line of the editor and multiply that with the maximum width of a
118
\snippet widgets/codeeditor/codeeditor.cpp slotUpdateExtraAreaWidth
120
When we update the width of the line number area, we simply call
121
QAbstractScrollArea::setViewportMargins().
123
\snippet widgets/codeeditor/codeeditor.cpp slotUpdateRequest
125
This slot is invoked when the editors viewport has been scrolled.
126
The QRect given as argument is the part of the editing area that
127
is do be updated (redrawn). \c dy holds the number of pixels the
128
view has been scrolled vertically.
130
\snippet widgets/codeeditor/codeeditor.cpp resizeEvent
132
When the size of the editor changes, we also need to resize the
135
\snippet widgets/codeeditor/codeeditor.cpp cursorPositionChanged
137
When the cursor position changes, we highlight the current line,
138
i.e., the line containing the cursor.
140
QPlainTextEdit gives the possibility to have more than one
141
selection at the same time. we can set the character format
142
(QTextCharFormat) of these selections. We clear the cursors
143
selection before setting the new new
144
QPlainTextEdit::ExtraSelection, else several lines would get
145
highlighted when the user selects multiple lines with the mouse.
146
\omit ask someone how this works \endomit
148
One sets the selection with a text cursor. When using the
149
FullWidthSelection property, the current cursor text block (line)
150
will be selected. If you want to select just a portion of the text
151
block, the cursor should be moved with QTextCursor::movePosition()
152
from a position set with \l{QTextCursor::}{setPosition()}.
154
\snippet widgets/codeeditor/codeeditor.cpp extraAreaPaintEvent_0
156
The \c lineNumberAreaPaintEvent() is called from \c LineNumberArea
157
whenever it receives a paint event. We start off by painting the
160
\snippet widgets/codeeditor/codeeditor.cpp extraAreaPaintEvent_1
162
We will now loop through all visible lines and paint the line
163
numbers in the extra area for each line. Notice that in a plain
164
text edit each line will consist of one QTextBlock; though, if
165
line wrapping is enabled, a line may span several rows in the text
168
We get the top and bottom y-coordinate of the first text block,
169
and adjust these values by the height of the current text block in
170
each iteration in the loop.
172
\snippet widgets/codeeditor/codeeditor.cpp extraAreaPaintEvent_2
174
Notice that we check if the block is visible in addition to check
175
if it is in the areas viewport - a block can, for example, be
176
hidden by a window placed over the text edit.
178
\section1 Suggestions for Extending the Code Editor
180
No self-respecting code editor is without a syntax
181
highligther; the \l{Syntax Highlighter Example} shows how to
184
In addition to line numbers, you can add more to the extra area,
185
for instance, break points.
187
QSyntaxHighlighter gives the possibility to add user data to each
189
\l{QSyntaxHighlighter::}{setCurrentBlockUserData()}. This can be
190
used to implement parenthesis matching. In the \c
191
highlightCurrentLine(), the data of the currentBlock() can be
192
fetched with QTextBlock::userData(). Matching parentheses can be
193
highlighted with an extra selection. The "Matching Parentheses
194
with QSyntaxHighlighter" article in Qt Quarterly 31 implements
195
this. You find it here: \l{http://doc.qt.digia.com/qq/}.