Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquicktextdocument.cpp
Go to the documentation of this file.
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
6
7#include "qquicktextedit_p.h"
8
9#include <QtQml/qqmlcontext.h>
10#include <QtQml/qqmlfile.h>
11#include <QtQml/qqmlinfo.h>
12#include <QtQuick/private/qquickpixmap_p.h>
13
14#include <QtCore/qfile.h>
15#include <QtCore/qpointer.h>
16
18
19Q_LOGGING_CATEGORY(lcTextDoc, "qt.quick.textdocument")
20
21using namespace Qt::StringLiterals;
22
62 : QObject(*(new QQuickTextDocumentPrivate), parent)
63{
65 Q_ASSERT(parent);
66 d->editor = qobject_cast<QQuickTextEdit *>(parent);
67 Q_ASSERT(d->editor);
69 this, &QQuickTextDocument::modifiedChanged);
70}
71
142{
143 Q_D(const QQuickTextDocument);
144 return d->status;
145}
146
170{
171 Q_D(const QQuickTextDocument);
172 return d->errorString;
173}
174
176{
178 if (status == s)
179 return;
180
181 status = s;
182 emit q->statusChanged();
183
184 if (errorString == err)
185 return;
186 errorString = err;
187 emit q->errorStringChanged();
188 if (!err.isEmpty())
189 qmlWarning(q) << err;
190}
191
229{
230 Q_D(const QQuickTextDocument);
231 return d->url;
232}
233
235{
237
238 if (url == d->url)
239 return;
240
241 if (isModified()) {
242 qmlWarning(this) << "Existing document modified: you should save(),"
243 "or call TextEdit.clear() before setting a different source";
244 return;
245 }
246
247 d->url = url;
248 emit sourceChanged();
249 d->load();
250}
251
285{
286 const auto *doc = textDocument();
287 return doc && doc->isModified();
288}
289
291{
292 if (auto *doc = textDocument())
293 doc->setModified(modified);
294}
295
297{
298 auto *doc = editor->document();
299 if (!doc) {
301 QQuickTextDocument::tr("Null document object: cannot load"));
302 return;
303 }
305 const QUrl &resolvedUrl = context ? context->resolvedUrl(url) : url;
307 QFile file(filePath);
308 if (file.exists()) {
309#if QT_CONFIG(mimetype)
311 const bool isHtml = mimeType.inherits("text/html"_L1);
312 const bool isMarkdown = mimeType.inherits("text/markdown"_L1);
313#else
314 const bool isHtml = filePath.endsWith(".html"_L1, Qt::CaseInsensitive) ||
315 filePath.endsWith(".htm"_L1, Qt::CaseInsensitive);
316 const bool isMarkdown = filePath.endsWith(".md"_L1, Qt::CaseInsensitive) ||
317 filePath.endsWith(".markdown"_L1, Qt::CaseInsensitive);
318#endif
319 if (isHtml)
321 else if (isMarkdown)
323 else
328 doc->setBaseUrl(resolvedUrl.adjusted(QUrl::RemoveFilename));
329#if QT_CONFIG(textmarkdownreader) || QT_CONFIG(texthtmlparser)
331#endif
332#if QT_CONFIG(textmarkdownreader)
333 if (!plainText && isMarkdown) {
334 doc->setMarkdown(QString::fromUtf8(data));
335 } else
336#endif
337#if QT_CONFIG(texthtmlparser)
338 if (!plainText && isHtml) {
339 // If a user loads an HTML file, remember the encoding.
340 // If the user then calls save() later, the same encoding will be used.
342 if (encoding) {
343 QStringDecoder decoder(*encoding);
344 doc->setHtml(decoder(data));
345 } else {
346 // fall back to utf8
347 doc->setHtml(QString::fromUtf8(data));
348 }
349 } else
350#endif
351 {
352 doc->setPlainText(QString::fromUtf8(data));
353 }
355 qCDebug(lcTextDoc) << editor << "loaded" << filePath
356 << "as" << editor->textFormat() << "detected" << detectedFormat
357#if QT_CONFIG(mimetype)
358 << "(file type" << mimeType << ')'
359#endif
360 ;
361 doc->setModified(false);
362 return;
363 }
365 QQuickTextDocument::tr("Failed to read: %1").arg(file.errorString()));
366 } else {
368 QQuickTextDocument::tr("%1 does not exist").arg(filePath));
369 }
370}
371
373{
374 auto *doc = editor->document();
375 if (!doc)
376 return;
377
378 const QString filePath = fileUrl.toLocalFile();
379 const bool sameUrl = fileUrl == url;
380 if (!sameUrl) {
381#if QT_CONFIG(mimetype)
382 const auto type = QMimeDatabase().mimeTypeForUrl(fileUrl);
383 if (type.inherits("text/html"_L1))
385 else if (type.inherits("text/markdown"_L1))
387 else
389#else
390 if (filePath.endsWith(".html"_L1, Qt::CaseInsensitive) ||
391 filePath.endsWith(".htm"_L1, Qt::CaseInsensitive))
393 else if (filePath.endsWith(".md"_L1, Qt::CaseInsensitive) ||
394 filePath.endsWith(".markdown"_L1, Qt::CaseInsensitive))
396 else
398#endif
399 }
400 QFile file(filePath);
404 QQuickTextDocument::tr("Cannot save: %1").arg(file.errorString()));
405 return;
406 }
408 QByteArray raw;
409
410 switch (detectedFormat) {
411#if QT_CONFIG(textmarkdownwriter)
412 case Qt::MarkdownText:
413 raw = doc->toMarkdown().toUtf8();
414 break;
415#endif
416#if QT_CONFIG(texthtmlparser)
417 case Qt::RichText:
418 if (sameUrl && encoding) {
420 raw = enc.encode(doc->toHtml());
421 } else {
422 // default to UTF-8 unless the user is saving the same file as previously loaded
423 raw = doc->toHtml().toUtf8();
424 }
425 break;
426#endif
427 default:
428 raw = doc->toPlainText().toUtf8();
429 break;
430 }
431
432 file.write(raw);
433 file.close();
435 doc->setModified(false);
436}
437
439{
440 return editor->document();
441}
442
444{
446 QTextDocument *oldDoc = editor->document();
447 if (doc == oldDoc)
448 return;
449
450 if (oldDoc)
451 oldDoc->disconnect(q);
452 if (doc) {
454 q, &QQuickTextDocument::modifiedChanged);
455 }
456 editor->setDocument(doc);
457 emit q->textDocumentChanged();
458}
459
464{
465 Q_D(const QQuickTextDocument);
466 return d->document();
467}
468
476{
477 d_func()->setDocument(document);
478}
479
532void QQuickTextDocument::save()
533{
535 d->writeTo(d->url);
536}
537
565void QQuickTextDocument::saveAs(const QUrl &url)
566{
568 if (!url.isLocalFile()) {
570 QQuickTextDocument::tr("Can only save to local files"));
571 return;
572 }
573 d->writeTo(url);
574
575 if (url == d->url)
576 return;
577
578 d->url = url;
579 emit sourceChanged();
580}
581
586
588 QTextDocument *doc, int, const QTextFormat &format)
589{
590 if (format.isImageFormat()) {
591 QTextImageFormat imageFormat = format.toImageFormat();
592 const int width = qRound(imageFormat.width());
593 const bool hasWidth = imageFormat.hasProperty(QTextFormat::ImageWidth) && width > 0;
594 const int height = qRound(imageFormat.height());
595 const bool hasHeight = imageFormat.hasProperty(QTextFormat::ImageHeight) && height > 0;
597 if (!hasWidth || !hasHeight) {
599 QImage image = res.value<QImage>();
600 if (image.isNull()) {
601 // autotests expect us to reserve a 16x16 space for a "broken image" icon,
602 // even though we don't actually display one
603 if (!hasWidth)
604 size.setWidth(16);
605 if (!hasHeight)
606 size.setHeight(16);
607 return size;
608 }
609 QSize imgSize = image.size();
610 if (!hasWidth) {
611 if (!hasHeight)
612 size.setWidth(imgSize.width());
613 else
614 size.setWidth(qRound(height * (imgSize.width() / (qreal) imgSize.height())));
615 }
616 if (!hasHeight) {
617 if (!hasWidth)
618 size.setHeight(imgSize.height());
619 else
620 size.setHeight(qRound(width * (imgSize.height() / (qreal) imgSize.width())));
621 }
622 }
623 return size;
624 }
625 return QSizeF();
626}
627
629
630#include "moc_qquicktextdocument.cpp"
631#include "moc_qquicktextdocument_p.cpp"
\inmodule QtCore
Definition qbytearray.h:57
void close() override
Calls QFileDevice::flush() and closes the file.
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
QString errorString() const
Returns a human-readable description of the last device error that occurred.
\inmodule QtGui
Definition qimage.h:37
\inmodule QtCore
QMimeType mimeTypeForUrl(const QUrl &url) const
Returns a MIME type for url.
QMimeType mimeTypeForFile(const QString &fileName, MatchMode mode=MatchDefault) const
Returns a MIME type for the file named fileName using mode.
\inmodule QtCore
Definition qmimetype.h:25
\inmodule QtCore
Definition qobject.h:103
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
The QQmlContext class defines a context within a QML engine.
Definition qqmlcontext.h:25
static QString urlToLocalFileOrQrc(const QString &)
If url is a local file returns a path suitable for passing to \l{QFile}.
Definition qqmlfile.cpp:742
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
QQuickTextDocument::Status status
QTextDocument * document() const
std::optional< QStringConverter::Encoding > encoding
void setStatus(QQuickTextDocument::Status s, const QString &err)
void setDocument(QTextDocument *doc)
void writeTo(const QUrl &fileUrl)
\qmltype TextDocument \instantiates QQuickTextDocument \inqmlmodule QtQuick
Status status
the status of document loading or saving
bool isModified() const
\qmlproperty bool QtQuick::TextDocument::modified
QUrl source
the URL from which to load document contents
void setSource(const QUrl &url)
void setModified(bool modified)
void setTextDocument(QTextDocument *document)
Sets the given document.
bool modified
whether the document has been modified by the user
QTextDocument * textDocument() const
Returns a pointer to the QTextDocument object.
QString errorString
a human-readable string describing the error that occurred during loading or saving,...
TextFormat textFormat
QQuickTextImageHandler(QObject *parent=nullptr)
QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format) override
The intrinsicSize() function returns the size of the text object represented by format in the given d...
\inmodule QtCore
Definition qsize.h:208
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
static Q_CORE_EXPORT std::optional< Encoding > encodingForHtml(QByteArrayView data)
Tries to determine the encoding of the HTML in data by looking at leading byte order marks or a chars...
\inmodule QtCore
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition qstring.cpp:5506
\reentrant \inmodule QtGui
void modificationChanged(bool m)
This signal is emitted whenever the content of the document changes in a way that affects the modific...
QVariant resource(int type, const QUrl &name) const
Returns data of the specified type from the resource with the given name.
\reentrant
Definition qtextformat.h:90
QTextImageFormat toImageFormat() const
Returns this format as an image format.
bool hasProperty(int propertyId) const
Returns true if the text format has a property with the given propertyId; otherwise returns false.
qreal width() const
Returns the width of the rectangle occupied by the image.
qreal height() const
Returns the height of the rectangle occupied by the image.
QString name() const
Returns the name of the image.
\inmodule QtCore
Definition qurl.h:94
bool isLocalFile() const
Definition qurl.cpp:3445
QString url(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2817
@ RemoveFilename
Definition qurl.h:116
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition qurl.cpp:3425
\inmodule QtCore
Definition qvariant.h:65
Combined button and popup list for selecting options.
Definition qcompare.h:63
@ RichText
@ MarkdownText
@ PlainText
@ CaseInsensitive
Definition image.cpp:4
static void * context
const char * mimeType
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:327
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei width
GLenum type
GLint GLsizei GLsizei GLenum format
GLdouble s
[6]
Definition qopenglext.h:235
GLuint res
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
QQmlContext * qmlContext(const QObject *obj)
Definition qqml.cpp:75
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me)
static QUrl resolvedUrl(const QUrl &url, const QQmlRefPointer< QQmlContextData > &context)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
SSL_CTX int void * arg
#define emit
double qreal
Definition qtypes.h:187
QFile file
[0]
QUrl url("example.com")
[constructor-url-reference]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
const QByteArray plainText