diff --git a/docs/source/user-docs/menus/menu-bar/view-menu.rst b/docs/source/user-docs/menus/menu-bar/view-menu.rst index f4320d7a..7ff6158a 100644 --- a/docs/source/user-docs/menus/menu-bar/view-menu.rst +++ b/docs/source/user-docs/menus/menu-bar/view-menu.rst @@ -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 @@ -63,4 +64,17 @@ Reset Zoom **Steps:** View -> Zoom -> Reset -**Shortcut:** :kbd:`Ctrl` + :kbd:`=` \ No newline at end of file +**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 diff --git a/src/Cutter.pro b/src/Cutter.pro index 5f18dd53..03a016ed 100644 --- a/src/Cutter.pro +++ b/src/Cutter.pro @@ -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 diff --git a/src/Main.cpp b/src/Main.cpp index 5825123a..a1493995 100644 --- a/src/Main.cpp +++ b/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 #include -/** - * @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 diff --git a/src/common/Helpers.cpp b/src/common/Helpers.cpp index 94daed0a..f5da9b8f 100644 --- a/src/common/Helpers.cpp +++ b/src/common/Helpers.cpp @@ -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); } diff --git a/src/common/SettingsUpgrade.cpp b/src/common/SettingsUpgrade.cpp new file mode 100644 index 00000000..500747ae --- /dev/null +++ b/src/common/SettingsUpgrade.cpp @@ -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 unsyncDocks = unsyncList.toSet(); +#else + QSet 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); + } +} diff --git a/src/common/SettingsUpgrade.h b/src/common/SettingsUpgrade.h new file mode 100644 index 00000000..8d58f245 --- /dev/null +++ b/src/common/SettingsUpgrade.h @@ -0,0 +1,12 @@ +#ifndef COMMON_SETTINGS_UPGRADE_H +#define COMMON_SETTINGS_UPGRADE_H + +#include +#include + +namespace Cutter { + void initializeSettings(); + void migrateThemes(); +} + +#endif // COMMON_SETTINGS_UPGRADE_H diff --git a/src/core/CutterCommon.h b/src/core/CutterCommon.h index e59fc251..3508f9ac 100644 --- a/src/core/CutterCommon.h +++ b/src/core/CutterCommon.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 diff --git a/src/core/MainWindow.cpp b/src/core/MainWindow.cpp index b08ee72c..0a2e8ad7 100644 --- a/src/core/MainWindow.cpp +++ b/src/core/MainWindow.cpp @@ -91,6 +91,7 @@ #include #include #include +#include #include #include @@ -111,7 +112,14 @@ #include template -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); - widgetTypeToConstructorMap.insert(DisassemblyWidget::getWidgetType(), getNewInstance); + widgetTypeToConstructorMap.insert(DisassemblyWidget::getWidgetType(), + getNewInstance); widgetTypeToConstructorMap.insert(HexdumpWidget::getWidgetType(), getNewInstance); 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 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 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 docks) { + QList 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 windowDocks = { + dashboardDock, + nullptr, + functionsDock, + decompilerDock, + overviewDock, + nullptr, + searchDock, + stringsDock, + typesDock, + nullptr, + }; + ui->menuWindows->insertActions(ui->actionExtraDisassembly, makeActionList(windowDocks)); + QList 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(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(dockWidget); + auto graphWidget = qobject_cast(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(dockWidget); + auto disasmWidget = qobject_cast(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(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(it) || - qobject_cast(it) || - qobject_cast(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(dock) || + qobject_cast(dock) || + qobject_cast(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(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(widget), &CutterDockWidget::closed, - this, [this]() { - QDockWidget *widget = qobject_cast(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 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(w) || - qobject_cast(w) || - qobject_cast(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(w) || - qobject_cast(w) || - qobject_cast(w)) { + isExtraMemoryWidget(w)) { w->show(); } + if (qobject_cast(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(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 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 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) diff --git a/src/core/MainWindow.h b/src/core/MainWindow.h index 7f9b5e73..e67d2638 100644 --- a/src/core/MainWindow.h +++ b/src/core/MainWindow.h @@ -55,6 +55,13 @@ namespace Ui { class MainWindow; } +struct CutterLayout +{ + QByteArray geometry; + QByteArray state; + QMap 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 dockWidgets; - QMultiMap dockWidgetsOfAction; + QList dockWidgets; + QList 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 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> widgetTypeToConstructorMap; + QMap> widgetTypeToConstructorMap; MemoryDockWidget* lastSyncMemoryWidget = nullptr; MemoryDockWidget* lastMemoryWidget = nullptr; + int functionDockWidthToRestore = 0; }; #endif // MAINWINDOW_H diff --git a/src/core/MainWindow.ui b/src/core/MainWindow.ui index 58bc8541..8a618e56 100644 --- a/src/core/MainWindow.ui +++ b/src/core/MainWindow.ui @@ -102,6 +102,13 @@ + + + + Layouts + + + @@ -133,55 +140,20 @@ Info... - - - - - - - - - - - - - - Debug... - - - - - - - - - - - - - - - - - - - - - - + @@ -231,10 +203,7 @@ - Reset Layout - - - Reset layout + Reset to default layout @@ -399,105 +368,6 @@ Lock/Unlock - - - true - - - Strings - - - Show/Hide Strings panel - - - - - true - - - Sections - - - Show/Hide Sections panel - - - - - true - - - Segments - - - Show/Hide Segments panel - - - - - true - - - Functions - - - Show/Hide Functions panel - - - - - true - - - Imports - - - Show/Hide Imports panel - - - - - true - - - Symbols - - - Show/Hide Symbols panel - - - - - true - - - Relocs - - - Show/Hide Relocs panel - - - - - true - - - Flags - - - Show/Hide Flags panel - - - - - false - - - Memory - - - Show/Hide Memory panel - - false @@ -537,17 +407,6 @@ Refresh - - - true - - - Comments - - - Show/Hide comments - - true @@ -776,30 +635,11 @@ Show/Hide bottom pannel - - - true - - - SDB Browser - - Run Script - - - true - - - Dashboard - - - Show/Hide Dashboard panel - - Reset Settings @@ -851,14 +691,6 @@ Show pseudocode rather than assembly - - - true - - - Entry Points - - true @@ -888,102 +720,6 @@ Graph - - - true - - - Graph Overview - - - - - true - - - Decompiler - - - - - true - - - Console - - - - - true - - - Stack - - - - - true - - - Registers - - - - - true - - - Backtrace - - - - - true - - - Threads - - - - - true - - - Processes - - - - - true - - - Memory map - - - - - true - - - Breakpoints - - - - - true - - - Register References - - - - - true - - - Classes - - Import PDB @@ -994,69 +730,6 @@ Analyze - - - true - - - Resources - - - - - true - - - VTables - - - Show/Hide VTables panel - - - - - true - - - Types - - - Show/Hide Types panel - - - - - true - - - Search - - - Show/Hide Search panel - - - - - true - - - Headers - - - Show/Hide Headers panel - - - - - true - - - Zignatures - - - Show/Hide Zignatures panel - - Export as code @@ -1126,6 +799,11 @@ Commit changes + + + Save layout + + diff --git a/src/plugins/sample-cpp/CutterSamplePlugin.cpp b/src/plugins/sample-cpp/CutterSamplePlugin.cpp index e514611c..aa53c889 100644 --- a/src/plugins/sample-cpp/CutterSamplePlugin.cpp +++ b/src/plugins/sample-cpp/CutterSamplePlugin.cpp @@ -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"); diff --git a/src/plugins/sample-python/sample_python.py b/src/plugins/sample-python/sample_python.py index 7165d4d0..6267b900 100644 --- a/src/plugins/sample-python/sample_python.py +++ b/src/plugins/sample-python/sample_python.py @@ -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) diff --git a/src/widgets/BacktraceWidget.cpp b/src/widgets/BacktraceWidget.cpp index 09469099..6400fb9b 100644 --- a/src/widgets/BacktraceWidget.cpp +++ b/src/widgets/BacktraceWidget.cpp @@ -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); diff --git a/src/widgets/BacktraceWidget.h b/src/widgets/BacktraceWidget.h index a21d6b90..0adf327b 100644 --- a/src/widgets/BacktraceWidget.h +++ b/src/widgets/BacktraceWidget.h @@ -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: @@ -32,4 +32,4 @@ private: QStandardItemModel *modelBacktrace = new QStandardItemModel(1, 5, this); QTableView *viewBacktrace = new QTableView(this); RefreshDeferrer *refreshDeferrer; -}; \ No newline at end of file +}; diff --git a/src/widgets/BreakpointWidget.cpp b/src/widgets/BreakpointWidget.cpp index 41f13085..01b235bd 100644 --- a/src/widgets/BreakpointWidget.cpp +++ b/src/widgets/BreakpointWidget.cpp @@ -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); diff --git a/src/widgets/BreakpointWidget.h b/src/widgets/BreakpointWidget.h index 51bba9b6..6fdb5ad5 100644 --- a/src/widgets/BreakpointWidget.h +++ b/src/widgets/BreakpointWidget.h @@ -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: diff --git a/src/widgets/ClassesWidget.cpp b/src/widgets/ClassesWidget.cpp index ae151018..024689cf 100644 --- a/src/widgets/ClassesWidget.cpp +++ b/src/widgets/ClassesWidget.cpp @@ -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); diff --git a/src/widgets/ClassesWidget.h b/src/widgets/ClassesWidget.h index 2e170904..47c78359 100644 --- a/src/widgets/ClassesWidget.h +++ b/src/widgets/ClassesWidget.h @@ -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: diff --git a/src/widgets/CommentsWidget.cpp b/src/widgets/CommentsWidget.cpp index 8a7150f9..a2e6ec0b 100644 --- a/src/widgets/CommentsWidget.cpp +++ b/src/widgets/CommentsWidget.cpp @@ -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) { diff --git a/src/widgets/CommentsWidget.h b/src/widgets/CommentsWidget.h index 395e30c2..6b2e75aa 100644 --- a/src/widgets/CommentsWidget.h +++ b/src/widgets/CommentsWidget.h @@ -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: diff --git a/src/widgets/ConsoleWidget.cpp b/src/widgets/ConsoleWidget.cpp index 94f0ddcc..4f1c2b3c 100644 --- a/src/widgets/ConsoleWidget.cpp +++ b/src/widgets/ConsoleWidget.cpp @@ -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), diff --git a/src/widgets/ConsoleWidget.h b/src/widgets/ConsoleWidget.h index 01017749..fa8d82c2 100644 --- a/src/widgets/ConsoleWidget.h +++ b/src/widgets/ConsoleWidget.h @@ -24,7 +24,7 @@ class ConsoleWidget : public CutterDockWidget Q_OBJECT public: - explicit ConsoleWidget(MainWindow *main, QAction *action = nullptr); + explicit ConsoleWidget(MainWindow *main); ~ConsoleWidget(); diff --git a/src/widgets/CutterDockWidget.cpp b/src/widgets/CutterDockWidget.cpp index c617a76e..a0559777 100644 --- a/src/widgets/CutterDockWidget.cpp +++ b/src/widgets/CutterDockWidget.cpp @@ -1,26 +1,22 @@ #include "CutterDockWidget.h" #include "core/MainWindow.h" -#include #include #include -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(); diff --git a/src/widgets/CutterDockWidget.h b/src/widgets/CutterDockWidget.h index b4c1a755..910046da 100644 --- a/src/widgets/CutterDockWidget.h +++ b/src/widgets/CutterDockWidget.h @@ -1,10 +1,11 @@ #ifndef CUTTERWIDGET_H #define CUTTERWIDGET_H -#include - +#include "CutterCommon.h" #include "common/RefreshDeferrer.h" +#include + 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; diff --git a/src/widgets/Dashboard.cpp b/src/widgets/Dashboard.cpp index 3c16a6ee..33b502d8 100644 --- a/src/widgets/Dashboard.cpp +++ b/src/widgets/Dashboard.cpp @@ -21,8 +21,8 @@ #include #include -Dashboard::Dashboard(MainWindow *main, QAction *action) : - CutterDockWidget(main, action), +Dashboard::Dashboard(MainWindow *main) : + CutterDockWidget(main), ui(new Ui::Dashboard) { ui->setupUi(this); diff --git a/src/widgets/Dashboard.h b/src/widgets/Dashboard.h index 264f4c82..67f76162 100644 --- a/src/widgets/Dashboard.h +++ b/src/widgets/Dashboard.h @@ -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: diff --git a/src/widgets/DecompilerWidget.cpp b/src/widgets/DecompilerWidget.cpp index 4a523827..39482d3d 100644 --- a/src/widgets/DecompilerWidget.cpp +++ b/src/widgets/DecompilerWidget.cpp @@ -15,8 +15,8 @@ #include #include -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) { diff --git a/src/widgets/DecompilerWidget.h b/src/widgets/DecompilerWidget.h index 2b9ecbd0..11c1a1dc 100644 --- a/src/widgets/DecompilerWidget.h +++ b/src/widgets/DecompilerWidget.h @@ -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); diff --git a/src/widgets/DisassemblyWidget.cpp b/src/widgets/DisassemblyWidget.cpp index ef5ad7e9..34c1efbe 100644 --- a/src/widgets/DisassemblyWidget.cpp +++ b/src/widgets/DisassemblyWidget.cpp @@ -38,8 +38,8 @@ static DisassemblyTextBlockUserData *getUserData(const QTextBlock &block) return static_cast(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)) diff --git a/src/widgets/DisassemblyWidget.h b/src/widgets/DisassemblyWidget.h index fc4719f3..9d43a872 100644 --- a/src/widgets/DisassemblyWidget.h +++ b/src/widgets/DisassemblyWidget.h @@ -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(); diff --git a/src/widgets/EntrypointWidget.cpp b/src/widgets/EntrypointWidget.cpp index 65e5946f..f9a335c6 100644 --- a/src/widgets/EntrypointWidget.cpp +++ b/src/widgets/EntrypointWidget.cpp @@ -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); diff --git a/src/widgets/EntrypointWidget.h b/src/widgets/EntrypointWidget.h index 96cead3d..157245e2 100644 --- a/src/widgets/EntrypointWidget.h +++ b/src/widgets/EntrypointWidget.h @@ -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: diff --git a/src/widgets/ExportsWidget.cpp b/src/widgets/ExportsWidget.cpp index 70d4c525..76fa1eea 100644 --- a/src/widgets/ExportsWidget.cpp +++ b/src/widgets/ExportsWidget.cpp @@ -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"); @@ -138,8 +138,7 @@ 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); + toggleDockWidget(true); } ); connect(Core(), &CutterCore::codeRebased, this, &ExportsWidget::refreshExports); diff --git a/src/widgets/ExportsWidget.h b/src/widgets/ExportsWidget.h index b1836c03..acce84ee 100644 --- a/src/widgets/ExportsWidget.h +++ b/src/widgets/ExportsWidget.h @@ -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: diff --git a/src/widgets/FlagsWidget.cpp b/src/widgets/FlagsWidget.cpp index 2fc1e2ce..765255de 100644 --- a/src/widgets/FlagsWidget.cpp +++ b/src/widgets/FlagsWidget.cpp @@ -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)) diff --git a/src/widgets/FlagsWidget.h b/src/widgets/FlagsWidget.h index c43e403f..0835aae4 100644 --- a/src/widgets/FlagsWidget.h +++ b/src/widgets/FlagsWidget.h @@ -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: diff --git a/src/widgets/FunctionsWidget.cpp b/src/widgets/FunctionsWidget.cpp index 4f5d19e8..60d9189f 100644 --- a/src/widgets/FunctionsWidget.cpp +++ b/src/widgets/FunctionsWidget.cpp @@ -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), diff --git a/src/widgets/FunctionsWidget.h b/src/widgets/FunctionsWidget.h index eaaa816e..93ff3955 100644 --- a/src/widgets/FunctionsWidget.h +++ b/src/widgets/FunctionsWidget.h @@ -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); diff --git a/src/widgets/GraphWidget.cpp b/src/widgets/GraphWidget.cpp index 7d513ab7..4ec60ad6 100644 --- a/src/widgets/GraphWidget.cpp +++ b/src/widgets/GraphWidget.cpp @@ -4,8 +4,8 @@ #include "WidgetShortcuts.h" #include -GraphWidget::GraphWidget(MainWindow *main, QAction *action) : - MemoryDockWidget(MemoryWidgetType::Graph, main, action) +GraphWidget::GraphWidget(MainWindow *main) : + MemoryDockWidget(MemoryWidgetType::Graph, main) { setObjectName(main ? main->getUniqueObjectName(getWidgetType()) diff --git a/src/widgets/GraphWidget.h b/src/widgets/GraphWidget.h index 542ea3e7..ee44ad5b 100644 --- a/src/widgets/GraphWidget.h +++ b/src/widgets/GraphWidget.h @@ -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; diff --git a/src/widgets/HeadersWidget.cpp b/src/widgets/HeadersWidget.cpp index 0019d404..58a83c67 100644 --- a/src/widgets/HeadersWidget.cpp +++ b/src/widgets/HeadersWidget.cpp @@ -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"); diff --git a/src/widgets/HeadersWidget.h b/src/widgets/HeadersWidget.h index 4ac93f10..75597ca0 100644 --- a/src/widgets/HeadersWidget.h +++ b/src/widgets/HeadersWidget.h @@ -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: diff --git a/src/widgets/HexWidget.h b/src/widgets/HexWidget.h index 368b111c..5b2aa47c 100644 --- a/src/widgets/HexWidget.h +++ b/src/widgets/HexWidget.h @@ -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; } diff --git a/src/widgets/HexdumpWidget.cpp b/src/widgets/HexdumpWidget.cpp index 90964b6e..49f61a25 100644 --- a/src/widgets/HexdumpWidget.cpp +++ b/src/widgets/HexdumpWidget.cpp @@ -17,8 +17,8 @@ #include #include -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); diff --git a/src/widgets/HexdumpWidget.h b/src/widgets/HexdumpWidget.h index f18c3e2c..c3a9d8b5 100644 --- a/src/widgets/HexdumpWidget.h +++ b/src/widgets/HexdumpWidget.h @@ -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; diff --git a/src/widgets/ImportsWidget.cpp b/src/widgets/ImportsWidget.cpp index f666e928..1b554374 100644 --- a/src/widgets/ImportsWidget.cpp +++ b/src/widgets/ImportsWidget.cpp @@ -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)) { @@ -167,8 +167,7 @@ ImportsWidget::ImportsWidget(MainWindow *main, QAction *action) : ui->treeView->sortByColumn(ImportsModel::LibraryColumn, Qt::AscendingOrder); QShortcut *toggle_shortcut = new QShortcut(widgetShortcuts["ImportsWidget"], main); connect(toggle_shortcut, &QShortcut::activated, this, [=] (){ - toggleDockWidget(true); - main->updateDockActionChecked(action); + toggleDockWidget(true); } ); connect(Core(), &CutterCore::codeRebased, this, &ImportsWidget::refreshImports); diff --git a/src/widgets/ImportsWidget.h b/src/widgets/ImportsWidget.h index 7cb92327..71049d4e 100644 --- a/src/widgets/ImportsWidget.h +++ b/src/widgets/ImportsWidget.h @@ -77,7 +77,7 @@ class ImportsWidget : public ListDockWidget Q_OBJECT public: - explicit ImportsWidget(MainWindow *main, QAction *action); + explicit ImportsWidget(MainWindow *main); ~ImportsWidget(); private slots: diff --git a/src/widgets/ListDockWidget.cpp b/src/widgets/ListDockWidget.cpp index 1b5ebdda..42435961 100644 --- a/src/widgets/ListDockWidget.cpp +++ b/src/widgets/ListDockWidget.cpp @@ -8,8 +8,8 @@ #include #include -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) diff --git a/src/widgets/ListDockWidget.h b/src/widgets/ListDockWidget.h index 5799cb2c..f324b846 100644 --- a/src/widgets/ListDockWidget.h +++ b/src/widgets/ListDockWidget.h @@ -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); diff --git a/src/widgets/MemoryDockWidget.cpp b/src/widgets/MemoryDockWidget.cpp index d4dc7a44..bf5bc3d4 100644 --- a/src/widgets/MemoryDockWidget.cpp +++ b/src/widgets/MemoryDockWidget.cpp @@ -6,8 +6,8 @@ #include #include -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(); diff --git a/src/widgets/MemoryDockWidget.h b/src/widgets/MemoryDockWidget.h index 7147ffa8..e0533f6e 100644 --- a/src/widgets/MemoryDockWidget.h +++ b/src/widgets/MemoryDockWidget.h @@ -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; diff --git a/src/widgets/MemoryMapWidget.cpp b/src/widgets/MemoryMapWidget.cpp index 0987cc46..8cd6a887 100644 --- a/src/widgets/MemoryMapWidget.cpp +++ b/src/widgets/MemoryMapWidget.cpp @@ -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"); diff --git a/src/widgets/MemoryMapWidget.h b/src/widgets/MemoryMapWidget.h index a5859cde..729127c7 100644 --- a/src/widgets/MemoryMapWidget.h +++ b/src/widgets/MemoryMapWidget.h @@ -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: diff --git a/src/widgets/OverviewWidget.cpp b/src/widgets/OverviewWidget.cpp index 0d781368..7899baa6 100644 --- a/src/widgets/OverviewWidget.cpp +++ b/src/widgets/OverviewWidget.cpp @@ -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"); diff --git a/src/widgets/OverviewWidget.h b/src/widgets/OverviewWidget.h index ad9e61f8..f90825e3 100644 --- a/src/widgets/OverviewWidget.h +++ b/src/widgets/OverviewWidget.h @@ -12,7 +12,7 @@ class OverviewWidget : public CutterDockWidget Q_OBJECT public: - explicit OverviewWidget(MainWindow *main, QAction *action = nullptr); + explicit OverviewWidget(MainWindow *main); ~OverviewWidget(); private: diff --git a/src/widgets/ProcessesWidget.cpp b/src/widgets/ProcessesWidget.cpp index e71c9466..75e95489 100644 --- a/src/widgets/ProcessesWidget.cpp +++ b/src/widgets/ProcessesWidget.cpp @@ -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); diff --git a/src/widgets/ProcessesWidget.h b/src/widgets/ProcessesWidget.h index 2552fca6..80e89007 100644 --- a/src/widgets/ProcessesWidget.h +++ b/src/widgets/ProcessesWidget.h @@ -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: diff --git a/src/widgets/RegisterRefsWidget.cpp b/src/widgets/RegisterRefsWidget.cpp index eeac36e7..4b4437a3 100644 --- a/src/widgets/RegisterRefsWidget.cpp +++ b/src/widgets/RegisterRefsWidget.cpp @@ -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) diff --git a/src/widgets/RegisterRefsWidget.h b/src/widgets/RegisterRefsWidget.h index 44531f1c..cf089dc0 100644 --- a/src/widgets/RegisterRefsWidget.h +++ b/src/widgets/RegisterRefsWidget.h @@ -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: diff --git a/src/widgets/RegistersWidget.cpp b/src/widgets/RegistersWidget.cpp index cc62998a..98202d60 100644 --- a/src/widgets/RegistersWidget.cpp +++ b/src/widgets/RegistersWidget.cpp @@ -8,8 +8,8 @@ #include #include -RegistersWidget::RegistersWidget(MainWindow *main, QAction *action) : - CutterDockWidget(main, action), +RegistersWidget::RegistersWidget(MainWindow *main) : + CutterDockWidget(main), ui(new Ui::RegistersWidget), addressContextMenu(this, main) { diff --git a/src/widgets/RegistersWidget.h b/src/widgets/RegistersWidget.h index ec78197c..0b15be39 100644 --- a/src/widgets/RegistersWidget.h +++ b/src/widgets/RegistersWidget.h @@ -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: diff --git a/src/widgets/RelocsWidget.cpp b/src/widgets/RelocsWidget.cpp index 69684235..0cba5c14 100644 --- a/src/widgets/RelocsWidget.cpp +++ b/src/widgets/RelocsWidget.cpp @@ -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)) { diff --git a/src/widgets/RelocsWidget.h b/src/widgets/RelocsWidget.h index 663c8c2b..e26d31fb 100644 --- a/src/widgets/RelocsWidget.h +++ b/src/widgets/RelocsWidget.h @@ -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: diff --git a/src/widgets/ResourcesWidget.cpp b/src/widgets/ResourcesWidget.cpp index 9bc23028..00340d5d 100644 --- a/src/widgets/ResourcesWidget.cpp +++ b/src/widgets/ResourcesWidget.cpp @@ -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"); diff --git a/src/widgets/ResourcesWidget.h b/src/widgets/ResourcesWidget.h index a291b38e..335d3fa7 100644 --- a/src/widgets/ResourcesWidget.h +++ b/src/widgets/ResourcesWidget.h @@ -45,7 +45,7 @@ private: QList resources; public: - explicit ResourcesWidget(MainWindow *main, QAction *action = nullptr); + explicit ResourcesWidget(MainWindow *main); private slots: void refreshResources(); diff --git a/src/widgets/SdbWidget.cpp b/src/widgets/SdbWidget.cpp index 21c39f7f..8b01fe86 100644 --- a/src/widgets/SdbWidget.cpp +++ b/src/widgets/SdbWidget.cpp @@ -8,8 +8,8 @@ #include -SdbWidget::SdbWidget(MainWindow *main, QAction *action) : - CutterDockWidget(main, action), +SdbWidget::SdbWidget(MainWindow *main) : + CutterDockWidget(main), ui(new Ui::SdbWidget) { ui->setupUi(this); diff --git a/src/widgets/SdbWidget.h b/src/widgets/SdbWidget.h index f763aad1..2525725a 100644 --- a/src/widgets/SdbWidget.h +++ b/src/widgets/SdbWidget.h @@ -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: diff --git a/src/widgets/SearchWidget.cpp b/src/widgets/SearchWidget.cpp index 8078a1db..813f11cf 100644 --- a/src/widgets/SearchWidget.cpp +++ b/src/widgets/SearchWidget.cpp @@ -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); diff --git a/src/widgets/SearchWidget.h b/src/widgets/SearchWidget.h index f5b0ce99..3141ef64 100644 --- a/src/widgets/SearchWidget.h +++ b/src/widgets/SearchWidget.h @@ -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: diff --git a/src/widgets/SectionsWidget.cpp b/src/widgets/SectionsWidget.cpp index 5797bf3d..fb2da7b7 100644 --- a/src/widgets/SectionsWidget.cpp +++ b/src/widgets/SectionsWidget.cpp @@ -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")); diff --git a/src/widgets/SectionsWidget.h b/src/widgets/SectionsWidget.h index d59d9b2a..c4a45b1f 100644 --- a/src/widgets/SectionsWidget.h +++ b/src/widgets/SectionsWidget.h @@ -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: diff --git a/src/widgets/SegmentsWidget.cpp b/src/widgets/SegmentsWidget.cpp index b14c85e2..54c7ac70 100644 --- a/src/widgets/SegmentsWidget.cpp +++ b/src/widgets/SegmentsWidget.cpp @@ -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")); diff --git a/src/widgets/SegmentsWidget.h b/src/widgets/SegmentsWidget.h index 27bdaa45..10aefcd9 100644 --- a/src/widgets/SegmentsWidget.h +++ b/src/widgets/SegmentsWidget.h @@ -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: diff --git a/src/widgets/StackWidget.cpp b/src/widgets/StackWidget.cpp index 933f10bb..b5100e23 100644 --- a/src/widgets/StackWidget.cpp +++ b/src/widgets/StackWidget.cpp @@ -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) diff --git a/src/widgets/StackWidget.h b/src/widgets/StackWidget.h index b9517286..6e0b190c 100644 --- a/src/widgets/StackWidget.h +++ b/src/widgets/StackWidget.h @@ -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: diff --git a/src/widgets/StringsWidget.cpp b/src/widgets/StringsWidget.cpp index a579893f..bb90f7cd 100644 --- a/src/widgets/StringsWidget.cpp +++ b/src/widgets/StringsWidget.cpp @@ -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())); diff --git a/src/widgets/StringsWidget.h b/src/widgets/StringsWidget.h index 3ee82795..2f306219 100644 --- a/src/widgets/StringsWidget.h +++ b/src/widgets/StringsWidget.h @@ -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: diff --git a/src/widgets/SymbolsWidget.cpp b/src/widgets/SymbolsWidget.cpp index 04d615ae..6db41b9c 100644 --- a/src/widgets/SymbolsWidget.cpp +++ b/src/widgets/SymbolsWidget.cpp @@ -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"); diff --git a/src/widgets/SymbolsWidget.h b/src/widgets/SymbolsWidget.h index 1af35ebc..d76dfedb 100644 --- a/src/widgets/SymbolsWidget.h +++ b/src/widgets/SymbolsWidget.h @@ -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: diff --git a/src/widgets/ThreadsWidget.cpp b/src/widgets/ThreadsWidget.cpp index a4b6a261..75f9c726 100644 --- a/src/widgets/ThreadsWidget.cpp +++ b/src/widgets/ThreadsWidget.cpp @@ -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); diff --git a/src/widgets/ThreadsWidget.h b/src/widgets/ThreadsWidget.h index 7c264a3d..8d9c6a0e 100644 --- a/src/widgets/ThreadsWidget.h +++ b/src/widgets/ThreadsWidget.h @@ -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: diff --git a/src/widgets/TypesWidget.cpp b/src/widgets/TypesWidget.cpp index 4243d9b8..cf13a0e1 100644 --- a/src/widgets/TypesWidget.cpp +++ b/src/widgets/TypesWidget.cpp @@ -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)) { diff --git a/src/widgets/TypesWidget.h b/src/widgets/TypesWidget.h index ef02f965..358779e5 100644 --- a/src/widgets/TypesWidget.h +++ b/src/widgets/TypesWidget.h @@ -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: diff --git a/src/widgets/VTablesWidget.cpp b/src/widgets/VTablesWidget.cpp index 894e6e11..6b23d1a1 100644 --- a/src/widgets/VTablesWidget.cpp +++ b/src/widgets/VTablesWidget.cpp @@ -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)) { diff --git a/src/widgets/VTablesWidget.h b/src/widgets/VTablesWidget.h index 107f6bf4..ff567d7e 100644 --- a/src/widgets/VTablesWidget.h +++ b/src/widgets/VTablesWidget.h @@ -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: diff --git a/src/widgets/ZignaturesWidget.cpp b/src/widgets/ZignaturesWidget.cpp index f8cd63d0..6bd46449 100644 --- a/src/widgets/ZignaturesWidget.cpp +++ b/src/widgets/ZignaturesWidget.cpp @@ -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); diff --git a/src/widgets/ZignaturesWidget.h b/src/widgets/ZignaturesWidget.h index 40c4b6d8..46e75836 100644 --- a/src/widgets/ZignaturesWidget.h +++ b/src/widgets/ZignaturesWidget.h @@ -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: