diff --git a/src/core/MainWindow.cpp b/src/core/MainWindow.cpp index 0fba7635..80324110 100644 --- a/src/core/MainWindow.cpp +++ b/src/core/MainWindow.cpp @@ -123,9 +123,49 @@ void MainWindow::initUI() { ui->setupUi(this); + initToolBar(); + initDocks(); + initLayout(); + /* - * Toolbar + * Some global shortcuts */ + // Period goes to command entry + QShortcut *cmd_shortcut = new QShortcut(QKeySequence(Qt::Key_Period), this); + connect(cmd_shortcut, SIGNAL(activated()), consoleDock, SLOT(focusInputLineEdit())); + + // G and S goes to goto entry + QShortcut *goto_shortcut = new QShortcut(QKeySequence(Qt::Key_G), this); + connect(goto_shortcut, SIGNAL(activated()), this->omnibar, SLOT(setFocus())); + QShortcut *seek_shortcut = new QShortcut(QKeySequence(Qt::Key_S), this); + connect(seek_shortcut, SIGNAL(activated()), this->omnibar, SLOT(setFocus())); + + QShortcut *refresh_shortcut = new QShortcut(QKeySequence(QKeySequence::Refresh), this); + connect(refresh_shortcut, SIGNAL(activated()), this, SLOT(refreshAll())); + + connect(core, SIGNAL(projectSaved(bool, const QString &)), this, SLOT(projectSaved(bool, + const QString &))); + + connect(core, &CutterCore::changeDebugView, this, &MainWindow::changeDebugView); + connect(core, &CutterCore::changeDefinedView, this, &MainWindow::changeDefinedView); + + connect(core, SIGNAL(newMessage(const QString &)), + this->consoleDock, SLOT(addOutput(const QString &))); + connect(core, SIGNAL(newDebugMessage(const QString &)), + this->consoleDock, SLOT(addDebugOutput(const QString &))); + + updateTasksIndicator(); + connect(core->getAsyncTaskManager(), &AsyncTaskManager::tasksChanged, this, + &MainWindow::updateTasksIndicator); + + /* Setup plugins interfaces */ + for (auto plugin : Plugins()->getPlugins()) { + plugin->setupInterface(this); + } +} + +void MainWindow::initToolBar() +{ // Sepparator between undo/redo and goto lineEdit QWidget *spacer3 = new QWidget(); spacer3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); @@ -186,18 +226,15 @@ void MainWindow::initUI() QObject::connect(configuration, &Configuration::colorsUpdated, [this]() { this->visualNavbar->updateGraphicsScene(); }); +} - /* - * Dock Widgets - */ +void MainWindow::initDocks() +{ dockWidgets.reserve(20); - disassemblyDock = new DisassemblyWidget(this, ui->actionDisassembly); hexdumpDock = new HexdumpWidget(this, ui->actionHexdump); pseudocodeDock = new PseudocodeWidget(this, ui->actionPseudocode); consoleDock = new ConsoleWidget(this, ui->actionConsole); - - // Add graph view as dockable overviewDock = new OverviewWidget(this, ui->actionOverview); overviewDock->hide(); graphDock = new GraphWidget(this, ui->actionGraph); @@ -242,57 +279,18 @@ void MainWindow::initUI() classesDock = new ClassesWidget(this, ui->actionClasses); resourcesDock = new ResourcesWidget(this, ui->actionResources); vTablesDock = new VTablesWidget(this, ui->actionVTables); +} - +void MainWindow::initLayout() +{ // Set up dock widgets default layout - resetToDefaultLayout(); enableDebugWidgetsMenu(false); - // Restore saved settings - this->readSettings(); + readSettingsOrDefault(); // TODO: Allow the user to select this option visually in the GUI settings // Adjust the DockWidget areas setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); - //setCorner( Qt::TopRightCorner, Qt::RightDockWidgetArea ); setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); - //setCorner( Qt::BottomRightCorner, Qt::RightDockWidgetArea ); - - - /* - * Some global shortcuts - */ - // Period goes to command entry - QShortcut *cmd_shortcut = new QShortcut(QKeySequence(Qt::Key_Period), this); - connect(cmd_shortcut, SIGNAL(activated()), consoleDock, SLOT(focusInputLineEdit())); - - // G and S goes to goto entry - QShortcut *goto_shortcut = new QShortcut(QKeySequence(Qt::Key_G), this); - connect(goto_shortcut, SIGNAL(activated()), this->omnibar, SLOT(setFocus())); - QShortcut *seek_shortcut = new QShortcut(QKeySequence(Qt::Key_S), this); - connect(seek_shortcut, SIGNAL(activated()), this->omnibar, SLOT(setFocus())); - - QShortcut *refresh_shortcut = new QShortcut(QKeySequence(QKeySequence::Refresh), this); - connect(refresh_shortcut, SIGNAL(activated()), this, SLOT(refreshAll())); - - connect(core, SIGNAL(projectSaved(bool, const QString &)), this, SLOT(projectSaved(bool, - const QString &))); - - connect(core, &CutterCore::changeDebugView, this, &MainWindow::changeDebugView); - connect(core, &CutterCore::changeDefinedView, this, &MainWindow::changeDefinedView); - - connect(core, SIGNAL(newMessage(const QString &)), - this->consoleDock, SLOT(addOutput(const QString &))); - connect(core, SIGNAL(newDebugMessage(const QString &)), - this->consoleDock, SLOT(addDebugOutput(const QString &))); - - updateTasksIndicator(); - connect(core->getAsyncTaskManager(), &AsyncTaskManager::tasksChanged, this, - &MainWindow::updateTasksIndicator); - - /* Setup plugins interfaces */ - for (auto plugin : Plugins()->getPlugins()) { - plugin->setupInterface(this); - } } void MainWindow::toggleOverview(bool visibility, GraphWidget *targetGraph) @@ -327,13 +325,17 @@ void MainWindow::toggleOverview(bool visibility, GraphWidget *targetGraph) void MainWindow::disconnectOverview() { - disconnect(targetGraphDock->graphView, SIGNAL(refreshBlock()), this, SLOT(updateOverview())); - disconnect(targetGraphDock->graphView, SIGNAL(viewRefreshed()), this, SLOT(forceUpdateOverview())); - disconnect(targetGraphDock->graphView, SIGNAL(viewZoomed()), this, SLOT(updateOverview())); - disconnect(overviewDock->graphView, SIGNAL(mouseMoved()), this, SLOT(adjustGraph())); - disconnect(overviewDock->graphView, SIGNAL(refreshBlock()), this, SLOT(updateOverviewAddr())); - disconnect(overviewDock, &QDockWidget::dockLocationChanged, this, &MainWindow::forceUpdateOverview); - disconnect(overviewDock, SIGNAL(resized()), this, SLOT(forceUpdateOverview())); + if (targetGraphDock) { + disconnect(targetGraphDock->graphView, SIGNAL(refreshBlock()), this, SLOT(updateOverview())); + disconnect(targetGraphDock->graphView, SIGNAL(viewRefreshed()), this, SLOT(updateOverview())); + disconnect(targetGraphDock->graphView, SIGNAL(viewZoomed()), this, SLOT(updateOverview())); + } + if (overviewDock) { + disconnect(overviewDock->graphView, SIGNAL(mouseMoved()), this, SLOT(adjustGraph())); + disconnect(overviewDock->graphView, SIGNAL(refreshBlock()), this, SLOT(updateOverviewAddr())); + disconnect(overviewDock, &QDockWidget::dockLocationChanged, this, &MainWindow::forceUpdateOverview); + disconnect(overviewDock, SIGNAL(resized()), this, SLOT(forceUpdateOverview())); + } } void MainWindow::setOverviewData() @@ -616,14 +618,37 @@ void MainWindow::closeEvent(QCloseEvent *event) QMainWindow::closeEvent(event); } -void MainWindow::readSettings() +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 + */ + if (functionsDock) { + functionsDock->changeSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + } +} + +void MainWindow::readSettingsOrDefault() { QSettings settings; QByteArray geo = settings.value("geometry", QByteArray()).toByteArray(); - restoreGeometry(geo); 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); - this->responsive = settings.value("responsive").toBool(); + responsive = settings.value("responsive").toBool(); panelLock = settings.value("panelLock").toBool(); setPanelLock(); tabsOnTop = settings.value("tabsOnTop").toBool(); @@ -778,8 +803,6 @@ void MainWindow::hideAllDocks() for (auto w : dockWidgets) { removeDockWidget(w); } - - updateDockActionsChecked(); } void MainWindow::updateDockActionsChecked() @@ -855,16 +878,6 @@ void MainWindow::resetToDefaultLayout() restoreDocks(); showZenDocks(); dashboardDock->raise(); - - // Ugly workaround to set the default widths of functions docks - // if anyone finds a way to do this cleaner that also works, feel free to change it! - auto restoreFunctionDock = qhelpers::forceWidth(functionsDock->widget(), 200); - auto restoreOverviewDock = qhelpers::forceWidth(overviewDock->widget(), 200); - qApp->processEvents(); - restoreFunctionDock.restoreWidth(functionsDock->widget()); - restoreOverviewDock.restoreWidth(overviewDock->widget()); - - core->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Disassembly); } void MainWindow::resetToDebugLayout() @@ -927,6 +940,7 @@ void MainWindow::on_actionFunctionsRename_triggered() void MainWindow::on_actionDefault_triggered() { + disconnectOverview(); if (core->currentlyDebugging) { resetToDebugLayout(); } else { @@ -1203,7 +1217,7 @@ void MainWindow::changeDefinedView() CutterCore::MemoryWidgetType memType = core->getMemoryWidgetPriority(); hideAllDocks(); restoreDocks(); - readSettings(); + readSettingsOrDefault(); enableDebugWidgetsMenu(false); core->raisePrioritizedMemoryWidget(memType); } diff --git a/src/core/MainWindow.h b/src/core/MainWindow.h index a4952a05..bab32454 100644 --- a/src/core/MainWindow.h +++ b/src/core/MainWindow.h @@ -89,7 +89,8 @@ public: bool saveProjectAs(bool quit = false); void closeEvent(QCloseEvent *event) override; - void readSettings(); + void paintEvent(QPaintEvent *event) override; + void readSettingsOrDefault(); void saveSettings(); void readDebugSettings(); void saveDebugSettings(); @@ -254,6 +255,9 @@ private: JupyterWidget *jupyterDock = nullptr; #endif + void initToolBar(); + void initDocks(); + void initLayout(); void displayInitialOptionsDialog(const InitialOptions &options = InitialOptions(), bool skipOptionsDialog = false); void resetToDefaultLayout(); diff --git a/src/widgets/CutterDockWidget.cpp b/src/widgets/CutterDockWidget.cpp index 80d5d4c6..96aebaff 100644 --- a/src/widgets/CutterDockWidget.cpp +++ b/src/widgets/CutterDockWidget.cpp @@ -8,8 +8,8 @@ CutterDockWidget::CutterDockWidget(MainWindow *parent, QAction *action) : QDockWidget(parent), action(action) { + parent->addToDockWidgetList(this); if (action) { - parent->addToDockWidgetList(this); parent->addDockWidgetAction(this, action); connect(action, &QAction::triggered, this, &CutterDockWidget::toggleDockWidget); } diff --git a/src/widgets/DisassemblyWidget.cpp b/src/widgets/DisassemblyWidget.cpp index 4cac591b..87150c9e 100644 --- a/src/widgets/DisassemblyWidget.cpp +++ b/src/widgets/DisassemblyWidget.cpp @@ -42,6 +42,18 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action) , mDisasTextEdit(new DisassemblyTextEdit(this)) , seekable(new CutterSeekable(this)) { + /* + * Ugly hack just for the layout issue + * QSettings saves the state with the object names + * By doing this hack, + * you can at least avoid some mess by dismissing all the Extra Widgets + */ + QString name = "Disassembly"; + if (!action) { + name = "Extra Disassembly"; + } + setObjectName(name); + topOffset = bottomOffset = RVA_INVALID; cursorLineOffset = 0; seekFromCursor = false; @@ -57,7 +69,6 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action) setWidget(mDisasScrollArea); setAllowedAreas(Qt::AllDockWidgetAreas); - setObjectName("DisassemblyWidget"); setupFonts(); setupColors(); diff --git a/src/widgets/FunctionsWidget.cpp b/src/widgets/FunctionsWidget.cpp index f7c595b5..f8459e13 100644 --- a/src/widgets/FunctionsWidget.cpp +++ b/src/widgets/FunctionsWidget.cpp @@ -566,6 +566,11 @@ void FunctionsWidget::refreshTree() Core()->getAsyncTaskManager()->start(task); } +void FunctionsWidget::changeSizePolicy(QSizePolicy::Policy hor, QSizePolicy::Policy ver) +{ + ui->dockWidgetContents->setSizePolicy(hor, ver); +} + void FunctionsWidget::onFunctionsDoubleClicked(const QModelIndex &index) { if (!index.isValid()) diff --git a/src/widgets/FunctionsWidget.h b/src/widgets/FunctionsWidget.h index aa26b290..f65d6384 100644 --- a/src/widgets/FunctionsWidget.h +++ b/src/widgets/FunctionsWidget.h @@ -101,21 +101,18 @@ class FunctionsWidget : public CutterDockWidget public: explicit FunctionsWidget(MainWindow *main, QAction *action = nullptr); ~FunctionsWidget(); + void changeSizePolicy(QSizePolicy::Policy hor, QSizePolicy::Policy ver); private slots: void onFunctionsDoubleClicked(const QModelIndex &index); void showFunctionsContextMenu(const QPoint &pt); - void on_actionDisasAdd_comment_triggered(); void on_actionFunctionsRename_triggered(); void on_action_References_triggered(); void on_actionFunctionsUndefine_triggered(); - void on_actionHorizontal_triggered(); void on_actionVertical_triggered(); - void showTitleContextMenu(const QPoint &pt); - void refreshTree(); protected: @@ -124,18 +121,13 @@ protected: private: std::unique_ptr ui; MainWindow *main; - QSharedPointer task; - QList functions; QSet importAddresses; ut64 mainAdress; - FunctionModel *functionModel; FunctionSortFilterProxyModel *functionProxyModel; - CutterTreeWidget *tree; - void setScrollMode(); }; diff --git a/src/widgets/FunctionsWidget.ui b/src/widgets/FunctionsWidget.ui index 5f5d7a40..2967b8d6 100644 --- a/src/widgets/FunctionsWidget.ui +++ b/src/widgets/FunctionsWidget.ui @@ -18,7 +18,7 @@ - + 1 0 diff --git a/src/widgets/GraphWidget.cpp b/src/widgets/GraphWidget.cpp index f418ca0b..71188dcc 100644 --- a/src/widgets/GraphWidget.cpp +++ b/src/widgets/GraphWidget.cpp @@ -6,10 +6,20 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) : CutterDockWidget(main, action) { - this->setObjectName("Graph"); - this->setAllowedAreas(Qt::AllDockWidgetAreas); - this->graphView = new DisassemblerGraphView(this); - this->setWidget(graphView); + /* + * Ugly hack just for the layout issue + * QSettings saves the state with the object names + * By doing this hack, + * you can at least avoid some mess by dismissing all the Extra Widgets + */ + QString name = "Graph"; + if (!action) { + name = "Extra Graph"; + } + setObjectName(name); + setAllowedAreas(Qt::AllDockWidgetAreas); + graphView = new DisassemblerGraphView(this); + setWidget(graphView); // getting the name of the class is implementation defined, and cannot be // used reliably across different compilers. @@ -24,8 +34,8 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) : main->toggleOverview(visibility, this); if (visibility) { Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Graph); - this->graphView->refreshView(); - this->graphView->onSeekChanged(Core()->getOffset()); + graphView->refreshView(); + graphView->onSeekChanged(Core()->getOffset()); } }); @@ -37,8 +47,8 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) : this, [ = ](CutterCore::MemoryWidgetType type) { bool emptyGraph = (type == CutterCore::MemoryWidgetType::Graph && Core()->isGraphEmpty()); if (type == CutterCore::MemoryWidgetType::Graph && !emptyGraph) { - this->raise(); - this->graphView->setFocus(); + raise(); + graphView->setFocus(); } }); } diff --git a/src/widgets/HexdumpWidget.cpp b/src/widgets/HexdumpWidget.cpp index 84bde252..6f791e18 100644 --- a/src/widgets/HexdumpWidget.cpp +++ b/src/widgets/HexdumpWidget.cpp @@ -21,6 +21,18 @@ HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) : { ui->setupUi(this); + /* + * Ugly hack just for the layout issue + * QSettings saves the state with the object names + * By doing this hack, + * you can at least avoid some mess by dismissing all the Extra Widgets + */ + QString name = "Hexdump"; + if (!action) { + name = "Extra Hexdump"; + } + setObjectName(name); + // Setup hex highlight //connect(ui->hexHexText, SIGNAL(cursorPositionChanged()), this, SLOT(highlightHexCurrentLine())); //highlightHexCurrentLine(); diff --git a/src/widgets/OverviewWidget.cpp b/src/widgets/OverviewWidget.cpp index 3068f05a..46c52c5b 100644 --- a/src/widgets/OverviewWidget.cpp +++ b/src/widgets/OverviewWidget.cpp @@ -5,11 +5,11 @@ OverviewWidget::OverviewWidget(MainWindow *main, QAction *action) : CutterDockWidget(main, action) { - this->setWindowTitle("Graph Overview"); - this->setObjectName("Graph Overview"); - this->setAllowedAreas(Qt::AllDockWidgetAreas); - this->graphView = new OverviewView(this); - this->setWidget(graphView); + setWindowTitle("Graph Overview"); + setObjectName("Graph Overview"); + setAllowedAreas(Qt::AllDockWidgetAreas); + graphView = new OverviewView(this); + setWidget(graphView); refreshDeferrer = createRefreshDeferrer([this]() { updateContents(); });