1 #include "SymbolsWidget.h"
2 #include "ui_ListDockWidget.h"
3 #include "core/MainWindow.h"
4 #include "common/Helpers.h"
5 
6 #include <QShortcut>
7 
SymbolsModel(QList<SymbolDescription> * symbols,QObject * parent)8 SymbolsModel::SymbolsModel(QList<SymbolDescription> *symbols, QObject *parent)
9     : AddressableItemModel<QAbstractListModel>(parent),
10       symbols(symbols)
11 {
12 }
13 
rowCount(const QModelIndex &) const14 int SymbolsModel::rowCount(const QModelIndex &) const
15 {
16     return symbols->count();
17 }
18 
columnCount(const QModelIndex &) const19 int SymbolsModel::columnCount(const QModelIndex &) const
20 {
21     return SymbolsModel::ColumnCount;
22 }
23 
data(const QModelIndex & index,int role) const24 QVariant SymbolsModel::data(const QModelIndex &index, int role) const
25 {
26     if (index.row() >= symbols->count()) {
27         return QVariant();
28     }
29 
30     const SymbolDescription &symbol = symbols->at(index.row());
31 
32     switch (role) {
33     case Qt::DisplayRole:
34         switch (index.column()) {
35         case SymbolsModel::AddressColumn:
36             return RAddressString(symbol.vaddr);
37         case SymbolsModel::TypeColumn:
38             return QString("%1 %2").arg(symbol.bind, symbol.type).trimmed();
39         case SymbolsModel::NameColumn:
40             return symbol.name;
41         case SymbolsModel::CommentColumn:
42             return Core()->getCommentAt(symbol.vaddr);
43         default:
44             return QVariant();
45         }
46     case SymbolsModel::SymbolDescriptionRole:
47         return QVariant::fromValue(symbol);
48     default:
49         return QVariant();
50     }
51 }
52 
headerData(int section,Qt::Orientation,int role) const53 QVariant SymbolsModel::headerData(int section, Qt::Orientation, int role) const
54 {
55     switch (role) {
56     case Qt::DisplayRole:
57         switch (section) {
58         case SymbolsModel::AddressColumn:
59             return tr("Address");
60         case SymbolsModel::TypeColumn:
61             return tr("Type");
62         case SymbolsModel::NameColumn:
63             return tr("Name");
64         case SymbolsModel::CommentColumn:
65             return tr("Comment");
66         default:
67             return QVariant();
68         }
69     default:
70         return QVariant();
71     }
72 }
73 
address(const QModelIndex & index) const74 RVA SymbolsModel::address(const QModelIndex &index) const
75 {
76     const SymbolDescription &symbol = symbols->at(index.row());
77     return symbol.vaddr;
78 }
79 
name(const QModelIndex & index) const80 QString SymbolsModel::name(const QModelIndex &index) const
81 {
82     const SymbolDescription &symbol = symbols->at(index.row());
83     return symbol.name;
84 }
85 
SymbolsProxyModel(SymbolsModel * sourceModel,QObject * parent)86 SymbolsProxyModel::SymbolsProxyModel(SymbolsModel *sourceModel, QObject *parent)
87     : AddressableFilterProxyModel(sourceModel, parent)
88 {
89     setFilterCaseSensitivity(Qt::CaseInsensitive);
90     setSortCaseSensitivity(Qt::CaseInsensitive);
91 }
92 
filterAcceptsRow(int row,const QModelIndex & parent) const93 bool SymbolsProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
94 {
95     QModelIndex index = sourceModel()->index(row, 0, parent);
96     auto symbol = index.data(SymbolsModel::SymbolDescriptionRole).value<SymbolDescription>();
97 
98     return symbol.name.contains(filterRegExp());
99 }
100 
lessThan(const QModelIndex & left,const QModelIndex & right) const101 bool SymbolsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
102 {
103     auto leftSymbol = left.data(SymbolsModel::SymbolDescriptionRole).value<SymbolDescription>();
104     auto rightSymbol = right.data(SymbolsModel::SymbolDescriptionRole).value<SymbolDescription>();
105 
106     switch (left.column()) {
107     case SymbolsModel::AddressColumn:
108         return leftSymbol.vaddr < rightSymbol.vaddr;
109     case SymbolsModel::TypeColumn:
110         return leftSymbol.type < rightSymbol.type;
111     case SymbolsModel::NameColumn:
112         return leftSymbol.name < rightSymbol.name;
113     case SymbolsModel::CommentColumn:
114         return Core()->getCommentAt(leftSymbol.vaddr) < Core()->getCommentAt(rightSymbol.vaddr);
115     default:
116         break;
117     }
118 
119     return false;
120 }
121 
SymbolsWidget(MainWindow * main)122 SymbolsWidget::SymbolsWidget(MainWindow *main) :
123     ListDockWidget(main)
124 {
125     setWindowTitle(tr("Symbols"));
126     setObjectName("SymbolsWidget");
127 
128     symbolsModel = new SymbolsModel(&symbols, this);
129     symbolsProxyModel = new SymbolsProxyModel(symbolsModel, this);
130     setModels(symbolsProxyModel);
131     ui->treeView->sortByColumn(SymbolsModel::AddressColumn, Qt::AscendingOrder);
132 
133     connect(Core(), &CutterCore::codeRebased, this, &SymbolsWidget::refreshSymbols);
134     connect(Core(), &CutterCore::refreshAll, this, &SymbolsWidget::refreshSymbols);
135     connect(Core(), &CutterCore::commentsChanged, this, [this]() {
136         qhelpers::emitColumnChanged(symbolsModel, SymbolsModel::CommentColumn);
137     });
138 }
139 
~SymbolsWidget()140 SymbolsWidget::~SymbolsWidget() {}
141 
refreshSymbols()142 void SymbolsWidget::refreshSymbols()
143 {
144     symbolsModel->beginResetModel();
145     symbols = Core()->getAllSymbols();
146     symbolsModel->endResetModel();
147 
148     qhelpers::adjustColumns(ui->treeView, SymbolsModel::ColumnCount, 0);
149 }
150