diff options
author | Shawn Rutledge <[email protected]> | 2022-11-09 10:15:13 +0100 |
---|---|---|
committer | Shawn Rutledge <[email protected]> | 2023-12-04 12:16:06 -0700 |
commit | 7fb39a7accba014063e32ac41a58b77905bbd95b (patch) | |
tree | a7ed0e25e83af7f1dde97577ee684db2ef703e70 /src/quick/items/qquicktextedit_p_p.h | |
parent | 90abce175f9440de0978eb8ae36a0afe11e4c058 (diff) |
Get rid of QQuickTextDocumentWithImageResources
Users want to be able to provide their own QTextDocument instances
to TextEdit; but we had been creating a subclass called
QQuickTextDocumentWithImageResources, which was an obstacle for that.
QTextDocumentPrivate has two QMaps to hold resources, but
QQuickTextDocumentWithImageResources existed for the purpose of caching
remote resources, which only QQuickPixmap knows how to fetch. (This
design was apparently invented as a workaround to the lack of
virtual-filesystem functionality in Qt Core. If QtCore already knew how
to fetch web resources from URLs in the background, QTextDocument could
use it to do its own fetching of remote resources.) What we want instead
of subclassing QTextDocument is to keep doing the fetching in Qt Quick
(because there's no other choice for now), but get the images into the
same QTextDocumentPrivate::cachedResources map where local-file
resources are cached.
As it turns out, since qtbase ac300a166f801a6f6c0b15278e6893720a5726f8
QTextDocument::loadResource() can use QMetaMethod::invoke() to call a
method with the signature QVariant loadResource(int,QUrl) if such a
method is found in QTD's parent object; so since QQuickTextEdit creates
its own document by default, and is the document's parent, we can keep
remote resource fetching functionality working by 1) providing the
QQuickTextEdit::loadResource() method to be invoked, and 2) moving the
document to the QML thread so that it can be invoked directly.
(QMetaMethod::invoke() doesn't work across a queued connection, because
we need to return a value: the QVariant.) QTD will already cache the
images as soon as the call to loadResource() returns a valid QVariant.
We ask for the QQuickPixmap not to be cached by passing an empty
QQuickPixmap::Option enum to its ctor, which gets passed through
to the load() function.
When we consider fetching resources from a web server, it's unfortunate
that the signature of QTextDocument::resource() sets the expectation
that resources can be loaded immediately. But as long as
QQuickTextEdit::loadResource() is waiting for fetching to be done, it
keeps returning a default-constructed QVariant, which won't be cached;
and it will be called again later, repeatedly, until it eventually
succeeds. To ensure that it is called again when fetching is done, we
call QTextDocument::resource() again, to provoke it to call our
QQuickTextEdit::loadResource() one last time. If the returned image
wasn't cached before, it will be after that. Then it's ok to delete the
QQuickPixmap, and invalidate the TextEdit so that layout will be updated
to include the image, now that we have it.
But most of the time it's relatively boring: QTextDocument knows
how to load local files on its own, and caches them.
So we no longer need QQuickTextDocumentWithImageResources. But we
still needed to replace QTextImageHandler with a custom implementation,
as explained in bab2eaf3da299c471dd898c89cf356984b077412: we need
QQuickPixmap for its QML-specific URL resolution relative to the Text
item's context. And it turns out that in case the document contains
only a missing image, the minimum size is 16x16 pixels, to reserve
space to display a "broken image" icon as browsers sometimes do...
we have never actually done that in Qt Quick AFAICT, but autotests have
been enforcing the 16x16 minimum size all along. This is done in
QQuickTextImageHandler::intrinsicSize() now.
The same approach is taken with Text (when textFormat is RichText or
MarkdownText. In case of StyledText, there is no QTextDocument instance,
and resource loading is taken care of entirely within QQuickText.)
For the autotests, friendly use of QQuickPixmapCache::m_cache requires
QT_BEGIN_NAMESPACE.
Task-number: QTBUG-35688
Change-Id: I8ad8142b3b3790254dd56d6cfe5209d641465f08
Reviewed-by: Oliver Eftevaag <[email protected]>
Reviewed-by: Axel Spoerl <[email protected]>
Reviewed-by: Fabian Kosmale <[email protected]>
Diffstat (limited to 'src/quick/items/qquicktextedit_p_p.h')
-rw-r--r-- | src/quick/items/qquicktextedit_p_p.h | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h index 7891a744ec..934ef0e460 100644 --- a/src/quick/items/qquicktextedit_p_p.h +++ b/src/quick/items/qquicktextedit_p_p.h @@ -22,6 +22,7 @@ #include <QtQml/qqml.h> #include <QtCore/qlist.h> #include <private/qlazilyallocated_p.h> +#include <private/qquicktextdocument_p.h> #if QT_CONFIG(accessibility) #include <QtGui/qaccessible.h> @@ -31,7 +32,7 @@ QT_BEGIN_NAMESPACE class QTextLayout; -class QQuickTextDocumentWithImageResources; +class QQuickPixmap; class QQuickTextControl; class QSGInternalTextNode; class QQuickTextNodeEngine; @@ -163,10 +164,11 @@ public: QQmlComponent* cursorComponent = nullptr; QQuickItem* cursorItem = nullptr; - QQuickTextDocumentWithImageResources *document = nullptr; + QTextDocument *document = nullptr; QQuickTextControl *control = nullptr; QQuickTextDocument *quickDocument = nullptr; QList<Node> textNodeMap; + QList<QQuickPixmap *> pixmapsInProgress; int lastSelectionStart = 0; int lastSelectionEnd = 0; |