Fix bugs with the context link text for localdocs to make the context links

persistently work across application loads and fix scrolling bug with context
links.

Signed-off-by: Adam Treat <treat.adam@gmail.com>
This commit is contained in:
Adam Treat 2023-12-21 13:59:33 -05:00 committed by AT
parent ac498f79ac
commit e27653219b
2 changed files with 64 additions and 9 deletions

View File

@ -7,6 +7,7 @@
#include <QTextTableCell> #include <QTextTableCell>
#include <QGuiApplication> #include <QGuiApplication>
#include <QClipboard> #include <QClipboard>
#include <QPainter>
enum Language { enum Language {
None, None,
@ -845,11 +846,36 @@ void SyntaxHighlighter::highlightBlock(const QString &text)
} }
} }
const int ContextLinkFormat = QTextFormat::UserObject + 1;
const int ContextLinkHref = QTextFormat::UserProperty + 1;
const int ContextLinkText = QTextFormat::UserProperty + 2;
void ContextLinkInterface::drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc,
int posInDocument, const QTextFormat &format)
{
const QString &href = format.property(ContextLinkHref).toString();
const QString &text = format.property(ContextLinkText).toString();
painter->setFont(doc->defaultFont());
painter->setPen(format.foreground().color());
painter->drawText(rect.bottomLeft(), text);
}
QSizeF ContextLinkInterface::intrinsicSize(QTextDocument *doc, int posInDocument,
const QTextFormat &format)
{
const QString &href = format.property(ContextLinkHref).toString();
const QString &text = format.property(ContextLinkText).toString();
const QFontMetricsF metrics(doc->defaultFont());
const QSizeF textSize = metrics.size(Qt::TextSingleLine, text);
return textSize;
}
ResponseText::ResponseText(QObject *parent) ResponseText::ResponseText(QObject *parent)
: QObject{parent} : QObject{parent}
, m_textDocument(nullptr) , m_textDocument(nullptr)
, m_syntaxHighlighter(new SyntaxHighlighter(this)) , m_syntaxHighlighter(new SyntaxHighlighter(this))
, m_isProcessingText(false) , m_isProcessingText(false)
, m_contextLink(new ContextLinkInterface(this))
{ {
} }
@ -864,6 +890,7 @@ void ResponseText::setTextDocument(QQuickTextDocument* textDocument)
disconnect(m_textDocument->textDocument(), &QTextDocument::contentsChanged, this, &ResponseText::handleTextChanged); disconnect(m_textDocument->textDocument(), &QTextDocument::contentsChanged, this, &ResponseText::handleTextChanged);
m_textDocument = textDocument; m_textDocument = textDocument;
m_textDocument->textDocument()->documentLayout()->registerHandler(ContextLinkFormat, m_contextLink);
m_syntaxHighlighter->setDocument(m_textDocument->textDocument()); m_syntaxHighlighter->setDocument(m_textDocument->textDocument());
connect(m_textDocument->textDocument(), &QTextDocument::contentsChanged, this, &ResponseText::handleTextChanged); connect(m_textDocument->textDocument(), &QTextDocument::contentsChanged, this, &ResponseText::handleTextChanged);
handleTextChanged(); handleTextChanged();
@ -871,10 +898,20 @@ void ResponseText::setTextDocument(QQuickTextDocument* textDocument)
QString ResponseText::getLinkAtPosition(int position) const QString ResponseText::getLinkAtPosition(int position) const
{ {
int i = 0; QTextCursor cursor(m_textDocument->textDocument());
for (const auto &link : m_links) { cursor.setPosition(position);
if (position >= link.startPos && position < link.endPos) QTextCharFormat format = cursor.charFormat();
return link.href; if (format.objectType() == ContextLinkFormat) {
QString href = format.property(ContextLinkHref).toString();
if (!href.isEmpty())
return href;
}
cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor);
format = cursor.charFormat();
if (format.objectType() == ContextLinkFormat) {
QString href = format.property(ContextLinkHref).toString();
if (!href.isEmpty())
return href;
} }
return QString(); return QString();
} }
@ -912,9 +949,6 @@ void ResponseText::handleContextLinks()
{ {
QTextDocument* doc = m_textDocument->textDocument(); QTextDocument* doc = m_textDocument->textDocument();
QTextCursor cursor(doc); QTextCursor cursor(doc);
QTextCharFormat linkFormat;
linkFormat.setForeground(m_linkColor);
linkFormat.setFontUnderline(true);
// Regex for context links // Regex for context links
static const QRegularExpression reLink("\\[Context\\]\\((context://\\d+)\\)"); static const QRegularExpression reLink("\\[Context\\]\\((context://\\d+)\\)");
@ -943,8 +977,13 @@ void ResponseText::handleContextLinks()
cursor.setPosition(matchesLink.at(index).capturedStart()); cursor.setPosition(matchesLink.at(index).capturedStart());
cursor.setPosition(matchesLink.at(index).capturedEnd(), QTextCursor::KeepAnchor); cursor.setPosition(matchesLink.at(index).capturedEnd(), QTextCursor::KeepAnchor);
cursor.removeSelectedText(); cursor.removeSelectedText();
cursor.setCharFormat(linkFormat); QTextCharFormat objectFormat;
cursor.insertText(newLinks.at(index).text); objectFormat.setForeground(m_linkColor);
objectFormat.setFontUnderline(true);
objectFormat.setProperty(ContextLinkHref, newLinks.at(index).href);
objectFormat.setProperty(ContextLinkText, newLinks.at(index).text);
objectFormat.setObjectType(ContextLinkFormat);
cursor.insertText(QString(QChar::ObjectReplacementCharacter), objectFormat);
cursor.setCharFormat(QTextCharFormat()); cursor.setCharFormat(QTextCharFormat());
} }

View File

@ -6,6 +6,7 @@
#include <QQuickTextDocument> #include <QQuickTextDocument>
#include <QSyntaxHighlighter> #include <QSyntaxHighlighter>
#include <QRegularExpression> #include <QRegularExpression>
#include <QTextObjectInterface>
class SyntaxHighlighter : public QSyntaxHighlighter { class SyntaxHighlighter : public QSyntaxHighlighter {
Q_OBJECT Q_OBJECT
@ -28,6 +29,20 @@ struct CodeCopy {
QString text; QString text;
}; };
class ContextLinkInterface : public QObject, public QTextObjectInterface
{
Q_OBJECT
Q_INTERFACES(QTextObjectInterface)
public:
explicit ContextLinkInterface(QObject *parent) : QObject(parent) {}
void drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc, int posInDocument,
const QTextFormat &format) override;
QSizeF intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format) override;
};
class ResponseText : public QObject class ResponseText : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -61,6 +76,7 @@ private:
QColor m_linkColor; QColor m_linkColor;
QColor m_headerColor; QColor m_headerColor;
bool m_isProcessingText = false; bool m_isProcessingText = false;
ContextLinkInterface *m_contextLink;
}; };
#endif // RESPONSETEXT_H #endif // RESPONSETEXT_H