diff options
Diffstat (limited to 'tests/manual/textrendering')
13 files changed, 457 insertions, 16 deletions
diff --git a/tests/manual/textrendering/CMakeLists.txt b/tests/manual/textrendering/CMakeLists.txt index 788f9fc34f..cd06705ce5 100644 --- a/tests/manual/textrendering/CMakeLists.txt +++ b/tests/manual/textrendering/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from textrendering.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause add_subdirectory(glyphshaping) add_subdirectory(textperformance) diff --git a/tests/manual/textrendering/codeeditor/CMakeLists.txt b/tests/manual/textrendering/codeeditor/CMakeLists.txt new file mode 100644 index 0000000000..0e8a3b49ff --- /dev/null +++ b/tests/manual/textrendering/codeeditor/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(codeeditor LANGUAGES CXX) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/widgets/codeeditor") + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets) + +qt_standard_project_setup() + +qt_add_executable(codeeditor + codeeditor.cpp codeeditor.h + main.cpp +) + +set_target_properties(codeeditor PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(codeeditor PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Widgets +) + +install(TARGETS codeeditor + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/tests/manual/textrendering/codeeditor/codeeditor.cpp b/tests/manual/textrendering/codeeditor/codeeditor.cpp new file mode 100644 index 0000000000..3b7fd58d30 --- /dev/null +++ b/tests/manual/textrendering/codeeditor/codeeditor.cpp @@ -0,0 +1,134 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "codeeditor.h" + +#include <QPainter> +#include <QTextBlock> + +//![constructor] + +CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent) +{ + lineNumberArea = new LineNumberArea(this); + + connect(this, &CodeEditor::blockCountChanged, this, &CodeEditor::updateLineNumberAreaWidth); + connect(this, &CodeEditor::updateRequest, this, &CodeEditor::updateLineNumberArea); + connect(this, &CodeEditor::cursorPositionChanged, this, &CodeEditor::highlightCurrentLine); + + updateLineNumberAreaWidth(0); + highlightCurrentLine(); +} + +//![constructor] + +//![extraAreaWidth] + +int CodeEditor::lineNumberAreaWidth() +{ + int digits = 1; + int max = qMax(1, blockCount()); + while (max >= 10) { + max /= 10; + ++digits; + } + + int space = 3 + fontMetrics().horizontalAdvance(QLatin1Char('9')) * digits; + + return space; +} + +//![extraAreaWidth] + +//![slotUpdateExtraAreaWidth] + +void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */) +{ + setViewportMargins(lineNumberAreaWidth(), 0, 0, 0); +} + +//![slotUpdateExtraAreaWidth] + +//![slotUpdateRequest] + +void CodeEditor::updateLineNumberArea(const QRect &rect, int dy) +{ + if (dy) + lineNumberArea->scroll(0, dy); + else + lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height()); + + if (rect.contains(viewport()->rect())) + updateLineNumberAreaWidth(0); +} + +//![slotUpdateRequest] + +//![resizeEvent] + +void CodeEditor::resizeEvent(QResizeEvent *e) +{ + QPlainTextEdit::resizeEvent(e); + + QRect cr = contentsRect(); + lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height())); +} + +//![resizeEvent] + +//![cursorPositionChanged] + +void CodeEditor::highlightCurrentLine() +{ + QList<QTextEdit::ExtraSelection> extraSelections; + + if (!isReadOnly()) { + QTextEdit::ExtraSelection selection; + + QColor lineColor = QColor(Qt::yellow).lighter(160); + + selection.format.setBackground(lineColor); + selection.format.setProperty(QTextFormat::FullWidthSelection, true); + selection.cursor = textCursor(); + selection.cursor.clearSelection(); + extraSelections.append(selection); + } + + setExtraSelections(extraSelections); +} + +//![cursorPositionChanged] + +//![extraAreaPaintEvent_0] + +void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event) +{ + QPainter painter(lineNumberArea); + painter.fillRect(event->rect(), Qt::lightGray); + +//![extraAreaPaintEvent_0] + +//![extraAreaPaintEvent_1] + QTextBlock block = firstVisibleBlock(); + int blockNumber = block.blockNumber(); + int top = qRound(blockBoundingGeometry(block).translated(contentOffset()).top()); + int bottom = top + qRound(blockBoundingRect(block).height()); +//![extraAreaPaintEvent_1] + +//![extraAreaPaintEvent_2] + while (block.isValid() && top <= event->rect().bottom()) { + if (block.isVisible() && bottom >= event->rect().top()) { + QString number = QString::number(blockNumber + 1); + painter.setPen(Qt::black); + painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(), + Qt::AlignRight, number); + } + + block = block.next(); + top = bottom; + bottom = top + qRound(blockBoundingRect(block).height()); + ++blockNumber; + } +} +//![extraAreaPaintEvent_2] + diff --git a/tests/manual/textrendering/codeeditor/codeeditor.h b/tests/manual/textrendering/codeeditor/codeeditor.h new file mode 100644 index 0000000000..583bf3b4a0 --- /dev/null +++ b/tests/manual/textrendering/codeeditor/codeeditor.h @@ -0,0 +1,68 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef CODEEDITOR_H +#define CODEEDITOR_H + +#include <QPlainTextEdit> + +QT_BEGIN_NAMESPACE +class QPaintEvent; +class QResizeEvent; +class QSize; +class QWidget; +QT_END_NAMESPACE + +class LineNumberArea; + +//![codeeditordefinition] + +class CodeEditor : public QPlainTextEdit +{ + Q_OBJECT + +public: + CodeEditor(QWidget *parent = nullptr); + + void lineNumberAreaPaintEvent(QPaintEvent *event); + int lineNumberAreaWidth(); + +protected: + void resizeEvent(QResizeEvent *event) override; + +private slots: + void updateLineNumberAreaWidth(int newBlockCount); + void highlightCurrentLine(); + void updateLineNumberArea(const QRect &rect, int dy); + +private: + QWidget *lineNumberArea; +}; + +//![codeeditordefinition] +//![extraarea] + +class LineNumberArea : public QWidget +{ +public: + LineNumberArea(CodeEditor *editor) : QWidget(editor), codeEditor(editor) + {} + + QSize sizeHint() const override + { + return QSize(codeEditor->lineNumberAreaWidth(), 0); + } + +protected: + void paintEvent(QPaintEvent *event) override + { + codeEditor->lineNumberAreaPaintEvent(event); + } + +private: + CodeEditor *codeEditor; +}; + +//![extraarea] + +#endif diff --git a/tests/manual/textrendering/codeeditor/codeeditor.pro b/tests/manual/textrendering/codeeditor/codeeditor.pro new file mode 100644 index 0000000000..5618160d17 --- /dev/null +++ b/tests/manual/textrendering/codeeditor/codeeditor.pro @@ -0,0 +1,8 @@ +QT += widgets + +HEADERS = codeeditor.h +SOURCES = main.cpp \ + codeeditor.cpp +# install +target.path = $$[QT_INSTALL_EXAMPLES]/widgets/widgets/codeeditor +INSTALLS += target diff --git a/tests/manual/textrendering/codeeditor/codeeditor.qdoc b/tests/manual/textrendering/codeeditor/codeeditor.qdoc new file mode 100644 index 0000000000..f3b417c5b8 --- /dev/null +++ b/tests/manual/textrendering/codeeditor/codeeditor.qdoc @@ -0,0 +1,173 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only + +/*! + \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 + 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/}. + +*/ diff --git a/tests/manual/textrendering/codeeditor/main.cpp b/tests/manual/textrendering/codeeditor/main.cpp new file mode 100644 index 0000000000..3e3d98ae31 --- /dev/null +++ b/tests/manual/textrendering/codeeditor/main.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QApplication> + +#include "codeeditor.h" + +int main(int argv, char **args) +{ + QApplication app(argv, args); + + CodeEditor editor; + editor.setWindowTitle(QObject::tr("Code Editor Example")); + editor.show(); + + return app.exec(); +} + diff --git a/tests/manual/textrendering/glyphshaping/CMakeLists.txt b/tests/manual/textrendering/glyphshaping/CMakeLists.txt index e0a69745e8..8965070139 100644 --- a/tests/manual/textrendering/glyphshaping/CMakeLists.txt +++ b/tests/manual/textrendering/glyphshaping/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from glyphshaping.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## glyphshaping Binary: @@ -8,12 +9,7 @@ qt_internal_add_manual_test(glyphshaping GUI SOURCES main.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui Qt::Widgets ) - -#### Keys ignored in scope 1:.:.:glyphshaping.pro:<TRUE>: -# DEPLOYMENT = "glyphshaping_data" -# glyphshaping_data.files = "$$PWD/glyphshaping_data.xml" -# glyphshaping_data.path = "." diff --git a/tests/manual/textrendering/glyphshaping/main.cpp b/tests/manual/textrendering/glyphshaping/main.cpp index b9f94d46b5..bbe36a8abf 100644 --- a/tests/manual/textrendering/glyphshaping/main.cpp +++ b/tests/manual/textrendering/glyphshaping/main.cpp @@ -1,5 +1,7 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses #include <QApplication> #include <QDir> diff --git a/tests/manual/textrendering/nativetext/CMakeLists.txt b/tests/manual/textrendering/nativetext/CMakeLists.txt index 447288e6df..67918640af 100644 --- a/tests/manual/textrendering/nativetext/CMakeLists.txt +++ b/tests/manual/textrendering/nativetext/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from nativetext.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## nativetext Binary: @@ -7,7 +8,7 @@ qt_internal_add_manual_test(nativetext SOURCES main.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate @@ -18,7 +19,7 @@ qt_internal_add_manual_test(nativetext ##################################################################### qt_internal_extend_target(nativetext CONDITION APPLE - PUBLIC_LIBRARIES + LIBRARIES ${FWAppKit} ${FWCoreGraphics} ${FWFoundation} diff --git a/tests/manual/textrendering/nativetext/main.cpp b/tests/manual/textrendering/nativetext/main.cpp index 265ebcac45..65a361eddb 100644 --- a/tests/manual/textrendering/nativetext/main.cpp +++ b/tests/manual/textrendering/nativetext/main.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtWidgets> diff --git a/tests/manual/textrendering/textperformance/CMakeLists.txt b/tests/manual/textrendering/textperformance/CMakeLists.txt index ed1664dd2a..56e67d3688 100644 --- a/tests/manual/textrendering/textperformance/CMakeLists.txt +++ b/tests/manual/textrendering/textperformance/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from textperformance.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## textperformance Binary: @@ -8,7 +9,7 @@ qt_internal_add_manual_test(textperformance GUI SOURCES main.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui Qt::Widgets ) diff --git a/tests/manual/textrendering/textperformance/main.cpp b/tests/manual/textrendering/textperformance/main.cpp index fa3a5122ce..babeb2f810 100644 --- a/tests/manual/textrendering/textperformance/main.cpp +++ b/tests/manual/textrendering/textperformance/main.cpp @@ -1,5 +1,7 @@ // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses #include <QApplication> #include <QDialog> |