Revision control

++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
++
++ /*!
++ \example richtext/syntaxhighlighter
++ \title Syntax Highlighter Example
++ \examplecategory {User Interface Components}
++ \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
++ {Text editor with syntax highlighting}
++
++ 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
++ QList.
++
++ 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 list. 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.
++ */