aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@qt.io>2016-07-06 13:04:07 +0200
committerJ-P Nurmi <jpnurmi@qt.io>2016-08-11 16:47:48 +0000
commitfcf4a1ed81c547f24384e005e9776f478161c616 (patch)
tree373907ca5fc1f87d0780fb7e2e4a4e9c5c6109fa /examples
parent4092df376916ad9477547ecd4ef4679dc59e0fdf (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>
Diffstat (limited to 'examples')
-rw-r--r--examples/quickcontrols2/quickcontrols2.pro3
-rw-r--r--examples/quickcontrols2/texteditor/doc/images/qtquickcontrols2-texteditor-desktop.pngbin0 -> 88813 bytes
-rw-r--r--examples/quickcontrols2/texteditor/doc/src/qtquickcontrols2-texteditor.qdoc67
-rw-r--r--examples/quickcontrols2/texteditor/documenthandler.cpp381
-rw-r--r--examples/quickcontrols2/texteditor/documenthandler.h173
-rw-r--r--examples/quickcontrols2/texteditor/fonts/fontello.ttfbin0 -> 9188 bytes
-rw-r--r--examples/quickcontrols2/texteditor/images/qt-logo.pngbin0 -> 5681 bytes
-rw-r--r--examples/quickcontrols2/texteditor/qml/texteditor.qml437
-rw-r--r--examples/quickcontrols2/texteditor/qtquickcontrols2.conf10
-rw-r--r--examples/quickcontrols2/texteditor/texteditor.cpp71
-rw-r--r--examples/quickcontrols2/texteditor/texteditor.html44
-rw-r--r--examples/quickcontrols2/texteditor/texteditor.pro19
-rw-r--r--examples/quickcontrols2/texteditor/texteditor.qrc9
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
new file mode 100644
index 00000000..4b4d7f79
--- /dev/null
+++ b/examples/quickcontrols2/texteditor/doc/images/qtquickcontrols2-texteditor-desktop.png
Binary files differ
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
new file mode 100644
index 00000000..9871d4c5
--- /dev/null
+++ b/examples/quickcontrols2/texteditor/fonts/fontello.ttf
Binary files differ
diff --git a/examples/quickcontrols2/texteditor/images/qt-logo.png b/examples/quickcontrols2/texteditor/images/qt-logo.png
new file mode 100644
index 00000000..e16b4182
--- /dev/null
+++ b/examples/quickcontrols2/texteditor/images/qt-logo.png
Binary files differ
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>