summaryrefslogtreecommitdiff
path: root/view/sharedcache/ui/symboltable.cpp
blob: c5e2d7bf9740c52b74148cb65090afb640dcf3c7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <progresstask.h>
#include "symboltable.h"

#include <QHeaderView>

#include "binaryninjaapi.h"

using namespace BinaryNinja;
using namespace SharedCacheAPI;

SymbolTableModel::SymbolTableModel(SymbolTableView* parent)
	: QAbstractTableModel(parent), m_parent(parent) {
}

int SymbolTableModel::rowCount(const QModelIndex& parent) const {
	Q_UNUSED(parent);
	return static_cast<int>(m_symbols.size());
}

int SymbolTableModel::columnCount(const QModelIndex& parent) const {
	Q_UNUSED(parent);
	// We have 2 columns: Address, Name
	return 2;
}

QVariant SymbolTableModel::data(const QModelIndex& index, int role) const {
	if (!index.isValid() || role != Qt::DisplayRole) {
		return QVariant();
	}

	const CacheSymbol& symbol = m_symbols.at(index.row());

	switch (index.column()) {
	case 0: // Address column
		return QString("0x%1").arg(symbol.address, 0, 16); // Display address as hexadecimal
	case 1: // Name column
		return QString::fromUtf8(symbol.name.c_str(), symbol.name.size());
	default:
		return QVariant();
	}
}

QVariant SymbolTableModel::headerData(int section, Qt::Orientation orientation, int role) const {
	if (role != Qt::DisplayRole || orientation != Qt::Horizontal) {
		return QVariant();
	}

	switch (section) {
	case 0:
		return QString("Address");
	case 1:
		return QString("Name");
	default:
		return QVariant();
	}
}

void SymbolTableModel::updateSymbols() {
	m_symbols = m_parent->m_symbols;
	setFilter(m_filter);
}

const CacheSymbol& SymbolTableModel::symbolAt(int row) const {
	return m_symbols.at(row);
}


void SymbolTableModel::setFilter(std::string text)
{
	beginResetModel();

	m_filter = text;
	m_symbols.clear();

	if (m_filter.empty())
	{
		m_symbols = m_parent->m_symbols;
	}
	else
	{
		m_symbols.reserve(m_parent->m_symbols.size());
		for (const auto& symbol : m_parent->m_symbols)
		{
			if (((std::string_view)symbol.name).find(m_filter) != std::string::npos)
			{
				m_symbols.push_back(symbol);
			}
		}
		m_symbols.shrink_to_fit();
	}

	endResetModel();
}


SymbolTableView::SymbolTableView(QWidget* parent)
	: m_model(new SymbolTableModel(this)) {

	// Set up the filter model
	setModel(m_model);

	// Configure view settings
	horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
	setSelectionBehavior(QAbstractItemView::SelectRows);
	setSelectionMode(QAbstractItemView::SingleSelection);

	setSortingEnabled(true);
}

SymbolTableView::~SymbolTableView() {
	delete m_model;
}

void SymbolTableView::populateSymbols(BinaryView &view)
{
	if (auto controller = SharedCacheController::GetController(view)) {
		BackgroundThread::create(this)
			->thenBackground([this, controller]() {
				std::vector<CacheSymbol> newSymbols = controller->GetSymbols();
				m_symbols.swap(newSymbols);
			})
			->thenMainThread([this](){ m_model->updateSymbols(); })
			->start();
	}
}

void SymbolTableView::setFilter(const std::string& filter) {
	m_model->setFilter(filter);
}