Introduce QTextDocument::baseUrl

Required for QQuickText & friends to implement image resource handling
in a clean way - to get rid of QQuickTextDocumentWithImageResources and
eventually make QQuickTextEdit's document interchangeable.

Change-Id: I97314a6c3e2d5726539d5722795a472631388cb0
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
This commit is contained in:
J-P Nurmi 2013-09-01 23:34:20 +02:00 committed by The Qt Project
parent 2ced0cb08d
commit 1f22c1d981
4 changed files with 115 additions and 24 deletions

View File

@ -550,6 +550,39 @@ void QTextDocument::setDefaultTextOption(const QTextOption &option)
d->lout->documentChanged(0, 0, d->length());
}
/*!
\property QTextDocument::baseUrl
\since 5.3
\brief the base URL used to resolve relative resource URLs within the document.
Resource URLs are resolved to be within the same directory as the target of the base
URL meaning any portion of the path after the last '/' will be ignored.
\table
\header \li Base URL \li Relative URL \li Resolved URL
\row \li file:///path/to/content \li images/logo.png \li file:///path/to/images/logo.png
\row \li file:///path/to/content/ \li images/logo.png \li file:///path/to/content/images/logo.png
\row \li file:///path/to/content/index.html \li images/logo.png \li file:///path/to/content/images/logo.png
\row \li file:///path/to/content/images/ \li ../images/logo.png \li file:///path/to/content/images/logo.png
\endtable
*/
QUrl QTextDocument::baseUrl() const
{
Q_D(const QTextDocument);
return d->baseUrl;
}
void QTextDocument::setBaseUrl(const QUrl &url)
{
Q_D(QTextDocument);
if (d->baseUrl != url) {
d->baseUrl = url;
if (d->lout)
d->lout->documentChanged(0, 0, d->length());
emit baseUrlChanged(url);
}
}
/*!
\since 4.8
@ -1849,11 +1882,12 @@ void QTextDocument::print(QPagedPaintDevice *printer) const
QVariant QTextDocument::resource(int type, const QUrl &name) const
{
Q_D(const QTextDocument);
QVariant r = d->resources.value(name);
const QUrl url = d->baseUrl.resolved(name);
QVariant r = d->resources.value(url);
if (!r.isValid()) {
r = d->cachedResources.value(name);
r = d->cachedResources.value(url);
if (!r.isValid())
r = const_cast<QTextDocument *>(this)->loadResource(type, name);
r = const_cast<QTextDocument *>(this)->loadResource(type, url);
}
return r;
}
@ -1924,10 +1958,11 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name)
}
// if resource was not loaded try to load it here
if (!qobject_cast<QTextDocument *>(p) && r.isNull() && name.isRelative()) {
QUrl currentURL = d->url;
if (!qobject_cast<QTextDocument *>(p) && r.isNull()) {
QUrl resourceUrl = name;
if (name.isRelative()) {
QUrl currentURL = d->url;
// For the second case QUrl can merge "#someanchor" with "foo.html"
// correctly to "foo.html#someanchor"
if (!(currentURL.isRelative()
@ -1947,6 +1982,7 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name)
resourceUrl.setScheme(QLatin1String("file"));
}
}
}
QString s = resourceUrl.toLocalFile();
QFile f(s);

View File

@ -47,6 +47,7 @@
#include <QtCore/qrect.h>
#include <QtCore/qvariant.h>
#include <QtGui/qfont.h>
#include <QtCore/qurl.h>
QT_BEGIN_NAMESPACE
@ -63,7 +64,6 @@ class QTextFormat;
class QTextFrame;
class QTextBlock;
class QTextCodec;
class QUrl;
class QVariant;
class QRectF;
class QTextOption;
@ -114,6 +114,7 @@ class Q_GUI_EXPORT QTextDocument : public QObject
Q_PROPERTY(int maximumBlockCount READ maximumBlockCount WRITE setMaximumBlockCount)
Q_PROPERTY(qreal documentMargin READ documentMargin WRITE setDocumentMargin)
QDOC_PROPERTY(QTextOption defaultTextOption READ defaultTextOption WRITE setDefaultTextOption)
Q_PROPERTY(QUrl baseUrl READ baseUrl WRITE setBaseUrl NOTIFY baseUrlChanged)
public:
explicit QTextDocument(QObject *parent = 0);
@ -256,6 +257,9 @@ public:
QTextOption defaultTextOption() const;
void setDefaultTextOption(const QTextOption &option);
QUrl baseUrl() const;
void setBaseUrl(const QUrl &url);
Qt::CursorMoveStyle defaultCursorMoveStyle() const;
void setDefaultCursorMoveStyle(Qt::CursorMoveStyle style);
@ -268,7 +272,7 @@ Q_SIGNALS:
void modificationChanged(bool m);
void cursorPositionChanged(const QTextCursor &cursor);
void blockCountChanged(int newBlockCount);
void baseUrlChanged(const QUrl &url);
void documentLayoutChanged();
public Q_SLOTS:

View File

@ -355,6 +355,7 @@ public:
QString url;
qreal indentWidth;
qreal documentMargin;
QUrl baseUrl;
void mergeCachedResources(const QTextDocumentPrivate *priv);

View File

@ -189,6 +189,9 @@ private slots:
void QTBUG27354_spaceAndSoftSpace();
void cssInheritance();
void baseUrl_data();
void baseUrl();
void QTBUG28998_linkColor();
private:
@ -2978,6 +2981,53 @@ void tst_QTextDocument::cssInheritance()
}
}
class BaseDocument : public QTextDocument
{
public:
QUrl loadedResource() const { return resourceUrl; }
QVariant loadResource(int type, const QUrl &name)
{
resourceUrl = name;
return QTextDocument::loadResource(type, name);
}
private:
QUrl resourceUrl;
};
void tst_QTextDocument::baseUrl_data()
{
QTest::addColumn<QUrl>("base");
QTest::addColumn<QUrl>("resource");
QTest::addColumn<QUrl>("loaded");
QTest::newRow("1") << QUrl() << QUrl("images/logo.png") << QUrl("images/logo.png");
QTest::newRow("2") << QUrl("file:///path/to/content") << QUrl("images/logo.png") << QUrl("file:///path/to/images/logo.png");
QTest::newRow("3") << QUrl("file:///path/to/content/") << QUrl("images/logo.png") << QUrl("file:///path/to/content/images/logo.png");
QTest::newRow("4") << QUrl("file:///path/to/content/images") << QUrl("images/logo.png") << QUrl("file:///path/to/content/images/logo.png");
QTest::newRow("5") << QUrl("file:///path/to/content/images/") << QUrl("images/logo.png") << QUrl("file:///path/to/content/images/images/logo.png");
QTest::newRow("6") << QUrl("file:///path/to/content/images") << QUrl("../images/logo.png") << QUrl("file:///path/to/images/logo.png");
QTest::newRow("7") << QUrl("file:///path/to/content/images/") << QUrl("../images/logo.png") << QUrl("file:///path/to/content/images/logo.png");
QTest::newRow("8") << QUrl("file:///path/to/content/index.html") << QUrl("images/logo.png") << QUrl("file:///path/to/content/images/logo.png");
}
void tst_QTextDocument::baseUrl()
{
QFETCH(QUrl, base);
QFETCH(QUrl, resource);
QFETCH(QUrl, loaded);
BaseDocument document;
QVERIFY(!document.baseUrl().isValid());
document.setBaseUrl(base);
QCOMPARE(document.baseUrl(), base);
document.setHtml(QString("<img src='%1'/>").arg(resource.toString()));
document.resource(QTextDocument::ImageResource, resource);
QCOMPARE(document.loadedResource(), loaded);
}
void tst_QTextDocument::QTBUG28998_linkColor()
{
QPalette pal;