mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-19 10:58:51 +00:00
parent
bb80cbd862
commit
06aceaf9b1
@ -70,7 +70,7 @@ static void initializeSettings()
|
|||||||
qInfo() << "Migrating Settings to Version" << v;
|
qInfo() << "Migrating Settings to Version" << v;
|
||||||
switch (v) {
|
switch (v) {
|
||||||
case 1:
|
case 1:
|
||||||
migrateSettingsTo1(settings);
|
migrateSettingsTo1(settings); break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,13 @@ CutterSeekable::CutterSeekable(QObject *parent)
|
|||||||
|
|
||||||
CutterSeekable::~CutterSeekable() {}
|
CutterSeekable::~CutterSeekable() {}
|
||||||
|
|
||||||
|
void CutterSeekable::setSynchronization(bool sync)
|
||||||
|
{
|
||||||
|
synchronized = sync;
|
||||||
|
onCoreSeekChanged(Core()->getOffset());
|
||||||
|
emit syncChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void CutterSeekable::onCoreSeekChanged(RVA addr)
|
void CutterSeekable::onCoreSeekChanged(RVA addr)
|
||||||
{
|
{
|
||||||
if (synchronized && widgetOffset != addr) {
|
if (synchronized && widgetOffset != addr) {
|
||||||
@ -48,8 +55,7 @@ RVA CutterSeekable::getOffset()
|
|||||||
|
|
||||||
void CutterSeekable::toggleSynchronization()
|
void CutterSeekable::toggleSynchronization()
|
||||||
{
|
{
|
||||||
synchronized = !synchronized;
|
setSynchronization(!synchronized);
|
||||||
onCoreSeekChanged(Core()->getOffset());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CutterSeekable::isSynchronized()
|
bool CutterSeekable::isSynchronized()
|
||||||
|
@ -23,10 +23,10 @@ public:
|
|||||||
void seek(RVA addr) { updateSeek(addr, false); }
|
void seek(RVA addr) { updateSeek(addr, false); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief toggleSyncWithCore toggles
|
* @brief setSynchronization sets
|
||||||
* Core seek synchronization.
|
* Core seek synchronization.
|
||||||
*/
|
*/
|
||||||
void toggleSynchronization();
|
void setSynchronization(bool sync);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief getOffset returns the seekable offset.
|
* @brief getOffset returns the seekable offset.
|
||||||
@ -50,6 +50,12 @@ public slots:
|
|||||||
*/
|
*/
|
||||||
void seekPrev();
|
void seekPrev();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief toggleSyncWithCore toggles
|
||||||
|
* Core seek synchronization.
|
||||||
|
*/
|
||||||
|
void toggleSynchronization();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
/**
|
/**
|
||||||
* @brief onCoreSeekChanged
|
* @brief onCoreSeekChanged
|
||||||
@ -82,5 +88,5 @@ private:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void seekableSeekChanged(RVA addr);
|
void seekableSeekChanged(RVA addr);
|
||||||
|
void syncChanged();
|
||||||
};
|
};
|
||||||
|
@ -106,6 +106,9 @@
|
|||||||
#include <QGraphicsScene>
|
#include <QGraphicsScene>
|
||||||
#include <QGraphicsView>
|
#include <QGraphicsView>
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T* getNewInstance(MainWindow *m, QAction *a) { return new T(m, a); }
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent) :
|
MainWindow::MainWindow(QWidget *parent) :
|
||||||
QMainWindow(parent),
|
QMainWindow(parent),
|
||||||
core(Core()),
|
core(Core()),
|
||||||
@ -124,9 +127,21 @@ void MainWindow::initUI()
|
|||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
connect(ui->actionExtraGraph, &QAction::triggered, this, &MainWindow::addExtraGraph);
|
||||||
|
connect(ui->actionExtraDisassembly, &QAction::triggered, this, &MainWindow::addExtraDisassembly);
|
||||||
|
connect(ui->actionExtraHexdump, &QAction::triggered, this, &MainWindow::addExtraHexdump);
|
||||||
|
|
||||||
|
classNameToConstructorAndActionMap.insert(GraphWidget::getWidgetType(),
|
||||||
|
{getNewInstance<GraphWidget>, ui->actionGraph});
|
||||||
|
classNameToConstructorAndActionMap.insert(DisassemblyWidget::getWidgetType(),
|
||||||
|
{getNewInstance<DisassemblyWidget>, ui->actionDisassembly});
|
||||||
|
classNameToConstructorAndActionMap.insert(HexdumpWidget::getWidgetType(),
|
||||||
|
{getNewInstance<HexdumpWidget>, ui->actionHexdump});
|
||||||
|
|
||||||
initToolBar();
|
initToolBar();
|
||||||
initDocks();
|
initDocks();
|
||||||
|
|
||||||
|
emptyState = saveState();
|
||||||
/*
|
/*
|
||||||
* Some global shortcuts
|
* Some global shortcuts
|
||||||
*/
|
*/
|
||||||
@ -251,8 +266,6 @@ void MainWindow::initToolBar()
|
|||||||
void MainWindow::initDocks()
|
void MainWindow::initDocks()
|
||||||
{
|
{
|
||||||
dockWidgets.reserve(20);
|
dockWidgets.reserve(20);
|
||||||
disassemblyDock = new DisassemblyWidget(this, ui->actionDisassembly);
|
|
||||||
hexdumpDock = new HexdumpWidget(this, ui->actionHexdump);
|
|
||||||
pseudocodeDock = new PseudocodeWidget(this, ui->actionPseudocode);
|
pseudocodeDock = new PseudocodeWidget(this, ui->actionPseudocode);
|
||||||
consoleDock = new ConsoleWidget(this, ui->actionConsole);
|
consoleDock = new ConsoleWidget(this, ui->actionConsole);
|
||||||
|
|
||||||
@ -271,7 +284,6 @@ void MainWindow::initDocks()
|
|||||||
});
|
});
|
||||||
|
|
||||||
ui->actionOverview->setChecked(overviewDock->getUserOpened());
|
ui->actionOverview->setChecked(overviewDock->getUserOpened());
|
||||||
graphDock = new GraphWidget(this, ui->actionGraph);
|
|
||||||
sectionsDock = new SectionsWidget(this, ui->actionSections);
|
sectionsDock = new SectionsWidget(this, ui->actionSections);
|
||||||
segmentsDock = new SegmentsWidget(this, ui->actionSegments);
|
segmentsDock = new SegmentsWidget(this, ui->actionSegments);
|
||||||
entrypointDock = new EntrypointWidget(this, ui->actionEntrypoints);
|
entrypointDock = new EntrypointWidget(this, ui->actionEntrypoints);
|
||||||
@ -298,6 +310,38 @@ void MainWindow::initDocks()
|
|||||||
classesDock = new ClassesWidget(this, ui->actionClasses);
|
classesDock = new ClassesWidget(this, ui->actionClasses);
|
||||||
resourcesDock = new ResourcesWidget(this, ui->actionResources);
|
resourcesDock = new ResourcesWidget(this, ui->actionResources);
|
||||||
vTablesDock = new VTablesWidget(this, ui->actionVTables);
|
vTablesDock = new VTablesWidget(this, ui->actionVTables);
|
||||||
|
|
||||||
|
QSettings s;
|
||||||
|
QStringList docks = s.value("docks").toStringList();
|
||||||
|
|
||||||
|
// Restore all extra widgets
|
||||||
|
QString className;
|
||||||
|
for (const auto &it : docks) {
|
||||||
|
if (std::none_of(dockWidgets.constBegin(), dockWidgets.constEnd(),
|
||||||
|
[&it](QDockWidget *w) { return w->objectName() == it; })) {
|
||||||
|
className = it.split(';').at(0);
|
||||||
|
if (classNameToConstructorAndActionMap.contains(className)) {
|
||||||
|
auto widget = classNameToConstructorAndActionMap[className]
|
||||||
|
.first(this, classNameToConstructorAndActionMap[className].second);
|
||||||
|
widget->setObjectName(it);
|
||||||
|
addExtraWidget(widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMemberPointers();
|
||||||
|
|
||||||
|
if (!disassemblyDock) {
|
||||||
|
addExtraDisassembly();
|
||||||
|
}
|
||||||
|
if (!graphDock) {
|
||||||
|
addExtraGraph();
|
||||||
|
}
|
||||||
|
if (!hexdumpDock) {
|
||||||
|
addExtraHexdump();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMemberPointers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::initLayout()
|
void MainWindow::initLayout()
|
||||||
@ -306,10 +350,8 @@ void MainWindow::initLayout()
|
|||||||
enableDebugWidgetsMenu(false);
|
enableDebugWidgetsMenu(false);
|
||||||
// Restore saved settings
|
// Restore saved settings
|
||||||
readSettingsOrDefault();
|
readSettingsOrDefault();
|
||||||
// TODO: Allow the user to select this option visually in the GUI settings
|
|
||||||
// Adjust the DockWidget areas
|
initCorners();
|
||||||
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
|
|
||||||
setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::toggleOverview(bool visibility, GraphWidget *targetGraph)
|
void MainWindow::toggleOverview(bool visibility, GraphWidget *targetGraph)
|
||||||
@ -328,28 +370,31 @@ void MainWindow::updateTasksIndicator()
|
|||||||
tasksProgressIndicator->setProgressIndicatorVisible(running);
|
tasksProgressIndicator->setProgressIndicatorVisible(running);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionExtraGraph_triggered()
|
void MainWindow::addExtraGraph()
|
||||||
{
|
{
|
||||||
auto *extraDock = new GraphWidget(this, nullptr);
|
auto *extraDock = new GraphWidget(this, ui->actionGraph);
|
||||||
|
extraDock->setObjectName(getUniqueObjectName(extraDock->getWidgetType()));
|
||||||
addExtraWidget(extraDock);
|
addExtraWidget(extraDock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionExtraHexdump_triggered()
|
void MainWindow::addExtraHexdump()
|
||||||
{
|
{
|
||||||
auto *extraDock = new HexdumpWidget(this, nullptr);
|
auto *extraDock = new HexdumpWidget(this, ui->actionHexdump);
|
||||||
|
extraDock->setObjectName(getUniqueObjectName(extraDock->getWidgetType()));
|
||||||
addExtraWidget(extraDock);
|
addExtraWidget(extraDock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionExtraDisassembly_triggered()
|
void MainWindow::addExtraDisassembly()
|
||||||
{
|
{
|
||||||
auto *extraDock = new DisassemblyWidget(this, nullptr);
|
auto *extraDock = new DisassemblyWidget(this, ui->actionDisassembly);
|
||||||
|
extraDock->setObjectName(getUniqueObjectName(extraDock->getWidgetType()));
|
||||||
addExtraWidget(extraDock);
|
addExtraWidget(extraDock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::addExtraWidget(CutterDockWidget *extraDock)
|
void MainWindow::addExtraWidget(CutterDockWidget *extraDock)
|
||||||
{
|
{
|
||||||
extraDock->setTransient(true);
|
extraDock->setTransient(true);
|
||||||
addDockWidget(Qt::TopDockWidgetArea, extraDock);
|
addDockWidget(Qt::TopDockWidgetArea, extraDock, Qt::Orientation::Horizontal);
|
||||||
auto restoreExtraDock = qhelpers::forceWidth(extraDock->widget(), 600);
|
auto restoreExtraDock = qhelpers::forceWidth(extraDock->widget(), 600);
|
||||||
qApp->processEvents();
|
qApp->processEvents();
|
||||||
restoreExtraDock.restoreWidth(extraDock->widget());
|
restoreExtraDock.restoreWidth(extraDock->widget());
|
||||||
@ -385,7 +430,8 @@ QMenu *MainWindow::getMenuByType(MenuType type)
|
|||||||
void MainWindow::addPluginDockWidget(QDockWidget *dockWidget, QAction *action)
|
void MainWindow::addPluginDockWidget(QDockWidget *dockWidget, QAction *action)
|
||||||
{
|
{
|
||||||
addDockWidget(Qt::TopDockWidgetArea, dockWidget);
|
addDockWidget(Qt::TopDockWidgetArea, dockWidget);
|
||||||
addDockWidgetAction(dockWidget, action);
|
dockWidget->addAction(action);
|
||||||
|
addWidget(dockWidget);
|
||||||
ui->menuPlugins->addAction(action);
|
ui->menuPlugins->addAction(action);
|
||||||
addDockWidget(Qt::DockWidgetArea::TopDockWidgetArea, dockWidget);
|
addDockWidget(Qt::DockWidgetArea::TopDockWidgetArea, dockWidget);
|
||||||
updateDockActionChecked(action);
|
updateDockActionChecked(action);
|
||||||
@ -494,6 +540,14 @@ void MainWindow::finalizeOpen()
|
|||||||
showMaximized();
|
showMaximized();
|
||||||
|
|
||||||
|
|
||||||
|
QSettings s;
|
||||||
|
QStringList unsync = s.value("unsync").toStringList();
|
||||||
|
for (auto it : dockWidgets) {
|
||||||
|
auto w = qobject_cast<MemoryDockWidget*>(it);
|
||||||
|
if (w) {
|
||||||
|
w->getSeekable()->setSynchronization(!unsync.contains(it->objectName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set focus to disasm or graph widget
|
// Set focus to disasm or graph widget
|
||||||
|
|
||||||
@ -606,7 +660,7 @@ void MainWindow::readSettingsOrDefault()
|
|||||||
* Check if saved settings exist
|
* Check if saved settings exist
|
||||||
* If not, then read the default layout
|
* If not, then read the default layout
|
||||||
*/
|
*/
|
||||||
if (!geo.length() && !state.length()) {
|
if (!geo.length() || !state.length()) {
|
||||||
resetToDefaultLayout();
|
resetToDefaultLayout();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -642,6 +696,22 @@ void MainWindow::readSettingsOrDefault()
|
|||||||
void MainWindow::saveSettings()
|
void MainWindow::saveSettings()
|
||||||
{
|
{
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
|
|
||||||
|
QStringList docks;
|
||||||
|
const QStringList syncable = QStringList()
|
||||||
|
<< HexdumpWidget::getWidgetType()
|
||||||
|
<< DisassemblyWidget::getWidgetType()
|
||||||
|
<< GraphWidget::getWidgetType();
|
||||||
|
QStringList unsync;
|
||||||
|
for (const auto &it : dockWidgets) {
|
||||||
|
docks.append(it->objectName());
|
||||||
|
if (syncable.contains(it->metaObject()->className()) &&
|
||||||
|
!qobject_cast<MemoryDockWidget*>(it)->getSeekable()->isSynchronized()) {
|
||||||
|
unsync.append(it->objectName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
settings.setValue("docks", docks);
|
||||||
|
settings.setValue("unsync", unsync);
|
||||||
settings.setValue("geometry", saveGeometry());
|
settings.setValue("geometry", saveGeometry());
|
||||||
settings.setValue("size", size());
|
settings.setValue("size", size());
|
||||||
settings.setValue("pos", pos());
|
settings.setValue("pos", pos());
|
||||||
@ -728,22 +798,7 @@ void MainWindow::restoreDocks()
|
|||||||
addDockWidget(Qt::TopDockWidgetArea, overviewDock);
|
addDockWidget(Qt::TopDockWidgetArea, overviewDock);
|
||||||
|
|
||||||
// Function | Dashboard
|
// Function | Dashboard
|
||||||
splitDockWidget(overviewDock, dashboardDock, Qt::Horizontal);
|
splitDockWidget(functionsDock, dashboardDock, Qt::Horizontal);
|
||||||
splitDockWidget(functionsDock, overviewDock, Qt::Vertical);
|
|
||||||
|
|
||||||
// In the lower half the console is the first widget
|
|
||||||
addDockWidget(Qt::BottomDockWidgetArea, consoleDock);
|
|
||||||
|
|
||||||
// Console | Sections
|
|
||||||
splitDockWidget(consoleDock, sectionsDock, Qt::Horizontal);
|
|
||||||
splitDockWidget(consoleDock, segmentsDock, Qt::Horizontal);
|
|
||||||
|
|
||||||
// Tabs for center (must be applied after splitDockWidget())
|
|
||||||
tabifyDockWidget(sectionsDock, commentsDock);
|
|
||||||
tabifyDockWidget(segmentsDock, commentsDock);
|
|
||||||
tabifyDockWidget(dashboardDock, disassemblyDock);
|
|
||||||
tabifyDockWidget(dashboardDock, graphDock);
|
|
||||||
tabifyDockWidget(dashboardDock, hexdumpDock);
|
|
||||||
tabifyDockWidget(dashboardDock, pseudocodeDock);
|
tabifyDockWidget(dashboardDock, pseudocodeDock);
|
||||||
tabifyDockWidget(dashboardDock, entrypointDock);
|
tabifyDockWidget(dashboardDock, entrypointDock);
|
||||||
tabifyDockWidget(dashboardDock, flagsDock);
|
tabifyDockWidget(dashboardDock, flagsDock);
|
||||||
@ -760,17 +815,34 @@ void MainWindow::restoreDocks()
|
|||||||
tabifyDockWidget(dashboardDock, resourcesDock);
|
tabifyDockWidget(dashboardDock, resourcesDock);
|
||||||
tabifyDockWidget(dashboardDock, vTablesDock);
|
tabifyDockWidget(dashboardDock, vTablesDock);
|
||||||
tabifyDockWidget(dashboardDock, sdbDock);
|
tabifyDockWidget(dashboardDock, sdbDock);
|
||||||
|
tabifyDockWidget(dashboardDock, memoryMapDock);
|
||||||
|
tabifyDockWidget(dashboardDock, breakpointDock);
|
||||||
|
tabifyDockWidget(dashboardDock, registerRefsDock);
|
||||||
|
for (const auto &it : dockWidgets) {
|
||||||
|
// Check whether or not current widgets is graph, hexdump or disasm
|
||||||
|
if (qobject_cast<GraphWidget*>(it) ||
|
||||||
|
qobject_cast<HexdumpWidget*>(it) ||
|
||||||
|
qobject_cast<DisassemblyWidget*>(it)) {
|
||||||
|
tabifyDockWidget(dashboardDock, it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
splitDockWidget(functionsDock, overviewDock, Qt::Vertical);
|
||||||
|
|
||||||
|
// In the lower half the console is the first widget
|
||||||
|
addDockWidget(Qt::BottomDockWidgetArea, consoleDock);
|
||||||
|
|
||||||
|
// Console | Sections
|
||||||
|
splitDockWidget(consoleDock, sectionsDock, Qt::Horizontal);
|
||||||
|
splitDockWidget(consoleDock, segmentsDock, Qt::Horizontal);
|
||||||
|
|
||||||
|
tabifyDockWidget(sectionsDock, commentsDock);
|
||||||
|
|
||||||
// Add Stack, Registers and Backtrace vertically stacked
|
// Add Stack, Registers and Backtrace vertically stacked
|
||||||
addDockWidget(Qt::TopDockWidgetArea, stackDock);
|
addDockWidget(Qt::TopDockWidgetArea, stackDock);
|
||||||
splitDockWidget(stackDock, registersDock, Qt::Vertical);
|
splitDockWidget(stackDock, registersDock, Qt::Vertical);
|
||||||
tabifyDockWidget(stackDock, backtraceDock);
|
tabifyDockWidget(stackDock, backtraceDock);
|
||||||
|
|
||||||
// MemoryMap/Breakpoint/RegRefs widget goes in the center tabs
|
|
||||||
tabifyDockWidget(dashboardDock, memoryMapDock);
|
|
||||||
tabifyDockWidget(dashboardDock, breakpointDock);
|
|
||||||
tabifyDockWidget(dashboardDock, registerRefsDock);
|
|
||||||
|
|
||||||
updateDockActionsChecked();
|
updateDockActionsChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,14 +856,88 @@ void MainWindow::hideAllDocks()
|
|||||||
|
|
||||||
void MainWindow::updateDockActionsChecked()
|
void MainWindow::updateDockActionsChecked()
|
||||||
{
|
{
|
||||||
for (auto i = dockWidgetActions.constBegin(); i != dockWidgetActions.constEnd(); i++) {
|
for (auto i = dockWidgetsOfAction.constBegin(); i != dockWidgetsOfAction.constEnd(); i++) {
|
||||||
i.key()->setChecked(!i.value()->isHidden());
|
updateDockActionChecked(i.key());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MainWindow::getUniqueObjectName(const QString& widgetType) const
|
||||||
|
{
|
||||||
|
QStringList docks;
|
||||||
|
docks.reserve(dockWidgets.size());
|
||||||
|
QString name;
|
||||||
|
for (const auto &it : dockWidgets) {
|
||||||
|
name = it->objectName();
|
||||||
|
if (name.split(';').at(0) == widgetType && name != "Graph Overview") {
|
||||||
|
docks.push_back(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (docks.isEmpty()) {
|
||||||
|
return widgetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = 0;
|
||||||
|
while (docks.contains(widgetType + ";" + QString::number(id))) {
|
||||||
|
id++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return widgetType + ";" + QString::number(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::initCorners()
|
||||||
|
{
|
||||||
|
// TODO: Allow the user to select this option visually in the GUI settings
|
||||||
|
// Adjust the DockWidget areas
|
||||||
|
|
||||||
|
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
|
||||||
|
setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
|
||||||
|
|
||||||
|
setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
|
||||||
|
setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::updateMemberPointers()
|
||||||
|
{
|
||||||
|
QString className;
|
||||||
|
for (auto it : dockWidgets) {
|
||||||
|
if (!graphDock) {
|
||||||
|
graphDock = qobject_cast<GraphWidget*>(it);
|
||||||
|
}
|
||||||
|
if (!disassemblyDock) {
|
||||||
|
disassemblyDock = qobject_cast<DisassemblyWidget*>(it);
|
||||||
|
}
|
||||||
|
if (!hexdumpDock) {
|
||||||
|
hexdumpDock = qobject_cast<HexdumpWidget*>(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::addWidget(QDockWidget* widget)
|
||||||
|
{
|
||||||
|
dockWidgets.push_back(widget);
|
||||||
|
for (auto action : widget->actions()) {
|
||||||
|
dockWidgetsOfAction.insert(action, widget);
|
||||||
|
connect(qobject_cast<CutterDockWidget*>(widget), &CutterDockWidget::closed,
|
||||||
|
this, [this]() {
|
||||||
|
QDockWidget *widget = qobject_cast<QDockWidget*>(sender());
|
||||||
|
dockWidgets.removeOne(widget);
|
||||||
|
for (auto action : widget->actions()) {
|
||||||
|
dockWidgetsOfAction.remove(action, widget);
|
||||||
|
}
|
||||||
|
updateMemberPointers();
|
||||||
|
updateDockActionsChecked();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::updateDockActionChecked(QAction *action)
|
void MainWindow::updateDockActionChecked(QAction *action)
|
||||||
{
|
{
|
||||||
action->setChecked(!dockWidgetActions[action]->isHidden());
|
auto actions = dockWidgetsOfAction.values(action);
|
||||||
|
action->setChecked(!std::accumulate(actions.begin(), actions.end(), false,
|
||||||
|
[](bool a, QDockWidget* w) -> bool {
|
||||||
|
return a || w->isHidden();
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::showZenDocks()
|
void MainWindow::showZenDocks()
|
||||||
@ -799,17 +945,20 @@ void MainWindow::showZenDocks()
|
|||||||
const QList<QDockWidget *> zenDocks = { functionsDock,
|
const QList<QDockWidget *> zenDocks = { functionsDock,
|
||||||
dashboardDock,
|
dashboardDock,
|
||||||
stringsDock,
|
stringsDock,
|
||||||
graphDock,
|
|
||||||
disassemblyDock,
|
|
||||||
hexdumpDock,
|
|
||||||
searchDock,
|
searchDock,
|
||||||
importsDock,
|
importsDock
|
||||||
};
|
};
|
||||||
|
int width = functionsDock->maximumWidth();
|
||||||
|
functionsDock->setMaximumWidth(200);
|
||||||
for (auto w : dockWidgets) {
|
for (auto w : dockWidgets) {
|
||||||
if (zenDocks.contains(w)) {
|
if (zenDocks.contains(w) ||
|
||||||
|
qobject_cast<GraphWidget*>(w) ||
|
||||||
|
qobject_cast<HexdumpWidget*>(w) ||
|
||||||
|
qobject_cast<DisassemblyWidget*>(w)) {
|
||||||
w->show();
|
w->show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
functionsDock->setMaximumWidth(width);
|
||||||
updateDockActionsChecked();
|
updateDockActionsChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -817,9 +966,6 @@ void MainWindow::showDebugDocks()
|
|||||||
{
|
{
|
||||||
const QList<QDockWidget *> debugDocks = { functionsDock,
|
const QList<QDockWidget *> debugDocks = { functionsDock,
|
||||||
stringsDock,
|
stringsDock,
|
||||||
graphDock,
|
|
||||||
disassemblyDock,
|
|
||||||
hexdumpDock,
|
|
||||||
searchDock,
|
searchDock,
|
||||||
stackDock,
|
stackDock,
|
||||||
registersDock,
|
registersDock,
|
||||||
@ -827,11 +973,17 @@ void MainWindow::showDebugDocks()
|
|||||||
memoryMapDock,
|
memoryMapDock,
|
||||||
breakpointDock
|
breakpointDock
|
||||||
};
|
};
|
||||||
|
int width = functionsDock->maximumWidth();
|
||||||
|
functionsDock->setMaximumWidth(200);
|
||||||
for (auto w : dockWidgets) {
|
for (auto w : dockWidgets) {
|
||||||
if (debugDocks.contains(w)) {
|
if (debugDocks.contains(w) ||
|
||||||
|
qobject_cast<GraphWidget*>(w) ||
|
||||||
|
qobject_cast<HexdumpWidget*>(w) ||
|
||||||
|
qobject_cast<DisassemblyWidget*>(w)) {
|
||||||
w->show();
|
w->show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
functionsDock->setMaximumWidth(width);
|
||||||
updateDockActionsChecked();
|
updateDockActionsChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -877,6 +1029,23 @@ void MainWindow::restoreDebugLayout()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::resetDockWidgetList()
|
||||||
|
{
|
||||||
|
QStringList isLeft;
|
||||||
|
QList<QWidget*> toClose;
|
||||||
|
for (auto it : dockWidgets) {
|
||||||
|
if (isLeft.contains(it->metaObject()->className())) {
|
||||||
|
toClose.append(it);
|
||||||
|
} else if (QRegExp("\\w+ \\d+").exactMatch(it->objectName())) {
|
||||||
|
isLeft.append(it->metaObject()->className());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto it : toClose) {
|
||||||
|
it->close();
|
||||||
|
}
|
||||||
|
updateMemberPointers();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionLock_triggered()
|
void MainWindow::on_actionLock_triggered()
|
||||||
{
|
{
|
||||||
panelLock = !panelLock;
|
panelLock = !panelLock;
|
||||||
@ -908,9 +1077,21 @@ void MainWindow::on_actionFunctionsRename_triggered()
|
|||||||
|
|
||||||
void MainWindow::on_actionDefault_triggered()
|
void MainWindow::on_actionDefault_triggered()
|
||||||
{
|
{
|
||||||
|
QSettings s;
|
||||||
|
restoreState(emptyState);
|
||||||
|
|
||||||
|
initCorners();
|
||||||
|
resetDockWidgetList();
|
||||||
|
|
||||||
if (core->currentlyDebugging) {
|
if (core->currentlyDebugging) {
|
||||||
|
resetToDefaultLayout();
|
||||||
|
saveSettings();
|
||||||
|
|
||||||
resetToDebugLayout();
|
resetToDebugLayout();
|
||||||
} else {
|
} else {
|
||||||
|
resetToDebugLayout();
|
||||||
|
saveDebugSettings();
|
||||||
|
|
||||||
resetToDefaultLayout();
|
resetToDefaultLayout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1207,16 +1388,6 @@ bool MainWindow::eventFilter(QObject *, QEvent *event)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::addToDockWidgetList(QDockWidget *dockWidget)
|
|
||||||
{
|
|
||||||
this->dockWidgets.push_back(dockWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::addDockWidgetAction(QDockWidget *dockWidget, QAction *action)
|
|
||||||
{
|
|
||||||
this->dockWidgetActions[action] = dockWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Show a warning message box.
|
* @brief Show a warning message box.
|
||||||
*
|
*
|
||||||
|
@ -94,8 +94,7 @@ public:
|
|||||||
void setFilename(const QString &fn);
|
void setFilename(const QString &fn);
|
||||||
void refreshOmniBar(const QStringList &flags);
|
void refreshOmniBar(const QStringList &flags);
|
||||||
|
|
||||||
void addToDockWidgetList(QDockWidget *dockWidget);
|
void addWidget(QDockWidget* widget);
|
||||||
void addDockWidgetAction(QDockWidget *dockWidget, QAction *action);
|
|
||||||
void addExtraWidget(CutterDockWidget *extraDock);
|
void addExtraWidget(CutterDockWidget *extraDock);
|
||||||
|
|
||||||
void addPluginDockWidget(QDockWidget *dockWidget, QAction *action);
|
void addPluginDockWidget(QDockWidget *dockWidget, QAction *action);
|
||||||
@ -138,9 +137,9 @@ public slots:
|
|||||||
private slots:
|
private slots:
|
||||||
void on_actionAbout_triggered();
|
void on_actionAbout_triggered();
|
||||||
void on_actionIssue_triggered();
|
void on_actionIssue_triggered();
|
||||||
void on_actionExtraGraph_triggered();
|
void addExtraGraph();
|
||||||
void on_actionExtraHexdump_triggered();
|
void addExtraHexdump();
|
||||||
void on_actionExtraDisassembly_triggered();
|
void addExtraDisassembly();
|
||||||
|
|
||||||
void on_actionRefresh_Panels_triggered();
|
void on_actionRefresh_Panels_triggered();
|
||||||
|
|
||||||
@ -204,11 +203,12 @@ private:
|
|||||||
VisualNavbar *visualNavbar;
|
VisualNavbar *visualNavbar;
|
||||||
Omnibar *omnibar;
|
Omnibar *omnibar;
|
||||||
ProgressIndicator *tasksProgressIndicator;
|
ProgressIndicator *tasksProgressIndicator;
|
||||||
|
QByteArray emptyState;
|
||||||
|
|
||||||
Configuration *configuration;
|
Configuration *configuration;
|
||||||
|
|
||||||
QList<QDockWidget *> dockWidgets;
|
QList<QDockWidget *> dockWidgets;
|
||||||
QMap<QAction *, QDockWidget *> dockWidgetActions;
|
QMultiMap<QAction *, QDockWidget *> dockWidgetsOfAction;
|
||||||
DisassemblyWidget *disassemblyDock = nullptr;
|
DisassemblyWidget *disassemblyDock = nullptr;
|
||||||
HexdumpWidget *hexdumpDock = nullptr;
|
HexdumpWidget *hexdumpDock = nullptr;
|
||||||
PseudocodeWidget *pseudocodeDock = nullptr;
|
PseudocodeWidget *pseudocodeDock = nullptr;
|
||||||
@ -250,12 +250,15 @@ private:
|
|||||||
void initToolBar();
|
void initToolBar();
|
||||||
void initDocks();
|
void initDocks();
|
||||||
void initLayout();
|
void initLayout();
|
||||||
|
void initCorners();
|
||||||
void displayInitialOptionsDialog(const InitialOptions &options = InitialOptions(), bool skipOptionsDialog = false);
|
void displayInitialOptionsDialog(const InitialOptions &options = InitialOptions(), bool skipOptionsDialog = false);
|
||||||
|
|
||||||
void resetToDefaultLayout();
|
void resetToDefaultLayout();
|
||||||
void resetToDebugLayout();
|
void resetToDebugLayout();
|
||||||
void restoreDebugLayout();
|
void restoreDebugLayout();
|
||||||
|
|
||||||
|
void updateMemberPointers();
|
||||||
|
void resetDockWidgetList();
|
||||||
void restoreDocks();
|
void restoreDocks();
|
||||||
void hideAllDocks();
|
void hideAllDocks();
|
||||||
void showZenDocks();
|
void showZenDocks();
|
||||||
@ -267,6 +270,14 @@ private:
|
|||||||
void updateDockActionsChecked();
|
void updateDockActionsChecked();
|
||||||
void setOverviewData();
|
void setOverviewData();
|
||||||
bool isOverviewActive();
|
bool isOverviewActive();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Map, where key is class name an value is pair of
|
||||||
|
* pointer to class constructor and action that passed to this constructor.
|
||||||
|
*/
|
||||||
|
QMap<QString, std::pair<std::function<CutterDockWidget*(MainWindow*, QAction*)>, QAction*>> classNameToConstructorAndActionMap;
|
||||||
|
|
||||||
|
QString getUniqueObjectName(const QString &widgetType) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAINWINDOW_H
|
#endif // MAINWINDOW_H
|
||||||
|
@ -8,12 +8,12 @@ CutterDockWidget::CutterDockWidget(MainWindow *parent, QAction *action) :
|
|||||||
QDockWidget(parent),
|
QDockWidget(parent),
|
||||||
action(action)
|
action(action)
|
||||||
{
|
{
|
||||||
if (parent) {
|
|
||||||
parent->addToDockWidgetList(this);
|
|
||||||
if (action) {
|
if (action) {
|
||||||
parent->addDockWidgetAction(this, action);
|
addAction(action);
|
||||||
connect(action, &QAction::triggered, this, &CutterDockWidget::toggleDockWidget);
|
connect(action, &QAction::triggered, this, &CutterDockWidget::toggleDockWidget);
|
||||||
}
|
}
|
||||||
|
if (parent) {
|
||||||
|
parent->addWidget(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Install event filter to catch redraw widgets when needed
|
// Install event filter to catch redraw widgets when needed
|
||||||
@ -39,7 +39,7 @@ bool CutterDockWidget::eventFilter(QObject *object, QEvent *event)
|
|||||||
void CutterDockWidget::toggleDockWidget(bool show)
|
void CutterDockWidget::toggleDockWidget(bool show)
|
||||||
{
|
{
|
||||||
if (!show) {
|
if (!show) {
|
||||||
this->close();
|
this->hide();
|
||||||
} else {
|
} else {
|
||||||
this->show();
|
this->show();
|
||||||
this->raise();
|
this->raise();
|
||||||
@ -73,6 +73,8 @@ void CutterDockWidget::closeEvent(QCloseEvent *event)
|
|||||||
if (isTransient) {
|
if (isTransient) {
|
||||||
deleteLater();
|
deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit closed();
|
||||||
}
|
}
|
||||||
|
|
||||||
QAction *CutterDockWidget::getBoundAction() const
|
QAction *CutterDockWidget::getBoundAction() const
|
||||||
|
@ -57,6 +57,7 @@ public:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void becameVisibleToUser();
|
void becameVisibleToUser();
|
||||||
|
void closed();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void toggleDockWidget(bool show);
|
void toggleDockWidget(bool show);
|
||||||
|
@ -29,12 +29,12 @@
|
|||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
DisassemblerGraphView::DisassemblerGraphView(QWidget *parent)
|
DisassemblerGraphView::DisassemblerGraphView(QWidget *parent, CutterSeekable* seekable)
|
||||||
: GraphView(parent),
|
: GraphView(parent),
|
||||||
mFontMetrics(nullptr),
|
mFontMetrics(nullptr),
|
||||||
blockMenu(new DisassemblyContextMenu(this)),
|
blockMenu(new DisassemblyContextMenu(this)),
|
||||||
contextMenu(new QMenu(this)),
|
contextMenu(new QMenu(this)),
|
||||||
seekable(new CutterSeekable(this))
|
seekable(seekable)
|
||||||
{
|
{
|
||||||
highlight_token = nullptr;
|
highlight_token = nullptr;
|
||||||
auto *layout = new QVBoxLayout(this);
|
auto *layout = new QVBoxLayout(this);
|
||||||
@ -107,7 +107,7 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent)
|
|||||||
actionExportGraph.setText(tr("Export Graph"));
|
actionExportGraph.setText(tr("Export Graph"));
|
||||||
connect(&actionExportGraph, SIGNAL(triggered(bool)), this, SLOT(on_actionExportGraph_triggered()));
|
connect(&actionExportGraph, SIGNAL(triggered(bool)), this, SLOT(on_actionExportGraph_triggered()));
|
||||||
actionSyncOffset.setText(tr("Sync/unsync offset"));
|
actionSyncOffset.setText(tr("Sync/unsync offset"));
|
||||||
connect(&actionSyncOffset, SIGNAL(triggered(bool)), this, SLOT(toggleSync()));
|
connect(&actionSyncOffset, &QAction::triggered, seekable, &CutterSeekable::toggleSynchronization);
|
||||||
|
|
||||||
// Context menu that applies to everything
|
// Context menu that applies to everything
|
||||||
contextMenu->addAction(&actionExportGraph);
|
contextMenu->addAction(&actionExportGraph);
|
||||||
@ -190,16 +190,6 @@ DisassemblerGraphView::~DisassemblerGraphView()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisassemblerGraphView::toggleSync()
|
|
||||||
{
|
|
||||||
seekable->toggleSynchronization();
|
|
||||||
if (seekable->isSynchronized()) {
|
|
||||||
parentWidget()->setWindowTitle(windowTitle);
|
|
||||||
} else {
|
|
||||||
parentWidget()->setWindowTitle(windowTitle + CutterSeekable::tr(" (unsynced)"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisassemblerGraphView::refreshView()
|
void DisassemblerGraphView::refreshView()
|
||||||
{
|
{
|
||||||
initFont();
|
initFont();
|
||||||
@ -259,11 +249,7 @@ void DisassemblerGraphView::loadCurrentGraph()
|
|||||||
} else if (!funcName.isEmpty()) {
|
} else if (!funcName.isEmpty()) {
|
||||||
windowTitle += " (" + funcName + ")";
|
windowTitle += " (" + funcName + ")";
|
||||||
}
|
}
|
||||||
if (!seekable->isSynchronized()) {
|
emit nameChanged(windowTitle);
|
||||||
parentWidget()->setWindowTitle(windowTitle + CutterSeekable::tr(" (unsynced)"));
|
|
||||||
} else {
|
|
||||||
parentWidget()->setWindowTitle(windowTitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
RVA entry = func["offset"].toVariant().toULongLong();
|
RVA entry = func["offset"].toVariant().toULongLong();
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ class DisassemblerGraphView : public GraphView
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DisassemblerGraphView(QWidget *parent);
|
DisassemblerGraphView(QWidget *parent, CutterSeekable* seekable);
|
||||||
~DisassemblerGraphView() override;
|
~DisassemblerGraphView() override;
|
||||||
std::unordered_map<ut64, DisassemblyBlock> disassembly_blocks;
|
std::unordered_map<ut64, DisassemblyBlock> disassembly_blocks;
|
||||||
virtual void drawBlock(QPainter &p, GraphView::GraphBlock &block) override;
|
virtual void drawBlock(QPainter &p, GraphView::GraphBlock &block) override;
|
||||||
@ -115,8 +115,6 @@ public slots:
|
|||||||
void colorsUpdatedSlot();
|
void colorsUpdatedSlot();
|
||||||
void fontsUpdatedSlot();
|
void fontsUpdatedSlot();
|
||||||
void onSeekChanged(RVA addr);
|
void onSeekChanged(RVA addr);
|
||||||
void toggleSync();
|
|
||||||
|
|
||||||
void zoom(QPointF mouseRelativePos, double velocity);
|
void zoom(QPointF mouseRelativePos, double velocity);
|
||||||
void zoomReset();
|
void zoomReset();
|
||||||
|
|
||||||
@ -215,6 +213,7 @@ signals:
|
|||||||
void viewZoomed();
|
void viewZoomed();
|
||||||
void graphMoved();
|
void graphMoved();
|
||||||
void resized();
|
void resized();
|
||||||
|
void nameChanged(const QString& name);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool isGraphEmpty() { return emptyGraph; }
|
bool isGraphEmpty() { return emptyGraph; }
|
||||||
|
@ -38,26 +38,15 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action)
|
|||||||
, mCtxMenu(new DisassemblyContextMenu(this))
|
, mCtxMenu(new DisassemblyContextMenu(this))
|
||||||
, mDisasScrollArea(new DisassemblyScrollArea(this))
|
, mDisasScrollArea(new DisassemblyScrollArea(this))
|
||||||
, mDisasTextEdit(new DisassemblyTextEdit(this))
|
, mDisasTextEdit(new DisassemblyTextEdit(this))
|
||||||
, seekable(new CutterSeekable(this))
|
|
||||||
{
|
{
|
||||||
/*
|
setObjectName(getWidgetType());
|
||||||
* Ugly hack just for the layout issue
|
|
||||||
* QSettings saves the state with the object names
|
|
||||||
* By doing this hack,
|
|
||||||
* you can at least avoid some mess by dismissing all the Extra Widgets
|
|
||||||
*/
|
|
||||||
QString name = "Disassembly";
|
|
||||||
if (!action) {
|
|
||||||
name = "Extra Disassembly";
|
|
||||||
}
|
|
||||||
setObjectName(name);
|
|
||||||
|
|
||||||
topOffset = bottomOffset = RVA_INVALID;
|
topOffset = bottomOffset = RVA_INVALID;
|
||||||
cursorLineOffset = 0;
|
cursorLineOffset = 0;
|
||||||
cursorCharOffset = 0;
|
cursorCharOffset = 0;
|
||||||
seekFromCursor = false;
|
seekFromCursor = false;
|
||||||
|
|
||||||
setWindowTitle(tr("Disassembly"));
|
setWindowTitle(getWindowTitle());
|
||||||
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout();
|
QVBoxLayout *layout = new QVBoxLayout();
|
||||||
layout->addWidget(mDisasTextEdit);
|
layout->addWidget(mDisasTextEdit);
|
||||||
@ -144,7 +133,7 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action)
|
|||||||
mCtxMenu->addSeparator();
|
mCtxMenu->addSeparator();
|
||||||
syncIt.setText(tr("Sync/unsync offset"));
|
syncIt.setText(tr("Sync/unsync offset"));
|
||||||
mCtxMenu->addAction(&syncIt);
|
mCtxMenu->addAction(&syncIt);
|
||||||
connect(&syncIt, SIGNAL(triggered(bool)), this, SLOT(toggleSync()));
|
connect(&syncIt, &QAction::triggered, seekable, &CutterSeekable::toggleSynchronization);
|
||||||
connect(seekable, &CutterSeekable::seekableSeekChanged, this, &DisassemblyWidget::on_seekChanged);
|
connect(seekable, &CutterSeekable::seekableSeekChanged, this, &DisassemblyWidget::on_seekChanged);
|
||||||
|
|
||||||
addActions(mCtxMenu->actions());
|
addActions(mCtxMenu->actions());
|
||||||
@ -191,17 +180,6 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action)
|
|||||||
#undef ADD_ACTION
|
#undef ADD_ACTION
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisassemblyWidget::toggleSync()
|
|
||||||
{
|
|
||||||
QString windowTitle = tr("Disassembly");
|
|
||||||
seekable->toggleSynchronization();
|
|
||||||
if (seekable->isSynchronized()) {
|
|
||||||
setWindowTitle(windowTitle);
|
|
||||||
} else {
|
|
||||||
setWindowTitle(windowTitle + CutterSeekable::tr(" (unsynced)"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisassemblyWidget::setPreviewMode(bool previewMode)
|
void DisassemblyWidget::setPreviewMode(bool previewMode)
|
||||||
{
|
{
|
||||||
mDisasTextEdit->setContextMenuPolicy(previewMode
|
mDisasTextEdit->setContextMenuPolicy(previewMode
|
||||||
@ -217,8 +195,8 @@ void DisassemblyWidget::setPreviewMode(bool previewMode)
|
|||||||
action->setEnabled(!previewMode);
|
action->setEnabled(!previewMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (seekable->isSynchronized() && previewMode) {
|
if (previewMode) {
|
||||||
toggleSync();
|
seekable->setSynchronization(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,6 +205,11 @@ QWidget *DisassemblyWidget::getTextWidget()
|
|||||||
return mDisasTextEdit;
|
return mDisasTextEdit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString DisassemblyWidget::getWidgetType()
|
||||||
|
{
|
||||||
|
return "Disassembly";
|
||||||
|
}
|
||||||
|
|
||||||
void DisassemblyWidget::refreshDisasm(RVA offset)
|
void DisassemblyWidget::refreshDisasm(RVA offset)
|
||||||
{
|
{
|
||||||
if(!disasmRefresh->attemptRefresh(offset == RVA_INVALID ? nullptr : new RVA(offset))) {
|
if(!disasmRefresh->attemptRefresh(offset == RVA_INVALID ? nullptr : new RVA(offset))) {
|
||||||
@ -655,6 +638,11 @@ bool DisassemblyWidget::eventFilter(QObject *obj, QEvent *event)
|
|||||||
return CutterDockWidget::eventFilter(obj, event);
|
return CutterDockWidget::eventFilter(obj, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString DisassemblyWidget::getWindowTitle() const
|
||||||
|
{
|
||||||
|
return tr("Disassembly");
|
||||||
|
}
|
||||||
|
|
||||||
void DisassemblyWidget::on_seekChanged(RVA offset)
|
void DisassemblyWidget::on_seekChanged(RVA offset)
|
||||||
{
|
{
|
||||||
if (!seekFromCursor) {
|
if (!seekFromCursor) {
|
||||||
|
@ -23,13 +23,14 @@ public:
|
|||||||
explicit DisassemblyWidget(MainWindow *main, QAction *action = nullptr);
|
explicit DisassemblyWidget(MainWindow *main, QAction *action = nullptr);
|
||||||
QWidget *getTextWidget();
|
QWidget *getTextWidget();
|
||||||
|
|
||||||
|
static QString getWidgetType();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void highlightCurrentLine();
|
void highlightCurrentLine();
|
||||||
void showDisasContextMenu(const QPoint &pt);
|
void showDisasContextMenu(const QPoint &pt);
|
||||||
void fontsUpdatedSlot();
|
void fontsUpdatedSlot();
|
||||||
void colorsUpdatedSlot();
|
void colorsUpdatedSlot();
|
||||||
void seekPrev();
|
void seekPrev();
|
||||||
void toggleSync();
|
|
||||||
void setPreviewMode(bool previewMode);
|
void setPreviewMode(bool previewMode);
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
@ -68,6 +69,7 @@ private:
|
|||||||
RVA readCurrentDisassemblyOffset();
|
RVA readCurrentDisassemblyOffset();
|
||||||
RVA readDisassemblyOffset(QTextCursor tc);
|
RVA readDisassemblyOffset(QTextCursor tc);
|
||||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||||
|
QString getWindowTitle() const override;
|
||||||
|
|
||||||
QList<RVA> breakpoints;
|
QList<RVA> breakpoints;
|
||||||
|
|
||||||
@ -82,7 +84,6 @@ private:
|
|||||||
QList<QTextEdit::ExtraSelection> getSameWordsSelections();
|
QList<QTextEdit::ExtraSelection> getSameWordsSelections();
|
||||||
|
|
||||||
QAction syncIt;
|
QAction syncIt;
|
||||||
CutterSeekable *seekable;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DisassemblyScrollArea : public QAbstractScrollArea
|
class DisassemblyScrollArea : public QAbstractScrollArea
|
||||||
|
@ -6,19 +6,9 @@
|
|||||||
GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
|
GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
|
||||||
MemoryDockWidget(CutterCore::MemoryWidgetType::Graph, main, action)
|
MemoryDockWidget(CutterCore::MemoryWidgetType::Graph, main, action)
|
||||||
{
|
{
|
||||||
/*
|
setObjectName(getWidgetType());
|
||||||
* Ugly hack just for the layout issue
|
|
||||||
* QSettings saves the state with the object names
|
|
||||||
* By doing this hack,
|
|
||||||
* you can at least avoid some mess by dismissing all the Extra Widgets
|
|
||||||
*/
|
|
||||||
QString name = "Graph";
|
|
||||||
if (!action) {
|
|
||||||
name = "Extra Graph";
|
|
||||||
}
|
|
||||||
setObjectName(name);
|
|
||||||
setAllowedAreas(Qt::AllDockWidgetAreas);
|
setAllowedAreas(Qt::AllDockWidgetAreas);
|
||||||
graphView = new DisassemblerGraphView(this);
|
graphView = new DisassemblerGraphView(this, seekable);
|
||||||
setWidget(graphView);
|
setWidget(graphView);
|
||||||
|
|
||||||
// getting the name of the class is implementation defined, and cannot be
|
// getting the name of the class is implementation defined, and cannot be
|
||||||
@ -30,6 +20,8 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
|
|||||||
main->updateDockActionChecked(action);
|
main->updateDockActionChecked(action);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(graphView, &DisassemblerGraphView::nameChanged, this, &MemoryDockWidget::updateWindowTitle);
|
||||||
|
|
||||||
connect(this, &QDockWidget::visibilityChanged, this, [ = ](bool visibility) {
|
connect(this, &QDockWidget::visibilityChanged, this, [ = ](bool visibility) {
|
||||||
main->toggleOverview(visibility, this);
|
main->toggleOverview(visibility, this);
|
||||||
if (visibility) {
|
if (visibility) {
|
||||||
@ -54,7 +46,17 @@ void GraphWidget::closeEvent(QCloseEvent *event)
|
|||||||
emit graphClosed();
|
emit graphClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString GraphWidget::getWindowTitle() const
|
||||||
|
{
|
||||||
|
return graphView->windowTitle;
|
||||||
|
}
|
||||||
|
|
||||||
DisassemblerGraphView *GraphWidget::getGraphView() const
|
DisassemblerGraphView *GraphWidget::getGraphView() const
|
||||||
{
|
{
|
||||||
return graphView;
|
return graphView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString GraphWidget::getWidgetType()
|
||||||
|
{
|
||||||
|
return "Graph";
|
||||||
|
}
|
||||||
|
@ -12,10 +12,12 @@ class GraphWidget : public MemoryDockWidget
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GraphWidget(MainWindow *main, QAction *action = nullptr);
|
explicit GraphWidget(MainWindow *main, QAction *action = nullptr);
|
||||||
~GraphWidget() {}
|
~GraphWidget() override {}
|
||||||
|
|
||||||
DisassemblerGraphView *getGraphView() const;
|
DisassemblerGraphView *getGraphView() const;
|
||||||
|
|
||||||
|
static QString getWidgetType();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void graphClosed();
|
void graphClosed();
|
||||||
|
|
||||||
@ -25,6 +27,8 @@ protected:
|
|||||||
private:
|
private:
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
|
|
||||||
|
QString getWindowTitle() const override;
|
||||||
|
|
||||||
DisassemblerGraphView *graphView;
|
DisassemblerGraphView *graphView;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,22 +17,11 @@
|
|||||||
|
|
||||||
HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) :
|
HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) :
|
||||||
MemoryDockWidget(CutterCore::MemoryWidgetType::Hexdump, main, action),
|
MemoryDockWidget(CutterCore::MemoryWidgetType::Hexdump, main, action),
|
||||||
ui(new Ui::HexdumpWidget),
|
ui(new Ui::HexdumpWidget)
|
||||||
seekable(new CutterSeekable(this))
|
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
/*
|
setObjectName(getWidgetType());
|
||||||
* Ugly hack just for the layout issue
|
|
||||||
* QSettings saves the state with the object names
|
|
||||||
* By doing this hack,
|
|
||||||
* you can at least avoid some mess by dismissing all the Extra Widgets
|
|
||||||
*/
|
|
||||||
QString name = "Hexdump";
|
|
||||||
if (!action) {
|
|
||||||
name = "Extra Hexdump";
|
|
||||||
}
|
|
||||||
setObjectName(name);
|
|
||||||
|
|
||||||
ui->copyMD5->setIcon(QIcon(":/img/icons/copy.svg"));
|
ui->copyMD5->setIcon(QIcon(":/img/icons/copy.svg"));
|
||||||
ui->copySHA1->setIcon(QIcon(":/img/icons/copy.svg"));
|
ui->copySHA1->setIcon(QIcon(":/img/icons/copy.svg"));
|
||||||
@ -75,13 +64,13 @@ HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) :
|
|||||||
" border-color : #3daee9"
|
" border-color : #3daee9"
|
||||||
"}");
|
"}");
|
||||||
|
|
||||||
this->setWindowTitle(tr("Hexdump"));
|
setWindowTitle(getWindowTitle());
|
||||||
|
|
||||||
refreshDeferrer = createReplacingRefreshDeferrer<RVA>(false, [this](const RVA *offset) {
|
refreshDeferrer = createReplacingRefreshDeferrer<RVA>(false, [this](const RVA *offset) {
|
||||||
refresh(offset ? *offset : RVA_INVALID);
|
refresh(offset ? *offset : RVA_INVALID);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(&syncAction, SIGNAL(triggered(bool)), this, SLOT(toggleSync()));
|
connect(&syncAction, &QAction::triggered, seekable, &CutterSeekable::toggleSynchronization);
|
||||||
syncAction.setText(tr("Sync/unsync offset"));
|
syncAction.setText(tr("Sync/unsync offset"));
|
||||||
this->ui->hexTextView->addAction(&syncAction);
|
this->ui->hexTextView->addAction(&syncAction);
|
||||||
|
|
||||||
@ -121,6 +110,11 @@ void HexdumpWidget::onSeekChanged(RVA addr)
|
|||||||
|
|
||||||
HexdumpWidget::~HexdumpWidget() {}
|
HexdumpWidget::~HexdumpWidget() {}
|
||||||
|
|
||||||
|
QString HexdumpWidget::getWidgetType()
|
||||||
|
{
|
||||||
|
return "Hexdump";
|
||||||
|
}
|
||||||
|
|
||||||
void HexdumpWidget::refresh()
|
void HexdumpWidget::refresh()
|
||||||
{
|
{
|
||||||
refresh(RVA_INVALID);
|
refresh(RVA_INVALID);
|
||||||
@ -169,19 +163,6 @@ void HexdumpWidget::on_parseBitsComboBox_currentTextChanged(const QString &/*arg
|
|||||||
refreshSelectionInfo();
|
refreshSelectionInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void HexdumpWidget::toggleSync()
|
|
||||||
{
|
|
||||||
QString windowTitle = tr("Hexdump");
|
|
||||||
seekable->toggleSynchronization();
|
|
||||||
if (seekable->isSynchronized()) {
|
|
||||||
setWindowTitle(windowTitle);
|
|
||||||
} else {
|
|
||||||
setWindowTitle(windowTitle + CutterSeekable::tr(" (unsynced)"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void HexdumpWidget::setupFonts()
|
void HexdumpWidget::setupFonts()
|
||||||
{
|
{
|
||||||
QFont font = Config()->getFont();
|
QFont font = Config()->getFont();
|
||||||
@ -216,6 +197,11 @@ void HexdumpWidget::showSidePanel(bool show)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString HexdumpWidget::getWindowTitle() const
|
||||||
|
{
|
||||||
|
return tr("Hexdump");
|
||||||
|
}
|
||||||
|
|
||||||
void HexdumpWidget::updateParseWindow(RVA start_address, int size)
|
void HexdumpWidget::updateParseWindow(RVA start_address, int size)
|
||||||
{
|
{
|
||||||
if (!ui->hexSideTab_2->isVisible()) {
|
if (!ui->hexSideTab_2->isVisible()) {
|
||||||
|
@ -34,10 +34,11 @@ public:
|
|||||||
~HexdumpWidget() override;
|
~HexdumpWidget() override;
|
||||||
Highlighter *highlighter;
|
Highlighter *highlighter;
|
||||||
|
|
||||||
|
static QString getWidgetType();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void initParsing();
|
void initParsing();
|
||||||
|
|
||||||
void toggleSync();
|
|
||||||
protected:
|
protected:
|
||||||
virtual void resizeEvent(QResizeEvent *event) override;
|
virtual void resizeEvent(QResizeEvent *event) override;
|
||||||
QWidget *widgetToFocusOnRaise() override;
|
QWidget *widgetToFocusOnRaise() override;
|
||||||
@ -59,8 +60,9 @@ private:
|
|||||||
void clearParseWindow();
|
void clearParseWindow();
|
||||||
void showSidePanel(bool show);
|
void showSidePanel(bool show);
|
||||||
|
|
||||||
|
QString getWindowTitle() const override;
|
||||||
|
|
||||||
QAction syncAction;
|
QAction syncAction;
|
||||||
CutterSeekable *seekable;
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onSeekChanged(RVA addr);
|
void onSeekChanged(RVA addr);
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
#include "MemoryDockWidget.h"
|
#include "MemoryDockWidget.h"
|
||||||
|
#include "common/CutterSeekable.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
|
||||||
MemoryDockWidget::MemoryDockWidget(CutterCore::MemoryWidgetType type, MainWindow *parent, QAction *action)
|
MemoryDockWidget::MemoryDockWidget(CutterCore::MemoryWidgetType type, MainWindow *parent, QAction *action)
|
||||||
: CutterDockWidget(parent, action)
|
: CutterDockWidget(parent, action)
|
||||||
, mType(type)
|
, mType(type), seekable(new CutterSeekable(this))
|
||||||
{
|
{
|
||||||
connect(Core(), &CutterCore::raisePrioritizedMemoryWidget, this, &MemoryDockWidget::handleRaiseMemoryWidget);
|
connect(Core(), &CutterCore::raisePrioritizedMemoryWidget, this, &MemoryDockWidget::handleRaiseMemoryWidget);
|
||||||
|
connect(seekable, &CutterSeekable::syncChanged, this, &MemoryDockWidget::updateWindowTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryDockWidget::handleRaiseMemoryWidget(CutterCore::MemoryWidgetType raiseType)
|
void MemoryDockWidget::handleRaiseMemoryWidget(CutterCore::MemoryWidgetType raiseType)
|
||||||
@ -26,3 +28,17 @@ void MemoryDockWidget::handleRaiseMemoryWidget(CutterCore::MemoryWidgetType rais
|
|||||||
widgetToFocusOnRaise()->setFocus(Qt::FocusReason::TabFocusReason);
|
widgetToFocusOnRaise()->setFocus(Qt::FocusReason::TabFocusReason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MemoryDockWidget::updateWindowTitle()
|
||||||
|
{
|
||||||
|
if (seekable->isSynchronized()) {
|
||||||
|
setWindowTitle(getWindowTitle());
|
||||||
|
} else {
|
||||||
|
setWindowTitle(getWindowTitle() + CutterSeekable::tr(" (unsynced)"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CutterSeekable* MemoryDockWidget::getSeekable() const
|
||||||
|
{
|
||||||
|
return seekable;
|
||||||
|
}
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include "CutterDockWidget.h"
|
#include "CutterDockWidget.h"
|
||||||
#include "core/Cutter.h"
|
#include "core/Cutter.h"
|
||||||
|
|
||||||
|
class CutterSeekable;
|
||||||
|
|
||||||
class MemoryDockWidget : public CutterDockWidget
|
class MemoryDockWidget : public CutterDockWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -11,10 +13,20 @@ public:
|
|||||||
MemoryDockWidget(CutterCore::MemoryWidgetType type, MainWindow *parent, QAction *action = nullptr);
|
MemoryDockWidget(CutterCore::MemoryWidgetType type, MainWindow *parent, QAction *action = nullptr);
|
||||||
~MemoryDockWidget() {}
|
~MemoryDockWidget() {}
|
||||||
|
|
||||||
|
CutterSeekable* getSeekable() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handleRaiseMemoryWidget(CutterCore::MemoryWidgetType raiseType);
|
void handleRaiseMemoryWidget(CutterCore::MemoryWidgetType raiseType);
|
||||||
|
|
||||||
CutterCore::MemoryWidgetType mType;
|
CutterCore::MemoryWidgetType mType;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void updateWindowTitle();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CutterSeekable *seekable = nullptr;
|
||||||
|
|
||||||
|
virtual QString getWindowTitle() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MEMORYDOCKWIDGET_H
|
#endif // MEMORYDOCKWIDGET_H
|
||||||
|
@ -86,6 +86,11 @@ void PseudocodeWidget::setupFonts()
|
|||||||
ui->textEdit->setFont(font);
|
ui->textEdit->setFont(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString PseudocodeWidget::getWindowTitle() const
|
||||||
|
{
|
||||||
|
return tr("Pseudocode");
|
||||||
|
}
|
||||||
|
|
||||||
void PseudocodeWidget::fontsUpdated()
|
void PseudocodeWidget::fontsUpdated()
|
||||||
{
|
{
|
||||||
setupFonts();
|
setupFonts();
|
||||||
|
@ -34,6 +34,8 @@ private:
|
|||||||
|
|
||||||
void doRefresh(RVA addr);
|
void doRefresh(RVA addr);
|
||||||
void setupFonts();
|
void setupFonts();
|
||||||
|
|
||||||
|
QString getWindowTitle() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PSEUDOCODEWIDGET_H
|
#endif // PSEUDOCODEWIDGET_H
|
||||||
|
Loading…
Reference in New Issue
Block a user