1 #include "ZignaturesWidget.h"
2 #include "ui_ZignaturesWidget.h"
3 #include "core/MainWindow.h"
4 #include "common/Helpers.h"
5 
ZignaturesModel(QList<ZignatureDescription> * zignatures,QObject * parent)6 ZignaturesModel::ZignaturesModel(QList<ZignatureDescription> *zignatures, QObject *parent)
7     : QAbstractListModel(parent),
8       zignatures(zignatures)
9 {
10 }
11 
rowCount(const QModelIndex &) const12 int ZignaturesModel::rowCount(const QModelIndex &) const
13 {
14     return zignatures->count();
15 }
16 
columnCount(const QModelIndex &) const17 int ZignaturesModel::columnCount(const QModelIndex &) const
18 {
19     return ZignaturesModel::ColumnCount;
20 }
21 
data(const QModelIndex & index,int role) const22 QVariant ZignaturesModel::data(const QModelIndex &index, int role) const
23 {
24     if (index.row() >= zignatures->count())
25         return QVariant();
26 
27     const ZignatureDescription &zignature = zignatures->at(index.row());
28 
29     switch (role) {
30     case Qt::DisplayRole:
31         switch (index.column()) {
32         case OffsetColumn:
33             return RAddressString(zignature.offset);
34         case NameColumn:
35             return zignature.name;
36         case ValueColumn:
37             return zignature.bytes;
38         default:
39             return QVariant();
40         }
41 
42     case ZignatureDescriptionRole:
43         return QVariant::fromValue(zignature);
44 
45     case Qt::ToolTipRole: {
46         QString tmp = QString("Graph:\n\n    Cyclomatic complexity: " + RSizeString(zignature.cc) +
47                               "\n    Nodes / basicblocks: " + RSizeString(zignature.nbbs) +
48                               "\n    Edges: " + RSizeString(zignature.edges) +
49                               "\n    Ebbs: " + RSizeString(zignature.ebbs) +
50                               "\n\nRefs:\n");
51         for (const QString &ref : zignature.refs) {
52             tmp.append("\n    " + ref);
53         }
54         return tmp;
55     }
56 
57     default:
58         return QVariant();
59     }
60 }
61 
headerData(int section,Qt::Orientation,int role) const62 QVariant ZignaturesModel::headerData(int section, Qt::Orientation, int role) const
63 {
64     switch (role) {
65     case Qt::DisplayRole:
66         switch (section) {
67         case OffsetColumn:
68             return tr("Offset");
69         case NameColumn:
70             return tr("Name");
71         case ValueColumn:
72             return tr("Bytes");
73         default:
74             return QVariant();
75         }
76     default:
77         return QVariant();
78     }
79 }
80 
ZignaturesProxyModel(ZignaturesModel * sourceModel,QObject * parent)81 ZignaturesProxyModel::ZignaturesProxyModel(ZignaturesModel *sourceModel, QObject *parent)
82     : QSortFilterProxyModel(parent)
83 {
84     setSourceModel(sourceModel);
85 }
86 
filterAcceptsRow(int row,const QModelIndex & parent) const87 bool ZignaturesProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
88 {
89     QModelIndex index = sourceModel()->index(row, 0, parent);
90     ZignatureDescription item = index.data(
91                                     ZignaturesModel::ZignatureDescriptionRole).value<ZignatureDescription>();
92     return item.name.contains(filterRegExp());
93 }
94 
lessThan(const QModelIndex & left,const QModelIndex & right) const95 bool ZignaturesProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
96 {
97     ZignatureDescription leftZignature = left.data(
98                                              ZignaturesModel::ZignatureDescriptionRole).value<ZignatureDescription>();
99     ZignatureDescription rightZignature = right.data(
100                                               ZignaturesModel::ZignatureDescriptionRole).value<ZignatureDescription>();
101 
102     switch (left.column()) {
103     case ZignaturesModel::OffsetColumn:
104         return leftZignature.offset < rightZignature.offset;
105     case ZignaturesModel::NameColumn:
106         return leftZignature.name < rightZignature.name;
107     case ZignaturesModel::ValueColumn:
108         return leftZignature.bytes < rightZignature.bytes;
109     default:
110         break;
111     }
112 
113     return leftZignature.offset < rightZignature.offset;
114 }
115 
ZignaturesWidget(MainWindow * main)116 ZignaturesWidget::ZignaturesWidget(MainWindow *main) :
117     CutterDockWidget(main),
118     ui(new Ui::ZignaturesWidget)
119 {
120     ui->setupUi(this);
121 
122     zignaturesModel = new ZignaturesModel(&zignatures, this);
123     zignaturesProxyModel = new ZignaturesProxyModel(zignaturesModel, this);
124     ui->zignaturesTreeView->setModel(zignaturesProxyModel);
125     ui->zignaturesTreeView->sortByColumn(ZignaturesModel::OffsetColumn, Qt::AscendingOrder);
126 
127     setScrollMode();
128 
129     connect(Core(), &CutterCore::refreshAll, this, &ZignaturesWidget::refreshZignatures);
130 }
131 
~ZignaturesWidget()132 ZignaturesWidget::~ZignaturesWidget() {}
133 
refreshZignatures()134 void ZignaturesWidget::refreshZignatures()
135 {
136     zignaturesModel->beginResetModel();
137     zignatures = Core()->getAllZignatures();
138     zignaturesModel->endResetModel();
139 
140     ui->zignaturesTreeView->resizeColumnToContents(0);
141     ui->zignaturesTreeView->resizeColumnToContents(1);
142     ui->zignaturesTreeView->resizeColumnToContents(2);
143 }
144 
setScrollMode()145 void ZignaturesWidget::setScrollMode()
146 {
147     qhelpers::setVerticalScrollMode(ui->zignaturesTreeView);
148 }
149 
on_zignaturesTreeView_doubleClicked(const QModelIndex & index)150 void ZignaturesWidget::on_zignaturesTreeView_doubleClicked(const QModelIndex &index)
151 {
152     ZignatureDescription item = index.data(
153                                     ZignaturesModel::ZignatureDescriptionRole).value<ZignatureDescription>();
154     Core()->seekAndShow(item.offset);
155 }
156