diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2020-01-31 14:32:24 +0100 |
---|---|---|
committer | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2020-02-03 14:58:06 +0100 |
commit | 2d265dce58d26047f196d79eabfe41edab45c799 (patch) | |
tree | adc89bf20f21399a2e0709c24382deea0d0c9778 /src/gui/text | |
parent | c29fac453f3eaac73b29eb0a66d130220d073fc6 (diff) |
Markdown importer: properly set hyperlinks
The "title" in markdown is the tooltip, not the name attribute of
a link. Also, tell the char format that it's an anchor.
Change-Id: I2978848ec6705fe16376d6fe17f31007cce4b801
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/gui/text')
-rw-r--r-- | src/gui/text/qtextmarkdownimporter.cpp | 4 | ||||
-rw-r--r-- | src/gui/text/qtextmarkdownwriter.cpp | 76 |
2 files changed, 78 insertions, 2 deletions
diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp index b6a275f59c..7e18a10895 100644 --- a/src/gui/text/qtextmarkdownimporter.cpp +++ b/src/gui/text/qtextmarkdownimporter.cpp @@ -399,8 +399,10 @@ int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det) MD_SPAN_A_DETAIL *detail = static_cast<MD_SPAN_A_DETAIL *>(det); QString url = QString::fromUtf8(detail->href.text, int(detail->href.size)); QString title = QString::fromUtf8(detail->title.text, int(detail->title.size)); + charFmt.setAnchor(true); charFmt.setAnchorHref(url); - charFmt.setAnchorNames(QStringList(title)); + if (!title.isEmpty()) + charFmt.setToolTip(title); charFmt.setForeground(m_palette.link()); qCDebug(lcMD) << "anchor" << url << title; } break; diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp index c9a63920c3..7bd321becc 100644 --- a/src/gui/text/qtextmarkdownwriter.cpp +++ b/src/gui/text/qtextmarkdownwriter.cpp @@ -56,10 +56,13 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcMDW, "qt.text.markdown.writer") static const QChar Space = QLatin1Char(' '); +static const QChar Tab = QLatin1Char('\t'); static const QChar Newline = QLatin1Char('\n'); +static const QChar CarriageReturn = QLatin1Char('\r'); static const QChar LineBreak = QChar(0x2028); static const QChar DoubleQuote = QLatin1Char('"'); static const QChar Backtick = QLatin1Char('`'); +static const QChar Backslash = QLatin1Char('\\'); static const QChar Period = QLatin1Char('.'); QTextMarkdownWriter::QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features) @@ -291,6 +294,72 @@ static void maybeEscapeFirstChar(QString &s) } } +struct LineEndPositions { + const QChar *lineEnd; + const QChar *nextLineBegin; +}; + +static LineEndPositions findLineEnd(const QChar *begin, const QChar *end) +{ + LineEndPositions result{ end, end }; + + while (begin < end) { + if (*begin == Newline) { + result.lineEnd = begin; + result.nextLineBegin = begin + 1; + break; + } else if (*begin == CarriageReturn) { + result.lineEnd = begin; + result.nextLineBegin = begin + 1; + if (((begin + 1) < end) && begin[1] == Newline) + ++result.nextLineBegin; + break; + } + + ++begin; + } + + return result; +} + +static bool isBlankLine(const QChar *begin, const QChar *end) +{ + while (begin < end) { + if (*begin != Space && *begin != Tab) + return false; + ++begin; + } + return true; +} + +static QString createLinkTitle(const QString &title) +{ + QString result; + result.reserve(title.size() + 2); + result += DoubleQuote; + + const QChar *data = title.data(); + const QChar *end = data + title.size(); + + while (data < end) { + const auto lineEndPositions = findLineEnd(data, end); + + if (!isBlankLine(data, lineEndPositions.lineEnd)) { + while (data < lineEndPositions.nextLineBegin) { + if (*data == DoubleQuote) + result += Backslash; + result += *data; + ++data; + } + } + + data = lineEndPositions.nextLineBegin; + } + + result += DoubleQuote; + return result; +} + int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat, bool ignoreEmpty) { if (block.text().isEmpty() && ignoreEmpty) @@ -445,7 +514,12 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign col += s.length(); } else if (fmt.hasProperty(QTextFormat::AnchorHref)) { QString s = QLatin1Char('[') + fragmentText + QLatin1String("](") + - fmt.property(QTextFormat::AnchorHref).toString() + QLatin1Char(')'); + fmt.property(QTextFormat::AnchorHref).toString(); + if (fmt.hasProperty(QTextFormat::TextToolTip)) { + s += Space; + s += createLinkTitle(fmt.property(QTextFormat::TextToolTip).toString()); + } + s += QLatin1Char(')'); if (wrap && col + s.length() > ColumnLimit) { m_stream << Newline << wrapIndentString; col = m_wrappedLineIndent; |