| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the documentation of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:FDL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Free Documentation License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Free |
| ** Documentation License version 1.3 as published by the Free Software |
| ** Foundation and appearing in the file included in the packaging of |
| ** this file. Please review the following information to ensure |
| ** the GNU Free Documentation License version 1.3 requirements |
| ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| /*! |
| \example richtext/syntaxhighlighter |
| \title Syntax Highlighter Example |
| \ingroup examples-richtext |
| \brief The Syntax Highlighter example shows how to perform |
| simple syntax highlighting. |
| |
| \brief The Syntax Highlighter example shows how to perform simple syntax |
| highlighting by subclassing the QSyntaxHighlighter class. |
| |
| \image syntaxhighlighter-example.png |
| |
| The Syntax Highlighter application displays C++ files with custom |
| syntax highlighting. |
| |
| The example consists of two classes: |
| |
| \list |
| \li The \c Highlighter class defines and applies the |
| highlighting rules. |
| \li The \c MainWindow widget is the application's main window. |
| \endlist |
| |
| We will first review the \c Highlighter class to see how you can |
| customize the QSyntaxHighlighter class to fit your preferences, |
| then we will take a look at the relevant parts of the \c |
| MainWindow class to see how you can use your custom highlighter |
| class in an application. |
| |
| \section1 Highlighter Class Definition |
| |
| \snippet richtext/syntaxhighlighter/highlighter.h 0 |
| |
| To provide your own syntax highlighting, you must subclass |
| QSyntaxHighlighter, reimplement the \l |
| {QSyntaxHighlighter::highlightBlock()}{highlightBlock()} function, |
| and define your own highlighting rules. |
| |
| We have chosen to store our highlighting rules using a private |
| struct: A rule consists of a QRegularExpression pattern and a |
| QTextCharFormat instance. The various rules are then stored using a |
| QVector. |
| |
| The QTextCharFormat class provides formatting information for |
| characters in a QTextDocument specifying the visual properties of |
| the text, as well as information about its role in a hypertext |
| document. In this example, we will only define the font weight and |
| color using the QTextCharFormat::setFontWeight() and |
| QTextCharFormat::setForeground() functions. |
| |
| \section1 Highlighter Class Implementation |
| |
| When subclassing the QSyntaxHighlighter class you must pass the |
| parent parameter to the base class constructor. The parent is the |
| text document upon which the syntax highlighting will be |
| applied. In this example, we have also chosen to define our |
| highlighting rules in the constructor: |
| |
| \snippet richtext/syntaxhighlighter/highlighter.cpp 0 |
| \snippet richtext/syntaxhighlighter/highlighter.cpp 1 |
| |
| First we define a keyword rule which recognizes the most common |
| C++ keywords. We give the \c keywordFormat a bold, dark blue |
| font. For each keyword, we assign the keyword and the specified |
| format to a HighlightingRule object and append the object to our |
| list of rules. |
| |
| \snippet richtext/syntaxhighlighter/highlighter.cpp 2 |
| \codeline |
| \snippet richtext/syntaxhighlighter/highlighter.cpp 4 |
| \codeline |
| \snippet richtext/syntaxhighlighter/highlighter.cpp 5 |
| |
| Then we create a format that we will apply to Qt class names. The |
| class names will be rendered with a dark magenta color and a bold |
| style. We specify a string pattern that is actually a regular |
| expression capturing all Qt class names. Then we assign the |
| regular expression and the specified format to a HighlightingRule |
| object and append the object to our list of rules. |
| |
| We also define highlighting rules for quotations and functions |
| using the same approach: The patterns have the form of regular |
| expressions and are stored in HighlightingRule objects with the |
| associated format. |
| |
| \snippet richtext/syntaxhighlighter/highlighter.cpp 3 |
| \codeline |
| \snippet richtext/syntaxhighlighter/highlighter.cpp 6 |
| |
| The C++ language has two variations of comments: The single line |
| comment (\c //) and the multiline comment (\c{/*...*}\c{/}). The single |
| line comment can easily be defined through a highlighting rule |
| similar to the previous ones. But the multiline comment needs |
| special care due to the design of the QSyntaxHighlighter class. |
| |
| After a QSyntaxHighlighter object is created, its \l |
| {QSyntaxHighlighter::highlightBlock()}{highlightBlock()} function |
| will be called automatically whenever it is necessary by the rich |
| text engine, highlighting the given text block. The problem |
| appears when a comment spans several text blocks. We will take a |
| closer look at how this problem can be solved when reviewing the |
| implementation of the \c Highlighter::highlightBlock() |
| function. At this point we only specify the multiline comment's |
| color. |
| |
| \snippet richtext/syntaxhighlighter/highlighter.cpp 7 |
| |
| The highlightBlock() function is called automatically whenever it |
| is necessary by the rich text engine, i.e. when there are text |
| blocks that have changed. |
| |
| First we apply the syntax highlighting rules that we stored in the |
| \c highlightingRules vector. For each rule (i.e. for each |
| HighlightingRule object) we search for the pattern in the given |
| text block using the QString::indexOf() function. When the first |
| occurrence of the pattern is found, we use the |
| QRegularExpressionMatch::capturedLength() function to determine the string |
| that will be formatted. QRegularExpressionMatch::capturedLength() returns |
| the length of the last matched string, or 0 if there was no match. |
| |
| To perform the actual formatting the QSyntaxHighlighter class |
| provides the \l {QSyntaxHighlighter::setFormat()}{setFormat()} |
| function. This function operates on the text block that is passed |
| as argument to the \c highlightBlock() function. The specified |
| format is applied to the text from the given start position for |
| the given length. The formatting properties set in the given |
| format are merged at display time with the formatting information |
| stored directly in the document. Note that the document itself |
| remains unmodified by the format set through this function. |
| |
| This process is repeated until the last occurrence of the pattern |
| in the current text block is found. |
| |
| \snippet richtext/syntaxhighlighter/highlighter.cpp 8 |
| |
| To deal with constructs that can span several text blocks (like |
| the C++ multiline comment), it is necessary to know the end state |
| of the previous text block (e.g. "in comment"). Inside your \c |
| highlightBlock() implementation you can query the end state of the |
| previous text block using the |
| QSyntaxHighlighter::previousBlockState() function. After parsing |
| the block you can save the last state using |
| QSyntaxHighlighter::setCurrentBlockState(). |
| |
| The \l |
| {QSyntaxHighlighter::previousBlockState()}{previousBlockState()} |
| function return an int value. If no state is set, the returned |
| value is -1. You can designate any other value to identify any |
| given state using the \l |
| {QSyntaxHighlighter::setCurrentBlockState()}{setCurrentBlockState()} |
| function. Once the state is set, the QTextBlock keeps that value |
| until it is set again or until the corresponding paragraph of text |
| is deleted. |
| |
| In this example we have chosen to use 0 to represent the "not in |
| comment" state, and 1 for the "in comment" state. When the stored |
| syntax highlighting rules are applied we initialize the current |
| block state to 0. |
| |
| \snippet richtext/syntaxhighlighter/highlighter.cpp 9 |
| |
| If the previous block state was "in comment" (\c |
| {previousBlockState() == 1}), we start the search for an end |
| expression at the beginning of the text block. If the |
| previousBlockState() returns 0, we start the search at the |
| location of the first occurrence of a start expression. |
| |
| \snippet richtext/syntaxhighlighter/highlighter.cpp 10 |
| \snippet richtext/syntaxhighlighter/highlighter.cpp 11 |
| |
| When an end expression is found, we calculate the length of the |
| comment and apply the multiline comment format. Then we search for |
| the next occurrence of the start expression and repeat the |
| process. If no end expression can be found in the current text |
| block we set the current block state to 1, i.e. "in comment". |
| |
| This completes the \c Highlighter class implementation; it is now |
| ready for use. |
| |
| \section1 MainWindow Class Definition |
| |
| Using a QSyntaxHighlighter subclass is simple; just provide your |
| application with an instance of the class and pass it the document |
| upon which you want the highlighting to be applied. |
| |
| \snippet richtext/syntaxhighlighter/mainwindow.h 0 |
| |
| In this example we declare a pointer to a \c Highlighter instance |
| which we later will initialize in the private \c setupEditor() |
| function. |
| |
| \section1 MainWindow Class Implementation |
| |
| The constructor of the main window is straight forward. We first |
| set up the menus, then we initialize the editor and make it the |
| central widget of the application. Finally we set the main |
| window's title. |
| |
| \snippet richtext/syntaxhighlighter/mainwindow.cpp 0 |
| |
| We initialize and install the \c Highlighter object in the private |
| setupEditor() convenience function: |
| |
| \snippet richtext/syntaxhighlighter/mainwindow.cpp 1 |
| |
| First we create the font we want to use in the editor, then we |
| create the editor itself which is an instance of the QTextEdit |
| class. Before we initialize the editor with the \c MainWindow |
| class definition file, we create a \c Highlighter instance passing |
| the editor's document as argument. This is the document that the |
| highlighting will be applied to. Then we are done. |
| |
| A QSyntaxHighlighter object can only be installed on one document |
| at the time, but you can easily reinstall the highlighter on |
| another document using the QSyntaxHighlighter::setDocument() |
| function. The QSyntaxHighlighter class also provides the \l |
| {QSyntaxHighlighter::document()}{document()} function which |
| returns the currently set document. |
| |
| \section1 Other Code Editor Features |
| |
| The \l{Code Editor Example} shows how to implement line |
| numbers and how to highlight the current line. |
| |
| */ |