1
0
Fork 0

Support HTML in the status bar log label

This commit is contained in:
Duncan Ogilvie 2022-09-02 14:11:40 +02:00
parent 0db522082e
commit 1bef2b9a8f
4 changed files with 69 additions and 38 deletions

View File

@ -1,23 +1,35 @@
#include "LogStatusLabel.h"
#include "LogView.h"
#include <QTextDocument>
#include <QApplication>
#include <QStatusBar>
LogStatusLabel::LogStatusLabel(QStatusBar* parent) : QLabel(parent)
{
this->setTextFormat(Qt::PlainText);
this->setTextFormat(Qt::RichText);
this->setOpenExternalLinks(false);
this->setTextInteractionFlags(Qt::LinksAccessibleByMouse);
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
connect(Bridge::getBridge(), SIGNAL(addMsgToLog(QByteArray)), this, SLOT(logUpdateUtf8(QByteArray)));
connect(Bridge::getBridge(), SIGNAL(addMsgToLogHtml(QByteArray)), this, SLOT(logUpdateUtf8Html(QByteArray)));
connect(Bridge::getBridge(), SIGNAL(addMsgToStatusBar(QString)), this, SLOT(logUpdate(QString)));
connect(Bridge::getBridge(), SIGNAL(getActiveView(ACTIVEVIEW*)), this, SLOT(getActiveView(ACTIVEVIEW*)));
connect(QApplication::instance(), SIGNAL(focusChanged(QWidget*, QWidget*)), this, SLOT(focusChanged(QWidget*, QWidget*)));
connect(this, SIGNAL(linkActivated(QString)), this, SLOT(linkActivatedSlot(QString)));
}
void LogStatusLabel::logUpdate(QString message)
void LogStatusLabel::logUpdate(QString message, bool encodeHTML)
{
//TODO: This subroutine can be optimized
if(!message.length())
return;
// See LogView::addMsgToLogSlotRaw for details on the logic
if(encodeHTML)
{
message = message.toHtmlEscaped();
message.replace(QChar(' '), QString("&nbsp;"));
LogView::linkify(message);
}
labelText += message.replace("\r\n", "\n");
QStringList lineList = labelText.split('\n');
labelText = lineList.last(); //if the last character is a newline this will be an empty string
@ -38,6 +50,11 @@ void LogStatusLabel::logUpdateUtf8(QByteArray message)
logUpdate(QString::fromUtf8(message));
}
void LogStatusLabel::logUpdateUtf8Html(QByteArray message)
{
logUpdate(QString::fromUtf8(message), false);
}
void LogStatusLabel::focusChanged(QWidget* old, QWidget* now)
{
if(old && now && QString(now->metaObject()->className()) == QString("CPUWidget"))
@ -90,3 +107,8 @@ void LogStatusLabel::showMessage(const QString & message)
setText(statusTip);
}
}
void LogStatusLabel::linkActivatedSlot(const QString & link)
{
LogView::handleLink(this, QUrl(link));
}

View File

@ -12,12 +12,14 @@ public:
explicit LogStatusLabel(QStatusBar* parent = 0);
public slots:
void logUpdate(QString message);
void logUpdate(QString message, bool encodeHTML = true);
void logUpdateUtf8(QByteArray message);
void logUpdateUtf8Html(QByteArray message);
void focusChanged(QWidget* old, QWidget* now);
void getActiveView(ACTIVEVIEW* active);
// show status tip
void showMessage(const QString & message);
void linkActivatedSlot(const QString & link);
private:
QString finalLabel;

View File

@ -170,6 +170,44 @@ void LogView::hideEvent(QHideEvent* event)
QTextBrowser::hideEvent(event);
}
void LogView::handleLink(QWidget* parent, const QUrl & link)
{
if(link.scheme() == "x64dbg")
{
// x64dbg:path#fragment
auto path = link.path();
auto fragment = link.fragment(QUrl::FullyDecoded);
if(path == "address" || path == "/address32" || path == "/address64")
{
if(DbgIsDebugging())
{
bool ok = false;
auto address = duint(fragment.toULongLong(&ok, 16));
if(ok && DbgMemIsValidReadPtr(address))
{
if(DbgFunctions()->MemIsCodePage(address, true))
DbgCmdExec(QString("disasm %1").arg(link.fragment()));
else
{
DbgCmdExecDirect(QString("dump %1").arg(link.fragment()));
emit Bridge::getBridge()->getDumpAttention();
}
}
else
SimpleErrorBox(parent, tr("Invalid address!"), tr("The address %1 is not a valid memory location...").arg(ToPtrString(address)));
}
}
else if(path == "command")
{
DbgCmdExec(fragment.toUtf8().constData());
}
else
SimpleErrorBox(parent, tr("Url is not valid!"), tr("The Url %1 is not supported").arg(link.toString()));
}
else
QDesktopServices::openUrl(link); // external Url
}
/**
* @brief linkify Add hyperlink HTML to the message where applicable.
* @param msg The message passed by reference.
@ -182,7 +220,7 @@ static QRegularExpression addressRegExp("([0-9A-Fa-f]{16})");
#else //x86
static QRegularExpression addressRegExp("([0-9A-Fa-f]{8})");
#endif //_WIN64
static void linkify(QString & msg)
void LogView::linkify(QString & msg)
{
#ifdef _WIN64
msg.replace(addressRegExp, "<a href=\"x64dbg://localhost/address64#\\1\">\\1</a>");
@ -329,40 +367,7 @@ void LogView::addMsgToLogSlotRaw(QByteArray msg, bool encodeHTML)
*/
void LogView::onAnchorClicked(const QUrl & link)
{
if(link.scheme() == "x64dbg")
{
// x64dbg:path#fragment
auto path = link.path();
auto fragment = link.fragment(QUrl::FullyDecoded);
if(path == "address" || path == "/address32" || path == "/address64")
{
if(DbgIsDebugging())
{
bool ok = false;
auto address = duint(fragment.toULongLong(&ok, 16));
if(ok && DbgMemIsValidReadPtr(address))
{
if(DbgFunctions()->MemIsCodePage(address, true))
DbgCmdExec(QString("disasm %1").arg(link.fragment()));
else
{
DbgCmdExecDirect(QString("dump %1").arg(link.fragment()));
emit Bridge::getBridge()->getDumpAttention();
}
}
else
SimpleErrorBox(this, tr("Invalid address!"), tr("The address %1 is not a valid memory location...").arg(ToPtrString(address)));
}
}
else if(path == "command")
{
DbgCmdExec(fragment.toUtf8().constData());
}
else
SimpleErrorBox(this, tr("Url is not valid!"), tr("The Url %1 is not supported").arg(link.toString()));
}
else
QDesktopServices::openUrl(link); // external Url
handleLink(this, link);
}
void LogView::clearLogSlot()

View File

@ -14,6 +14,8 @@ public:
void contextMenuEvent(QContextMenuEvent* event) override;
void showEvent(QShowEvent* event) override;
void hideEvent(QHideEvent* event) override;
static void handleLink(QWidget* parent, const QUrl & link);
static void linkify(QString & msg);
public slots:
void refreshShortcutsSlot();