1 #include "SegmentsWidget.h"
2 #include "core/MainWindow.h"
3 #include "common/Helpers.h"
4 #include "ui_ListDockWidget.h"
5
6 #include <QVBoxLayout>
7 #include <QShortcut>
8
SegmentsModel(QList<SegmentDescription> * segments,QObject * parent)9 SegmentsModel::SegmentsModel(QList<SegmentDescription> *segments, QObject *parent)
10 : AddressableItemModel<QAbstractListModel>(parent),
11 segments(segments)
12 {
13 }
14
rowCount(const QModelIndex &) const15 int SegmentsModel::rowCount(const QModelIndex &) const
16 {
17 return segments->count();
18 }
19
columnCount(const QModelIndex &) const20 int SegmentsModel::columnCount(const QModelIndex &) const
21 {
22 return SegmentsModel::ColumnCount;
23 }
24
data(const QModelIndex & index,int role) const25 QVariant SegmentsModel::data(const QModelIndex &index, int role) const
26 {
27 // TODO: create unique colors, e. g. use HSV color space and rotate in H for 360/size
28 static const QList<QColor> colors = { QColor("#1ABC9C"), //TURQUOISE
29 QColor("#2ECC71"), //EMERALD
30 QColor("#3498DB"), //PETER RIVER
31 QColor("#9B59B6"), //AMETHYST
32 QColor("#34495E"), //WET ASPHALT
33 QColor("#F1C40F"), //SUN FLOWER
34 QColor("#E67E22"), //CARROT
35 QColor("#E74C3C"), //ALIZARIN
36 QColor("#ECF0F1"), //CLOUDS
37 QColor("#BDC3C7"), //SILVER
38 QColor("#95A5A6") //COBCRETE
39 };
40
41 if (index.row() >= segments->count())
42 return QVariant();
43
44 const SegmentDescription &segment = segments->at(index.row());
45
46 switch (role) {
47 case Qt::DisplayRole:
48 switch (index.column()) {
49 case SegmentsModel::NameColumn:
50 return segment.name;
51 case SegmentsModel::SizeColumn:
52 return QString::number(segment.size);
53 case SegmentsModel::AddressColumn:
54 return RAddressString(segment.vaddr);
55 case SegmentsModel::EndAddressColumn:
56 return RAddressString(segment.vaddr + segment.size);
57 case SegmentsModel::PermColumn:
58 return segment.perm;
59 case SegmentsModel::CommentColumn:
60 return Core()->getCommentAt(segment.vaddr);
61 default:
62 return QVariant();
63 }
64 case Qt::DecorationRole:
65 if (index.column() == 0)
66 return colors[index.row() % colors.size()];
67 return QVariant();
68 case SegmentsModel::SegmentDescriptionRole:
69 return QVariant::fromValue(segment);
70 default:
71 return QVariant();
72 }
73 }
74
headerData(int segment,Qt::Orientation,int role) const75 QVariant SegmentsModel::headerData(int segment, Qt::Orientation, int role) const
76 {
77 switch (role) {
78 case Qt::DisplayRole:
79 switch (segment) {
80 case SegmentsModel::NameColumn:
81 return tr("Name");
82 case SegmentsModel::SizeColumn:
83 return tr("Size");
84 case SegmentsModel::AddressColumn:
85 return tr("Address");
86 case SegmentsModel::EndAddressColumn:
87 return tr("End Address");
88 case SegmentsModel::PermColumn:
89 return tr("Permissions");
90 case SegmentsModel::CommentColumn:
91 return tr("Comment");
92 default:
93 return QVariant();
94 }
95 default:
96 return QVariant();
97 }
98 }
99
address(const QModelIndex & index) const100 RVA SegmentsModel::address(const QModelIndex &index) const
101 {
102 const SegmentDescription &segment = segments->at(index.row());
103 return segment.vaddr;
104 }
105
name(const QModelIndex & index) const106 QString SegmentsModel::name(const QModelIndex &index) const
107 {
108 const SegmentDescription &segment = segments->at(index.row());
109 return segment.name;
110 }
111
SegmentsProxyModel(SegmentsModel * sourceModel,QObject * parent)112 SegmentsProxyModel::SegmentsProxyModel(SegmentsModel *sourceModel, QObject *parent)
113 : AddressableFilterProxyModel(sourceModel, parent)
114 {
115 setFilterCaseSensitivity(Qt::CaseInsensitive);
116 setSortCaseSensitivity(Qt::CaseInsensitive);
117 }
118
lessThan(const QModelIndex & left,const QModelIndex & right) const119 bool SegmentsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
120 {
121 auto leftSegment = left.data(SegmentsModel::SegmentDescriptionRole).value<SegmentDescription>();
122 auto rightSegment = right.data(SegmentsModel::SegmentDescriptionRole).value<SegmentDescription>();
123 switch (left.column()) {
124 case SegmentsModel::NameColumn:
125 return leftSegment.name < rightSegment.name;
126 case SegmentsModel::SizeColumn:
127 return leftSegment.size < rightSegment.size;
128 case SegmentsModel::AddressColumn:
129 case SegmentsModel::EndAddressColumn:
130 return leftSegment.vaddr < rightSegment.vaddr;
131 case SegmentsModel::CommentColumn:
132 return Core()->getCommentAt(leftSegment.vaddr) < Core()->getCommentAt(rightSegment.vaddr);
133 default:
134 break;
135 }
136 return false;
137 }
138
SegmentsWidget(MainWindow * main)139 SegmentsWidget::SegmentsWidget(MainWindow *main) :
140 ListDockWidget(main)
141 {
142 setObjectName("SegmentsWidget");
143 setWindowTitle(QStringLiteral("Segments"));
144
145 segmentsModel = new SegmentsModel(&segments, this);
146 auto proxyModel = new SegmentsProxyModel(segmentsModel, this);
147 setModels(proxyModel);
148
149 ui->treeView->sortByColumn(SegmentsModel::NameColumn, Qt::AscendingOrder);
150
151 ui->quickFilterView->closeFilter();
152 showCount(false);
153
154 connect(Core(), &CutterCore::refreshAll, this, &SegmentsWidget::refreshSegments);
155 connect(Core(), &CutterCore::codeRebased, this, &SegmentsWidget::refreshSegments);
156 connect(Core(), &CutterCore::commentsChanged, this, [this]() {
157 qhelpers::emitColumnChanged(segmentsModel, SegmentsModel::CommentColumn);
158 });
159 }
160
~SegmentsWidget()161 SegmentsWidget::~SegmentsWidget() {}
162
refreshSegments()163 void SegmentsWidget::refreshSegments()
164 {
165 segmentsModel->beginResetModel();
166 segments = Core()->getAllSegments();
167 segmentsModel->endResetModel();
168
169 qhelpers::adjustColumns(ui->treeView, SegmentsModel::ColumnCount, 0);
170 }
171