mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-20 03:46:11 +00:00
Rewrite raise memory widget functionality (#1654)
* Seperate seek from seeking and changing focused widget. * Change memory widget priorities * Add Show in context menu
This commit is contained in:
parent
914b35e637
commit
6c40191cce
@ -628,25 +628,38 @@ void CutterCore::seek(ut64 offset)
|
|||||||
}
|
}
|
||||||
cmd(QString("s %1").arg(offset));
|
cmd(QString("s %1").arg(offset));
|
||||||
// cmd already does emit seekChanged(core_->offset);
|
// cmd already does emit seekChanged(core_->offset);
|
||||||
triggerRaisePrioritizedMemoryWidget();
|
}
|
||||||
|
|
||||||
|
void CutterCore::showMemoryWidget()
|
||||||
|
{
|
||||||
|
emit showMemoryWidgetRequested();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::seekAndShow(ut64 offset)
|
||||||
|
{
|
||||||
|
seek(offset);
|
||||||
|
showMemoryWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::seekAndShow(QString offset)
|
||||||
|
{
|
||||||
|
seek(offset);
|
||||||
|
showMemoryWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::seek(QString thing)
|
void CutterCore::seek(QString thing)
|
||||||
{
|
{
|
||||||
cmdRaw(QString("s %1").arg(thing));
|
cmdRaw(QString("s %1").arg(thing));
|
||||||
triggerRaisePrioritizedMemoryWidget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::seekPrev()
|
void CutterCore::seekPrev()
|
||||||
{
|
{
|
||||||
cmd("s-");
|
cmd("s-");
|
||||||
triggerRaisePrioritizedMemoryWidget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::seekNext()
|
void CutterCore::seekNext()
|
||||||
{
|
{
|
||||||
cmd("s+");
|
cmd("s+");
|
||||||
triggerRaisePrioritizedMemoryWidget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::updateSeek()
|
void CutterCore::updateSeek()
|
||||||
@ -1116,7 +1129,7 @@ void CutterCore::attachDebug(int pid)
|
|||||||
// attach to process with dbg plugin
|
// attach to process with dbg plugin
|
||||||
cmd("o-*; e cfg.debug = true; o+ dbg://" + QString::number(pid));
|
cmd("o-*; e cfg.debug = true; o+ dbg://" + QString::number(pid));
|
||||||
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
seek(programCounterValue);
|
seekAndShow(programCounterValue);
|
||||||
emit registersChanged();
|
emit registersChanged();
|
||||||
if (!currentlyDebugging || !currentlyEmulating) {
|
if (!currentlyDebugging || !currentlyEmulating) {
|
||||||
// prevent register flags from appearing during debug/emul
|
// prevent register flags from appearing during debug/emul
|
||||||
@ -1141,7 +1154,7 @@ void CutterCore::stopDebug()
|
|||||||
} else {
|
} else {
|
||||||
cmd("dk 9; oo; .ar-");
|
cmd("dk 9; oo; .ar-");
|
||||||
}
|
}
|
||||||
seek(offsetPriorDebugging);
|
seekAndShow(offsetPriorDebugging);
|
||||||
setConfig("asm.flags", true);
|
setConfig("asm.flags", true);
|
||||||
setConfig("io.cache", false);
|
setConfig("io.cache", false);
|
||||||
currentlyDebugging = false;
|
currentlyDebugging = false;
|
||||||
@ -1185,7 +1198,7 @@ void CutterCore::continueUntilCall()
|
|||||||
cmd("dcc");
|
cmd("dcc");
|
||||||
}
|
}
|
||||||
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
seek(programCounterValue);
|
seekAndShow(programCounterValue);
|
||||||
emit registersChanged();
|
emit registersChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1199,7 +1212,7 @@ void CutterCore::continueUntilSyscall()
|
|||||||
cmd("dcs");
|
cmd("dcs");
|
||||||
}
|
}
|
||||||
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
seek(programCounterValue);
|
seekAndShow(programCounterValue);
|
||||||
emit registersChanged();
|
emit registersChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1209,7 +1222,7 @@ void CutterCore::stepDebug()
|
|||||||
if (currentlyDebugging) {
|
if (currentlyDebugging) {
|
||||||
cmdEsil("ds");
|
cmdEsil("ds");
|
||||||
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
seek(programCounterValue);
|
seekAndShow(programCounterValue);
|
||||||
emit registersChanged();
|
emit registersChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1219,7 +1232,7 @@ void CutterCore::stepOverDebug()
|
|||||||
if (currentlyDebugging) {
|
if (currentlyDebugging) {
|
||||||
cmdEsil("dso");
|
cmdEsil("dso");
|
||||||
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
seek(programCounterValue);
|
seekAndShow(programCounterValue);
|
||||||
emit registersChanged();
|
emit registersChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1229,7 +1242,7 @@ void CutterCore::stepOutDebug()
|
|||||||
if (currentlyDebugging) {
|
if (currentlyDebugging) {
|
||||||
cmd("dsf");
|
cmd("dsf");
|
||||||
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
QString programCounterValue = cmd("dr?`drn PC`").trimmed();
|
||||||
seek(programCounterValue);
|
seekAndShow(programCounterValue);
|
||||||
emit registersChanged();
|
emit registersChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,6 @@ public:
|
|||||||
RCore *operator->() const;
|
RCore *operator->() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class CutterCore: public QObject
|
class CutterCore: public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -150,25 +149,25 @@ public:
|
|||||||
void seekPrev();
|
void seekPrev();
|
||||||
void seekNext();
|
void seekNext();
|
||||||
void updateSeek();
|
void updateSeek();
|
||||||
|
/**
|
||||||
|
* @brief Raise a memory widget showing current offset, prefer last active
|
||||||
|
* memory widget.
|
||||||
|
*/
|
||||||
|
void showMemoryWidget();
|
||||||
|
/**
|
||||||
|
* @brief Seek to \p offset and raise a memory widget showing it.
|
||||||
|
* @param offset
|
||||||
|
*/
|
||||||
|
void seekAndShow(ut64 offset);
|
||||||
|
/**
|
||||||
|
* @brief \see CutterCore::show(ut64)
|
||||||
|
* @param thing - addressable expression
|
||||||
|
*/
|
||||||
|
void seekAndShow(QString thing);
|
||||||
RVA getOffset();
|
RVA getOffset();
|
||||||
RVA prevOpAddr(RVA startAddr, int count);
|
RVA prevOpAddr(RVA startAddr, int count);
|
||||||
RVA nextOpAddr(RVA startAddr, int count);
|
RVA nextOpAddr(RVA startAddr, int count);
|
||||||
|
|
||||||
/* Disassembly/Graph/Hexdump/Pseudocode view priority */
|
|
||||||
enum class MemoryWidgetType { Disassembly, Graph, Hexdump, Pseudocode };
|
|
||||||
MemoryWidgetType getMemoryWidgetPriority() const
|
|
||||||
{
|
|
||||||
return memoryWidgetPriority;
|
|
||||||
}
|
|
||||||
void setMemoryWidgetPriority(MemoryWidgetType type)
|
|
||||||
{
|
|
||||||
memoryWidgetPriority = type;
|
|
||||||
}
|
|
||||||
void triggerRaisePrioritizedMemoryWidget()
|
|
||||||
{
|
|
||||||
emit raisePrioritizedMemoryWidget(memoryWidgetPriority);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Math functions */
|
/* Math functions */
|
||||||
ut64 math(const QString &expr);
|
ut64 math(const QString &expr);
|
||||||
ut64 num(const QString &expr);
|
ut64 num(const QString &expr);
|
||||||
@ -444,16 +443,15 @@ signals:
|
|||||||
*/
|
*/
|
||||||
void seekChanged(RVA offset);
|
void seekChanged(RVA offset);
|
||||||
|
|
||||||
void raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType type);
|
|
||||||
void changeDefinedView();
|
void changeDefinedView();
|
||||||
void changeDebugView();
|
void changeDebugView();
|
||||||
|
|
||||||
void newMessage(const QString &msg);
|
void newMessage(const QString &msg);
|
||||||
void newDebugMessage(const QString &msg);
|
void newDebugMessage(const QString &msg);
|
||||||
|
|
||||||
private:
|
void showMemoryWidgetRequested();
|
||||||
MemoryWidgetType memoryWidgetPriority;
|
|
||||||
|
|
||||||
|
private:
|
||||||
QString notes;
|
QString notes;
|
||||||
RCore *core_ = nullptr;
|
RCore *core_ = nullptr;
|
||||||
AsyncTaskManager *asyncTaskManager;
|
AsyncTaskManager *asyncTaskManager;
|
||||||
|
@ -171,6 +171,9 @@ void MainWindow::initUI()
|
|||||||
connect(core, SIGNAL(newDebugMessage(const QString &)),
|
connect(core, SIGNAL(newDebugMessage(const QString &)),
|
||||||
this->consoleDock, SLOT(addDebugOutput(const QString &)));
|
this->consoleDock, SLOT(addDebugOutput(const QString &)));
|
||||||
|
|
||||||
|
connect(core, &CutterCore::showMemoryWidgetRequested,
|
||||||
|
this, static_cast<void(MainWindow::*)()>(&MainWindow::showMemoryWidget));
|
||||||
|
|
||||||
updateTasksIndicator();
|
updateTasksIndicator();
|
||||||
connect(core->getAsyncTaskManager(), &AsyncTaskManager::tasksChanged, this,
|
connect(core->getAsyncTaskManager(), &AsyncTaskManager::tasksChanged, this,
|
||||||
&MainWindow::updateTasksIndicator);
|
&MainWindow::updateTasksIndicator);
|
||||||
@ -839,6 +842,14 @@ void MainWindow::updateDockActionsChecked()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemoryWidgetType MainWindow::getMemoryWidgetTypeToRestore()
|
||||||
|
{
|
||||||
|
if (lastMemoryWidget) {
|
||||||
|
return lastMemoryWidget->getType();
|
||||||
|
}
|
||||||
|
return MemoryWidgetType::Disassembly;
|
||||||
|
}
|
||||||
|
|
||||||
QString MainWindow::getUniqueObjectName(const QString &widgetType) const
|
QString MainWindow::getUniqueObjectName(const QString &widgetType) const
|
||||||
{
|
{
|
||||||
QStringList docks;
|
QStringList docks;
|
||||||
@ -863,6 +874,90 @@ QString MainWindow::getUniqueObjectName(const QString &widgetType) const
|
|||||||
return widgetType + ";" + QString::number(id);
|
return widgetType + ";" + QString::number(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::showMemoryWidget()
|
||||||
|
{
|
||||||
|
if (lastMemoryWidget) {
|
||||||
|
if (lastMemoryWidget->tryRaiseMemoryWidget()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showMemoryWidget(MemoryWidgetType::Disassembly);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::showMemoryWidget(MemoryWidgetType type)
|
||||||
|
{
|
||||||
|
for (auto &dock : dockWidgets) {
|
||||||
|
if (auto memoryWidget = qobject_cast<MemoryDockWidget *>(dock)) {
|
||||||
|
if (memoryWidget->getType() == type && memoryWidget->getSeekable()->isSynchronized()) {
|
||||||
|
memoryWidget->tryRaiseMemoryWidget();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto memoryDockWidget = addNewMemoryWidget(type, Core()->getOffset());
|
||||||
|
memoryDockWidget->raiseMemoryWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
QMenu *MainWindow::createShowInMenu(QWidget *parent, RVA address)
|
||||||
|
{
|
||||||
|
QMenu *menu = new QMenu(parent);
|
||||||
|
for (auto &dock : dockWidgets) {
|
||||||
|
if (auto memoryWidget = qobject_cast<MemoryDockWidget *>(dock)) {
|
||||||
|
QAction *action = new QAction(memoryWidget->windowTitle(), menu);
|
||||||
|
connect(action, &QAction::triggered, this, [this, memoryWidget, address](){
|
||||||
|
memoryWidget->getSeekable()->seek(address);
|
||||||
|
memoryWidget->raiseMemoryWidget();
|
||||||
|
});
|
||||||
|
menu->addAction(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
menu->addSeparator();
|
||||||
|
auto createAddNewWidgetAction = [this, menu, address](QString label, MemoryWidgetType type) {
|
||||||
|
QAction *action = new QAction(label, menu);
|
||||||
|
connect(action, &QAction::triggered, this, [this, address, type](){
|
||||||
|
addNewMemoryWidget(type, address, true);
|
||||||
|
});
|
||||||
|
menu->addAction(action);
|
||||||
|
};
|
||||||
|
createAddNewWidgetAction(tr("New disassembly"), MemoryWidgetType::Disassembly);
|
||||||
|
createAddNewWidgetAction(tr("New graph"), MemoryWidgetType::Graph);
|
||||||
|
createAddNewWidgetAction(tr("New hexdump"), MemoryWidgetType::Hexdump);
|
||||||
|
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::setCurrentMemoryWidget(MemoryDockWidget *memoryWidget)
|
||||||
|
{
|
||||||
|
if (memoryWidget->getSeekable()->isSynchronized()) {
|
||||||
|
lastMemoryWidget = memoryWidget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryDockWidget *MainWindow::addNewMemoryWidget(MemoryWidgetType type, RVA address,
|
||||||
|
bool synchronized)
|
||||||
|
{
|
||||||
|
MemoryDockWidget *memoryWidget = nullptr;
|
||||||
|
switch (type) {
|
||||||
|
case MemoryWidgetType::Graph:
|
||||||
|
memoryWidget = new GraphWidget(this);
|
||||||
|
break;
|
||||||
|
case MemoryWidgetType::Hexdump:
|
||||||
|
memoryWidget = new HexdumpWidget(this);
|
||||||
|
break;
|
||||||
|
case MemoryWidgetType::Disassembly:
|
||||||
|
memoryWidget = new DisassemblyWidget(this);
|
||||||
|
break;
|
||||||
|
case MemoryWidgetType::Pseudocode:
|
||||||
|
memoryWidget = new PseudocodeWidget(this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto seekable = memoryWidget->getSeekable();
|
||||||
|
seekable->setSynchronization(synchronized);
|
||||||
|
seekable->seek(address);
|
||||||
|
addExtraWidget(memoryWidget);
|
||||||
|
return memoryWidget;
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::initCorners()
|
void MainWindow::initCorners()
|
||||||
{
|
{
|
||||||
// TODO: Allow the user to select this option visually in the GUI settings
|
// TODO: Allow the user to select this option visually in the GUI settings
|
||||||
@ -892,9 +987,21 @@ void MainWindow::addWidget(QDockWidget* widget)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::addMemoryDockWidget(MemoryDockWidget *widget)
|
||||||
|
{
|
||||||
|
connect(widget, &QDockWidget::visibilityChanged, this, [this, widget](bool visibility) {
|
||||||
|
if (visibility) {
|
||||||
|
setCurrentMemoryWidget(widget);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::removeWidget(QDockWidget *widget)
|
void MainWindow::removeWidget(QDockWidget *widget)
|
||||||
{
|
{
|
||||||
dockWidgets.removeAll(widget);
|
dockWidgets.removeAll(widget);
|
||||||
|
if (lastMemoryWidget == widget) {
|
||||||
|
lastMemoryWidget = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::updateDockActionChecked(QAction *action)
|
void MainWindow::updateDockActionChecked(QAction *action)
|
||||||
@ -968,11 +1075,11 @@ void MainWindow::resetToDefaultLayout()
|
|||||||
|
|
||||||
void MainWindow::resetToDebugLayout()
|
void MainWindow::resetToDebugLayout()
|
||||||
{
|
{
|
||||||
CutterCore::MemoryWidgetType memType = core->getMemoryWidgetPriority();
|
MemoryWidgetType memType = getMemoryWidgetTypeToRestore();
|
||||||
hideAllDocks();
|
hideAllDocks();
|
||||||
restoreDocks();
|
restoreDocks();
|
||||||
showDebugDocks();
|
showDebugDocks();
|
||||||
core->raisePrioritizedMemoryWidget(memType);
|
showMemoryWidget(memType);
|
||||||
|
|
||||||
auto restoreStackDock = qhelpers::forceWidth(stackDock->widget(), 400);
|
auto restoreStackDock = qhelpers::forceWidth(stackDock->widget(), 400);
|
||||||
qApp->processEvents();
|
qApp->processEvents();
|
||||||
@ -981,13 +1088,13 @@ void MainWindow::resetToDebugLayout()
|
|||||||
|
|
||||||
void MainWindow::restoreDebugLayout()
|
void MainWindow::restoreDebugLayout()
|
||||||
{
|
{
|
||||||
CutterCore::MemoryWidgetType memType = core->getMemoryWidgetPriority();
|
MemoryWidgetType memType = getMemoryWidgetTypeToRestore();
|
||||||
bool isMaxim = isMaximized();
|
bool isMaxim = isMaximized();
|
||||||
hideAllDocks();
|
hideAllDocks();
|
||||||
restoreDocks();
|
restoreDocks();
|
||||||
showDebugDocks();
|
showDebugDocks();
|
||||||
readDebugSettings();
|
readDebugSettings();
|
||||||
core->raisePrioritizedMemoryWidget(memType);
|
showMemoryWidget(memType);
|
||||||
if (isMaxim) {
|
if (isMaxim) {
|
||||||
showMaximized();
|
showMaximized();
|
||||||
} else {
|
} else {
|
||||||
@ -1319,12 +1426,12 @@ void MainWindow::changeDebugView()
|
|||||||
void MainWindow::changeDefinedView()
|
void MainWindow::changeDefinedView()
|
||||||
{
|
{
|
||||||
saveDebugSettings();
|
saveDebugSettings();
|
||||||
CutterCore::MemoryWidgetType memType = core->getMemoryWidgetPriority();
|
MemoryWidgetType memType = getMemoryWidgetTypeToRestore();
|
||||||
hideAllDocks();
|
hideAllDocks();
|
||||||
restoreDocks();
|
restoreDocks();
|
||||||
readSettingsOrDefault();
|
readSettingsOrDefault();
|
||||||
enableDebugWidgetsMenu(false);
|
enableDebugWidgetsMenu(false);
|
||||||
core->raisePrioritizedMemoryWidget(memType);
|
showMemoryWidget(memType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::mousePressEvent(QMouseEvent *event)
|
void MainWindow::mousePressEvent(QMouseEvent *event)
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "dialogs/WelcomeDialog.h"
|
#include "dialogs/WelcomeDialog.h"
|
||||||
#include "common/Configuration.h"
|
#include "common/Configuration.h"
|
||||||
#include "common/InitialOptions.h"
|
#include "common/InitialOptions.h"
|
||||||
|
#include "MemoryDockWidget.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -54,7 +55,6 @@ namespace Ui {
|
|||||||
class MainWindow;
|
class MainWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
class MainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -95,8 +95,11 @@ public:
|
|||||||
void refreshOmniBar(const QStringList &flags);
|
void refreshOmniBar(const QStringList &flags);
|
||||||
|
|
||||||
void addWidget(QDockWidget *widget);
|
void addWidget(QDockWidget *widget);
|
||||||
|
void addMemoryDockWidget(MemoryDockWidget *widget);
|
||||||
void removeWidget(QDockWidget *widget);
|
void removeWidget(QDockWidget *widget);
|
||||||
void addExtraWidget(CutterDockWidget *extraDock);
|
void addExtraWidget(CutterDockWidget *extraDock);
|
||||||
|
MemoryDockWidget *addNewMemoryWidget(MemoryWidgetType type, RVA address, bool synchronized = true);
|
||||||
|
|
||||||
|
|
||||||
void addPluginDockWidget(QDockWidget *dockWidget, QAction *action);
|
void addPluginDockWidget(QDockWidget *dockWidget, QAction *action);
|
||||||
enum class MenuType { File, Edit, View, Windows, Debug, Help, Plugins };
|
enum class MenuType { File, Edit, View, Windows, Debug, Help, Plugins };
|
||||||
@ -112,6 +115,11 @@ public:
|
|||||||
void messageBoxWarning(QString title, QString message);
|
void messageBoxWarning(QString title, QString message);
|
||||||
|
|
||||||
QString getUniqueObjectName(const QString &widgetType) const;
|
QString getUniqueObjectName(const QString &widgetType) const;
|
||||||
|
void showMemoryWidget();
|
||||||
|
void showMemoryWidget(MemoryWidgetType type);
|
||||||
|
|
||||||
|
QMenu *createShowInMenu(QWidget *parent, RVA address);
|
||||||
|
void setCurrentMemoryWidget(MemoryDockWidget* memoryWidget);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void finalizeOpen();
|
void finalizeOpen();
|
||||||
@ -271,10 +279,14 @@ private:
|
|||||||
void setOverviewData();
|
void setOverviewData();
|
||||||
bool isOverviewActive();
|
bool isOverviewActive();
|
||||||
|
|
||||||
|
MemoryWidgetType getMemoryWidgetTypeToRestore();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Map from a widget type (e.g. DisassemblyWidget::getWidgetType()) to the respective contructor of the widget
|
* @brief Map from a widget type (e.g. DisassemblyWidget::getWidgetType()) to the respective contructor of the widget
|
||||||
*/
|
*/
|
||||||
QMap<QString, std::function<CutterDockWidget*(MainWindow*, QAction*)>> widgetTypeToConstructorMap;
|
QMap<QString, std::function<CutterDockWidget*(MainWindow*, QAction*)>> widgetTypeToConstructorMap;
|
||||||
|
|
||||||
|
MemoryDockWidget* lastMemoryWidget = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAINWINDOW_H
|
#endif // MAINWINDOW_H
|
||||||
|
@ -67,7 +67,7 @@ void LinkTypeDialog::done(int r)
|
|||||||
QDialog::done(r);
|
QDialog::done(r);
|
||||||
|
|
||||||
// Seek to the specified address
|
// Seek to the specified address
|
||||||
Core()->seek(address);
|
Core()->seekAndShow(address);
|
||||||
|
|
||||||
// Refresh the views
|
// Refresh the views
|
||||||
emit Core()->refreshCodeViews();
|
emit Core()->refreshCodeViews();
|
||||||
|
@ -75,7 +75,7 @@ void XrefsDialog::on_fromTreeWidget_itemDoubleClicked(QTreeWidgetItem *item, int
|
|||||||
Q_UNUSED(column);
|
Q_UNUSED(column);
|
||||||
|
|
||||||
XrefDescription xref = item->data(0, Qt::UserRole).value<XrefDescription>();
|
XrefDescription xref = item->data(0, Qt::UserRole).value<XrefDescription>();
|
||||||
Core()->seek(xref.to);
|
Core()->seekAndShow(xref.to);
|
||||||
this->close();
|
this->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ void XrefsDialog::on_toTreeWidget_itemDoubleClicked(QTreeWidgetItem *item, int c
|
|||||||
Q_UNUSED(column);
|
Q_UNUSED(column);
|
||||||
|
|
||||||
XrefDescription xref = item->data(0, Qt::UserRole).value<XrefDescription>();
|
XrefDescription xref = item->data(0, Qt::UserRole).value<XrefDescription>();
|
||||||
Core()->seek(xref.from);
|
Core()->seekAndShow(xref.from);
|
||||||
this->close();
|
this->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "dialogs/SetToDataDialog.h"
|
#include "dialogs/SetToDataDialog.h"
|
||||||
#include "dialogs/EditFunctionDialog.h"
|
#include "dialogs/EditFunctionDialog.h"
|
||||||
#include "dialogs/LinkTypeDialog.h"
|
#include "dialogs/LinkTypeDialog.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
|
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
@ -17,10 +18,11 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
|
|
||||||
DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent)
|
DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow* mainWindow)
|
||||||
: QMenu(parent),
|
: QMenu(parent),
|
||||||
offset(0),
|
offset(0),
|
||||||
canCopy(false)
|
canCopy(false),
|
||||||
|
mainWindow(mainWindow)
|
||||||
{
|
{
|
||||||
initAction(&actionCopy, tr("Copy"), SLOT(on_actionCopy_triggered()), getCopySequence());
|
initAction(&actionCopy, tr("Copy"), SLOT(on_actionCopy_triggered()), getCopySequence());
|
||||||
addAction(&actionCopy);
|
addAction(&actionCopy);
|
||||||
@ -28,6 +30,9 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent)
|
|||||||
initAction(&actionCopyAddr, tr("Copy address"), SLOT(on_actionCopyAddr_triggered()), getCopyAddressSequence());
|
initAction(&actionCopyAddr, tr("Copy address"), SLOT(on_actionCopyAddr_triggered()), getCopyAddressSequence());
|
||||||
addAction(&actionCopyAddr);
|
addAction(&actionCopyAddr);
|
||||||
|
|
||||||
|
initAction(&showInSubmenu, tr("Show in"), nullptr);
|
||||||
|
addAction(&showInSubmenu);
|
||||||
|
|
||||||
copySeparator = addSeparator();
|
copySeparator = addSeparator();
|
||||||
|
|
||||||
initAction(&actionAddComment, tr("Add Comment"),
|
initAction(&actionAddComment, tr("Add Comment"),
|
||||||
@ -379,6 +384,11 @@ void DisassemblyContextMenu::aboutToShowSlot()
|
|||||||
// Decide to show Reverse jmp option
|
// Decide to show Reverse jmp option
|
||||||
showReverseJmpQuery();
|
showReverseJmpQuery();
|
||||||
|
|
||||||
|
if (showInSubmenu.menu() != nullptr) {
|
||||||
|
showInSubmenu.menu()->deleteLater();
|
||||||
|
}
|
||||||
|
showInSubmenu.setMenu(mainWindow->createShowInMenu(this, offset));
|
||||||
|
|
||||||
// Only show debug options if we are currently debugging
|
// Only show debug options if we are currently debugging
|
||||||
debugMenu->menuAction()->setVisible(Core()->currentlyDebugging);
|
debugMenu->menuAction()->setVisible(Core()->currentlyDebugging);
|
||||||
QString progCounterName = Core()->getRegisterName("PC");
|
QString progCounterName = Core()->getRegisterName("PC");
|
||||||
|
@ -10,7 +10,7 @@ class DisassemblyContextMenu : public QMenu
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DisassemblyContextMenu(QWidget *parent = nullptr);
|
DisassemblyContextMenu(QWidget *parent, MainWindow* mainWindow);
|
||||||
~DisassemblyContextMenu();
|
~DisassemblyContextMenu();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@ -101,6 +101,7 @@ private:
|
|||||||
RVA offset;
|
RVA offset;
|
||||||
bool canCopy;
|
bool canCopy;
|
||||||
QString curHighlightedWord; // The current highlighted word
|
QString curHighlightedWord; // The current highlighted word
|
||||||
|
MainWindow* mainWindow;
|
||||||
|
|
||||||
QList<QAction *> anonymousActions;
|
QList<QAction *> anonymousActions;
|
||||||
|
|
||||||
@ -164,6 +165,8 @@ private:
|
|||||||
QAction actionSetToDataDword;
|
QAction actionSetToDataDword;
|
||||||
QAction actionSetToDataQword;
|
QAction actionSetToDataQword;
|
||||||
|
|
||||||
|
QAction showInSubmenu;
|
||||||
|
|
||||||
// For creating anonymous entries (that are always visible)
|
// For creating anonymous entries (that are always visible)
|
||||||
QAction *addAnonymousAction(QString name, const char *slot, QKeySequence shortcut);
|
QAction *addAnonymousAction(QString name, const char *slot, QKeySequence shortcut);
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ void BreakpointWidget::on_breakpointTreeView_doubleClicked(const QModelIndex &in
|
|||||||
{
|
{
|
||||||
BreakpointDescription item = index.data(
|
BreakpointDescription item = index.data(
|
||||||
BreakpointModel::BreakpointDescriptionRole).value<BreakpointDescription>();
|
BreakpointModel::BreakpointDescriptionRole).value<BreakpointDescription>();
|
||||||
Core()->seek(item.addr);
|
Core()->seekAndShow(item.addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BreakpointWidget::showBreakpointContextMenu(const QPoint &pt)
|
void BreakpointWidget::showBreakpointContextMenu(const QPoint &pt)
|
||||||
|
@ -634,7 +634,7 @@ void ClassesWidget::on_classesTreeView_doubleClicked(const QModelIndex &index)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RVA offset = offsetData.value<RVA>();
|
RVA offset = offsetData.value<RVA>();
|
||||||
Core()->seek(offset);
|
Core()->seekAndShow(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassesWidget::showContextMenu(const QPoint &pt)
|
void ClassesWidget::showContextMenu(const QPoint &pt)
|
||||||
@ -696,7 +696,7 @@ void ClassesWidget::on_seekToVTableAction_triggered()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core()->seek(vtables[0].addr + desc.vtableOffset);
|
Core()->seekAndShow(vtables[0].addr + desc.vtableOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassesWidget::on_addMethodAction_triggered()
|
void ClassesWidget::on_addMethodAction_triggered()
|
||||||
|
@ -272,7 +272,7 @@ void CommentsWidget::on_commentsTreeView_doubleClicked(const QModelIndex &index)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
auto comment = index.data(CommentsModel::CommentDescriptionRole).value<CommentDescription>();
|
auto comment = index.data(CommentsModel::CommentDescriptionRole).value<CommentDescription>();
|
||||||
Core()->seek(comment.offset);
|
Core()->seekAndShow(comment.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommentsWidget::on_actionHorizontal_triggered()
|
void CommentsWidget::on_actionHorizontal_triggered()
|
||||||
|
@ -86,3 +86,15 @@ QAction *CutterDockWidget::getBoundAction() const
|
|||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString CutterDockWidget::getDockNumber()
|
||||||
|
{
|
||||||
|
auto name = this->objectName();
|
||||||
|
if (name.contains(';')) {
|
||||||
|
auto parts = name.split(';');
|
||||||
|
if (parts.size() >= 2) {
|
||||||
|
return parts[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -67,9 +67,11 @@ protected:
|
|||||||
|
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
QAction *getBoundAction() const;
|
QAction *getBoundAction() const;
|
||||||
|
QString getDockNumber();
|
||||||
|
|
||||||
|
MainWindow *mainWindow;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MainWindow *mainWindow;
|
|
||||||
QAction *action;
|
QAction *action;
|
||||||
|
|
||||||
bool isTransient = false;
|
bool isTransient = false;
|
||||||
|
@ -29,10 +29,10 @@
|
|||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
DisassemblerGraphView::DisassemblerGraphView(QWidget *parent, CutterSeekable* seekable)
|
DisassemblerGraphView::DisassemblerGraphView(QWidget *parent, CutterSeekable* seekable, MainWindow* mainWindow)
|
||||||
: GraphView(parent),
|
: GraphView(parent),
|
||||||
mFontMetrics(nullptr),
|
mFontMetrics(nullptr),
|
||||||
blockMenu(new DisassemblyContextMenu(this)),
|
blockMenu(new DisassemblyContextMenu(this, mainWindow)),
|
||||||
contextMenu(new QMenu(this)),
|
contextMenu(new QMenu(this)),
|
||||||
seekable(seekable)
|
seekable(seekable)
|
||||||
{
|
{
|
||||||
@ -55,13 +55,6 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent, CutterSeekable* se
|
|||||||
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdatedSlot()));
|
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdatedSlot()));
|
||||||
connectSeekChanged(false);
|
connectSeekChanged(false);
|
||||||
|
|
||||||
// Space to switch to disassembly
|
|
||||||
QShortcut *shortcut_disassembly = new QShortcut(QKeySequence(Qt::Key_Space), this);
|
|
||||||
shortcut_disassembly->setContext(Qt::WidgetShortcut);
|
|
||||||
connect(shortcut_disassembly, &QShortcut::activated, this, [] {
|
|
||||||
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Disassembly);
|
|
||||||
Core()->triggerRaisePrioritizedMemoryWidget();
|
|
||||||
});
|
|
||||||
// ESC for previous
|
// ESC for previous
|
||||||
QShortcut *shortcut_escape = new QShortcut(QKeySequence(Qt::Key_Escape), this);
|
QShortcut *shortcut_escape = new QShortcut(QKeySequence(Qt::Key_Escape), this);
|
||||||
shortcut_escape->setContext(Qt::WidgetShortcut);
|
shortcut_escape->setContext(Qt::WidgetShortcut);
|
||||||
@ -95,7 +88,6 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent, CutterSeekable* se
|
|||||||
QShortcut *shortcut_prev_instr = new QShortcut(QKeySequence(Qt::Key_K), this);
|
QShortcut *shortcut_prev_instr = new QShortcut(QKeySequence(Qt::Key_K), this);
|
||||||
shortcut_prev_instr->setContext(Qt::WidgetShortcut);
|
shortcut_prev_instr->setContext(Qt::WidgetShortcut);
|
||||||
connect(shortcut_prev_instr, SIGNAL(activated()), this, SLOT(prevInstr()));
|
connect(shortcut_prev_instr, SIGNAL(activated()), this, SLOT(prevInstr()));
|
||||||
shortcuts.append(shortcut_disassembly);
|
|
||||||
shortcuts.append(shortcut_escape);
|
shortcuts.append(shortcut_escape);
|
||||||
shortcuts.append(shortcut_zoom_in);
|
shortcuts.append(shortcut_zoom_in);
|
||||||
shortcuts.append(shortcut_zoom_out);
|
shortcuts.append(shortcut_zoom_out);
|
||||||
|
@ -87,7 +87,7 @@ class DisassemblerGraphView : public GraphView
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DisassemblerGraphView(QWidget *parent, CutterSeekable* seekable);
|
DisassemblerGraphView(QWidget *parent, CutterSeekable* seekable, MainWindow* mainWindow);
|
||||||
~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;
|
||||||
|
@ -39,8 +39,8 @@ static DisassemblyTextBlockUserData *getUserData(const QTextBlock &block)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action)
|
DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action)
|
||||||
: MemoryDockWidget(CutterCore::MemoryWidgetType::Disassembly, main, action)
|
: MemoryDockWidget(MemoryWidgetType::Disassembly, main, action)
|
||||||
, mCtxMenu(new DisassemblyContextMenu(this))
|
, mCtxMenu(new DisassemblyContextMenu(this, main))
|
||||||
, mDisasScrollArea(new DisassemblyScrollArea(this))
|
, mDisasScrollArea(new DisassemblyScrollArea(this))
|
||||||
, mDisasTextEdit(new DisassemblyTextEdit(this))
|
, mDisasTextEdit(new DisassemblyTextEdit(this))
|
||||||
{
|
{
|
||||||
@ -161,14 +161,6 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action)
|
|||||||
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdatedSlot()));
|
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdatedSlot()));
|
||||||
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
|
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
|
||||||
|
|
||||||
connect(this, &QDockWidget::visibilityChanged, this, [](bool visibility) {
|
|
||||||
bool emptyGraph = (Core()->getMemoryWidgetPriority() == CutterCore::MemoryWidgetType::Graph
|
|
||||||
&& Core()->isGraphEmpty());
|
|
||||||
if (visibility && !emptyGraph) {
|
|
||||||
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Disassembly);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(Core(), &CutterCore::refreshAll, this, [this]() {
|
connect(Core(), &CutterCore::refreshAll, this, [this]() {
|
||||||
refreshDisasm(seekable->getOffset());
|
refreshDisasm(seekable->getOffset());
|
||||||
});
|
});
|
||||||
@ -192,9 +184,8 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action)
|
|||||||
connect(a, &QAction::triggered, this, (slot)); }
|
connect(a, &QAction::triggered, this, (slot)); }
|
||||||
|
|
||||||
// Space to switch to graph
|
// Space to switch to graph
|
||||||
ADD_ACTION(Qt::Key_Space, Qt::WidgetWithChildrenShortcut, [] {
|
ADD_ACTION(Qt::Key_Space, Qt::WidgetWithChildrenShortcut, [this] {
|
||||||
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Graph);
|
mainWindow->showMemoryWidget(MemoryWidgetType::Graph);
|
||||||
Core()->triggerRaisePrioritizedMemoryWidget();
|
|
||||||
})
|
})
|
||||||
|
|
||||||
ADD_ACTION(Qt::Key_Escape, Qt::WidgetWithChildrenShortcut, &DisassemblyWidget::seekPrev)
|
ADD_ACTION(Qt::Key_Escape, Qt::WidgetWithChildrenShortcut, &DisassemblyWidget::seekPrev)
|
||||||
|
@ -51,5 +51,5 @@ void EntrypointWidget::on_entrypointTreeWidget_itemDoubleClicked(QTreeWidgetItem
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
EntrypointDescription ep = item->data(0, Qt::UserRole).value<EntrypointDescription>();
|
EntrypointDescription ep = item->data(0, Qt::UserRole).value<EntrypointDescription>();
|
||||||
Core()->seek(ep.vaddr);
|
Core()->seekAndShow(ep.vaddr);
|
||||||
}
|
}
|
||||||
|
@ -183,5 +183,5 @@ void ExportsWidget::on_exportsTreeView_doubleClicked(const QModelIndex &index)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
ExportDescription exp = index.data(ExportsModel::ExportDescriptionRole).value<ExportDescription>();
|
ExportDescription exp = index.data(ExportsModel::ExportDescriptionRole).value<ExportDescription>();
|
||||||
Core()->seek(exp.vaddr);
|
Core()->seekAndShow(exp.vaddr);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ void FlagsWidget::on_flagsTreeView_doubleClicked(const QModelIndex &index)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
FlagDescription flag = index.data(FlagsModel::FlagDescriptionRole).value<FlagDescription>();
|
FlagDescription flag = index.data(FlagsModel::FlagDescriptionRole).value<FlagDescription>();
|
||||||
Core()->seek(flag.offset);
|
Core()->seekAndShow(flag.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlagsWidget::on_flagspaceCombo_currentTextChanged(const QString &arg1)
|
void FlagsWidget::on_flagspaceCombo_currentTextChanged(const QString &arg1)
|
||||||
|
@ -522,7 +522,7 @@ void FunctionsWidget::onFunctionsDoubleClicked(const QModelIndex &index)
|
|||||||
|
|
||||||
FunctionDescription function = index.data(
|
FunctionDescription function = index.data(
|
||||||
FunctionModel::FunctionDescriptionRole).value<FunctionDescription>();
|
FunctionModel::FunctionDescriptionRole).value<FunctionDescription>();
|
||||||
Core()->seek(function.offset);
|
Core()->seekAndShow(function.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionsWidget::showFunctionsContextMenu(const QPoint &pt)
|
void FunctionsWidget::showFunctionsContextMenu(const QPoint &pt)
|
||||||
@ -556,7 +556,7 @@ void FunctionsWidget::on_actionDisasAdd_comment_triggered()
|
|||||||
// Rename function in r2 core
|
// Rename function in r2 core
|
||||||
Core()->setComment(function.offset, comment);
|
Core()->setComment(function.offset, comment);
|
||||||
// Seek to new renamed function
|
// Seek to new renamed function
|
||||||
Core()->seek(function.offset);
|
Core()->seekAndShow(function.offset);
|
||||||
// TODO: Refresh functions tree widget
|
// TODO: Refresh functions tree widget
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -581,7 +581,7 @@ void FunctionsWidget::on_actionFunctionsRename_triggered()
|
|||||||
Core()->renameFunction(function.name, new_name);
|
Core()->renameFunction(function.name, new_name);
|
||||||
|
|
||||||
// Seek to new renamed function
|
// Seek to new renamed function
|
||||||
Core()->seek(function.offset);
|
Core()->seekAndShow(function.offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
|
GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
|
||||||
MemoryDockWidget(CutterCore::MemoryWidgetType::Graph, main, action)
|
MemoryDockWidget(MemoryWidgetType::Graph, main, action)
|
||||||
{
|
{
|
||||||
setObjectName(main
|
setObjectName(main
|
||||||
? main->getUniqueObjectName(getWidgetType())
|
? main->getUniqueObjectName(getWidgetType())
|
||||||
@ -23,7 +23,7 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
|
|||||||
header->setReadOnly(true);
|
header->setReadOnly(true);
|
||||||
layout->addWidget(header);
|
layout->addWidget(header);
|
||||||
|
|
||||||
graphView = new DisassemblerGraphView(layoutWidget, seekable);
|
graphView = new DisassemblerGraphView(layoutWidget, seekable, main);
|
||||||
layout->addWidget(graphView);
|
layout->addWidget(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
|
||||||
@ -40,16 +40,24 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
|
|||||||
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) {
|
||||||
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Graph);
|
|
||||||
graphView->onSeekChanged(Core()->getOffset());
|
graphView->onSeekChanged(Core()->getOffset());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QAction *switchAction = new QAction(this);
|
||||||
|
switchAction->setShortcut(Qt::Key_Space);
|
||||||
|
switchAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||||
|
addAction(switchAction);
|
||||||
|
connect(switchAction, &QAction::triggered, this, [this] {
|
||||||
|
mainWindow->showMemoryWidget(MemoryWidgetType::Disassembly);
|
||||||
|
});
|
||||||
|
|
||||||
connect(graphView, &DisassemblerGraphView::graphMoved, this, [ = ]() {
|
connect(graphView, &DisassemblerGraphView::graphMoved, this, [ = ]() {
|
||||||
main->toggleOverview(true, this);
|
main->toggleOverview(true, this);
|
||||||
});
|
});
|
||||||
connect(seekable, &CutterSeekable::seekableSeekChanged, this, &GraphWidget::prepareHeader);
|
connect(seekable, &CutterSeekable::seekableSeekChanged, this, &GraphWidget::prepareHeader);
|
||||||
connect(Core(), &CutterCore::functionRenamed, this, &GraphWidget::prepareHeader);
|
connect(Core(), &CutterCore::functionRenamed, this, &GraphWidget::prepareHeader);
|
||||||
|
graphView->installEventFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *GraphWidget::widgetToFocusOnRaise()
|
QWidget *GraphWidget::widgetToFocusOnRaise()
|
||||||
|
@ -134,5 +134,5 @@ void HeadersWidget::setScrollMode()
|
|||||||
void HeadersWidget::on_headersTreeView_doubleClicked(const QModelIndex &index)
|
void HeadersWidget::on_headersTreeView_doubleClicked(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
HeaderDescription item = index.data(HeadersModel::HeaderDescriptionRole).value<HeaderDescription>();
|
HeaderDescription item = index.data(HeadersModel::HeaderDescriptionRole).value<HeaderDescription>();
|
||||||
Core()->seek(item.vaddr);
|
Core()->seekAndShow(item.vaddr);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#include <QShortcut>
|
#include <QShortcut>
|
||||||
|
|
||||||
HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) :
|
HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) :
|
||||||
MemoryDockWidget(CutterCore::MemoryWidgetType::Hexdump, main, action),
|
MemoryDockWidget(MemoryWidgetType::Hexdump, main, action),
|
||||||
ui(new Ui::HexdumpWidget)
|
ui(new Ui::HexdumpWidget)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
@ -78,13 +78,6 @@ HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) :
|
|||||||
this->ui->hexTextView->addAction(&syncAction);
|
this->ui->hexTextView->addAction(&syncAction);
|
||||||
|
|
||||||
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdated()));
|
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdated()));
|
||||||
|
|
||||||
connect(this, &QDockWidget::visibilityChanged, this, [](bool visibility) {
|
|
||||||
if (visibility) {
|
|
||||||
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Hexdump);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(Core(), &CutterCore::refreshAll, this, [this]() { refresh(); });
|
connect(Core(), &CutterCore::refreshAll, this, [this]() { refresh(); });
|
||||||
|
|
||||||
connect(seekable, &CutterSeekable::seekableSeekChanged, this, &HexdumpWidget::onSeekChanged);
|
connect(seekable, &CutterSeekable::seekableSeekChanged, this, &HexdumpWidget::onSeekChanged);
|
||||||
@ -97,6 +90,7 @@ HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) :
|
|||||||
});
|
});
|
||||||
connect(ui->hexTextView, &HexWidget::selectionChanged, this, &HexdumpWidget::selectionChanged);
|
connect(ui->hexTextView, &HexWidget::selectionChanged, this, &HexdumpWidget::selectionChanged);
|
||||||
connect(ui->hexSideTab_2, &QTabWidget::currentChanged, this, &HexdumpWidget::refreshSelectionInfo);
|
connect(ui->hexSideTab_2, &QTabWidget::currentChanged, this, &HexdumpWidget::refreshSelectionInfo);
|
||||||
|
ui->hexTextView->installEventFilter(this);
|
||||||
|
|
||||||
initParsing();
|
initParsing();
|
||||||
selectHexPreview();
|
selectHexPreview();
|
||||||
|
@ -194,5 +194,5 @@ void ImportsWidget::on_importsTreeView_doubleClicked(const QModelIndex &index)
|
|||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Core()->seek(index.data(ImportsModel::AddressRole).toLongLong());
|
Core()->seekAndShow(index.data(ImportsModel::AddressRole).toLongLong());
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,36 @@
|
|||||||
#include "MemoryDockWidget.h"
|
#include "MemoryDockWidget.h"
|
||||||
#include "common/CutterSeekable.h"
|
#include "common/CutterSeekable.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
#include <QEvent>
|
||||||
|
|
||||||
MemoryDockWidget::MemoryDockWidget(CutterCore::MemoryWidgetType type, MainWindow *parent, QAction *action)
|
MemoryDockWidget::MemoryDockWidget(MemoryWidgetType type, MainWindow *parent, QAction *action)
|
||||||
: CutterDockWidget(parent, action)
|
: CutterDockWidget(parent, action)
|
||||||
, mType(type), seekable(new CutterSeekable(this))
|
, mType(type), seekable(new CutterSeekable(this))
|
||||||
{
|
{
|
||||||
connect(Core(), &CutterCore::raisePrioritizedMemoryWidget, this, &MemoryDockWidget::handleRaiseMemoryWidget);
|
if (parent) {
|
||||||
|
parent->addMemoryDockWidget(this);
|
||||||
|
}
|
||||||
connect(seekable, &CutterSeekable::syncChanged, this, &MemoryDockWidget::updateWindowTitle);
|
connect(seekable, &CutterSeekable::syncChanged, this, &MemoryDockWidget::updateWindowTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryDockWidget::handleRaiseMemoryWidget(CutterCore::MemoryWidgetType raiseType)
|
bool MemoryDockWidget::tryRaiseMemoryWidget()
|
||||||
{
|
{
|
||||||
if (!seekable->isSynchronized()) {
|
if (!seekable->isSynchronized()) {
|
||||||
return;
|
return false;
|
||||||
}
|
|
||||||
bool raisingEmptyGraph = (raiseType == CutterCore::MemoryWidgetType::Graph && Core()->isGraphEmpty());
|
|
||||||
if (raisingEmptyGraph) {
|
|
||||||
raiseType = CutterCore::MemoryWidgetType::Disassembly;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (raiseType == mType) {
|
if (mType == MemoryWidgetType::Graph && Core()->isGraphEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
raiseMemoryWidget();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryDockWidget::raiseMemoryWidget()
|
||||||
|
{
|
||||||
|
|
||||||
if (getBoundAction()) {
|
if (getBoundAction()) {
|
||||||
getBoundAction()->setChecked(true);
|
getBoundAction()->setChecked(true);
|
||||||
}
|
}
|
||||||
@ -30,15 +39,26 @@ void MemoryDockWidget::handleRaiseMemoryWidget(CutterCore::MemoryWidgetType rais
|
|||||||
raise();
|
raise();
|
||||||
widgetToFocusOnRaise()->setFocus(Qt::FocusReason::TabFocusReason);
|
widgetToFocusOnRaise()->setFocus(Qt::FocusReason::TabFocusReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MemoryDockWidget::eventFilter(QObject *object, QEvent *event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::FocusIn) {
|
||||||
|
mainWindow->setCurrentMemoryWidget(this);
|
||||||
|
}
|
||||||
|
return CutterDockWidget::eventFilter(object, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryDockWidget::updateWindowTitle()
|
void MemoryDockWidget::updateWindowTitle()
|
||||||
{
|
{
|
||||||
if (seekable->isSynchronized()) {
|
QString name = getWindowTitle();
|
||||||
setWindowTitle(getWindowTitle());
|
QString id = getDockNumber();
|
||||||
} else {
|
if (!id.isEmpty()) {
|
||||||
setWindowTitle(getWindowTitle() + CutterSeekable::tr(" (unsynced)"));
|
name += " " + id;
|
||||||
}
|
}
|
||||||
|
if (!seekable->isSynchronized()) {
|
||||||
|
name += CutterSeekable::tr(" (unsynced)");
|
||||||
|
}
|
||||||
|
setWindowTitle(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
CutterSeekable* MemoryDockWidget::getSeekable() const
|
CutterSeekable* MemoryDockWidget::getSeekable() const
|
||||||
|
@ -6,19 +6,28 @@
|
|||||||
|
|
||||||
class CutterSeekable;
|
class CutterSeekable;
|
||||||
|
|
||||||
|
/* Disassembly/Graph/Hexdump/Pseudocode view priority */
|
||||||
|
enum class MemoryWidgetType { Disassembly, Graph, Hexdump, Pseudocode };
|
||||||
|
|
||||||
class MemoryDockWidget : public CutterDockWidget
|
class MemoryDockWidget : public CutterDockWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
MemoryDockWidget(CutterCore::MemoryWidgetType type, MainWindow *parent, QAction *action = nullptr);
|
MemoryDockWidget(MemoryWidgetType type, MainWindow *parent, QAction *action = nullptr);
|
||||||
~MemoryDockWidget() {}
|
~MemoryDockWidget() {}
|
||||||
|
|
||||||
CutterSeekable* getSeekable() const;
|
CutterSeekable* getSeekable() const;
|
||||||
|
|
||||||
|
bool tryRaiseMemoryWidget();
|
||||||
|
void raiseMemoryWidget();
|
||||||
|
MemoryWidgetType getType() const
|
||||||
|
{
|
||||||
|
return mType;
|
||||||
|
}
|
||||||
|
bool eventFilter(QObject *object, QEvent *event);
|
||||||
private:
|
private:
|
||||||
void handleRaiseMemoryWidget(CutterCore::MemoryWidgetType raiseType);
|
|
||||||
|
|
||||||
CutterCore::MemoryWidgetType mType;
|
MemoryWidgetType mType;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateWindowTitle();
|
void updateWindowTitle();
|
||||||
|
@ -152,5 +152,5 @@ void MemoryMapWidget::on_memoryTreeView_doubleClicked(const QModelIndex &index)
|
|||||||
{
|
{
|
||||||
MemoryMapDescription item = index.data(
|
MemoryMapDescription item = index.data(
|
||||||
MemoryMapModel::MemoryDescriptionRole).value<MemoryMapDescription>();
|
MemoryMapModel::MemoryDescriptionRole).value<MemoryMapDescription>();
|
||||||
Core()->seek(item.addrStart);
|
Core()->seekAndShow(item.addrStart);
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ void Omnibar::on_gotoEntry_returnPressed()
|
|||||||
{
|
{
|
||||||
QString str = this->text();
|
QString str = this->text();
|
||||||
if (!str.isEmpty()) {
|
if (!str.isEmpty()) {
|
||||||
Core()->seek(str);
|
Core()->seekAndShow(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->setText("");
|
this->setText("");
|
||||||
|
@ -35,7 +35,7 @@ struct DecompiledCodeTextLine
|
|||||||
|
|
||||||
|
|
||||||
PseudocodeWidget::PseudocodeWidget(MainWindow *main, QAction *action) :
|
PseudocodeWidget::PseudocodeWidget(MainWindow *main, QAction *action) :
|
||||||
MemoryDockWidget(CutterCore::MemoryWidgetType::Pseudocode, main, action),
|
MemoryDockWidget(MemoryWidgetType::Pseudocode, main, action),
|
||||||
ui(new Ui::PseudocodeWidget)
|
ui(new Ui::PseudocodeWidget)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
@ -48,12 +48,6 @@ PseudocodeWidget::PseudocodeWidget(MainWindow *main, QAction *action) :
|
|||||||
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdated()));
|
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdated()));
|
||||||
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
|
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
|
||||||
|
|
||||||
connect(this, &QDockWidget::visibilityChanged, this, [](bool visibility) {
|
|
||||||
if (visibility) {
|
|
||||||
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Pseudocode);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO Use RefreshDeferrer and remove the refresh button
|
// TODO Use RefreshDeferrer and remove the refresh button
|
||||||
connect(ui->refreshButton, &QAbstractButton::clicked, this, [this]() {
|
connect(ui->refreshButton, &QAbstractButton::clicked, this, [this]() {
|
||||||
doRefresh(Core()->getOffset());
|
doRefresh(Core()->getOffset());
|
||||||
|
@ -179,7 +179,7 @@ void RegisterRefsWidget::on_registerRefTreeView_doubleClicked(const QModelIndex
|
|||||||
{
|
{
|
||||||
RegisterRefDescription item = index.data(
|
RegisterRefDescription item = index.data(
|
||||||
RegisterRefModel::RegisterRefDescriptionRole).value<RegisterRefDescription>();
|
RegisterRefModel::RegisterRefDescriptionRole).value<RegisterRefDescription>();
|
||||||
Core()->seek(item.value);
|
Core()->seekAndShow(item.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterRefsWidget::showRegRefContextMenu(const QPoint &pt)
|
void RegisterRefsWidget::showRegRefContextMenu(const QPoint &pt)
|
||||||
|
@ -147,7 +147,7 @@ void RelocsWidget::on_relocsTreeView_doubleClicked(const QModelIndex &index)
|
|||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Core()->seek(index.data(RelocsModel::AddressRole).toLongLong());
|
Core()->seekAndShow(index.data(RelocsModel::AddressRole).toLongLong());
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelocsWidget::refreshRelocs()
|
void RelocsWidget::refreshRelocs()
|
||||||
|
@ -107,5 +107,5 @@ void ResourcesWidget::onDoubleClicked(const QModelIndex &index)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
ResourcesDescription res = index.data(Qt::UserRole).value<ResourcesDescription>();
|
ResourcesDescription res = index.data(Qt::UserRole).value<ResourcesDescription>();
|
||||||
Core()->seek(res.vaddr);
|
Core()->seekAndShow(res.vaddr);
|
||||||
}
|
}
|
||||||
|
@ -206,7 +206,7 @@ void SearchWidget::on_searchTreeView_doubleClicked(const QModelIndex &index)
|
|||||||
|
|
||||||
SearchDescription search = index.data(
|
SearchDescription search = index.data(
|
||||||
SearchModel::SearchDescriptionRole).value<SearchDescription>();
|
SearchModel::SearchDescriptionRole).value<SearchDescription>();
|
||||||
Core()->seek(search.offset);
|
Core()->seekAndShow(search.offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchWidget::searchChanged()
|
void SearchWidget::searchChanged()
|
||||||
|
@ -303,7 +303,7 @@ void SectionsWidget::onSectionsDoubleClicked(const QModelIndex &index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto section = index.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>();
|
auto section = index.data(SectionsModel::SectionDescriptionRole).value<SectionDescription>();
|
||||||
Core()->seek(section.vaddr);
|
Core()->seekAndShow(section.vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SectionsWidget::resizeEvent(QResizeEvent *event) {
|
void SectionsWidget::resizeEvent(QResizeEvent *event) {
|
||||||
@ -470,7 +470,7 @@ void AddrDockScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
if (event->buttons() & Qt::LeftButton) {
|
if (event->buttons() & Qt::LeftButton) {
|
||||||
RVA seekAddr = getAddrFromPos((int)event->scenePos().y(), true);
|
RVA seekAddr = getAddrFromPos((int)event->scenePos().y(), true);
|
||||||
disableCenterOn = true;
|
disableCenterOn = true;
|
||||||
Core()->seek(seekAddr);
|
Core()->seekAndShow(seekAddr);
|
||||||
disableCenterOn = false;
|
disableCenterOn = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -188,5 +188,5 @@ void SegmentsWidget::onSegmentsDoubleClicked(const QModelIndex &index)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
auto segment = index.data(SegmentsModel::SegmentDescriptionRole).value<SegmentDescription>();
|
auto segment = index.data(SegmentsModel::SegmentDescriptionRole).value<SegmentDescription>();
|
||||||
Core()->seek(segment.vaddr);
|
Core()->seekAndShow(segment.vaddr);
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ void StackWidget::onDoubleClicked(const QModelIndex &index)
|
|||||||
// Check if we are clicking on the offset or value columns and seek if it is the case
|
// Check if we are clicking on the offset or value columns and seek if it is the case
|
||||||
if (index.column() <= 1) {
|
if (index.column() <= 1) {
|
||||||
QString item = index.data().toString();
|
QString item = index.data().toString();
|
||||||
Core()->seek(item);
|
Core()->seekAndShow(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ void StackWidget::customMenuRequested(QPoint pos)
|
|||||||
void StackWidget::seekOffset()
|
void StackWidget::seekOffset()
|
||||||
{
|
{
|
||||||
QString offset = viewStack->selectionModel()->currentIndex().data().toString();
|
QString offset = viewStack->selectionModel()->currentIndex().data().toString();
|
||||||
Core()->seek(offset);
|
Core()->seekAndShow(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StackWidget::editStack()
|
void StackWidget::editStack()
|
||||||
|
@ -204,7 +204,7 @@ void StringsWidget::on_stringsTreeView_doubleClicked(const QModelIndex &index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
StringDescription str = index.data(StringsModel::StringDescriptionRole).value<StringDescription>();
|
StringDescription str = index.data(StringsModel::StringDescriptionRole).value<StringDescription>();
|
||||||
Core()->seek(str.vaddr);
|
Core()->seekAndShow(str.vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringsWidget::refreshStrings()
|
void StringsWidget::refreshStrings()
|
||||||
|
@ -150,7 +150,7 @@ void SymbolsWidget::on_symbolsTreeView_doubleClicked(const QModelIndex &index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto symbol = index.data(SymbolsModel::SymbolDescriptionRole).value<SymbolDescription>();
|
auto symbol = index.data(SymbolsModel::SymbolDescriptionRole).value<SymbolDescription>();
|
||||||
Core()->seek(symbol.vaddr);
|
Core()->seekAndShow(symbol.vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolsWidget::refreshSymbols()
|
void SymbolsWidget::refreshSymbols()
|
||||||
|
@ -188,10 +188,10 @@ void VTablesWidget::on_vTableTreeView_doubleClicked(const QModelIndex &index)
|
|||||||
|
|
||||||
QModelIndex parent = index.parent();
|
QModelIndex parent = index.parent();
|
||||||
if (parent.isValid()) {
|
if (parent.isValid()) {
|
||||||
Core()->seek(index.data(
|
Core()->seekAndShow(index.data(
|
||||||
VTableModel::VTableDescriptionRole).value<BinClassMethodDescription>().addr);
|
VTableModel::VTableDescriptionRole).value<BinClassMethodDescription>().addr);
|
||||||
} else {
|
} else {
|
||||||
Core()->seek(index.data(
|
Core()->seekAndShow(index.data(
|
||||||
VTableModel::VTableDescriptionRole).value<VTableDescription>().addr);
|
VTableModel::VTableDescriptionRole).value<VTableDescription>().addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,5 +151,5 @@ void ZignaturesWidget::on_zignaturesTreeView_doubleClicked(const QModelIndex &in
|
|||||||
{
|
{
|
||||||
ZignatureDescription item = index.data(
|
ZignatureDescription item = index.data(
|
||||||
ZignaturesModel::ZignatureDescriptionRole).value<ZignatureDescription>();
|
ZignaturesModel::ZignatureDescriptionRole).value<ZignatureDescription>();
|
||||||
Core()->seek(item.offset);
|
Core()->seekAndShow(item.offset);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user