aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2024-03-05 22:15:44 -0700
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-03-19 05:13:51 +0000
commit81dfaa0fcb06b2667b248d5f9137b9e636a3576a (patch)
tree96326f1643a172dc446a665fe03dc41140d30586
parent1e7b19af808c561b2954751a193757402a25afea (diff)
Update Controls Text Editor example and docs
a27b75c89da31a9ed1cf6dc6f6d3f3514ad28f8e doesn't work in its entirety on 6.7 branch; but this patch applies the parts that are possible. These docs have been adapted from the version in 6217408799c43869b8a7c1fcbff882d42ae71171. We update the html and markdown example files. We also move ScrollBar to make explanation easier. Change-Id: If65de335f840382b5e236d8a04db382b0b7aee6a Reviewed-by: Oliver Eftevaag <oliver.eftevaag@qt.io> (cherry picked from commit 6217408799c43869b8a7c1fcbff882d42ae71171) (cherry picked from commit 3b44a457efcf42f4f6b3ce0d6ae41ef3821e4478) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--examples/quickcontrols/texteditor/doc/src/qtquickcontrols-texteditor.qdoc165
-rw-r--r--examples/quickcontrols/texteditor/example.md10
-rw-r--r--examples/quickcontrols/texteditor/qml/texteditor.qml53
-rw-r--r--examples/quickcontrols/texteditor/texteditor.cpp2
-rw-r--r--examples/quickcontrols/texteditor/texteditor.html25
-rw-r--r--src/quickcontrols/doc/qtquickcontrols.qdocconf2
6 files changed, 173 insertions, 84 deletions
diff --git a/examples/quickcontrols/texteditor/doc/src/qtquickcontrols-texteditor.qdoc b/examples/quickcontrols/texteditor/doc/src/qtquickcontrols-texteditor.qdoc
index 4f7a9beb04..1e3144f942 100644
--- a/examples/quickcontrols/texteditor/doc/src/qtquickcontrols-texteditor.qdoc
+++ b/examples/quickcontrols/texteditor/doc/src/qtquickcontrols-texteditor.qdoc
@@ -7,46 +7,152 @@
\keyword Qt Quick Controls 2 - Text Editor
\ingroup qtquickcontrols-examples
\examplecategory {Graphics}
- \brief A QML app using Qt Quick Controls and a C++ class to
- provide a fully-functional rich-text editor application.
+ \brief A rich-text editor app using Qt Quick Controls.
- The \e {Text Editor Example} presents a sample HTML file using the TextArea
- control, preserving the HTML formatting. The application comes with two user
- interfaces; one for traditional desktop platforms with a mouse pointer, and
- another simpler, touch-oriented version.
+ The \e {Text Editor Example} allows WYSIWYG editing of an HTML, Markdown or
+ plain text file. The application comes with two user interfaces: one for
+ larger screens, and a simplified UI for small touch-based devices. Both are
+ "pure" QML. \c texteditor.cpp contains the \c main() function, which calls
+ QFontDatabase::addApplicationFont() to add an icon font. (\l FontLoader
+ would be an alternative way to achieve the same result.)
\section1 Desktop User Interface
\image qtquickcontrols-texteditor-desktop.jpg
The desktop version is a complete text editor with capabilities for formatting
- text, and opening and saving HTML and plain text files. It demonstrates the
- native-looking dialogs and menus using the \l{Qt Labs Platform} module. These
- types are mostly suitable for desktop platforms with support for multiple
- top-level windows, a mouse pointer, and moderate screen size.
+ text, and opening and saving HTML, Markdown and plain text files.
- The desktop UI uses FileDialog for opening and saving files:
+ In the \l {https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller}{model-view-control (MVC)}
+ design pattern, the \e control layer includes the set of operations that
+ can be performed. In Qt Quick Controls, the \l Action type is used to
+ encapsulate a single operation or command. Accordingly, we begin with a
+ set of Action objects:
\quotefromfile texteditor/qml/texteditor.qml
- \skipto FileDialog
- \printuntil /\bsaveAs\b/
- \printline }
+ \skipto Action
+ \printuntil openAction
+ \printto Action
+
+ The \l Action for opening a file must first prompt the user if the existing
+ document has been changed, to avoid losing the user's changes. Otherwise
+ it simply opens the FileDialog which is declared further below.
+
+ The \l Action for saving the file is enabled only if there are changes to save:
+
+ \printuntil saveAction
+ \printto Action
+
+ \skipto quitAction
+ \skipuntil }
+
+ The \l Action for copying selected text is enabled only if some text is selected:
+
+ \printuntil copyAction
+ \printuntil }
+
+ \skipto pasteAction
+ \skipuntil }
+
+ Each Action to change text formatting (such as bold, italic and alignment)
+ is \l {Action::}{checkable}, and its boolean \c checked state
+ is in sync with the relevant property in the
+ \l {TextEdit::selectedText}{selected text}.
+ Since declarative bidirectional synchronization is difficult, we use
+ an \c onTriggered script to change the property when the Action is
+ activated. The \l {TextEdit::}{cursorSelection} property
+ is new in Qt 6.7 and makes this much easier than it was.
+
+ \printuntil boldAction
+ \printto Action
+
+ \skipto alignLeftAction
+ \skipuntil }
+
+ \printuntil alignCenterAction
+ \printto Action
+
+ We have a \l {Qt.labs.platform::}{MenuBar} containing the hierarchy of
+ \l {Qt.labs.platform::Menu}{Menus} and MenuItems. \c Platform.MenuItem does
+ not have an \c action property, so at minimum we need to set \c text and
+ implement \c onTriggered.
+
+ \note In Qt Quick Controls, each \l {QtQuick.Controls::}{MenuItem} could
+ simply bind the relevant \l {AbstractButton::}{action}. In a near-future
+ version of Qt, \c Qt.labs.platform will be obsolete, and
+ \l {QtQuick.Controls::}{MenuBar} will be suitable on every platform.
+ Unless you need a native menu bar (only on platforms that provide one)
+ in Qt 6.7 and older versions, you should avoid importing \c Qt.labs.platform.
+ \c QtQuick.Controls is more portable.
+
+ \skipto MenuBar
+ \printuntil copyAction
+ \printuntil }
+ \dots 8
- It uses FontDialog and ColorDialog for choosing fonts and colors:
+ The existing \l Action objects are reused in the \l ToolBar; but here we
+ override each Action's \l {AbstractButton::}{text} property to
+ choose a textual icon from our icon font:
- \skipto FontDialog
- \printuntil /.*colorDialog$/
- \printuntil /^\s{4}\}$/
+ \skipto ToolBar
+ \printuntil copyButton
+ \printuntil }
+ \dots 12
- It also uses \l[QML QtLabsPlatform]{Menu} and
- \l[QML QtLabsPlatform]{MenuItem} that provide a context menu to format text
- within:
+ The main part of the text editor is a \l TextArea inside a \l Flickable:
- \skipto /\bMenu\b/
- \printuntil /^\s{4}\}$/
+ \skipto Flickable
+ \printuntil persistentSelection
+ \dots 12
- \note There is also a standard menubar with more options than the
- context menu.
+ A \l ScrollBar is attached to the vertical axis. Since word-wrapping is
+ enabled via \l {TextEdit::}{wrapMode}, we don't need a horizontal
+ ScrollBar.
+
+ The \l {TextArea::flickable}{TextArea.flickable} attached property is used
+ so that when the text cursor is moved out of the viewport (for example via
+ arrow keys, or by typing a lot of text), \l TextArea scrolls the
+ \l Flickable to keep the cursor visible.
+
+ There is a context menu; we use a TapHandler to detect a right-click and
+ open it:
+
+ \skipto TapHandler
+ \printuntil }
+
+ The context \l {Qt.labs.platform::}{Menu} contains
+ \l {Qt.labs.platform::MenuItem}{MenuItems}.
+
+ \skipto Menu
+ \printuntil MenuItem
+ \printuntil }
+ \dots 8
+
+ We consistently use the \l qsTr function to enable translation of UI text,
+ so that the application will make sense regardless of the end user's native
+ language.
+
+ We use several kinds of \l {Qt Quick Dialogs QML Types}{dialogs}:
+
+ \quotefromfile texteditor/qml/texteditor.qml
+ \skipto FileDialog
+ \printuntil discardDialog
+ \printuntil }
+ \printuntil }
+
+ It's generally easier to declare separate instances for each purpose.
+ We have two instances of \l {QtQuick.Dialogs::}{FileDialog}, for opening
+ and saving files respectively. This became easier in Qt 6.7, with new
+ features in \l TextDocument.
+
+ A \l {QtQuick.Dialogs::}{FontDialog} and a \l {QtQuick.Dialogs::ColorDialog}{ColorDialog}
+ allow changing text formatting. (In Markdown format, there's no syntax to
+ represent specific font and color choices; but font characteristics such as
+ bold, italic and monospace are saved. In HTML format, all formatting is
+ saved.)
+
+ We have a \l {QtQuick.Dialogs::}{MessageDialog} to show error messages, and
+ two more for prompting the user what to do when a file has been modified.
\section1 Touch User Interface
@@ -57,14 +163,5 @@
\l{Using File Selectors with Qt Quick Controls}{file selectors} to load
the appropriate user interface automatically.
- Unlike the desktop version, which uses top-level dialogs, the touch version
- uses the QML \l Dialog type, which is not a top-level window. This type of
- dialog is fully supported on mobile and embedded platforms that do not support
- multiple top-level windows.
-
- \quotefromfile texteditor/qml/+touch/texteditor.qml
- \skipto /\bDialog\b/
- \printuntil /^\s{4}\}$/
-
\include examples-run.qdocinc
*/
diff --git a/examples/quickcontrols/texteditor/example.md b/examples/quickcontrols/texteditor/example.md
index e385227e3b..f54edab5ae 100644
--- a/examples/quickcontrols/texteditor/example.md
+++ b/examples/quickcontrols/texteditor/example.md
@@ -1,10 +1,10 @@
# Markdown in Qt Quick
The Text, TextEdit and TextArea items support rich text formatted in HTML.
-Since Qt 5.14, they now support two dialects of Markdown as well:
-[The CommonMark Specification](https://spec.commonmark.org/0.29/) is the
+Since Qt 5.14, they support two dialects of Markdown as well:
+[The CommonMark Specification](https://spec.commonmark.org/0.31.2/) is the
conservative formal specification, while
-[GitHub Flavored Markdown](https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown)
+[GitHub Flavored Markdown](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax)
adds extra features such as task lists and tables.
If you are viewing this document in the Qt Quick Controls Text Editor example,
@@ -36,7 +36,7 @@ Block {
Block quotes can be nested, and block quotes can include indented code blocks.
-In [The CommonMark Specification](https://spec.commonmark.org/0.29/)
+In [The CommonMark Specification](https://spec.commonmark.org/0.31.2/)
John MacFarlane writes:
> What distinguishes Markdown from many other lightweight markup syntaxes,
@@ -158,7 +158,7 @@ Some Qt Widgets also support Markdown.
[QTextEdit](https://doc.qt.io/qt-6/qtextedit.html) has similar WYSIWYG
editing features as TextEdit and TextArea: you can edit the rendered text
directly. You can use
-[QTextDocument::toMarkdown](https://doc-snapshots.qt.io/qt5-dev/qtextdocument.html#toMarkdown)
+[QTextDocument::toMarkdown](https://doc.qt.io/qt-6/qtextdocument.html#toMarkdown)
to rewrite the Markdown format, and save it back to a file.
If you have the [KDE Kate Editor](https://kate-editor.org/) installed on your
diff --git a/examples/quickcontrols/texteditor/qml/texteditor.qml b/examples/quickcontrols/texteditor/qml/texteditor.qml
index a33aba6f31..9aee7e1e45 100644
--- a/examples/quickcontrols/texteditor/qml/texteditor.qml
+++ b/examples/quickcontrols/texteditor/qml/texteditor.qml
@@ -6,7 +6,7 @@ import QtCore
import QtQuick.Controls
import QtQuick.Window
import QtQuick.Dialogs
-import Qt.labs.platform as Platform
+import Qt.labs.platform as Platform // note: soon to be obsolete
// TODO:
// - make designer-friendly
@@ -57,18 +57,21 @@ ApplicationWindow {
Action {
id: copyAction
shortcut: StandardKey.Copy
+ enabled: textArea.selectedText
onTriggered: textArea.copy()
}
Action {
id: cutAction
shortcut: StandardKey.Cut
+ enabled: textArea.selectedText
onTriggered: textArea.cut()
}
Action {
id: pasteAction
shortcut: StandardKey.Paste
+ enabled: textArea.canPaste
onTriggered: textArea.paste()
}
@@ -141,15 +144,19 @@ ApplicationWindow {
Platform.MenuItem {
text: qsTr("&Open")
- onTriggered: openDialog.open()
+ onTriggered: openAction.trigger()
}
Platform.MenuItem {
- text: qsTr("&Save As...")
- onTriggered: saveDialog.open()
+ text: qsTr("&Save…")
+ onTriggered: saveAction.trigger()
+ }
+ Platform.MenuItem {
+ text: qsTr("Save &As…")
+ onTriggered: saveAsAction.trigger()
}
Platform.MenuItem {
text: qsTr("&Quit")
- onTriggered: close()
+ onTriggered: quitAction.trigger()
}
}
@@ -158,18 +165,18 @@ ApplicationWindow {
Platform.MenuItem {
text: qsTr("&Copy")
- enabled: textArea.selectedText
- onTriggered: textArea.copy()
+ enabled: copyAction.enabled
+ onTriggered: copyAction.trigger()
}
Platform.MenuItem {
text: qsTr("Cu&t")
- enabled: textArea.selectedText
- onTriggered: textArea.cut()
+ enabled: cutAction.enabled
+ onTriggered: cutAction.trigger()
}
Platform.MenuItem {
text: qsTr("&Paste")
- enabled: textArea.canPaste
- onTriggered: textArea.paste()
+ enabled: pasteAction.enabled
+ onTriggered: pasteAction.trigger()
}
}
@@ -325,7 +332,6 @@ ApplicationWindow {
text: "\uF0C5" // icon-docs
font.family: "fontello"
focusPolicy: Qt.TabFocus
- enabled: textArea.selectedText
action: copyAction
}
ToolButton {
@@ -333,7 +339,6 @@ ApplicationWindow {
text: "\uE802" // icon-scissors
font.family: "fontello"
focusPolicy: Qt.TabFocus
- enabled: textArea.selectedText
action: cutAction
}
ToolButton {
@@ -341,7 +346,6 @@ ApplicationWindow {
text: "\uF0EA" // icon-paste
font.family: "fontello"
focusPolicy: Qt.TabFocus
- enabled: textArea.canPaste
action: pasteAction
}
ToolSeparator {
@@ -463,6 +467,8 @@ ApplicationWindow {
flickableDirection: Flickable.VerticalFlick
anchors.fill: parent
+ ScrollBar.vertical: ScrollBar {}
+
TextArea.flickable: TextArea {
id: textArea
textFormat: Qt.RichText
@@ -479,10 +485,9 @@ ApplicationWindow {
bottomPadding: 0
background: null
- MouseArea {
+ TapHandler {
acceptedButtons: Qt.RightButton
- anchors.fill: parent
- onClicked: contextMenu.open()
+ onTapped: contextMenu.open()
}
onLinkActivated: function (link) {
@@ -511,8 +516,6 @@ ApplicationWindow {
}
}
}
-
- ScrollBar.vertical: ScrollBar {}
}
Platform.Menu {
@@ -520,18 +523,18 @@ ApplicationWindow {
Platform.MenuItem {
text: qsTr("Copy")
- enabled: textArea.selectedText
- onTriggered: textArea.copy()
+ enabled: copyAction.enabled
+ onTriggered: copyAction.trigger()
}
Platform.MenuItem {
text: qsTr("Cut")
- enabled: textArea.selectedText
- onTriggered: textArea.cut()
+ enabled: cutAction.enabled
+ onTriggered: cutAction.trigger()
}
Platform.MenuItem {
text: qsTr("Paste")
- enabled: textArea.canPaste
- onTriggered: textArea.paste()
+ enabled: pasteAction.enabled
+ onTriggered: pasteAction.trigger()
}
Platform.MenuSeparator {}
diff --git a/examples/quickcontrols/texteditor/texteditor.cpp b/examples/quickcontrols/texteditor/texteditor.cpp
index dd4800f7b5..7d2d9d0e09 100644
--- a/examples/quickcontrols/texteditor/texteditor.cpp
+++ b/examples/quickcontrols/texteditor/texteditor.cpp
@@ -18,7 +18,7 @@ int main(int argc, char *argv[])
QGuiApplication::setOrganizationName("QtProject");
#ifdef QT_WIDGETS_LIB
- QApplication app(argc, argv);
+ QApplication app(argc, argv); // only for Qt.labs.platform components
#else
QGuiApplication app(argc, argv);
#endif
diff --git a/examples/quickcontrols/texteditor/texteditor.html b/examples/quickcontrols/texteditor/texteditor.html
index 3c59a053c5..f53693ec33 100644
--- a/examples/quickcontrols/texteditor/texteditor.html
+++ b/examples/quickcontrols/texteditor/texteditor.html
@@ -20,24 +20,13 @@
Qt Quick Controls 2
</h2>
<p align="center">
- This example demonstrates a modern rich text editor. The UI uses Qt Labs Platforms to provide native menus and dialogs.
+ This example demonstrates a modern rich text editor. The UI uses Qt Labs Platform to provide native
+ <a href="https://doc.qt.io/qt-6/qml-qt-labs-platform-menubar.html">menus</a>,
+ and <a href="https://doc.qt.io/qt-6/qtquick-dialogs-qmlmodule.html">Qt Quick Dialogs</a> for native dialogs.
+ <a href="https://doc.qt.io/qt-6/qml-qtquick-controls-textarea.html">TextArea</a>,
+ <a href="https://doc.qt.io/qt-6/qml-qtquick-textedit.html#cursorSelection-prop">TextSelection</a> and
+ <a href="https://doc.qt.io/qt-6/qml-qtquick-textedit.html#textDocument-prop">TextDocument</a>
+ provide text-editing API.
</p>
- <br />
- <br />
- <br />
-
- <p>
- Below you'll find a list of the native controls used in this application.
- </p>
-
- <ul>
- <li><a href="https://doc.qt.io/qt-6/qml-qt-labs-platform-menu.html">Menu</a> - provides a QML API for native platform menu popups.</li>
- <li><a href="https://doc.qt.io/qt-6/qml-qt-labs-platform-menubar.html">MenuBar</a> - provides a QML API for native platform menubars.</li>
- <li><a href="https://doc.qt.io/qt-6/qml-qt-labs-platform-menuitem.html">MenuItem</a> - provides a QML API for native platform menu items.</li>
- <li><a href="https://doc.qt.io/qt-6/qml-qt-labs-platform-filedialog.html">FileDialog</a> - provides a QML API for native platform file dialogs.</li>
- <li><a href="https://doc.qt.io/qt-6/qml-qt-labs-platform-fontdialog.html">FontDialog</a> - provides a QML API for native platform font dialogs.</li>
- <li><a href="https://doc.qt.io/qt-6/qml-qt-labs-platform-colordialog.html">ColorDialog</a> - provides a QML API for native platform color dialogs.</li>
- <li><a href="https://doc.qt.io/qt-6/qml-qt-labs-platform-messagedialog.html">MessageDialog</a> - provides a QML API for native platform message dialogs.</li>
- </ul>
</body>
</html>
diff --git a/src/quickcontrols/doc/qtquickcontrols.qdocconf b/src/quickcontrols/doc/qtquickcontrols.qdocconf
index df2e67c933..1cfe683e38 100644
--- a/src/quickcontrols/doc/qtquickcontrols.qdocconf
+++ b/src/quickcontrols/doc/qtquickcontrols.qdocconf
@@ -29,7 +29,7 @@ qhp.QtQuickControls.subprojects.examples.title = Examples
qhp.QtQuickControls.subprojects.examples.indexTitle = Qt Quick Controls Examples
qhp.QtQuickControls.subprojects.examples.selectors = fake:example
-depends = qtcore qtgui qtdoc qtqml qtqmlmodels qtquick qtsql qtwidgets qtlabsplatform qmake qtcmake qtvirtualkeyboard
+depends = qtcore qtgui qtdoc qtqml qtqmlmodels qtquick qtquickdialogs qtsql qtwidgets qtlabsplatform qmake qtcmake qtvirtualkeyboard
# Specify the install path under QT_INSTALL_EXAMPLES
# Note: paths passed to \example command must contain the parent directory, e.g.