60QQuickTextDocument::QQuickTextDocument(QQuickItem *parent)
61 : QObject(*(
new QQuickTextDocumentPrivate), parent)
63 Q_D(QQuickTextDocument);
65 d->editor = qobject_cast<QQuickTextEdit *>(parent);
67 connect(textDocument(), &QTextDocument::modificationChanged,
68 this, &QQuickTextDocument::modifiedChanged);
297 auto *doc =
editor->document();
299 setStatus(QQuickTextDocument::Status::ReadError,
300 QQuickTextDocument::tr(
"Null document object: cannot load"));
303 const QQmlContext *context = qmlContext(
editor);
304 const QUrl &resolvedUrl = context ? context->resolvedUrl(url) : url;
305 const QString filePath = QQmlFile::urlToLocalFileOrQrc(resolvedUrl);
306 QFile file(filePath);
308#if QT_CONFIG(mimetype)
309 QMimeType mimeType = QMimeDatabase().mimeTypeForFile(filePath);
310 const bool isHtml = mimeType.inherits(
"text/html"_L1);
311 const bool isMarkdown = mimeType.inherits(
"text/markdown"_L1)
312 || mimeType.inherits(
"text/x-web-markdown"_L1);
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);
320 detectedFormat = Qt::RichText;
322 detectedFormat = Qt::MarkdownText;
324 detectedFormat = Qt::PlainText;
325 if (file.open(QFile::ReadOnly | QFile::Text)) {
326 setStatus(QQuickTextDocument::Status::Loading, {});
327 QByteArray data = file.readAll();
328 doc->setBaseUrl(resolvedUrl.adjusted(QUrl::RemoveFilename));
329#if QT_CONFIG(textmarkdownreader) || QT_CONFIG(texthtmlparser)
330 const bool plainText = editor->textFormat() == QQuickTextEdit::PlainText;
332#if QT_CONFIG(textmarkdownreader)
333 if (!plainText && isMarkdown) {
334 doc->setMarkdown(QString::fromUtf8(data));
337#if QT_CONFIG(texthtmlparser)
338 if (!plainText && isHtml) {
341 encoding = QStringConverter::encodingForHtml(data);
343 QStringDecoder decoder(*encoding);
344 doc->setHtml(decoder(data));
347 doc->setHtml(QString::fromUtf8(data));
352 doc->setPlainText(QString::fromUtf8(data));
354 editor->setCursorPosition(0);
355 setStatus(QQuickTextDocument::Status::Loaded, {});
356 qCDebug(lcTextDoc) <<
editor <<
"loaded" << filePath
357 <<
"as" <<
editor->textFormat() <<
"detected" << detectedFormat
358#if QT_CONFIG(mimetype)
359 <<
"(file type" << mimeType <<
')'
362 doc->setModified(
false);
365 setStatus(QQuickTextDocument::Status::ReadError,
366 QQuickTextDocument::tr(
"Failed to read: %1").arg(file.errorString()));
368 setStatus(QQuickTextDocument::Status::ReadError,
369 QQuickTextDocument::tr(
"%1 does not exist").arg(filePath));
375 auto *doc =
editor->document();
379 const QString filePath = QQmlFile::urlToLocalFileOrQrc(fileUrl);
380 const bool sameUrl = fileUrl == url;
382#if QT_CONFIG(mimetype)
383 const auto type = QMimeDatabase().mimeTypeForUrl(fileUrl);
384 if (type.inherits(
"text/html"_L1))
385 detectedFormat = Qt::RichText;
386 else if (type.inherits(
"text/markdown"_L1))
387 detectedFormat = Qt::MarkdownText;
389 detectedFormat = Qt::PlainText;
391 if (filePath.endsWith(
".html"_L1, Qt::CaseInsensitive) ||
392 filePath.endsWith(
".htm"_L1, Qt::CaseInsensitive))
393 detectedFormat = Qt::RichText;
394 else if (filePath.endsWith(
".md"_L1, Qt::CaseInsensitive) ||
395 filePath.endsWith(
".markdown"_L1, Qt::CaseInsensitive))
396 detectedFormat = Qt::MarkdownText;
398 detectedFormat = Qt::PlainText;
401 QFile file(filePath);
402 if (!file.open(QFile::WriteOnly | QFile::Truncate |
403 (detectedFormat == Qt::RichText ? QFile::NotOpen : QFile::Text))) {
404 setStatus(QQuickTextDocument::Status::WriteError,
405 QQuickTextDocument::tr(
"Cannot save: %1").arg(file.errorString()));
408 setStatus(QQuickTextDocument::Status::Saving, {});
411 switch (detectedFormat) {
412#if QT_CONFIG(textmarkdownwriter)
413 case Qt::MarkdownText:
414 raw = doc->toMarkdown().toUtf8();
417#if QT_CONFIG(texthtmlparser)
419 if (sameUrl && encoding) {
420 QStringEncoder enc(*encoding);
421 raw = enc.encode(doc->toHtml());
424 raw = doc->toHtml().toUtf8();
429 raw = doc->toPlainText().toUtf8();
435 setStatus(QQuickTextDocument::Status::Saved, {});
436 doc->setModified(
false);
593 QTextDocument *doc,
int,
const QTextFormat &format)
595 if (format.isImageFormat()) {
596 QTextImageFormat imageFormat = format.toImageFormat();
597 int width = qRound(qBound(qreal(INT_MIN), imageFormat.width(), qreal(INT_MAX)));
598 const bool hasWidth = imageFormat.hasProperty(QTextFormat::ImageWidth) && width > 0;
599 const int height = qRound(qBound(qreal(INT_MIN), imageFormat.height(), qreal(INT_MAX)));
600 const bool hasHeight = imageFormat.hasProperty(QTextFormat::ImageHeight) && height > 0;
601 const auto maxWidth = imageFormat.maximumWidth();
602 const bool hasMaxWidth = imageFormat.hasProperty(QTextFormat::ImageMaxWidth) && maxWidth.type() != QTextLength::VariableLength;
604 int effectiveMaxWidth = INT_MAX;
606 if (maxWidth.type() == QTextLength::PercentageLength) {
607 effectiveMaxWidth = (doc->pageSize().width() - 2 * doc->documentMargin()) * maxWidth.value(100) / 100;
609 effectiveMaxWidth = maxWidth.rawValue();
612 width = qMin(effectiveMaxWidth, width);
615 QSizeF size(width, height);
616 if (!hasWidth || !hasHeight) {
617 QVariant res = doc->resource(QTextDocument::ImageResource, QUrl(imageFormat.name()));
618 QImage image = res.value<QImage>();
619 if (image.isNull()) {
628 QSize imgSize = image.size();
629 if (imgSize.width() > effectiveMaxWidth) {
631 imgSize.setHeight(effectiveMaxWidth * imgSize.height() / (qreal) imgSize.width());
632 imgSize.setWidth(effectiveMaxWidth);
637 size.setWidth(imgSize.width());
639 size.setWidth(qMin(effectiveMaxWidth, qRound(height * (imgSize.width() / (qreal) imgSize.height()))));
643 size.setHeight(imgSize.height());
645 size.setHeight(qRound(width * (imgSize.height() / (qreal) imgSize.width())));
QTextDocument * document() const
void setStatus(QQuickTextDocument::Status s, const QString &err)
void setDocument(QTextDocument *doc)
void writeTo(const QUrl &fileUrl)
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...