mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-18 10:56:11 +00:00
Make ClassesWidget a ListDockWidget (#3152)
Adds Quick Filter and generic address-based context menu entries to the existing ClassesWidget. The original ClassesWidget.ui is not used anymore as the layout is provided by ListDockWidget and only adjusted. The AddressableItemContextMenu may now also optionally be shown when there no currently selected item by using setShowItemContextMenuWithoutAddress(). This is used e.g. to display the "Create Class" option when nothing is present in the list. Fixes #2237 Co-authored-by: Tristan Crawford <tristanthtcrawford@gmail.com>
This commit is contained in:
parent
d3ee310a21
commit
1f133741ab
@ -338,7 +338,6 @@ set(UI_FILES
|
||||
dialogs/preferences/InitializationFileEditor.ui
|
||||
widgets/QuickFilterView.ui
|
||||
widgets/DecompilerWidget.ui
|
||||
widgets/ClassesWidget.ui
|
||||
widgets/VTablesWidget.ui
|
||||
widgets/TypesWidget.ui
|
||||
widgets/SearchWidget.ui
|
||||
|
@ -13,11 +13,17 @@ AddressableFilterProxyModel::AddressableFilterProxyModel(AddressableItemModelI *
|
||||
|
||||
RVA AddressableFilterProxyModel::address(const QModelIndex &index) const
|
||||
{
|
||||
if (!addressableSourceModel) {
|
||||
return RVA_INVALID;
|
||||
}
|
||||
return addressableSourceModel->address(this->mapToSource(index));
|
||||
}
|
||||
|
||||
QString AddressableFilterProxyModel::name(const QModelIndex &index) const
|
||||
{
|
||||
if (!addressableSourceModel) {
|
||||
return QString();
|
||||
}
|
||||
return addressableSourceModel->name(this->mapToSource(index));
|
||||
}
|
||||
|
||||
@ -28,6 +34,6 @@ void AddressableFilterProxyModel::setSourceModel(QAbstractItemModel *)
|
||||
|
||||
void AddressableFilterProxyModel::setSourceModel(AddressableItemModelI *sourceModel)
|
||||
{
|
||||
ParentClass::setSourceModel(sourceModel->asItemModel());
|
||||
ParentClass::setSourceModel(sourceModel ? sourceModel->asItemModel() : nullptr);
|
||||
addressableSourceModel = sourceModel;
|
||||
}
|
||||
|
@ -112,7 +112,8 @@ void AddressableItemContextMenu::aboutToShowSlot()
|
||||
void AddressableItemContextMenu::setHasTarget(bool hasTarget)
|
||||
{
|
||||
this->hasTarget = hasTarget;
|
||||
for (const auto &action : this->actions()) {
|
||||
action->setEnabled(hasTarget);
|
||||
}
|
||||
actionShowInMenu->setEnabled(hasTarget);
|
||||
actionCopyAddress->setEnabled(hasTarget);
|
||||
actionShowXrefs->setEnabled(hasTarget);
|
||||
actionAddcomment->setEnabled(hasTarget);
|
||||
}
|
||||
|
@ -57,16 +57,30 @@ public:
|
||||
itemContextMenu = menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is set to true, the context menu will also be shown if no item
|
||||
* is currently selected.
|
||||
*/
|
||||
void setShowItemContextMenuWithoutAddress(bool val) { showItemContextMenuWithoutAddress = val; }
|
||||
|
||||
protected:
|
||||
virtual void showItemContextMenu(const QPoint &pt)
|
||||
{
|
||||
if (!itemContextMenu) {
|
||||
return;
|
||||
}
|
||||
auto index = this->currentIndex();
|
||||
if (index.isValid() && itemContextMenu) {
|
||||
if (index.isValid()) {
|
||||
auto offset = addressableModel->address(index);
|
||||
auto name = addressableModel->name(index);
|
||||
itemContextMenu->setTarget(offset, name);
|
||||
itemContextMenu->exec(this->mapToGlobal(pt));
|
||||
} else {
|
||||
if (!showItemContextMenuWithoutAddress) {
|
||||
return;
|
||||
}
|
||||
itemContextMenu->clearTarget();
|
||||
}
|
||||
itemContextMenu->exec(this->mapToGlobal(pt));
|
||||
}
|
||||
|
||||
virtual void onItemActivated(const QModelIndex &index)
|
||||
@ -90,6 +104,7 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
bool showItemContextMenuWithoutAddress = false;
|
||||
AddressableItemModelI *addressableModel = nullptr;
|
||||
AddressableItemContextMenu *itemContextMenu = nullptr;
|
||||
MainWindow *mainWindow = nullptr;
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "ClassesWidget.h"
|
||||
#include "core/MainWindow.h"
|
||||
#include "ui_ClassesWidget.h"
|
||||
#include "ui_ListDockWidget.h"
|
||||
#include "common/Helpers.h"
|
||||
#include "common/SvgIconEngine.h"
|
||||
#include "dialogs/EditMethodDialog.h"
|
||||
@ -9,6 +9,8 @@
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QInputDialog>
|
||||
#include <QShortcut>
|
||||
#include <QComboBox>
|
||||
|
||||
QVariant ClassesModel::headerData(int section, Qt::Orientation, int role) const
|
||||
{
|
||||
@ -33,6 +35,17 @@ QVariant ClassesModel::headerData(int section, Qt::Orientation, int role) const
|
||||
}
|
||||
}
|
||||
|
||||
RVA ClassesModel::address(const QModelIndex &index) const
|
||||
{
|
||||
QVariant v = data(index, OffsetRole);
|
||||
return v.isValid() ? v.toULongLong() : RVA_INVALID;
|
||||
}
|
||||
|
||||
QString ClassesModel::name(const QModelIndex &index) const
|
||||
{
|
||||
return data(index, NameRole).toString();
|
||||
}
|
||||
|
||||
BinClassesModel::BinClassesModel(QObject *parent) : ClassesModel(parent) {}
|
||||
|
||||
void BinClassesModel::setClasses(const QList<BinClassDescription> &classes)
|
||||
@ -526,12 +539,17 @@ QVariant AnalysisClassesModel::data(const QModelIndex &index, int role) const
|
||||
}
|
||||
|
||||
ClassesSortFilterProxyModel::ClassesSortFilterProxyModel(QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
: AddressableFilterProxyModel(nullptr, parent)
|
||||
{
|
||||
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
bool ClassesSortFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return true;
|
||||
|
||||
QModelIndex index = sourceModel()->index(row, 0, parent);
|
||||
return qhelpers::filterStringContains(index.data(ClassesModel::NameRole).toString(), this);
|
||||
}
|
||||
@ -576,23 +594,63 @@ bool ClassesSortFilterProxyModel::hasChildren(const QModelIndex &parent) const
|
||||
return !parent.isValid() || !parent.parent().isValid();
|
||||
}
|
||||
|
||||
ClassesWidget::ClassesWidget(MainWindow *main) : CutterDockWidget(main), ui(new Ui::ClassesWidget)
|
||||
ClassesWidget::ClassesWidget(MainWindow *main)
|
||||
: ListDockWidget(main),
|
||||
seekToVTableAction(tr("Seek to VTable"), this),
|
||||
editMethodAction(tr("Edit Method"), this),
|
||||
addMethodAction(tr("Add Method"), this),
|
||||
newClassAction(tr("Create new Class"), this),
|
||||
renameClassAction(tr("Rename Class"), this),
|
||||
deleteClassAction(tr("Delete Class"), this)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowTitle(tr("Classes"));
|
||||
setObjectName("ClassesWidget");
|
||||
|
||||
ui->classesTreeView->setIconSize(QSize(10, 10));
|
||||
ui->treeView->setIconSize(QSize(10, 10));
|
||||
|
||||
proxy_model = new ClassesSortFilterProxyModel(this);
|
||||
ui->classesTreeView->setModel(proxy_model);
|
||||
ui->classesTreeView->sortByColumn(ClassesModel::TYPE, Qt::AscendingOrder);
|
||||
ui->classesTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
setModels(proxy_model);
|
||||
|
||||
ui->classSourceCombo->setCurrentIndex(1);
|
||||
classSourceCombo = new QComboBox(this);
|
||||
// User an intermediate single-child layout to contain the combo box, otherwise
|
||||
// when the combo box is inserted directly, the entire vertical layout gets a
|
||||
// weird horizontal padding on macOS.
|
||||
QBoxLayout *comboLayout = new QBoxLayout(QBoxLayout::Direction::LeftToRight, nullptr);
|
||||
comboLayout->addWidget(classSourceCombo);
|
||||
ui->verticalLayout->insertLayout(ui->verticalLayout->indexOf(ui->quickFilterView), comboLayout);
|
||||
classSourceCombo->addItem(tr("Binary Info (Fixed)"));
|
||||
classSourceCombo->addItem(tr("Analysis (Editable)"));
|
||||
classSourceCombo->setCurrentIndex(1);
|
||||
|
||||
connect<void (QComboBox::*)(int)>(ui->classSourceCombo, &QComboBox::currentIndexChanged, this,
|
||||
connect<void (QComboBox::*)(int)>(classSourceCombo, &QComboBox::currentIndexChanged, this,
|
||||
&ClassesWidget::refreshClasses);
|
||||
connect(ui->classesTreeView, &QTreeView::customContextMenuRequested, this,
|
||||
&ClassesWidget::showContextMenu);
|
||||
|
||||
connect(&seekToVTableAction, &QAction::triggered, this,
|
||||
&ClassesWidget::seekToVTableActionTriggered);
|
||||
connect(&editMethodAction, &QAction::triggered, this,
|
||||
&ClassesWidget::editMethodActionTriggered);
|
||||
connect(&addMethodAction, &QAction::triggered, this, &ClassesWidget::addMethodActionTriggered);
|
||||
connect(&newClassAction, &QAction::triggered, this, &ClassesWidget::newClassActionTriggered);
|
||||
connect(&renameClassAction, &QAction::triggered, this,
|
||||
&ClassesWidget::renameClassActionTriggered);
|
||||
connect(&deleteClassAction, &QAction::triggered, this,
|
||||
&ClassesWidget::deleteClassActionTriggered);
|
||||
|
||||
// Build context menu like this:
|
||||
// class-related actions
|
||||
// -- classesMethodsSeparator
|
||||
// method-related actions
|
||||
// -- separator
|
||||
// default actions from AddressableItemList
|
||||
auto contextMenu = ui->treeView->getItemContextMenu();
|
||||
contextMenu->insertSeparator(contextMenu->actions().first());
|
||||
contextMenu->insertActions(contextMenu->actions().first(),
|
||||
{ &addMethodAction, &editMethodAction, &seekToVTableAction });
|
||||
classesMethodsSeparator = contextMenu->insertSeparator(contextMenu->actions().first());
|
||||
contextMenu->insertActions(classesMethodsSeparator,
|
||||
{ &newClassAction, &renameClassAction, &deleteClassAction });
|
||||
connect(contextMenu, &QMenu::aboutToShow, this, &ClassesWidget::updateActions);
|
||||
ui->treeView->setShowItemContextMenuWithoutAddress(true);
|
||||
|
||||
refreshClasses();
|
||||
}
|
||||
@ -601,7 +659,7 @@ ClassesWidget::~ClassesWidget() {}
|
||||
|
||||
ClassesWidget::Source ClassesWidget::getSource()
|
||||
{
|
||||
switch (ui->classSourceCombo->currentIndex()) {
|
||||
switch (classSourceCombo->currentIndex()) {
|
||||
case 0:
|
||||
return Source::BIN;
|
||||
default:
|
||||
@ -614,88 +672,68 @@ void ClassesWidget::refreshClasses()
|
||||
switch (getSource()) {
|
||||
case Source::BIN:
|
||||
if (!bin_model) {
|
||||
proxy_model->setSourceModel(nullptr);
|
||||
proxy_model->setSourceModel(static_cast<AddressableItemModelI *>(nullptr));
|
||||
delete analysis_model;
|
||||
analysis_model = nullptr;
|
||||
bin_model = new BinClassesModel(this);
|
||||
proxy_model->setSourceModel(bin_model);
|
||||
proxy_model->setSourceModel(static_cast<AddressableItemModelI *>(bin_model));
|
||||
}
|
||||
bin_model->setClasses(Core()->getAllClassesFromBin());
|
||||
break;
|
||||
case Source::ANALYSIS:
|
||||
if (!analysis_model) {
|
||||
proxy_model->setSourceModel(nullptr);
|
||||
proxy_model->setSourceModel(static_cast<AddressableItemModelI *>(nullptr));
|
||||
delete bin_model;
|
||||
bin_model = nullptr;
|
||||
analysis_model = new AnalysisClassesModel(this);
|
||||
proxy_model->setSourceModel(analysis_model);
|
||||
proxy_model->setSourceModel(static_cast<AddressableItemModelI *>(analysis_model));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
qhelpers::adjustColumns(ui->classesTreeView, 3, 0);
|
||||
qhelpers::adjustColumns(ui->treeView, 3, 0);
|
||||
|
||||
ui->classesTreeView->setColumnWidth(0, 200);
|
||||
ui->treeView->setColumnWidth(0, 200);
|
||||
}
|
||||
|
||||
void ClassesWidget::on_classesTreeView_doubleClicked(const QModelIndex &index)
|
||||
void ClassesWidget::updateActions()
|
||||
{
|
||||
if (!index.isValid())
|
||||
return;
|
||||
bool isAnalysis = !!analysis_model;
|
||||
newClassAction.setVisible(isAnalysis);
|
||||
addMethodAction.setVisible(isAnalysis);
|
||||
|
||||
QVariant offsetData = index.data(ClassesModel::OffsetRole);
|
||||
if (!offsetData.isValid()) {
|
||||
return;
|
||||
}
|
||||
RVA offset = offsetData.value<RVA>();
|
||||
Core()->seekAndShow(offset);
|
||||
}
|
||||
|
||||
void ClassesWidget::showContextMenu(const QPoint &pt)
|
||||
{
|
||||
if (!analysis_model) {
|
||||
// no context menu for bin classes
|
||||
return;
|
||||
bool rowIsAnalysisClass = false;
|
||||
bool rowIsAnalysisMethod = false;
|
||||
QModelIndex index = ui->treeView->selectionModel()->currentIndex();
|
||||
if (isAnalysis && index.isValid()) {
|
||||
auto type = static_cast<ClassesModel::RowType>(index.data(ClassesModel::TypeRole).toInt());
|
||||
rowIsAnalysisClass = type == ClassesModel::RowType::Class;
|
||||
rowIsAnalysisMethod = type == ClassesModel::RowType::Method;
|
||||
}
|
||||
|
||||
QModelIndex index = ui->classesTreeView->selectionModel()->currentIndex();
|
||||
if (!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
auto type = static_cast<ClassesModel::RowType>(index.data(ClassesModel::TypeRole).toInt());
|
||||
renameClassAction.setVisible(rowIsAnalysisClass);
|
||||
deleteClassAction.setVisible(rowIsAnalysisClass);
|
||||
|
||||
QMenu menu(ui->classesTreeView);
|
||||
|
||||
menu.addAction(ui->newClassAction);
|
||||
|
||||
if (type == ClassesModel::RowType::Class) {
|
||||
menu.addAction(ui->renameClassAction);
|
||||
menu.addAction(ui->deleteClassAction);
|
||||
}
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
menu.addAction(ui->addMethodAction);
|
||||
|
||||
if (type == ClassesModel::RowType::Method) {
|
||||
menu.addAction(ui->editMethodAction);
|
||||
classesMethodsSeparator->setVisible(rowIsAnalysisClass || rowIsAnalysisMethod);
|
||||
|
||||
editMethodAction.setVisible(rowIsAnalysisMethod);
|
||||
bool rowHasVTable = false;
|
||||
if (rowIsAnalysisMethod) {
|
||||
QString className = index.parent().data(ClassesModel::NameRole).toString();
|
||||
QString methodName = index.data(ClassesModel::NameRole).toString();
|
||||
AnalysisMethodDescription desc;
|
||||
if (Core()->getAnalysisMethod(className, methodName, &desc)) {
|
||||
if (desc.vtableOffset >= 0) {
|
||||
menu.addAction(ui->seekToVTableAction);
|
||||
rowHasVTable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
menu.exec(ui->classesTreeView->mapToGlobal(pt));
|
||||
seekToVTableAction.setVisible(rowHasVTable);
|
||||
}
|
||||
|
||||
void ClassesWidget::on_seekToVTableAction_triggered()
|
||||
void ClassesWidget::seekToVTableActionTriggered()
|
||||
{
|
||||
QModelIndex index = ui->classesTreeView->selectionModel()->currentIndex();
|
||||
QModelIndex index = ui->treeView->selectionModel()->currentIndex();
|
||||
QString className = index.parent().data(ClassesModel::NameRole).toString();
|
||||
|
||||
QList<AnalysisVTableDescription> vtables = Core()->getAnalysisClassVTables(className);
|
||||
@ -714,9 +752,9 @@ void ClassesWidget::on_seekToVTableAction_triggered()
|
||||
Core()->seekAndShow(vtables[0].addr + desc.vtableOffset);
|
||||
}
|
||||
|
||||
void ClassesWidget::on_addMethodAction_triggered()
|
||||
void ClassesWidget::addMethodActionTriggered()
|
||||
{
|
||||
QModelIndex index = ui->classesTreeView->selectionModel()->currentIndex();
|
||||
QModelIndex index = ui->treeView->selectionModel()->currentIndex();
|
||||
if (!index.isValid()) {
|
||||
return;
|
||||
}
|
||||
@ -732,9 +770,9 @@ void ClassesWidget::on_addMethodAction_triggered()
|
||||
EditMethodDialog::newMethod(className, QString(), this);
|
||||
}
|
||||
|
||||
void ClassesWidget::on_editMethodAction_triggered()
|
||||
void ClassesWidget::editMethodActionTriggered()
|
||||
{
|
||||
QModelIndex index = ui->classesTreeView->selectionModel()->currentIndex();
|
||||
QModelIndex index = ui->treeView->selectionModel()->currentIndex();
|
||||
if (!index.isValid()
|
||||
|| index.data(ClassesModel::TypeRole).toInt()
|
||||
!= static_cast<int>(ClassesModel::RowType::Method)) {
|
||||
@ -745,7 +783,7 @@ void ClassesWidget::on_editMethodAction_triggered()
|
||||
EditMethodDialog::editMethod(className, methName, this);
|
||||
}
|
||||
|
||||
void ClassesWidget::on_newClassAction_triggered()
|
||||
void ClassesWidget::newClassActionTriggered()
|
||||
{
|
||||
bool ok;
|
||||
QString name = QInputDialog::getText(this, tr("Create new Class"), tr("Class Name:"),
|
||||
@ -755,9 +793,9 @@ void ClassesWidget::on_newClassAction_triggered()
|
||||
}
|
||||
}
|
||||
|
||||
void ClassesWidget::on_deleteClassAction_triggered()
|
||||
void ClassesWidget::deleteClassActionTriggered()
|
||||
{
|
||||
QModelIndex index = ui->classesTreeView->selectionModel()->currentIndex();
|
||||
QModelIndex index = ui->treeView->selectionModel()->currentIndex();
|
||||
if (!index.isValid()
|
||||
|| index.data(ClassesModel::TypeRole).toInt()
|
||||
!= static_cast<int>(ClassesModel::RowType::Class)) {
|
||||
@ -772,9 +810,9 @@ void ClassesWidget::on_deleteClassAction_triggered()
|
||||
Core()->deleteClass(className);
|
||||
}
|
||||
|
||||
void ClassesWidget::on_renameClassAction_triggered()
|
||||
void ClassesWidget::renameClassActionTriggered()
|
||||
{
|
||||
QModelIndex index = ui->classesTreeView->selectionModel()->currentIndex();
|
||||
QModelIndex index = ui->treeView->selectionModel()->currentIndex();
|
||||
if (!index.isValid()
|
||||
|| index.data(ClassesModel::TypeRole).toInt()
|
||||
!= static_cast<int>(ClassesModel::RowType::Class)) {
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "core/Cutter.h"
|
||||
#include "CutterDockWidget.h"
|
||||
#include "widgets/ListDockWidget.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
@ -21,7 +22,7 @@ class ClassesWidget;
|
||||
/**
|
||||
* @brief Common abstract base class for Bin and Anal classes models
|
||||
*/
|
||||
class ClassesModel : public QAbstractItemModel
|
||||
class ClassesModel : public AddressableItemModel<>
|
||||
{
|
||||
public:
|
||||
enum Columns { NAME = 0, REAL_NAME, TYPE, OFFSET, VTABLE, COUNT };
|
||||
@ -69,10 +70,13 @@ public:
|
||||
*/
|
||||
static const int RealNameRole = Qt::UserRole + 4;
|
||||
|
||||
explicit ClassesModel(QObject *parent = nullptr) : QAbstractItemModel(parent) {}
|
||||
explicit ClassesModel(QObject *parent = nullptr) : AddressableItemModel(parent) {}
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const override;
|
||||
|
||||
RVA address(const QModelIndex &index) const override;
|
||||
QString name(const QModelIndex &index) const override;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(ClassesModel::RowType)
|
||||
@ -163,7 +167,7 @@ public slots:
|
||||
void classAttrsChanged(const QString &cls);
|
||||
};
|
||||
|
||||
class ClassesSortFilterProxyModel : public QSortFilterProxyModel
|
||||
class ClassesSortFilterProxyModel : public AddressableFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -176,7 +180,7 @@ protected:
|
||||
bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
|
||||
};
|
||||
|
||||
class ClassesWidget : public CutterDockWidget
|
||||
class ClassesWidget : public ListDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -185,29 +189,34 @@ public:
|
||||
~ClassesWidget();
|
||||
|
||||
private slots:
|
||||
void on_classesTreeView_doubleClicked(const QModelIndex &index);
|
||||
|
||||
void on_seekToVTableAction_triggered();
|
||||
void on_addMethodAction_triggered();
|
||||
void on_editMethodAction_triggered();
|
||||
void on_newClassAction_triggered();
|
||||
void on_deleteClassAction_triggered();
|
||||
void on_renameClassAction_triggered();
|
||||
|
||||
void showContextMenu(const QPoint &pt);
|
||||
void seekToVTableActionTriggered();
|
||||
void editMethodActionTriggered();
|
||||
void addMethodActionTriggered();
|
||||
void newClassActionTriggered();
|
||||
void renameClassActionTriggered();
|
||||
void deleteClassActionTriggered();
|
||||
|
||||
void refreshClasses();
|
||||
void updateActions();
|
||||
|
||||
private:
|
||||
enum class Source { BIN, ANALYSIS };
|
||||
|
||||
Source getSource();
|
||||
|
||||
std::unique_ptr<Ui::ClassesWidget> ui;
|
||||
|
||||
BinClassesModel *bin_model = nullptr;
|
||||
AnalysisClassesModel *analysis_model = nullptr;
|
||||
ClassesSortFilterProxyModel *proxy_model;
|
||||
|
||||
QComboBox *classSourceCombo;
|
||||
|
||||
QAction seekToVTableAction;
|
||||
QAction editMethodAction;
|
||||
QAction addMethodAction;
|
||||
QAction newClassAction;
|
||||
QAction renameClassAction;
|
||||
QAction deleteClassAction;
|
||||
QAction *classesMethodsSeparator;
|
||||
};
|
||||
|
||||
#endif // CLASSESWIDGET_H
|
||||
|
@ -1,148 +0,0 @@
|
||||
<?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="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<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="CutterTreeView" name="classesTreeView">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">CutterTreeView::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>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_17">
|
||||
<property name="spacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="classSourceLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Source:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="classSourceCombo">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Binary Info (Fixed)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Analysis (Editable)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<action name="seekToVTableAction">
|
||||
<property name="text">
|
||||
<string>Seek to VTable</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="editMethodAction">
|
||||
<property name="text">
|
||||
<string>Edit Method</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="addMethodAction">
|
||||
<property name="text">
|
||||
<string>Add Method</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="newClassAction">
|
||||
<property name="text">
|
||||
<string>Create new Class</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="renameClassAction">
|
||||
<property name="text">
|
||||
<string>Rename Class</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="deleteClassAction">
|
||||
<property name="text">
|
||||
<string>Delete Class</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>CutterTreeView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>widgets/CutterTreeView.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -2,7 +2,6 @@
|
||||
#include "ui_ListDockWidget.h"
|
||||
#include "core/MainWindow.h"
|
||||
#include "common/Helpers.h"
|
||||
#include "menus/AddressableItemContextMenu.h"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QResizeEvent>
|
||||
|
Loading…
Reference in New Issue
Block a user