summaryrefslogtreecommitdiffstats
path: root/tests/manual/examples/widgets/richtext
diff options
context:
space:
mode:
Diffstat (limited to 'tests/manual/examples/widgets/richtext')
-rw-r--r--tests/manual/examples/widgets/richtext/calendar/CMakeLists.txt37
-rw-r--r--tests/manual/examples/widgets/richtext/calendar/calendar.pro10
-rw-r--r--tests/manual/examples/widgets/richtext/calendar/main.cpp15
-rw-r--r--tests/manual/examples/widgets/richtext/calendar/mainwindow.cpp179
-rw-r--r--tests/manual/examples/widgets/richtext/calendar/mainwindow.h36
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/CMakeLists.txt105
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/example.html84
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/example.md104
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/logo32.pngbin0 -> 1410 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/checkbox-checked.pngbin0 -> 1167 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/checkbox.pngbin0 -> 779 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/editcopy.pngbin0 -> 1468 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/editcut.pngbin0 -> 1512 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/editpaste.pngbin0 -> 1906 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/editredo.pngbin0 -> 1752 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/editundo.pngbin0 -> 1746 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/exportpdf.pngbin0 -> 12637 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/filenew.pngbin0 -> 1172 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/fileopen.pngbin0 -> 2168 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/fileprint.pngbin0 -> 2087 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/filesave.pngbin0 -> 2699 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/format-indent-less.pngbin0 -> 1201 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/format-indent-more.pngbin0 -> 993 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/textbold.pngbin0 -> 1611 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/textcenter.pngbin0 -> 1404 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/textitalic.pngbin0 -> 1164 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/textjustify.pngbin0 -> 1257 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/textleft.pngbin0 -> 1235 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/textright.pngbin0 -> 1406 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/textunder.pngbin0 -> 1183 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/textundercolor.pngbin0 -> 6916 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/zoomin.pngbin0 -> 1696 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/mac/zoomout.pngbin0 -> 1662 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/checkbox-checked.pngbin0 -> 1167 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/checkbox.pngbin0 -> 779 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/editcopy.pngbin0 -> 1325 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/editcut.pngbin0 -> 1896 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/editpaste.pngbin0 -> 1482 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/editredo.pngbin0 -> 1787 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/editundo.pngbin0 -> 1768 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/exportpdf.pngbin0 -> 1215 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/filenew.pngbin0 -> 768 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/fileopen.pngbin0 -> 1662 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/fileprint.pngbin0 -> 1456 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/filesave.pngbin0 -> 1205 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/format-indent-less.pngbin0 -> 1201 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/format-indent-more.pngbin0 -> 993 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/textbold.pngbin0 -> 1134 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/textcenter.pngbin0 -> 627 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/textitalic.pngbin0 -> 829 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/textjustify.pngbin0 -> 695 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/textleft.pngbin0 -> 673 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/textright.pngbin0 -> 677 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/textunder.pngbin0 -> 971 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/textundercolor.pngbin0 -> 6916 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/zoomin.pngbin0 -> 1208 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/images/win/zoomout.pngbin0 -> 1226 bytes
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/main.cpp36
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/textedit.cpp904
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/textedit.h110
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/textedit.pro22
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/textedit.qdoc20
-rw-r--r--tests/manual/examples/widgets/richtext/textedit/textedit.qrc54
63 files changed, 1716 insertions, 0 deletions
diff --git a/tests/manual/examples/widgets/richtext/calendar/CMakeLists.txt b/tests/manual/examples/widgets/richtext/calendar/CMakeLists.txt
new file mode 100644
index 0000000000..7b8e10060b
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/calendar/CMakeLists.txt
@@ -0,0 +1,37 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+project(calendar LANGUAGES CXX)
+
+if(NOT DEFINED INSTALL_EXAMPLESDIR)
+ set(INSTALL_EXAMPLESDIR "examples")
+endif()
+
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/richtext/calendar")
+
+find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
+
+qt_standard_project_setup()
+
+qt_add_executable(calendar
+ main.cpp
+ mainwindow.cpp mainwindow.h
+)
+
+set_target_properties(calendar PROPERTIES
+ WIN32_EXECUTABLE TRUE
+ MACOSX_BUNDLE TRUE
+)
+
+target_link_libraries(calendar PRIVATE
+ Qt6::Core
+ Qt6::Gui
+ Qt6::Widgets
+)
+
+install(TARGETS calendar
+ RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
+ BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
+ LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+)
diff --git a/tests/manual/examples/widgets/richtext/calendar/calendar.pro b/tests/manual/examples/widgets/richtext/calendar/calendar.pro
new file mode 100644
index 0000000000..199c1dbb8d
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/calendar/calendar.pro
@@ -0,0 +1,10 @@
+QT += widgets
+requires(qtConfig(combobox))
+
+HEADERS = mainwindow.h
+SOURCES = main.cpp \
+ mainwindow.cpp
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/widgets/richtext/calendar
+INSTALLS += target
diff --git a/tests/manual/examples/widgets/richtext/calendar/main.cpp b/tests/manual/examples/widgets/richtext/calendar/main.cpp
new file mode 100644
index 0000000000..5641ae527a
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/calendar/main.cpp
@@ -0,0 +1,15 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include <QApplication>
+
+#include "mainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ MainWindow window;
+ window.resize(640, 256);
+ window.show();
+ return app.exec();
+}
diff --git a/tests/manual/examples/widgets/richtext/calendar/mainwindow.cpp b/tests/manual/examples/widgets/richtext/calendar/mainwindow.cpp
new file mode 100644
index 0000000000..0b44c96d46
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/calendar/mainwindow.cpp
@@ -0,0 +1,179 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "mainwindow.h"
+
+#include <QtWidgets>
+
+//! [0]
+MainWindow::MainWindow()
+{
+ selectedDate = QDate::currentDate();
+ fontSize = 10;
+
+ QWidget *centralWidget = new QWidget;
+//! [0]
+
+//! [1]
+ QLabel *dateLabel = new QLabel(tr("Date:"));
+ QComboBox *monthCombo = new QComboBox;
+
+ for (int month = 1; month <= 12; ++month)
+ monthCombo->addItem(QLocale::system().monthName(month));
+
+ QDateTimeEdit *yearEdit = new QDateTimeEdit;
+ yearEdit->setDisplayFormat("yyyy");
+ yearEdit->setDateRange(QDate(1753, 1, 1), QDate(8000, 1, 1));
+//! [1]
+
+ monthCombo->setCurrentIndex(selectedDate.month() - 1);
+ yearEdit->setDate(selectedDate);
+
+//! [2]
+ QLabel *fontSizeLabel = new QLabel(tr("Font size:"));
+ QSpinBox *fontSizeSpinBox = new QSpinBox;
+ fontSizeSpinBox->setRange(1, 64);
+
+ editor = new QTextBrowser;
+ insertCalendar();
+//! [2]
+
+//! [3]
+ connect(monthCombo, &QComboBox::activated,
+ this, &MainWindow::setMonth);
+ connect(yearEdit, &QDateTimeEdit::dateChanged,
+ this, &MainWindow::setYear);
+ connect(fontSizeSpinBox, &QSpinBox::valueChanged,
+ this, &MainWindow::setFontSize);
+//! [3]
+
+ fontSizeSpinBox->setValue(10);
+
+//! [4]
+ QHBoxLayout *controlsLayout = new QHBoxLayout;
+ controlsLayout->addWidget(dateLabel);
+ controlsLayout->addWidget(monthCombo);
+ controlsLayout->addWidget(yearEdit);
+ controlsLayout->addSpacing(24);
+ controlsLayout->addWidget(fontSizeLabel);
+ controlsLayout->addWidget(fontSizeSpinBox);
+ controlsLayout->addStretch(1);
+
+ QVBoxLayout *centralLayout = new QVBoxLayout;
+ centralLayout->addLayout(controlsLayout);
+ centralLayout->addWidget(editor, 1);
+ centralWidget->setLayout(centralLayout);
+
+ setCentralWidget(centralWidget);
+//! [4]
+}
+
+//! [5]
+void MainWindow::insertCalendar()
+{
+ editor->clear();
+ QTextCursor cursor = editor->textCursor();
+ cursor.beginEditBlock();
+
+ QDate date(selectedDate.year(), selectedDate.month(), 1);
+//! [5]
+
+//! [6]
+ QTextTableFormat tableFormat;
+ tableFormat.setAlignment(Qt::AlignHCenter);
+ tableFormat.setBackground(QColor("#e0e0e0"));
+ tableFormat.setCellPadding(2);
+ tableFormat.setCellSpacing(4);
+//! [6] //! [7]
+ QList<QTextLength> constraints;
+ constraints << QTextLength(QTextLength::PercentageLength, 14)
+ << QTextLength(QTextLength::PercentageLength, 14)
+ << QTextLength(QTextLength::PercentageLength, 14)
+ << QTextLength(QTextLength::PercentageLength, 14)
+ << QTextLength(QTextLength::PercentageLength, 14)
+ << QTextLength(QTextLength::PercentageLength, 14)
+ << QTextLength(QTextLength::PercentageLength, 14);
+ tableFormat.setColumnWidthConstraints(constraints);
+//! [7]
+
+//! [8]
+ QTextTable *table = cursor.insertTable(1, 7, tableFormat);
+//! [8]
+
+//! [9]
+ QTextFrame *frame = cursor.currentFrame();
+ QTextFrameFormat frameFormat = frame->frameFormat();
+ frameFormat.setBorder(1);
+ frame->setFrameFormat(frameFormat);
+//! [9]
+
+//! [10]
+ QTextCharFormat format = cursor.charFormat();
+ format.setFontPointSize(fontSize);
+
+ QTextCharFormat boldFormat = format;
+ boldFormat.setFontWeight(QFont::Bold);
+
+ QTextCharFormat highlightedFormat = boldFormat;
+ highlightedFormat.setBackground(Qt::yellow);
+//! [10]
+
+//! [11]
+ for (int weekDay = 1; weekDay <= 7; ++weekDay) {
+ QTextTableCell cell = table->cellAt(0, weekDay-1);
+//! [11] //! [12]
+ QTextCursor cellCursor = cell.firstCursorPosition();
+ cellCursor.insertText(QLocale::system().dayName(weekDay), boldFormat);
+ }
+//! [12]
+
+//! [13]
+ table->insertRows(table->rows(), 1);
+//! [13]
+
+ while (date.month() == selectedDate.month()) {
+ int weekDay = date.dayOfWeek();
+ QTextTableCell cell = table->cellAt(table->rows()-1, weekDay-1);
+ QTextCursor cellCursor = cell.firstCursorPosition();
+
+ if (date == QDate::currentDate())
+ cellCursor.insertText(QString("%1").arg(date.day()), highlightedFormat);
+ else
+ cellCursor.insertText(QString("%1").arg(date.day()), format);
+
+ date = date.addDays(1);
+ if (weekDay == 7 && date.month() == selectedDate.month())
+ table->insertRows(table->rows(), 1);
+ }
+
+ cursor.endEditBlock();
+//! [14]
+ setWindowTitle(tr("Calendar for %1 %2"
+ ).arg(QLocale::system().monthName(selectedDate.month())
+ ).arg(selectedDate.year()));
+}
+//! [14]
+
+//! [15]
+void MainWindow::setFontSize(int size)
+{
+ fontSize = size;
+ insertCalendar();
+}
+//! [15]
+
+//! [16]
+void MainWindow::setMonth(int month)
+{
+ selectedDate = QDate(selectedDate.year(), month + 1, selectedDate.day());
+ insertCalendar();
+}
+//! [16]
+
+//! [17]
+void MainWindow::setYear(QDate date)
+{
+ selectedDate = QDate(date.year(), selectedDate.month(), selectedDate.day());
+ insertCalendar();
+}
+//! [17]
diff --git a/tests/manual/examples/widgets/richtext/calendar/mainwindow.h b/tests/manual/examples/widgets/richtext/calendar/mainwindow.h
new file mode 100644
index 0000000000..76632820d6
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/calendar/mainwindow.h
@@ -0,0 +1,36 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QDate>
+#include <QMainWindow>
+
+QT_BEGIN_NAMESPACE
+class QTextBrowser;
+QT_END_NAMESPACE
+
+//! [0]
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ MainWindow();
+
+public slots:
+ void setFontSize(int size);
+ void setMonth(int month);
+ void setYear(QDate date);
+
+private:
+ void insertCalendar();
+
+ int fontSize;
+ QDate selectedDate;
+ QTextBrowser *editor;
+};
+//! [0]
+
+#endif // MAINWINDOW_H
diff --git a/tests/manual/examples/widgets/richtext/textedit/CMakeLists.txt b/tests/manual/examples/widgets/richtext/textedit/CMakeLists.txt
new file mode 100644
index 0000000000..6e8df9134d
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/CMakeLists.txt
@@ -0,0 +1,105 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+project(textedit LANGUAGES CXX)
+
+if(NOT DEFINED INSTALL_EXAMPLESDIR)
+ set(INSTALL_EXAMPLESDIR "examples")
+endif()
+
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/widgets/richtext/textedit")
+
+find_package(Qt6
+ REQUIRED COMPONENTS Core Gui Widgets
+ OPTIONAL_COMPONENTS PrintSupport
+)
+
+qt_standard_project_setup()
+
+qt_add_executable(textedit
+ main.cpp
+ textedit.cpp textedit.h
+)
+
+set_target_properties(textedit PROPERTIES
+ WIN32_EXECUTABLE TRUE
+ MACOSX_BUNDLE TRUE
+)
+
+target_link_libraries(textedit PRIVATE
+ Qt6::Core
+ Qt6::Gui
+ Qt6::Widgets
+)
+
+if (TARGET Qt6::PrintSupport)
+ target_link_libraries(textedit PRIVATE Qt6::PrintSupport)
+endif()
+
+# Resources:
+set(textedit_resource_files
+ "example.html"
+ "images/logo32.png"
+ "images/mac/checkbox-checked.png"
+ "images/mac/checkbox.png"
+ "images/mac/editcopy.png"
+ "images/mac/editcut.png"
+ "images/mac/editpaste.png"
+ "images/mac/editredo.png"
+ "images/mac/editundo.png"
+ "images/mac/exportpdf.png"
+ "images/mac/filenew.png"
+ "images/mac/fileopen.png"
+ "images/mac/fileprint.png"
+ "images/mac/filesave.png"
+ "images/mac/format-indent-less.png"
+ "images/mac/format-indent-more.png"
+ "images/mac/textbold.png"
+ "images/mac/textcenter.png"
+ "images/mac/textitalic.png"
+ "images/mac/textjustify.png"
+ "images/mac/textleft.png"
+ "images/mac/textright.png"
+ "images/mac/textunder.png"
+ "images/mac/textundercolor.png"
+ "images/mac/zoomin.png"
+ "images/mac/zoomout.png"
+ "images/win/checkbox-checked.png"
+ "images/win/checkbox.png"
+ "images/win/editcopy.png"
+ "images/win/editcut.png"
+ "images/win/editpaste.png"
+ "images/win/editredo.png"
+ "images/win/editundo.png"
+ "images/win/exportpdf.png"
+ "images/win/filenew.png"
+ "images/win/fileopen.png"
+ "images/win/fileprint.png"
+ "images/win/filesave.png"
+ "images/win/format-indent-less.png"
+ "images/win/format-indent-more.png"
+ "images/win/textbold.png"
+ "images/win/textcenter.png"
+ "images/win/textitalic.png"
+ "images/win/textjustify.png"
+ "images/win/textleft.png"
+ "images/win/textright.png"
+ "images/win/textunder.png"
+ "images/win/textundercolor.png"
+ "images/win/zoomin.png"
+ "images/win/zoomout.png"
+)
+
+qt_add_resources(textedit "textedit"
+ PREFIX
+ "/"
+ FILES
+ ${textedit_resource_files}
+)
+
+install(TARGETS textedit
+ RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
+ BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
+ LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+)
diff --git a/tests/manual/examples/widgets/richtext/textedit/example.html b/tests/manual/examples/widgets/richtext/textedit/example.html
new file mode 100644
index 0000000000..038f71acfe
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/example.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><title>QTextEdit Example</title><style type="text/css">
+p, li { white-space: pre-wrap; }
+hr { height: 1px; border-width: 0; }
+</style></head><body style=" font-family:'Helvetica'; font-size:9pt; font-weight:400; font-style:normal;">
+<h1 align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:20pt; font-weight:600;">QTextEdit</span></h1>
+<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">The QTextEdit widget is an advanced editor that supports formatted rich text. It can be used to display HTML and other rich document formats. Internally, QTextEdit uses the QTextDocument class to describe both the high-level structure of each document and the low-level formatting of paragraphs.</span></p>
+<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">If you are viewing this document in the <span style=" font-style:italic;">textedit</span> example, you can edit this document to explore Qt's rich text editing features. We have included some comments in each of the following sections to encourage you to experiment. </p>
+<h2 style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:18pt; font-weight:600;"><span style=" font-size:16pt;">Font and Paragraph Styles</span></h2>
+<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">QTextEdit supports </span><span style=" font-size:11pt; font-weight:600;">bold</span><span style=" font-size:11pt;">, </span><span style=" font-size:11pt; font-style:italic;">italic</span><span style=" font-size:11pt;">, and </span><span style=" font-size:11pt; text-decoration: underline;">underlined</span><span style=" font-size:11pt;"> font styles, and can display </span><span style=" font-size:11pt; font-weight:600; color:#00007f;">multicolored</span><span style=" font-size:11pt;"> </span><span style=" font-size:11pt; font-weight:600; color:#aa0000;">text</span><span style=" font-size:11pt;">. Font families such as </span><span style=" font-family:'Times New Roman'; font-size:11pt; font-weight:600;">Times New Roman</span><span style=" font-size:11pt;"> and </span><span style=" font-family:'Courier'; font-size:11pt; font-weight:600;">Courier</span><span style=" font-size:11pt;"> can also be used directly. </span><span style=" font-size:11pt; font-style:italic;">If you place the cursor in a region of styled text, the controls in the tool bars will change to reflect the current style.</span></p>
+<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">Paragraphs can be formatted so that the text is left-aligned, right-aligned, centered, or fully justified.</p>
+<p align="center" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-style:italic;">Try changing the alignment of some text and resize the editor to see how the text layout changes.</span> </p>
+<h2 align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600;">Lists</span></h2>
+<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt; font-weight:600;"><span style=" font-size:11pt; font-weight:400;">Different kinds of lists can be included in rich text documents. Standard bullet lists can be nested, using different symbols for each level of the list: </span></p>
+<ul style="-qt-list-indent: 1;"><li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Disc symbols are typically used for top-level list items. </li></ul>
+<ul type=circle style="-qt-list-indent: 2;"><li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Circle symbols can be used to distinguish between items in lower-level lists.</li></ul>
+<ul type=square style="-qt-list-indent: 3;"><li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Square symbols provide a reasonable alternative to discs and circles. </li></ul>
+<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">Ordered lists can be created that can be used for tables of contents. Different characters can be used to enumerate items, and we can use both Roman and Arabic numerals in the same list structure: </p>
+<ol style="-qt-list-indent: 1;"><li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Introduction</li>
+<li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Qt Tools </li></ol>
+<ol type=a style="-qt-list-indent: 2;"><li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Qt Assistant</li>
+<li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Qt Widgets Designer</li>
+<ol type=A style="-qt-list-indent: 3;"><li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Form Editor</li>
+<li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Component Architecture</li></ol>
+<li style=" font-size:11pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Qt Linguist</li></ol>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">The list will automatically be renumbered if you add or remove items. <span style=" font-style:italic;">Try adding new sections to the above list or removing existing item to see the numbers change.</span> </p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"></p>
+<h2 style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Images</span></h2>
+<p style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt; font-weight:600;"><span style=" font-size:11pt; font-weight:400;">Inline images are treated like ordinary ranges of characters in the text editor, so they flow with the surrounding text. Images can also be selected in the same way as text, making it easy to cut, copy, and paste them. </span></p>
+<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><img src=":/images/logo32.png" /><span style=" font-style:italic;"> Try to select this image by clicking and dragging over it with the mouse, or use the text cursor to select it by holding down Shift and using the arrow keys. You can then cut or copy it, and paste it into different parts of this document.</span></p>
+<h2 align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600;">Horizontal Rule</span></h2>
+<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Here is an example:</p>
+<hr width="50%" style=" background-color:green;"/>
+<h2 align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Tables</span></h2>
+<p align="justify" style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:16pt; font-weight:600;"><span style=" font-size:11pt; font-weight:400;">QTextEdit can arrange and format tables, supporting features such as row and column spans, text formatting within cells, and size constraints for columns. </span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"></p>
+<table border="1" align="center" width="90%" cellspacing="0" cellpadding="4">
+<tr>
+<td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p></td>
+<td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Development Tools </span></p></td>
+<td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Programming Techniques </span></p></td>
+<td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Graphical User Interfaces </span></p></td></tr>
+<tr>
+<td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">9:00 - 11:00 </span></p></td>
+<td colspan="3">
+<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Introduction to <span style=" font-style:italic;">Qt </span></p></td></tr>
+<tr>
+<td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">11:00 - 13:00 </span></p></td>
+<td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Using <span style=" font-style:italic;">qmake</span> </p></td>
+<td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Object-oriented Programming </p></td>
+<td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Layouts in <span style=" font-style:italic;">Qt</span> </p></td></tr>
+<tr>
+<td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">13:00 - 15:00 </span></p></td>
+<td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:italic;">Qt Widgets Designer</span> Tutorial </p></td>
+<td rowspan="2">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Extreme Programming </p></td>
+<td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Writing Custom Styles </p></td></tr>
+<tr>
+<td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">15:00 - 17:00 </span></p></td>
+<td>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-style:italic;">Qt Linguist</span> and Internationalization </p></td>
+<td></td></tr></table>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"></p>
+<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; font-style:italic;">Try adding text to the cells in the table and experiment with the alignment of the paragraphs.</p>
+<h2 style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Hyperlinks</span></h2>
+<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:11pt;">QTextEdit is designed to support hyperlinks between documents, and this feature is used extensively in </span><span style=" font-size:11pt; font-style:italic;">Qt Assistant</span><span style=" font-size:11pt;">. Hyperlinks are automatically created when an HTML file is imported into an editor. Since the rich text framework supports hyperlinks natively, they can also be created programmatically.</span></p>
+<h2 style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-size:16pt; font-weight:600;">Undo and Redo</span></h2>
+<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;">Full support for undo and redo operations is built into QTextEdit and the underlying rich text framework. Operations on a document can be packaged together to make editing a more comfortable experience for the user.</p>
+<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;"><span style=" font-style:italic;">Try making changes to this document and press Ctrl+Z to undo them. You can always recover the original contents of the document.</span> </p></body></html>
diff --git a/tests/manual/examples/widgets/richtext/textedit/example.md b/tests/manual/examples/widgets/richtext/textedit/example.md
new file mode 100644
index 0000000000..8a5eed72f6
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/example.md
@@ -0,0 +1,104 @@
+# QTextEdit
+
+The QTextEdit widget is an advanced editor that supports formatted rich text.
+It can be used to display HTML and other rich document formats. Internally,
+QTextEdit uses the QTextDocument class to describe both the high-level
+structure of each document and the low-level formatting of paragraphs.
+
+If you are viewing this document in the textedit example, you can edit this
+document to explore Qt's rich text editing features. We have included some
+comments in each of the following sections to encourage you to experiment.
+
+## Font and Paragraph Styles
+
+QTextEdit supports **bold**, *italic*, _underline_ &amp; ~~strikethrough~~ font
+styles, and can display
+<span style="font-size:10pt; font-weight:600; color:#00007f;"> multicolored</span>
+text. Font families such as
+<span style="font-family:Times New Roman">Times New Roman</span> and
+<span style="font-family:Courier">Courier</span>
+can also be used directly. *If you place the cursor in a region of styled text,
+the controls in the tool bars will change to reflect the current style.*
+
+Paragraphs can be formatted so that the text is left-aligned, right-aligned,
+centered, or fully justified.
+
+*Try changing the alignment of some text and resize the editor to see how the
+text layout changes.*
+
+## Lists
+
+Different kinds of lists can be included in rich text documents. Standard
+bullet lists can be nested, using different symbols for each level of the list:
+
+- Disc symbols are typically used for top-level list items.
+ * Circle symbols can be used to distinguish between items in lower-level
+ lists.
+ + Square symbols provide a reasonable alternative to discs and circles.
+
+Ordered lists can be created that can be used for tables of contents. Different
+characters can be used to enumerate items, and we can use both Roman and Arabic
+numerals in the same list structure:
+
+1. Introduction
+2. Qt Tools
+ 1) Qt Assistant
+ 2) Qt Widgets Designer
+ 1. Form Editor
+ 2. Component Architecture
+ 3) Qt Linguist
+
+The list will automatically be renumbered if you add or remove items. *Try
+adding new sections to the above list or removing existing item to see the
+numbers change.*
+
+Task lists can be used to track progress on projects:
+
+- [ ] This is not yet done
+- This is just a bullet point
+- [x] This is done
+
+## Images
+
+Inline images are treated like ordinary ranges of characters in the text
+editor, so they flow with the surrounding text. Images can also be selected in
+the same way as text, making it easy to cut, copy, and paste them.
+
+![logo](images/logo32.png "logo") *Try to select this image by clicking and
+dragging over it with the mouse, or use the text cursor to select it by holding
+down Shift and using the arrow keys. You can then cut or copy it, and paste it
+into different parts of this document.*
+
+## Tables
+
+QTextEdit can arrange and format tables, supporting features such as row and
+column spans, text formatting within cells, and size constraints for columns.
+
+| | Development Tools | Programming Techniques | Graphical User Interfaces |
+| ------------: | ----------------- | ---------------------- | ------------------------- |
+| 9:00 - 11:00 | Introduction to Qt |||
+| 11:00 - 13:00 | Using qmake | Object-oriented Programming | Layouts in Qt |
+| 13:00 - 15:00 | Qt Widgets Designer Tutorial | Extreme Programming | Writing Custom Styles |
+| 15:00 - 17:00 | Qt Linguist and Internationalization | &nbsp; | &nbsp; |
+
+*Try adding text to the cells in the table and experiment with the alignment of
+the paragraphs.*
+
+## Hyperlinks
+
+QTextEdit is designed to support hyperlinks between documents, and this feature
+is used extensively in
+[Qt Assistant](http://doc.qt.io/qt-5/qtassistant-index.html). Hyperlinks are
+automatically created when an HTML file is imported into an editor. Since the
+rich text framework supports hyperlinks natively, they can also be created
+programmatically.
+
+## Undo and Redo
+
+Full support for undo and redo operations is built into QTextEdit and the
+underlying rich text framework. Operations on a document can be packaged
+together to make editing a more comfortable experience for the user.
+
+*Try making changes to this document and press `Ctrl+Z` to undo them. You can
+always recover the original contents of the document.*
+
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/logo32.png b/tests/manual/examples/widgets/richtext/textedit/images/logo32.png
new file mode 100644
index 0000000000..5f91e9873b
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/logo32.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/checkbox-checked.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/checkbox-checked.png
new file mode 100644
index 0000000000..a072d7fb5c
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/checkbox-checked.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/checkbox.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/checkbox.png
new file mode 100644
index 0000000000..4064909712
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/checkbox.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/editcopy.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/editcopy.png
new file mode 100644
index 0000000000..f551364464
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/editcopy.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/editcut.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/editcut.png
new file mode 100644
index 0000000000..a784fd5709
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/editcut.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/editpaste.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/editpaste.png
new file mode 100644
index 0000000000..64c0b2d6ab
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/editpaste.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/editredo.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/editredo.png
new file mode 100644
index 0000000000..8875bf246c
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/editredo.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/editundo.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/editundo.png
new file mode 100644
index 0000000000..a3bd5e0bf2
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/editundo.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/exportpdf.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/exportpdf.png
new file mode 100644
index 0000000000..9e199407af
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/exportpdf.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/filenew.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/filenew.png
new file mode 100644
index 0000000000..d3882c7b3f
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/filenew.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/fileopen.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/fileopen.png
new file mode 100644
index 0000000000..fc06c5ec63
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/fileopen.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/fileprint.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/fileprint.png
new file mode 100644
index 0000000000..10ca56c82a
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/fileprint.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/filesave.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/filesave.png
new file mode 100644
index 0000000000..e65a29d5f1
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/filesave.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/format-indent-less.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/format-indent-less.png
new file mode 100644
index 0000000000..e38074e78b
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/format-indent-less.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/format-indent-more.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/format-indent-more.png
new file mode 100644
index 0000000000..1bdeabd354
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/format-indent-more.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/textbold.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/textbold.png
new file mode 100644
index 0000000000..38400bd1f6
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/textbold.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/textcenter.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/textcenter.png
new file mode 100644
index 0000000000..2ef5b2ee6f
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/textcenter.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/textitalic.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/textitalic.png
new file mode 100644
index 0000000000..0170ee26a6
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/textitalic.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/textjustify.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/textjustify.png
new file mode 100644
index 0000000000..39cd6c1a9d
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/textjustify.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/textleft.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/textleft.png
new file mode 100644
index 0000000000..83a66d5535
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/textleft.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/textright.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/textright.png
new file mode 100644
index 0000000000..e7c04645cf
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/textright.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/textunder.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/textunder.png
new file mode 100644
index 0000000000..968bac5e90
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/textunder.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/textundercolor.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/textundercolor.png
new file mode 100644
index 0000000000..30e24e61c3
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/textundercolor.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/zoomin.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/zoomin.png
new file mode 100644
index 0000000000..d46f5aff0d
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/zoomin.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/mac/zoomout.png b/tests/manual/examples/widgets/richtext/textedit/images/mac/zoomout.png
new file mode 100644
index 0000000000..46326566d1
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/mac/zoomout.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/checkbox-checked.png b/tests/manual/examples/widgets/richtext/textedit/images/win/checkbox-checked.png
new file mode 100644
index 0000000000..a072d7fb5c
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/checkbox-checked.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/checkbox.png b/tests/manual/examples/widgets/richtext/textedit/images/win/checkbox.png
new file mode 100644
index 0000000000..4064909712
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/checkbox.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/editcopy.png b/tests/manual/examples/widgets/richtext/textedit/images/win/editcopy.png
new file mode 100644
index 0000000000..1121b47d8b
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/editcopy.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/editcut.png b/tests/manual/examples/widgets/richtext/textedit/images/win/editcut.png
new file mode 100644
index 0000000000..38e55f7420
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/editcut.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/editpaste.png b/tests/manual/examples/widgets/richtext/textedit/images/win/editpaste.png
new file mode 100644
index 0000000000..ffab15aaf8
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/editpaste.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/editredo.png b/tests/manual/examples/widgets/richtext/textedit/images/win/editredo.png
new file mode 100644
index 0000000000..9d679fe6fc
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/editredo.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/editundo.png b/tests/manual/examples/widgets/richtext/textedit/images/win/editundo.png
new file mode 100644
index 0000000000..eee23d24a3
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/editundo.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/exportpdf.png b/tests/manual/examples/widgets/richtext/textedit/images/win/exportpdf.png
new file mode 100644
index 0000000000..ebb44e6b88
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/exportpdf.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/filenew.png b/tests/manual/examples/widgets/richtext/textedit/images/win/filenew.png
new file mode 100644
index 0000000000..af5d122141
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/filenew.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/fileopen.png b/tests/manual/examples/widgets/richtext/textedit/images/win/fileopen.png
new file mode 100644
index 0000000000..fc6f17e977
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/fileopen.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/fileprint.png b/tests/manual/examples/widgets/richtext/textedit/images/win/fileprint.png
new file mode 100644
index 0000000000..ba7c02dc18
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/fileprint.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/filesave.png b/tests/manual/examples/widgets/richtext/textedit/images/win/filesave.png
new file mode 100644
index 0000000000..8feec99bee
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/filesave.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/format-indent-less.png b/tests/manual/examples/widgets/richtext/textedit/images/win/format-indent-less.png
new file mode 100644
index 0000000000..e38074e78b
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/format-indent-less.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/format-indent-more.png b/tests/manual/examples/widgets/richtext/textedit/images/win/format-indent-more.png
new file mode 100644
index 0000000000..1bdeabd354
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/format-indent-more.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/textbold.png b/tests/manual/examples/widgets/richtext/textedit/images/win/textbold.png
new file mode 100644
index 0000000000..9cbc7138b9
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/textbold.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/textcenter.png b/tests/manual/examples/widgets/richtext/textedit/images/win/textcenter.png
new file mode 100644
index 0000000000..11efb4b852
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/textcenter.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/textitalic.png b/tests/manual/examples/widgets/richtext/textedit/images/win/textitalic.png
new file mode 100644
index 0000000000..b30ce14c14
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/textitalic.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/textjustify.png b/tests/manual/examples/widgets/richtext/textedit/images/win/textjustify.png
new file mode 100644
index 0000000000..9de0c88085
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/textjustify.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/textleft.png b/tests/manual/examples/widgets/richtext/textedit/images/win/textleft.png
new file mode 100644
index 0000000000..16f80bc325
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/textleft.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/textright.png b/tests/manual/examples/widgets/richtext/textedit/images/win/textright.png
new file mode 100644
index 0000000000..16872df62a
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/textright.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/textunder.png b/tests/manual/examples/widgets/richtext/textedit/images/win/textunder.png
new file mode 100644
index 0000000000..c72eff53fb
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/textunder.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/textundercolor.png b/tests/manual/examples/widgets/richtext/textedit/images/win/textundercolor.png
new file mode 100644
index 0000000000..30e24e61c3
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/textundercolor.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/zoomin.png b/tests/manual/examples/widgets/richtext/textedit/images/win/zoomin.png
new file mode 100644
index 0000000000..2e586fc7bf
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/zoomin.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/images/win/zoomout.png b/tests/manual/examples/widgets/richtext/textedit/images/win/zoomout.png
new file mode 100644
index 0000000000..a736d39343
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/images/win/zoomout.png
Binary files differ
diff --git a/tests/manual/examples/widgets/richtext/textedit/main.cpp b/tests/manual/examples/widgets/richtext/textedit/main.cpp
new file mode 100644
index 0000000000..4d46dcd51c
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/main.cpp
@@ -0,0 +1,36 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "textedit.h"
+
+#include <QApplication>
+#include <QCommandLineParser>
+#include <QCommandLineOption>
+#include <QScreen>
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ QCoreApplication::setOrganizationName("QtProject");
+ QCoreApplication::setApplicationName("Rich Text");
+ QCoreApplication::setApplicationVersion(QT_VERSION_STR);
+ QCommandLineParser parser;
+ parser.setApplicationDescription(QCoreApplication::applicationName());
+ parser.addHelpOption();
+ parser.addVersionOption();
+ parser.addPositionalArgument("file", "The file to open.");
+ parser.process(a);
+
+ TextEdit mw;
+
+ const QRect availableGeometry = mw.screen()->availableGeometry();
+ mw.resize(availableGeometry.width() / 2, (availableGeometry.height() * 2) / 3);
+ mw.move((availableGeometry.width() - mw.width()) / 2,
+ (availableGeometry.height() - mw.height()) / 2);
+
+ if (!mw.load(parser.positionalArguments().value(0, QLatin1String(":/example.html"))))
+ mw.fileNew();
+
+ mw.show();
+ return a.exec();
+}
diff --git a/tests/manual/examples/widgets/richtext/textedit/textedit.cpp b/tests/manual/examples/widgets/richtext/textedit/textedit.cpp
new file mode 100644
index 0000000000..5f9e8d87b7
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/textedit.cpp
@@ -0,0 +1,904 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "textedit.h"
+
+#include <QActionGroup>
+#include <QApplication>
+#include <QClipboard>
+#include <QColorDialog>
+#include <QComboBox>
+#include <QFontComboBox>
+#include <QFile>
+#include <QFileDialog>
+#include <QFileInfo>
+#include <QFontDatabase>
+#include <QMenu>
+#include <QMenuBar>
+#include <QTextEdit>
+#include <QStatusBar>
+#include <QToolBar>
+#include <QTextCursor>
+#include <QTextDocumentWriter>
+#include <QTextList>
+#include <QTimer>
+#include <QtDebug>
+#include <QCloseEvent>
+#include <QMessageBox>
+#include <QMimeData>
+#include <QMimeDatabase>
+#include <QStringDecoder>
+#if defined(QT_PRINTSUPPORT_LIB)
+#include <QtPrintSupport/qtprintsupportglobal.h>
+#if QT_CONFIG(printer)
+#if QT_CONFIG(printdialog)
+#include <QPrintDialog>
+#endif
+#include <QPrinter>
+#if QT_CONFIG(printpreviewdialog)
+#include <QPrintPreviewDialog>
+#endif
+#endif
+#endif
+
+#ifdef Q_OS_MAC
+const QString rsrcPath = ":/images/mac";
+#else
+const QString rsrcPath = ":/images/win";
+#endif
+
+TextEdit::TextEdit(QWidget *parent)
+ : QMainWindow(parent)
+{
+#ifdef Q_OS_MACOS
+ setUnifiedTitleAndToolBarOnMac(true);
+#endif
+ setWindowTitle(QCoreApplication::applicationName());
+
+ textEdit = new QTextEdit(this);
+ connect(textEdit, &QTextEdit::currentCharFormatChanged,
+ this, &TextEdit::currentCharFormatChanged);
+ connect(textEdit, &QTextEdit::cursorPositionChanged,
+ this, &TextEdit::cursorPositionChanged);
+ setCentralWidget(textEdit);
+
+ setToolButtonStyle(Qt::ToolButtonFollowStyle);
+ setupFileActions();
+ setupEditActions();
+ setupTextActions();
+
+ {
+ QMenu *helpMenu = menuBar()->addMenu(tr("Help"));
+ helpMenu->addAction(tr("About"), this, &TextEdit::about);
+ helpMenu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt);
+ }
+
+ QFont textFont("Helvetica");
+ textFont.setStyleHint(QFont::SansSerif);
+ textEdit->setFont(textFont);
+ fontChanged(textEdit->font());
+ colorChanged(textEdit->textColor());
+ alignmentChanged(textEdit->alignment());
+
+ auto *document = textEdit->document();
+ connect(document, &QTextDocument::modificationChanged,
+ actionSave, &QAction::setEnabled);
+ connect(document, &QTextDocument::modificationChanged,
+ this, &QWidget::setWindowModified);
+ connect(document, &QTextDocument::undoAvailable,
+ actionUndo, &QAction::setEnabled);
+ connect(document, &QTextDocument::redoAvailable,
+ actionRedo, &QAction::setEnabled);
+
+ setWindowModified(document->isModified());
+ actionSave->setEnabled(document->isModified());
+ actionUndo->setEnabled(document->isUndoAvailable());
+ actionRedo->setEnabled(document->isRedoAvailable());
+
+#ifndef QT_NO_CLIPBOARD
+ actionCut->setEnabled(false);
+ connect(textEdit, &QTextEdit::copyAvailable, actionCut, &QAction::setEnabled);
+ actionCopy->setEnabled(false);
+ connect(textEdit, &QTextEdit::copyAvailable, actionCopy, &QAction::setEnabled);
+
+ connect(QGuiApplication::clipboard(), &QClipboard::dataChanged,
+ this, &TextEdit::clipboardDataChanged);
+#endif
+
+ textEdit->setFocus();
+ setCurrentFileName(QString());
+
+#ifdef Q_OS_MACOS
+ // Use dark text on light background on macOS, also in dark mode.
+ QPalette pal = textEdit->palette();
+ pal.setColor(QPalette::Base, QColor(Qt::white));
+ pal.setColor(QPalette::Text, QColor(Qt::black));
+ textEdit->setPalette(pal);
+#endif
+}
+
+//! [closeevent]
+void TextEdit::closeEvent(QCloseEvent *e)
+{
+ if (closeAccepted) {
+ e->accept();
+ return;
+ }
+
+ e->ignore();
+ maybeSave(SaveContinuation::Close);
+}
+//! [closeevent]
+
+void TextEdit::setupFileActions()
+{
+ QToolBar *tb = addToolBar(tr("File Actions"));
+ QMenu *menu = menuBar()->addMenu(tr("&File"));
+
+ const QIcon newIcon = QIcon::fromTheme("document-new", QIcon(rsrcPath + "/filenew.png"));
+ QAction *a = menu->addAction(newIcon, tr("&New"), this, &TextEdit::fileNew);
+ tb->addAction(a);
+ a->setPriority(QAction::LowPriority);
+ a->setShortcut(QKeySequence::New);
+
+ const QIcon openIcon = QIcon::fromTheme("document-open", QIcon(rsrcPath + "/fileopen.png"));
+ a = menu->addAction(openIcon, tr("&Open..."), this, &TextEdit::fileOpen);
+ a->setShortcut(QKeySequence::Open);
+ tb->addAction(a);
+
+ menu->addSeparator();
+
+ const QIcon saveIcon = QIcon::fromTheme("document-save", QIcon(rsrcPath + "/filesave.png"));
+ actionSave = menu->addAction(saveIcon, tr("&Save"), this,
+ [this]() { fileSave(SaveContinuation::None); });
+ actionSave->setShortcut(QKeySequence::Save);
+ actionSave->setEnabled(false);
+ tb->addAction(actionSave);
+
+ a = menu->addAction(tr("Save &As..."), this, [this]() { fileSaveAs(SaveContinuation::None); });
+ a->setPriority(QAction::LowPriority);
+ menu->addSeparator();
+
+#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
+ const QIcon printIcon = QIcon::fromTheme("document-print", QIcon(rsrcPath + "/fileprint.png"));
+ a = menu->addAction(printIcon, tr("&Print..."), this, &TextEdit::filePrint);
+ a->setPriority(QAction::LowPriority);
+ a->setShortcut(QKeySequence::Print);
+ tb->addAction(a);
+
+ const QIcon filePrintIcon = QIcon::fromTheme("fileprint", QIcon(rsrcPath + "/fileprint.png"));
+ menu->addAction(filePrintIcon, tr("Print Preview..."), this, &TextEdit::filePrintPreview);
+
+ const QIcon exportPdfIcon = QIcon::fromTheme("exportpdf", QIcon(rsrcPath + "/exportpdf.png"));
+ a = menu->addAction(exportPdfIcon, tr("&Export PDF..."), this, &TextEdit::filePrintPdf);
+ a->setPriority(QAction::LowPriority);
+ a->setShortcut(Qt::CTRL | Qt::Key_D);
+ tb->addAction(a);
+
+ menu->addSeparator();
+#endif
+
+ a = menu->addAction(tr("&Quit"), qApp, &QCoreApplication::quit);
+ a->setShortcut(Qt::CTRL | Qt::Key_Q);
+}
+
+void TextEdit::setupEditActions()
+{
+ QToolBar *tb = addToolBar(tr("Edit Actions"));
+ QMenu *menu = menuBar()->addMenu(tr("&Edit"));
+
+ const QIcon undoIcon = QIcon::fromTheme("edit-undo", QIcon(rsrcPath + "/editundo.png"));
+ actionUndo = menu->addAction(undoIcon, tr("&Undo"), textEdit, &QTextEdit::undo);
+ actionUndo->setShortcut(QKeySequence::Undo);
+ tb->addAction(actionUndo);
+
+ const QIcon redoIcon = QIcon::fromTheme("edit-redo", QIcon(rsrcPath + "/editredo.png"));
+ actionRedo = menu->addAction(redoIcon, tr("&Redo"), textEdit, &QTextEdit::redo);
+ actionRedo->setPriority(QAction::LowPriority);
+ actionRedo->setShortcut(QKeySequence::Redo);
+ tb->addAction(actionRedo);
+ menu->addSeparator();
+
+#ifndef QT_NO_CLIPBOARD
+ const QIcon cutIcon = QIcon::fromTheme("edit-cut", QIcon(rsrcPath + "/editcut.png"));
+ actionCut = menu->addAction(cutIcon, tr("Cu&t"), textEdit, &QTextEdit::cut);
+ actionCut->setPriority(QAction::LowPriority);
+ actionCut->setShortcut(QKeySequence::Cut);
+ tb->addAction(actionCut);
+
+ const QIcon copyIcon = QIcon::fromTheme("edit-copy", QIcon(rsrcPath + "/editcopy.png"));
+ actionCopy = menu->addAction(copyIcon, tr("&Copy"), textEdit, &QTextEdit::copy);
+ actionCopy->setPriority(QAction::LowPriority);
+ actionCopy->setShortcut(QKeySequence::Copy);
+ tb->addAction(actionCopy);
+
+ const QIcon pasteIcon = QIcon::fromTheme("edit-paste", QIcon(rsrcPath + "/editpaste.png"));
+ actionPaste = menu->addAction(pasteIcon, tr("&Paste"), textEdit, &QTextEdit::paste);
+ actionPaste->setPriority(QAction::LowPriority);
+ actionPaste->setShortcut(QKeySequence::Paste);
+ tb->addAction(actionPaste);
+ if (const QMimeData *md = QGuiApplication::clipboard()->mimeData())
+ actionPaste->setEnabled(md->hasText());
+#endif
+}
+
+void TextEdit::setupTextActions()
+{
+ QToolBar *tb = addToolBar(tr("Format Actions"));
+ QMenu *menu = menuBar()->addMenu(tr("F&ormat"));
+
+ const QIcon boldIcon = QIcon::fromTheme("format-text-bold", QIcon(rsrcPath + "/textbold.png"));
+ actionTextBold = menu->addAction(boldIcon, tr("&Bold"), this, &TextEdit::textBold);
+ actionTextBold->setShortcut(Qt::CTRL | Qt::Key_B);
+ actionTextBold->setPriority(QAction::LowPriority);
+ QFont bold;
+ bold.setBold(true);
+ actionTextBold->setFont(bold);
+ tb->addAction(actionTextBold);
+ actionTextBold->setCheckable(true);
+
+ const QIcon italicIcon = QIcon::fromTheme("format-text-italic", QIcon(rsrcPath + "/textitalic.png"));
+ actionTextItalic = menu->addAction(italicIcon, tr("&Italic"), this, &TextEdit::textItalic);
+ actionTextItalic->setPriority(QAction::LowPriority);
+ actionTextItalic->setShortcut(Qt::CTRL | Qt::Key_I);
+ QFont italic;
+ italic.setItalic(true);
+ actionTextItalic->setFont(italic);
+ tb->addAction(actionTextItalic);
+ actionTextItalic->setCheckable(true);
+
+ const QIcon underlineIcon = QIcon::fromTheme("format-text-underline", QIcon(rsrcPath + "/textunder.png"));
+ actionTextUnderline = menu->addAction(underlineIcon, tr("&Underline"), this, &TextEdit::textUnderline);
+ actionTextUnderline->setShortcut(Qt::CTRL | Qt::Key_U);
+ actionTextUnderline->setPriority(QAction::LowPriority);
+ QFont underline;
+ underline.setUnderline(true);
+ actionTextUnderline->setFont(underline);
+ tb->addAction(actionTextUnderline);
+ actionTextUnderline->setCheckable(true);
+
+ menu->addSeparator();
+
+ const QIcon leftIcon = QIcon::fromTheme("format-justify-left", QIcon(rsrcPath + "/textleft.png"));
+ actionAlignLeft = new QAction(leftIcon, tr("&Left"), this);
+ actionAlignLeft->setShortcut(Qt::CTRL | Qt::Key_L);
+ actionAlignLeft->setCheckable(true);
+ actionAlignLeft->setPriority(QAction::LowPriority);
+ const QIcon centerIcon = QIcon::fromTheme("format-justify-center", QIcon(rsrcPath + "/textcenter.png"));
+ actionAlignCenter = new QAction(centerIcon, tr("C&enter"), this);
+ actionAlignCenter->setShortcut(Qt::CTRL | Qt::Key_E);
+ actionAlignCenter->setCheckable(true);
+ actionAlignCenter->setPriority(QAction::LowPriority);
+ const QIcon rightIcon = QIcon::fromTheme("format-justify-right", QIcon(rsrcPath + "/textright.png"));
+ actionAlignRight = new QAction(rightIcon, tr("&Right"), this);
+ actionAlignRight->setShortcut(Qt::CTRL | Qt::Key_R);
+ actionAlignRight->setCheckable(true);
+ actionAlignRight->setPriority(QAction::LowPriority);
+ const QIcon fillIcon = QIcon::fromTheme("format-justify-fill", QIcon(rsrcPath + "/textjustify.png"));
+ actionAlignJustify = new QAction(fillIcon, tr("&Justify"), this);
+ actionAlignJustify->setShortcut(Qt::CTRL | Qt::Key_J);
+ actionAlignJustify->setCheckable(true);
+ actionAlignJustify->setPriority(QAction::LowPriority);
+ const QIcon indentMoreIcon = QIcon::fromTheme("format-indent-more", QIcon(rsrcPath + "/format-indent-more.png"));
+ actionIndentMore = menu->addAction(indentMoreIcon, tr("&Indent"), this, &TextEdit::indent);
+ actionIndentMore->setShortcut(Qt::CTRL | Qt::Key_BracketRight);
+ actionIndentMore->setPriority(QAction::LowPriority);
+ const QIcon indentLessIcon = QIcon::fromTheme("format-indent-less", QIcon(rsrcPath + "/format-indent-less.png"));
+ actionIndentLess = menu->addAction(indentLessIcon, tr("&Unindent"), this, &TextEdit::unindent);
+ actionIndentLess->setShortcut(Qt::CTRL | Qt::Key_BracketLeft);
+ actionIndentLess->setPriority(QAction::LowPriority);
+
+ // Make sure the alignLeft is always left of the alignRight
+ QActionGroup *alignGroup = new QActionGroup(this);
+ connect(alignGroup, &QActionGroup::triggered, this, &TextEdit::textAlign);
+
+ if (QGuiApplication::isLeftToRight()) {
+ alignGroup->addAction(actionAlignLeft);
+ alignGroup->addAction(actionAlignCenter);
+ alignGroup->addAction(actionAlignRight);
+ } else {
+ alignGroup->addAction(actionAlignRight);
+ alignGroup->addAction(actionAlignCenter);
+ alignGroup->addAction(actionAlignLeft);
+ }
+ alignGroup->addAction(actionAlignJustify);
+
+ tb->addActions(alignGroup->actions());
+ menu->addActions(alignGroup->actions());
+ tb->addAction(actionIndentMore);
+ tb->addAction(actionIndentLess);
+ menu->addAction(actionIndentMore);
+ menu->addAction(actionIndentLess);
+
+ menu->addSeparator();
+
+ QPixmap pix(16, 16);
+ pix.fill(Qt::black);
+ actionTextColor = menu->addAction(pix, tr("&Color..."), this, &TextEdit::textColor);
+ tb->addAction(actionTextColor);
+
+ const QIcon underlineColorIcon(rsrcPath + "/textundercolor.png");
+ actionUnderlineColor = menu->addAction(underlineColorIcon, tr("Underline color..."), this, &TextEdit::underlineColor);
+ tb->addAction(actionUnderlineColor);
+
+ menu->addSeparator();
+
+ const QIcon checkboxIcon = QIcon::fromTheme("status-checkbox-checked", QIcon(rsrcPath + "/checkbox-checked.png"));
+ actionToggleCheckState = menu->addAction(checkboxIcon, tr("Chec&ked"), this, &TextEdit::setChecked);
+ actionToggleCheckState->setShortcut(Qt::CTRL | Qt::Key_K);
+ actionToggleCheckState->setCheckable(true);
+ actionToggleCheckState->setPriority(QAction::LowPriority);
+ tb->addAction(actionToggleCheckState);
+
+ tb = addToolBar(tr("Format Actions"));
+ tb->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
+ addToolBarBreak(Qt::TopToolBarArea);
+ addToolBar(tb);
+
+ comboStyle = new QComboBox(tb);
+ tb->addWidget(comboStyle);
+ comboStyle->addItems({"Standard",
+ "Bullet List (Disc)",
+ "Bullet List (Circle)",
+ "Bullet List (Square)",
+ "Task List (Unchecked)",
+ "Task List (Checked)",
+ "Ordered List (Decimal)",
+ "Ordered List (Alpha lower)",
+ "Ordered List (Alpha upper)",
+ "Ordered List (Roman lower)",
+ "Ordered List (Roman upper)",
+ "Heading 1",
+ "Heading 2",
+ "Heading 3",
+ "Heading 4",
+ "Heading 5",
+ "Heading 6"}),
+
+ connect(comboStyle, &QComboBox::activated, this, &TextEdit::textStyle);
+
+ comboFont = new QFontComboBox(tb);
+ tb->addWidget(comboFont);
+ connect(comboFont, &QComboBox::textActivated, this, &TextEdit::textFamily);
+
+ comboSize = new QComboBox(tb);
+ comboSize->setObjectName("comboSize");
+ tb->addWidget(comboSize);
+ comboSize->setEditable(true);
+
+ const QList<int> standardSizes = QFontDatabase::standardSizes();
+ for (int size : standardSizes)
+ comboSize->addItem(QString::number(size));
+ comboSize->setCurrentIndex(standardSizes.indexOf(QApplication::font().pointSize()));
+
+ connect(comboSize, &QComboBox::textActivated, this, &TextEdit::textSize);
+}
+
+bool TextEdit::load(const QString &f)
+{
+ if (!QFile::exists(f))
+ return false;
+ QFile file(f);
+ if (!file.open(QFile::ReadOnly))
+ return false;
+
+ QByteArray data = file.readAll();
+ QMimeDatabase db;
+ const QString &mimeTypeName = db.mimeTypeForFileNameAndData(f, data).name();
+ if (mimeTypeName == u"text/html") {
+ auto encoding = QStringDecoder::encodingForHtml(data);
+ QString str = QStringDecoder(encoding ? *encoding : QStringDecoder::Utf8)(data);
+ QUrl fileUrl = f.startsWith(u':') ? QUrl(f) : QUrl::fromLocalFile(f);
+ textEdit->document()->setBaseUrl(fileUrl.adjusted(QUrl::RemoveFilename));
+ textEdit->setHtml(str);
+#if QT_CONFIG(textmarkdownreader)
+ } else if (mimeTypeName == u"text/markdown") {
+ textEdit->setMarkdown(QString::fromUtf8(data));
+#endif
+ } else {
+ textEdit->setPlainText(QString::fromUtf8(data));
+ }
+
+ setCurrentFileName(f);
+ return true;
+}
+
+void TextEdit::maybeSave(SaveContinuation continuation)
+{
+ if (!textEdit->document()->isModified()) {
+ // Execute continuation as soon as control has returned to the event loop so that existing
+ // dialogs do not get in the way of closing the window.
+ QTimer::singleShot(0, [this, continuation]() { fileSaveComplete(continuation); });
+ return;
+ }
+
+ QMessageBox *msgBox =
+ new QMessageBox(QMessageBox::Icon::Warning, QCoreApplication::applicationName(),
+ tr("The document has been modified.\n"
+ "Do you want to save your changes?"),
+ QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel, this);
+
+ connect(msgBox, &QMessageBox::finished, [=](int result) {
+ if (result == QMessageBox::Save) {
+ fileSave(continuation);
+ return;
+ }
+ fileSaveComplete(result == QMessageBox::Discard ? continuation : SaveContinuation::None);
+ });
+
+ msgBox->setAttribute(Qt::WA_DeleteOnClose);
+ msgBox->open();
+}
+
+void TextEdit::setCurrentFileName(const QString &fileName)
+{
+ this->fileName = fileName;
+ textEdit->document()->setModified(false);
+
+ QString shownName;
+ if (fileName.isEmpty())
+ shownName = "untitled.txt";
+ else
+ shownName = QFileInfo(fileName).fileName();
+
+ setWindowTitle(tr("%1[*] - %2").arg(shownName, QCoreApplication::applicationName()));
+ setWindowModified(false);
+}
+
+void TextEdit::fileNew()
+{
+ maybeSave(SaveContinuation::Clear);
+}
+
+void TextEdit::fileOpen()
+{
+ QFileDialog *fileDialog = new QFileDialog(this, tr("Open File..."));
+ fileDialog->setAcceptMode(QFileDialog::AcceptOpen);
+ fileDialog->setFileMode(QFileDialog::ExistingFile);
+ fileDialog->setMimeTypeFilters({
+#if QT_CONFIG(texthtmlparser)
+ "text/html",
+#endif
+#if QT_CONFIG(textmarkdownreader)
+
+ "text/markdown",
+#endif
+ "text/plain"});
+
+ connect(fileDialog, &QFileDialog::fileSelected, [=](const QString &file) {
+ statusBar()->showMessage(
+ load(file) ? tr(R"(Opened "%1")").arg(QDir::toNativeSeparators(file))
+ : tr(R"(Could not open "%1")").arg(QDir::toNativeSeparators(file)));
+ });
+ fileDialog->setAttribute(Qt::WA_DeleteOnClose);
+ fileDialog->open();
+}
+
+void TextEdit::fileSave(SaveContinuation continuation)
+{
+ if (fileName.isEmpty() || fileName.startsWith(u":/"))
+ return fileSaveAs(continuation);
+
+ QTextDocumentWriter writer(fileName);
+ bool success = writer.write(textEdit->document());
+ if (success) {
+ textEdit->document()->setModified(false);
+ statusBar()->showMessage(tr("Wrote \"%1\"").arg(QDir::toNativeSeparators(fileName)));
+ } else {
+ statusBar()->showMessage(tr("Could not write to file \"%1\"")
+ .arg(QDir::toNativeSeparators(fileName)));
+ }
+ fileSaveComplete(success ? continuation : SaveContinuation::None);
+}
+
+void TextEdit::fileSaveAs(SaveContinuation continuation)
+{
+ QFileDialog *fileDialog = new QFileDialog(this, tr("Save as..."));
+ fileDialog->setAcceptMode(QFileDialog::AcceptSave);
+ QStringList mimeTypes{"text/plain",
+#if QT_CONFIG(textodfwriter)
+ "application/vnd.oasis.opendocument.text",
+#endif
+#if QT_CONFIG(textmarkdownwriter)
+ "text/markdown",
+#endif
+ "text/html"};
+ fileDialog->setMimeTypeFilters(mimeTypes);
+#if QT_CONFIG(textodfwriter)
+ fileDialog->setDefaultSuffix("odt");
+#endif
+ connect(fileDialog, &QFileDialog::finished, [this, continuation, fileDialog](int result) {
+ if (result != QDialog::Accepted)
+ return;
+ setCurrentFileName(fileDialog->selectedFiles().constFirst());
+ fileSave(continuation);
+ });
+ fileDialog->setAttribute(Qt::WA_DeleteOnClose);
+ fileDialog->open();
+}
+
+void TextEdit::fileSaveComplete(SaveContinuation continuation)
+{
+ switch (continuation) {
+ case SaveContinuation::Clear:
+ textEdit->clear();
+ setCurrentFileName({});
+ return;
+ case SaveContinuation::Close:
+ closeAccepted = true;
+ close();
+ return;
+ case SaveContinuation::None:
+ // NOOP as promised
+ return;
+ }
+}
+
+void TextEdit::filePrint()
+{
+#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog)
+ auto printer = std::make_shared<QPrinter>(QPrinter::HighResolution);
+ QPrintDialog *dlg = new QPrintDialog(printer.get(), this);
+ if (textEdit->textCursor().hasSelection())
+ dlg->setOption(QAbstractPrintDialog::PrintSelection);
+ dlg->setWindowTitle(tr("Print Document"));
+ dlg->setAttribute(Qt::WA_DeleteOnClose);
+ connect(dlg, qOverload<QPrinter *>(&QPrintDialog::accepted),
+ [this](QPrinter *printer) { textEdit->print(printer); });
+ connect(dlg, &QPrintDialog::finished, [printer]() mutable { printer.reset(); });
+ dlg->open();
+#endif
+}
+
+void TextEdit::filePrintPreview()
+{
+#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printpreviewdialog)
+ auto printer = std::make_shared<QPrinter>(QPrinter::HighResolution);
+ QPrintPreviewDialog *preview = new QPrintPreviewDialog(printer.get(), this);
+ preview->setAttribute(Qt::WA_DeleteOnClose);
+ connect(preview, &QPrintPreviewDialog::paintRequested, textEdit, &QTextEdit::print);
+ connect(preview, &QPrintPreviewDialog::finished, [printer]() mutable { printer.reset(); });
+ preview->open();
+#endif
+}
+
+void TextEdit::filePrintPdf()
+{
+#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
+ QFileDialog *fileDialog = new QFileDialog(this, tr("Export PDF"));
+ fileDialog->setAcceptMode(QFileDialog::AcceptSave);
+ fileDialog->setMimeTypeFilters(QStringList("application/pdf"));
+ fileDialog->setDefaultSuffix("pdf");
+ fileDialog->setAttribute(Qt::WA_DeleteOnClose);
+ connect(fileDialog, &QFileDialog::fileSelected, [this](const QString &file) {
+ QPrinter printer(QPrinter::HighResolution);
+ printer.setOutputFormat(QPrinter::PdfFormat);
+ printer.setOutputFileName(file);
+ textEdit->document()->print(&printer);
+ statusBar()->showMessage(tr("Exported \"%1\"").arg(QDir::toNativeSeparators(file)));
+ });
+
+ fileDialog->open();
+#endif
+}
+
+void TextEdit::textBold()
+{
+ QTextCharFormat fmt;
+ fmt.setFontWeight(actionTextBold->isChecked() ? QFont::Bold : QFont::Normal);
+ mergeFormatOnWordOrSelection(fmt);
+}
+
+void TextEdit::textUnderline()
+{
+ QTextCharFormat fmt;
+ fmt.setFontUnderline(actionTextUnderline->isChecked());
+ mergeFormatOnWordOrSelection(fmt);
+}
+
+void TextEdit::textItalic()
+{
+ QTextCharFormat fmt;
+ fmt.setFontItalic(actionTextItalic->isChecked());
+ mergeFormatOnWordOrSelection(fmt);
+}
+
+void TextEdit::textFamily(const QString &f)
+{
+ QTextCharFormat fmt;
+ fmt.setFontFamilies({f});
+ mergeFormatOnWordOrSelection(fmt);
+}
+
+void TextEdit::textSize(const QString &p)
+{
+ qreal pointSize = p.toFloat();
+ if (pointSize > 0) {
+ QTextCharFormat fmt;
+ fmt.setFontPointSize(pointSize);
+ mergeFormatOnWordOrSelection(fmt);
+ }
+}
+
+void TextEdit::textStyle(int styleIndex)
+{
+ QTextCursor cursor = textEdit->textCursor();
+ QTextListFormat::Style style = QTextListFormat::ListStyleUndefined;
+ QTextBlockFormat::MarkerType marker = QTextBlockFormat::MarkerType::NoMarker;
+
+ switch (styleIndex) {
+ case 1:
+ style = QTextListFormat::ListDisc;
+ break;
+ case 2:
+ style = QTextListFormat::ListCircle;
+ break;
+ case 3:
+ style = QTextListFormat::ListSquare;
+ break;
+ case 4:
+ if (cursor.currentList())
+ style = cursor.currentList()->format().style();
+ else
+ style = QTextListFormat::ListDisc;
+ marker = QTextBlockFormat::MarkerType::Unchecked;
+ break;
+ case 5:
+ if (cursor.currentList())
+ style = cursor.currentList()->format().style();
+ else
+ style = QTextListFormat::ListDisc;
+ marker = QTextBlockFormat::MarkerType::Checked;
+ break;
+ case 6:
+ style = QTextListFormat::ListDecimal;
+ break;
+ case 7:
+ style = QTextListFormat::ListLowerAlpha;
+ break;
+ case 8:
+ style = QTextListFormat::ListUpperAlpha;
+ break;
+ case 9:
+ style = QTextListFormat::ListLowerRoman;
+ break;
+ case 10:
+ style = QTextListFormat::ListUpperRoman;
+ break;
+ default:
+ break;
+ }
+
+ cursor.beginEditBlock();
+
+ QTextBlockFormat blockFmt = cursor.blockFormat();
+
+ if (style == QTextListFormat::ListStyleUndefined) {
+ blockFmt.setObjectIndex(-1);
+ int headingLevel = styleIndex >= 11 ? styleIndex - 11 + 1 : 0; // H1 to H6, or Standard
+ blockFmt.setHeadingLevel(headingLevel);
+ cursor.setBlockFormat(blockFmt);
+
+ int sizeAdjustment = headingLevel ? 4 - headingLevel : 0; // H1 to H6: +3 to -2
+ QTextCharFormat fmt;
+ fmt.setFontWeight(headingLevel ? QFont::Bold : QFont::Normal);
+ fmt.setProperty(QTextFormat::FontSizeAdjustment, sizeAdjustment);
+ cursor.select(QTextCursor::LineUnderCursor);
+ cursor.mergeCharFormat(fmt);
+ textEdit->mergeCurrentCharFormat(fmt);
+ } else {
+ blockFmt.setMarker(marker);
+ cursor.setBlockFormat(blockFmt);
+ QTextListFormat listFmt;
+ if (cursor.currentList()) {
+ listFmt = cursor.currentList()->format();
+ } else {
+ listFmt.setIndent(blockFmt.indent() + 1);
+ blockFmt.setIndent(0);
+ cursor.setBlockFormat(blockFmt);
+ }
+ listFmt.setStyle(style);
+ cursor.createList(listFmt);
+ }
+
+ cursor.endEditBlock();
+}
+
+void TextEdit::textColor()
+{
+ QColorDialog *dlg = new QColorDialog(this);
+ dlg->setCurrentColor(textEdit->textColor());
+ connect(dlg, &QColorDialog::colorSelected, [this](const QColor &color) {
+ if (!color.isValid())
+ return;
+ QTextCharFormat fmt;
+ fmt.setForeground(color);
+ mergeFormatOnWordOrSelection(fmt);
+ colorChanged(color);
+ });
+ dlg->setAttribute(Qt::WA_DeleteOnClose);
+ dlg->open();
+}
+
+void TextEdit::underlineColor()
+{
+ QColorDialog *dlg = new QColorDialog(this);
+ dlg->setCurrentColor(textEdit->textColor());
+ connect(dlg, &QColorDialog::colorSelected, [this](const QColor &color) {
+ if (!color.isValid())
+ return;
+ QTextCharFormat fmt;
+ fmt.setUnderlineColor(color);
+ mergeFormatOnWordOrSelection(fmt);
+ colorChanged(color);
+ });
+ dlg->setAttribute(Qt::WA_DeleteOnClose);
+ dlg->open();
+}
+
+void TextEdit::textAlign(QAction *a)
+{
+ if (a == actionAlignLeft)
+ textEdit->setAlignment(Qt::AlignLeft | Qt::AlignAbsolute);
+ else if (a == actionAlignCenter)
+ textEdit->setAlignment(Qt::AlignHCenter);
+ else if (a == actionAlignRight)
+ textEdit->setAlignment(Qt::AlignRight | Qt::AlignAbsolute);
+ else if (a == actionAlignJustify)
+ textEdit->setAlignment(Qt::AlignJustify);
+}
+
+void TextEdit::setChecked(bool checked)
+{
+ textStyle(checked ? 5 : 4);
+}
+
+void TextEdit::indent()
+{
+ modifyIndentation(1);
+}
+
+void TextEdit::unindent()
+{
+ modifyIndentation(-1);
+}
+
+void TextEdit::modifyIndentation(int amount)
+{
+ QTextCursor cursor = textEdit->textCursor();
+ cursor.beginEditBlock();
+ if (cursor.currentList()) {
+ QTextListFormat listFmt = cursor.currentList()->format();
+ // See whether the line above is the list we want to move this item into,
+ // or whether we need a new list.
+ QTextCursor above(cursor);
+ above.movePosition(QTextCursor::Up);
+ if (above.currentList() && listFmt.indent() + amount == above.currentList()->format().indent()) {
+ above.currentList()->add(cursor.block());
+ } else {
+ listFmt.setIndent(listFmt.indent() + amount);
+ cursor.createList(listFmt);
+ }
+ } else {
+ QTextBlockFormat blockFmt = cursor.blockFormat();
+ blockFmt.setIndent(blockFmt.indent() + amount);
+ cursor.setBlockFormat(blockFmt);
+ }
+ cursor.endEditBlock();
+}
+
+void TextEdit::currentCharFormatChanged(const QTextCharFormat &format)
+{
+ fontChanged(format.font());
+ colorChanged(format.foreground().color());
+}
+
+void TextEdit::cursorPositionChanged()
+{
+ alignmentChanged(textEdit->alignment());
+ QTextList *list = textEdit->textCursor().currentList();
+ if (list) {
+ switch (list->format().style()) {
+ case QTextListFormat::ListDisc:
+ comboStyle->setCurrentIndex(1);
+ break;
+ case QTextListFormat::ListCircle:
+ comboStyle->setCurrentIndex(2);
+ break;
+ case QTextListFormat::ListSquare:
+ comboStyle->setCurrentIndex(3);
+ break;
+ case QTextListFormat::ListDecimal:
+ comboStyle->setCurrentIndex(6);
+ break;
+ case QTextListFormat::ListLowerAlpha:
+ comboStyle->setCurrentIndex(7);
+ break;
+ case QTextListFormat::ListUpperAlpha:
+ comboStyle->setCurrentIndex(8);
+ break;
+ case QTextListFormat::ListLowerRoman:
+ comboStyle->setCurrentIndex(9);
+ break;
+ case QTextListFormat::ListUpperRoman:
+ comboStyle->setCurrentIndex(10);
+ break;
+ default:
+ comboStyle->setCurrentIndex(-1);
+ break;
+ }
+ switch (textEdit->textCursor().block().blockFormat().marker()) {
+ case QTextBlockFormat::MarkerType::NoMarker:
+ actionToggleCheckState->setChecked(false);
+ break;
+ case QTextBlockFormat::MarkerType::Unchecked:
+ comboStyle->setCurrentIndex(4);
+ actionToggleCheckState->setChecked(false);
+ break;
+ case QTextBlockFormat::MarkerType::Checked:
+ comboStyle->setCurrentIndex(5);
+ actionToggleCheckState->setChecked(true);
+ break;
+ }
+ } else {
+ int headingLevel = textEdit->textCursor().blockFormat().headingLevel();
+ comboStyle->setCurrentIndex(headingLevel ? headingLevel + 10 : 0);
+ }
+}
+
+void TextEdit::clipboardDataChanged()
+{
+#ifndef QT_NO_CLIPBOARD
+ if (const QMimeData *md = QGuiApplication::clipboard()->mimeData())
+ actionPaste->setEnabled(md->hasText());
+#endif
+}
+
+void TextEdit::about()
+{
+ QMessageBox *msgBox =
+ new QMessageBox(QMessageBox::Icon::Information, tr("About"),
+ tr("This example demonstrates Qt's rich text editing facilities in "
+ "action, providing an example document for you to experiment with."),
+ QMessageBox::NoButton, this);
+ msgBox->setAttribute(Qt::WA_DeleteOnClose);
+ msgBox->open();
+}
+
+void TextEdit::mergeFormatOnWordOrSelection(const QTextCharFormat &format)
+{
+ QTextCursor cursor = textEdit->textCursor();
+ if (!cursor.hasSelection())
+ cursor.select(QTextCursor::WordUnderCursor);
+ cursor.mergeCharFormat(format);
+ textEdit->mergeCurrentCharFormat(format);
+}
+
+void TextEdit::fontChanged(const QFont &f)
+{
+ comboFont->setCurrentIndex(comboFont->findText(QFontInfo(f).family()));
+ comboSize->setCurrentIndex(comboSize->findText(QString::number(f.pointSize())));
+ actionTextBold->setChecked(f.bold());
+ actionTextItalic->setChecked(f.italic());
+ actionTextUnderline->setChecked(f.underline());
+}
+
+void TextEdit::colorChanged(const QColor &c)
+{
+ QPixmap pix(16, 16);
+ pix.fill(c);
+ actionTextColor->setIcon(pix);
+}
+
+void TextEdit::alignmentChanged(Qt::Alignment a)
+{
+ if (a.testFlag(Qt::AlignLeft))
+ actionAlignLeft->setChecked(true);
+ else if (a.testFlag(Qt::AlignHCenter))
+ actionAlignCenter->setChecked(true);
+ else if (a.testFlag(Qt::AlignRight))
+ actionAlignRight->setChecked(true);
+ else if (a.testFlag(Qt::AlignJustify))
+ actionAlignJustify->setChecked(true);
+}
+
diff --git a/tests/manual/examples/widgets/richtext/textedit/textedit.h b/tests/manual/examples/widgets/richtext/textedit/textedit.h
new file mode 100644
index 0000000000..f0f4abb827
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/textedit.h
@@ -0,0 +1,110 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef TEXTEDIT_H
+#define TEXTEDIT_H
+
+#include <QMainWindow>
+
+QT_BEGIN_NAMESPACE
+class QAction;
+class QComboBox;
+class QFontComboBox;
+class QTextEdit;
+class QTextCharFormat;
+class QMenu;
+class QPrinter;
+QT_END_NAMESPACE
+
+class TextEdit : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ TextEdit(QWidget *parent = nullptr);
+
+ bool load(const QString &f);
+
+public slots:
+ void fileNew();
+
+protected:
+ void closeEvent(QCloseEvent *e) override;
+
+private:
+ enum class SaveContinuation { None, Close, Clear };
+
+private slots:
+ void fileOpen();
+ void filePrint();
+ void filePrintPreview();
+ void filePrintPdf();
+
+ void textBold();
+ void textUnderline();
+ void textItalic();
+ void textFamily(const QString &f);
+ void textSize(const QString &p);
+ void textStyle(int styleIndex);
+ void textColor();
+ void underlineColor();
+ void textAlign(QAction *a);
+ void setChecked(bool checked);
+ void indent();
+ void unindent();
+
+ void currentCharFormatChanged(const QTextCharFormat &format);
+ void cursorPositionChanged();
+
+ void clipboardDataChanged();
+ void about();
+
+private:
+ void setupFileActions();
+ void setupEditActions();
+ void setupTextActions();
+ void maybeSave(SaveContinuation saveContinuation);
+ void setCurrentFileName(const QString &fileName);
+ void modifyIndentation(int amount);
+
+ void mergeFormatOnWordOrSelection(const QTextCharFormat &format);
+ void fontChanged(const QFont &f);
+ void colorChanged(const QColor &c);
+ void alignmentChanged(Qt::Alignment a);
+
+ void fileSave(SaveContinuation continuation);
+ void fileSaveAs(SaveContinuation continuation);
+ void fileSaveComplete(SaveContinuation continuation);
+
+ QAction *actionSave;
+ QAction *actionTextBold;
+ QAction *actionTextUnderline;
+ QAction *actionTextItalic;
+ QAction *actionTextColor;
+ QAction *actionUnderlineColor;
+ QAction *actionAlignLeft;
+ QAction *actionAlignCenter;
+ QAction *actionAlignRight;
+ QAction *actionAlignJustify;
+ QAction *actionIndentLess;
+ QAction *actionIndentMore;
+ QAction *actionToggleCheckState;
+ QAction *actionUndo;
+ QAction *actionRedo;
+#ifndef QT_NO_CLIPBOARD
+ QAction *actionCut;
+ QAction *actionCopy;
+ QAction *actionPaste;
+#endif
+
+ QComboBox *comboStyle;
+ QFontComboBox *comboFont;
+ QComboBox *comboSize;
+
+ QString fileName;
+ QTextEdit *textEdit;
+
+ bool closeAccepted = false;
+};
+
+#endif // TEXTEDIT_H
diff --git a/tests/manual/examples/widgets/richtext/textedit/textedit.pro b/tests/manual/examples/widgets/richtext/textedit/textedit.pro
new file mode 100644
index 0000000000..b7a2155b0b
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/textedit.pro
@@ -0,0 +1,22 @@
+QT += widgets
+requires(qtConfig(filedialog))
+qtHaveModule(printsupport): QT += printsupport
+
+TEMPLATE = app
+TARGET = textedit
+
+HEADERS = textedit.h
+SOURCES = textedit.cpp \
+ main.cpp
+
+RESOURCES += textedit.qrc
+build_all:!build_pass {
+ CONFIG -= build_all
+ CONFIG += release
+}
+
+EXAMPLE_FILES = textedit.qdoc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/widgets/richtext/textedit
+INSTALLS += target
diff --git a/tests/manual/examples/widgets/richtext/textedit/textedit.qdoc b/tests/manual/examples/widgets/richtext/textedit/textedit.qdoc
new file mode 100644
index 0000000000..ce574353b4
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/textedit.qdoc
@@ -0,0 +1,20 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*! \page textedit-example.html
+
+ \ingroup examples
+ \title Text Edit Example
+
+ \brief This example displays a text editor with the user interface written
+ in pure C++.
+
+ A similar example which uses \QD to produce the user
+ interface is in the \l {Qt Widgets Designer Manual}.
+
+
+ See \c{$QTDIR/examples/textedit} for the source code.
+
+*/
+
+
diff --git a/tests/manual/examples/widgets/richtext/textedit/textedit.qrc b/tests/manual/examples/widgets/richtext/textedit/textedit.qrc
new file mode 100644
index 0000000000..a30d50fdbf
--- /dev/null
+++ b/tests/manual/examples/widgets/richtext/textedit/textedit.qrc
@@ -0,0 +1,54 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/">
+ <file>images/logo32.png</file>
+ <file>images/mac/checkbox.png</file>
+ <file>images/mac/checkbox-checked.png</file>
+ <file>images/mac/editcopy.png</file>
+ <file>images/mac/editcut.png</file>
+ <file>images/mac/editpaste.png</file>
+ <file>images/mac/editredo.png</file>
+ <file>images/mac/editundo.png</file>
+ <file>images/mac/exportpdf.png</file>
+ <file>images/mac/filenew.png</file>
+ <file>images/mac/fileopen.png</file>
+ <file>images/mac/fileprint.png</file>
+ <file>images/mac/filesave.png</file>
+ <file>images/mac/format-indent-less.png</file>
+ <file>images/mac/format-indent-more.png</file>
+ <file>images/mac/textbold.png</file>
+ <file>images/mac/textcenter.png</file>
+ <file>images/mac/textitalic.png</file>
+ <file>images/mac/textjustify.png</file>
+ <file>images/mac/textleft.png</file>
+ <file>images/mac/textright.png</file>
+ <file>images/mac/textunder.png</file>
+ <file>images/mac/textundercolor.png</file>
+ <file>images/mac/zoomin.png</file>
+ <file>images/mac/zoomout.png</file>
+ <file>images/win/checkbox.png</file>
+ <file>images/win/checkbox-checked.png</file>
+ <file>images/win/editcopy.png</file>
+ <file>images/win/editcut.png</file>
+ <file>images/win/editpaste.png</file>
+ <file>images/win/editredo.png</file>
+ <file>images/win/editundo.png</file>
+ <file>images/win/exportpdf.png</file>
+ <file>images/win/filenew.png</file>
+ <file>images/win/fileopen.png</file>
+ <file>images/win/fileprint.png</file>
+ <file>images/win/filesave.png</file>
+ <file>images/win/format-indent-less.png</file>
+ <file>images/win/format-indent-more.png</file>
+ <file>images/win/textbold.png</file>
+ <file>images/win/textcenter.png</file>
+ <file>images/win/textitalic.png</file>
+ <file>images/win/textjustify.png</file>
+ <file>images/win/textleft.png</file>
+ <file>images/win/textright.png</file>
+ <file>images/win/textunder.png</file>
+ <file>images/win/textundercolor.png</file>
+ <file>images/win/zoomin.png</file>
+ <file>images/win/zoomout.png</file>
+ <file>example.html</file>
+</qresource>
+</RCC>