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>
This commit is contained in:
parent
9e09677c1d
commit
376e3bd8ec
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
@ -2118,6 +2127,30 @@ void QTextDocument::addResource(int type, const QUrl &name, const QVariant &reso
|
||||
d->resources.insert(name, resource);
|
||||
}
|
||||
|
||||
/*!
|
||||
\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.
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -366,6 +366,7 @@ private:
|
||||
QMap<int, QTextObject *> objects;
|
||||
QMap<QUrl, QVariant> resources;
|
||||
QMap<QUrl, QVariant> cachedResources;
|
||||
QUrlResourceProvider *resourceProvider;
|
||||
QString defaultStyleSheet;
|
||||
|
||||
int lastBlockCount;
|
||||
|
88
src/gui/text/qurlresourceprovider.cpp
Normal file
88
src/gui/text/qurlresourceprovider.cpp
Normal file
@ -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
|
61
src/gui/text/qurlresourceprovider.h
Normal file
61
src/gui/text/qurlresourceprovider.h
Normal file
@ -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
|
@ -100,7 +100,8 @@ QLabelPrivate::QLabelPrivate()
|
||||
validCursor(false),
|
||||
onAnchor(false),
|
||||
#endif
|
||||
openExternalLinks(false)
|
||||
openExternalLinks(false),
|
||||
resourceProvider(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1423,6 +1424,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
|
||||
*/
|
||||
@ -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());
|
||||
|
@ -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);
|
||||
|
||||
|
@ -154,6 +154,7 @@ public:
|
||||
#endif
|
||||
uint openExternalLinks : 1;
|
||||
// <-- space for more bit field values here
|
||||
QUrlResourceProvider *resourceProvider;
|
||||
|
||||
friend class QMessageBoxPrivate;
|
||||
};
|
||||
|
@ -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());
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user