mirror of
https://github.com/rizinorg/cutter.git
synced 2025-02-07 15:32:13 +00:00
Add ClassesWidget (Fix #193)
This commit is contained in:
parent
320a81ee14
commit
a476dda5d0
@ -33,12 +33,14 @@
|
|||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
#include <QToolTip>
|
#include <QToolTip>
|
||||||
#include <QTreeWidgetItem>
|
#include <QTreeWidgetItem>
|
||||||
|
#include <QSvgRenderer>
|
||||||
|
|
||||||
#include "utils/Highlighter.h"
|
#include "utils/Highlighter.h"
|
||||||
#include "utils/HexAsciiHighlighter.h"
|
#include "utils/HexAsciiHighlighter.h"
|
||||||
#include "utils/Helpers.h"
|
#include "utils/Helpers.h"
|
||||||
#include "dialogs/NewFileDialog.h"
|
#include "utils/SvgIconEngine.h"
|
||||||
|
|
||||||
|
#include "dialogs/NewFileDialog.h"
|
||||||
#include "widgets/DisassemblerGraphView.h"
|
#include "widgets/DisassemblerGraphView.h"
|
||||||
#include "widgets/FunctionsWidget.h"
|
#include "widgets/FunctionsWidget.h"
|
||||||
#include "widgets/SectionsWidget.h"
|
#include "widgets/SectionsWidget.h"
|
||||||
@ -60,6 +62,7 @@
|
|||||||
#include "dialogs/OptionsDialog.h"
|
#include "dialogs/OptionsDialog.h"
|
||||||
#include "widgets/EntrypointWidget.h"
|
#include "widgets/EntrypointWidget.h"
|
||||||
#include "dialogs/SaveProjectDialog.h"
|
#include "dialogs/SaveProjectDialog.h"
|
||||||
|
#include "widgets/ClassesWidget.h"
|
||||||
|
|
||||||
// graphics
|
// graphics
|
||||||
#include <QGraphicsEllipseItem>
|
#include <QGraphicsEllipseItem>
|
||||||
@ -116,9 +119,6 @@ MainWindow::~MainWindow()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <QSvgRenderer>
|
|
||||||
#include "utils/SvgIconEngine.h"
|
|
||||||
|
|
||||||
void MainWindow::initUI()
|
void MainWindow::initUI()
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
@ -241,6 +241,8 @@ void MainWindow::initUI()
|
|||||||
ADD_DOCK(Notepad, notepadDock, ui->actionNotepad);
|
ADD_DOCK(Notepad, notepadDock, ui->actionNotepad);
|
||||||
ADD_DOCK(Dashboard, dashboardDock, ui->actionDashboard);
|
ADD_DOCK(Dashboard, dashboardDock, ui->actionDashboard);
|
||||||
ADD_DOCK(SdbDock, sdbDock, ui->actionSDBBrowser);
|
ADD_DOCK(SdbDock, sdbDock, ui->actionSDBBrowser);
|
||||||
|
ADD_DOCK(ClassesWidget, classesDock, ui->actionClasses);
|
||||||
|
|
||||||
#undef ADD_DOCK
|
#undef ADD_DOCK
|
||||||
|
|
||||||
// Set up dock widgets default layout
|
// Set up dock widgets default layout
|
||||||
@ -622,6 +624,7 @@ void MainWindow::restoreDocks()
|
|||||||
tabifyDockWidget(dashboardDock, exportsDock);
|
tabifyDockWidget(dashboardDock, exportsDock);
|
||||||
tabifyDockWidget(dashboardDock, symbolsDock);
|
tabifyDockWidget(dashboardDock, symbolsDock);
|
||||||
tabifyDockWidget(dashboardDock, notepadDock);
|
tabifyDockWidget(dashboardDock, notepadDock);
|
||||||
|
tabifyDockWidget(dashboardDock, classesDock);
|
||||||
|
|
||||||
dashboardDock->raise();
|
dashboardDock->raise();
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ class SectionsDock;
|
|||||||
class ConsoleWidget;
|
class ConsoleWidget;
|
||||||
class EntrypointWidget;
|
class EntrypointWidget;
|
||||||
class DisassemblerGraphView;
|
class DisassemblerGraphView;
|
||||||
|
class ClassesWidget;
|
||||||
|
|
||||||
class QDockWidget;
|
class QDockWidget;
|
||||||
|
|
||||||
@ -185,6 +186,7 @@ private:
|
|||||||
//QAction *sidebar_action;
|
//QAction *sidebar_action;
|
||||||
SectionsDock *sectionsDock;
|
SectionsDock *sectionsDock;
|
||||||
ConsoleWidget *consoleDock;
|
ConsoleWidget *consoleDock;
|
||||||
|
ClassesWidget *classesDock;
|
||||||
|
|
||||||
QList<QDockWidget *> dockWidgets;
|
QList<QDockWidget *> dockWidgets;
|
||||||
QMap<QAction *, QDockWidget *> dockWidgetActions;
|
QMap<QAction *, QDockWidget *> dockWidgetActions;
|
||||||
|
@ -241,6 +241,7 @@ border-top: 0px;
|
|||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionEntrypoints"/>
|
<addaction name="actionEntrypoints"/>
|
||||||
<addaction name="actionFunctions"/>
|
<addaction name="actionFunctions"/>
|
||||||
|
<addaction name="actionClasses"/>
|
||||||
<addaction name="actionImports"/>
|
<addaction name="actionImports"/>
|
||||||
<addaction name="actionExports"/>
|
<addaction name="actionExports"/>
|
||||||
<addaction name="actionSymbols"/>
|
<addaction name="actionSymbols"/>
|
||||||
@ -1019,6 +1020,14 @@ QToolButton:pressed {
|
|||||||
<string>Console</string>
|
<string>Console</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionClasses">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Classes</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources>
|
<resources>
|
||||||
|
@ -1175,6 +1175,46 @@ QList<EntrypointDescription> CutterCore::getAllEntrypoint()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<ClassDescription> CutterCore::getAllClasses()
|
||||||
|
{
|
||||||
|
CORE_LOCK();
|
||||||
|
QList<ClassDescription> ret;
|
||||||
|
|
||||||
|
QJsonArray classesArray = cmdj("icj").array();
|
||||||
|
for (QJsonValueRef value : classesArray)
|
||||||
|
{
|
||||||
|
QJsonObject classObject = value.toObject();
|
||||||
|
|
||||||
|
ClassDescription cls;
|
||||||
|
cls.name = classObject["classname"].toString();
|
||||||
|
cls.addr = classObject["addr"].toVariant().toULongLong();
|
||||||
|
cls.index = classObject["index"].toVariant().toULongLong();
|
||||||
|
|
||||||
|
for(QJsonValueRef value2 : classObject["methods"].toArray())
|
||||||
|
{
|
||||||
|
QJsonObject methObject = value2.toObject();
|
||||||
|
|
||||||
|
ClassMethodDescription meth;
|
||||||
|
meth.name = methObject["name"].toString();
|
||||||
|
meth.addr = methObject["addr"].toVariant().toULongLong();
|
||||||
|
cls.methods << meth;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(QJsonValueRef value2 : classObject["fields"].toArray())
|
||||||
|
{
|
||||||
|
QJsonObject fieldObject = value2.toObject();
|
||||||
|
|
||||||
|
ClassFieldDescription field;
|
||||||
|
field.name = fieldObject["name"].toString();
|
||||||
|
field.addr = fieldObject["addr"].toVariant().toULongLong();
|
||||||
|
cls.fields << field;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret << cls;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
QList<XrefDescription> CutterCore::getXRefs(RVA addr, bool to, bool whole_function, const QString &filterType)
|
QList<XrefDescription> CutterCore::getXRefs(RVA addr, bool to, bool whole_function, const QString &filterType)
|
||||||
{
|
{
|
||||||
QList<XrefDescription> ret = QList<XrefDescription>();
|
QList<XrefDescription> ret = QList<XrefDescription>();
|
||||||
|
28
src/cutter.h
28
src/cutter.h
@ -174,6 +174,27 @@ struct DisassemblyLine
|
|||||||
QString text;
|
QString text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ClassMethodDescription
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
RVA addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ClassFieldDescription
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
RVA addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ClassDescription
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
RVA addr;
|
||||||
|
ut64 index;
|
||||||
|
QList<ClassMethodDescription> methods;
|
||||||
|
QList<ClassFieldDescription> fields;
|
||||||
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(FunctionDescription)
|
Q_DECLARE_METATYPE(FunctionDescription)
|
||||||
Q_DECLARE_METATYPE(ImportDescription)
|
Q_DECLARE_METATYPE(ImportDescription)
|
||||||
Q_DECLARE_METATYPE(ExportDescription)
|
Q_DECLARE_METATYPE(ExportDescription)
|
||||||
@ -186,6 +207,12 @@ Q_DECLARE_METATYPE(FlagDescription)
|
|||||||
Q_DECLARE_METATYPE(XrefDescription)
|
Q_DECLARE_METATYPE(XrefDescription)
|
||||||
Q_DECLARE_METATYPE(EntrypointDescription)
|
Q_DECLARE_METATYPE(EntrypointDescription)
|
||||||
Q_DECLARE_METATYPE(RBinPluginDescription)
|
Q_DECLARE_METATYPE(RBinPluginDescription)
|
||||||
|
Q_DECLARE_METATYPE(ClassMethodDescription)
|
||||||
|
Q_DECLARE_METATYPE(ClassFieldDescription)
|
||||||
|
Q_DECLARE_METATYPE(ClassDescription)
|
||||||
|
Q_DECLARE_METATYPE(const ClassDescription *)
|
||||||
|
Q_DECLARE_METATYPE(const ClassMethodDescription *)
|
||||||
|
Q_DECLARE_METATYPE(const ClassFieldDescription *)
|
||||||
|
|
||||||
class CutterCore: public QObject
|
class CutterCore: public QObject
|
||||||
{
|
{
|
||||||
@ -313,6 +340,7 @@ public:
|
|||||||
QList<FlagDescription> getAllFlags(QString flagspace = NULL);
|
QList<FlagDescription> getAllFlags(QString flagspace = NULL);
|
||||||
QList<SectionDescription> getAllSections();
|
QList<SectionDescription> getAllSections();
|
||||||
QList<EntrypointDescription> getAllEntrypoint();
|
QList<EntrypointDescription> getAllEntrypoint();
|
||||||
|
QList<ClassDescription> getAllClasses();
|
||||||
|
|
||||||
QList<XrefDescription> getXRefs(RVA addr, bool to, bool whole_function, const QString &filterType = QString::null);
|
QList<XrefDescription> getXRefs(RVA addr, bool to, bool whole_function, const QString &filterType = QString::null);
|
||||||
|
|
||||||
|
@ -85,7 +85,8 @@ SOURCES += \
|
|||||||
dialogs/preferences/PreferencesDialog.cpp \
|
dialogs/preferences/PreferencesDialog.cpp \
|
||||||
dialogs/preferences/GeneralOptionsWidget.cpp \
|
dialogs/preferences/GeneralOptionsWidget.cpp \
|
||||||
dialogs/preferences/GraphOptionsWidget.cpp \
|
dialogs/preferences/GraphOptionsWidget.cpp \
|
||||||
widgets/QuickFilterView.cpp
|
widgets/QuickFilterView.cpp \
|
||||||
|
widgets/ClassesWidget.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
cutter.h \
|
cutter.h \
|
||||||
@ -141,7 +142,8 @@ HEADERS += \
|
|||||||
dialogs/preferences/PreferencesDialog.h \
|
dialogs/preferences/PreferencesDialog.h \
|
||||||
dialogs/preferences/GeneralOptionsWidget.h \
|
dialogs/preferences/GeneralOptionsWidget.h \
|
||||||
dialogs/preferences/GraphOptionsWidget.h \
|
dialogs/preferences/GraphOptionsWidget.h \
|
||||||
widgets/QuickFilterView.h
|
widgets/QuickFilterView.h \
|
||||||
|
widgets/ClassesWidget.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
dialogs/AboutDialog.ui \
|
dialogs/AboutDialog.ui \
|
||||||
@ -175,7 +177,8 @@ FORMS += \
|
|||||||
dialogs/preferences/GeneralOptionsWidget.ui \
|
dialogs/preferences/GeneralOptionsWidget.ui \
|
||||||
dialogs/preferences/GraphOptionsWidget.ui \
|
dialogs/preferences/GraphOptionsWidget.ui \
|
||||||
widgets/QuickFilterView.ui \
|
widgets/QuickFilterView.ui \
|
||||||
widgets/PseudocodeWidget.ui
|
widgets/PseudocodeWidget.ui \
|
||||||
|
widgets/ClassesWidget.ui
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
resources.qrc
|
resources.qrc
|
||||||
|
@ -20,20 +20,24 @@ static QAbstractItemView::ScrollMode scrollMode()
|
|||||||
|
|
||||||
namespace qhelpers
|
namespace qhelpers
|
||||||
{
|
{
|
||||||
void adjustColumns(QTreeWidget *tw, int columnCount, int padding)
|
void adjustColumns(QTreeView *tv, int columnCount, int padding)
|
||||||
{
|
{
|
||||||
const int count = columnCount == 0 ? tw->columnCount() : columnCount;
|
for (int i = 0; i != columnCount; ++i)
|
||||||
for (int i = 0; i != count; ++i)
|
|
||||||
{
|
{
|
||||||
tw->resizeColumnToContents(i);
|
tv->resizeColumnToContents(i);
|
||||||
if (padding > 0)
|
if (padding > 0)
|
||||||
{
|
{
|
||||||
int width = tw->columnWidth(i);
|
int width = tv->columnWidth(i);
|
||||||
tw->setColumnWidth(i, width + padding);
|
tv->setColumnWidth(i, width + padding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void adjustColumns(QTreeWidget *tw, int padding)
|
||||||
|
{
|
||||||
|
adjustColumns(tw, tw->columnCount(), padding);
|
||||||
|
}
|
||||||
|
|
||||||
QTreeWidgetItem *appendRow(QTreeWidget *tw, const QString &str, const QString &str2,
|
QTreeWidgetItem *appendRow(QTreeWidget *tw, const QString &str, const QString &str2,
|
||||||
const QString &str3, const QString &str4, const QString &str5)
|
const QString &str3, const QString &str4, const QString &str5)
|
||||||
{
|
{
|
||||||
|
@ -13,10 +13,12 @@ class QTreeWidgetItem;
|
|||||||
class QAbstractItemView;
|
class QAbstractItemView;
|
||||||
class QAbstractButton;
|
class QAbstractButton;
|
||||||
class QWidget;
|
class QWidget;
|
||||||
|
class QTreeView;
|
||||||
|
|
||||||
namespace qhelpers
|
namespace qhelpers
|
||||||
{
|
{
|
||||||
void adjustColumns(QTreeWidget *tw, int columnCount = 0, int padding = 0);
|
void adjustColumns(QTreeView *tv, int columnCount, int padding);
|
||||||
|
void adjustColumns(QTreeWidget *tw, int padding);
|
||||||
|
|
||||||
QTreeWidgetItem *appendRow(QTreeWidget *tw, const QString &str, const QString &str2 = QString(),
|
QTreeWidgetItem *appendRow(QTreeWidget *tw, const QString &str, const QString &str2 = QString(),
|
||||||
const QString &str3 = QString(), const QString &str4 = QString(), const QString &str5 = QString());
|
const QString &str3 = QString(), const QString &str4 = QString(), const QString &str5 = QString());
|
||||||
|
283
src/widgets/ClassesWidget.cpp
Normal file
283
src/widgets/ClassesWidget.cpp
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
#include "ClassesWidget.h"
|
||||||
|
#include "ui_ClassesWidget.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
|
#include "utils/Helpers.h"
|
||||||
|
|
||||||
|
ClassesModel::ClassesModel(QList<ClassDescription> *classes, QObject *parent)
|
||||||
|
: QAbstractItemModel(parent),
|
||||||
|
classes(classes)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QModelIndex ClassesModel::index(int row, int column, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (!parent.isValid())
|
||||||
|
return createIndex(row, column, (quintptr)0); // root function nodes have id = 0
|
||||||
|
|
||||||
|
return createIndex(row, column, (quintptr)parent.row() + 1); // sub-nodes have id = class index + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex ClassesModel::parent(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid() || index.column() != 0)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
if (index.internalId() == 0) // root function node
|
||||||
|
return QModelIndex();
|
||||||
|
else // sub-node
|
||||||
|
return this->index((int)(index.internalId() - 1), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ClassesModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (!parent.isValid()) // root
|
||||||
|
{
|
||||||
|
return classes->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent.internalId() == 0) // methods/fields
|
||||||
|
{
|
||||||
|
const ClassDescription *cls = &classes->at(parent.row());
|
||||||
|
return cls->methods.length() + cls->fields.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; // below methods/fields
|
||||||
|
}
|
||||||
|
|
||||||
|
int ClassesModel::columnCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return Columns::COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant ClassesModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
const ClassDescription *cls;
|
||||||
|
const ClassMethodDescription *meth = nullptr;
|
||||||
|
const ClassFieldDescription *field = nullptr;
|
||||||
|
if (index.internalId() == 0) // class row
|
||||||
|
{
|
||||||
|
if (index.row() >= classes->count())
|
||||||
|
{
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
cls = &classes->at(index.row());
|
||||||
|
}
|
||||||
|
else // method/field row
|
||||||
|
{
|
||||||
|
cls = &classes->at(static_cast<int>(index.internalId() - 1));
|
||||||
|
|
||||||
|
if (index.row() >= cls->methods.length() + cls->fields.length())
|
||||||
|
{
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index.row() < cls->methods.length())
|
||||||
|
{
|
||||||
|
meth = &cls->methods[index.row()];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
field = &cls->fields[index.row() - cls->methods.length()];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meth)
|
||||||
|
{
|
||||||
|
switch (role)
|
||||||
|
{
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (index.column())
|
||||||
|
{
|
||||||
|
case NAME:
|
||||||
|
return meth->name;
|
||||||
|
case TYPE:
|
||||||
|
return tr("method");
|
||||||
|
case OFFSET:
|
||||||
|
return RAddressString(meth->addr);
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
case OffsetRole:
|
||||||
|
return QVariant::fromValue(meth->addr);
|
||||||
|
case NameRole:
|
||||||
|
return meth->name;
|
||||||
|
case TypeRole:
|
||||||
|
return QVariant::fromValue(METHOD);
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (field)
|
||||||
|
{
|
||||||
|
switch (role)
|
||||||
|
{
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (index.column())
|
||||||
|
{
|
||||||
|
case NAME:
|
||||||
|
return field->name;
|
||||||
|
case TYPE:
|
||||||
|
return tr("field");
|
||||||
|
case OFFSET:
|
||||||
|
return RAddressString(field->addr);
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
case OffsetRole:
|
||||||
|
return QVariant::fromValue(field->addr);
|
||||||
|
case NameRole:
|
||||||
|
return field->name;
|
||||||
|
case TypeRole:
|
||||||
|
return QVariant::fromValue(FIELD);
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (role)
|
||||||
|
{
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (index.column())
|
||||||
|
{
|
||||||
|
case NAME:
|
||||||
|
return cls->name;
|
||||||
|
case TYPE:
|
||||||
|
return tr("class");
|
||||||
|
case OFFSET:
|
||||||
|
return RAddressString(cls->addr);
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
case OffsetRole:
|
||||||
|
return QVariant::fromValue(cls->addr);
|
||||||
|
case NameRole:
|
||||||
|
return cls->name;
|
||||||
|
case TypeRole:
|
||||||
|
return QVariant::fromValue(CLASS);
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant ClassesModel::headerData(int section, Qt::Orientation, int role) const
|
||||||
|
{
|
||||||
|
switch (role)
|
||||||
|
{
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (section)
|
||||||
|
{
|
||||||
|
case NAME:
|
||||||
|
return tr("Name");
|
||||||
|
case TYPE:
|
||||||
|
return tr("Type");
|
||||||
|
case OFFSET:
|
||||||
|
return tr("Offset");
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassesModel::beginReload()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassesModel::endReload()
|
||||||
|
{
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ClassesSortFilterProxyModel::ClassesSortFilterProxyModel(ClassesModel *source_model, QObject *parent)
|
||||||
|
: QSortFilterProxyModel(parent)
|
||||||
|
{
|
||||||
|
setSourceModel(source_model);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClassesSortFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
QModelIndex index = sourceModel()->index(row, 0, parent);
|
||||||
|
return index.data(ClassesModel::NameRole).toString().contains(filterRegExp());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClassesSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||||
|
{
|
||||||
|
switch (left.column())
|
||||||
|
{
|
||||||
|
case ClassesModel::OFFSET:
|
||||||
|
{
|
||||||
|
RVA left_offset = left.data(ClassesModel::OffsetRole).toULongLong();
|
||||||
|
RVA right_offset = right.data(ClassesModel::OffsetRole).toULongLong();
|
||||||
|
if (left_offset != right_offset)
|
||||||
|
return left_offset < right_offset;
|
||||||
|
}
|
||||||
|
// fallthrough
|
||||||
|
case ClassesModel::TYPE:
|
||||||
|
{
|
||||||
|
auto left_type = left.data(ClassesModel::TypeRole).value<ClassesModel::RowType>();
|
||||||
|
auto right_type = right.data(ClassesModel::TypeRole).value<ClassesModel::RowType>();
|
||||||
|
if (left_type != right_type)
|
||||||
|
return left_type < right_type;
|
||||||
|
}
|
||||||
|
// fallthrough
|
||||||
|
case ClassesModel::NAME:
|
||||||
|
default:
|
||||||
|
QString left_name = left.data(ClassesModel::NameRole).toString();
|
||||||
|
QString right_name = right.data(ClassesModel::NameRole).toString();
|
||||||
|
return left_name < right_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ClassesWidget::ClassesWidget(MainWindow *main, QWidget *parent) :
|
||||||
|
QDockWidget(parent),
|
||||||
|
ui(new Ui::ClassesWidget),
|
||||||
|
main(main)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
// Radare core found in:
|
||||||
|
this->main = main;
|
||||||
|
|
||||||
|
model = new ClassesModel(&classes, this);
|
||||||
|
proxy_model = new ClassesSortFilterProxyModel(model, this);
|
||||||
|
ui->classesTreeView->setModel(proxy_model);
|
||||||
|
ui->classesTreeView->sortByColumn(ClassesModel::TYPE, Qt::AscendingOrder);
|
||||||
|
|
||||||
|
connect(Core(), SIGNAL(refreshAll()), this, SLOT(refreshClasses()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassesWidget::~ClassesWidget() {}
|
||||||
|
|
||||||
|
void ClassesWidget::refreshClasses()
|
||||||
|
{
|
||||||
|
model->beginReload();
|
||||||
|
classes = CutterCore::getInstance()->getAllClasses();
|
||||||
|
model->endReload();
|
||||||
|
|
||||||
|
ui->classesTreeView->resizeColumnToContents(0);
|
||||||
|
ui->classesTreeView->resizeColumnToContents(1);
|
||||||
|
ui->classesTreeView->resizeColumnToContents(2);
|
||||||
|
|
||||||
|
ui->classesTreeView->setColumnWidth(0, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassesWidget::on_classesTreeView_doubleClicked(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
RVA offset = index.data(ClassesModel::OffsetRole).value<RVA>();
|
||||||
|
CutterCore::getInstance()->seek(offset);
|
||||||
|
}
|
95
src/widgets/ClassesWidget.h
Normal file
95
src/widgets/ClassesWidget.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#ifndef CLASSWSWIDGET_H
|
||||||
|
#define CLASSWSWIDGET_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "cutter.h"
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QDockWidget>
|
||||||
|
|
||||||
|
class MainWindow;
|
||||||
|
class QTreeWidget;
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class ClassesWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class MainWindow;
|
||||||
|
class QTreeWidgetItem;
|
||||||
|
|
||||||
|
|
||||||
|
class ClassesModel: public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<ClassDescription> *classes;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Columns { NAME = 0, TYPE, OFFSET, COUNT };
|
||||||
|
enum RowType { CLASS = 0, METHOD = 1, FIELD = 2 };
|
||||||
|
|
||||||
|
static const int OffsetRole = Qt::UserRole;
|
||||||
|
static const int NameRole = Qt::UserRole + 1;
|
||||||
|
static const int TypeRole = Qt::UserRole + 2;
|
||||||
|
|
||||||
|
explicit ClassesModel(QList<ClassDescription> *classes, QObject *parent = 0);
|
||||||
|
|
||||||
|
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QModelIndex parent(const QModelIndex &index) const override;
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
void beginReload();
|
||||||
|
void endReload();
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(ClassesModel::RowType);
|
||||||
|
|
||||||
|
|
||||||
|
class ClassesSortFilterProxyModel : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ClassesSortFilterProxyModel(ClassesModel *source_model, QObject *parent = 0);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool filterAcceptsRow(int row, const QModelIndex &parent) const override;
|
||||||
|
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ClassesWidget : public QDockWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ClassesWidget(MainWindow *main, QWidget *parent = 0);
|
||||||
|
~ClassesWidget();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_classesTreeView_doubleClicked(const QModelIndex &index);
|
||||||
|
|
||||||
|
void refreshClasses();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::ClassesWidget> ui;
|
||||||
|
MainWindow *main;
|
||||||
|
|
||||||
|
ClassesModel *model;
|
||||||
|
ClassesSortFilterProxyModel *proxy_model;
|
||||||
|
QList<ClassDescription> classes;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CLASSWSWIDGET_H
|
58
src/widgets/ClassesWidget.ui
Normal file
58
src/widgets/ClassesWidget.ui
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ClassesWidget</class>
|
||||||
|
<widget class="QDockWidget" name="ClassesWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string notr="true">Classes</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="classesTreeView">
|
||||||
|
<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="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="expandsOnDoubleClick">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@ -162,7 +162,7 @@ void CommentsWidget::refreshTree()
|
|||||||
|
|
||||||
nestedComments[fcn_name].append(comment);
|
nestedComments[fcn_name].append(comment);
|
||||||
}
|
}
|
||||||
qhelpers::adjustColumns(ui->commentsTreeWidget);
|
qhelpers::adjustColumns(ui->commentsTreeWidget, 0);
|
||||||
|
|
||||||
// Add nested comments
|
// Add nested comments
|
||||||
ui->nestedCmtsTreeWidget->clear();
|
ui->nestedCmtsTreeWidget->clear();
|
||||||
@ -180,5 +180,5 @@ void CommentsWidget::refreshTree()
|
|||||||
}
|
}
|
||||||
ui->nestedCmtsTreeWidget->addTopLevelItem(item);
|
ui->nestedCmtsTreeWidget->addTopLevelItem(item);
|
||||||
}
|
}
|
||||||
qhelpers::adjustColumns(ui->nestedCmtsTreeWidget);
|
qhelpers::adjustColumns(ui->nestedCmtsTreeWidget, 0);
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ void RelocsWidget::fillTreeWidget()
|
|||||||
ui->relocsTreeWidget->addTopLevelItem(item);
|
ui->relocsTreeWidget->addTopLevelItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
qhelpers::adjustColumns(ui->relocsTreeWidget);
|
qhelpers::adjustColumns(ui->relocsTreeWidget, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelocsWidget::setScrollMode()
|
void RelocsWidget::setScrollMode()
|
||||||
|
@ -34,7 +34,7 @@ void SectionsWidget::refreshSections()
|
|||||||
fillSections(row++, section);
|
fillSections(row++, section);
|
||||||
}
|
}
|
||||||
|
|
||||||
qhelpers::adjustColumns(tree);
|
qhelpers::adjustColumns(tree, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SectionsWidget::setupViews()
|
void SectionsWidget::setupViews()
|
||||||
|
@ -44,7 +44,7 @@ void SymbolsWidget::fillSymbols()
|
|||||||
item->setData(0, Qt::UserRole, QVariant::fromValue(symbol));
|
item->setData(0, Qt::UserRole, QVariant::fromValue(symbol));
|
||||||
ui->symbolsTreeWidget->addTopLevelItem(item);
|
ui->symbolsTreeWidget->addTopLevelItem(item);
|
||||||
}
|
}
|
||||||
qhelpers::adjustColumns(ui->symbolsTreeWidget);
|
qhelpers::adjustColumns(ui->symbolsTreeWidget, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolsWidget::setScrollMode()
|
void SymbolsWidget::setScrollMode()
|
||||||
|
Loading…
Reference in New Issue
Block a user