diff options
author | Mitch Curtis <mitch.curtis@qt.io> | 2016-07-06 13:04:07 +0200 |
---|---|---|
committer | J-P Nurmi <jpnurmi@qt.io> | 2016-08-11 16:47:48 +0000 |
commit | fcf4a1ed81c547f24384e005e9776f478161c616 (patch) | |
tree | 373907ca5fc1f87d0780fb7e2e4a4e9c5c6109fa | |
parent | 4092df376916ad9477547ecd4ef4679dc59e0fdf (diff) |
Add Text Editor example
A follow up commit will contain the touch UI.
Change-Id: I26275fdd31294506821fa3e3e4a4bb63329665b9
Task-number: QTBUG-54952
Reviewed-by: J-P Nurmi <jpnurmi@qt.io>
-rw-r--r-- | examples/quickcontrols2/quickcontrols2.pro | 3 | ||||
-rw-r--r-- | examples/quickcontrols2/texteditor/doc/images/qtquickcontrols2-texteditor-desktop.png | bin | 0 -> 88813 bytes | |||
-rw-r--r-- | examples/quickcontrols2/texteditor/doc/src/qtquickcontrols2-texteditor.qdoc | 67 | ||||
-rw-r--r-- | examples/quickcontrols2/texteditor/documenthandler.cpp | 381 | ||||
-rw-r--r-- | examples/quickcontrols2/texteditor/documenthandler.h | 173 | ||||
-rw-r--r-- | examples/quickcontrols2/texteditor/fonts/fontello.ttf | bin | 0 -> 9188 bytes | |||
-rw-r--r-- | examples/quickcontrols2/texteditor/images/qt-logo.png | bin | 0 -> 5681 bytes | |||
-rw-r--r-- | examples/quickcontrols2/texteditor/qml/texteditor.qml | 437 | ||||
-rw-r--r-- | examples/quickcontrols2/texteditor/qtquickcontrols2.conf | 10 | ||||
-rw-r--r-- | examples/quickcontrols2/texteditor/texteditor.cpp | 71 | ||||
-rw-r--r-- | examples/quickcontrols2/texteditor/texteditor.html | 44 | ||||
-rw-r--r-- | examples/quickcontrols2/texteditor/texteditor.pro | 19 | ||||
-rw-r--r-- | examples/quickcontrols2/texteditor/texteditor.qrc | 9 |
13 files changed, 1213 insertions, 1 deletions
diff --git a/examples/quickcontrols2/quickcontrols2.pro b/examples/quickcontrols2/quickcontrols2.pro index 4f0f2fcc..6d732b17 100644 --- a/examples/quickcontrols2/quickcontrols2.pro +++ b/examples/quickcontrols2/quickcontrols2.pro @@ -1,4 +1,5 @@ TEMPLATE = subdirs SUBDIRS += \ gallery \ - chattutorial + chattutorial \ + texteditor diff --git a/examples/quickcontrols2/texteditor/doc/images/qtquickcontrols2-texteditor-desktop.png b/examples/quickcontrols2/texteditor/doc/images/qtquickcontrols2-texteditor-desktop.png Binary files differnew file mode 100644 index 00000000..4b4d7f79 --- /dev/null +++ b/examples/quickcontrols2/texteditor/doc/images/qtquickcontrols2-texteditor-desktop.png diff --git a/examples/quickcontrols2/texteditor/doc/src/qtquickcontrols2-texteditor.qdoc b/examples/quickcontrols2/texteditor/doc/src/qtquickcontrols2-texteditor.qdoc new file mode 100644 index 00000000..60ff0567 --- /dev/null +++ b/examples/quickcontrols2/texteditor/doc/src/qtquickcontrols2-texteditor.qdoc @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example texteditor + \title Qt Quick Controls 2 - Text Editor + \ingroup qtquickcontrols2-examples + \brief A QML app using Qt Quick Controls 2 and a C++ class to + provide a fully-functional rich-text editor application. + + \image qtquickcontrols2-texteditor-desktop.png + + The \e {Text Editor Example} presents a sample HTML file using the TextArea + control, preserving the HTML formatting. It uses a C++ class to handle the + document by providing options to open, format, and edit. The application + also lets you open and edit plain text files. + + The C++ class, DocumentHandler, extends QObject and is registered + as a QML type under the namespace \c {io.qt.examples.texteditor 1.0}. + + The following snippets show how the type is registered under + a namespace and later imported by \e main.qml. + + QML type registration: + + \code + #include <QtQml/qqml.h> + ... + qmlRegisterType<DocumentHandler>("io.qt.examples.texteditor", 1, 0, "DocumentHandler"); + ... + \endcode + + QML namespace import: + + \code + import io.qt.examples.texteditor 1.0 + \endcode + + For more information about registering C++ classes as QML types, see + \l {Defining QML Types from C++}. + + \include examples-run.qdocinc +*/ diff --git a/examples/quickcontrols2/texteditor/documenthandler.cpp b/examples/quickcontrols2/texteditor/documenthandler.cpp new file mode 100644 index 00000000..2a13b211 --- /dev/null +++ b/examples/quickcontrols2/texteditor/documenthandler.cpp @@ -0,0 +1,381 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "documenthandler.h" + +#include <QFileInfo> +#include <QFontDatabase> +#include <QQmlFile> +#include <QQuickTextDocument> +#include <QTextCharFormat> +#include <QTextCodec> +#include <QTextCursor> +#include <QTextDocument> + +DocumentHandler::DocumentHandler(QObject *parent) + : QObject(parent) + , m_doc(nullptr) + , m_cursorPosition(-1) + , m_selectionStart(0) + , m_selectionEnd(0) +{ +} + +QQuickTextDocument *DocumentHandler::document() const +{ + return m_quickDoc; +} + +void DocumentHandler::setDocument(QQuickTextDocument *quickDoc) +{ + if (quickDoc == m_quickDoc) + return; + + m_quickDoc = quickDoc; + m_doc = nullptr; + + if (quickDoc) + m_doc = quickDoc->textDocument(); + + emit documentChanged(); +} + +void DocumentHandler::setFileUrl(const QUrl &fileUrl) +{ + if (fileUrl == m_fileUrl) + return; + + m_fileUrl = fileUrl; + QString fileName = QQmlFile::urlToLocalFileOrQrc(fileUrl); + if (QFile::exists(fileName)) { + QFile file(fileName); + if (file.open(QFile::ReadOnly)) { + QByteArray data = file.readAll(); + QTextCodec *codec = QTextCodec::codecForHtml(data); + setText(codec->toUnicode(data)); + if (m_doc) + m_doc->setModified(false); + if (fileName.isEmpty()) + m_documentTitle = QStringLiteral("untitled.txt"); + else + m_documentTitle = QFileInfo(fileName).fileName(); + + emit textChanged(); + emit documentTitleChanged(); + + reset(); + } + } + emit fileUrlChanged(); +} + +QString DocumentHandler::documentTitle() const +{ + return m_documentTitle; +} + +void DocumentHandler::setDocumentTitle(const QString &documentTitle) +{ + if (documentTitle == m_documentTitle) + return; + + m_documentTitle = documentTitle; + emit documentTitleChanged(); +} + +void DocumentHandler::setText(const QString &text) +{ + if (text == m_text) + return; + + m_text = text; + emit textChanged(); +} + +void DocumentHandler::saveAs(const QUrl &fileUrl, const QString &fileType) +{ + if (!m_doc) + return; + + // TODO: remove this when FileDialog gets suffix property + QString localPath = fileUrl.toLocalFile(); + QString extension = fileType; + if (extension.isEmpty()) { + if (QFile::exists(localPath)) { + extension = QFileInfo(localPath).suffix(); + } else { + const int periodIndex = localPath.indexOf(QLatin1Char('.')); + if (periodIndex != -1) + extension = localPath.mid(periodIndex); + } + } + + const bool isHtml = extension.contains(QLatin1String("htm")); + if (!localPath.endsWith(extension)) + localPath += extension; + QFile f(localPath); + if (!f.open(QFile::WriteOnly | QFile::Truncate | (isHtml ? QFile::NotOpen : QFile::Text))) { + emit error(tr("Cannot save: ") + f.errorString()); + return; + } + f.write((isHtml ? m_doc->toHtml() : m_doc->toPlainText()).toLocal8Bit()); + f.close(); + setFileUrl(QUrl::fromLocalFile(localPath)); +} + +QUrl DocumentHandler::fileUrl() const +{ + return m_fileUrl; +} + +QString DocumentHandler::text() const +{ + return m_text; +} + +void DocumentHandler::setCursorPosition(int position) +{ + if (position == m_cursorPosition) + return; + + m_cursorPosition = position; + + reset(); +} + +void DocumentHandler::reset() +{ + emit fontFamilyChanged(); + emit alignmentChanged(); + emit boldChanged(); + emit italicChanged(); + emit underlineChanged(); + emit fontSizeChanged(); + emit textColorChanged(); +} + +QTextCursor DocumentHandler::textCursor() const +{ + if (!m_doc) + return QTextCursor(); + + QTextCursor cursor = QTextCursor(m_doc); + if (m_selectionStart != m_selectionEnd) { + cursor.setPosition(m_selectionStart); + cursor.setPosition(m_selectionEnd, QTextCursor::KeepAnchor); + } else { + cursor.setPosition(m_cursorPosition); + } + return cursor; +} + +void DocumentHandler::mergeFormatOnWordOrSelection(const QTextCharFormat &format) +{ + QTextCursor cursor = textCursor(); + if (!cursor.hasSelection()) + cursor.select(QTextCursor::WordUnderCursor); + cursor.mergeCharFormat(format); +} + +void DocumentHandler::setSelectionStart(int position) +{ + if (position == m_selectionStart) + return; + + m_selectionStart = position; + emit selectionStartChanged(); +} + +void DocumentHandler::setSelectionEnd(int position) +{ + if (position == m_selectionEnd) + return; + + m_selectionEnd = position; + emit selectionEndChanged(); +} + +void DocumentHandler::setAlignment(Qt::Alignment alignment) +{ + if (!m_doc) + return; + + QTextBlockFormat format; + format.setAlignment(alignment); + QTextCursor cursor = textCursor(); + cursor.mergeBlockFormat(format); + emit alignmentChanged(); +} + +Qt::Alignment DocumentHandler::alignment() const +{ + QTextCursor cursor = textCursor(); + if (cursor.isNull()) + return Qt::AlignLeft; + return textCursor().blockFormat().alignment(); +} + +bool DocumentHandler::bold() const +{ + QTextCursor cursor = textCursor(); + if (cursor.isNull()) + return false; + return textCursor().charFormat().fontWeight() == QFont::Bold; +} + +bool DocumentHandler::italic() const +{ + QTextCursor cursor = textCursor(); + if (cursor.isNull()) + return false; + return textCursor().charFormat().fontItalic(); +} + +bool DocumentHandler::underline() const +{ + QTextCursor cursor = textCursor(); + if (cursor.isNull()) + return false; + return textCursor().charFormat().fontUnderline(); +} + +void DocumentHandler::setBold(bool bold) +{ + QTextCharFormat format; + format.setFontWeight(bold ? QFont::Bold : QFont::Normal); + mergeFormatOnWordOrSelection(format); + emit boldChanged(); +} + +void DocumentHandler::setItalic(bool italic) +{ + QTextCharFormat format; + format.setFontItalic(italic); + mergeFormatOnWordOrSelection(format); + emit italicChanged(); +} + +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 fontSize) +{ + if (fontSize <= 0) + return; + + QTextCursor cursor = textCursor(); + if (cursor.isNull()) + return; + + if (!cursor.hasSelection()) + cursor.select(QTextCursor::WordUnderCursor); + + if (cursor.charFormat().property(QTextFormat::FontPointSize).toInt() == fontSize) + return; + + QTextCharFormat format; + format.setFontPointSize(fontSize); + mergeFormatOnWordOrSelection(format); + emit fontSizeChanged(); +} + +QColor DocumentHandler::textColor() const +{ + QTextCursor cursor = textCursor(); + if (cursor.isNull()) + return QColor(Qt::black); + QTextCharFormat format = cursor.charFormat(); + return format.foreground().color(); +} + +void DocumentHandler::setTextColor(const QColor &color) +{ + QTextCursor cursor = textCursor(); + if (cursor.isNull()) + return; + QTextCharFormat format; + format.setForeground(QBrush(color)); + mergeFormatOnWordOrSelection(format); + emit textColorChanged(); +} + +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 &fontFamily) +{ + QTextCursor cursor = textCursor(); + if (cursor.isNull()) + return; + QTextCharFormat format; + format.setFontFamily(fontFamily); + mergeFormatOnWordOrSelection(format); + emit fontFamilyChanged(); +} diff --git a/examples/quickcontrols2/texteditor/documenthandler.h b/examples/quickcontrols2/texteditor/documenthandler.h new file mode 100644 index 00000000..48e2c509 --- /dev/null +++ b/examples/quickcontrols2/texteditor/documenthandler.h @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DOCUMENTHANDLER_H +#define DOCUMENTHANDLER_H + +#include <QFont> +#include <QObject> +#include <QTextCursor> +#include <QUrl> + +QT_BEGIN_NAMESPACE +class QTextDocument; +class QQuickTextDocument; +QT_END_NAMESPACE + +class DocumentHandler : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QQuickTextDocument *document READ document WRITE setDocument NOTIFY documentChanged) + Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged) + Q_PROPERTY(int selectionStart READ selectionStart WRITE setSelectionStart NOTIFY selectionStartChanged) + 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(QUrl fileUrl READ fileUrl WRITE setFileUrl NOTIFY fileUrlChanged) + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) + Q_PROPERTY(QString documentTitle READ documentTitle WRITE setDocumentTitle NOTIFY documentTitleChanged) + +public: + explicit DocumentHandler(QObject *parent = nullptr); + + QQuickTextDocument *document() const; + void setDocument(QQuickTextDocument *quickDoc); + + void setCursorPosition(int position); + void setSelectionStart(int position); + void setSelectionEnd(int position); + + int cursorPosition() const { return m_cursorPosition; } + int selectionStart() const { return m_selectionStart; } + int selectionEnd() const { return m_selectionEnd; } + + QString fontFamily() const; + + QColor textColor() const; + + Qt::Alignment alignment() const; + void setAlignment(Qt::Alignment alignment); + + bool bold() const; + bool italic() const; + bool underline() const; + int fontSize() const; + + QUrl fileUrl() const; + QString text() const; + + QString documentTitle() const; + +public Q_SLOTS: + void setBold(bool bold); + void setItalic(bool italic); + void setUnderline(bool underline); + void setFontSize(int fontSize); + void setTextColor(const QColor &color); + void setFontFamily(const QString &fontFamily); + + void setFileUrl(const QUrl &fileUrl); + void setText(const QString &text); + void saveAs(const QUrl &fileUrl, const QString &fileType); + + void setDocumentTitle(const QString &documentTitle); + +Q_SIGNALS: + void documentChanged(); + void cursorPositionChanged(); + void selectionStartChanged(); + void selectionEndChanged(); + + void fontFamilyChanged(); + void textColorChanged(); + void alignmentChanged(); + + void boldChanged(); + void italicChanged(); + void underlineChanged(); + + void fontSizeChanged(); + + void fileUrlChanged(); + + void textChanged(); + void documentTitleChanged(); + void error(const QString &message); + +private: + void reset(); + QTextCursor textCursor() const; + void mergeFormatOnWordOrSelection(const QTextCharFormat &format); + + QQuickTextDocument *m_quickDoc; + QTextDocument *m_doc; + + int m_cursorPosition; + int m_selectionStart; + int m_selectionEnd; + + QFont m_font; + int m_fontSize; + QUrl m_fileUrl; + QString m_text; + QString m_documentTitle; +}; + +#endif diff --git a/examples/quickcontrols2/texteditor/fonts/fontello.ttf b/examples/quickcontrols2/texteditor/fonts/fontello.ttf Binary files differnew file mode 100644 index 00000000..9871d4c5 --- /dev/null +++ b/examples/quickcontrols2/texteditor/fonts/fontello.ttf diff --git a/examples/quickcontrols2/texteditor/images/qt-logo.png b/examples/quickcontrols2/texteditor/images/qt-logo.png Binary files differnew file mode 100644 index 00000000..e16b4182 --- /dev/null +++ b/examples/quickcontrols2/texteditor/images/qt-logo.png diff --git a/examples/quickcontrols2/texteditor/qml/texteditor.qml b/examples/quickcontrols2/texteditor/qml/texteditor.qml new file mode 100644 index 00000000..cac5a66d --- /dev/null +++ b/examples/quickcontrols2/texteditor/qml/texteditor.qml @@ -0,0 +1,437 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.1 +import QtQuick.Window 2.0 +import QtQuick.Controls.Material 2.1 +//import QtQuick.Controls.Universal 2.1 +import Qt.labs.platform 1.0 + +import io.qt.examples.texteditor 1.0 + +ApplicationWindow { + id: window + width: 1024 + height: 600 + visible: true + title: document.documentTitle + " - Text Editor Example" + + Component.onCompleted: { + x = Screen.width / 2 - width / 2 + y = Screen.height / 2 - height / 2 + } + + Shortcut { + sequence: StandardKey.Open + onActivated: openDialog.open() + } + Shortcut { + sequence: StandardKey.SaveAs + onActivated: saveDialog.open() + } + Shortcut { + sequence: StandardKey.Quit + onActivated: Qt.quit() + } + Shortcut { + sequence: StandardKey.Copy + onActivated: textArea.copy() + } + Shortcut { + sequence: StandardKey.Cut + onActivated: textArea.cut() + } + Shortcut { + sequence: StandardKey.Paste + onActivated: textArea.paste() + } + Shortcut { + sequence: StandardKey.Bold + onActivated: document.bold = !document.bold + } + Shortcut { + sequence: StandardKey.Italic + onActivated: document.italic = !document.italic + } + Shortcut { + sequence: StandardKey.Underline + onActivated: document.underline = !document.underline + } + + MenuBar { + Menu { + title: qsTr("File") + + MenuItem { + text: qsTr("Open") + onTriggered: openDialog.open() + } + MenuItem { + text: qsTr("Save As...") + onTriggered: saveDialog.open() + } + MenuItem { + text: qsTr("Quit") + onTriggered: Qt.quit() + } + } + + Menu { + title: qsTr("Edit") + + MenuItem { + text: qsTr("Copy") + enabled: textArea.selectedText + onTriggered: textArea.copy() + } + MenuItem { + text: qsTr("Cut") + enabled: textArea.selectedText + onTriggered: textArea.cut() + } + MenuItem { + text: qsTr("Paste") + enabled: textArea.canPaste + onTriggered: textArea.paste() + } + } + + Menu { + title: qsTr("Format") + + MenuItem { + text: qsTr("Bold") + checkable: true + checked: document.bold + onTriggered: document.bold = !document.bold + } + MenuItem { + text: qsTr("Italic") + checkable: true + checked: document.italic + onTriggered: document.italic = !document.italic + } + MenuItem { + text: qsTr("Underline") + checkable: true + checked: document.underline + onTriggered: document.underline = !document.underline + } + } + } + + FileDialog { + id: openDialog + fileMode: FileDialog.OpenFile + nameFilters: ["Text files (*.txt)", "HTML files (*.html, *.htm)"] + onFileSelected: document.fileUrl = file + } + + FileDialog { + id: saveDialog + fileMode: FileDialog.SaveFile + nameFilters: openDialog.nameFilters + // TODO: will eventually pass FileDialog's suffix property here + onFileSelected: document.saveAs(file, "") + } + + FontDialog { + id: fontDialog + onFontSelected: { + document.fontFamily = font.family; + document.fontSize = font.pointSize; + } + } + + ColorDialog { + id: colorDialog + currentColor: "black" + } + + MessageDialog { + id: errorDialog + } + + header: ToolBar { + leftPadding: 8 + + RowLayout { + anchors.fill: parent + spacing: 0 + + ToolButton { + id: openButton + text: "\uF115" + font.family: "fontello" + onClicked: openDialog.open() + } + + ToolSeparator {} + + Row { + ToolButton { + id: copyButton + text: "\uF0C5" + font.family: "fontello" + focusPolicy: Qt.TabFocus + enabled: textArea.selectedText + onClicked: textArea.copy() + } + ToolButton { + id: cutButton + text: "\uE802" + font.family: "fontello" + focusPolicy: Qt.TabFocus + enabled: textArea.selectedText + onClicked: textArea.cut() + } + ToolButton { + id: pasteButton + text: "\uF0EA" + font.family: "fontello" + focusPolicy: Qt.TabFocus + enabled: textArea.canPaste + onClicked: textArea.paste() + } + } + + ToolSeparator {} + + Row { + ToolButton { + id: boldButton + text: "\uE800" + font.family: "fontello" + focusPolicy: Qt.TabFocus + checkable: true + checked: document.bold + onClicked: document.bold = !document.bold + } + ToolButton { + id: italicButton + text: "\uE801" + font.family: "fontello" + focusPolicy: Qt.TabFocus + checkable: true + checked: document.italic + onClicked: document.italic = !document.italic + } + ToolButton { + id: underlineButton + text: "\uF0CD" + font.family: "fontello" + focusPolicy: Qt.TabFocus + checkable: true + checked: document.underline + onClicked: document.underline = !document.underline + } + ToolButton { + id: textColorButton + text: "\uE808" + font.family: "fontello" + focusPolicy: Qt.TabFocus + onClicked: colorDialog.open() + + Rectangle { + width: aFontMetrics.width + 3 + height: 2 + color: document.textColor + parent: textColorButton.contentItem + anchors.horizontalCenter: parent.horizontalCenter + anchors.baseline: parent.baseline + anchors.baselineOffset: 4 + + TextMetrics { + id: aFontMetrics + font: textColorButton.font + text: textColorButton.text + } + } + } + } + + ToolSeparator {} + + Row { + ToolButton { + id: alignLeftButton + text: "\uE803" + font.family: "fontello" + focusPolicy: Qt.TabFocus + checkable: true + checked: document.alignment == Qt.AlignLeft + onClicked: document.alignment = Qt.AlignLeft + } + ToolButton { + id: alignCenterButton + text: "\uE804" + font.family: "fontello" + focusPolicy: Qt.TabFocus + checkable: true + checked: document.alignment == Qt.AlignHCenter + onClicked: document.alignment = Qt.AlignHCenter + } + ToolButton { + id: alignRightButton + text: "\uE805" + font.family: "fontello" + focusPolicy: Qt.TabFocus + checkable: true + checked: document.alignment == Qt.AlignRight + onClicked: document.alignment = Qt.AlignRight + } + ToolButton { + id: alignJustifyButton + text: "\uE806" + font.family: "fontello" + focusPolicy: Qt.TabFocus + checkable: true + checked: document.alignment == Qt.AlignJustify + onClicked: document.alignment = Qt.AlignJustify + } + } + + ToolSeparator {} + + ToolButton { + id: fontFamilyToolButton + text: qsTr("F") + font.family: document.fontFamily + 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(); + } + } + + Item { + Layout.fillWidth: true + } + } + } + + DocumentHandler { + id: document + document: textArea.textDocument + cursorPosition: textArea.cursorPosition + selectionStart: textArea.selectionStart + selectionEnd: textArea.selectionEnd + textColor: colorDialog.currentColor + // TODO: if we don't do this, e.g. the bold button won't be checked + // when it should be (the title is bold) + Component.onCompleted: document.fileUrl = "qrc:/texteditor.html" + onError: { + errorDialog.text = message + errorDialog.visible = true + } + } + + Flickable { + id: flickable + flickableDirection: Flickable.VerticalFlick + anchors.fill: parent + + TextArea.flickable: TextArea { + id: textArea + text: document.text + textFormat: Qt.RichText + wrapMode: TextArea.Wrap + focus: true + selectByMouse: true + // Different styles have different padding and background + // decorations, but since this editor is almost taking up the + // entire window, we don't need them. + leftPadding: 6 + rightPadding: 6 + topPadding: 0 + bottomPadding: 0 + background: null + + MouseArea { + acceptedButtons: Qt.RightButton + anchors.fill: parent + onClicked: contextMenu.open() + } + + onLinkActivated: Qt.openUrlExternally(link) + } + + ScrollBar.vertical: ScrollBar {} + } + + Menu { + id: contextMenu + + MenuItem { + text: qsTr("Copy") + enabled: textArea.selectedText + onTriggered: textArea.copy() + } + MenuItem { + text: qsTr("Cut") + enabled: textArea.selectedText + onTriggered: textArea.cut() + } + MenuItem { + text: qsTr("Paste") + enabled: textArea.canPaste + onTriggered: textArea.paste() + } + + MenuItem { + separator: true + } + + MenuItem { + text: qsTr("Font...") + onTriggered: fontDialog.open() + } + + MenuItem { + text: qsTr("Color...") + onTriggered: colorDialog.open() + } + } +} diff --git a/examples/quickcontrols2/texteditor/qtquickcontrols2.conf b/examples/quickcontrols2/texteditor/qtquickcontrols2.conf new file mode 100644 index 00000000..496037be --- /dev/null +++ b/examples/quickcontrols2/texteditor/qtquickcontrols2.conf @@ -0,0 +1,10 @@ +[Controls] +Style=Material + +[Material] +Primary=BlueGrey +Accent=Blue +Theme=System + +[Universal] +Theme=System diff --git a/examples/quickcontrols2/texteditor/texteditor.cpp b/examples/quickcontrols2/texteditor/texteditor.cpp new file mode 100644 index 00000000..9af4cc3b --- /dev/null +++ b/examples/quickcontrols2/texteditor/texteditor.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> +#include <QFontDatabase> +#include <QDebug> +#include <QQmlApplicationEngine> +#include <QQmlContext> +#include <QQuickStyle> +#include <QFileSelector> + +#include "documenthandler.h" + +int main(int argc, char *argv[]) +{ + QGuiApplication::setApplicationName("Text Editor"); + QGuiApplication::setOrganizationName("QtProject"); + QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + + QApplication app(argc, argv); + + QFontDatabase fontDatabase; + if (fontDatabase.addApplicationFont(":/fonts/fontello.ttf") == -1) + qWarning() << "Failed to load fontello.ttf"; + + qmlRegisterType<DocumentHandler>("io.qt.examples.texteditor", 1, 0, "DocumentHandler"); + + QQmlApplicationEngine engine; + engine.load(QUrl("qrc:/qml/texteditor.qml")); + if (engine.rootObjects().isEmpty()) + return -1; + + return app.exec(); +} diff --git a/examples/quickcontrols2/texteditor/texteditor.html b/examples/quickcontrols2/texteditor/texteditor.html new file mode 100644 index 00000000..1310da42 --- /dev/null +++ b/examples/quickcontrols2/texteditor/texteditor.html @@ -0,0 +1,44 @@ +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <meta name="qrichtext" content="1"> + <title>Text Editor Example</title> + <style type="text/css"> + p, + body, <!-- specifiying font-size for body seems to be necessary to avoid bullet points being incorrectly positioned --> + li { + white-space: pre-wrap; + font-size:11pt; + } + </style> +</head> +<body> + <p align="center"> + <img src="qrc:/images/qt-logo.png" /> + </p> + <h2 align="center"> + 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. + </p> + <br /> + <br /> + <br /> + + <p> + Below you'll find a list of the native controls used in this application. + </p> + + <ul> + <!-- TODO: update the links before the 5.8 release --> + <li><a href="http://doc-snapshots.qt.io/qt5-dev/qml-qt-labs-platform-menu.html">Menu</a> - provides a QML API for native platform menu popups.</li> + <li><a href="http://doc-snapshots.qt.io/qt5-dev/qml-qt-labs-platform-menubar.html">MenuBar</a> - provides a QML API for native platform menubars.</li> + <li><a href="http://doc-snapshots.qt.io/qt5-dev/qml-qt-labs-platform-menuitem.html">MenuItem</a> - provides a QML API for native platform menu items.</li> + <li><a href="http://doc-snapshots.qt.io/qt5-dev/qml-qt-labs-platform-filedialog.html">FileDialog</a> - provides a QML API for native platform file dialogs.</li> + <li><a href="http://doc-snapshots.qt.io/qt5-dev/qml-qt-labs-platform-fontdialog.html">FontDialog</a> - provides a QML API for native platform font dialogs.</li> + <li><a href="http://doc-snapshots.qt.io/qt5-dev/qml-qt-labs-platform-colordialog.html">ColorDialog</a> - provides a QML API for native platform color dialogs.</li> + <li><a href="http://doc-snapshots.qt.io/qt5-dev/qml-qt-labs-platform-messagedialog.html">MessageDialog</a> - provides a QML API for native platform message dialogs.</li> + </ul> +</body> +</html> diff --git a/examples/quickcontrols2/texteditor/texteditor.pro b/examples/quickcontrols2/texteditor/texteditor.pro new file mode 100644 index 00000000..9a955a89 --- /dev/null +++ b/examples/quickcontrols2/texteditor/texteditor.pro @@ -0,0 +1,19 @@ +TEMPLATE = app +TARGET = texteditor +QT += quick quickcontrols2 widgets + +SOURCES += \ + texteditor.cpp \ + documenthandler.cpp + +OTHER_FILES += \ + qml/*.qml + +RESOURCES += \ + texteditor.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/quickcontrols2/texteditor +INSTALLS += target + +HEADERS += \ + documenthandler.h diff --git a/examples/quickcontrols2/texteditor/texteditor.qrc b/examples/quickcontrols2/texteditor/texteditor.qrc new file mode 100644 index 00000000..92f317fa --- /dev/null +++ b/examples/quickcontrols2/texteditor/texteditor.qrc @@ -0,0 +1,9 @@ +<RCC> + <qresource prefix="/"> + <file>qtquickcontrols2.conf</file> + <file>images/qt-logo.png</file> + <file>fonts/fontello.ttf</file> + <file>qml/texteditor.qml</file> + <file>texteditor.html</file> + </qresource> +</RCC> |