mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-19 02:48:49 +00:00
Added headers widget (#499)
This commit is contained in:
parent
55be4efb8c
commit
7fdfad32f7
@ -1020,6 +1020,29 @@ QList<SymbolDescription> CutterCore::getAllSymbols()
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<HeaderDescription> CutterCore::getAllHeaders()
|
||||
{
|
||||
CORE_LOCK();
|
||||
QList<HeaderDescription> ret;
|
||||
|
||||
QJsonArray headersArray = cmdj("ihj").array();
|
||||
|
||||
for (QJsonValue value : headersArray) {
|
||||
QJsonObject headerObject = value.toObject();
|
||||
|
||||
HeaderDescription header;
|
||||
|
||||
header.vaddr = headerObject["vaddr"].toVariant().toULongLong();
|
||||
header.paddr = headerObject["paddr"].toVariant().toULongLong();
|
||||
header.value = headerObject["comment"].toString();
|
||||
header.name = headerObject["name"].toString();
|
||||
|
||||
ret << header;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<CommentDescription> CutterCore::getAllComments(const QString &filterType)
|
||||
{
|
||||
CORE_LOCK();
|
||||
|
10
src/Cutter.h
10
src/Cutter.h
@ -108,6 +108,14 @@ struct ExportDescription {
|
||||
QString flag_name;
|
||||
};
|
||||
|
||||
struct HeaderDescription
|
||||
{
|
||||
RVA vaddr;
|
||||
RVA paddr;
|
||||
QString value;
|
||||
QString name;
|
||||
};
|
||||
|
||||
struct TypeDescription {
|
||||
QString type;
|
||||
int size;
|
||||
@ -275,6 +283,7 @@ Q_DECLARE_METATYPE(const ClassFieldDescription *)
|
||||
Q_DECLARE_METATYPE(ResourcesDescription)
|
||||
Q_DECLARE_METATYPE(VTableDescription)
|
||||
Q_DECLARE_METATYPE(TypeDescription)
|
||||
Q_DECLARE_METATYPE(HeaderDescription)
|
||||
Q_DECLARE_METATYPE(SearchDescription)
|
||||
Q_DECLARE_METATYPE(SectionDescription)
|
||||
|
||||
@ -429,6 +438,7 @@ public:
|
||||
QList<ImportDescription> getAllImports();
|
||||
QList<ExportDescription> getAllExports();
|
||||
QList<SymbolDescription> getAllSymbols();
|
||||
QList<HeaderDescription> getAllHeaders();
|
||||
QList<CommentDescription> getAllComments(const QString &filterType);
|
||||
QList<RelocDescription> getAllRelocs();
|
||||
QList<StringDescription> getAllStrings();
|
||||
|
@ -146,6 +146,7 @@ SOURCES += \
|
||||
widgets/ResourcesWidget.cpp \
|
||||
widgets/VTablesWidget.cpp \
|
||||
widgets/TypesWidget.cpp \
|
||||
widgets/HeadersWidget.cpp \
|
||||
widgets/SearchWidget.cpp \
|
||||
CutterApplication.cpp \
|
||||
utils/JupyterConnection.cpp \
|
||||
@ -219,6 +220,7 @@ HEADERS += \
|
||||
CutterApplication.h \
|
||||
widgets/VTablesWidget.h \
|
||||
widgets/TypesWidget.h \
|
||||
widgets/HeadersWidget.h \
|
||||
widgets/SearchWidget.h \
|
||||
utils/JupyterConnection.h \
|
||||
widgets/JupyterWidget.h \
|
||||
@ -267,6 +269,7 @@ FORMS += \
|
||||
widgets/ClassesWidget.ui \
|
||||
widgets/VTablesWidget.ui \
|
||||
widgets/TypesWidget.ui \
|
||||
widgets/HeadersWidget.ui \
|
||||
widgets/SearchWidget.ui \
|
||||
widgets/JupyterWidget.ui \
|
||||
dialogs/R2PluginsDialog.ui \
|
||||
|
@ -68,6 +68,7 @@
|
||||
#include "widgets/ResourcesWidget.h"
|
||||
#include "widgets/VTablesWidget.h"
|
||||
#include "widgets/JupyterWidget.h"
|
||||
#include "widgets/HeadersWidget.h"
|
||||
|
||||
// graphics
|
||||
#include <QGraphicsEllipseItem>
|
||||
@ -167,6 +168,7 @@ void MainWindow::initUI()
|
||||
functionsDock = new FunctionsWidget(this, ui->actionFunctions);
|
||||
importsDock = new ImportsWidget(this, ui->actionImports);
|
||||
exportsDock = new ExportsWidget(this, ui->actionExports);
|
||||
headersDock = new HeadersWidget(this, ui->actionHeaders);
|
||||
typesDock = new TypesWidget(this, ui->actionTypes);
|
||||
searchDock = new SearchWidget(this, ui->actionSearch);
|
||||
symbolsDock = new SymbolsWidget(this, ui->actionSymbols);
|
||||
@ -461,6 +463,7 @@ void MainWindow::restoreDocks()
|
||||
tabifyDockWidget(dashboardDock, exportsDock);
|
||||
tabifyDockWidget(dashboardDock, typesDock);
|
||||
tabifyDockWidget(dashboardDock, searchDock);
|
||||
tabifyDockWidget(dashboardDock, headersDock);
|
||||
tabifyDockWidget(dashboardDock, symbolsDock);
|
||||
tabifyDockWidget(dashboardDock, classesDock);
|
||||
tabifyDockWidget(dashboardDock, resourcesDock);
|
||||
|
@ -40,6 +40,7 @@ class ClassesWidget;
|
||||
class ResourcesWidget;
|
||||
class VTablesWidget;
|
||||
class TypesWidget;
|
||||
class HeadersWidget;
|
||||
class SearchWidget;
|
||||
#ifdef CUTTER_ENABLE_JUPYTER
|
||||
class JupyterWidget;
|
||||
@ -183,8 +184,9 @@ private:
|
||||
FunctionsWidget *functionsDock = nullptr;
|
||||
ImportsWidget *importsDock = nullptr;
|
||||
ExportsWidget *exportsDock = nullptr;
|
||||
HeadersWidget *headersDock = nullptr;
|
||||
TypesWidget *typesDock = nullptr;
|
||||
SearchWidget *searchDock = nullptr;
|
||||
SearchWidget *searchDock = nullptr;
|
||||
SymbolsWidget *symbolsDock = nullptr;
|
||||
RelocsWidget *relocsDock = nullptr;
|
||||
CommentsWidget *commentsDock = nullptr;
|
||||
|
@ -250,6 +250,7 @@ border-top: 0px;
|
||||
<addaction name="actionStrings"/>
|
||||
<addaction name="actionFlags"/>
|
||||
<addaction name="actionSections"/>
|
||||
<addaction name="actionHeaders"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionComments"/>
|
||||
<addaction name="actionConsole"/>
|
||||
@ -1061,6 +1062,17 @@ background-color: palette(dark);
|
||||
<string>Show/Hide Search panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHeaders">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Headers</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Headers panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionJupyter">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
|
146
src/widgets/HeadersWidget.cpp
Normal file
146
src/widgets/HeadersWidget.cpp
Normal file
@ -0,0 +1,146 @@
|
||||
#include "HeadersWidget.h"
|
||||
#include "ui_HeadersWidget.h"
|
||||
#include "MainWindow.h"
|
||||
#include "utils/Helpers.h"
|
||||
|
||||
HeadersModel::HeadersModel(QList<HeaderDescription> *headers, QObject *parent)
|
||||
: QAbstractListModel(parent),
|
||||
headers(headers)
|
||||
{
|
||||
}
|
||||
|
||||
int HeadersModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return headers->count();
|
||||
}
|
||||
|
||||
int HeadersModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return HeadersModel::ColumnCount;
|
||||
}
|
||||
|
||||
QVariant HeadersModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.row() >= headers->count())
|
||||
return QVariant();
|
||||
|
||||
const HeaderDescription &header = headers->at(index.row());
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
switch (index.column()) {
|
||||
case OffsetColumn:
|
||||
return RAddressString(header.vaddr);
|
||||
case NameColumn:
|
||||
return header.name;
|
||||
case ValueColumn:
|
||||
return header.value;
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
case HeaderDescriptionRole:
|
||||
return QVariant::fromValue(header);
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant HeadersModel::headerData(int section, Qt::Orientation, int role) const
|
||||
{
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
switch (section) {
|
||||
case OffsetColumn:
|
||||
return tr("Offset");
|
||||
case NameColumn:
|
||||
return tr("Name");
|
||||
case ValueColumn:
|
||||
return tr("Value");
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
void HeadersModel::beginReloadHeaders()
|
||||
{
|
||||
beginResetModel();
|
||||
}
|
||||
|
||||
void HeadersModel::endReloadHeaders()
|
||||
{
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
HeadersProxyModel::HeadersProxyModel(HeadersModel *sourceModel, QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{
|
||||
setSourceModel(sourceModel);
|
||||
}
|
||||
|
||||
bool HeadersProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
|
||||
{
|
||||
QModelIndex index = sourceModel()->index(row, 0, parent);
|
||||
HeaderDescription item = index.data(HeadersModel::HeaderDescriptionRole).value<HeaderDescription>();
|
||||
return item.name.contains(filterRegExp());
|
||||
}
|
||||
|
||||
bool HeadersProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
HeaderDescription leftHeader = left.data(HeadersModel::HeaderDescriptionRole).value<HeaderDescription>();
|
||||
HeaderDescription rightHeader = right.data(HeadersModel::HeaderDescriptionRole).value<HeaderDescription>();
|
||||
|
||||
switch (left.column()) {
|
||||
case HeadersModel::OffsetColumn:
|
||||
return leftHeader.vaddr < rightHeader.vaddr;
|
||||
case HeadersModel::NameColumn:
|
||||
return leftHeader.name < rightHeader.name;
|
||||
case HeadersModel::ValueColumn:
|
||||
return leftHeader.value < rightHeader.value;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return leftHeader.vaddr < rightHeader.vaddr;
|
||||
}
|
||||
|
||||
HeadersWidget::HeadersWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
ui(new Ui::HeadersWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
headersModel = new HeadersModel(&headers, this);
|
||||
headersProxyModel = new HeadersProxyModel(headersModel, this);
|
||||
ui->headersTreeView->setModel(headersProxyModel);
|
||||
ui->headersTreeView->sortByColumn(HeadersModel::OffsetColumn, Qt::AscendingOrder);
|
||||
|
||||
setScrollMode();
|
||||
|
||||
connect(Core(), &CutterCore::refreshAll, this, &HeadersWidget::refreshHeaders);
|
||||
}
|
||||
|
||||
HeadersWidget::~HeadersWidget() {}
|
||||
|
||||
void HeadersWidget::refreshHeaders()
|
||||
{
|
||||
headersModel->beginReloadHeaders();
|
||||
headers = Core()->getAllHeaders();
|
||||
headersModel->endReloadHeaders();
|
||||
|
||||
ui->headersTreeView->resizeColumnToContents(0);
|
||||
ui->headersTreeView->resizeColumnToContents(1);
|
||||
}
|
||||
|
||||
void HeadersWidget::setScrollMode()
|
||||
{
|
||||
qhelpers::setVerticalScrollMode(ui->headersTreeView);
|
||||
}
|
||||
|
||||
void HeadersWidget::on_headersTreeView_doubleClicked(const QModelIndex &index)
|
||||
{
|
||||
HeaderDescription item = index.data(HeadersModel::HeaderDescriptionRole).value<HeaderDescription>();
|
||||
Core()->seek(item.vaddr);
|
||||
}
|
88
src/widgets/HeadersWidget.h
Normal file
88
src/widgets/HeadersWidget.h
Normal file
@ -0,0 +1,88 @@
|
||||
#ifndef HEADERSWIDGET_H
|
||||
#define HEADERSWIDGET_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Cutter.h"
|
||||
#include "CutterDockWidget.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class MainWindow;
|
||||
class QTreeWidget;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class HeadersWidget;
|
||||
}
|
||||
|
||||
|
||||
class MainWindow;
|
||||
class QTreeWidgetItem;
|
||||
|
||||
|
||||
class HeadersModel: public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QList<HeaderDescription> *headers;
|
||||
|
||||
public:
|
||||
enum Column { OffsetColumn = 0, NameColumn, ValueColumn, ColumnCount };
|
||||
enum Role { HeaderDescriptionRole = Qt::UserRole };
|
||||
|
||||
HeadersModel(QList<HeaderDescription> *headers, QObject *parent = 0);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
|
||||
void beginReloadHeaders();
|
||||
void endReloadHeaders();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class HeadersProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HeadersProxyModel(HeadersModel *sourceModel, QObject *parent = nullptr);
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int row, const QModelIndex &parent) const override;
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class HeadersWidget : public CutterDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit HeadersWidget(MainWindow *main, QAction *action = nullptr);
|
||||
~HeadersWidget();
|
||||
|
||||
private slots:
|
||||
void on_headersTreeView_doubleClicked(const QModelIndex &index);
|
||||
|
||||
void refreshHeaders();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::HeadersWidget> ui;
|
||||
|
||||
HeadersModel *headersModel;
|
||||
HeadersProxyModel *headersProxyModel;
|
||||
QList<HeaderDescription> headers;
|
||||
|
||||
void setScrollMode();
|
||||
};
|
||||
|
||||
|
||||
#endif // HEADERSWIDGET_H
|
58
src/widgets/HeadersWidget.ui
Normal file
58
src/widgets/HeadersWidget.ui
Normal file
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>HeadersWidget</class>
|
||||
<widget class="QDockWidget" name="HeadersWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Headers</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTreeView" name="headersTreeView">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QTreeView::item
|
||||
{
|
||||
padding-top: 1px;
|
||||
padding-bottom: 1px;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
Reference in New Issue
Block a user