diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index edb6bd93107..2fadc40cd22 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -225,6 +225,7 @@ public: void print(QPagedPaintDevice *printer) const; enum ResourceType { + UnknownResource = 0, HtmlResource = 1, ImageResource = 2, StyleSheetResource = 3, @@ -232,6 +233,7 @@ public: UserResource = 100 }; + Q_ENUM(ResourceType) QVariant resource(int type, const QUrl &name) const; void addResource(int type, const QUrl &name, const QVariant &resource); diff --git a/src/widgets/widgets/qtextbrowser.cpp b/src/widgets/widgets/qtextbrowser.cpp index 8e06efc75ee..bee1021950a 100644 --- a/src/widgets/widgets/qtextbrowser.cpp +++ b/src/widgets/widgets/qtextbrowser.cpp @@ -86,6 +86,7 @@ public: int hpos; int vpos; int focusIndicatorPosition, focusIndicatorAnchor; + QTextDocument::ResourceType type = QTextDocument::UnknownResource; }; HistoryEntry history(int i) const @@ -122,6 +123,8 @@ public: bool openExternalLinks; bool openLinks; + QTextDocument::ResourceType currentType; + #ifndef QT_NO_CURSOR QCursor oldCursor; #endif @@ -137,7 +140,7 @@ public: void _q_activateAnchor(const QString &href); void _q_highlightLink(const QString &href); - void setSource(const QUrl &url); + void setSource(const QUrl &url, QTextDocument::ResourceType type); // re-imlemented from QTextEditPrivate virtual QUrl resolveUrl(const QUrl &url) const override; @@ -274,7 +277,7 @@ void QTextBrowserPrivate::_q_highlightLink(const QString &anchor) } } -void QTextBrowserPrivate::setSource(const QUrl &url) +void QTextBrowserPrivate::setSource(const QUrl &url, QTextDocument::ResourceType type) { Q_Q(QTextBrowser); #ifndef QT_NO_CURSOR @@ -291,14 +294,18 @@ void QTextBrowserPrivate::setSource(const QUrl &url) currentUrlWithoutFragment.setFragment(QString()); QUrl newUrlWithoutFragment = currentURL.resolved(url); newUrlWithoutFragment.setFragment(QString()); - QTextDocument::ResourceType type = QTextDocument::HtmlResource; QString fileName = url.fileName(); + if (type == QTextDocument::UnknownResource) { #if QT_CONFIG(textmarkdownreader) - if (fileName.endsWith(QLatin1String(".md")) || - fileName.endsWith(QLatin1String(".mkd")) || - fileName.endsWith(QLatin1String(".markdown"))) - type = QTextDocument::MarkdownResource; + if (fileName.endsWith(QLatin1String(".md")) || + fileName.endsWith(QLatin1String(".mkd")) || + fileName.endsWith(QLatin1String(".markdown"))) + type = QTextDocument::MarkdownResource; + else #endif + type = QTextDocument::HtmlResource; + } + currentType = type; if (url.isValid() && (newUrlWithoutFragment != currentUrlWithoutFragment || forceLoadOnSourceChange)) { @@ -574,6 +581,7 @@ QTextBrowserPrivate::HistoryEntry QTextBrowserPrivate::createHistoryEntry() cons { HistoryEntry entry; entry.url = q_func()->source(); + entry.type = q_func()->sourceType(); entry.title = q_func()->documentTitle(); entry.hpos = hbar->value(); entry.vpos = vbar->value(); @@ -590,7 +598,7 @@ QTextBrowserPrivate::HistoryEntry QTextBrowserPrivate::createHistoryEntry() cons void QTextBrowserPrivate::restoreHistoryEntry(const HistoryEntry &entry) { - setSource(entry.url); + setSource(entry.url, entry.type); hbar->setValue(entry.hpos); vbar->setValue(entry.vpos); if (entry.focusIndicatorAnchor != -1 && entry.focusIndicatorPosition != -1) { @@ -732,7 +740,13 @@ QTextBrowser::~QTextBrowser() document is displayed as a popup rather than as new document in the browser window itself. Otherwise, the document is displayed normally in the text browser with the text set to the contents of - the named document with setHtml(). + the named document with \l QTextDocument::setHtml() or + \l QTextDocument::setMarkdown(), depending on whether the filename ends + with any of the known Markdown file extensions. + + If you would like to avoid automatic type detection + and specify the type explicitly, call setSource() rather than + setting this property. By default, this property contains an empty URL. */ @@ -745,6 +759,23 @@ QUrl QTextBrowser::source() const return d->stack.top().url; } +/*! + \property QTextBrowser::sourceType + \brief the type of the displayed document + + This is QTextDocument::UnknownResource if no document is displayed or if + the type of the source is unknown. Otherwise it holds the type that was + detected, or the type that was specified when setSource() was called. +*/ +QTextDocument::ResourceType QTextBrowser::sourceType() const +{ + Q_D(const QTextBrowser); + if (d->stack.isEmpty()) + return QTextDocument::UnknownResource; + else + return d->stack.top().type; +} + /*! \property QTextBrowser::searchPaths \brief the search paths used by the text browser to find supporting @@ -775,16 +806,46 @@ void QTextBrowser::reload() Q_D(QTextBrowser); QUrl s = d->currentURL; d->currentURL = QUrl(); - setSource(s); + setSource(s, d->currentType); } +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) void QTextBrowser::setSource(const QUrl &url) +{ + setSource(url, QTextDocument::UnknownResource); +} +#endif + +/*! + Attempts to load the document at the given \a url with the specified \a type. + + If \a type is \l {QTextDocument::ResourceType::UnknownResource}{UnknownResource} + (the default), the document type will be detected: that is, if the url ends + with an extension of \c{.md}, \c{.mkd} or \c{.markdown}, the document will be + loaded via \l QTextDocument::setMarkdown(); otherwise it will be loaded via + \l QTextDocument::setHtml(). This detection can be bypassed by specifying + the \a type explicitly. +*/ +void QTextBrowser::setSource(const QUrl &url, QTextDocument::ResourceType type) +{ + doSetSource(url, type); +} + +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) +/*! + Attempts to load the document at the given \a url with the specified \a type. + + setSource() calls doSetSource. In Qt 5, setSource(const QUrl &url) was virtual. + In Qt 6, doSetSource() is virtual instead, so that it can be overridden in subclasses. +*/ +#endif +void QTextBrowser::doSetSource(const QUrl &url, QTextDocument::ResourceType type) { Q_D(QTextBrowser); const QTextBrowserPrivate::HistoryEntry historyEntry = d->createHistoryEntry(); - d->setSource(url); + d->setSource(url, type); if (!url.isValid()) return; @@ -798,6 +859,7 @@ void QTextBrowser::setSource(const QUrl &url) QTextBrowserPrivate::HistoryEntry entry; entry.url = url; + entry.type = d->currentType; entry.title = documentTitle(); entry.hpos = 0; entry.vpos = 0; diff --git a/src/widgets/widgets/qtextbrowser.h b/src/widgets/widgets/qtextbrowser.h index ea81256f503..33e5b3980c4 100644 --- a/src/widgets/widgets/qtextbrowser.h +++ b/src/widgets/widgets/qtextbrowser.h @@ -55,6 +55,7 @@ class Q_WIDGETS_EXPORT QTextBrowser : public QTextEdit Q_OBJECT Q_PROPERTY(QUrl source READ source WRITE setSource) + Q_PROPERTY(QTextDocument::ResourceType sourceType READ sourceType) Q_OVERRIDE(bool modified SCRIPTABLE false) Q_OVERRIDE(bool readOnly DESIGNABLE false SCRIPTABLE false) Q_OVERRIDE(bool undoRedoEnabled DESIGNABLE false SCRIPTABLE false) @@ -67,6 +68,7 @@ public: virtual ~QTextBrowser(); QUrl source() const; + QTextDocument::ResourceType sourceType() const; QStringList searchPaths() const; void setSearchPaths(const QStringList &paths); @@ -88,7 +90,12 @@ public: void setOpenLinks(bool open); public Q_SLOTS: +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) virtual void setSource(const QUrl &name); + void setSource(const QUrl &name, QTextDocument::ResourceType type); +#else + void setSource(const QUrl &name, QTextDocument::ResourceType type = QTextDocument::UnknownResource); +#endif virtual void backward(); virtual void forward(); virtual void home(); @@ -112,6 +119,10 @@ protected: virtual void focusOutEvent(QFocusEvent *ev) override; virtual bool focusNextPrevChild(bool next) override; virtual void paintEvent(QPaintEvent *e) override; +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) + virtual +#endif + void doSetSource(const QUrl &name, QTextDocument::ResourceType type = QTextDocument::UnknownResource); private: Q_DISABLE_COPY(QTextBrowser) diff --git a/tests/auto/widgets/widgets/qtextbrowser/heading.html b/tests/auto/widgets/widgets/qtextbrowser/heading.html new file mode 100644 index 00000000000..8b23807f650 --- /dev/null +++ b/tests/auto/widgets/widgets/qtextbrowser/heading.html @@ -0,0 +1,2 @@ +
this is a paragraph
diff --git a/tests/auto/widgets/widgets/qtextbrowser/markdown.really b/tests/auto/widgets/widgets/qtextbrowser/markdown.really new file mode 100644 index 00000000000..be56aef234b --- /dev/null +++ b/tests/auto/widgets/widgets/qtextbrowser/markdown.really @@ -0,0 +1,2 @@ +### this is a heading +this is a paragraph diff --git a/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro b/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro index 05c156bf59c..dfdcf264978 100644 --- a/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro +++ b/tests/auto/widgets/widgets/qtextbrowser/qtextbrowser.pro @@ -4,6 +4,6 @@ SOURCES += tst_qtextbrowser.cpp QT += widgets testlib -TESTDATA += *.html *.md subdir/* +TESTDATA += *.html *.md markdown.really subdir/* builtin_testdata: DEFINES += BUILTIN_TESTDATA diff --git a/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp b/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp index 22cd3b46c6f..083e297941b 100644 --- a/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp +++ b/tests/auto/widgets/widgets/qtextbrowser/tst_qtextbrowser.cpp @@ -92,7 +92,8 @@ private slots: void focusIndicator(); void focusHistory(); void urlEncoding(); - void markdown(); + void sourceType_data(); + void sourceType(); private: TestBrowser *browser; @@ -679,19 +680,45 @@ void tst_QTextBrowser::urlEncoding() delete browser; } -void tst_QTextBrowser::markdown() +void tst_QTextBrowser::sourceType_data() { - browser->setSource(QUrl::fromLocalFile(QFINDTESTDATA("markdown.md"))); + QTest::addColumn