|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the documentation of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 /*! |
|
43 \example richtext/syntaxhighlighter |
|
44 \title Syntax Highlighter Example |
|
45 |
|
46 The Syntax Highlighter example shows how to perform simple syntax |
|
47 highlighting by subclassing the QSyntaxHighlighter class. |
|
48 |
|
49 \image syntaxhighlighter-example.png |
|
50 |
|
51 The Syntax Highlighter application displays C++ files with custom |
|
52 syntax highlighting. |
|
53 |
|
54 The example consists of two classes: |
|
55 |
|
56 \list |
|
57 \o The \c Highlighter class defines and applies the |
|
58 highlighting rules. |
|
59 \o The \c MainWindow widget is the application's main window. |
|
60 \endlist |
|
61 |
|
62 We will first review the \c Highlighter class to see how you can |
|
63 customize the QSyntaxHighlighter class to fit your preferences, |
|
64 then we will take a look at the relevant parts of the \c |
|
65 MainWindow class to see how you can use your custom highlighter |
|
66 class in an application. |
|
67 |
|
68 \section1 Highlighter Class Definition |
|
69 |
|
70 \snippet examples/richtext/syntaxhighlighter/highlighter.h 0 |
|
71 |
|
72 To provide your own syntax highlighting, you must subclass |
|
73 QSyntaxHighlighter, reimplement the \l |
|
74 {QSyntaxHighlighter::highlightBlock()}{highlightBlock()} function, |
|
75 and define your own highlighting rules. |
|
76 |
|
77 We have chosen to store our highlighting rules using a private |
|
78 struct: A rule consists of a QRegExp pattern and a QTextCharFormat |
|
79 instance. The various rules are then stored using a QVector. |
|
80 |
|
81 The QTextCharFormat class provides formatting information for |
|
82 characters in a QTextDocument specifying the visual properties of |
|
83 the text, as well as information about its role in a hypertext |
|
84 document. In this example, we will only define the font weight and |
|
85 color using the QTextCharFormat::setFontWeight() and |
|
86 QTextCharFormat::setForeground() functions. |
|
87 |
|
88 \section1 Highlighter Class Implementation |
|
89 |
|
90 When subclassing the QSyntaxHighlighter class you must pass the |
|
91 parent parameter to the base class constructor. The parent is the |
|
92 text document upon which the syntax highligning will be |
|
93 applied. In this example, we have also chosen to define our |
|
94 highlighting rules in the constructor: |
|
95 |
|
96 \snippet examples/richtext/syntaxhighlighter/highlighter.cpp 0 |
|
97 \snippet examples/richtext/syntaxhighlighter/highlighter.cpp 1 |
|
98 |
|
99 First we define a keyword rule which recognizes the most common |
|
100 C++ keywords. We give the \c keywordFormat a bold, dark blue |
|
101 font. For each keyword, we assign the keyword and the specified |
|
102 format to a HighlightingRule object and append the object to our |
|
103 list of rules. |
|
104 |
|
105 \snippet examples/richtext/syntaxhighlighter/highlighter.cpp 2 |
|
106 \codeline |
|
107 \snippet examples/richtext/syntaxhighlighter/highlighter.cpp 4 |
|
108 \codeline |
|
109 \snippet examples/richtext/syntaxhighlighter/highlighter.cpp 5 |
|
110 |
|
111 Then we create a format that we will apply to Qt class names. The |
|
112 class names will be rendered with a dark magenta color and a bold |
|
113 style. We specify a string pattern that is actually a regular |
|
114 expression capturing all Qt class names. Then we assign the |
|
115 regular expression and the specified format to a HighlightingRule |
|
116 object and append the object to our list of rules. |
|
117 |
|
118 We also define highlighting rules for quotations and functions |
|
119 using the same approach: The patterns have the form of regular |
|
120 expressions and are stored in HighlightingRule objects with the |
|
121 associated format. |
|
122 |
|
123 \snippet examples/richtext/syntaxhighlighter/highlighter.cpp 3 |
|
124 \codeline |
|
125 \snippet examples/richtext/syntaxhighlighter/highlighter.cpp 6 |
|
126 |
|
127 The C++ language has two variations of comments: The single line |
|
128 comment (\c //) and the multiline comment (\c{/*...}\starslash). The single |
|
129 line comment can easily be defined through a highlighting rule |
|
130 similar to the previous ones. But the multiline comment needs |
|
131 special care due to the design of the QSyntaxHighlighter class. |
|
132 |
|
133 After a QSyntaxHighlighter object is created, its \l |
|
134 {QSyntaxHighlighter::highlightBlock()}{highlightBlock()} function |
|
135 will be called automatically whenever it is necessary by the rich |
|
136 text engine, highlighting the given text block. The problem |
|
137 appears when a comment spans several text blocks. We will take a |
|
138 closer look at how this problem can be solved when reviewing the |
|
139 implementation of the \c Highlighter::highlightBlock() |
|
140 function. At this point we only specify the multiline comment's |
|
141 color. |
|
142 |
|
143 \snippet examples/richtext/syntaxhighlighter/highlighter.cpp 7 |
|
144 |
|
145 The highlightBlock() function is called automatically whenever it |
|
146 is necessary by the rich text engine, i.e. when there are text |
|
147 blocks that have changed. |
|
148 |
|
149 First we apply the syntax highlighting rules that we stored in the |
|
150 \c highlightingRules vector. For each rule (i.e. for each |
|
151 HighlightingRule object) we search for the pattern in the given |
|
152 textblock using the QString::indexOf() function. When the first |
|
153 occurrence of the pattern is found, we use the |
|
154 QRegExp::matchedLength() function to determine the string that |
|
155 will be formatted. QRegExp::matchedLength() returns the length of |
|
156 the last matched string, or -1 if there was no match. |
|
157 |
|
158 To perform the actual formatting the QSyntaxHighlighter class |
|
159 provides the \l {QSyntaxHighlighter::setFormat()}{setFormat()} |
|
160 function. This function operates on the text block that is passed |
|
161 as argument to the \c highlightBlock() function. The specified |
|
162 format is applied to the text from the given start position for |
|
163 the given length. The formatting properties set in the given |
|
164 format are merged at display time with the formatting information |
|
165 stored directly in the document. Note that the document itself |
|
166 remains unmodified by the format set through this function. |
|
167 |
|
168 This process is repeated until the last occurrence of the pattern |
|
169 in the current text block is found. |
|
170 |
|
171 \snippet examples/richtext/syntaxhighlighter/highlighter.cpp 8 |
|
172 |
|
173 To deal with constructs that can span several text blocks (like |
|
174 the C++ multiline comment), it is necessary to know the end state |
|
175 of the previous text block (e.g. "in comment"). Inside your \c |
|
176 highlightBlock() implementation you can query the end state of the |
|
177 previous text block using the |
|
178 QSyntaxHighlighter::previousBlockState() function. After parsing |
|
179 the block you can save the last state using |
|
180 QSyntaxHighlighter::setCurrentBlockState(). |
|
181 |
|
182 The \l |
|
183 {QSyntaxHighlighter::previousBlockState()}{previousBlockState()} |
|
184 function return an int value. If no state is set, the returned |
|
185 value is -1. You can designate any other value to identify any |
|
186 given state using the \l |
|
187 {QSyntaxHighlighter::setCurrentBlockState()}{setCurrentBlockState()} |
|
188 function. Once the state is set, the QTextBlock keeps that value |
|
189 until it is set again or until the corresponding paragraph of text |
|
190 is deleted. |
|
191 |
|
192 In this example we have chosen to use 0 to represent the "not in |
|
193 comment" state, and 1 for the "in comment" state. When the stored |
|
194 syntax highlighting rules are applied we initialize the current |
|
195 block state to 0. |
|
196 |
|
197 \snippet examples/richtext/syntaxhighlighter/highlighter.cpp 9 |
|
198 |
|
199 If the previous block state was "in comment" (\c |
|
200 {previousBlockState() == 1}), we start the search for an end |
|
201 expression at the beginning of the text block. If the |
|
202 previousBlockState() returns 0, we start the search at the |
|
203 location of the first occurrence of a start expression. |
|
204 |
|
205 \snippet examples/richtext/syntaxhighlighter/highlighter.cpp 10 |
|
206 \snippet examples/richtext/syntaxhighlighter/highlighter.cpp 11 |
|
207 |
|
208 When an end expression is found, we calculate the length of the |
|
209 comment and apply the multiline comment format. Then we search for |
|
210 the next occurrence of the start expression and repeat the |
|
211 process. If no end expression can be found in the current text |
|
212 block we set the current block state to 1, i.e. "in comment". |
|
213 |
|
214 This completes the \c Highlighter class implementation; it is now |
|
215 ready for use. |
|
216 |
|
217 \section1 MainWindow Class Definition |
|
218 |
|
219 Using a QSyntaxHighlighter subclass is simple; just provide your |
|
220 application with an instance of the class and pass it the document |
|
221 upon which you want the highlighting to be applied. |
|
222 |
|
223 \snippet examples/richtext/syntaxhighlighter/mainwindow.h 0 |
|
224 |
|
225 In this example we declare a pointer to a \c Highlighter instance |
|
226 which we later will initialize in the private \c setupEditor() |
|
227 function. |
|
228 |
|
229 \section1 MainWindow Class Implementation |
|
230 |
|
231 The constructor of the main window is straight forward. We first |
|
232 set up the menus, then we initialize the editor and make it the |
|
233 central widget of the application. Finally we set the main |
|
234 window's title. |
|
235 |
|
236 \snippet examples/richtext/syntaxhighlighter/mainwindow.cpp 0 |
|
237 |
|
238 We initialize and install the \c Highlighter object in the private |
|
239 setupEditor() convenience function: |
|
240 |
|
241 \snippet examples/richtext/syntaxhighlighter/mainwindow.cpp 1 |
|
242 |
|
243 First we create the font we want to use in the editor, then we |
|
244 create the editor itself which is an instance of the QTextEdit |
|
245 class. Before we initialize the editor with the \c MainWindow |
|
246 class definition file, we create a \c Highlighter instance passing |
|
247 the editor's document as argument. This is the document that the |
|
248 highlighting will be applied to. Then we are done. |
|
249 |
|
250 A QSyntaxHighlighter object can only be installed on one document |
|
251 at the time, but you can easily reinstall the highlighter on |
|
252 another document using the QSyntaxHighlighter::setDocument() |
|
253 function. The QSyntaxHighlighter class also provides the \l |
|
254 {QSyntaxHighlighter::document()}{document()} function which |
|
255 returns the currently set document. |
|
256 */ |