1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquicktextdocument.h"
5#include "qquicktextdocument_p.h"
6
7#include "qquicktextedit_p.h"
8#include "qquicktextedit_p_p.h"
9#include "qquicktext_p_p.h"
10
11#include <QtQml/qqmlinfo.h>
12#include <QtQml/qqmlcontext.h>
13#include <QtQuick/private/qquickpixmapcache_p.h>
14
15QT_BEGIN_NAMESPACE
16
17/*!
18 \class QQuickTextDocument
19 \since 5.1
20 \brief The QQuickTextDocument class provides access to the QTextDocument of QQuickTextEdit.
21 \inmodule QtQuick
22
23 This class provides access to the QTextDocument of QQuickTextEdit elements.
24 This is provided to allow usage of the \l{Rich Text Processing} functionalities of Qt.
25 You are not allowed to modify the document, but it can be used to output content, for example with \l{QTextDocumentWriter}),
26 or provide additional formatting, for example with \l{QSyntaxHighlighter}.
27
28 The class has to be used from C++ directly, using the property of the \l TextEdit.
29
30 Warning: The QTextDocument provided is used internally by \l {Qt Quick} elements to provide text manipulation primitives.
31 You are not allowed to perform any modification of the internal state of the QTextDocument. If you do, the element
32 in question may stop functioning or crash.
33*/
34
35class QQuickTextDocumentPrivate : public QObjectPrivate
36{
37public:
38 QPointer<QTextDocument> document;
39};
40
41/*!
42 Constructs a QQuickTextDocument object with
43 \a parent as the parent object.
44*/
45QQuickTextDocument::QQuickTextDocument(QQuickItem *parent)
46 : QObject(*(new QQuickTextDocumentPrivate), parent)
47{
48 Q_D(QQuickTextDocument);
49 Q_ASSERT(parent);
50 Q_ASSERT(qobject_cast<QQuickTextEdit*>(parent));
51 d->document = QPointer<QTextDocument>(qobject_cast<QQuickTextEdit*>(object: parent)->d_func()->document);
52}
53
54/*!
55 Returns a pointer to the QTextDocument object.
56*/
57QTextDocument* QQuickTextDocument::textDocument() const
58{
59 Q_D(const QQuickTextDocument);
60 return d->document.data();
61}
62
63QQuickTextDocumentWithImageResources::QQuickTextDocumentWithImageResources(QQuickItem *parent)
64: QTextDocument(parent), outstanding(0)
65{
66 setUndoRedoEnabled(false);
67 documentLayout()->registerHandler(objectType: QTextFormat::ImageObject, component: this);
68 connect(sender: this, signal: &QTextDocument::baseUrlChanged, slot: [this]() {
69 clearResources();
70 markContentsDirty(from: 0, length: characterCount());
71 });
72}
73
74QQuickTextDocumentWithImageResources::~QQuickTextDocumentWithImageResources()
75{
76 if (!m_resources.isEmpty())
77 qDeleteAll(c: m_resources);
78}
79
80QVariant QQuickTextDocumentWithImageResources::loadResource(int type, const QUrl &name)
81{
82 QVariant resource = QTextDocument::loadResource(type, name);
83 if (resource.isNull() && type == QTextDocument::ImageResource) {
84 QQmlContext *context = qmlContext(parent());
85 QUrl url = baseUrl().resolved(relative: name);
86 QQuickPixmap *p = loadPixmap(context, name: url);
87 resource = p->image();
88 }
89
90 return resource;
91}
92
93void QQuickTextDocumentWithImageResources::requestFinished()
94{
95 outstanding--;
96 if (outstanding == 0) {
97 markContentsDirty(from: 0, length: characterCount());
98 emit imagesLoaded();
99 }
100}
101
102QSizeF QQuickTextDocumentWithImageResources::intrinsicSize(
103 QTextDocument *, int, const QTextFormat &format)
104{
105 if (format.isImageFormat()) {
106 QTextImageFormat imageFormat = format.toImageFormat();
107
108 const int width = qRound(d: imageFormat.width());
109 const bool hasWidth = imageFormat.hasProperty(propertyId: QTextFormat::ImageWidth) && width > 0;
110 const int height = qRound(d: imageFormat.height());
111 const bool hasHeight = imageFormat.hasProperty(propertyId: QTextFormat::ImageHeight) && height > 0;
112
113 QSizeF size(width, height);
114 if (!hasWidth || !hasHeight) {
115 QVariant res = resource(type: QTextDocument::ImageResource, name: QUrl(imageFormat.name()));
116 QImage image = res.value<QImage>();
117 if (image.isNull()) {
118 if (!hasWidth)
119 size.setWidth(16);
120 if (!hasHeight)
121 size.setHeight(16);
122 return size;
123 }
124 QSize imgSize = image.size();
125
126 if (!hasWidth) {
127 if (!hasHeight)
128 size.setWidth(imgSize.width());
129 else
130 size.setWidth(qRound(d: height * (imgSize.width() / (qreal) imgSize.height())));
131 }
132 if (!hasHeight) {
133 if (!hasWidth)
134 size.setHeight(imgSize.height());
135 else
136 size.setHeight(qRound(d: width * (imgSize.height() / (qreal) imgSize.width())));
137 }
138 }
139 return size;
140 }
141 return QSizeF();
142}
143
144void QQuickTextDocumentWithImageResources::drawObject(
145 QPainter *, const QRectF &, QTextDocument *, int, const QTextFormat &)
146{
147}
148
149QImage QQuickTextDocumentWithImageResources::image(const QTextImageFormat &format) const
150{
151 QVariant res = resource(type: QTextDocument::ImageResource, name: QUrl(format.name()));
152 return res.value<QImage>();
153}
154
155QQuickPixmap *QQuickTextDocumentWithImageResources::loadPixmap(
156 QQmlContext *context, const QUrl &url)
157{
158
159 QHash<QUrl, QQuickPixmap *>::Iterator iter = m_resources.find(key: url);
160
161 if (iter == m_resources.end()) {
162 QQuickPixmap *p = new QQuickPixmap(context->engine(), url);
163 iter = m_resources.insert(key: url, value: p);
164
165 if (p->isLoading()) {
166 p->connectFinished(this, SLOT(requestFinished()));
167 outstanding++;
168 }
169 }
170
171 QQuickPixmap *p = *iter;
172 if (p->isError()) {
173 if (!errors.contains(value: url)) {
174 errors.insert(value: url);
175 qmlWarning(me: parent()) << p->error();
176 }
177 }
178 return p;
179}
180
181void QQuickTextDocumentWithImageResources::clearResources()
182{
183 for (QQuickPixmap *pixmap : std::as_const(t&: m_resources))
184 pixmap->clear(this);
185 qDeleteAll(c: m_resources);
186 m_resources.clear();
187 outstanding = 0;
188}
189
190QSet<QUrl> QQuickTextDocumentWithImageResources::errors;
191
192QT_END_NAMESPACE
193
194#include "moc_qquicktextdocument.cpp"
195#include "moc_qquicktextdocument_p.cpp"
196

source code of qtdeclarative/src/quick/items/qquicktextdocument.cpp