2019-12-19 13:51:41 +00:00
|
|
|
#include <QGuiApplication>
|
|
|
|
#include <QPalette>
|
2019-12-11 14:52:12 +00:00
|
|
|
#include <QPainter>
|
2021-01-02 19:01:33 +00:00
|
|
|
#include <QPainterPath>
|
2019-12-11 14:52:12 +00:00
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
#include "DisAsmTableModel.h"
|
2019-12-11 14:52:12 +00:00
|
|
|
#include "string_cast.h"
|
|
|
|
#include "string_format.h"
|
|
|
|
#include "lexical_cast_ex.h"
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
CDisAsmTableModel::CDisAsmTableModel(QTableView* parent, CVirtualMachine& virtualMachine, CMIPS* context, uint64 size, uint32 windowSize, DISASM_TYPE disAsmType)
|
2019-12-11 14:52:12 +00:00
|
|
|
: QAbstractTableModel(parent)
|
2019-12-19 21:37:47 +00:00
|
|
|
, m_virtualMachine(virtualMachine)
|
2019-12-11 14:52:12 +00:00
|
|
|
, m_ctx(context)
|
|
|
|
, m_instructionSize(4)
|
2024-03-20 19:33:37 -04:00
|
|
|
, m_size(size)
|
|
|
|
, m_windowSize(windowSize)
|
2021-01-03 17:41:08 +00:00
|
|
|
, m_disAsmType(disAsmType)
|
2019-12-11 14:52:12 +00:00
|
|
|
{
|
2024-03-20 19:33:37 -04:00
|
|
|
if(windowSize == 0)
|
|
|
|
{
|
|
|
|
assert(size <= UINT32_MAX);
|
|
|
|
m_windowSize = static_cast<uint32>(size);
|
|
|
|
}
|
|
|
|
|
2021-01-03 17:41:08 +00:00
|
|
|
m_headers = {"S", "Address", "R", "Instr", "I-Mn", "I-Op", "Target/Comments"};
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
auto target_comment_column_index = ((m_disAsmType == CDisAsmTableModel::DISASM_STANDARD) ? 3 : 5) + 3;
|
2021-01-03 17:41:08 +00:00
|
|
|
parent->setItemDelegateForColumn(target_comment_column_index, new TableColumnDelegateTargetComment(parent));
|
2019-12-11 14:52:12 +00:00
|
|
|
|
2024-03-20 19:33:37 -04:00
|
|
|
BuildIcons();
|
|
|
|
}
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
void CDisAsmTableModel::BuildIcons()
|
2024-03-20 19:33:37 -04:00
|
|
|
{
|
2019-12-19 13:51:41 +00:00
|
|
|
auto size = m_start_line.size();
|
|
|
|
auto start = 2;
|
|
|
|
auto middle = size.width() / 2;
|
|
|
|
auto end = size.width() - 2;
|
|
|
|
|
|
|
|
QPalette palette = QGuiApplication::palette();
|
2019-12-11 14:52:12 +00:00
|
|
|
QPen pen;
|
2019-12-19 13:51:41 +00:00
|
|
|
pen.setWidth(2);
|
|
|
|
pen.setColor(palette.color(QPalette::WindowText));
|
2019-12-11 14:52:12 +00:00
|
|
|
pen.setCapStyle(Qt::RoundCap);
|
|
|
|
pen.setJoinStyle(Qt::MiterJoin);
|
|
|
|
{
|
2019-12-19 13:51:41 +00:00
|
|
|
m_start_line.fill(Qt::transparent);
|
2019-12-11 14:52:12 +00:00
|
|
|
|
|
|
|
QPainterPath start_path;
|
2019-12-19 13:51:41 +00:00
|
|
|
start_path.moveTo(middle, end);
|
|
|
|
start_path.lineTo(middle, middle);
|
|
|
|
start_path.lineTo(end, middle);
|
2019-12-11 14:52:12 +00:00
|
|
|
|
2019-12-19 13:51:41 +00:00
|
|
|
QPainter painter(&m_start_line);
|
2019-12-11 14:52:12 +00:00
|
|
|
painter.setPen(pen);
|
|
|
|
painter.drawPath(start_path);
|
|
|
|
}
|
|
|
|
{
|
2019-12-19 13:51:41 +00:00
|
|
|
m_end_line.fill(Qt::transparent);
|
2019-12-11 14:52:12 +00:00
|
|
|
|
|
|
|
QPainterPath end_path;
|
2019-12-19 13:51:41 +00:00
|
|
|
end_path.moveTo(middle, start);
|
|
|
|
end_path.lineTo(middle, middle);
|
|
|
|
end_path.lineTo(end, middle);
|
2019-12-11 14:52:12 +00:00
|
|
|
|
2019-12-19 13:51:41 +00:00
|
|
|
QPainter painter(&m_end_line);
|
2019-12-11 14:52:12 +00:00
|
|
|
painter.setPen(pen);
|
|
|
|
painter.drawPath(end_path);
|
|
|
|
}
|
|
|
|
{
|
2019-12-19 13:51:41 +00:00
|
|
|
m_line.fill(Qt::transparent);
|
2019-12-11 14:52:12 +00:00
|
|
|
|
|
|
|
QPainterPath line_path;
|
2019-12-19 13:51:41 +00:00
|
|
|
line_path.moveTo(middle, start);
|
|
|
|
line_path.lineTo(middle, end);
|
2019-12-11 14:52:12 +00:00
|
|
|
|
2019-12-19 13:51:41 +00:00
|
|
|
QPainter painter(&m_line);
|
2019-12-11 14:52:12 +00:00
|
|
|
painter.setPen(pen);
|
|
|
|
painter.drawPath(line_path);
|
|
|
|
}
|
2019-12-19 13:51:41 +00:00
|
|
|
QPainterPath arrow_path;
|
2019-12-11 16:30:43 +00:00
|
|
|
{
|
2019-12-19 13:51:41 +00:00
|
|
|
m_arrow.fill(Qt::transparent);
|
2019-12-11 16:30:43 +00:00
|
|
|
|
2019-12-19 13:51:41 +00:00
|
|
|
arrow_path.moveTo(middle, start);
|
|
|
|
arrow_path.lineTo(end, middle);
|
|
|
|
arrow_path.lineTo(middle, end);
|
2019-12-11 16:30:43 +00:00
|
|
|
|
2019-12-19 13:51:41 +00:00
|
|
|
arrow_path.lineTo(middle, middle + 3);
|
2019-12-11 16:30:43 +00:00
|
|
|
|
2019-12-19 13:51:41 +00:00
|
|
|
arrow_path.lineTo(start, middle + 3);
|
|
|
|
arrow_path.lineTo(start, middle - 3);
|
2019-12-11 16:30:43 +00:00
|
|
|
|
2019-12-19 13:51:41 +00:00
|
|
|
arrow_path.lineTo(middle, middle - 3);
|
2019-12-12 01:18:27 +00:00
|
|
|
|
2019-12-19 13:51:41 +00:00
|
|
|
arrow_path.closeSubpath();
|
2019-12-12 01:18:27 +00:00
|
|
|
|
2019-12-19 13:51:41 +00:00
|
|
|
QPainter painter(&m_arrow);
|
|
|
|
pen.setColor(palette.color(QPalette::WindowText));
|
2019-12-12 01:18:27 +00:00
|
|
|
painter.setPen(pen);
|
2019-12-19 13:51:41 +00:00
|
|
|
painter.setBrush(QBrush(Qt::yellow));
|
|
|
|
painter.drawPath(arrow_path);
|
2019-12-12 01:18:27 +00:00
|
|
|
}
|
2019-12-19 13:51:41 +00:00
|
|
|
{
|
|
|
|
m_breakpoint.fill(Qt::transparent);
|
2019-12-12 01:18:27 +00:00
|
|
|
|
2019-12-19 13:51:41 +00:00
|
|
|
QPainter painter(&m_breakpoint);
|
|
|
|
painter.setBrush(QBrush(Qt::darkRed));
|
|
|
|
painter.setPen(Qt::NoPen);
|
|
|
|
painter.drawEllipse(QPointF(middle, middle), middle - 1, middle - 1);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
m_breakpoint_arrow.fill(Qt::transparent);
|
2019-12-12 01:18:27 +00:00
|
|
|
|
2019-12-19 13:51:41 +00:00
|
|
|
QPainter painter(&m_breakpoint_arrow);
|
|
|
|
painter.setBrush(QBrush(Qt::darkRed));
|
|
|
|
painter.setPen(Qt::NoPen);
|
|
|
|
painter.drawEllipse(QPointF(middle, middle), middle - 1, middle - 1);
|
2019-12-12 01:18:27 +00:00
|
|
|
|
2019-12-19 13:51:41 +00:00
|
|
|
painter.setBrush(QBrush(Qt::yellow));
|
|
|
|
pen.setColor(palette.color(QPalette::WindowText));
|
2019-12-12 01:18:27 +00:00
|
|
|
painter.setPen(pen);
|
2019-12-19 13:51:41 +00:00
|
|
|
painter.drawPath(arrow_path);
|
2019-12-12 01:18:27 +00:00
|
|
|
}
|
2019-12-11 14:52:12 +00:00
|
|
|
}
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
int CDisAsmTableModel::rowCount(const QModelIndex& /*parent*/) const
|
2019-12-11 14:52:12 +00:00
|
|
|
{
|
2024-03-20 19:33:37 -04:00
|
|
|
return m_windowSize / m_instructionSize;
|
2019-12-11 14:52:12 +00:00
|
|
|
}
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
int CDisAsmTableModel::columnCount(const QModelIndex& /*parent*/) const
|
2019-12-11 14:52:12 +00:00
|
|
|
{
|
|
|
|
return m_headers.size();
|
|
|
|
}
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
void CDisAsmTableModel::SetWindowCenter(uint32 windowCenter)
|
2024-03-20 19:33:37 -04:00
|
|
|
{
|
|
|
|
int64 lowerBound = static_cast<int64>(windowCenter) - static_cast<int64>(m_windowSize / 2);
|
|
|
|
int64 upperBound = static_cast<int64>(windowCenter) + static_cast<int64>(m_windowSize / 2);
|
|
|
|
if(lowerBound < 0)
|
|
|
|
{
|
|
|
|
m_windowStart = 0;
|
|
|
|
}
|
|
|
|
else if(upperBound >= m_size)
|
|
|
|
{
|
|
|
|
m_windowStart = static_cast<uint32>(m_size - static_cast<uint64>(m_windowSize));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_windowStart = static_cast<uint32>(lowerBound);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
QVariant CDisAsmTableModel::data(const QModelIndex& index, int role) const
|
2019-12-11 14:52:12 +00:00
|
|
|
{
|
|
|
|
// "S", "Address", "R", "I-Mn", "I-Op", "Name",
|
2021-01-04 18:05:53 +00:00
|
|
|
uint32 address = TranslateModelIndexToAddress(index);
|
2019-12-11 14:52:12 +00:00
|
|
|
if(role == Qt::DisplayRole)
|
|
|
|
{
|
|
|
|
switch(index.column())
|
|
|
|
{
|
2019-12-19 21:37:47 +00:00
|
|
|
case 0: //SYMBOL:
|
|
|
|
return QVariant();
|
2019-12-11 14:52:12 +00:00
|
|
|
break;
|
2019-12-19 21:37:47 +00:00
|
|
|
case 1: //Address:
|
|
|
|
return string_format(("%08X"), address).c_str();
|
2019-12-11 14:52:12 +00:00
|
|
|
break;
|
2019-12-19 21:37:47 +00:00
|
|
|
case 2: //Relation:
|
|
|
|
return QVariant();
|
2019-12-11 14:52:12 +00:00
|
|
|
break;
|
|
|
|
}
|
2019-12-19 22:20:32 +00:00
|
|
|
auto size = (m_disAsmType == DISASM_TYPE::DISASM_STANDARD) ? 3 : 5;
|
|
|
|
auto subindex = index.column() - 3;
|
|
|
|
if(subindex < size)
|
|
|
|
return GetInstructionDetails(subindex, address).c_str();
|
|
|
|
else if(subindex == size)
|
|
|
|
return GetInstructionMetadata(address).c_str();
|
2021-01-03 17:41:08 +00:00
|
|
|
}
|
|
|
|
if(role == Qt::UserRole)
|
|
|
|
{
|
|
|
|
auto size = (m_disAsmType == DISASM_TYPE::DISASM_STANDARD) ? 3 : 5;
|
|
|
|
auto subindex = index.column() - 3;
|
|
|
|
if(subindex == size)
|
2021-01-01 00:17:33 +00:00
|
|
|
return m_ctx->m_Comments.Find(address);
|
2019-12-11 14:52:12 +00:00
|
|
|
}
|
|
|
|
if(role == Qt::DecorationRole)
|
|
|
|
{
|
2019-12-11 16:30:43 +00:00
|
|
|
switch(index.column())
|
2019-12-11 14:52:12 +00:00
|
|
|
{
|
2019-12-19 21:37:47 +00:00
|
|
|
case 0:
|
|
|
|
{
|
2024-03-22 13:16:37 -04:00
|
|
|
uint32 physAddress = m_ctx->m_pAddrTranslator(m_ctx, address);
|
|
|
|
bool isBreakpoint = (m_ctx->m_breakpoints.find(physAddress) != std::end(m_ctx->m_breakpoints));
|
2019-12-19 21:37:47 +00:00
|
|
|
bool isPC = (m_virtualMachine.GetStatus() != CVirtualMachine::RUNNING && address == m_ctx->m_State.nPC);
|
2019-12-12 01:18:27 +00:00
|
|
|
|
2019-12-19 21:37:47 +00:00
|
|
|
//Draw current instruction m_arrow and m_breakpoint icon
|
|
|
|
if(isBreakpoint && isPC)
|
|
|
|
{
|
|
|
|
return m_breakpoint_arrow;
|
|
|
|
}
|
|
|
|
//Draw m_breakpoint icon
|
|
|
|
if(isBreakpoint)
|
|
|
|
{
|
|
|
|
return m_breakpoint;
|
|
|
|
}
|
|
|
|
//Draw current instruction m_arrow
|
|
|
|
if(isPC)
|
|
|
|
{
|
|
|
|
return m_arrow;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
const auto* sub = m_ctx->m_analysis->FindSubroutine(address);
|
|
|
|
if(sub != nullptr)
|
|
|
|
{
|
|
|
|
if(address == sub->start)
|
2019-12-12 01:18:27 +00:00
|
|
|
{
|
2019-12-19 21:37:47 +00:00
|
|
|
return m_start_line;
|
2019-12-12 01:18:27 +00:00
|
|
|
}
|
2019-12-19 21:37:47 +00:00
|
|
|
else if(address == sub->end)
|
2019-12-12 01:18:27 +00:00
|
|
|
{
|
2019-12-19 21:37:47 +00:00
|
|
|
return m_end_line;
|
2019-12-11 14:52:12 +00:00
|
|
|
}
|
2019-12-19 21:37:47 +00:00
|
|
|
else
|
2019-12-11 14:52:12 +00:00
|
|
|
{
|
2019-12-19 21:37:47 +00:00
|
|
|
return m_line;
|
2019-12-11 14:52:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-12-19 21:37:47 +00:00
|
|
|
}
|
2019-12-11 14:52:12 +00:00
|
|
|
}
|
2021-01-07 22:23:08 +00:00
|
|
|
if(role == Qt::BackgroundRole)
|
|
|
|
{
|
2024-03-20 19:33:37 -04:00
|
|
|
QColor background = QColor(QPalette().base().color());
|
2021-01-07 22:23:08 +00:00
|
|
|
QBrush brush(background);
|
|
|
|
return brush;
|
|
|
|
}
|
2019-12-11 14:52:12 +00:00
|
|
|
return QVariant();
|
|
|
|
}
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
QVariant CDisAsmTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
2019-12-11 14:52:12 +00:00
|
|
|
{
|
|
|
|
if(orientation == Qt::Horizontal)
|
|
|
|
{
|
|
|
|
if(role == Qt::DisplayRole)
|
|
|
|
{
|
|
|
|
if(section < m_headers.size())
|
|
|
|
{
|
|
|
|
return m_headers.at(section);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return QAbstractTableModel::headerData(section, orientation, role);
|
|
|
|
}
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
void CDisAsmTableModel::Redraw()
|
2019-12-11 14:52:12 +00:00
|
|
|
{
|
2021-01-03 17:41:08 +00:00
|
|
|
emit QAbstractTableModel::beginResetModel();
|
|
|
|
emit QAbstractTableModel::endResetModel();
|
2019-12-11 14:52:12 +00:00
|
|
|
}
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
void CDisAsmTableModel::Redraw(uint32 address)
|
2019-12-11 14:52:12 +00:00
|
|
|
{
|
2024-03-22 13:16:37 -04:00
|
|
|
auto modelIndex = TranslateAddressToModelIndex(address);
|
|
|
|
emit QAbstractTableModel::dataChanged(index(modelIndex.row(), 0), index(modelIndex.row(), columnCount()));
|
2019-12-11 14:52:12 +00:00
|
|
|
}
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
uint32 CDisAsmTableModel::GetInstruction(uint32 address) const
|
2019-12-11 14:52:12 +00:00
|
|
|
{
|
2024-03-20 19:33:37 -04:00
|
|
|
address = m_ctx->m_pAddrTranslator(m_ctx, address);
|
2019-12-11 14:52:12 +00:00
|
|
|
return m_ctx->m_pMemoryMap->GetInstruction(address);
|
2019-12-19 22:20:32 +00:00
|
|
|
}
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
std::string CDisAsmTableModel::GetInstructionDetails(int index, uint32 address) const
|
2019-12-19 22:20:32 +00:00
|
|
|
{
|
|
|
|
uint32 instruction = GetInstruction(address);
|
|
|
|
switch(index)
|
|
|
|
{
|
2019-12-19 21:37:47 +00:00
|
|
|
case 0:
|
|
|
|
{
|
|
|
|
std::string instructionCode = lexical_cast_hex<std::string>(instruction, 8);
|
|
|
|
return instructionCode;
|
|
|
|
}
|
|
|
|
case 1:
|
|
|
|
{
|
|
|
|
char disAsm[256];
|
2020-12-31 23:33:19 +00:00
|
|
|
m_ctx->m_pArch->GetInstructionMnemonic(m_ctx, address, instruction, disAsm, 256);
|
2019-12-19 21:37:47 +00:00
|
|
|
return disAsm;
|
|
|
|
}
|
|
|
|
case 2:
|
|
|
|
{
|
|
|
|
char disAsm[256];
|
2020-12-31 23:33:19 +00:00
|
|
|
m_ctx->m_pArch->GetInstructionOperands(m_ctx, address, instruction, disAsm, 256);
|
2019-12-19 21:37:47 +00:00
|
|
|
return disAsm;
|
|
|
|
}
|
2019-12-19 22:20:32 +00:00
|
|
|
}
|
2019-12-19 13:51:41 +00:00
|
|
|
return "";
|
2019-12-19 22:20:32 +00:00
|
|
|
}
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
std::string CDisAsmTableModel::GetInstructionMetadata(uint32 address) const
|
2019-12-19 22:20:32 +00:00
|
|
|
{
|
|
|
|
bool commentDrawn = false;
|
|
|
|
std::string disAsm;
|
|
|
|
//Draw function name
|
|
|
|
{
|
|
|
|
const char* tag = m_ctx->m_Functions.Find(address);
|
|
|
|
if(tag != nullptr)
|
|
|
|
{
|
|
|
|
disAsm += ("@");
|
|
|
|
disAsm += tag;
|
|
|
|
commentDrawn = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Draw target function call if applicable
|
|
|
|
if(!commentDrawn)
|
|
|
|
{
|
|
|
|
uint32 opcode = GetInstruction(address);
|
|
|
|
if(m_ctx->m_pArch->IsInstructionBranch(m_ctx, address, opcode) == MIPS_BRANCH_NORMAL)
|
|
|
|
{
|
|
|
|
uint32 effAddr = m_ctx->m_pArch->GetInstructionEffectiveAddress(m_ctx, address, opcode);
|
2022-12-07 14:48:20 -05:00
|
|
|
if(effAddr != MIPS_INVALID_PC)
|
2019-12-19 22:20:32 +00:00
|
|
|
{
|
2022-12-07 14:48:20 -05:00
|
|
|
const char* tag = m_ctx->m_Functions.Find(effAddr);
|
|
|
|
if(tag != nullptr)
|
|
|
|
{
|
|
|
|
disAsm += ("-> ");
|
|
|
|
disAsm += tag;
|
|
|
|
commentDrawn = true;
|
|
|
|
}
|
2019-12-19 22:20:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return disAsm.c_str();
|
|
|
|
}
|
2021-01-03 17:41:08 +00:00
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
uint32 CDisAsmTableModel::TranslateModelIndexToAddress(const QModelIndex& index) const
|
2021-01-04 18:05:53 +00:00
|
|
|
{
|
2024-03-22 17:18:50 -04:00
|
|
|
return m_windowStart + (index.row() * m_instructionSize);
|
2021-01-04 18:05:53 +00:00
|
|
|
}
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
QModelIndex CDisAsmTableModel::TranslateAddressToModelIndex(uint32 address) const
|
2021-01-04 18:05:53 +00:00
|
|
|
{
|
2024-03-20 19:33:37 -04:00
|
|
|
if(address <= m_windowStart)
|
2021-01-07 22:23:08 +00:00
|
|
|
{
|
2024-03-20 19:33:37 -04:00
|
|
|
return index(0, 0);
|
2021-01-07 22:23:08 +00:00
|
|
|
}
|
2024-03-20 19:33:37 -04:00
|
|
|
address -= m_windowStart;
|
|
|
|
if(address >= m_windowSize)
|
2021-01-04 18:05:53 +00:00
|
|
|
{
|
2024-03-20 19:33:37 -04:00
|
|
|
address = (m_windowSize - m_instructionSize);
|
2021-01-04 18:05:53 +00:00
|
|
|
}
|
2024-03-20 19:33:37 -04:00
|
|
|
return index(address / m_instructionSize, 0);
|
2021-01-04 18:05:53 +00:00
|
|
|
}
|
|
|
|
|
2024-03-21 14:24:08 -04:00
|
|
|
int CDisAsmTableModel::GetLinePixMapWidth() const
|
2021-02-12 11:48:13 -05:00
|
|
|
{
|
|
|
|
return m_line.width();
|
|
|
|
}
|
|
|
|
|
2021-01-03 17:41:08 +00:00
|
|
|
TableColumnDelegateTargetComment::TableColumnDelegateTargetComment(QObject* parent)
|
|
|
|
: QStyledItemDelegate(parent)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void TableColumnDelegateTargetComment::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
|
|
|
{
|
|
|
|
QString target = index.data(Qt::DisplayRole).toString();
|
|
|
|
QString comment = index.data(Qt::UserRole).toString();
|
|
|
|
if(!target.isEmpty() || !comment.isEmpty())
|
|
|
|
{
|
|
|
|
if(!comment.isEmpty())
|
|
|
|
{
|
|
|
|
comment = ";" + comment;
|
|
|
|
}
|
|
|
|
|
|
|
|
painter->save();
|
|
|
|
if((option.state & QStyle::State_Selected) && (option.state & QStyle::State_Active))
|
|
|
|
{
|
|
|
|
painter->setPen(Qt::white);
|
|
|
|
painter->fillRect(option.rect, option.palette.highlight());
|
|
|
|
}
|
|
|
|
else if((option.state & QStyle::State_Selected) && !(option.state & QStyle::State_HasFocus))
|
|
|
|
{
|
2021-01-07 22:48:58 +00:00
|
|
|
painter->fillRect(option.rect, option.palette.window());
|
2021-01-03 17:41:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const QString html = QString("<html><target>%1</target> <comment>%2</comment></html>").arg(target).arg(comment);
|
|
|
|
QTextDocument doc;
|
|
|
|
doc.setTextWidth(option.rect.width());
|
|
|
|
doc.setDefaultStyleSheet("target {color : blue;} comment {color : red;}");
|
|
|
|
doc.setHtml(html);
|
|
|
|
|
|
|
|
QRect clip(0, 0, option.rect.width(), option.rect.height());
|
|
|
|
painter->translate(option.rect.left(), option.rect.top());
|
|
|
|
doc.drawContents(painter, clip);
|
|
|
|
painter->restore();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QStyledItemDelegate::paint(painter, option, index);
|
|
|
|
}
|