1
0
Fork 0

Highlight keywords in the StructWidget

This commit is contained in:
Duncan Ogilvie 2022-06-19 21:07:01 +02:00
parent d869248e91
commit f62a75953a
5 changed files with 187 additions and 1 deletions

View File

@ -0,0 +1,101 @@
#include "RichTextItemDelegate.h"
#include <QTextDocument>
#include <QPainter>
#include <QAbstractTextDocumentLayout>
#include <QApplication>
RichTextItemDelegate::RichTextItemDelegate(QObject* parent)
: QStyledItemDelegate(parent)
{
}
void RichTextItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem & inOption, const QModelIndex & index) const
{
QStyleOptionViewItem option = inOption;
initStyleOption(&option, index);
if(option.text.isEmpty())
{
// This is nothing this function is supposed to handle
QStyledItemDelegate::paint(painter, inOption, index);
return;
}
QStyle* style = option.widget ? option.widget->style() : QApplication::style();
QTextOption textOption;
textOption.setWrapMode(option.features & QStyleOptionViewItem::WrapText ? QTextOption::WordWrap
: QTextOption::ManualWrap);
textOption.setTextDirection(option.direction);
QTextDocument doc;
doc.setDefaultTextOption(textOption);
doc.setHtml(option.text);
doc.setDefaultFont(option.font);
doc.setDocumentMargin(0);
doc.setTextWidth(option.rect.width());
doc.adjustSize();
if(doc.size().width() > option.rect.width())
{
// Elide text
QTextCursor cursor(&doc);
cursor.movePosition(QTextCursor::End);
const QString elidedPostfix = "...";
QFontMetrics metric(option.font);
#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
int postfixWidth = metric.horizontalAdvance(elidedPostfix);
#else
int postfixWidth = metric.width(elidedPostfix);
#endif
while(doc.size().width() > option.rect.width() - postfixWidth)
{
cursor.deletePreviousChar();
doc.adjustSize();
}
cursor.insertText(elidedPostfix);
}
// Painting item without text (this takes care of painting e.g. the highlighted for selected
// or hovered over items in an ItemView)
option.text = QString();
style->drawControl(QStyle::CE_ItemViewItem, &option, painter, inOption.widget);
// Figure out where to render the text in order to follow the requested alignment
QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &option);
QSize documentSize(doc.size().width(), doc.size().height()); // Convert QSizeF to QSize
QRect layoutRect = QStyle::alignedRect(Qt::LayoutDirectionAuto, option.displayAlignment, documentSize, textRect);
painter->save();
// Translate the painter to the origin of the layout rectangle in order for the text to be
// rendered at the correct position
painter->translate(layoutRect.topLeft());
doc.drawContents(painter, textRect.translated(-textRect.topLeft()));
painter->restore();
}
QSize RichTextItemDelegate::sizeHint(const QStyleOptionViewItem & inOption, const QModelIndex & index) const
{
QStyleOptionViewItem option = inOption;
initStyleOption(&option, index);
if(option.text.isEmpty())
{
// This is nothing this function is supposed to handle
return QStyledItemDelegate::sizeHint(inOption, index);
}
QTextDocument doc;
doc.setHtml(option.text);
doc.setTextWidth(option.rect.width());
doc.setDefaultFont(option.font);
doc.setDocumentMargin(0);
return QSize(doc.idealWidth(), doc.size().height());
}

View File

@ -0,0 +1,17 @@
#pragma once
#include <QStyledItemDelegate>
// Based on: https://stackoverflow.com/a/66412883/1806760
class RichTextItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit RichTextItemDelegate(QObject* parent = nullptr);
protected:
void paint(QPainter* painter, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const override;
};

View File

