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);
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()
{
if (targetGraphDock) {
disconnect(targetGraphDock->graphView, SIGNAL(refreshBlock()), this, SLOT(updateOverview()));
disconnect(targetGraphDock->graphView, SIGNAL(viewRefreshed()), this, SLOT(forceUpdateOverview()));
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);
}

View File

@ -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();

View File

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

View File

@ -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();

View File

@ -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())

View File

@ -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::FunctionsWidget> ui;
MainWindow *main;
QSharedPointer<FunctionsTask> task;
QList<FunctionDescription> functions;
QSet<RVA> importAddresses;
ut64 mainAdress;
FunctionModel *functionModel;
FunctionSortFilterProxyModel *functionProxyModel;
CutterTreeWidget *tree;
void setScrollMode();
};

View File

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

View File

@ -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();
}
});
}

View File

@ -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();

View File

@ -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();
});