mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-18 19:06:10 +00:00
Add UI for managing layouts (#2211)
* Add dialog for deleting and renaming layouts. * Add documentation. Co-authored-by: Itay Cohen
This commit is contained in:
parent
6f75fa1a71
commit
0ea5d6fa4b
@ -41,6 +41,7 @@ release = '1.10.3'
|
||||
extensions = [
|
||||
'breathe',
|
||||
'recommonmark',
|
||||
'sphinx.ext.autosectionlabel'
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
@ -73,6 +74,9 @@ exclude_patterns = ['_build']
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'rainbow_dash'
|
||||
|
||||
|
||||
autosectionlabel_prefix_document = True
|
||||
|
||||
# -- Options for Breathe -----------------------------------------------------
|
||||
|
||||
breathe_projects = { 'cutter': '../doxygen-out/xml' }
|
||||
|
BIN
docs/source/images/layout_manager.png
Normal file
BIN
docs/source/images/layout_manager.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.7 KiB |
@ -13,7 +13,7 @@ Refresh contents
|
||||
|
||||
Reset to default layout
|
||||
----------------------------------------
|
||||
**Description:** Reset the current layout to the default layout provided by Cutter.
|
||||
**Description:** Reset the current :doc:`layout</user-docs/preferences/layout>` to the default layout provided by Cutter.
|
||||
|
||||
**Steps:** View -> Reset to default layout
|
||||
|
||||
@ -67,14 +67,20 @@ Reset Zoom
|
||||
**Shortcut:** :kbd:`Ctrl` + :kbd:`=`
|
||||
|
||||
|
||||
Manage layouts
|
||||
----------------------------------------
|
||||
**Description:** Rename and delete saved :doc:`layouts</user-docs/preferences/layout>`.
|
||||
|
||||
**Steps:** View -> Manage layouts , select layout, choose command
|
||||
|
||||
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.
|
||||
**Description:** Save the current :doc:`layout</user-docs/preferences/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.
|
||||
**Description:** Load the settings from the selected :doc:`layout</user-docs/preferences/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
|
||||
|
@ -1,11 +1,12 @@
|
||||
Preferences
|
||||
Configuration
|
||||
=====================
|
||||
This part of the documentation will provide the reader with information about different preferences available.
|
||||
Preferences can be opened by clicking ``Edit -> Preferences``.
|
||||
This part of the documentation will provide the reader with information about different configuration options available.
|
||||
Most configuration is done using the Preferences dialog. It can be opened by clicking :ref:`Edit -> Preferences<user-docs/menus/menu-bar/edit-menu:Preferences>`.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:maxdepth: 1
|
||||
:glob:
|
||||
|
||||
preferences/initialization-script
|
||||
preferences/*
|
||||
preferences/layout
|
||||
preferences/*
|
||||
|
21
docs/source/user-docs/preferences/layout.rst
Normal file
21
docs/source/user-docs/preferences/layout.rst
Normal file
@ -0,0 +1,21 @@
|
||||
Layout
|
||||
======
|
||||
|
||||
The set of currently opened widgets, their placement, and some properties is grouped into layouts.
|
||||
Cutter will automatically restore the last layout state when reopening Cutter. Last debug and normal layouts are stored separately.
|
||||
You can :ref:`save<user-docs/menus/menu-bar/view-menu:Save Layout>` multiple named layouts for different use cases.
|
||||
Use :doc:`../menus/menu-bar/view-menu` to :ref:`save<user-docs/menus/menu-bar/view-menu:Save Layout>`,
|
||||
:ref:`load<user-docs/menus/menu-bar/view-menu:Layouts>` or :ref:`user-docs/menus/menu-bar/view-menu:Reset to default layout`.
|
||||
A named layout is never automatically modified. To modify a previously saved layout, instead of entering a new name, select
|
||||
an existing layout from list in Save Layout dialog.
|
||||
|
||||
Layout manager
|
||||
-----------------------------------
|
||||
|
||||
.. image:: ../../images/layout_manager.png
|
||||
:alt: Layout manager dialog
|
||||
|
||||
|
||||
**Description:** Layout manager allows renaming and deleting saved layouts.
|
||||
|
||||
**Steps to open:** :doc:`View<../menus/menu-bar/view-menu>` -> :ref:`user-docs/menus/menu-bar/view-menu:Manage Layouts`
|
@ -422,7 +422,9 @@ SOURCES += \
|
||||
dialogs/MultitypeFileSaveDialog.cpp \
|
||||
widgets/BoolToggleDelegate.cpp \
|
||||
common/IOModesController.cpp \
|
||||
common/SettingsUpgrade.cpp
|
||||
common/SettingsUpgrade.cpp \
|
||||
dialogs/LayoutManager.cpp \
|
||||
common/CutterLayout.cpp
|
||||
|
||||
GRAPHVIZ_SOURCES = \
|
||||
widgets/GraphvizLayout.cpp
|
||||
@ -570,7 +572,9 @@ HEADERS += \
|
||||
dialogs/MultitypeFileSaveDialog.h \
|
||||
widgets/BoolToggleDelegate.h \
|
||||
common/IOModesController.h \
|
||||
common/SettingsUpgrade.h
|
||||
common/SettingsUpgrade.h \
|
||||
dialogs/LayoutManager.h \
|
||||
common/CutterLayout.h
|
||||
|
||||
GRAPHVIZ_HEADERS = widgets/GraphGridLayout.h
|
||||
|
||||
@ -637,7 +641,8 @@ FORMS += \
|
||||
dialogs/LinkTypeDialog.ui \
|
||||
widgets/ColorPicker.ui \
|
||||
dialogs/preferences/ColorThemeEditDialog.ui \
|
||||
widgets/ListDockWidget.ui
|
||||
widgets/ListDockWidget.ui \
|
||||
dialogs/LayoutManager.ui
|
||||
|
||||
RESOURCES += \
|
||||
resources.qrc \
|
||||
|
8
src/common/CutterLayout.cpp
Normal file
8
src/common/CutterLayout.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "CutterLayout.h"
|
||||
|
||||
using namespace Cutter;
|
||||
|
||||
bool Cutter::isBuiltinLayoutName(const QString &name)
|
||||
{
|
||||
return name == LAYOUT_DEFAULT || name == LAYOUT_DEBUG;
|
||||
}
|
25
src/common/CutterLayout.h
Normal file
25
src/common/CutterLayout.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef CUTTER_LAYOUT_H
|
||||
#define CUTTER_LAYOUT_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
#include <QVariantMap>
|
||||
|
||||
namespace Cutter
|
||||
{
|
||||
|
||||
struct CutterLayout
|
||||
{
|
||||
QByteArray geometry;
|
||||
QByteArray state;
|
||||
QMap<QString, QVariantMap> viewProperties;
|
||||
};
|
||||
|
||||
const QString LAYOUT_DEFAULT = "Default";
|
||||
const QString LAYOUT_DEBUG = "Debug";
|
||||
|
||||
bool isBuiltinLayoutName(const QString &name);
|
||||
|
||||
}
|
||||
#endif
|
@ -26,6 +26,7 @@
|
||||
#include "dialogs/preferences/PreferencesDialog.h"
|
||||
#include "dialogs/MapFileDialog.h"
|
||||
#include "dialogs/AsyncTaskDialog.h"
|
||||
#include "dialogs/LayoutManager.h"
|
||||
|
||||
// Widgets Headers
|
||||
#include "widgets/DisassemblerGraphView.h"
|
||||
@ -114,12 +115,7 @@
|
||||
template<class T>
|
||||
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;
|
||||
}
|
||||
using namespace Cutter;
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
@ -235,6 +231,7 @@ void MainWindow::initUI()
|
||||
});
|
||||
|
||||
connect(ui->actionSaveLayout, &QAction::triggered, this, &MainWindow::saveNamedLayout);
|
||||
connect(ui->actionManageLayouts, &QAction::triggered, this, &MainWindow::manageLayouts);
|
||||
|
||||
/* Setup plugins interfaces */
|
||||
for (auto &plugin : Plugins()->getPlugins()) {
|
||||
@ -1110,11 +1107,14 @@ void MainWindow::saveNamedLayout()
|
||||
{
|
||||
bool ok = false;
|
||||
QString name;
|
||||
QStringList names = layouts.keys();
|
||||
names.removeAll(LAYOUT_DEBUG);
|
||||
names.removeAll(LAYOUT_DEFAULT);
|
||||
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);
|
||||
name = QInputDialog::getItem(this, tr("Save layout"), tr("Enter name"), names, -1, true, &ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
@ -1124,6 +1124,13 @@ void MainWindow::saveNamedLayout()
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
void MainWindow::manageLayouts()
|
||||
{
|
||||
LayoutManager layoutManger(layouts, this);
|
||||
layoutManger.exec();
|
||||
updateLayoutsMenu();
|
||||
}
|
||||
|
||||
void MainWindow::addWidget(CutterDockWidget *widget)
|
||||
{
|
||||
dockWidgets.push_back(widget);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "common/Configuration.h"
|
||||
#include "common/InitialOptions.h"
|
||||
#include "common/IOModesController.h"
|
||||
#include "common/CutterLayout.h"
|
||||
#include "MemoryDockWidget.h"
|
||||
|
||||
#include <memory>
|
||||
@ -56,13 +57,6 @@ namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
struct CutterLayout
|
||||
{
|
||||
QByteArray geometry;
|
||||
QByteArray state;
|
||||
QMap<QString, QVariantMap> viewProperties;
|
||||
};
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -279,7 +273,7 @@ private:
|
||||
QMenu *disassemblyContextMenuExtensions = nullptr;
|
||||
QMenu *addressableContextMenuExtensions = nullptr;
|
||||
|
||||
QMap<QString, CutterLayout> layouts;
|
||||
QMap<QString, Cutter::CutterLayout> layouts;
|
||||
|
||||
void initUI();
|
||||
void initToolBar();
|
||||
@ -287,10 +281,10 @@ private:
|
||||
void initBackForwardMenu();
|
||||
void displayInitialOptionsDialog(const InitialOptions &options = InitialOptions(), bool skipOptionsDialog = false);
|
||||
|
||||
CutterLayout getViewLayout();
|
||||
CutterLayout getViewLayout(const QString &name);
|
||||
Cutter::CutterLayout getViewLayout();
|
||||
Cutter::CutterLayout getViewLayout(const QString &name);
|
||||
|
||||
void setViewLayout(const CutterLayout &layout);
|
||||
void setViewLayout(const Cutter::CutterLayout &layout);
|
||||
void loadLayouts(QSettings &settings);
|
||||
void saveLayouts(QSettings &settings);
|
||||
|
||||
@ -313,6 +307,7 @@ private:
|
||||
void updateHistoryMenu(QMenu *menu, bool redo = false);
|
||||
void updateLayoutsMenu();
|
||||
void saveNamedLayout();
|
||||
void manageLayouts();
|
||||
|
||||
void setOverviewData();
|
||||
bool isOverviewActive();
|
||||
|
@ -114,6 +114,8 @@
|
||||
<addaction name="actionGrouped_dock_dragging"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="menuZoom"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionManageLayouts"/>
|
||||
<addaction name="actionSaveLayout"/>
|
||||
<widget class="QMenu" name="menuLayouts">
|
||||
<property name="title">
|
||||
@ -849,6 +851,11 @@
|
||||
<string>Save layout</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionManageLayouts">
|
||||
<property name="text">
|
||||
<string>Manage layouts</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
|
75
src/dialogs/LayoutManager.cpp
Normal file
75
src/dialogs/LayoutManager.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#include "LayoutManager.h"
|
||||
#include "ui_LayoutManager.h"
|
||||
#include <QIntValidator>
|
||||
#include <QInputDialog>
|
||||
|
||||
using namespace Cutter;
|
||||
|
||||
LayoutManager::LayoutManager(QMap<QString, Cutter::CutterLayout> &layouts, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::LayoutManager),
|
||||
layouts(layouts)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
connect(ui->renameButton, &QPushButton::clicked, this, &LayoutManager::renameCurrentLayout);
|
||||
connect(ui->deleteButton, &QPushButton::clicked, this, &LayoutManager::deleteLayout);
|
||||
connect(ui->layoutSelector, &QComboBox::currentTextChanged, this, &LayoutManager::updateButtons);
|
||||
refreshNameList();
|
||||
}
|
||||
|
||||
LayoutManager::~LayoutManager()
|
||||
{
|
||||
}
|
||||
|
||||
void LayoutManager::refreshNameList(QString selection)
|
||||
{
|
||||
ui->layoutSelector->clear();
|
||||
for (auto it = layouts.begin(), end = layouts.end(); it != end; ++it) {
|
||||
if (!Cutter::isBuiltinLayoutName(it.key())) {
|
||||
ui->layoutSelector->addItem(it.key());
|
||||
}
|
||||
}
|
||||
if (!selection.isEmpty()) {
|
||||
ui->layoutSelector->setCurrentText(selection);
|
||||
}
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
void LayoutManager::renameCurrentLayout()
|
||||
{
|
||||
QString current = ui->layoutSelector->currentText();
|
||||
if (layouts.contains(current)) {
|
||||
QString newName;
|
||||
while (newName.isEmpty() || isBuiltinLayoutName(newName) || layouts.contains(newName)) {
|
||||
if (!newName.isEmpty()) {
|
||||
QMessageBox::warning(this, tr("Rename layout error"), tr("'%1' is already used.").arg(newName));
|
||||
}
|
||||
newName = QInputDialog::getText(this, tr("Save layout"), tr("Enter name"), QLineEdit::Normal,
|
||||
current);
|
||||
if (newName.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto layout = layouts.take(current);
|
||||
layouts.insert(newName, layout);
|
||||
refreshNameList(newName);
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutManager::deleteLayout()
|
||||
{
|
||||
auto selected = ui->layoutSelector->currentText();
|
||||
auto answer = QMessageBox::question(this, tr("Delete"),
|
||||
tr("Do you want to delete '%1'").arg(selected));
|
||||
if (answer == QMessageBox::Yes) {
|
||||
layouts.remove(selected);
|
||||
refreshNameList();
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutManager::updateButtons()
|
||||
{
|
||||
bool hasSelection = !ui->layoutSelector->currentText().isEmpty();
|
||||
ui->renameButton->setEnabled(hasSelection);
|
||||
ui->deleteButton->setEnabled(hasSelection);
|
||||
}
|
30
src/dialogs/LayoutManager.h
Normal file
30
src/dialogs/LayoutManager.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef LAYOUT_MANAGER_H
|
||||
#define LAYOUT_MANAGER_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <memory>
|
||||
#include "core/Cutter.h"
|
||||
#include "common/CutterLayout.h"
|
||||
|
||||
namespace Ui {
|
||||
class LayoutManager;
|
||||
}
|
||||
|
||||
class LayoutManager : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LayoutManager(QMap<QString, Cutter::CutterLayout> &layouts, QWidget *parent);
|
||||
~LayoutManager();
|
||||
|
||||
private:
|
||||
void refreshNameList(QString selection = "");
|
||||
void renameCurrentLayout();
|
||||
void deleteLayout();
|
||||
void updateButtons();
|
||||
std::unique_ptr<Ui::LayoutManager> ui;
|
||||
QMap<QString, Cutter::CutterLayout> &layouts;
|
||||
};
|
||||
|
||||
#endif // LAYOUT_MANAGER_H
|
42
src/dialogs/LayoutManager.ui
Normal file
42
src/dialogs/LayoutManager.ui
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LayoutManager</class>
|
||||
<widget class="QDialog" name="LayoutManager">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>254</width>
|
||||
<height>88</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Layout</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="layoutSelector"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="renameButton">
|
||||
<property name="text">
|
||||
<string>Rename</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteButton">
|
||||
<property name="text">
|
||||
<string>Delete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
Reference in New Issue
Block a user