@ -7,6 +7,7 @@
#include <QFileDialog>
#include "StringUtil.h"
#include "MiscUtil.h"
#include "RichTextItemDelegate.h"
struct TypeDescriptor
{
@ -21,6 +22,7 @@ StructWidget::StructWidget(QWidget* parent) :
{
ui->setupUi(this);
ui->treeWidget->setStyleSheet("QTreeWidget { color: #000000; background-color: #FFF8F0; alternate-background-color: #DCD9CF; }");
ui->treeWidget->setItemDelegate(new RichTextItemDelegate(ui->treeWidget));
connect(Bridge::getBridge(), SIGNAL(typeAddNode(void*, const TYPEDESCRIPTOR*)), this, SLOT(typeAddNode(void*, const TYPEDESCRIPTOR*)));
connect(Bridge::getBridge(), SIGNAL(typeClear()), this, SLOT(typeClear()));
connect(Bridge::getBridge(), SIGNAL(typeUpdateWidget()), this, SLOT(typeUpdateWidget()));
@ -65,7 +67,7 @@ void StructWidget::typeAddNode(void* parent, const TYPEDESCRIPTOR* type)
{
TypeDescriptor dtype;
dtype.type = *type;
dtype.name = QString(dtype.type.name);
dtype.name = highlightTypeName(dtype.type.name);
dtype.type.name = nullptr;
auto text = QStringList() << dtype.name << ToPtrString(dtype.type.addr + dtype.type.offset) << "0x" + ToHexString(dtype.type.size);
QTreeWidgetItem* item = parent ? new QTreeWidgetItem((QTreeWidgetItem*)parent, text) : new QTreeWidgetItem(ui->treeWidget, text);
@ -166,6 +168,69 @@ void StructWidget::setupContextMenu()
mMenuBuilder->loadFromConfig();
}
QString StructWidget::highlightTypeName(QString name) const
{
// TODO: this can be improved with colors
static auto re = []
{
const char* keywords[] =
{
"uint64_t",
"uint32_t",
"uint16_t",
"char16_t",
"unsigned",
"int64_t",
"int32_t",
"wchar_t",
"int16_t",
"uint8_t",
"struct",
"double",
"size_t",
"uint64",
"uint32",
"ushort",
"uint16",
"signed",
"int8_t",
"union",
"const",
"float",
"duint",
"dsint",
"int64",
"int32",
"short",
"int16",
"ubyte",
"uchar",
"uint8",
"void",
"long",
"bool",
"byte",
"char",
"int8",
"ptr",
"int",
};
QString keywordRegex;
keywordRegex += "\\b(";
for(size_t i = 0; i < _countof(keywords); i++)
{
if(i > 0)
keywordRegex += '|';
keywordRegex += QRegExp::escape(keywords[i]);
}
keywordRegex += ")\\b";
return QRegExp(keywordRegex, Qt::CaseSensitive);
}();
name.replace(re, "<b>\\1</b>");
return std::move(name);
}
void StructWidget::on_treeWidget_customContextMenuRequested(const QPoint & pos)
{
QMenu wMenu;

View File

@ -37,6 +37,7 @@ private:
void setupColumns();
void setupContextMenu();
QString highlightTypeName(QString name) const;
private slots:
void on_treeWidget_customContextMenuRequested(const QPoint & pos);

View File

@ -77,6 +77,7 @@ SOURCES += \
Src/BasicView/StdIconSearchListView.cpp \
Src/BasicView/StdIconTable.cpp \
Src/Gui/CPURegistersView.cpp \
Src/Gui/RichTextItemDelegate.cpp \
Src/Gui/SystemBreakpointScriptDialog.cpp \
Src/Imports.cpp \
Src/Tracer/TraceInfoBox.cpp \
@ -199,6 +200,7 @@ HEADERS += \
Src/BasicView/StdIconSearchListView.h \
Src/BasicView/StdIconTable.h \
Src/Gui/CPURegistersView.h \
Src/Gui/RichTextItemDelegate.h \
Src/Gui/SystemBreakpointScriptDialog.h \
Src/Tracer/TraceInfoBox.h \
Src/Tracer/TraceRegisters.h \