summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Volkov <avolkov@astralinux.ru>2018-09-25 18:09:28 +0300
committerAlexander Volkov <avolkov@astralinux.ru>2021-01-12 15:33:10 +0300
commit376e3bd8ecf40881685714f6f19e12d68e92127e (patch)
tree8a137b8cea51115b405202ef6c0cffdf6fe78192
parent9e09677c1dd4da92735736a0fbcb703416bf4d6d (diff)
Introduce QUrlResourceProvider to load resources for HTML
QTextDocument and the text editor classes suggest to override their loadResource() methods to provide data associated with a text document. This approach has the following drawbacks: - it requires subclassing - there is no way to set a global resource provider - QLabel is missing virtual loadResource() method and it can't be added without breaking ABI QUrlResourceProvider is designed to solve these issues. One should create a derived class that implements QUrlResourceProvider::resource(). The objects of the derived class then can be set for any text document. The default resource provider can be set with QUrlResourceProvider::setDefaultProvider(). This change also adds QLabel::setResourceProvider(), which doesn't break ABI. [ChangeLog][QtGui][Text] Introduced QUrlResourceProvider that allows to load resources for HTML. It is intended to replace the use of QTextDocument::loadResource(). Change-Id: Iaf19b229f522a73508f20715257450fe58f68daf Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com> Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--src/gui/CMakeLists.txt1
-rw-r--r--src/gui/text/qtextdocument.cpp35
-rw-r--r--src/gui/text/qtextdocument.h4
-rw-r--r--src/gui/text/qtextdocument_p.cpp4
-rw-r--r--src/gui/text/qtextdocument_p.h1
-rw-r--r--src/gui/text/qurlresourceprovider.cpp88
-rw-r--r--src/gui/text/qurlresourceprovider.h61
-rw-r--r--src/widgets/widgets/qlabel.cpp31
-rw-r--r--src/widgets/widgets/qlabel.h4
-rw-r--r--src/widgets/widgets/qlabel_p.h1
-rw-r--r--src/widgets/widgets/qwidgettextcontrol.cpp1
-rw-r--r--tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp25
-rw-r--r--tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp26
13 files changed, 279 insertions, 3 deletions
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 802c0a2ecd..30e28cfd0e 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -242,6 +242,7 @@ qt_internal_add_module(Gui
text/qtextobject.cpp text/qtextobject.h text/qtextobject_p.h
text/qtextoption.cpp text/qtextoption.h
text/qtexttable.cpp text/qtexttable.h text/qtexttable_p.h
+ text/qurlresourceprovider.cpp text/qurlresourceprovider.h
util/qabstractlayoutstyleinfo.cpp util/qabstractlayoutstyleinfo_p.h
util/qastchandler.cpp util/qastchandler_p.h
util/qdesktopservices.cpp util/qdesktopservices.h
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 0fae775bae..2e9293eb99 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -46,6 +46,7 @@
#include "qtextdocumentfragment_p.h"
#include "qtexttable.h"
#include "qtextlist.h"
+#include "qurlresourceprovider.h"
#include <qdebug.h>
#if QT_CONFIG(regularexpression)
#include <qregularexpression.h>
@@ -354,6 +355,7 @@ QTextDocument *QTextDocument::clone(QObject *parent) const
priv->setDefaultFont(d->defaultFont());
priv->resources = d->resources;
priv->cachedResources.clear();
+ priv->resourceProvider = d->resourceProvider;
#ifndef QT_NO_CSSPARSER
priv->defaultStyleSheet = d->defaultStyleSheet;
priv->parsedDefaultStyleSheet = d->parsedDefaultStyleSheet;
@@ -2087,8 +2089,15 @@ QVariant QTextDocument::resource(int type, const QUrl &name) const
QVariant r = d->resources.value(url);
if (!r.isValid()) {
r = d->cachedResources.value(url);
- if (!r.isValid())
+ if (!r.isValid()) {
r = const_cast<QTextDocument *>(this)->loadResource(type, url);
+ if (!r.isValid()) {
+ if (d->resourceProvider)
+ r = d->resourceProvider->resource(url);
+ else if (auto defaultProvider = QUrlResourceProvider::defaultProvider())
+ r = defaultProvider->resource(url);
+ }
+ }
}
return r;
}
@@ -2119,6 +2128,30 @@ void QTextDocument::addResource(int type, const QUrl &name, const QVariant &reso
}
/*!
+ \since 6.1
+
+ Returns the resource provider for this text document.
+*/
+QUrlResourceProvider *QTextDocument::resourceProvider() const
+{
+ Q_D(const QTextDocument);
+ return d->resourceProvider;
+}
+
+/*!
+ \since 6.1
+
+ Sets the \a provider of resources for the text document.
+
+ \note The text document \e{does not} take ownership of the \a provider.
+*/
+void QTextDocument::setResourceProvider(QUrlResourceProvider *provider)
+{
+ Q_D(QTextDocument);
+ d->resourceProvider = provider;
+}
+
+/*!
Loads data of the specified \a type from the resource with the
given \a name.
diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h
index 23fffc4771..ea57b697a8 100644
--- a/src/gui/text/qtextdocument.h
+++ b/src/gui/text/qtextdocument.h
@@ -68,6 +68,7 @@ class QVariant;
class QRectF;
class QTextOption;
class QTextCursor;
+class QUrlResourceProvider;
namespace Qt
@@ -239,6 +240,9 @@ public:
QVariant resource(int type, const QUrl &name) const;
void addResource(int type, const QUrl &name, const QVariant &resource);
+ QUrlResourceProvider *resourceProvider() const;
+ void setResourceProvider(QUrlResourceProvider *provider);
+
QList<QTextFormat> allFormats() const;
void markContentsDirty(int from, int length);
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index d6da0f38d2..1f2e8d2da2 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -52,6 +52,7 @@
#include "qtextdocumentlayout_p.h"
#include "qtexttable.h"
#include "qtextengine_p.h"
+#include "qurlresourceprovider.h"
#include <stdlib.h>
@@ -186,7 +187,8 @@ QTextDocumentPrivate::QTextDocumentPrivate()
docChangeLength(0),
framesDirty(true),
rtFrame(nullptr),
- initialBlockCharFormatIndex(-1) // set correctly later in init()
+ initialBlockCharFormatIndex(-1), // set correctly later in init()
+ resourceProvider(nullptr)
{
editBlock = 0;
editBlockCursorPosition = -1;
diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h
index b4e0f526d0..d04113b320 100644
--- a/src/gui/text/qtextdocument_p.h
+++ b/src/gui/text/qtextdocument_p.h
@@ -366,6 +366,7 @@ private:
QMap<int, QTextObject *> objects;
QMap<QUrl, QVariant> resources;
QMap<QUrl, QVariant> cachedResources;
+ QUrlResourceProvider *resourceProvider;
QString defaultStyleSheet;
int lastBlockCount;
diff --git a/src/gui/text/qurlresourceprovider.cpp b/src/gui/text/qurlresourceprovider.cpp
new file mode 100644
index 0000000000..6a50504471
--- /dev/null
+++ b/src/gui/text/qurlresourceprovider.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Alexander Volkov <avolkov@astralinux.ru>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qurlresourceprovider.h"
+
+#include <QtCore/qatomic.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QUrlResourceProvider
+ \inmodule QtGui
+ \since 6.1
+ \brief The QUrlResourceProvider is the base class of resource providers for QTextDocument.
+ \note An implementation should be thread-safe if it can be accessed from different threads,
+ e.g. when the default resource provider lives in the main thread and a QTexDocument lives
+ outside the main thread.
+*/
+
+static QAtomicPointer<QUrlResourceProvider> qt_provider;
+
+/*!
+ Destroys the resource provider.
+*/
+QUrlResourceProvider::~QUrlResourceProvider()
+{
+ qt_provider.testAndSetRelease(this, nullptr);
+}
+
+/*!
+ \fn virtual QVariant QUrlResourceProvider::resource(const QUrl &url) = 0;
+
+ Returns data specified by the \a url.
+*/
+
+/*!
+ Returns the default resource provider.
+*/
+QUrlResourceProvider *QUrlResourceProvider::defaultProvider()
+{
+ return qt_provider.loadAcquire();
+}
+
+/*!
+ Set the default resource provider to \a provider.
+*/
+void QUrlResourceProvider::setDefaultProvider(QUrlResourceProvider *provider)
+{
+ qt_provider.storeRelease(provider);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qurlresourceprovider.h b/src/gui/text/qurlresourceprovider.h
new file mode 100644
index 0000000000..587a371a83
--- /dev/null
+++ b/src/gui/text/qurlresourceprovider.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Alexander Volkov <avolkov@astralinux.ru>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QURLRESOURCEPROVIDER_H
+#define QURLRESOURCEPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+
+class Q_GUI_EXPORT QUrlResourceProvider
+{
+public:
+ virtual ~QUrlResourceProvider();
+ virtual QVariant resource(const QUrl &url) = 0;
+
+ static QUrlResourceProvider *defaultProvider();
+ static void setDefaultProvider(QUrlResourceProvider *provider);
+};
+
+QT_END_NAMESPACE
+
+#endif // QURLRESOURCEPROVIDER_H
diff --git a/src/widgets/widgets/qlabel.cpp b/src/widgets/widgets/qlabel.cpp
index e124022e52..2d7b7f79b1 100644
--- a/src/widgets/widgets/qlabel.cpp
+++ b/src/widgets/widgets/qlabel.cpp
@@ -100,7 +100,8 @@ QLabelPrivate::QLabelPrivate()
validCursor(false),
onAnchor(false),
#endif
- openExternalLinks(false)
+ openExternalLinks(false),
+ resourceProvider(nullptr)
{
}
@@ -1424,6 +1425,32 @@ void QLabel::setTextFormat(Qt::TextFormat format)
}
/*!
+ \since 6.1
+
+ Returns the resource provider for rich text of this label.
+*/
+QUrlResourceProvider *QLabel::resourceProvider() const
+{
+ Q_D(const QLabel);
+ return d->control ? d->control->document()->resourceProvider() : d->resourceProvider;
+}
+
+/*!
+ \since 6.1
+
+ Sets the \a provider of resources for rich text of this label.
+
+ \note The label \e{does not} take ownership of the \a provider.
+*/
+void QLabel::setResourceProvider(QUrlResourceProvider *provider)
+{
+ Q_D(QLabel);
+ d->resourceProvider = provider;
+ if (d->control != nullptr)
+ d->control->document()->setResourceProvider(provider);
+}
+
+/*!
\reimp
*/
void QLabel::changeEvent(QEvent *ev)
@@ -1589,6 +1616,8 @@ void QLabelPrivate::ensureTextControl() const
control = new QWidgetTextControl(const_cast<QLabel *>(q));
control->document()->setUndoRedoEnabled(false);
control->document()->setDefaultFont(q->font());
+ if (resourceProvider != nullptr)
+ control->document()->setResourceProvider(resourceProvider);
control->setTextInteractionFlags(textInteractionFlags);
control->setOpenExternalLinks(openExternalLinks);
control->setPalette(q->palette());
diff --git a/src/widgets/widgets/qlabel.h b/src/widgets/widgets/qlabel.h
index 8cc86b421e..69aea6d57a 100644
--- a/src/widgets/widgets/qlabel.h
+++ b/src/widgets/widgets/qlabel.h
@@ -49,6 +49,7 @@ QT_REQUIRE_CONFIG(label);
QT_BEGIN_NAMESPACE
+class QUrlResourceProvider;
class QLabelPrivate;
class Q_WIDGETS_EXPORT QLabel : public QFrame
@@ -92,6 +93,9 @@ public:
Qt::TextFormat textFormat() const;
void setTextFormat(Qt::TextFormat);
+ QUrlResourceProvider *resourceProvider() const;
+ void setResourceProvider(QUrlResourceProvider *provider);
+
Qt::Alignment alignment() const;
void setAlignment(Qt::Alignment);
diff --git a/src/widgets/widgets/qlabel_p.h b/src/widgets/widgets/qlabel_p.h
index 4458df3b3e..80243239d2 100644
--- a/src/widgets/widgets/qlabel_p.h
+++ b/src/widgets/widgets/qlabel_p.h
@@ -154,6 +154,7 @@ public:
#endif
uint openExternalLinks : 1;
// <-- space for more bit field values here
+ QUrlResourceProvider *resourceProvider;
friend class QMessageBoxPrivate;
};
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp
index 9fe6e3e1e3..ef1be67975 100644
--- a/src/widgets/widgets/qwidgettextcontrol.cpp
+++ b/src/widgets/widgets/qwidgettextcontrol.cpp
@@ -2677,6 +2677,7 @@ void QWidgetTextControl::print(QPagedPaintDevice *printer) const
if (!d->cursor.hasSelection())
return;
tempDoc = new QTextDocument(const_cast<QTextDocument *>(doc));
+ tempDoc->setResourceProvider(doc->resourceProvider());
tempDoc->setMetaInformation(QTextDocument::DocumentTitle, doc->metaInformation(QTextDocument::DocumentTitle));
tempDoc->setPageSize(doc->pageSize());
tempDoc->setDefaultFont(doc->defaultFont());
diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
index c290305d2f..4e0b7f46df 100644
--- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
+++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
@@ -47,6 +47,7 @@
#include <qimage.h>
#include <qtextlayout.h>
#include <QDomDocument>
+#include <qurlresourceprovider.h>
#include "common.h"
// #define DEBUG_WRITE_OUTPUT
@@ -192,6 +193,8 @@ private slots:
void clearUndoRedoStacks();
void mergeFontFamilies();
+ void resourceProvider();
+
private:
void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
void buildRegExpData();
@@ -3593,6 +3596,28 @@ void tst_QTextDocument::clearUndoRedoStacks()
QVERIFY(!doc.isUndoAvailable());
}
+class UrlResourceProvider : public QUrlResourceProvider
+{
+public:
+ QVariant resource(const QUrl &url) override
+ {
+ resourseUrl = url;
+ return QVariant();
+ }
+
+ QUrl resourseUrl;
+};
+
+void tst_QTextDocument::resourceProvider()
+{
+ QTextDocument doc;
+ UrlResourceProvider resourceProvider;
+ doc.setResourceProvider(&resourceProvider);
+ QUrl url("test://img");
+ doc.setHtml(QStringLiteral("<img src='%1'/>").arg(url.toString()));
+ doc.resource(QTextDocument::UserResource, url);
+ QCOMPARE(url, resourceProvider.resourseUrl);
+}
QTEST_MAIN(tst_QTextDocument)
#include "tst_qtextdocument.moc"
diff --git a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp
index ea72c91b0a..5eed823a34 100644
--- a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp
+++ b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp
@@ -40,6 +40,7 @@
#include <qmessagebox.h>
#include <qfontmetrics.h>
#include <qmath.h>
+#include <qurlresourceprovider.h>
#include <private/qlabel_p.h>
class Widget : public QWidget
@@ -103,6 +104,8 @@ private Q_SLOTS:
void taskQTBUG_48157_dprPixmap();
void taskQTBUG_48157_dprMovie();
+ void resourceProvider();
+
private:
QLabel *testWidget;
QPointer<Widget> test_box;
@@ -596,5 +599,28 @@ void tst_QLabel::taskQTBUG_48157_dprMovie()
QCOMPARE(label.sizeHint(), movie.currentPixmap().size() / movie.currentPixmap().devicePixelRatio());
}
+class UrlResourceProvider : public QUrlResourceProvider
+{
+public:
+ QVariant resource(const QUrl &url) override
+ {
+ resourseUrl = url;
+ return QVariant();
+ }
+
+ QUrl resourseUrl;
+};
+
+void tst_QLabel::resourceProvider()
+{
+ QLabel label;
+ UrlResourceProvider resourceProvider;
+ label.setResourceProvider(&resourceProvider);
+ QUrl url("test://img");
+ label.setText(QStringLiteral("<img src='%1'/>").arg(url.toString()));
+ label.show();
+ QCOMPARE(url, resourceProvider.resourseUrl);
+}
+
QTEST_MAIN(tst_QLabel)
#include "tst_qlabel.moc"