| /**************************************************************************** |
| ** |
| ** 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 widgets/codeeditor |
| \title Code Editor Example |
| \ingroup examples-widgets |
| \brief The Code Editor example shows how to create a simple editor that |
| has line numbers and that highlights the current line. |
| |
| \borderedimage codeeditor-example.png |
| |
| As can be seen from the image, the editor displays the line |
| numbers in an area to the left of the area for editing. The editor |
| will highlight the line containing the cursor. |
| |
| We implement the editor in \c CodeEditor, which is a widget that |
| inherits QPlainTextEdit. We keep a separate widget in \c |
| CodeEditor (\c LineNumberArea) onto which we draw the line |
| numbers. |
| |
| QPlainTextEdit inherits from QAbstractScrollArea, and editing |
| takes place within its \l{QAbstractScrollArea::}{viewport()}'s |
| margins. We make room for our line number area by setting the left |
| margin of the viewport to the size we need to draw the line |
| numbers. |
| |
| When it comes to editing code, we prefer QPlainTextEdit over |
| QTextEdit because it is optimized for handling plain text. See |
| the QPlainTextEdit class description for details. |
| |
| QPlainTextEdit lets us add selections in addition to the |
| selection the user can make with the mouse or keyboard. We use |
| this functionality to highlight the current line. More on this |
| later. |
| |
| We will now move on to the definitions and implementations of \c |
| CodeEditor and \c LineNumberArea. Let's start with the \c |
| LineNumberArea class. |
| |
| \section1 The LineNumberArea Class |
| |
| We paint the line numbers on this widget, and place it over the \c |
| CodeEditor's \l{QAbstractScrollArea::}{viewport()}'s left margin |
| area. |
| |
| We need to use protected functions in QPlainTextEdit while |
| painting the area. So to keep things simple, we paint the area in |
| the \c CodeEditor class. The area also asks the editor to |
| calculate its size hint. |
| |
| Note that we could simply paint the line numbers directly on the |
| code editor, and drop the LineNumberArea class. However, the |
| QWidget class helps us to \l{QWidget::}{scroll()} its contents. |
| Also, having a separate widget is the right choice if we wish to |
| extend the editor with breakpoints or other code editor features. |
| The widget would then help in the handling of mouse events. |
| |
| \snippet widgets/codeeditor/codeeditor.h extraarea |
| |
| \section1 CodeEditor Class Definition |
| |
| Here is the code editor's class definition: |
| |
| \snippet widgets/codeeditor/codeeditor.h codeeditordefinition |
| |
| In the editor we resize and draw the line numbers on the \c |
| LineNumberArea. We need to do this when the number of lines in the |
| editor changes, and when the editor's viewport() is scrolled. Of |
| course, it is also done when the editor's size changes. We do |
| this in \c updateLineNumberWidth() and \c updateLineNumberArea(). |
| |
| Whenever, the cursor's position changes, we highlight the current |
| line in \c highlightCurrentLine(). |
| |
| \section1 CodeEditor Class Implementation |
| |
| We will now go through the code editors implementation, starting |
| off with the constructor. |
| |
| \snippet widgets/codeeditor/codeeditor.cpp constructor |
| |
| In the constructor we connect our slots to signals in |
| QPlainTextEdit. It is necessary to calculate the line number area |
| width and highlight the first line when the editor is created. |
| |
| \snippet widgets/codeeditor/codeeditor.cpp extraAreaWidth |
| |
| The \c lineNumberAreaWidth() function calculates the width of the |
| \c LineNumberArea widget. We take the number of digits in the last |
| line of the editor and multiply that with the maximum width of a |
| digit. |
| |
| \snippet widgets/codeeditor/codeeditor.cpp slotUpdateExtraAreaWidth |
| |
| When we update the width of the line number area, we simply call |
| QAbstractScrollArea::setViewportMargins(). |
| |
| \snippet widgets/codeeditor/codeeditor.cpp slotUpdateRequest |
| |
| This slot is invoked when the editors viewport has been scrolled. |
| The QRect given as argument is the part of the editing area that |
| is do be updated (redrawn). \c dy holds the number of pixels the |
| view has been scrolled vertically. |
| |
| \snippet widgets/codeeditor/codeeditor.cpp resizeEvent |
| |
| When the size of the editor changes, we also need to resize the |
| line number area. |
| |
| \snippet widgets/codeeditor/codeeditor.cpp cursorPositionChanged |
| |
| When the cursor position changes, we highlight the current line, |
| i.e., the line containing the cursor. |
| |
| QPlainTextEdit gives the possibility to have more than one |
| selection at the same time. we can set the character format |
| (QTextCharFormat) of these selections. We clear the cursors |
| selection before setting the new new |
| QPlainTextEdit::ExtraSelection, else several lines would get |
| highlighted when the user selects multiple lines with the mouse. |
| \omit ask someone how this works \endomit |
| |
| One sets the selection with a text cursor. When using the |
| FullWidthSelection property, the current cursor text block (line) |
| will be selected. If you want to select just a portion of the text |
| block, the cursor should be moved with QTextCursor::movePosition() |
| from a position set with \l{QTextCursor::}{setPosition()}. |
| |
| \snippet widgets/codeeditor/codeeditor.cpp extraAreaPaintEvent_0 |
| |
| The \c lineNumberAreaPaintEvent() is called from \c LineNumberArea |
| whenever it receives a paint event. We start off by painting the |
| widget's background. |
| |
| \snippet widgets/codeeditor/codeeditor.cpp extraAreaPaintEvent_1 |
| |
| We will now loop through all visible lines and paint the line |
| numbers in the extra area for each line. Notice that in a plain |
| text edit each line will consist of one QTextBlock; though, if |
| line wrapping is enabled, a line may span several rows in the text |
| edit's viewport. |
| |
| We get the top and bottom y-coordinate of the first text block, |
| and adjust these values by the height of the current text block in |
| each iteration in the loop. |
| |
| \snippet widgets/codeeditor/codeeditor.cpp extraAreaPaintEvent_2 |
| |
| Notice that we check if the block is visible in addition to check |
| if it is in the areas viewport - a block can, for example, be |
| hidden by a window placed over the text edit. |
| |
| \section1 Suggestions for Extending the Code Editor |
| |
| No self-respecting code editor is without a syntax |
| highligther; the \l{Syntax Highlighter Example} shows how to |
| create one. |
| |
| In addition to line numbers, you can add more to the extra area, |
| for instance, break points. |
| |
| QSyntaxHighlighter gives the possibility to add user data to each |
| text block with |
| \l{QSyntaxHighlighter::}{setCurrentBlockUserData()}. This can be |
| used to implement parenthesis matching. In the \c |
| highlightCurrentLine(), the data of the currentBlock() can be |
| fetched with QTextBlock::userData(). Matching parentheses can be |
| highlighted with an extra selection. The "Matching Parentheses |
| with QSyntaxHighlighter" article in Qt Quarterly 31 implements |
| this. You find it here: \l{http://doc.qt.io/archives/qq/}. |
| |
| */ |