mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-31 00:35:05 +00:00
Rewrite layout management code (#2172)
* Use QDockWidget::toggleViewAction instead of custom solution. * Improve new dock placement.
This commit is contained in:
parent
8a3b51c291
commit
3545f059f1
@ -1,6 +1,7 @@
|
||||
View Menu
|
||||
==============================
|
||||
|
||||
|
||||
Refresh contents
|
||||
----------------------------------------
|
||||
**Description:** In some cases, not all the displayed information on Cutter's widgets will be up-to-date, for example - after defining a new function from the integrated radare2 console. By refreshing the contents, Cutter will fetch the most up to date information from the session and will update the different views.
|
||||
@ -12,9 +13,9 @@ Refresh contents
|
||||
|
||||
Reset to default layout
|
||||
----------------------------------------
|
||||
**Description:** Reset the current layout to the default layout provided by Cutter. Future additions will include custom and user-defined layouts to which you'll be able to reset.
|
||||
**Description:** Reset the current layout to the default layout provided by Cutter.
|
||||
|
||||
**Steps:** View -> Reset Layout
|
||||
**Steps:** View -> Reset to default layout
|
||||
|
||||
Reset to default settings
|
||||
----------------------------------------
|
||||
@ -24,7 +25,7 @@ Reset to default settings
|
||||
|
||||
Lock and Unlock panels
|
||||
----------------------------------------
|
||||
**Description:** Allow or disable locking the different widgets.
|
||||
**Description:** Allow or disable moving and closing of different widgets. Uncheck this option to prevent accidentally modifying current layout.
|
||||
|
||||
**Steps:** View -> Unlock Panels
|
||||
|
||||
@ -64,3 +65,16 @@ Reset Zoom
|
||||
**Steps:** View -> Zoom -> Reset
|
||||
|
||||
**Shortcut:** :kbd:`Ctrl` + :kbd:`=`
|
||||
|
||||
|
||||
Save layout
|
||||
----------------------------------------
|
||||
**Description:** Save the current layout with a given name. A layout includes the set of currently opened widgets, their position, and some properties.
|
||||
|
||||
**Steps:** View -> Save Layout , enter a layout name in the dialog.
|
||||
|
||||
Layouts
|
||||
----------------------------------------
|
||||
**Description:** Load the settings from the selected layout into the current layout. Loading a layout will not cause it to automatically be modified. To do that you must use the `Save layout`_ command.
|
||||
|
||||
**Steps:** View -> Layouts -> layout name
|
||||
|
@ -421,7 +421,8 @@ SOURCES += \
|
||||
widgets/ListDockWidget.cpp \
|
||||
dialogs/MultitypeFileSaveDialog.cpp \
|
||||
widgets/BoolToggleDelegate.cpp \
|
||||
common/IOModesController.cpp
|
||||
common/IOModesController.cpp \
|
||||
common/SettingsUpgrade.cpp
|
||||
|
||||
GRAPHVIZ_SOURCES = \
|
||||
widgets/GraphvizLayout.cpp
|
||||
@ -568,7 +569,8 @@ HEADERS += \
|
||||
widgets/AddressableItemList.h \
|
||||
dialogs/MultitypeFileSaveDialog.h \
|
||||
widgets/BoolToggleDelegate.h \
|
||||
common/IOModesController.h
|
||||
common/IOModesController.h \
|
||||
common/SettingsUpgrade.h
|
||||
|
||||
GRAPHVIZ_HEADERS = widgets/GraphGridLayout.h
|
||||
|
||||
|
117
src/Main.cpp
117
src/Main.cpp
@ -2,124 +2,13 @@
|
||||
#include "CutterApplication.h"
|
||||
#include "core/MainWindow.h"
|
||||
#include "common/UpdateWorker.h"
|
||||
#include "common/ColorThemeWorker.h"
|
||||
#include "CutterConfig.h"
|
||||
#include "common/CrashHandler.h"
|
||||
#include "common/SettingsUpgrade.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
|
||||
/**
|
||||
* @brief Migrate Settings used before Cutter 1.8
|
||||
*
|
||||
* @return whether any settings have been migrated
|
||||
*/
|
||||
static bool migrateSettingsPre18(QSettings &newSettings)
|
||||
{
|
||||
if(newSettings.value("settings_migrated", false).toBool()) {
|
||||
return false;
|
||||
}
|
||||
QSettings oldSettings(QSettings::NativeFormat, QSettings::Scope::UserScope, "Cutter", "Cutter");
|
||||
QStringList allKeys = oldSettings.allKeys();
|
||||
if (allKeys.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
qInfo() << "Migrating Settings from pre-1.8";
|
||||
for (const QString &key : allKeys) {
|
||||
newSettings.setValue(key, oldSettings.value(key));
|
||||
}
|
||||
oldSettings.clear();
|
||||
QFile settingsFile(oldSettings.fileName());
|
||||
settingsFile.remove();
|
||||
newSettings.setValue("settings_migrated", true);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define CUTTER_SETTINGS_VERSION_CURRENT 2
|
||||
#define CUTTER_SETTINGS_VERSION_KEY "version"
|
||||
|
||||
/*
|
||||
* How Settings migrations work:
|
||||
*
|
||||
* Every time settings are changed in a way that needs migration,
|
||||
* CUTTER_SETTINGS_VERSION_CURRENT is raised by 1 and a function migrateSettingsToX
|
||||
* is implemented and added to initializeSettings().
|
||||
* This function takes care of migrating from EXACTLY version X-1 to X.
|
||||
*/
|
||||
|
||||
static void migrateSettingsTo1(QSettings &settings) {
|
||||
settings.remove("settings_migrated"); // now handled by version
|
||||
settings.remove("updated_custom_themes"); // now handled by theme_version
|
||||
}
|
||||
|
||||
static void migrateSettingsTo2(QSettings &settings) {
|
||||
QStringList docks = settings.value("docks").toStringList(); // get current list of docks
|
||||
// replace occurences of "PseudocodeWidget" with "DecompilerWidget"
|
||||
settings.setValue("docks", docks.replaceInStrings("PseudocodeWidget", "DecompilerWidget"));
|
||||
}
|
||||
|
||||
static void initializeSettings()
|
||||
{
|
||||
QSettings::setDefaultFormat(QSettings::IniFormat);
|
||||
QSettings settings;
|
||||
|
||||
int settingsVersion = settings.value(CUTTER_SETTINGS_VERSION_KEY, 0).toInt();
|
||||
if(settingsVersion == 0) {
|
||||
migrateSettingsPre18(settings);
|
||||
}
|
||||
|
||||
if(settings.allKeys().length() > 0) {
|
||||
if (settingsVersion > CUTTER_SETTINGS_VERSION_CURRENT) {
|
||||
qWarning() << "Settings have a higher version than current! Skipping migration.";
|
||||
} else if(settingsVersion >= 0) {
|
||||
for (int v = settingsVersion + 1; v <= CUTTER_SETTINGS_VERSION_CURRENT; v++) {
|
||||
qInfo() << "Migrating Settings to Version" << v;
|
||||
switch (v) {
|
||||
case 1:
|
||||
migrateSettingsTo1(settings); break;
|
||||
case 2:
|
||||
migrateSettingsTo2(settings);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
settings.setValue(CUTTER_SETTINGS_VERSION_KEY, CUTTER_SETTINGS_VERSION_CURRENT);
|
||||
}
|
||||
|
||||
|
||||
#define THEME_VERSION_CURRENT 1
|
||||
#define THEME_VERSION_KEY "theme_version"
|
||||
|
||||
static void removeObsoleteOptionsFromCustomThemes() {
|
||||
const QStringList options = Core()->cmdj("ecj").object().keys()
|
||||
<< ColorThemeWorker::cutterSpecificOptions;
|
||||
for (auto theme : Core()->cmdList("eco*")) {
|
||||
theme = theme.trimmed();
|
||||
if (!ThemeWorker().isCustomTheme(theme)) {
|
||||
continue;
|
||||
}
|
||||
QJsonObject updatedTheme;
|
||||
auto sch = ThemeWorker().getTheme(theme).object();
|
||||
for (const auto& key : sch.keys()) {
|
||||
if (options.contains(key)) {
|
||||
updatedTheme.insert(key, sch[key]);
|
||||
}
|
||||
}
|
||||
ThemeWorker().save(QJsonDocument(updatedTheme), theme);
|
||||
}
|
||||
}
|
||||
|
||||
static void migrateThemes()
|
||||
{
|
||||
QSettings settings;
|
||||
int themeVersion = settings.value(THEME_VERSION_KEY, 0).toInt();
|
||||
if (themeVersion != THEME_VERSION_CURRENT) {
|
||||
removeObsoleteOptionsFromCustomThemes();
|
||||
settings.setValue(THEME_VERSION_KEY, THEME_VERSION_CURRENT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attempt to connect to a parent console and configure outputs.
|
||||
@ -183,7 +72,7 @@ int main(int argc, char *argv[])
|
||||
QCoreApplication::setOrganizationName("RadareOrg");
|
||||
QCoreApplication::setApplicationName("Cutter");
|
||||
|
||||
initializeSettings();
|
||||
Cutter::initializeSettings();
|
||||
|
||||
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); // needed for QtWebEngine inside Plugins
|
||||
#ifdef Q_OS_WIN
|
||||
@ -195,7 +84,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
CutterApplication a(argc, argv);
|
||||
|
||||
migrateThemes();
|
||||
Cutter::migrateThemes();
|
||||
|
||||
if (Config()->getAutoUpdateEnabled()) {
|
||||
#if CUTTER_UPDATE_WORKER_AVAILABLE
|
||||
|
@ -145,14 +145,14 @@ SizePolicyMinMax forceHeight(QWidget *widget, int height)
|
||||
|
||||
void SizePolicyMinMax::restoreWidth(QWidget *widget)
|
||||
{
|
||||
widget->setSizePolicy(sizePolicy);
|
||||
widget->setSizePolicy(sizePolicy.horizontalPolicy(), widget->sizePolicy().verticalPolicy());
|
||||
widget->setMinimumWidth(min);
|
||||
widget->setMaximumWidth(max);
|
||||
}
|
||||
|
||||
void SizePolicyMinMax::restoreHeight(QWidget *widget)
|
||||
{
|
||||
widget->setSizePolicy(sizePolicy);
|
||||
widget->setSizePolicy(widget->sizePolicy().horizontalPolicy(), sizePolicy.verticalPolicy());
|
||||
widget->setMinimumHeight(min);
|
||||
widget->setMaximumHeight(max);
|
||||
}
|
||||
|
168
src/common/SettingsUpgrade.cpp
Normal file
168
src/common/SettingsUpgrade.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
#include "SettingsUpgrade.h"
|
||||
|
||||
#include "common/ColorThemeWorker.h"
|
||||
|
||||
/**
|
||||
* @brief Migrate Settings used before Cutter 1.8
|
||||
*
|
||||
* @return whether any settings have been migrated
|
||||
*/
|
||||
static bool migrateSettingsPre18(QSettings &newSettings)
|
||||
{
|
||||
if(newSettings.value("settings_migrated", false).toBool()) {
|
||||
return false;
|
||||
}
|
||||
QSettings oldSettings(QSettings::NativeFormat, QSettings::Scope::UserScope, "Cutter", "Cutter");
|
||||
QStringList allKeys = oldSettings.allKeys();
|
||||
if (allKeys.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
qInfo() << "Migrating Settings from pre-1.8";
|
||||
for (const QString &key : allKeys) {
|
||||
newSettings.setValue(key, oldSettings.value(key));
|
||||
}
|
||||
oldSettings.clear();
|
||||
QFile settingsFile(oldSettings.fileName());
|
||||
settingsFile.remove();
|
||||
newSettings.setValue("settings_migrated", true);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define CUTTER_SETTINGS_VERSION_CURRENT 3
|
||||
#define CUTTER_SETTINGS_VERSION_KEY "version"
|
||||
|
||||
/*
|
||||
* How Settings migrations work:
|
||||
*
|
||||
* Every time settings are changed in a way that needs migration,
|
||||
* CUTTER_SETTINGS_VERSION_CURRENT is raised by 1 and a function migrateSettingsToX
|
||||
* is implemented and added to initializeSettings().
|
||||
* This function takes care of migrating from EXACTLY version X-1 to X.
|
||||
*/
|
||||
|
||||
static void migrateSettingsTo1(QSettings &settings) {
|
||||
settings.remove("settings_migrated"); // now handled by version
|
||||
settings.remove("updated_custom_themes"); // now handled by theme_version
|
||||
}
|
||||
|
||||
static void migrateSettingsTo2(QSettings &settings) {
|
||||
QStringList docks = settings.value("docks").toStringList(); // get current list of docks
|
||||
// replace occurences of "PseudocodeWidget" with "DecompilerWidget"
|
||||
settings.setValue("docks", docks.replaceInStrings("PseudocodeWidget", "DecompilerWidget"));
|
||||
}
|
||||
|
||||
static void migrateSettingsTo3(QSettings &settings) {
|
||||
auto defaultGeometry = settings.value("geometry").toByteArray();
|
||||
auto defaultState = settings.value("state").toByteArray();
|
||||
|
||||
auto debugGeometry = settings.value("debug.geometry").toByteArray();
|
||||
auto debugState = settings.value("debug.state").toByteArray();
|
||||
|
||||
|
||||
const auto docks = settings.value("docks", QStringList()).toStringList();
|
||||
auto unsyncList = settings.value("unsync", QStringList()).toStringList();
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,14,0)
|
||||
QSet<QString> unsyncDocks = unsyncList.toSet();
|
||||
#else
|
||||
QSet<QString> unsyncDocks(unsyncList.begin(), unsyncList.end());
|
||||
#endif
|
||||
|
||||
QVariantMap viewProperties;
|
||||
for (auto &dock : docks) {
|
||||
QVariantMap properties;
|
||||
bool synchronized = true;
|
||||
if (unsyncDocks.contains(dock)) {
|
||||
synchronized = false;
|
||||
}
|
||||
properties.insert("synchronized", synchronized);
|
||||
viewProperties.insert(dock, properties);
|
||||
}
|
||||
|
||||
settings.beginWriteArray("layouts", 2);
|
||||
settings.setArrayIndex(0);
|
||||
settings.setValue("name", "Default");
|
||||
settings.setValue("geometry", defaultGeometry);
|
||||
settings.setValue("state", defaultState);
|
||||
settings.setValue("docks", viewProperties);
|
||||
|
||||
settings.setArrayIndex(1);
|
||||
settings.setValue("name", "Debug");
|
||||
settings.setValue("geometry", debugGeometry);
|
||||
settings.setValue("state", debugState);
|
||||
settings.setValue("docks", viewProperties);
|
||||
|
||||
settings.endArray();
|
||||
|
||||
settings.remove("pos"); // Pos and size already stored within geometry
|
||||
settings.remove("size");
|
||||
// keep geometry but with slightly different usecase
|
||||
settings.remove("state");
|
||||
settings.remove("debug.geometry");
|
||||
settings.remove("debug.state");
|
||||
settings.remove("docks");
|
||||
settings.remove("unsync");
|
||||
}
|
||||
|
||||
void Cutter::initializeSettings()
|
||||
{
|
||||
QSettings::setDefaultFormat(QSettings::IniFormat);
|
||||
QSettings settings;
|
||||
|
||||
int settingsVersion = settings.value(CUTTER_SETTINGS_VERSION_KEY, 0).toInt();
|
||||
if(settingsVersion == 0) {
|
||||
migrateSettingsPre18(settings);
|
||||
}
|
||||
|
||||
if(settings.allKeys().length() > 0) {
|
||||
if (settingsVersion > CUTTER_SETTINGS_VERSION_CURRENT) {
|
||||
qWarning() << "Settings have a higher version than current! Skipping migration.";
|
||||
} else if(settingsVersion >= 0) {
|
||||
for (int v = settingsVersion + 1; v <= CUTTER_SETTINGS_VERSION_CURRENT; v++) {
|
||||
qInfo() << "Migrating Settings to Version" << v;
|
||||
switch (v) {
|
||||
case 1:
|
||||
migrateSettingsTo1(settings); break;
|
||||
case 2:
|
||||
migrateSettingsTo2(settings); break;
|
||||
case 3:
|
||||
migrateSettingsTo3(settings); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
settings.setValue(CUTTER_SETTINGS_VERSION_KEY, CUTTER_SETTINGS_VERSION_CURRENT);
|
||||
}
|
||||
|
||||
#define THEME_VERSION_CURRENT 1
|
||||
#define THEME_VERSION_KEY "theme_version"
|
||||
|
||||
static void removeObsoleteOptionsFromCustomThemes() {
|
||||
const QStringList options = Core()->cmdj("ecj").object().keys()
|
||||
<< ColorThemeWorker::cutterSpecificOptions;
|
||||
for (auto theme : Core()->cmdList("eco*")) {
|
||||
theme = theme.trimmed();
|
||||
if (!ThemeWorker().isCustomTheme(theme)) {
|
||||
continue;
|
||||
}
|
||||
QJsonObject updatedTheme;
|
||||
auto sch = ThemeWorker().getTheme(theme).object();
|
||||
for (const auto& key : sch.keys()) {
|
||||
if (options.contains(key)) {
|
||||
updatedTheme.insert(key, sch[key]);
|
||||
}
|
||||
}
|
||||
ThemeWorker().save(QJsonDocument(updatedTheme), theme);
|
||||
}
|
||||
}
|
||||
|
||||
void Cutter::migrateThemes()
|
||||
{
|
||||
QSettings settings;
|
||||
int themeVersion = settings.value(THEME_VERSION_KEY, 0).toInt();
|
||||
if (themeVersion != THEME_VERSION_CURRENT) {
|
||||
removeObsoleteOptionsFromCustomThemes();
|
||||
settings.setValue(THEME_VERSION_KEY, THEME_VERSION_CURRENT);
|
||||
}
|
||||
}
|
12
src/common/SettingsUpgrade.h
Normal file
12
src/common/SettingsUpgrade.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef COMMON_SETTINGS_UPGRADE_H
|
||||
#define COMMON_SETTINGS_UPGRADE_H
|
||||
|
||||
#include <QSettings>
|
||||
#include <core/Cutter.h>
|
||||
|
||||
namespace Cutter {
|
||||
void initializeSettings();
|
||||
void migrateThemes();
|
||||
}
|
||||
|
||||
#endif // COMMON_SETTINGS_UPGRADE_H
|
@ -61,5 +61,12 @@ inline QString RHexString(RVA size)
|
||||
#define CUTTER_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__has_cpp_attribute) && __has_cpp_attribute(deprecated)
|
||||
#define CUTTER_DEPRECATED(msg) [[deprecated(msg)]]
|
||||
#else
|
||||
#define CUTTER_DEPRECATED(msg)
|
||||
#endif
|
||||
|
||||
#endif // CUTTERCORE_H
|
||||
|
||||
|
@ -91,6 +91,7 @@
|
||||
#include <QSysInfo>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QInputDialog>
|
||||
|
||||
#include <QScrollBar>
|
||||
#include <QSettings>
|
||||
@ -111,7 +112,14 @@
|
||||
#include <QGraphicsView>
|
||||
|
||||
template<class T>
|
||||
T* getNewInstance(MainWindow *m, QAction *a) { return new T(m, a); }
|
||||
T *getNewInstance(MainWindow *m) { return new T(m); }
|
||||
|
||||
static const QString LAYOUT_DEFAULT = "Default";
|
||||
static const QString LAYOUT_DEBUG = "Debug";
|
||||
|
||||
static bool isBuiltinLayoutName(const QString &name) {
|
||||
return name == LAYOUT_DEFAULT || name == LAYOUT_DEBUG;
|
||||
}
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
@ -147,7 +155,8 @@ void MainWindow::initUI()
|
||||
connect(Core(), &CutterCore::ioCacheChanged, ui->actionCommitChanges, &QAction::setEnabled);
|
||||
|
||||
widgetTypeToConstructorMap.insert(GraphWidget::getWidgetType(), getNewInstance<GraphWidget>);
|
||||
widgetTypeToConstructorMap.insert(DisassemblyWidget::getWidgetType(), getNewInstance<DisassemblyWidget>);
|
||||
widgetTypeToConstructorMap.insert(DisassemblyWidget::getWidgetType(),
|
||||
getNewInstance<DisassemblyWidget>);
|
||||
widgetTypeToConstructorMap.insert(HexdumpWidget::getWidgetType(), getNewInstance<HexdumpWidget>);
|
||||
|
||||
initToolBar();
|
||||
@ -202,6 +211,8 @@ void MainWindow::initUI()
|
||||
|
||||
initBackForwardMenu();
|
||||
|
||||
connect(ui->actionSaveLayout, &QAction::triggered, this, &MainWindow::saveNamedLayout);
|
||||
|
||||
/* Setup plugins interfaces */
|
||||
for (auto &plugin : Plugins()->getPlugins()) {
|
||||
plugin->setupInterface(this);
|
||||
@ -211,7 +222,8 @@ void MainWindow::initUI()
|
||||
ui->actionGrouped_dock_dragging->setVisible(false);
|
||||
#endif
|
||||
|
||||
initLayout();
|
||||
enableDebugWidgetsMenu(false);
|
||||
readSettings();
|
||||
}
|
||||
|
||||
void MainWindow::initToolBar()
|
||||
@ -296,85 +308,97 @@ void MainWindow::initToolBar()
|
||||
void MainWindow::initDocks()
|
||||
{
|
||||
dockWidgets.reserve(20);
|
||||
decompilerDock = new DecompilerWidget(this, ui->actionDecompiler);
|
||||
consoleDock = new ConsoleWidget(this, ui->actionConsole);
|
||||
decompilerDock = new DecompilerWidget(this);
|
||||
consoleDock = new ConsoleWidget(this);
|
||||
|
||||
overviewDock = new OverviewWidget(this, ui->actionOverview);
|
||||
overviewDock = new OverviewWidget(this);
|
||||
overviewDock->hide();
|
||||
actionOverview = overviewDock->toggleViewAction();
|
||||
connect(overviewDock, &OverviewWidget::isAvailableChanged, this, [this](bool isAvailable) {
|
||||
ui->actionOverview->setEnabled(isAvailable);
|
||||
});
|
||||
ui->actionOverview->setEnabled(overviewDock->getIsAvailable());
|
||||
connect(ui->actionOverview, &QAction::toggled, [this](bool checked) {
|
||||
if (checked) {
|
||||
overviewDock->show();
|
||||
} else {
|
||||
overviewDock->hide();
|
||||
}
|
||||
actionOverview->setEnabled(isAvailable);
|
||||
});
|
||||
actionOverview->setEnabled(overviewDock->getIsAvailable());
|
||||
actionOverview->setChecked(overviewDock->getUserOpened());
|
||||
|
||||
ui->actionOverview->setChecked(overviewDock->getUserOpened());
|
||||
sectionsDock = new SectionsWidget(this, ui->actionSections);
|
||||
segmentsDock = new SegmentsWidget(this, ui->actionSegments);
|
||||
entrypointDock = new EntrypointWidget(this, ui->actionEntrypoints);
|
||||
functionsDock = new FunctionsWidget(this, ui->actionFunctions);
|
||||
importsDock = new ImportsWidget(this, ui->actionImports);
|
||||
exportsDock = new ExportsWidget(this, ui->actionExports);
|
||||
headersDock = new HeadersWidget(this, ui->actionHeaders);
|
||||
zignaturesDock = new ZignaturesWidget(this, ui->actionZignatures);
|
||||
typesDock = new TypesWidget(this, ui->actionTypes);
|
||||
searchDock = new SearchWidget(this, ui->actionSearch);
|
||||
symbolsDock = new SymbolsWidget(this, ui->actionSymbols);
|
||||
relocsDock = new RelocsWidget(this, ui->actionRelocs);
|
||||
commentsDock = new CommentsWidget(this, ui->actionComments);
|
||||
stringsDock = new StringsWidget(this, ui->actionStrings);
|
||||
flagsDock = new FlagsWidget(this, ui->actionFlags);
|
||||
stackDock = new StackWidget(this, ui->actionStack);
|
||||
threadsDock = new ThreadsWidget(this, ui->actionThreads);
|
||||
processesDock = new ProcessesWidget(this, ui->actionProcesses);
|
||||
backtraceDock = new BacktraceWidget(this, ui->actionBacktrace);
|
||||
registersDock = new RegistersWidget(this, ui->actionRegisters);
|
||||
memoryMapDock = new MemoryMapWidget(this, ui->actionMemoryMap);
|
||||
breakpointDock = new BreakpointWidget(this, ui->actionBreakpoint);
|
||||
registerRefsDock = new RegisterRefsWidget(this, ui->actionRegisterRefs);
|
||||
dashboardDock = new Dashboard(this, ui->actionDashboard);
|
||||
sdbDock = new SdbWidget(this, ui->actionSDBBrowser);
|
||||
classesDock = new ClassesWidget(this, ui->actionClasses);
|
||||
resourcesDock = new ResourcesWidget(this, ui->actionResources);
|
||||
vTablesDock = new VTablesWidget(this, ui->actionVTables);
|
||||
dashboardDock = new Dashboard(this);
|
||||
functionsDock = new FunctionsWidget(this);
|
||||
typesDock = new TypesWidget(this);
|
||||
searchDock = new SearchWidget(this);
|
||||
commentsDock = new CommentsWidget(this);
|
||||
stringsDock = new StringsWidget(this);
|
||||
|
||||
QSettings s;
|
||||
QStringList docks = s.value("docks", QStringList {
|
||||
DisassemblyWidget::getWidgetType(),
|
||||
GraphWidget::getWidgetType(),
|
||||
HexdumpWidget::getWidgetType()
|
||||
}).toStringList();
|
||||
QList<CutterDockWidget *> debugDocks = {
|
||||
stackDock = new StackWidget(this),
|
||||
threadsDock = new ThreadsWidget(this),
|
||||
processesDock = new ProcessesWidget(this),
|
||||
backtraceDock = new BacktraceWidget(this),
|
||||
registersDock = new RegistersWidget(this),
|
||||
memoryMapDock = new MemoryMapWidget(this),
|
||||
breakpointDock = new BreakpointWidget(this),
|
||||
registerRefsDock = new RegisterRefsWidget(this)
|
||||
};
|
||||
|
||||
// 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 (widgetTypeToConstructorMap.contains(className)) {
|
||||
auto widget = widgetTypeToConstructorMap[className](this, nullptr);
|
||||
widget->setObjectName(it);
|
||||
addExtraWidget(widget);
|
||||
QList<CutterDockWidget *> infoDocks = {
|
||||
classesDock = new ClassesWidget(this),
|
||||
entrypointDock = new EntrypointWidget(this),
|
||||
exportsDock = new ExportsWidget(this),
|
||||
flagsDock = new FlagsWidget(this),
|
||||
headersDock = new HeadersWidget(this),
|
||||
importsDock = new ImportsWidget(this),
|
||||
relocsDock = new RelocsWidget(this),
|
||||
resourcesDock = new ResourcesWidget(this),
|
||||
sdbDock = new SdbWidget(this),
|
||||
sectionsDock = new SectionsWidget(this),
|
||||
segmentsDock = new SegmentsWidget(this),
|
||||
symbolsDock = new SymbolsWidget(this),
|
||||
vTablesDock = new VTablesWidget(this),
|
||||
zignaturesDock = new ZignaturesWidget(this)
|
||||
};
|
||||
|
||||
auto makeActionList = [this](QList<CutterDockWidget *> docks) {
|
||||
QList<QAction *> result;
|
||||
for (auto dock : docks) {
|
||||
if (dock != nullptr) {
|
||||
result.push_back(dock->toggleViewAction());
|
||||
} else {
|
||||
auto separator = new QAction(this);
|
||||
separator->setSeparator(true);
|
||||
result.push_back(separator);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
QList<CutterDockWidget *> windowDocks = {
|
||||
dashboardDock,
|
||||
nullptr,
|
||||
functionsDock,
|
||||
decompilerDock,
|
||||
overviewDock,
|
||||
nullptr,
|
||||
searchDock,
|
||||
stringsDock,
|
||||
typesDock,
|
||||
nullptr,
|
||||
};
|
||||
ui->menuWindows->insertActions(ui->actionExtraDisassembly, makeActionList(windowDocks));
|
||||
QList<CutterDockWidget *> windowDocks2 = {
|
||||
consoleDock,
|
||||
commentsDock,
|
||||
nullptr,
|
||||
};
|
||||
ui->menuWindows->addActions(makeActionList(windowDocks2));
|
||||
ui->menuAddInfoWidgets->addActions(makeActionList(infoDocks));
|
||||
ui->menuAddDebugWidgets->addActions(makeActionList(debugDocks));
|
||||
|
||||
auto uniqueDocks = windowDocks + windowDocks2 + infoDocks + debugDocks;
|
||||
for (auto dock : uniqueDocks) {
|
||||
if (dock) { // ignore nullptr used as separators
|
||||
addWidget(dock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::initLayout()
|
||||
{
|
||||
// Set up dock widgets default layout
|
||||
enableDebugWidgetsMenu(false);
|
||||
// Restore saved settings
|
||||
readSettingsOrDefault();
|
||||
|
||||
initCorners();
|
||||
}
|
||||
|
||||
void MainWindow::toggleOverview(bool visibility, GraphWidget *targetGraph)
|
||||
{
|
||||
if (!overviewDock) {
|
||||
@ -393,29 +417,29 @@ void MainWindow::updateTasksIndicator()
|
||||
|
||||
void MainWindow::addExtraGraph()
|
||||
{
|
||||
auto *extraDock = new GraphWidget(this, nullptr);
|
||||
auto *extraDock = new GraphWidget(this);
|
||||
addExtraWidget(extraDock);
|
||||
}
|
||||
|
||||
void MainWindow::addExtraHexdump()
|
||||
{
|
||||
auto *extraDock = new HexdumpWidget(this, nullptr);
|
||||
auto *extraDock = new HexdumpWidget(this);
|
||||
addExtraWidget(extraDock);
|
||||
}
|
||||
|
||||
void MainWindow::addExtraDisassembly()
|
||||
{
|
||||
auto *extraDock = new DisassemblyWidget(this, nullptr);
|
||||
auto *extraDock = new DisassemblyWidget(this);
|
||||
addExtraWidget(extraDock);
|
||||
}
|
||||
|
||||
void MainWindow::addExtraWidget(CutterDockWidget *extraDock)
|
||||
{
|
||||
extraDock->setTransient(true);
|
||||
addDockWidget(Qt::TopDockWidgetArea, extraDock, Qt::Orientation::Horizontal);
|
||||
auto restoreExtraDock = qhelpers::forceWidth(extraDock->widget(), 600);
|
||||
qApp->processEvents();
|
||||
restoreExtraDock.restoreWidth(extraDock->widget());
|
||||
dockOnMainArea(extraDock);
|
||||
addWidget(extraDock);
|
||||
extraDock->show();
|
||||
extraDock->raise();
|
||||
}
|
||||
|
||||
QMenu *MainWindow::getMenuByType(MenuType type)
|
||||
@ -440,14 +464,12 @@ QMenu *MainWindow::getMenuByType(MenuType type)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::addPluginDockWidget(QDockWidget *dockWidget, QAction *action)
|
||||
void MainWindow::addPluginDockWidget(CutterDockWidget *dockWidget)
|
||||
{
|
||||
addDockWidget(Qt::TopDockWidgetArea, dockWidget);
|
||||
dockWidget->addAction(action);
|
||||
addWidget(dockWidget);
|
||||
ui->menuPlugins->addAction(action);
|
||||
ui->menuPlugins->addAction(dockWidget->toggleViewAction());
|
||||
addDockWidget(Qt::DockWidgetArea::TopDockWidgetArea, dockWidget);
|
||||
updateDockActionChecked(action);
|
||||
pluginDocks.push_back(dockWidget);
|
||||
}
|
||||
|
||||
void MainWindow::addMenuFileAction(QAction *action)
|
||||
@ -546,21 +568,21 @@ void MainWindow::finalizeOpen()
|
||||
core->getOpcodes();
|
||||
core->updateSeek();
|
||||
refreshAll();
|
||||
|
||||
// Add fortune message
|
||||
core->message("\n" + core->cmdRaw("fo"));
|
||||
showMaximized();
|
||||
Config()->adjustColorThemeDarkness();
|
||||
|
||||
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()));
|
||||
}
|
||||
QSettings settings;
|
||||
auto geometry = settings.value("geometry").toByteArray();
|
||||
if (!geometry.isEmpty()) {
|
||||
restoreGeometry(geometry);
|
||||
show();
|
||||
} else {
|
||||
showMaximized();
|
||||
}
|
||||
|
||||
Config()->adjustColorThemeDarkness();
|
||||
setViewLayout(getViewLayout(LAYOUT_DEFAULT));
|
||||
|
||||
// Set focus to disasm or graph widget
|
||||
|
||||
// Use for loop to cover cases when main disasm/graph
|
||||
@ -577,7 +599,7 @@ void MainWindow::finalizeOpen()
|
||||
bool graphContainsFunc = false;
|
||||
for (auto dockWidget : dockWidgets) {
|
||||
const QString className = dockWidget->metaObject()->className();
|
||||
auto graphWidget = qobject_cast<GraphWidget*>(dockWidget);
|
||||
auto graphWidget = qobject_cast<GraphWidget *>(dockWidget);
|
||||
if (graphWidget && !dockWidget->visibleRegion().isNull()) {
|
||||
graphContainsFunc = !graphWidget->getGraphView()->getBlocks().empty();
|
||||
if (graphContainsFunc) {
|
||||
@ -585,7 +607,7 @@ void MainWindow::finalizeOpen()
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto disasmWidget = qobject_cast<DisassemblyWidget*>(dockWidget);
|
||||
auto disasmWidget = qobject_cast<DisassemblyWidget *>(dockWidget);
|
||||
if (disasmWidget && !dockWidget->visibleRegion().isNull()) {
|
||||
if (!graphContainsFunc) {
|
||||
disasmWidget->setFocus();
|
||||
@ -671,41 +693,18 @@ void MainWindow::paintEvent(QPaintEvent *event)
|
||||
QMainWindow::paintEvent(event);
|
||||
/*
|
||||
* Dirty hack
|
||||
* Just to adjust the width of Functions Widget to fixed size
|
||||
* After everything is drawn, safely make it Preferred size policy
|
||||
* So that user can change the widget size with the mouse
|
||||
* Just to adjust the width of Functions Widget to fixed size.
|
||||
* After everything is drawn, restore the max width limit.
|
||||
*/
|
||||
if (functionsDock) {
|
||||
functionsDock->changeSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
if (functionsDock && functionDockWidthToRestore) {
|
||||
functionsDock->setMaximumWidth(functionDockWidthToRestore);
|
||||
functionDockWidthToRestore = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::readSettingsOrDefault()
|
||||
void MainWindow::readSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
QByteArray geo = settings.value("geometry", QByteArray()).toByteArray();
|
||||
QByteArray state = settings.value("state", QByteArray()).toByteArray();
|
||||
/*
|
||||
* Check if saved settings exist
|
||||
* If not, then read the default layout
|
||||
*/
|
||||
if (!geo.length() || !state.length()) {
|
||||
resetToDefaultLayout();
|
||||
return;
|
||||
}
|
||||
hideAllDocks();
|
||||
restoreGeometry(geo);
|
||||
restoreState(state);
|
||||
|
||||
// make sure all DockWidgets are part of the MainWindow
|
||||
// also show them, so newly installed plugin widgets are shown right away
|
||||
for (auto dockWidget : dockWidgets) {
|
||||
if (dockWidgetArea(dockWidget) == Qt::DockWidgetArea::NoDockWidgetArea &&
|
||||
!isDebugWidget(dockWidget)) {
|
||||
addDockWidget(Qt::DockWidgetArea::TopDockWidgetArea, dockWidget);
|
||||
dockWidget->show();
|
||||
}
|
||||
}
|
||||
|
||||
responsive = settings.value("responsive").toBool();
|
||||
panelLock = settings.value("panelLock").toBool();
|
||||
@ -716,59 +715,22 @@ void MainWindow::readSettingsOrDefault()
|
||||
ui->actionGrouped_dock_dragging->setChecked(dockGroupedDragging);
|
||||
on_actionGrouped_dock_dragging_triggered(dockGroupedDragging);
|
||||
|
||||
QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
|
||||
QSize size = settings.value("size", QSize(400, 400)).toSize();
|
||||
resize(size);
|
||||
move(pos);
|
||||
updateDockActionsChecked();
|
||||
loadLayouts(settings);
|
||||
}
|
||||
|
||||
void MainWindow::saveSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
|
||||
QStringList docks;
|
||||
QStringList unsync;
|
||||
for (const auto &it : dockWidgets) {
|
||||
docks.append(it->objectName());
|
||||
auto memoryDockWidget = qobject_cast<MemoryDockWidget*>(it);
|
||||
if (memoryDockWidget && !memoryDockWidget->getSeekable()->isSynchronized()) {
|
||||
unsync.append(it->objectName());
|
||||
}
|
||||
}
|
||||
settings.setValue("docks", docks);
|
||||
settings.setValue("unsync", unsync);
|
||||
settings.setValue("geometry", saveGeometry());
|
||||
settings.setValue("size", size());
|
||||
settings.setValue("pos", pos());
|
||||
settings.setValue("state", saveState());
|
||||
settings.setValue("panelLock", panelLock);
|
||||
settings.setValue("tabsOnTop", tabsOnTop);
|
||||
settings.setValue("docksGroupedDragging", ui->actionGrouped_dock_dragging->isChecked());
|
||||
settings.setValue("geometry", saveGeometry());
|
||||
|
||||
layouts[Core()->currentlyDebugging ? LAYOUT_DEBUG : LAYOUT_DEFAULT] = getViewLayout();
|
||||
saveLayouts(settings);
|
||||
}
|
||||
|
||||
void MainWindow::readDebugSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
QByteArray geo = settings.value("debug.geometry", QByteArray()).toByteArray();
|
||||
restoreGeometry(geo);
|
||||
QByteArray state = settings.value("debug.state", QByteArray()).toByteArray();
|
||||
restoreState(state);
|
||||
QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
|
||||
QSize size = settings.value("size", QSize(400, 400)).toSize();
|
||||
resize(size);
|
||||
move(pos);
|
||||
updateDockActionsChecked();
|
||||
}
|
||||
|
||||
void MainWindow::saveDebugSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
settings.setValue("debug.geometry", saveGeometry());
|
||||
settings.setValue("debug.state", saveState());
|
||||
settings.setValue("size", size());
|
||||
settings.setValue("pos", pos());
|
||||
}
|
||||
|
||||
void MainWindow::setPanelLock()
|
||||
{
|
||||
@ -819,12 +781,19 @@ void MainWindow::lockUnlock_Docks(bool what)
|
||||
|
||||
void MainWindow::restoreDocks()
|
||||
{
|
||||
// In the upper half the functions are the first widget
|
||||
addDockWidget(Qt::TopDockWidgetArea, functionsDock);
|
||||
addDockWidget(Qt::TopDockWidgetArea, overviewDock);
|
||||
|
||||
// Function | Dashboard
|
||||
// Initial structure
|
||||
// func | main area | debug
|
||||
// |___________|
|
||||
// | console |
|
||||
addDockWidget(Qt::LeftDockWidgetArea, functionsDock);
|
||||
splitDockWidget(functionsDock, dashboardDock, Qt::Horizontal);
|
||||
splitDockWidget(dashboardDock, stackDock, Qt::Horizontal);
|
||||
splitDockWidget(dashboardDock, consoleDock, Qt::Vertical);
|
||||
|
||||
// overview bellow func
|
||||
splitDockWidget(functionsDock, overviewDock, Qt::Vertical);
|
||||
|
||||
// main area
|
||||
tabifyDockWidget(dashboardDock, decompilerDock);
|
||||
tabifyDockWidget(dashboardDock, entrypointDock);
|
||||
tabifyDockWidget(dashboardDock, flagsDock);
|
||||
@ -846,46 +815,24 @@ void MainWindow::restoreDocks()
|
||||
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)) {
|
||||
if (isExtraMemoryWidget(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
|
||||
// Console | Sections/segments/comments
|
||||
splitDockWidget(consoleDock, sectionsDock, Qt::Horizontal);
|
||||
splitDockWidget(consoleDock, segmentsDock, Qt::Horizontal);
|
||||
|
||||
tabifyDockWidget(sectionsDock, segmentsDock);
|
||||
tabifyDockWidget(sectionsDock, commentsDock);
|
||||
|
||||
// Add Stack, Registers, Threads and Backtrace vertically stacked
|
||||
addDockWidget(Qt::TopDockWidgetArea, stackDock);
|
||||
splitDockWidget(stackDock, registersDock, Qt::Vertical);
|
||||
tabifyDockWidget(stackDock, backtraceDock);
|
||||
tabifyDockWidget(backtraceDock, threadsDock);
|
||||
tabifyDockWidget(threadsDock, processesDock);
|
||||
|
||||
updateDockActionsChecked();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::hideAllDocks()
|
||||
{
|
||||
for (auto w : dockWidgets) {
|
||||
removeDockWidget(w);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateDockActionsChecked()
|
||||
{
|
||||
for (auto i = dockWidgetsOfAction.constBegin(); i != dockWidgetsOfAction.constEnd(); i++) {
|
||||
updateDockActionChecked(i.key());
|
||||
for (auto dock : pluginDocks) {
|
||||
dockOnMainArea(dock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -901,6 +848,13 @@ bool MainWindow::isDebugWidget(QDockWidget *dock) const
|
||||
dock == registerRefsDock;
|
||||
}
|
||||
|
||||
bool MainWindow::isExtraMemoryWidget(QDockWidget *dock) const
|
||||
{
|
||||
return qobject_cast<GraphWidget*>(dock) ||
|
||||
qobject_cast<HexdumpWidget*>(dock) ||
|
||||
qobject_cast<DisassemblyWidget*>(dock);
|
||||
}
|
||||
|
||||
MemoryWidgetType MainWindow::getMemoryWidgetTypeToRestore()
|
||||
{
|
||||
if (lastSyncMemoryWidget) {
|
||||
@ -963,7 +917,7 @@ QMenu *MainWindow::createShowInMenu(QWidget *parent, RVA address)
|
||||
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](){
|
||||
connect(action, &QAction::triggered, this, [this, memoryWidget, address]() {
|
||||
memoryWidget->getSeekable()->seek(address);
|
||||
memoryWidget->raiseMemoryWidget();
|
||||
});
|
||||
@ -973,7 +927,7 @@ QMenu *MainWindow::createShowInMenu(QWidget *parent, RVA address)
|
||||
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](){
|
||||
connect(action, &QAction::triggered, this, [this, address, type]() {
|
||||
addNewMemoryWidget(type, address, false);
|
||||
});
|
||||
menu->addAction(action);
|
||||
@ -1023,18 +977,6 @@ MemoryDockWidget *MainWindow::addNewMemoryWidget(MemoryWidgetType type, RVA addr
|
||||
return memoryWidget;
|
||||
}
|
||||
|
||||
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::initBackForwardMenu()
|
||||
{
|
||||
auto prepareButtonMenu = [this](QAction *action) -> QMenu* {
|
||||
@ -1135,21 +1077,43 @@ void MainWindow::updateHistoryMenu(QMenu *menu, bool redo)
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::addWidget(QDockWidget* widget)
|
||||
void MainWindow::updateLayoutsMenu()
|
||||
{
|
||||
ui->menuLayouts->clear();
|
||||
for (auto it = layouts.begin(), end = layouts.end(); it != end; ++it) {
|
||||
QString name = it.key();
|
||||
if (isBuiltinLayoutName(name)) {
|
||||
continue;
|
||||
}
|
||||
auto action = new QAction(it.key(), ui->menuLayouts);
|
||||
connect(action, &QAction::triggered, this, [this, name]() {
|
||||
setViewLayout(getViewLayout(name));
|
||||
});
|
||||
ui->menuLayouts->addAction(action);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::saveNamedLayout()
|
||||
{
|
||||
bool ok = false;
|
||||
QString name;
|
||||
while (name.isEmpty() || isBuiltinLayoutName(name)) {
|
||||
if (ok) {
|
||||
QMessageBox::warning(this, tr("Save layout error"), tr("'%1' is not a valid name.").arg(name));
|
||||
}
|
||||
name = QInputDialog::getText(this, tr("Save layout"), tr("Enter name"), QLineEdit::Normal, {}, &ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
layouts[name] = getViewLayout();
|
||||
updateLayoutsMenu();
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
void MainWindow::addWidget(CutterDockWidget *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);
|
||||
}
|
||||
updateDockActionsChecked();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::addMemoryDockWidget(MemoryDockWidget *widget)
|
||||
@ -1161,9 +1125,10 @@ void MainWindow::addMemoryDockWidget(MemoryDockWidget *widget)
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::removeWidget(QDockWidget *widget)
|
||||
void MainWindow::removeWidget(CutterDockWidget *widget)
|
||||
{
|
||||
dockWidgets.removeAll(widget);
|
||||
pluginDocks.removeAll(widget);
|
||||
if (lastSyncMemoryWidget == widget) {
|
||||
lastSyncMemoryWidget = nullptr;
|
||||
}
|
||||
@ -1172,15 +1137,6 @@ void MainWindow::removeWidget(QDockWidget *widget)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateDockActionChecked(QAction *action)
|
||||
{
|
||||
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()
|
||||
{
|
||||
const QList<QDockWidget *> zenDocks = { functionsDock,
|
||||
@ -1189,18 +1145,15 @@ void MainWindow::showZenDocks()
|
||||
searchDock,
|
||||
importsDock
|
||||
};
|
||||
int width = functionsDock->maximumWidth();
|
||||
functionDockWidthToRestore = functionsDock->maximumWidth();
|
||||
functionsDock->setMaximumWidth(200);
|
||||
for (auto w : dockWidgets) {
|
||||
if (zenDocks.contains(w) ||
|
||||
qobject_cast<GraphWidget*>(w) ||
|
||||
qobject_cast<HexdumpWidget*>(w) ||
|
||||
qobject_cast<DisassemblyWidget*>(w)) {
|
||||
isExtraMemoryWidget(w)) {
|
||||
w->show();
|
||||
}
|
||||
}
|
||||
functionsDock->setMaximumWidth(width);
|
||||
updateDockActionsChecked();
|
||||
dashboardDock->raise();
|
||||
}
|
||||
|
||||
void MainWindow::showDebugDocks()
|
||||
@ -1215,18 +1168,54 @@ void MainWindow::showDebugDocks()
|
||||
memoryMapDock,
|
||||
breakpointDock
|
||||
};
|
||||
int width = functionsDock->maximumWidth();
|
||||
functionDockWidthToRestore = functionsDock->maximumWidth();
|
||||
functionsDock->setMaximumWidth(200);
|
||||
auto registerWidth = qhelpers::forceWidth(registersDock, std::min(500, this->width() / 4));
|
||||
auto registerHeight = qhelpers::forceHeight(registersDock, std::max(100, height() / 2));
|
||||
QDockWidget *widgetToFocus = nullptr;
|
||||
for (auto w : dockWidgets) {
|
||||
if (debugDocks.contains(w) ||
|
||||
qobject_cast<GraphWidget*>(w) ||
|
||||
qobject_cast<HexdumpWidget*>(w) ||
|
||||
qobject_cast<DisassemblyWidget*>(w)) {
|
||||
isExtraMemoryWidget(w)) {
|
||||
w->show();
|
||||
}
|
||||
if (qobject_cast<DisassemblyWidget*>(w)) {
|
||||
widgetToFocus = w;
|
||||
}
|
||||
}
|
||||
registerHeight.restoreHeight(registersDock);
|
||||
registerWidth.restoreWidth(registersDock);
|
||||
if (widgetToFocus) {
|
||||
widgetToFocus->raise();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::dockOnMainArea(QDockWidget *widget)
|
||||
{
|
||||
QDockWidget* best = nullptr;
|
||||
float bestScore = 1;
|
||||
// choose best existing area for placing the new widget
|
||||
for (auto dock : dockWidgets) {
|
||||
if (dock->isHidden() || dock == widget ||
|
||||
dock->isFloating() || // tabifying onto floating dock using code doesn't work well
|
||||
dock->parentWidget() != this) { // floating group isn't considered floating
|
||||
continue;
|
||||
}
|
||||
float newScore = 0;
|
||||
if (isExtraMemoryWidget(dock)) {
|
||||
newScore += 10000000; // prefer existing disssasembly and graph widgets
|
||||
}
|
||||
newScore += dock->width() * dock->height(); // the bigger the better
|
||||
|
||||
if (newScore > bestScore) {
|
||||
bestScore = newScore;
|
||||
best = dock;
|
||||
}
|
||||
}
|
||||
if (best) {
|
||||
tabifyDockWidget(best, widget);
|
||||
} else {
|
||||
addDockWidget(Qt::TopDockWidgetArea, widget, Qt::Orientation::Horizontal);
|
||||
}
|
||||
functionsDock->setMaximumWidth(width);
|
||||
updateDockActionsChecked();
|
||||
}
|
||||
|
||||
void MainWindow::enableDebugWidgetsMenu(bool enable)
|
||||
@ -1239,57 +1228,144 @@ void MainWindow::enableDebugWidgetsMenu(bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::resetToDefaultLayout()
|
||||
CutterLayout MainWindow::getViewLayout()
|
||||
{
|
||||
hideAllDocks();
|
||||
restoreDocks();
|
||||
showZenDocks();
|
||||
dashboardDock->raise();
|
||||
}
|
||||
CutterLayout layout;
|
||||
layout.geometry = saveGeometry();
|
||||
layout.state = saveState();
|
||||
|
||||
void MainWindow::resetToDebugLayout()
|
||||
{
|
||||
MemoryWidgetType memType = getMemoryWidgetTypeToRestore();
|
||||
hideAllDocks();
|
||||
restoreDocks();
|
||||
showDebugDocks();
|
||||
showMemoryWidget(memType);
|
||||
|
||||
auto restoreStackDock = qhelpers::forceWidth(stackDock->widget(), 400);
|
||||
qApp->processEvents();
|
||||
restoreStackDock.restoreWidth(stackDock->widget());
|
||||
}
|
||||
|
||||
void MainWindow::restoreDebugLayout()
|
||||
{
|
||||
MemoryWidgetType memType = getMemoryWidgetTypeToRestore();
|
||||
bool isMaxim = isMaximized();
|
||||
hideAllDocks();
|
||||
restoreDocks();
|
||||
showDebugDocks();
|
||||
readDebugSettings();
|
||||
showMemoryWidget(memType);
|
||||
if (isMaxim) {
|
||||
showMaximized();
|
||||
} else {
|
||||
showNormal();
|
||||
for (auto dock : dockWidgets) {
|
||||
QVariantMap properties;
|
||||
if (auto cutterDock = qobject_cast<CutterDockWidget *>(dock)) {
|
||||
properties = cutterDock->serializeViewProprties();
|
||||
}
|
||||
layout.viewProperties.insert(dock->objectName(), std::move(properties));
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
void MainWindow::resetDockWidgetList()
|
||||
CutterLayout MainWindow::getViewLayout(const QString &name)
|
||||
{
|
||||
QStringList isLeft;
|
||||
QList<QWidget*> toClose;
|
||||
for (auto it : dockWidgets) {
|
||||
if (isLeft.contains(it->metaObject()->className())) {
|
||||
toClose.append(it);
|
||||
} else if (QRegularExpression("\\A(?:\\w+ \\d+)\\z").match(it->objectName()).hasMatch()) {
|
||||
isLeft.append(it->metaObject()->className());
|
||||
auto it = layouts.find(name);
|
||||
if (it != layouts.end()) {
|
||||
return *it;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void MainWindow::setViewLayout(const CutterLayout &layout)
|
||||
{
|
||||
bool isDefault = layout.state.isEmpty() || layout.geometry.isEmpty();
|
||||
bool isDebug = Core()->currentlyDebugging;
|
||||
|
||||
// make a copy to avoid iterating over container from which items are being removed
|
||||
auto widgetsToClose = dockWidgets;
|
||||
|
||||
for (auto dock : widgetsToClose) {
|
||||
dock->hide();
|
||||
dock->close();
|
||||
dock->setFloating(false); // tabifyDockWidget doesn't work if dock is floating
|
||||
removeDockWidget(dock);
|
||||
}
|
||||
|
||||
QStringList docksToCreate;
|
||||
if (isDefault) {
|
||||
docksToCreate = QStringList {
|
||||
DisassemblyWidget::getWidgetType(),
|
||||
GraphWidget::getWidgetType(),
|
||||
HexdumpWidget::getWidgetType()
|
||||
};
|
||||
} else {
|
||||
docksToCreate = layout.viewProperties.keys();
|
||||
}
|
||||
|
||||
for (const auto &it : docksToCreate) {
|
||||
if (std::none_of(dockWidgets.constBegin(), dockWidgets.constEnd(),
|
||||
[&it](QDockWidget * w) { return w->objectName() == it; })) {
|
||||
auto className = it.split(';').at(0);
|
||||
if (widgetTypeToConstructorMap.contains(className)) {
|
||||
auto widget = widgetTypeToConstructorMap[className](this);
|
||||
widget->setObjectName(it);
|
||||
addExtraWidget(widget);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto it : toClose) {
|
||||
it->close();
|
||||
|
||||
restoreDocks();
|
||||
|
||||
QList<QDockWidget *> newDocks;
|
||||
|
||||
for (auto dock : dockWidgets) {
|
||||
auto properties = layout.viewProperties.find(dock->objectName());
|
||||
if (properties != layout.viewProperties.end()) {
|
||||
dock->deserializeViewProperties(*properties);
|
||||
} else {
|
||||
dock->deserializeViewProperties({}); // call with empty properties to reset the widget
|
||||
newDocks.push_back(dock);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isDefault) {
|
||||
restoreState(layout.state);
|
||||
|
||||
for (auto dock : newDocks) {
|
||||
dock->hide(); // hide to prevent dockOnMainArea putting them on each other
|
||||
}
|
||||
for (auto dock : newDocks) {
|
||||
dockOnMainArea(dock);
|
||||
// Show any new docks by default.
|
||||
// Showing new builtin docks helps discovering features added in latest release.
|
||||
// Installing a new plugin hints that usre will likely want to use it.
|
||||
dock->show();
|
||||
}
|
||||
} else {
|
||||
if (isDebug) {
|
||||
showDebugDocks();
|
||||
} else {
|
||||
showZenDocks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::loadLayouts(QSettings &settings)
|
||||
{
|
||||
this->layouts.clear();
|
||||
int size = settings.beginReadArray("layouts");
|
||||
for (int i = 0; i < size; i++) {
|
||||
CutterLayout layout;
|
||||
settings.setArrayIndex(i);
|
||||
QString name = settings.value("name", "layout").toString();
|
||||
layout.geometry = settings.value("geometry").toByteArray();
|
||||
layout.state = settings.value("state").toByteArray();
|
||||
|
||||
auto docks = settings.value("docks").toMap();
|
||||
for (auto it = docks.begin(), end = docks.end(); it != end; it++) {
|
||||
layout.viewProperties.insert(it.key(), it.value().toMap());
|
||||
}
|
||||
|
||||
layouts.insert(name, std::move(layout));
|
||||
}
|
||||
settings.endArray();
|
||||
updateLayoutsMenu();
|
||||
}
|
||||
|
||||
void MainWindow::saveLayouts(QSettings &settings)
|
||||
{
|
||||
settings.beginWriteArray("layouts", layouts.size());
|
||||
int arrayIndex = 0;
|
||||
for (auto it = layouts.begin(), end = layouts.end(); it != end; ++it, ++arrayIndex) {
|
||||
settings.setArrayIndex(arrayIndex);
|
||||
settings.setValue("name", it.key());
|
||||
auto &layout = it.value();
|
||||
settings.setValue("state", layout.state);
|
||||
settings.setValue("geometry", layout.geometry);
|
||||
QVariantMap properties;
|
||||
for (auto it = layout.viewProperties.begin(), end = layout.viewProperties.end(); it != end; ++it) {
|
||||
properties.insert(it.key(), it.value());
|
||||
}
|
||||
settings.setValue("docks", properties);
|
||||
}
|
||||
settings.endArray();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionLock_triggered()
|
||||
@ -1323,22 +1399,12 @@ void MainWindow::on_actionFunctionsRename_triggered()
|
||||
|
||||
void MainWindow::on_actionDefault_triggered()
|
||||
{
|
||||
QSettings s;
|
||||
restoreState(emptyState);
|
||||
|
||||
initCorners();
|
||||
resetDockWidgetList();
|
||||
|
||||
if (core->currentlyDebugging) {
|
||||
resetToDefaultLayout();
|
||||
saveSettings();
|
||||
|
||||
resetToDebugLayout();
|
||||
layouts[LAYOUT_DEBUG] = {};
|
||||
setViewLayout(layouts[LAYOUT_DEBUG]);
|
||||
} else {
|
||||
resetToDebugLayout();
|
||||
saveDebugSettings();
|
||||
|
||||
resetToDefaultLayout();
|
||||
layouts[LAYOUT_DEFAULT] = {};
|
||||
setViewLayout(layouts[LAYOUT_DEFAULT]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1419,7 +1485,8 @@ void MainWindow::on_actionReset_settings_triggered()
|
||||
QMessageBox::Ok | QMessageBox::Cancel);
|
||||
if (ret == QMessageBox::Ok) {
|
||||
Config()->resetAll();
|
||||
on_actionDefault_triggered();
|
||||
readSettings();
|
||||
setViewLayout(getViewLayout(Core()->currentlyDebugging ? LAYOUT_DEBUG : LAYOUT_DEFAULT));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1586,19 +1653,17 @@ void MainWindow::projectSaved(bool successfully, const QString &name)
|
||||
|
||||
void MainWindow::toggleDebugView()
|
||||
{
|
||||
MemoryWidgetType memType = getMemoryWidgetTypeToRestore();
|
||||
if (Core()->currentlyDebugging) {
|
||||
saveSettings();
|
||||
restoreDebugLayout();
|
||||
layouts[LAYOUT_DEFAULT] = getViewLayout();
|
||||
setViewLayout(getViewLayout(LAYOUT_DEBUG));
|
||||
enableDebugWidgetsMenu(true);
|
||||
} else {
|
||||
saveDebugSettings();
|
||||
MemoryWidgetType memType = getMemoryWidgetTypeToRestore();
|
||||
hideAllDocks();
|
||||
restoreDocks();
|
||||
readSettingsOrDefault();
|
||||
layouts[LAYOUT_DEBUG] = getViewLayout();
|
||||
setViewLayout(getViewLayout(LAYOUT_DEFAULT));
|
||||
enableDebugWidgetsMenu(false);
|
||||
showMemoryWidget(memType);
|
||||
}
|
||||
showMemoryWidget(memType);
|
||||
}
|
||||
|
||||
void MainWindow::mousePressEvent(QMouseEvent *event)
|
||||
|
@ -55,6 +55,13 @@ namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
struct CutterLayout
|
||||
{
|
||||
QByteArray geometry;
|
||||
QByteArray state;
|
||||
QMap<QString, QVariantMap> viewProperties;
|
||||
};
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -85,21 +92,20 @@ public:
|
||||
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void readSettingsOrDefault();
|
||||
void readSettings();
|
||||
void saveSettings();
|
||||
void readDebugSettings();
|
||||
void saveDebugSettings();
|
||||
void setFilename(const QString &fn);
|
||||
void refreshOmniBar(const QStringList &flags);
|
||||
|
||||
void addWidget(QDockWidget *widget);
|
||||
void addWidget(CutterDockWidget *widget);
|
||||
void addMemoryDockWidget(MemoryDockWidget *widget);
|
||||
void removeWidget(QDockWidget *widget);
|
||||
void removeWidget(CutterDockWidget *widget);
|
||||
void addExtraWidget(CutterDockWidget *extraDock);
|
||||
MemoryDockWidget *addNewMemoryWidget(MemoryWidgetType type, RVA address, bool synchronized = true);
|
||||
|
||||
|
||||
void addPluginDockWidget(QDockWidget *dockWidget, QAction *action);
|
||||
CUTTER_DEPRECATED("Action will be ignored. Use addPluginDockWidget(CutterDockWidget*) instead.")
|
||||
void addPluginDockWidget(CutterDockWidget *dockWidget, QAction *) { addPluginDockWidget(dockWidget); }
|
||||
void addPluginDockWidget(CutterDockWidget *dockWidget);
|
||||
enum class MenuType { File, Edit, View, Windows, Debug, Help, Plugins };
|
||||
/**
|
||||
* @brief Getter for MainWindow's different menus
|
||||
@ -109,8 +115,6 @@ public:
|
||||
QMenu *getMenuByType(MenuType type);
|
||||
void addMenuFileAction(QAction *action);
|
||||
|
||||
void updateDockActionChecked(QAction * action);
|
||||
|
||||
QString getFilename() const
|
||||
{
|
||||
return filename;
|
||||
@ -233,10 +237,11 @@ private:
|
||||
|
||||
Configuration *configuration;
|
||||
|
||||
QList<QDockWidget *> dockWidgets;
|
||||
QMultiMap<QAction *, QDockWidget *> dockWidgetsOfAction;
|
||||
QList<CutterDockWidget *> dockWidgets;
|
||||
QList<CutterDockWidget *> pluginDocks;
|
||||
DecompilerWidget *decompilerDock = nullptr;
|
||||
OverviewWidget *overviewDock = nullptr;
|
||||
QAction *actionOverview = nullptr;
|
||||
EntrypointWidget *entrypointDock = nullptr;
|
||||
FunctionsWidget *functionsDock = nullptr;
|
||||
ImportsWidget *importsDock = nullptr;
|
||||
@ -250,7 +255,6 @@ private:
|
||||
StringsWidget *stringsDock = nullptr;
|
||||
FlagsWidget *flagsDock = nullptr;
|
||||
Dashboard *dashboardDock = nullptr;
|
||||
QLineEdit *gotoEntry = nullptr;
|
||||
SdbWidget *sdbDock = nullptr;
|
||||
SectionsWidget *sectionsDock = nullptr;
|
||||
SegmentsWidget *segmentsDock = nullptr;
|
||||
@ -259,40 +263,44 @@ private:
|
||||
ClassesWidget *classesDock = nullptr;
|
||||
ResourcesWidget *resourcesDock = nullptr;
|
||||
VTablesWidget *vTablesDock = nullptr;
|
||||
DisassemblerGraphView *graphView = nullptr;
|
||||
QDockWidget *asmDock = nullptr;
|
||||
QDockWidget *calcDock = nullptr;
|
||||
QDockWidget *stackDock = nullptr;
|
||||
QDockWidget *threadsDock = nullptr;
|
||||
QDockWidget *processesDock = nullptr;
|
||||
QDockWidget *registersDock = nullptr;
|
||||
QDockWidget *backtraceDock = nullptr;
|
||||
QDockWidget *memoryMapDock = nullptr;
|
||||
CutterDockWidget *stackDock = nullptr;
|
||||
CutterDockWidget *threadsDock = nullptr;
|
||||
CutterDockWidget *processesDock = nullptr;
|
||||
CutterDockWidget *registersDock = nullptr;
|
||||
CutterDockWidget *backtraceDock = nullptr;
|
||||
CutterDockWidget *memoryMapDock = nullptr;
|
||||
NewFileDialog *newFileDialog = nullptr;
|
||||
QDockWidget *breakpointDock = nullptr;
|
||||
QDockWidget *registerRefsDock = nullptr;
|
||||
CutterDockWidget *breakpointDock = nullptr;
|
||||
CutterDockWidget *registerRefsDock = nullptr;
|
||||
|
||||
QMenu *disassemblyContextMenuExtensions = nullptr;
|
||||
QMenu *addressableContextMenuExtensions = nullptr;
|
||||
|
||||
QMap<QString, CutterLayout> layouts;
|
||||
|
||||
void initUI();
|
||||
void initToolBar();
|
||||
void initDocks();
|
||||
void initLayout();
|
||||
void initCorners();
|
||||
void initBackForwardMenu();
|
||||
void displayInitialOptionsDialog(const InitialOptions &options = InitialOptions(), bool skipOptionsDialog = false);
|
||||
|
||||
void resetToDefaultLayout();
|
||||
void resetToDebugLayout();
|
||||
void restoreDebugLayout();
|
||||
CutterLayout getViewLayout();
|
||||
CutterLayout getViewLayout(const QString &name);
|
||||
|
||||
void setViewLayout(const CutterLayout &layout);
|
||||
void loadLayouts(QSettings &settings);
|
||||
void saveLayouts(QSettings &settings);
|
||||
|
||||
|
||||
void updateMemberPointers();
|
||||
void resetDockWidgetList();
|
||||
void restoreDocks();
|
||||
void hideAllDocks();
|
||||
void showZenDocks();
|
||||
void showDebugDocks();
|
||||
/**
|
||||
* @brief Try to guess which is the "main" section of layout and dock there.
|
||||
* @param widget that needs to be docked
|
||||
*/
|
||||
void dockOnMainArea(QDockWidget *widget);
|
||||
void enableDebugWidgetsMenu(bool enable);
|
||||
/**
|
||||
* @brief Fill menu with seek history entries.
|
||||
@ -300,10 +308,9 @@ private:
|
||||
* @param redo set to false for undo history, true for redo.
|
||||
*/
|
||||
void updateHistoryMenu(QMenu *menu, bool redo = false);
|
||||
void updateLayoutsMenu();
|
||||
void saveNamedLayout();
|
||||
|
||||
void toggleDockWidget(QDockWidget *dock_widget, bool show);
|
||||
|
||||
void updateDockActionsChecked();
|
||||
void setOverviewData();
|
||||
bool isOverviewActive();
|
||||
/**
|
||||
@ -312,16 +319,18 @@ private:
|
||||
* @return true for debug specific widgets, false for all other including common dock widgets.
|
||||
*/
|
||||
bool isDebugWidget(QDockWidget *dock) const;
|
||||
bool isExtraMemoryWidget(QDockWidget *dock) const;
|
||||
|
||||
MemoryWidgetType getMemoryWidgetTypeToRestore();
|
||||
|
||||
/**
|
||||
* @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*)>> widgetTypeToConstructorMap;
|
||||
|
||||
MemoryDockWidget* lastSyncMemoryWidget = nullptr;
|
||||
MemoryDockWidget* lastMemoryWidget = nullptr;
|
||||
int functionDockWidthToRestore = 0;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
@ -102,6 +102,13 @@
|
||||
<addaction name="actionGrouped_dock_dragging"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="menuZoom"/>
|
||||
<addaction name="actionSaveLayout"/>
|
||||
<widget class="QMenu" name="menuLayouts">
|
||||
<property name="title">
|
||||
<string>Layouts</string>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="menuLayouts"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuHelp">
|
||||
<property name="title">
|
||||
@ -133,55 +140,20 @@
|
||||
<property name="title">
|
||||
<string>Info...</string>
|
||||
</property>
|
||||
<addaction name="actionClasses"/>
|
||||
<addaction name="actionEntrypoints"/>
|
||||
<addaction name="actionExports"/>
|
||||
<addaction name="actionFlags"/>
|
||||
<addaction name="actionHeaders"/>
|
||||
<addaction name="actionImports"/>
|
||||
<addaction name="actionRelocs"/>
|
||||
<addaction name="actionResources"/>
|
||||
<addaction name="actionSDBBrowser"/>
|
||||
<addaction name="actionSections"/>
|
||||
<addaction name="actionSegments"/>
|
||||
<addaction name="actionSymbols"/>
|
||||
<addaction name="actionVTables"/>
|
||||
<addaction name="actionZignatures"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuAddDebugWidgets">
|
||||
<property name="title">
|
||||
<string>Debug...</string>
|
||||
</property>
|
||||
<addaction name="actionBacktrace"/>
|
||||
<addaction name="actionBreakpoint"/>
|
||||
<addaction name="actionThreads"/>
|
||||
<addaction name="actionProcesses"/>
|
||||
<addaction name="actionMemoryMap"/>
|
||||
<addaction name="actionRegisters"/>
|
||||
<addaction name="actionRegisterRefs"/>
|
||||
<addaction name="actionStack"/>
|
||||
</widget>
|
||||
<addaction name="actionDashboard"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionFunctions"/>
|
||||
<addaction name="actionDecompiler"/>
|
||||
<addaction name="actionOverview"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionSearch"/>
|
||||
<addaction name="actionStrings"/>
|
||||
<addaction name="actionTypes"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionExtraDisassembly"/>
|
||||
<addaction name="actionExtraGraph"/>
|
||||
<addaction name="actionExtraHexdump"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="menuAddInfoWidgets"/>
|
||||
<addaction name="menuAddDebugWidgets"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionComments"/>
|
||||
<addaction name="actionConsole"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="menuPlugins"/>
|
||||
<addaction name="separator"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuDebug">
|
||||
<property name="title">
|
||||
@ -231,10 +203,7 @@
|
||||
</widget>
|
||||
<action name="actionDefault">
|
||||
<property name="text">
|
||||
<string>Reset Layout</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Reset layout</string>
|
||||
<string>Reset to default layout</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionZen">
|
||||
@ -399,105 +368,6 @@
|
||||
<string>Lock/Unlock</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionStrings">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Strings</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Strings panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSections">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sections</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Sections panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSegments">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Segments</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Segments panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFunctions">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Functions</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Functions panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImports">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Imports</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Imports panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSymbols">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Symbols</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Symbols panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRelocs">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Relocs</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Relocs panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFlags">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Flags</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Flags panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMem">
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Memory</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Memory panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTheme">
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
@ -537,17 +407,6 @@
|
||||
<string>Refresh</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionComments">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Comments</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide comments</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTabs_on_Top">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
@ -776,30 +635,11 @@
|
||||
<string>Show/Hide bottom pannel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSDBBrowser">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>SDB Browser</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRun_Script">
|
||||
<property name="text">
|
||||
<string>Run Script</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDashboard">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Dashboard</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Dashboard panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionReset_settings">
|
||||
<property name="text">
|
||||
<string>Reset Settings</string>
|
||||
@ -851,14 +691,6 @@
|
||||
<string>Show pseudocode rather than assembly</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntrypoints">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Entry Points</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisplay_Offsets">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
@ -888,102 +720,6 @@
|
||||
<string>Graph</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOverview">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Graph Overview</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDecompiler">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Decompiler</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionConsole">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Console</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionStack">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stack</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRegisters">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Registers</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionBacktrace">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Backtrace</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionThreads">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Threads</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionProcesses">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Processes</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMemoryMap">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Memory map</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionBreakpoint">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Breakpoints</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRegisterRefs">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Register References</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionClasses">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Classes</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImportPDB">
|
||||
<property name="text">
|
||||
<string>Import PDB</string>
|
||||
@ -994,69 +730,6 @@
|
||||
<string>Analyze</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionResources">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Resources</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionVTables">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>VTables</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide VTables panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTypes">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Types</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Types panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSearch">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Search panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHeaders">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Headers</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Headers panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionZignatures">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zignatures</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show/Hide Zignatures panel</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExport_as_code">
|
||||
<property name="text">
|
||||
<string>Export as code</string>
|
||||
@ -1126,6 +799,11 @@
|
||||
<string>Commit changes</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSaveLayout">
|
||||
<property name="text">
|
||||
<string>Save layout</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
|
@ -14,14 +14,12 @@ void CutterSamplePlugin::setupPlugin()
|
||||
|
||||
void CutterSamplePlugin::setupInterface(MainWindow *main)
|
||||
{
|
||||
QAction *action = new QAction("Sample C++ Plugin", main);
|
||||
action->setCheckable(true);
|
||||
CutterSamplePluginWidget *widget = new CutterSamplePluginWidget(main, action);
|
||||
main->addPluginDockWidget(widget, action);
|
||||
CutterSamplePluginWidget *widget = new CutterSamplePluginWidget(main);
|
||||
main->addPluginDockWidget(widget);
|
||||
}
|
||||
|
||||
CutterSamplePluginWidget::CutterSamplePluginWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action)
|
||||
CutterSamplePluginWidget::CutterSamplePluginWidget(MainWindow *main) :
|
||||
CutterDockWidget(main)
|
||||
{
|
||||
this->setObjectName("CutterSamplePluginWidget");
|
||||
this->setWindowTitle("Sample C++ Plugin");
|
||||
|
@ -2,12 +2,12 @@
|
||||
import cutter
|
||||
|
||||
from PySide2.QtCore import Qt
|
||||
from PySide2.QtWidgets import QAction, QVBoxLayout, QLabel, QWidget, QSizePolicy, QPushButton
|
||||
from PySide2.QtWidgets import QVBoxLayout, QLabel, QWidget, QSizePolicy, QPushButton
|
||||
|
||||
|
||||
class FortuneWidget(cutter.CutterDockWidget):
|
||||
def __init__(self, parent, action):
|
||||
super(FortuneWidget, self).__init__(parent, action)
|
||||
def __init__(self, parent):
|
||||
super(FortuneWidget, self).__init__(parent)
|
||||
self.setObjectName("FancyDockWidgetFromCoolPlugin")
|
||||
self.setWindowTitle("Sample Python Plugin")
|
||||
|
||||
@ -62,10 +62,8 @@ class CutterSamplePlugin(cutter.CutterPlugin):
|
||||
|
||||
def setupInterface(self, main):
|
||||
# Dock widget
|
||||
action = QAction("Sample Python Plugin", main)
|
||||
action.setCheckable(True)
|
||||
widget = FortuneWidget(main, action)
|
||||
main.addPluginDockWidget(widget, action)
|
||||
widget = FortuneWidget(main)
|
||||
main.addPluginDockWidget(widget)
|
||||
|
||||
# Dissassembly context menu
|
||||
menu = main.getContextMenuExtensions(cutter.MainWindow.ContextMenuType.Disassembly)
|
||||
|
@ -5,8 +5,8 @@
|
||||
|
||||
#include "core/MainWindow.h"
|
||||
|
||||
BacktraceWidget::BacktraceWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
BacktraceWidget::BacktraceWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::BacktraceWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
@ -19,7 +19,7 @@ class BacktraceWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BacktraceWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit BacktraceWidget(MainWindow *main);
|
||||
~BacktraceWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -173,8 +173,8 @@ BreakpointProxyModel::BreakpointProxyModel(BreakpointModel *sourceModel, QObject
|
||||
this->setSortRole(Qt::EditRole);
|
||||
}
|
||||
|
||||
BreakpointWidget::BreakpointWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
BreakpointWidget::BreakpointWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::BreakpointWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
@ -69,7 +69,7 @@ class BreakpointWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BreakpointWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit BreakpointWidget(MainWindow *main);
|
||||
~BreakpointWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -575,8 +575,8 @@ bool ClassesSortFilterProxyModel::hasChildren(const QModelIndex &parent) const
|
||||
|
||||
|
||||
|
||||
ClassesWidget::ClassesWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
ClassesWidget::ClassesWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::ClassesWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
@ -175,7 +175,7 @@ class ClassesWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ClassesWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit ClassesWidget(MainWindow *main);
|
||||
~ClassesWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -229,8 +229,8 @@ bool CommentsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &ri
|
||||
return false;
|
||||
}
|
||||
|
||||
CommentsWidget::CommentsWidget(MainWindow *main, QAction *action) :
|
||||
ListDockWidget(main, action),
|
||||
CommentsWidget::CommentsWidget(MainWindow *main) :
|
||||
ListDockWidget(main),
|
||||
actionHorizontal(tr("Horizontal"), this),
|
||||
actionVertical(tr("Vertical"), this)
|
||||
{
|
||||
|
@ -75,7 +75,7 @@ class CommentsWidget : public ListDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CommentsWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit CommentsWidget(MainWindow *main);
|
||||
~CommentsWidget() override;
|
||||
|
||||
private slots:
|
||||
|
@ -37,8 +37,8 @@ static const int invalidHistoryPos = -1;
|
||||
|
||||
static const char *consoleWrapSettingsKey = "console.wrap";
|
||||
|
||||
ConsoleWidget::ConsoleWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
ConsoleWidget::ConsoleWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::ConsoleWidget),
|
||||
debugOutputEnabled(true),
|
||||
maxHistoryEntries(100),
|
||||
|
@ -24,7 +24,7 @@ class ConsoleWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ConsoleWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit ConsoleWidget(MainWindow *main);
|
||||
|
||||
~ConsoleWidget();
|
||||
|
||||
|
@ -1,26 +1,22 @@
|
||||
#include "CutterDockWidget.h"
|
||||
#include "core/MainWindow.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QEvent>
|
||||
#include <QtWidgets/QShortcut>
|
||||
|
||||
CutterDockWidget::CutterDockWidget(MainWindow *parent, QAction *action) :
|
||||
QDockWidget(parent),
|
||||
mainWindow(parent),
|
||||
action(action)
|
||||
CutterDockWidget::CutterDockWidget(MainWindow *parent, QAction *)
|
||||
: CutterDockWidget(parent)
|
||||
{
|
||||
if (action) {
|
||||
addAction(action);
|
||||
connect(action, &QAction::triggered, this, &CutterDockWidget::toggleDockWidget);
|
||||
}
|
||||
if (parent) {
|
||||
parent->addWidget(this);
|
||||
}
|
||||
}
|
||||
|
||||
CutterDockWidget::CutterDockWidget(MainWindow *parent) :
|
||||
QDockWidget(parent),
|
||||
mainWindow(parent)
|
||||
{
|
||||
// Install event filter to catch redraw widgets when needed
|
||||
installEventFilter(this);
|
||||
updateIsVisibleToUser();
|
||||
connect(toggleViewAction(), &QAction::triggered, this, &QWidget::raise);
|
||||
}
|
||||
|
||||
CutterDockWidget::~CutterDockWidget() = default;
|
||||
@ -38,6 +34,15 @@ bool CutterDockWidget::eventFilter(QObject *object, QEvent *event)
|
||||
return QDockWidget::eventFilter(object, event);
|
||||
}
|
||||
|
||||
QVariantMap CutterDockWidget::serializeViewProprties()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void CutterDockWidget::deserializeViewProperties(const QVariantMap &)
|
||||
{
|
||||
}
|
||||
|
||||
void CutterDockWidget::toggleDockWidget(bool show)
|
||||
{
|
||||
if (!show) {
|
||||
@ -68,25 +73,21 @@ void CutterDockWidget::updateIsVisibleToUser()
|
||||
|
||||
void CutterDockWidget::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if (action) {
|
||||
this->action->setChecked(false);
|
||||
}
|
||||
QDockWidget::closeEvent(event);
|
||||
if (isTransient) {
|
||||
if (mainWindow) {
|
||||
mainWindow->removeWidget(this);
|
||||
}
|
||||
|
||||
// remove parent, otherwise dock layout may still decide to use this widget which is about to be deleted
|
||||
setParent(nullptr);
|
||||
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
emit closed();
|
||||
}
|
||||
|
||||
QAction *CutterDockWidget::getBoundAction() const
|
||||
{
|
||||
return action;
|
||||
}
|
||||
|
||||
QString CutterDockWidget::getDockNumber()
|
||||
{
|
||||
auto name = this->objectName();
|
||||
|
@ -1,10 +1,11 @@
|
||||
#ifndef CUTTERWIDGET_H
|
||||
#define CUTTERWIDGET_H
|
||||
|
||||
#include <QDockWidget>
|
||||
|
||||
#include "CutterCommon.h"
|
||||
#include "common/RefreshDeferrer.h"
|
||||
|
||||
#include <QDockWidget>
|
||||
|
||||
class MainWindow;
|
||||
|
||||
class CutterDockWidget : public QDockWidget
|
||||
@ -12,7 +13,10 @@ class CutterDockWidget : public QDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CutterDockWidget(MainWindow *parent, QAction *action = nullptr);
|
||||
CUTTER_DEPRECATED("Action will be ignored. Use CutterDockWidget(MainWindow*) instead.")
|
||||
CutterDockWidget(MainWindow *parent, QAction *action);
|
||||
|
||||
explicit CutterDockWidget(MainWindow *parent);
|
||||
~CutterDockWidget() override;
|
||||
bool eventFilter(QObject *object, QEvent *event) override;
|
||||
bool isVisibleToUser() { return isVisibleToUserCurrent; }
|
||||
@ -54,7 +58,34 @@ public:
|
||||
});
|
||||
return deferrer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Serialize dock properties for saving as part of layout.
|
||||
*
|
||||
* Override this function for saving dock specific view properties. Use
|
||||
* in situations where it makes sense to have different properties for
|
||||
* multiple instances of widget. Don't use for options that are more suitable
|
||||
* as global settings and should be applied equally to all widgets or all
|
||||
* widgets of this kind.
|
||||
*
|
||||
* Keep synchrononized with deserializeViewProperties. When modifying add
|
||||
* project upgrade step in SettingsUpgrade.cpp if necessary.
|
||||
*
|
||||
* @return Dictionary of current dock properties.
|
||||
* @see CutterDockWidget#deserializeViewProperties
|
||||
*/
|
||||
virtual QVariantMap serializeViewProprties();
|
||||
/**
|
||||
* @brief Deserialization half of serialize view properties.
|
||||
*
|
||||
* When a property is not specified in property map dock should reset it
|
||||
* to default value instead of leaving it umodified. Empty map should reset
|
||||
* all properties controlled by serializeViewProprties/deserializeViewProperties
|
||||
* mechanism.
|
||||
*
|
||||
* @param properties to modify for current widget
|
||||
* @see CutterDockWidget#serializeViewProprties
|
||||
*/
|
||||
virtual void deserializeViewProperties(const QVariantMap &properties);
|
||||
signals:
|
||||
void becameVisibleToUser();
|
||||
void closed();
|
||||
@ -66,14 +97,11 @@ protected:
|
||||
virtual QWidget* widgetToFocusOnRaise();
|
||||
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
QAction *getBoundAction() const;
|
||||
QString getDockNumber();
|
||||
|
||||
MainWindow *mainWindow;
|
||||
|
||||
private:
|
||||
QAction *action;
|
||||
|
||||
bool isTransient = false;
|
||||
|
||||
bool isVisibleToUserCurrent = false;
|
||||
|
@ -21,8 +21,8 @@
|
||||
#include <QDialog>
|
||||
#include <QTreeWidget>
|
||||
|
||||
Dashboard::Dashboard(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
Dashboard::Dashboard(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::Dashboard)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
@ -21,7 +21,7 @@ class Dashboard : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Dashboard(MainWindow *main, QAction *action = nullptr);
|
||||
explicit Dashboard(MainWindow *main);
|
||||
~Dashboard();
|
||||
|
||||
private slots:
|
||||
|
@ -15,8 +15,8 @@
|
||||
#include <QObject>
|
||||
#include <QTextBlockUserData>
|
||||
|
||||
DecompilerWidget::DecompilerWidget(MainWindow *main, QAction *action) :
|
||||
MemoryDockWidget(MemoryWidgetType::Decompiler, main, action),
|
||||
DecompilerWidget::DecompilerWidget(MainWindow *main) :
|
||||
MemoryDockWidget(MemoryWidgetType::Decompiler, main),
|
||||
mCtxMenu(new DisassemblyContextMenu(this, main)),
|
||||
ui(new Ui::DecompilerWidget)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ protected:
|
||||
DisassemblyContextMenu *mCtxMenu;
|
||||
|
||||
public:
|
||||
explicit DecompilerWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit DecompilerWidget(MainWindow *main);
|
||||
~DecompilerWidget();
|
||||
public slots:
|
||||
void showDisasContextMenu(const QPoint &pt);
|
||||
|
@ -38,8 +38,8 @@ static DisassemblyTextBlockUserData *getUserData(const QTextBlock &block)
|
||||
return static_cast<DisassemblyTextBlockUserData *>(userData);
|
||||
}
|
||||
|
||||
DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action)
|
||||
: MemoryDockWidget(MemoryWidgetType::Disassembly, main, action)
|
||||
DisassemblyWidget::DisassemblyWidget(MainWindow *main)
|
||||
: MemoryDockWidget(MemoryWidgetType::Disassembly, main)
|
||||
, mCtxMenu(new DisassemblyContextMenu(this, main))
|
||||
, mDisasScrollArea(new DisassemblyScrollArea(this))
|
||||
, mDisasTextEdit(new DisassemblyTextEdit(this))
|
||||
|
@ -22,7 +22,7 @@ class DisassemblyWidget : public MemoryDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DisassemblyWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit DisassemblyWidget(MainWindow *main);
|
||||
QWidget *getTextWidget();
|
||||
|
||||
static QString getWidgetType();
|
||||
|
@ -12,8 +12,8 @@
|
||||
* Entrypoint Widget
|
||||
*/
|
||||
|
||||
EntrypointWidget::EntrypointWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
EntrypointWidget::EntrypointWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::EntrypointWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
@ -19,7 +19,7 @@ class EntrypointWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EntrypointWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit EntrypointWidget(MainWindow *main);
|
||||
~EntrypointWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -125,8 +125,8 @@ bool ExportsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &rig
|
||||
return leftExp.vaddr < rightExp.vaddr;
|
||||
}
|
||||
|
||||
ExportsWidget::ExportsWidget(MainWindow *main, QAction *action) :
|
||||
ListDockWidget(main, action)
|
||||
ExportsWidget::ExportsWidget(MainWindow *main) :
|
||||
ListDockWidget(main)
|
||||
{
|
||||
setWindowTitle(tr("Exports"));
|
||||
setObjectName("ExportsWidget");
|
||||
@ -139,7 +139,6 @@ ExportsWidget::ExportsWidget(MainWindow *main, QAction *action) :
|
||||
QShortcut *toggle_shortcut = new QShortcut(widgetShortcuts["ExportsWidget"], main);
|
||||
connect(toggle_shortcut, &QShortcut::activated, this, [=] (){
|
||||
toggleDockWidget(true);
|
||||
main->updateDockActionChecked(action);
|
||||
} );
|
||||
|
||||
connect(Core(), &CutterCore::codeRebased, this, &ExportsWidget::refreshExports);
|
||||
|
@ -60,7 +60,7 @@ class ExportsWidget : public ListDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExportsWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit ExportsWidget(MainWindow *main);
|
||||
~ExportsWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -137,8 +137,8 @@ bool FlagsSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIn
|
||||
}
|
||||
|
||||
|
||||
FlagsWidget::FlagsWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
FlagsWidget::FlagsWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::FlagsWidget),
|
||||
main(main),
|
||||
tree(new CutterTreeWidget(this))
|
||||
|
@ -69,7 +69,7 @@ class FlagsWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FlagsWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit FlagsWidget(MainWindow *main);
|
||||
~FlagsWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -424,8 +424,8 @@ bool FunctionSortFilterProxyModel::lessThan(const QModelIndex &left, const QMode
|
||||
}
|
||||
}
|
||||
|
||||
FunctionsWidget::FunctionsWidget(MainWindow *main, QAction *action) :
|
||||
ListDockWidget(main, action),
|
||||
FunctionsWidget::FunctionsWidget(MainWindow *main) :
|
||||
ListDockWidget(main),
|
||||
actionRename(tr("Rename"), this),
|
||||
actionUndefine(tr("Undefine"), this),
|
||||
actionHorizontal(tr("Horizontal"), this),
|
||||
|
@ -92,7 +92,7 @@ class FunctionsWidget : public ListDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FunctionsWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit FunctionsWidget(MainWindow *main);
|
||||
~FunctionsWidget() override;
|
||||
void changeSizePolicy(QSizePolicy::Policy hor, QSizePolicy::Policy ver);
|
||||
|
||||
|
@ -4,8 +4,8 @@
|
||||
#include "WidgetShortcuts.h"
|
||||
#include <QVBoxLayout>
|
||||
|
||||
GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
|
||||
MemoryDockWidget(MemoryWidgetType::Graph, main, action)
|
||||
GraphWidget::GraphWidget(MainWindow *main) :
|
||||
MemoryDockWidget(MemoryWidgetType::Graph, main)
|
||||
{
|
||||
setObjectName(main
|
||||
? main->getUniqueObjectName(getWidgetType())
|
||||
|
@ -12,7 +12,7 @@ class GraphWidget : public MemoryDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GraphWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit GraphWidget(MainWindow *main);
|
||||
~GraphWidget() override {}
|
||||
|
||||
DisassemblerGraphView *getGraphView() const;
|
||||
|
@ -109,8 +109,8 @@ bool HeadersProxyModel::lessThan(const QModelIndex &left, const QModelIndex &rig
|
||||
return leftHeader.vaddr < rightHeader.vaddr;
|
||||
}
|
||||
|
||||
HeadersWidget::HeadersWidget(MainWindow *main, QAction *action) :
|
||||
ListDockWidget(main, action)
|
||||
HeadersWidget::HeadersWidget(MainWindow *main) :
|
||||
ListDockWidget(main)
|
||||
{
|
||||
setWindowTitle(tr("Headers"));
|
||||
setObjectName("HeadersWidget");
|
||||
|
@ -68,7 +68,7 @@ class HeadersWidget : public ListDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit HeadersWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit HeadersWidget(MainWindow *main);
|
||||
~HeadersWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -147,7 +147,7 @@ public:
|
||||
|
||||
bool copy(void *out, uint64_t addr, size_t len) override {
|
||||
if (addr < m_firstBlockAddr || addr > m_lastValidAddr ||
|
||||
(m_lastValidAddr - addr + 1) < len /* do not merge with last check to handle overflows */) {
|
||||
(m_lastValidAddr - addr + 1) < len /* do not merge with last check to handle overflows */ || m_blocks.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -17,8 +17,8 @@
|
||||
#include <QInputDialog>
|
||||
#include <QShortcut>
|
||||
|
||||
HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) :
|
||||
MemoryDockWidget(MemoryWidgetType::Hexdump, main, action),
|
||||
HexdumpWidget::HexdumpWidget(MainWindow *main) :
|
||||
MemoryDockWidget(MemoryWidgetType::Hexdump, main),
|
||||
ui(new Ui::HexdumpWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
@ -31,7 +31,7 @@ class HexdumpWidget : public MemoryDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HexdumpWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit HexdumpWidget(MainWindow *main);
|
||||
~HexdumpWidget() override;
|
||||
Highlighter *highlighter;
|
||||
|
||||
|
@ -154,8 +154,8 @@ bool ImportsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &rig
|
||||
* Imports Widget
|
||||
*/
|
||||
|
||||
ImportsWidget::ImportsWidget(MainWindow *main, QAction *action) :
|
||||
ListDockWidget(main, action),
|
||||
ImportsWidget::ImportsWidget(MainWindow *main) :
|
||||
ListDockWidget(main),
|
||||
importsModel(new ImportsModel(&imports, this)),
|
||||
importsProxyModel(new ImportsProxyModel(importsModel, this))
|
||||
{
|
||||
@ -168,7 +168,6 @@ ImportsWidget::ImportsWidget(MainWindow *main, QAction *action) :
|
||||
QShortcut *toggle_shortcut = new QShortcut(widgetShortcuts["ImportsWidget"], main);
|
||||
connect(toggle_shortcut, &QShortcut::activated, this, [=] (){
|
||||
toggleDockWidget(true);
|
||||
main->updateDockActionChecked(action);
|
||||
} );
|
||||
|
||||
connect(Core(), &CutterCore::codeRebased, this, &ImportsWidget::refreshImports);
|
||||
|
@ -77,7 +77,7 @@ class ImportsWidget : public ListDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ImportsWidget(MainWindow *main, QAction *action);
|
||||
explicit ImportsWidget(MainWindow *main);
|
||||
~ImportsWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -8,8 +8,8 @@
|
||||
#include <QResizeEvent>
|
||||
#include <QShortcut>
|
||||
|
||||
ListDockWidget::ListDockWidget(MainWindow *main, QAction *action, SearchBarPolicy searchBarPolicy) :
|
||||
CutterDockWidget(main, action),
|
||||
ListDockWidget::ListDockWidget(MainWindow *main, SearchBarPolicy searchBarPolicy) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::ListDockWidget),
|
||||
tree(new CutterTreeWidget(this)),
|
||||
searchBarPolicy(searchBarPolicy)
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
Hide,
|
||||
};
|
||||
|
||||
explicit ListDockWidget(MainWindow *main, QAction *action = nullptr, SearchBarPolicy searchBarPolicy = SearchBarPolicy::ShowByDefault);
|
||||
explicit ListDockWidget(MainWindow *main, SearchBarPolicy searchBarPolicy = SearchBarPolicy::ShowByDefault);
|
||||
~ListDockWidget() override;
|
||||
|
||||
void showCount(bool show);
|
||||
|
@ -6,8 +6,8 @@
|
||||
#include <QMenu>
|
||||
#include <QContextMenuEvent>
|
||||
|
||||
MemoryDockWidget::MemoryDockWidget(MemoryWidgetType type, MainWindow *parent, QAction *action)
|
||||
: CutterDockWidget(parent, action)
|
||||
MemoryDockWidget::MemoryDockWidget(MemoryWidgetType type, MainWindow *parent)
|
||||
: CutterDockWidget(parent)
|
||||
, mType(type)
|
||||
, seekable(new CutterSeekable(this))
|
||||
, syncAction(tr("Sync/unsync offset"), this)
|
||||
@ -40,11 +40,6 @@ bool MemoryDockWidget::tryRaiseMemoryWidget()
|
||||
|
||||
void MemoryDockWidget::raiseMemoryWidget()
|
||||
{
|
||||
|
||||
if (getBoundAction()) {
|
||||
getBoundAction()->setChecked(true);
|
||||
}
|
||||
|
||||
show();
|
||||
raise();
|
||||
widgetToFocusOnRaise()->setFocus(Qt::FocusReason::TabFocusReason);
|
||||
@ -58,6 +53,19 @@ bool MemoryDockWidget::eventFilter(QObject *object, QEvent *event)
|
||||
return CutterDockWidget::eventFilter(object, event);
|
||||
}
|
||||
|
||||
QVariantMap MemoryDockWidget::serializeViewProprties()
|
||||
{
|
||||
auto result = CutterDockWidget::serializeViewProprties();
|
||||
result["synchronized"] = seekable->isSynchronized();
|
||||
return result;
|
||||
}
|
||||
|
||||
void MemoryDockWidget::deserializeViewProperties(const QVariantMap &properties)
|
||||
{
|
||||
QVariant synchronized = properties.value("synchronized", true);
|
||||
seekable->setSynchronization(synchronized.toBool());
|
||||
}
|
||||
|
||||
void MemoryDockWidget::updateWindowTitle()
|
||||
{
|
||||
QString name = getWindowTitle();
|
||||
|
@ -15,7 +15,7 @@ class MemoryDockWidget : public CutterDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MemoryDockWidget(MemoryWidgetType type, MainWindow *parent, QAction *action = nullptr);
|
||||
MemoryDockWidget(MemoryWidgetType type, MainWindow *parent);
|
||||
~MemoryDockWidget() override {}
|
||||
|
||||
CutterSeekable *getSeekable() const;
|
||||
@ -27,6 +27,9 @@ public:
|
||||
return mType;
|
||||
}
|
||||
bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
||||
QVariantMap serializeViewProprties() override;
|
||||
void deserializeViewProperties(const QVariantMap &properties) override;
|
||||
private:
|
||||
|
||||
MemoryWidgetType mType;
|
||||
|
@ -111,8 +111,8 @@ bool MemoryProxyModel::lessThan(const QModelIndex &left, const QModelIndex &righ
|
||||
return leftMemMap.addrStart < rightMemMap.addrStart;
|
||||
}
|
||||
|
||||
MemoryMapWidget::MemoryMapWidget(MainWindow *main, QAction *action) :
|
||||
ListDockWidget(main, action, ListDockWidget::SearchBarPolicy::HideByDefault)
|
||||
MemoryMapWidget::MemoryMapWidget(MainWindow *main) :
|
||||
ListDockWidget(main, ListDockWidget::SearchBarPolicy::HideByDefault)
|
||||
{
|
||||
setWindowTitle(tr("Memory Map"));
|
||||
setObjectName("MemoryMapWidget");
|
||||
|
@ -67,7 +67,7 @@ class MemoryMapWidget : public ListDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MemoryMapWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit MemoryMapWidget(MainWindow *main);
|
||||
~MemoryMapWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -3,8 +3,8 @@
|
||||
#include "GraphWidget.h"
|
||||
#include "OverviewView.h"
|
||||
|
||||
OverviewWidget::OverviewWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action)
|
||||
OverviewWidget::OverviewWidget(MainWindow *main) :
|
||||
CutterDockWidget(main)
|
||||
{
|
||||
setWindowTitle("Graph Overview");
|
||||
setObjectName("Graph Overview");
|
||||
|
@ -12,7 +12,7 @@ class OverviewWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OverviewWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit OverviewWidget(MainWindow *main);
|
||||
~OverviewWidget();
|
||||
|
||||
private:
|
||||
|
@ -16,8 +16,8 @@ enum ColumnIndex {
|
||||
COLUMN_PATH,
|
||||
};
|
||||
|
||||
ProcessesWidget::ProcessesWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
ProcessesWidget::ProcessesWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::ProcessesWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
@ -31,7 +31,7 @@ class ProcessesWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProcessesWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit ProcessesWidget(MainWindow *main);
|
||||
~ProcessesWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -111,8 +111,8 @@ bool RegisterRefProxyModel::lessThan(const QModelIndex &left, const QModelIndex
|
||||
return leftRegRef.reg < rightRegRef.reg;
|
||||
}
|
||||
|
||||
RegisterRefsWidget::RegisterRefsWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
RegisterRefsWidget::RegisterRefsWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::RegisterRefsWidget),
|
||||
tree(new CutterTreeWidget(this)),
|
||||
addressableItemContextMenu(this, main)
|
||||
|
@ -69,7 +69,7 @@ class RegisterRefsWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RegisterRefsWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit RegisterRefsWidget(MainWindow *main);
|
||||
~RegisterRefsWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -8,8 +8,8 @@
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
|
||||
RegistersWidget::RegistersWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
RegistersWidget::RegistersWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::RegistersWidget),
|
||||
addressContextMenu(this, main)
|
||||
{
|
||||
|
@ -21,7 +21,7 @@ class RegistersWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RegistersWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit RegistersWidget(MainWindow *main);
|
||||
~RegistersWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -113,8 +113,8 @@ bool RelocsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &righ
|
||||
return false;
|
||||
}
|
||||
|
||||
RelocsWidget::RelocsWidget(MainWindow *main, QAction *action) :
|
||||
ListDockWidget(main, action),
|
||||
RelocsWidget::RelocsWidget(MainWindow *main) :
|
||||
ListDockWidget(main),
|
||||
relocsModel(new RelocsModel(&relocs, this)),
|
||||
relocsProxyModel(new RelocsProxyModel(relocsModel, this))
|
||||
{
|
||||
|
@ -54,7 +54,7 @@ class RelocsWidget : public ListDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RelocsWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit RelocsWidget(MainWindow *main);
|
||||
~RelocsWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -79,8 +79,8 @@ RVA ResourcesModel::address(const QModelIndex &index) const
|
||||
return res.vaddr;
|
||||
}
|
||||
|
||||
ResourcesWidget::ResourcesWidget(MainWindow *main, QAction *action) :
|
||||
ListDockWidget(main, action, ListDockWidget::SearchBarPolicy::HideByDefault)
|
||||
ResourcesWidget::ResourcesWidget(MainWindow *main) :
|
||||
ListDockWidget(main, ListDockWidget::SearchBarPolicy::HideByDefault)
|
||||
{
|
||||
setObjectName("ResourcesWidget");
|
||||
|
||||
|
@ -45,7 +45,7 @@ private:
|
||||
QList<ResourcesDescription> resources;
|
||||
|
||||
public:
|
||||
explicit ResourcesWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit ResourcesWidget(MainWindow *main);
|
||||
|
||||
private slots:
|
||||
void refreshResources();
|
||||
|
@ -8,8 +8,8 @@
|
||||
#include <QTreeWidget>
|
||||
|
||||
|
||||
SdbWidget::SdbWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
SdbWidget::SdbWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::SdbWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
@ -17,7 +17,7 @@ class SdbWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SdbWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit SdbWidget(MainWindow *main);
|
||||
~SdbWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -167,8 +167,8 @@ bool SearchSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelI
|
||||
}
|
||||
|
||||
|
||||
SearchWidget::SearchWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
SearchWidget::SearchWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::SearchWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
@ -64,7 +64,7 @@ class SearchWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SearchWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit SearchWidget(MainWindow *main);
|
||||
~SearchWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -154,8 +154,8 @@ bool SectionsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &ri
|
||||
}
|
||||
}
|
||||
|
||||
SectionsWidget::SectionsWidget(MainWindow *main, QAction *action) :
|
||||
ListDockWidget(main, action)
|
||||
SectionsWidget::SectionsWidget(MainWindow *main) :
|
||||
ListDockWidget(main)
|
||||
{
|
||||
setObjectName("SectionsWidget");
|
||||
setWindowTitle(QStringLiteral("Sections"));
|
||||
|
@ -67,7 +67,7 @@ class SectionsWidget : public ListDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SectionsWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit SectionsWidget(MainWindow *main);
|
||||
~SectionsWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -130,8 +130,8 @@ bool SegmentsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &ri
|
||||
return false;
|
||||
}
|
||||
|
||||
SegmentsWidget::SegmentsWidget(MainWindow *main, QAction *action) :
|
||||
ListDockWidget(main, action)
|
||||
SegmentsWidget::SegmentsWidget(MainWindow *main) :
|
||||
ListDockWidget(main)
|
||||
{
|
||||
setObjectName("SegmentsWidget");
|
||||
setWindowTitle(QStringLiteral("Segments"));
|
||||
|
@ -53,7 +53,7 @@ class SegmentsWidget : public ListDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SegmentsWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit SegmentsWidget(MainWindow *main);
|
||||
~SegmentsWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -8,8 +8,8 @@
|
||||
#include "QHeaderView"
|
||||
#include "QMenu"
|
||||
|
||||
StackWidget::StackWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
StackWidget::StackWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::StackWidget),
|
||||
menuText(this),
|
||||
addressableItemContextMenu(this, main)
|
||||
|
@ -52,7 +52,7 @@ class StackWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit StackWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit StackWidget(MainWindow *main);
|
||||
~StackWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -137,8 +137,8 @@ bool StringsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &rig
|
||||
return leftStr->vaddr < rightStr->vaddr;
|
||||
}
|
||||
|
||||
StringsWidget::StringsWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
StringsWidget::StringsWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::StringsWidget),
|
||||
tree(new CutterTreeWidget(this))
|
||||
{
|
||||
@ -154,8 +154,7 @@ StringsWidget::StringsWidget(MainWindow *main, QAction *action) :
|
||||
QShortcut *toggle_shortcut = new QShortcut(widgetShortcuts["StringsWidget"], main);
|
||||
connect(toggle_shortcut, &QShortcut::activated, this, [ = ] () {
|
||||
toggleDockWidget(true);
|
||||
main->updateDockActionChecked(action);
|
||||
} );
|
||||
});
|
||||
|
||||
connect(ui->actionCopy_String, SIGNAL(triggered()), this, SLOT(on_actionCopy()));
|
||||
|
||||
|
@ -70,7 +70,7 @@ class StringsWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit StringsWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit StringsWidget(MainWindow *main);
|
||||
~StringsWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -113,8 +113,8 @@ bool SymbolsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &rig
|
||||
return false;
|
||||
}
|
||||
|
||||
SymbolsWidget::SymbolsWidget(MainWindow *main, QAction *action) :
|
||||
ListDockWidget(main, action)
|
||||
SymbolsWidget::SymbolsWidget(MainWindow *main) :
|
||||
ListDockWidget(main)
|
||||
{
|
||||
setWindowTitle(tr("Symbols"));
|
||||
setObjectName("SymbolsWidget");
|
||||
|
@ -58,7 +58,7 @@ class SymbolsWidget : public ListDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SymbolsWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit SymbolsWidget(MainWindow *main);
|
||||
~SymbolsWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -15,8 +15,8 @@ enum ColumnIndex {
|
||||
COLUMN_PATH,
|
||||
};
|
||||
|
||||
ThreadsWidget::ThreadsWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
ThreadsWidget::ThreadsWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::ThreadsWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
@ -31,7 +31,7 @@ class ThreadsWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ThreadsWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit ThreadsWidget(MainWindow *main);
|
||||
~ThreadsWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -127,8 +127,8 @@ bool TypesSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIn
|
||||
|
||||
|
||||
|
||||
TypesWidget::TypesWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
TypesWidget::TypesWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::TypesWidget),
|
||||
tree(new CutterTreeWidget(this))
|
||||
{
|
||||
|
@ -72,7 +72,7 @@ class TypesWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TypesWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit TypesWidget(MainWindow *main);
|
||||
~TypesWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -127,8 +127,8 @@ bool VTableSortFilterProxyModel::filterAcceptsRow(int source_row,
|
||||
}
|
||||
|
||||
|
||||
VTablesWidget::VTablesWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
VTablesWidget::VTablesWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::VTablesWidget),
|
||||
tree(new CutterTreeWidget(this))
|
||||
{
|
||||
|
@ -56,7 +56,7 @@ class VTablesWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VTablesWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit VTablesWidget(MainWindow *main);
|
||||
~VTablesWidget();
|
||||
|
||||
private slots:
|
||||
|
@ -113,8 +113,8 @@ bool ZignaturesProxyModel::lessThan(const QModelIndex &left, const QModelIndex &
|
||||
return leftZignature.offset < rightZignature.offset;
|
||||
}
|
||||
|
||||
ZignaturesWidget::ZignaturesWidget(MainWindow *main, QAction *action) :
|
||||
CutterDockWidget(main, action),
|
||||
ZignaturesWidget::ZignaturesWidget(MainWindow *main) :
|
||||
CutterDockWidget(main),
|
||||
ui(new Ui::ZignaturesWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
@ -61,7 +61,7 @@ class ZignaturesWidget : public CutterDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ZignaturesWidget(MainWindow *main, QAction *action = nullptr);
|
||||
explicit ZignaturesWidget(MainWindow *main);
|
||||
~ZignaturesWidget();
|
||||
|
||||
private slots:
|
||||
|
Loading…
Reference in New Issue
Block a user