Vane11ope/fix layout (#1308)

Refactoring and Fixes for the default layout.
This commit is contained in:
Vanellope 2019-03-18 15:44:14 +09:00 committed by Itay Cohen
parent f23ff9d8c5
commit 96f6e062fc
10 changed files with 147 additions and 99 deletions

View File

@ -123,9 +123,49 @@ void MainWindow::initUI()
{ {
ui->setupUi(this); 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 // Sepparator between undo/redo and goto lineEdit
QWidget *spacer3 = new QWidget(); QWidget *spacer3 = new QWidget();
spacer3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); spacer3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
@ -186,18 +226,15 @@ void MainWindow::initUI()
QObject::connect(configuration, &Configuration::colorsUpdated, [this]() { QObject::connect(configuration, &Configuration::colorsUpdated, [this]() {
this->visualNavbar->updateGraphicsScene(); this->visualNavbar->updateGraphicsScene();
}); });
}
/* void MainWindow::initDocks()
* Dock Widgets {
*/
dockWidgets.reserve(20); dockWidgets.reserve(20);
disassemblyDock = new DisassemblyWidget(this, ui->actionDisassembly); disassemblyDock = new DisassemblyWidget(this, ui->actionDisassembly);
hexdumpDock = new HexdumpWidget(this, ui->actionHexdump); hexdumpDock = new HexdumpWidget(this, ui->actionHexdump);
pseudocodeDock = new PseudocodeWidget(this, ui->actionPseudocode); pseudocodeDock = new PseudocodeWidget(this, ui->actionPseudocode);
consoleDock = new ConsoleWidget(this, ui->actionConsole); consoleDock = new ConsoleWidget(this, ui->actionConsole);
// Add graph view as dockable
overviewDock = new OverviewWidget(this, ui->actionOverview); overviewDock = new OverviewWidget(this, ui->actionOverview);
overviewDock->hide(); overviewDock->hide();
graphDock = new GraphWidget(this, ui->actionGraph); graphDock = new GraphWidget(this, ui->actionGraph);
@ -242,57 +279,18 @@ void MainWindow::initUI()
classesDock = new ClassesWidget(this, ui->actionClasses); classesDock = new ClassesWidget(this, ui->actionClasses);
resourcesDock = new ResourcesWidget(this, ui->actionResources); resourcesDock = new ResourcesWidget(this, ui->actionResources);
vTablesDock = new VTablesWidget(this, ui->actionVTables); vTablesDock = new VTablesWidget(this, ui->actionVTables);
}
void MainWindow::initLayout()
{
// Set up dock widgets default layout // Set up dock widgets default layout
resetToDefaultLayout();
enableDebugWidgetsMenu(false); enableDebugWidgetsMenu(false);
// Restore saved settings // Restore saved settings
this->readSettings(); readSettingsOrDefault();
// TODO: Allow the user to select this option visually in the GUI settings // TODO: Allow the user to select this option visually in the GUI settings
// Adjust the DockWidget areas // Adjust the DockWidget areas
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
//setCorner( Qt::TopRightCorner, Qt::RightDockWidgetArea );
setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); 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) void MainWindow::toggleOverview(bool visibility, GraphWidget *targetGraph)
@ -327,13 +325,17 @@ void MainWindow::toggleOverview(bool visibility, GraphWidget *targetGraph)
void MainWindow::disconnectOverview() void MainWindow::disconnectOverview()
{ {
disconnect(targetGraphDock->graphView, SIGNAL(refreshBlock()), this, SLOT(updateOverview())); if (targetGraphDock) {
disconnect(targetGraphDock->graphView, SIGNAL(viewRefreshed()), this, SLOT(forceUpdateOverview())); disconnect(targetGraphDock->graphView, SIGNAL(refreshBlock()), this, SLOT(updateOverview()));
disconnect(targetGraphDock->graphView, SIGNAL(viewZoomed()), this, SLOT(updateOverview())); disconnect(targetGraphDock->graphView, SIGNAL(viewRefreshed()), this, SLOT(updateOverview()));
disconnect(overviewDock->graphView, SIGNAL(mouseMoved()), this, SLOT(adjustGraph())); disconnect(targetGraphDock->graphView, SIGNAL(viewZoomed()), this, SLOT(updateOverview()));
disconnect(overviewDock->graphView, SIGNAL(refreshBlock()), this, SLOT(updateOverviewAddr())); }
disconnect(overviewDock, &QDockWidget::dockLocationChanged, this, &MainWindow::forceUpdateOverview); if (overviewDock) {
disconnect(overviewDock, SIGNAL(resized()), this, SLOT(forceUpdateOverview())); 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() void MainWindow::setOverviewData()
@ -616,14 +618,37 @@ void MainWindow::closeEvent(QCloseEvent *event)
QMainWindow::closeEvent(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; QSettings settings;
QByteArray geo = settings.value("geometry", QByteArray()).toByteArray(); QByteArray geo = settings.value("geometry", QByteArray()).toByteArray();
restoreGeometry(geo);
QByteArray state = settings.value("state", 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); restoreState(state);
this->responsive = settings.value("responsive").toBool(); responsive = settings.value("responsive").toBool();
panelLock = settings.value("panelLock").toBool(); panelLock = settings.value("panelLock").toBool();
setPanelLock(); setPanelLock();
tabsOnTop = settings.value("tabsOnTop").toBool(); tabsOnTop = settings.value("tabsOnTop").toBool();
@ -778,8 +803,6 @@ void MainWindow::hideAllDocks()
for (auto w : dockWidgets) { for (auto w : dockWidgets) {
removeDockWidget(w); removeDockWidget(w);
} }
updateDockActionsChecked();
} }
void MainWindow::updateDockActionsChecked() void MainWindow::updateDockActionsChecked()
@ -855,16 +878,6 @@ void MainWindow::resetToDefaultLayout()
restoreDocks(); restoreDocks();
showZenDocks(); showZenDocks();
dashboardDock->raise(); 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() void MainWindow::resetToDebugLayout()
@ -927,6 +940,7 @@ void MainWindow::on_actionFunctionsRename_triggered()
void MainWindow::on_actionDefault_triggered() void MainWindow::on_actionDefault_triggered()
{ {
disconnectOverview();
if (core->currentlyDebugging) { if (core->currentlyDebugging) {
resetToDebugLayout(); resetToDebugLayout();
} else { } else {
@ -1203,7 +1217,7 @@ void MainWindow::changeDefinedView()
CutterCore::MemoryWidgetType memType = core->getMemoryWidgetPriority(); CutterCore::MemoryWidgetType memType = core->getMemoryWidgetPriority();
hideAllDocks(); hideAllDocks();
restoreDocks(); restoreDocks();
readSettings(); readSettingsOrDefault();
enableDebugWidgetsMenu(false); enableDebugWidgetsMenu(false);
core->raisePrioritizedMemoryWidget(memType); core->raisePrioritizedMemoryWidget(memType);
} }

View File

@ -89,7 +89,8 @@ public:
bool saveProjectAs(bool quit = false); bool saveProjectAs(bool quit = false);
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
void readSettings(); void paintEvent(QPaintEvent *event) override;
void readSettingsOrDefault();
void saveSettings(); void saveSettings();
void readDebugSettings(); void readDebugSettings();
void saveDebugSettings(); void saveDebugSettings();
@ -254,6 +255,9 @@ private:
JupyterWidget *jupyterDock = nullptr; JupyterWidget *jupyterDock = nullptr;
#endif #endif
void initToolBar();
void initDocks();
void initLayout();
void displayInitialOptionsDialog(const InitialOptions &options = InitialOptions(), bool skipOptionsDialog = false); void displayInitialOptionsDialog(const InitialOptions &options = InitialOptions(), bool skipOptionsDialog = false);
void resetToDefaultLayout(); void resetToDefaultLayout();

View File

@ -8,8 +8,8 @@ CutterDockWidget::CutterDockWidget(MainWindow *parent, QAction *action) :
QDockWidget(parent), QDockWidget(parent),
action(action) action(action)
{ {
parent->addToDockWidgetList(this);
if (action) { if (action) {
parent->addToDockWidgetList(this);
parent->addDockWidgetAction(this, action); parent->addDockWidgetAction(this, action);
connect(action, &QAction::triggered, this, &CutterDockWidget::toggleDockWidget); connect(action, &QAction::triggered, this, &CutterDockWidget::toggleDockWidget);
} }

View File

@ -42,6 +42,18 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action)
, mDisasTextEdit(new DisassemblyTextEdit(this)) , mDisasTextEdit(new DisassemblyTextEdit(this))
, seekable(new CutterSeekable(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; topOffset = bottomOffset = RVA_INVALID;
cursorLineOffset = 0; cursorLineOffset = 0;
seekFromCursor = false; seekFromCursor = false;
@ -57,7 +69,6 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main, QAction *action)
setWidget(mDisasScrollArea); setWidget(mDisasScrollArea);
setAllowedAreas(Qt::AllDockWidgetAreas); setAllowedAreas(Qt::AllDockWidgetAreas);
setObjectName("DisassemblyWidget");
setupFonts(); setupFonts();
setupColors(); setupColors();

View File

@ -566,6 +566,11 @@ void FunctionsWidget::refreshTree()
Core()->getAsyncTaskManager()->start(task); Core()->getAsyncTaskManager()->start(task);
} }
void FunctionsWidget::changeSizePolicy(QSizePolicy::Policy hor, QSizePolicy::Policy ver)
{
ui->dockWidgetContents->setSizePolicy(hor, ver);
}
void FunctionsWidget::onFunctionsDoubleClicked(const QModelIndex &index) void FunctionsWidget::onFunctionsDoubleClicked(const QModelIndex &index)
{ {
if (!index.isValid()) if (!index.isValid())

View File

@ -101,21 +101,18 @@ class FunctionsWidget : public CutterDockWidget
public: public:
explicit FunctionsWidget(MainWindow *main, QAction *action = nullptr); explicit FunctionsWidget(MainWindow *main, QAction *action = nullptr);
~FunctionsWidget(); ~FunctionsWidget();
void changeSizePolicy(QSizePolicy::Policy hor, QSizePolicy::Policy ver);
private slots: private slots:
void onFunctionsDoubleClicked(const QModelIndex &index); void onFunctionsDoubleClicked(const QModelIndex &index);
void showFunctionsContextMenu(const QPoint &pt); void showFunctionsContextMenu(const QPoint &pt);
void on_actionDisasAdd_comment_triggered(); void on_actionDisasAdd_comment_triggered();
void on_actionFunctionsRename_triggered(); void on_actionFunctionsRename_triggered();
void on_action_References_triggered(); void on_action_References_triggered();
void on_actionFunctionsUndefine_triggered(); void on_actionFunctionsUndefine_triggered();
void on_actionHorizontal_triggered(); void on_actionHorizontal_triggered();
void on_actionVertical_triggered(); void on_actionVertical_triggered();
void showTitleContextMenu(const QPoint &pt); void showTitleContextMenu(const QPoint &pt);
void refreshTree(); void refreshTree();
protected: protected:
@ -124,18 +121,13 @@ protected:
private: private:
std::unique_ptr<Ui::FunctionsWidget> ui; std::unique_ptr<Ui::FunctionsWidget> ui;
MainWindow *main; MainWindow *main;
QSharedPointer<FunctionsTask> task; QSharedPointer<FunctionsTask> task;
QList<FunctionDescription> functions; QList<FunctionDescription> functions;
QSet<RVA> importAddresses; QSet<RVA> importAddresses;
ut64 mainAdress; ut64 mainAdress;
FunctionModel *functionModel; FunctionModel *functionModel;
FunctionSortFilterProxyModel *functionProxyModel; FunctionSortFilterProxyModel *functionProxyModel;
CutterTreeWidget *tree; CutterTreeWidget *tree;
void setScrollMode(); void setScrollMode();
}; };

View File

@ -18,7 +18,7 @@
</property> </property>
<widget class="QWidget" name="dockWidgetContents"> <widget class="QWidget" name="dockWidgetContents">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>1</horstretch> <horstretch>1</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>

View File

@ -6,10 +6,20 @@
GraphWidget::GraphWidget(MainWindow *main, QAction *action) : GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
CutterDockWidget(main, action) CutterDockWidget(main, action)
{ {
this->setObjectName("Graph"); /*
this->setAllowedAreas(Qt::AllDockWidgetAreas); * Ugly hack just for the layout issue
this->graphView = new DisassemblerGraphView(this); * QSettings saves the state with the object names
this->setWidget(graphView); * 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 // getting the name of the class is implementation defined, and cannot be
// used reliably across different compilers. // used reliably across different compilers.
@ -24,8 +34,8 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
main->toggleOverview(visibility, this); main->toggleOverview(visibility, this);
if (visibility) { if (visibility) {
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Graph); Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Graph);
this->graphView->refreshView(); graphView->refreshView();
this->graphView->onSeekChanged(Core()->getOffset()); graphView->onSeekChanged(Core()->getOffset());
} }
}); });
@ -37,8 +47,8 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
this, [ = ](CutterCore::MemoryWidgetType type) { this, [ = ](CutterCore::MemoryWidgetType type) {
bool emptyGraph = (type == CutterCore::MemoryWidgetType::Graph && Core()->isGraphEmpty()); bool emptyGraph = (type == CutterCore::MemoryWidgetType::Graph && Core()->isGraphEmpty());
if (type == CutterCore::MemoryWidgetType::Graph && !emptyGraph) { if (type == CutterCore::MemoryWidgetType::Graph && !emptyGraph) {
this->raise(); raise();
this->graphView->setFocus(); graphView->setFocus();
} }
}); });
} }

View File

@ -21,6 +21,18 @@ HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) :
{ {
ui->setupUi(this); 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 // Setup hex highlight
//connect(ui->hexHexText, SIGNAL(cursorPositionChanged()), this, SLOT(highlightHexCurrentLine())); //connect(ui->hexHexText, SIGNAL(cursorPositionChanged()), this, SLOT(highlightHexCurrentLine()));
//highlightHexCurrentLine(); //highlightHexCurrentLine();

View File

@ -5,11 +5,11 @@
OverviewWidget::OverviewWidget(MainWindow *main, QAction *action) : OverviewWidget::OverviewWidget(MainWindow *main, QAction *action) :
CutterDockWidget(main, action) CutterDockWidget(main, action)
{ {
this->setWindowTitle("Graph Overview"); setWindowTitle("Graph Overview");
this->setObjectName("Graph Overview"); setObjectName("Graph Overview");
this->setAllowedAreas(Qt::AllDockWidgetAreas); setAllowedAreas(Qt::AllDockWidgetAreas);
this->graphView = new OverviewView(this); graphView = new OverviewView(this);
this->setWidget(graphView); setWidget(graphView);
refreshDeferrer = createRefreshDeferrer([this]() { refreshDeferrer = createRefreshDeferrer([this]() {
updateContents(); updateContents();
}); });