From fec156771b0549ea0cfe30d1e821c9aadbacb01c Mon Sep 17 00:00:00 2001 From: Oliver Eftevaag Date: Thu, 23 Sep 2021 17:45:44 +0200 Subject: TextEditor: Clean up example and use quick dialogs The text editor example is dependent on Qt.labs for its dialogs and native menus. The long term goal is to remove the Qt.labs dependency, and replace it with components from QtQuick. Currently we have a file and a font dialog, that should be used instead of the Qt.labs dialogs. I'm also replacing some of the properties in the DocumentHandler, since I don't think it makes sense for the font to be limited to only a few font weights and styles (which can be selected through the font dialog). Selecting the most common font weight and style is still possible using the bold and italic shortcuts and toolbar buttons. Some more features includes: * An additional toolbar button, which can be used to strikeout the selected font. This required adding an additional glyph to fontello.ttf. * When coupled with the fix for QTBUG-96934, the font for the current selection should automatically update the listviews in the font dialog to select the correct family, style, sizes and effects for what is selected in the document handler. Fixes: QTBUG-95976 Change-Id: I2907a2270e2a139b1ccb3fcb3ce3a788306a42e3 Reviewed-by: Mitch Curtis (cherry picked from commit cba55a2f08b59a378e721077d03e871f291301fb) Reviewed-by: Qt Cherry-pick Bot --- examples/quickcontrols2/texteditor/CMakeLists.txt | 16 +- .../quickcontrols2/texteditor/documenthandler.cpp | 125 +++----------- .../quickcontrols2/texteditor/documenthandler.h | 32 +--- .../quickcontrols2/texteditor/fonts/fontello.ttf | Bin 10152 -> 10208 bytes .../quickcontrols2/texteditor/qml/texteditor.qml | 192 +++++++++++++-------- examples/quickcontrols2/texteditor/texteditor.html | 14 +- 6 files changed, 157 insertions(+), 222 deletions(-) (limited to 'examples') diff --git a/examples/quickcontrols2/texteditor/CMakeLists.txt b/examples/quickcontrols2/texteditor/CMakeLists.txt index 74c76943f7..187d1a88b4 100644 --- a/examples/quickcontrols2/texteditor/CMakeLists.txt +++ b/examples/quickcontrols2/texteditor/CMakeLists.txt @@ -7,7 +7,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) -set(CMAKE_AUTOUIC ON) if(NOT DEFINED INSTALL_EXAMPLESDIR) set(INSTALL_EXAMPLESDIR "examples") @@ -15,19 +14,14 @@ endif() set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/quickcontrols2/texteditor") -find_package(Qt6 COMPONENTS Core) -find_package(Qt6 COMPONENTS Gui) -find_package(Qt6 COMPONENTS Quick) -find_package(Qt6 COMPONENTS QuickControls2) +find_package(Qt6 COMPONENTS Core Gui Quick QuickControls2) +find_package(Qt6 COMPONENTS Widgets) -qt_add_executable(texteditor - documenthandler.cpp documenthandler.h +qt_add_executable(texteditor WIN32 MACOSX_BUNDLE + documenthandler.cpp texteditor.cpp ) -set_target_properties(texteditor PROPERTIES - WIN32_EXECUTABLE TRUE - MACOSX_BUNDLE TRUE -) + target_link_libraries(texteditor PUBLIC Qt::Core Qt::Gui diff --git a/examples/quickcontrols2/texteditor/documenthandler.cpp b/examples/quickcontrols2/texteditor/documenthandler.cpp index e82fbb8c55..d904e6f637 100644 --- a/examples/quickcontrols2/texteditor/documenthandler.cpp +++ b/examples/quickcontrols2/texteditor/documenthandler.cpp @@ -82,7 +82,7 @@ void DocumentHandler::setDocument(QQuickTextDocument *document) return; if (m_document) - m_document->textDocument()->disconnect(this); + disconnect(m_document->textDocument(), &QTextDocument::modificationChanged, this, &DocumentHandler::modifiedChanged); m_document = document; if (m_document) connect(m_document->textDocument(), &QTextDocument::modificationChanged, this, &DocumentHandler::modifiedChanged); @@ -132,23 +132,6 @@ void DocumentHandler::setSelectionEnd(int position) emit selectionEndChanged(); } -QString DocumentHandler::fontFamily() const -{ - QTextCursor cursor = textCursor(); - if (cursor.isNull()) - return QString(); - QTextCharFormat format = cursor.charFormat(); - return format.font().family(); -} - -void DocumentHandler::setFontFamily(const QString &family) -{ - QTextCharFormat format; - format.setFontFamily(family); - mergeFormatOnWordOrSelection(format); - emit fontFamilyChanged(); -} - QColor DocumentHandler::textColor() const { QTextCursor cursor = textCursor(); @@ -183,84 +166,6 @@ void DocumentHandler::setAlignment(Qt::Alignment alignment) emit alignmentChanged(); } -bool DocumentHandler::bold() const -{ - QTextCursor cursor = textCursor(); - if (cursor.isNull()) - return false; - return textCursor().charFormat().fontWeight() == QFont::Bold; -} - -void DocumentHandler::setBold(bool bold) -{ - QTextCharFormat format; - format.setFontWeight(bold ? QFont::Bold : QFont::Normal); - mergeFormatOnWordOrSelection(format); - emit boldChanged(); -} - -bool DocumentHandler::italic() const -{ - QTextCursor cursor = textCursor(); - if (cursor.isNull()) - return false; - return textCursor().charFormat().fontItalic(); -} - -void DocumentHandler::setItalic(bool italic) -{ - QTextCharFormat format; - format.setFontItalic(italic); - mergeFormatOnWordOrSelection(format); - emit italicChanged(); -} - -bool DocumentHandler::underline() const -{ - QTextCursor cursor = textCursor(); - if (cursor.isNull()) - return false; - return textCursor().charFormat().fontUnderline(); -} - -void DocumentHandler::setUnderline(bool underline) -{ - QTextCharFormat format; - format.setFontUnderline(underline); - mergeFormatOnWordOrSelection(format); - emit underlineChanged(); -} - -int DocumentHandler::fontSize() const -{ - QTextCursor cursor = textCursor(); - if (cursor.isNull()) - return 0; - QTextCharFormat format = cursor.charFormat(); - return format.font().pointSize(); -} - -void DocumentHandler::setFontSize(int size) -{ - if (size <= 0) - return; - - QTextCursor cursor = textCursor(); - if (cursor.isNull()) - return; - - if (!cursor.hasSelection()) - cursor.select(QTextCursor::WordUnderCursor); - - if (cursor.charFormat().property(QTextFormat::FontPointSize).toInt() == size) - return; - - QTextCharFormat format; - format.setFontPointSize(size); - mergeFormatOnWordOrSelection(format); - emit fontSizeChanged(); -} - QString DocumentHandler::fileName() const { const QString filePath = QQmlFile::urlToLocalFileOrQrc(m_fileUrl); @@ -348,13 +253,9 @@ void DocumentHandler::saveAs(const QUrl &fileUrl) void DocumentHandler::reset() { - emit fontFamilyChanged(); emit alignmentChanged(); - emit boldChanged(); - emit italicChanged(); - emit underlineChanged(); - emit fontSizeChanged(); emit textColorChanged(); + emit fontChanged(); } QTextCursor DocumentHandler::textCursor() const @@ -400,4 +301,26 @@ void DocumentHandler::setModified(bool m) m_document->textDocument()->setModified(m); } +QFont DocumentHandler::font() const +{ + QTextCursor cursor = textCursor(); + if (cursor.isNull()) + return m_document->textDocument()->defaultFont(); + QTextCharFormat format = cursor.charFormat(); + return format.font(); +} + +void DocumentHandler::setFont(const QFont & font){ + + QTextCursor cursor = textCursor(); + if (!cursor.isNull() && cursor.charFormat().font() == font) + return; + + QTextCharFormat format; + format.setFont(font); + mergeFormatOnWordOrSelection(format); + + emit fontChanged(); +} + #include "moc_documenthandler.cpp" diff --git a/examples/quickcontrols2/texteditor/documenthandler.h b/examples/quickcontrols2/texteditor/documenthandler.h index 3863eb49e7..66b5957a20 100644 --- a/examples/quickcontrols2/texteditor/documenthandler.h +++ b/examples/quickcontrols2/texteditor/documenthandler.h @@ -71,14 +71,9 @@ class DocumentHandler : public QObject Q_PROPERTY(int selectionEnd READ selectionEnd WRITE setSelectionEnd NOTIFY selectionEndChanged) Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor NOTIFY textColorChanged) - Q_PROPERTY(QString fontFamily READ fontFamily WRITE setFontFamily NOTIFY fontFamilyChanged) Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY alignmentChanged) - Q_PROPERTY(bool bold READ bold WRITE setBold NOTIFY boldChanged) - Q_PROPERTY(bool italic READ italic WRITE setItalic NOTIFY italicChanged) - Q_PROPERTY(bool underline READ underline WRITE setUnderline NOTIFY underlineChanged) - - Q_PROPERTY(int fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged) + Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) Q_PROPERTY(QString fileName READ fileName NOTIFY fileUrlChanged) Q_PROPERTY(QString fileType READ fileType NOTIFY fileUrlChanged) @@ -101,26 +96,14 @@ public: int selectionEnd() const; void setSelectionEnd(int position); - QString fontFamily() const; - void setFontFamily(const QString &family); - QColor textColor() const; void setTextColor(const QColor &color); Qt::Alignment alignment() const; void setAlignment(Qt::Alignment alignment); - bool bold() const; - void setBold(bool bold); - - bool italic() const; - void setItalic(bool italic); - - bool underline() const; - void setUnderline(bool underline); - - int fontSize() const; - void setFontSize(int size); + QFont font() const; + void setFont(const QFont & font); QString fileName() const; QString fileType() const; @@ -139,16 +122,10 @@ Q_SIGNALS: void selectionStartChanged(); void selectionEndChanged(); - void fontFamilyChanged(); + void fontChanged(); void textColorChanged(); void alignmentChanged(); - void boldChanged(); - void italicChanged(); - void underlineChanged(); - - void fontSizeChanged(); - void textChanged(); void fileUrlChanged(); @@ -169,7 +146,6 @@ private: int m_selectionStart; int m_selectionEnd; - QFont m_font; QUrl m_fileUrl; }; diff --git a/examples/quickcontrols2/texteditor/fonts/fontello.ttf b/examples/quickcontrols2/texteditor/fonts/fontello.ttf index db957652d3..f02b44ec12 100644 Binary files a/examples/quickcontrols2/texteditor/fonts/fontello.ttf and b/examples/quickcontrols2/texteditor/fonts/fontello.ttf differ diff --git a/examples/quickcontrols2/texteditor/qml/texteditor.qml b/examples/quickcontrols2/texteditor/qml/texteditor.qml index 0c0f75e113..5f47223bd3 100644 --- a/examples/quickcontrols2/texteditor/qml/texteditor.qml +++ b/examples/quickcontrols2/texteditor/qml/texteditor.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Toolkit. @@ -49,9 +49,11 @@ ****************************************************************************/ import QtQuick +import QtCore import QtQuick.Controls import QtQuick.Window -import Qt.labs.platform +import QtQuick.Dialogs +import Qt.labs.platform as Platform import io.qt.examples.texteditor @@ -70,102 +72,125 @@ ApplicationWindow { y = Screen.height / 2 - height / 2 } - Shortcut { - sequence: StandardKey.Open - onActivated: openDialog.open() + Action { + id: openAction + shortcut: StandardKey.Open + onTriggered: openDialog.open() } - Shortcut { - sequence: StandardKey.SaveAs - onActivated: saveDialog.open() + + Action { + id: saveAsAction + shortcut: StandardKey.SaveAs + onTriggered: saveDialog.open() } - Shortcut { - sequence: StandardKey.Quit - onActivated: close() + + Action { + id: quitAction + shortcut: StandardKey.Quit + onTriggered: close() } - Shortcut { - sequence: StandardKey.Copy - onActivated: textArea.copy() + + Action { + id: copyAction + shortcut: StandardKey.Copy + onTriggered: textArea.copy() } - Shortcut { - sequence: StandardKey.Cut - onActivated: textArea.cut() + + Action { + id: cutAction + shortcut: StandardKey.Cut + onTriggered: textArea.cut() } - Shortcut { - sequence: StandardKey.Paste - onActivated: textArea.paste() + + Action { + id: pasteAction + shortcut: StandardKey.Paste + onTriggered: textArea.paste() } - Shortcut { - sequence: StandardKey.Bold - onActivated: document.bold = !document.bold + + Action { + id: boldAction + shortcut: StandardKey.Bold + onTriggered: document.bold = !document.bold } - Shortcut { - sequence: StandardKey.Italic - onActivated: document.italic = !document.italic + + Action { + id: italicAction + shortcut: StandardKey.Italic + onTriggered: document.italic = !document.italic } - Shortcut { - sequence: StandardKey.Underline - onActivated: document.underline = !document.underline + + Action { + id: underlineAction + shortcut: StandardKey.Underline + onTriggered: document.underline = !document.underline } - MenuBar { - Menu { + Platform.MenuBar { + Platform.Menu { title: qsTr("&File") - MenuItem { + Platform.MenuItem { text: qsTr("&Open") onTriggered: openDialog.open() } - MenuItem { + Platform.MenuItem { text: qsTr("&Save As...") onTriggered: saveDialog.open() } - MenuItem { + Platform.MenuItem { text: qsTr("&Quit") onTriggered: close() } } - Menu { + Platform.Menu { title: qsTr("&Edit") - MenuItem { + Platform.MenuItem { text: qsTr("&Copy") enabled: textArea.selectedText onTriggered: textArea.copy() } - MenuItem { + Platform.MenuItem { text: qsTr("Cu&t") enabled: textArea.selectedText onTriggered: textArea.cut() } - MenuItem { + Platform.MenuItem { text: qsTr("&Paste") enabled: textArea.canPaste onTriggered: textArea.paste() } } - Menu { + Platform.Menu { title: qsTr("F&ormat") - MenuItem { + Platform.MenuItem { text: qsTr("&Bold") checkable: true checked: document.bold onTriggered: document.bold = !document.bold } - MenuItem { + Platform.MenuItem { text: qsTr("&Italic") checkable: true checked: document.italic onTriggered: document.italic = !document.italic } - MenuItem { + Platform.MenuItem { text: qsTr("&Underline") checkable: true checked: document.underline onTriggered: document.underline = !document.underline } + Platform.MenuItem { + text: qsTr("&Strikeout") + checkable: true + checked: document.strikeout + onTriggered: document.strikeout = !document.strikeout + } } } @@ -174,7 +199,7 @@ ApplicationWindow { fileMode: FileDialog.OpenFile selectedNameFilter.index: 1 nameFilters: ["Text files (*.txt)", "HTML files (*.html *.htm)", "Markdown files (*.md *.markdown)"] - folder: StandardPaths.writableLocation(StandardPaths.DocumentsLocation) + currentFolder: StandardPaths.writableLocation(StandardPaths.DocumentsLocation) onAccepted: document.load(file) } @@ -184,32 +209,31 @@ ApplicationWindow { defaultSuffix: document.fileType nameFilters: openDialog.nameFilters selectedNameFilter.index: document.fileType === "txt" ? 0 : 1 - folder: StandardPaths.writableLocation(StandardPaths.DocumentsLocation) + currentFolder: StandardPaths.writableLocation(StandardPaths.DocumentsLocation) onAccepted: document.saveAs(file) } FontDialog { id: fontDialog - onAccepted: { - document.fontFamily = font.family; - document.fontSize = font.pointSize; - } + + onAccepted: document.font = fontDialog.selectedFont + onVisibleChanged: if (visible) currentFont = document.font } - ColorDialog { + Platform.ColorDialog { id: colorDialog currentColor: "black" } - MessageDialog { + Platform.MessageDialog { id: errorDialog } - MessageDialog { + Platform.MessageDialog { id : quitDialog title: qsTr("Quit?") text: qsTr("The file has been modified. Quit anyway?") - buttons: (MessageDialog.Yes | MessageDialog.No) + buttons: (Platform.MessageDialog.Yes | Platform.MessageDialog.No) onYesClicked: Qt.quit() } @@ -226,7 +250,8 @@ ApplicationWindow { id: openButton text: "\uF115" // icon-folder-open-empty font.family: "fontello" - onClicked: openDialog.open() + action: openAction + focusPolicy: Qt.TabFocus } ToolSeparator { contentItem.visible: fileRow.y === editRow.y @@ -241,7 +266,7 @@ ApplicationWindow { font.family: "fontello" focusPolicy: Qt.TabFocus enabled: textArea.selectedText - onClicked: textArea.copy() + action: copyAction } ToolButton { id: cutButton @@ -249,7 +274,7 @@ ApplicationWindow { font.family: "fontello" focusPolicy: Qt.TabFocus enabled: textArea.selectedText - onClicked: textArea.cut() + action: cutAction } ToolButton { id: pasteButton @@ -257,7 +282,7 @@ ApplicationWindow { font.family: "fontello" focusPolicy: Qt.TabFocus enabled: textArea.canPaste - onClicked: textArea.paste() + action: pasteAction } ToolSeparator { contentItem.visible: editRow.y === formatRow.y @@ -273,7 +298,7 @@ ApplicationWindow { focusPolicy: Qt.TabFocus checkable: true checked: document.bold - onClicked: document.bold = !document.bold + action: boldAction } ToolButton { id: italicButton @@ -282,7 +307,7 @@ ApplicationWindow { focusPolicy: Qt.TabFocus checkable: true checked: document.italic - onClicked: document.italic = !document.italic + action: italicAction } ToolButton { id: underlineButton @@ -291,7 +316,16 @@ ApplicationWindow { focusPolicy: Qt.TabFocus checkable: true checked: document.underline - onClicked: document.underline = !document.underline + action: underlineAction + } + ToolButton { + id: strikeoutButton + text: "\uF0CC" + font.family: "fontello" + focusPolicy: Qt.TabFocus + checkable: true + checked: document.strikeout + onClicked: document.strikeout = !document.strikeout } ToolButton { id: fontFamilyToolButton @@ -300,11 +334,9 @@ ApplicationWindow { font.bold: document.bold font.italic: document.italic font.underline: document.underline - onClicked: { - fontDialog.currentFont.family = document.fontFamily; - fontDialog.currentFont.pointSize = document.fontSize; - fontDialog.open(); - } + font.strikeout: document.strikeout + focusPolicy: Qt.TabFocus + onClicked: fontDialog.open() } ToolButton { id: textColorButton @@ -383,17 +415,25 @@ ApplicationWindow { selectionStart: textArea.selectionStart selectionEnd: textArea.selectionEnd textColor: colorDialog.color + + property alias family: document.font.family + property alias bold: document.font.bold + property alias italic: document.font.italic + property alias underline: document.font.underline + property alias strikeout: document.font.strikeout + property alias size: document.font.pointSize + Component.onCompleted: { if (Qt.application.arguments.length === 2) document.load("file:" + Qt.application.arguments[1]); else document.load("qrc:/texteditor.html") } - onLoaded: { + onLoaded: function (text, format) { textArea.textFormat = format textArea.text = text } - onError: { + onError: function (message) { errorDialog.text = message errorDialog.visible = true } @@ -426,45 +466,47 @@ ApplicationWindow { onClicked: contextMenu.open() } - onLinkActivated: Qt.openUrlExternally(link) + onLinkActivated: function (link) { + Qt.openUrlExternally(link) + } } ScrollBar.vertical: ScrollBar {} } - Menu { + Platform.Menu { id: contextMenu - MenuItem { + Platform.MenuItem { text: qsTr("Copy") enabled: textArea.selectedText onTriggered: textArea.copy() } - MenuItem { + Platform.MenuItem { text: qsTr("Cut") enabled: textArea.selectedText onTriggered: textArea.cut() } - MenuItem { + Platform.MenuItem { text: qsTr("Paste") enabled: textArea.canPaste onTriggered: textArea.paste() } - MenuSeparator {} + Platform.MenuSeparator {} - MenuItem { + Platform.MenuItem { text: qsTr("Font...") onTriggered: fontDialog.open() } - MenuItem { + Platform.MenuItem { text: qsTr("Color...") onTriggered: colorDialog.open() } } - onClosing: { + onClosing: function (close) { if (document.modified) { quitDialog.open() close.accepted = false diff --git a/examples/quickcontrols2/texteditor/texteditor.html b/examples/quickcontrols2/texteditor/texteditor.html index 41705f85f0..3c59a053c5 100644 --- a/examples/quickcontrols2/texteditor/texteditor.html +++ b/examples/quickcontrols2/texteditor/texteditor.html @@ -31,13 +31,13 @@

    -
  • Menu - provides a QML API for native platform menu popups.
  • -
  • MenuBar - provides a QML API for native platform menubars.
  • -
  • MenuItem - provides a QML API for native platform menu items.
  • -
  • FileDialog - provides a QML API for native platform file dialogs.
  • -
  • FontDialog - provides a QML API for native platform font dialogs.
  • -
  • ColorDialog - provides a QML API for native platform color dialogs.
  • -
  • MessageDialog - provides a QML API for native platform message dialogs.
  • +
  • Menu - provides a QML API for native platform menu popups.
  • +
  • MenuBar - provides a QML API for native platform menubars.
  • +
  • MenuItem - provides a QML API for native platform menu items.
  • +
  • FileDialog - provides a QML API for native platform file dialogs.
  • +
  • FontDialog - provides a QML API for native platform font dialogs.
  • +
  • ColorDialog - provides a QML API for native platform color dialogs.
  • +
  • MessageDialog - provides a QML API for native platform message dialogs.
-- cgit v1.2.3