Highlight keywords in the StructWidget
This commit is contained in:
parent
d869248e91
commit
f62a75953a
|
@ -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());
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -37,6 +37,7 @@ private:
|
|||
|
||||
void setupColumns();
|
||||
void setupContextMenu();
|
||||
QString highlightTypeName(QString name) const;
|
||||
|
||||
private slots:
|
||||
void on_treeWidget_customContextMenuRequested(const QPoint & pos);
|
||||
|
|
|
@ -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 \
|
||||
|
|
Loading…
Reference in New Issue