2018-06-23 16:59:23 +00:00
# include "common/PythonManager.h"
2019-02-22 16:50:45 +00:00
# include "core/MainWindow.h"
2017-10-01 19:09:42 +00:00
# include "ui_MainWindow.h"
2018-10-17 07:55:53 +00:00
# include "common/Helpers.h"
2019-02-07 10:52:08 +00:00
# include "CutterConfig.h"
2019-02-09 13:05:06 +00:00
# include "plugins/PluginManager.h"
2017-03-29 10:18:37 +00:00
2018-11-17 10:10:44 +00:00
// Qt Headers
2018-01-09 12:09:25 +00:00
# include <QApplication>
2017-05-14 16:21:54 +00:00
# include <QComboBox>
# include <QCompleter>
2017-03-29 10:18:37 +00:00
# include <QDebug>
# include <QDesktopServices>
2017-05-14 16:21:54 +00:00
# include <QDir>
# include <QDockWidget>
# include <QFile>
2017-03-29 10:18:37 +00:00
# include <QFileDialog>
2017-05-14 16:21:54 +00:00
# include <QFont>
# include <QFontDialog>
# include <QLabel>
# include <QLineEdit>
# include <QList>
# include <QMessageBox>
# include <QProcess>
2017-03-29 10:18:37 +00:00
# include <QPropertyAnimation>
2019-02-07 10:52:08 +00:00
# include <QSysInfo>
# include <QJsonObject>
2017-05-14 16:21:54 +00:00
# include <QScrollBar>
# include <QSettings>
# include <QShortcut>
# include <QStringListModel>
2017-03-29 10:18:37 +00:00
# include <QStyledItemDelegate>
2017-05-14 16:21:54 +00:00
# include <QStyleFactory>
# include <QTextCursor>
2017-03-29 10:18:37 +00:00
# include <QtGlobal>
2017-05-14 16:21:54 +00:00
# include <QToolButton>
2017-03-29 10:18:37 +00:00
# include <QToolTip>
2017-04-13 15:36:20 +00:00
# include <QTreeWidgetItem>
2017-12-23 16:42:42 +00:00
# include <QSvgRenderer>
2017-05-14 16:21:54 +00:00
2018-11-17 10:10:44 +00:00
// Common Headers
2018-10-17 07:55:53 +00:00
# include "common/Highlighter.h"
# include "common/HexAsciiHighlighter.h"
# include "common/Helpers.h"
# include "common/SvgIconEngine.h"
# include "common/ProgressIndicator.h"
# include "common/TempConfig.h"
2017-04-13 15:36:20 +00:00
2018-11-17 10:10:44 +00:00
// Dialogs
2019-01-19 20:54:02 +00:00
# include "dialogs/WelcomeDialog.h"
2017-12-23 16:42:42 +00:00
# include "dialogs/NewFileDialog.h"
2018-08-18 10:51:11 +00:00
# include "dialogs/InitialOptionsDialog.h"
2018-06-20 09:24:28 +00:00
# include "dialogs/SaveProjectDialog.h"
# include "dialogs/CommentsDialog.h"
# include "dialogs/AboutDialog.h"
# include "dialogs/RenameDialog.h"
# include "dialogs/preferences/PreferencesDialog.h"
# include "dialogs/OpenFileDialog.h"
2019-01-28 13:37:20 +00:00
# include "dialogs/AsyncTaskDialog.h"
2018-06-20 09:24:28 +00:00
2018-11-17 10:10:44 +00:00
// Widgets Headers
2017-12-13 22:38:46 +00:00
# include "widgets/DisassemblerGraphView.h"
2019-01-24 17:13:04 +00:00
# include "widgets/GraphView.h"
2018-03-16 21:46:57 +00:00
# include "widgets/GraphWidget.h"
2019-01-24 17:13:04 +00:00
# include "widgets/OverviewWidget.h"
2019-02-19 15:56:50 +00:00
# include "widgets/OverviewView.h"
2017-10-02 16:18:40 +00:00
# include "widgets/FunctionsWidget.h"
# include "widgets/SectionsWidget.h"
2018-10-20 18:20:06 +00:00
# include "widgets/SegmentsWidget.h"
2017-10-02 16:18:40 +00:00
# include "widgets/CommentsWidget.h"
# include "widgets/ImportsWidget.h"
# include "widgets/ExportsWidget.h"
2018-03-06 17:21:48 +00:00
# include "widgets/TypesWidget.h"
2018-03-08 12:24:15 +00:00
# include "widgets/SearchWidget.h"
2017-10-02 16:18:40 +00:00
# include "widgets/SymbolsWidget.h"
# include "widgets/StringsWidget.h"
# include "widgets/RelocsWidget.h"
# include "widgets/FlagsWidget.h"
2017-12-08 15:00:52 +00:00
# include "widgets/VisualNavbar.h"
2017-10-02 16:18:40 +00:00
# include "widgets/Dashboard.h"
2019-02-13 06:38:47 +00:00
# include "widgets/SdbWidget.h"
2017-10-02 16:18:40 +00:00
# include "widgets/Omnibar.h"
# include "widgets/ConsoleWidget.h"
# include "widgets/EntrypointWidget.h"
2017-12-23 16:42:42 +00:00
# include "widgets/ClassesWidget.h"
2018-02-04 14:32:18 +00:00
# include "widgets/ResourcesWidget.h"
2018-02-26 22:26:18 +00:00
# include "widgets/VTablesWidget.h"
2017-12-13 17:36:00 +00:00
# include "widgets/JupyterWidget.h"
2018-05-21 17:34:41 +00:00
# include "widgets/HeadersWidget.h"
2018-05-24 15:37:37 +00:00
# include "widgets/ZignaturesWidget.h"
2018-12-21 20:36:40 +00:00
# include "widgets/DebugActions.h"
2018-06-12 08:43:14 +00:00
# include "widgets/MemoryMapWidget.h"
2018-06-22 08:45:00 +00:00
# include "widgets/BreakpointWidget.h"
2018-07-19 14:35:46 +00:00
# include "widgets/RegisterRefsWidget.h"
2017-04-13 15:36:20 +00:00
2019-02-22 16:50:45 +00:00
# include "common/RunScriptTask.h"
2019-01-28 13:37:20 +00:00
2018-07-06 21:23:51 +00:00
// Graphics
2017-03-29 10:18:37 +00:00
# include <QGraphicsEllipseItem>
# include <QGraphicsScene>
# include <QGraphicsView>
2017-05-13 18:09:36 +00:00
MainWindow : : MainWindow ( QWidget * parent ) :
2017-03-29 10:18:37 +00:00
QMainWindow ( parent ) ,
2018-02-26 22:25:23 +00:00
core ( Core ( ) ) ,
2018-02-04 14:32:18 +00:00
ui ( new Ui : : MainWindow )
2017-03-29 10:18:37 +00:00
{
2017-12-17 13:49:03 +00:00
panelLock = false ;
tabsOnTop = false ;
2018-02-26 22:25:23 +00:00
configuration = Config ( ) ;
2017-05-13 18:09:36 +00:00
}
2017-03-29 10:18:37 +00:00
2017-05-13 18:09:36 +00:00
MainWindow : : ~ MainWindow ( )
{
}
void MainWindow : : initUI ( )
{
ui - > setupUi ( this ) ;
2017-04-05 08:56:59 +00:00
2017-03-29 10:18:37 +00:00
/*
2018-11-01 22:23:01 +00:00
* Toolbar
*/
2017-03-29 10:18:37 +00:00
// Sepparator between undo/redo and goto lineEdit
2017-04-09 19:55:06 +00:00
QWidget * spacer3 = new QWidget ( ) ;
2017-03-29 10:18:37 +00:00
spacer3 - > setSizePolicy ( QSizePolicy : : Expanding , QSizePolicy : : Expanding ) ;
spacer3 - > setMinimumSize ( 20 , 20 ) ;
2018-06-12 08:43:14 +00:00
spacer3 - > setMaximumWidth ( 100 ) ;
2017-11-18 14:57:00 +00:00
ui - > mainToolBar - > addWidget ( spacer3 ) ;
2017-03-29 10:18:37 +00:00
2018-12-21 20:36:40 +00:00
DebugActions * debugActions = new DebugActions ( ui - > mainToolBar , this ) ;
2018-07-17 07:26:20 +00:00
// Debug menu
2018-12-21 20:36:40 +00:00
ui - > menuDebug - > addAction ( debugActions - > actionStartEmul ) ;
2018-07-17 07:26:20 +00:00
ui - > menuDebug - > addSeparator ( ) ;
2018-12-21 20:36:40 +00:00
ui - > menuDebug - > addAction ( debugActions - > actionStep ) ;
ui - > menuDebug - > addAction ( debugActions - > actionStepOver ) ;
ui - > menuDebug - > addAction ( debugActions - > actionStepOut ) ;
2018-07-17 07:26:20 +00:00
ui - > menuDebug - > addSeparator ( ) ;
2018-12-21 20:36:40 +00:00
ui - > menuDebug - > addAction ( debugActions - > actionContinue ) ;
ui - > menuDebug - > addAction ( debugActions - > actionContinueUntilCall ) ;
ui - > menuDebug - > addAction ( debugActions - > actionContinueUntilSyscall ) ;
2018-06-12 08:43:14 +00:00
// Sepparator between undo/redo and goto lineEdit
QWidget * spacer4 = new QWidget ( ) ;
spacer4 - > setSizePolicy ( QSizePolicy : : Expanding , QSizePolicy : : Expanding ) ;
spacer4 - > setMinimumSize ( 20 , 20 ) ;
spacer4 - > setMaximumWidth ( 100 ) ;
ui - > mainToolBar - > addWidget ( spacer4 ) ;
2017-03-29 10:18:37 +00:00
// Omnibar LineEdit
this - > omnibar = new Omnibar ( this ) ;
2017-11-18 14:57:00 +00:00
ui - > mainToolBar - > addWidget ( this - > omnibar ) ;
2017-03-29 10:18:37 +00:00
2017-09-01 13:03:35 +00:00
// Add special separators to the toolbar that expand to separate groups of elements
2017-04-09 19:55:06 +00:00
QWidget * spacer2 = new QWidget ( ) ;
2017-03-29 10:18:37 +00:00
spacer2 - > setSizePolicy ( QSizePolicy : : Expanding , QSizePolicy : : Expanding ) ;
spacer2 - > setMinimumSize ( 10 , 10 ) ;
spacer2 - > setMaximumWidth ( 300 ) ;
2017-11-18 14:57:00 +00:00
ui - > mainToolBar - > addWidget ( spacer2 ) ;
2017-03-29 10:18:37 +00:00
2017-09-01 13:03:35 +00:00
// Separator between back/forward and undo/redo buttons
2017-04-09 19:55:06 +00:00
QWidget * spacer = new QWidget ( ) ;
2017-03-29 10:18:37 +00:00
spacer - > setSizePolicy ( QSizePolicy : : Fixed , QSizePolicy : : Expanding ) ;
spacer - > setMinimumSize ( 20 , 20 ) ;
ui - > mainToolBar - > addWidget ( spacer ) ;
2018-06-24 19:12:02 +00:00
tasksProgressIndicator = new ProgressIndicator ( ) ;
ui - > mainToolBar - > addWidget ( tasksProgressIndicator ) ;
QWidget * spacerEnd = new QWidget ( ) ;
spacerEnd - > setSizePolicy ( QSizePolicy : : Fixed , QSizePolicy : : Expanding ) ;
spacerEnd - > setMinimumSize ( 4 , 0 ) ;
spacerEnd - > setMaximumWidth ( 4 ) ;
ui - > mainToolBar - > addWidget ( spacerEnd ) ;
2018-06-22 18:34:25 +00:00
2017-12-08 15:00:52 +00:00
// Visual navigation tool bar
this - > visualNavbar = new VisualNavbar ( this ) ;
this - > visualNavbar - > setMovable ( false ) ;
2017-03-29 10:18:37 +00:00
addToolBarBreak ( Qt : : TopToolBarArea ) ;
2017-12-08 15:00:52 +00:00
addToolBar ( visualNavbar ) ;
2018-10-10 09:37:24 +00:00
QObject : : connect ( configuration , & Configuration : : colorsUpdated , [ this ] ( ) {
this - > visualNavbar - > updateGraphicsScene ( ) ;
} ) ;
2017-03-29 10:18:37 +00:00
/*
* Dock Widgets
*/
2018-02-04 14:32:18 +00:00
dockWidgets . reserve ( 20 ) ;
2017-10-11 11:22:30 +00:00
2018-03-16 21:46:57 +00:00
disassemblyDock = new DisassemblyWidget ( this , ui - > actionDisassembly ) ;
hexdumpDock = new HexdumpWidget ( this , ui - > actionHexdump ) ;
2019-01-13 15:41:08 +00:00
pseudocodeDock = new PseudocodeWidget ( this , ui - > actionPseudocode ) ;
2018-03-16 21:46:57 +00:00
consoleDock = new ConsoleWidget ( this , ui - > actionConsole ) ;
2017-12-10 16:55:42 +00:00
2017-10-11 21:07:32 +00:00
// Add graph view as dockable
2019-01-24 17:13:04 +00:00
overviewDock = new OverviewWidget ( this , ui - > actionOverview ) ;
2019-02-19 15:56:50 +00:00
overviewDock - > hide ( ) ;
graphDock = new GraphWidget ( this , ui - > actionGraph ) ;
2019-01-13 15:41:08 +00:00
sectionsDock = new SectionsWidget ( this , ui - > actionSections ) ;
2019-01-13 17:55:02 +00:00
segmentsDock = new SegmentsWidget ( this , ui - > actionSegments ) ;
entrypointDock = new EntrypointWidget ( this , ui - > actionEntrypoints ) ;
2018-03-16 21:46:57 +00:00
functionsDock = new FunctionsWidget ( this , ui - > actionFunctions ) ;
2019-01-13 17:55:02 +00:00
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 ) ;
2019-01-13 15:41:08 +00:00
commentsDock = new CommentsWidget ( this , ui - > actionComments ) ;
2019-01-13 17:55:02 +00:00
stringsDock = new StringsWidget ( this , ui - > actionStrings ) ;
flagsDock = new FlagsWidget ( this , ui - > actionFlags ) ;
2019-01-13 18:11:59 +00:00
stackDock = new StackWidget ( this , ui - > actionStack ) ;
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 ) ;
2018-03-02 13:15:53 +00:00
# ifdef CUTTER_ENABLE_JUPYTER
2019-01-13 17:55:02 +00:00
jupyterDock = new JupyterWidget ( this , ui - > actionJupyter ) ;
2018-03-02 14:06:08 +00:00
# else
ui - > actionJupyter - > setEnabled ( false ) ;
ui - > actionJupyter - > setVisible ( false ) ;
2018-03-02 13:15:53 +00:00
# endif
2018-03-16 21:46:57 +00:00
dashboardDock = new Dashboard ( this , ui - > actionDashboard ) ;
2019-02-13 06:38:47 +00:00
sdbDock = new SdbWidget ( this , ui - > actionSDBBrowser ) ;
2019-01-13 17:55:02 +00:00
classesDock = new ClassesWidget ( this , ui - > actionClasses ) ;
resourcesDock = new ResourcesWidget ( this , ui - > actionResources ) ;
vTablesDock = new VTablesWidget ( this , ui - > actionVTables ) ;
2017-12-23 16:42:42 +00:00
2017-03-29 10:18:37 +00:00
2018-03-11 11:41:19 +00:00
// Set up dock widgets default layout
resetToDefaultLayout ( ) ;
2018-10-22 18:06:30 +00:00
enableDebugWidgetsMenu ( false ) ;
2018-03-11 11:41:19 +00:00
2017-03-29 10:18:37 +00:00
// Restore saved settings
this - > readSettings ( ) ;
// TODO: Allow the user to select this option visually in the GUI settings
// Adjust the DockWidget areas
2017-04-09 19:55:06 +00:00
setCorner ( Qt : : TopLeftCorner , Qt : : LeftDockWidgetArea ) ;
2017-03-29 10:18:37 +00:00
//setCorner( Qt::TopRightCorner, Qt::RightDockWidgetArea );
2017-04-09 19:55:06 +00:00
setCorner ( Qt : : BottomLeftCorner , Qt : : LeftDockWidgetArea ) ;
2017-03-29 10:18:37 +00:00
//setCorner( Qt::BottomRightCorner, Qt::RightDockWidgetArea );
/*
* Some global shortcuts
*/
// Period goes to command entry
2017-04-09 19:55:06 +00:00
QShortcut * cmd_shortcut = new QShortcut ( QKeySequence ( Qt : : Key_Period ) , this ) ;
2017-12-10 16:55:42 +00:00
connect ( cmd_shortcut , SIGNAL ( activated ( ) ) , consoleDock , SLOT ( focusInputLineEdit ( ) ) ) ;
2017-03-29 10:18:37 +00:00
// G and S goes to goto entry
2017-04-09 19:55:06 +00:00
QShortcut * goto_shortcut = new QShortcut ( QKeySequence ( Qt : : Key_G ) , this ) ;
2017-03-29 10:18:37 +00:00
connect ( goto_shortcut , SIGNAL ( activated ( ) ) , this - > omnibar , SLOT ( setFocus ( ) ) ) ;
2017-04-09 19:55:06 +00:00
QShortcut * seek_shortcut = new QShortcut ( QKeySequence ( Qt : : Key_S ) , this ) ;
2017-03-29 10:18:37 +00:00
connect ( seek_shortcut , SIGNAL ( activated ( ) ) , this - > omnibar , SLOT ( setFocus ( ) ) ) ;
2017-04-12 21:04:39 +00:00
QShortcut * refresh_shortcut = new QShortcut ( QKeySequence ( QKeySequence : : Refresh ) , this ) ;
2017-11-19 12:56:10 +00:00
connect ( refresh_shortcut , SIGNAL ( activated ( ) ) , this , SLOT ( refreshAll ( ) ) ) ;
2017-05-13 18:09:36 +00:00
2019-02-07 10:52:08 +00:00
connect ( core , SIGNAL ( projectSaved ( bool , const QString & ) ) , this , SLOT ( projectSaved ( bool ,
const QString & ) ) ) ;
2018-06-22 18:34:25 +00:00
2018-06-12 15:42:38 +00:00
connect ( core , & CutterCore : : changeDebugView , this , & MainWindow : : changeDebugView ) ;
connect ( core , & CutterCore : : changeDefinedView , this , & MainWindow : : changeDefinedView ) ;
2018-08-27 11:16:48 +00:00
connect ( core , SIGNAL ( newMessage ( const QString & ) ) ,
this - > consoleDock , SLOT ( addOutput ( const QString & ) ) ) ;
connect ( core , SIGNAL ( newDebugMessage ( const QString & ) ) ,
this - > consoleDock , SLOT ( addDebugOutput ( const QString & ) ) ) ;
2018-06-22 18:34:25 +00:00
updateTasksIndicator ( ) ;
2018-07-18 10:15:10 +00:00
connect ( core - > getAsyncTaskManager ( ) , & AsyncTaskManager : : tasksChanged , this ,
& MainWindow : : updateTasksIndicator ) ;
2018-06-26 07:40:08 +00:00
2018-11-01 22:23:01 +00:00
/* Setup plugins interfaces */
2019-02-09 13:05:06 +00:00
for ( auto plugin : Plugins ( ) - > getPlugins ( ) ) {
2019-02-07 16:19:05 +00:00
plugin - > setupInterface ( this ) ;
2018-06-26 07:40:08 +00:00
}
2018-06-22 18:34:25 +00:00
}
2019-02-19 15:56:50 +00:00
void MainWindow : : toggleOverview ( bool visibility , GraphWidget * targetGraph )
{
if ( ! overviewDock ) {
return ;
}
targetGraphDock = targetGraph ;
2019-02-24 07:15:40 +00:00
enableOverviewMenu ( visibility ) ;
if ( visibility & & ! core - > isGraphEmpty ( ) ) {
2019-02-19 15:56:50 +00:00
connect ( targetGraphDock - > graphView , SIGNAL ( refreshBlock ( ) ) , this , SLOT ( adjustOverview ( ) ) ) ;
connect ( targetGraphDock - > graphView , SIGNAL ( viewZoomed ( ) ) , this , SLOT ( adjustOverview ( ) ) ) ;
2019-02-24 07:15:40 +00:00
connect ( targetGraphDock , & GraphWidget : : graphClose , [ this ] ( ) {
overviewDock - > hide ( ) ;
} ) ;
connect ( targetGraphDock , & GraphWidget : : graphEmpty , [ this ] ( ) {
overviewDock - > hide ( ) ;
} ) ;
2019-02-19 15:56:50 +00:00
connect ( overviewDock - > graphView , SIGNAL ( mouseMoved ( ) ) , this , SLOT ( adjustGraph ( ) ) ) ;
connect ( overviewDock , & QDockWidget : : dockLocationChanged , this , & MainWindow : : adjustOverview ) ;
connect ( overviewDock , SIGNAL ( resized ( ) ) , this , SLOT ( adjustOverview ( ) ) ) ;
overviewDock - > show ( ) ;
} else {
disconnect ( targetGraphDock - > graphView , SIGNAL ( refreshBlock ( ) ) , this , SLOT ( adjustOverview ( ) ) ) ;
disconnect ( targetGraphDock - > graphView , SIGNAL ( viewZoomed ( ) ) , this , SLOT ( adjustOverview ( ) ) ) ;
disconnect ( overviewDock - > graphView , SIGNAL ( mouseMoved ( ) ) , this , SLOT ( adjustGraph ( ) ) ) ;
disconnect ( overviewDock , & QDockWidget : : dockLocationChanged , this , & MainWindow : : adjustOverview ) ;
disconnect ( overviewDock , SIGNAL ( resized ( ) ) , this , SLOT ( adjustOverview ( ) ) ) ;
}
}
void MainWindow : : setOverviewData ( )
{
overviewDock - > graphView - > setData ( targetGraphDock - > graphView - > getWidth ( ) ,
targetGraphDock - > graphView - > getHeight ( ) , targetGraphDock - > graphView - > getBlocks ( ) ) ;
}
void MainWindow : : adjustOverview ( )
{
if ( ! overviewDock ) {
return ;
}
setOverviewData ( ) ;
qreal curScale = overviewDock - > graphView - > current_scale ;
qreal baseScale = targetGraphDock - > graphView - > current_scale ;
qreal w = targetGraphDock - > graphView - > viewport ( ) - > width ( ) * curScale / baseScale ;
qreal h = targetGraphDock - > graphView - > viewport ( ) - > height ( ) * curScale / baseScale ;
int graph_offset_x = targetGraphDock - > graphView - > offset_x ;
int graph_offset_y = targetGraphDock - > graphView - > offset_y ;
int overview_offset_x = overviewDock - > graphView - > offset_x ;
int overview_offset_y = overviewDock - > graphView - > offset_y ;
int rangeRectX = graph_offset_x * curScale - overview_offset_x * curScale ;
int rangeRectY = graph_offset_y * curScale - overview_offset_y * curScale ;
overviewDock - > graphView - > rangeRect = QRectF ( rangeRectX , rangeRectY , w , h ) ;
overviewDock - > graphView - > viewport ( ) - > update ( ) ;
}
void MainWindow : : adjustGraph ( )
{
if ( ! overviewDock ) {
return ;
}
qreal curScale = overviewDock - > graphView - > current_scale ;
int rectx = overviewDock - > graphView - > rangeRect . x ( ) ;
int recty = overviewDock - > graphView - > rangeRect . y ( ) ;
int overview_offset_x = overviewDock - > graphView - > offset_x ;
int overview_offset_y = overviewDock - > graphView - > offset_y ;
targetGraphDock - > graphView - > offset_x = rectx / curScale + overview_offset_x ;
targetGraphDock - > graphView - > offset_y = recty / curScale + overview_offset_y ;
targetGraphDock - > graphView - > viewport ( ) - > update ( ) ;
}
2018-06-22 18:34:25 +00:00
void MainWindow : : updateTasksIndicator ( )
{
2018-08-27 11:16:48 +00:00
bool running = core - > getAsyncTaskManager ( ) - > getTasksRunning ( ) ;
2018-06-24 19:12:02 +00:00
tasksProgressIndicator - > setProgressIndicatorVisible ( running ) ;
2017-05-13 18:09:36 +00:00
}
2018-05-25 14:30:59 +00:00
void MainWindow : : on_actionExtraGraph_triggered ( )
{
QDockWidget * extraDock = new GraphWidget ( this , 0 ) ;
addExtraWidget ( extraDock ) ;
}
void MainWindow : : on_actionExtraHexdump_triggered ( )
{
QDockWidget * extraDock = new HexdumpWidget ( this , 0 ) ;
addExtraWidget ( extraDock ) ;
}
void MainWindow : : on_actionExtraDisassembly_triggered ( )
{
QDockWidget * extraDock = new DisassemblyWidget ( this , 0 ) ;
addExtraWidget ( extraDock ) ;
}
void MainWindow : : addExtraWidget ( QDockWidget * extraDock )
{
addDockWidget ( Qt : : TopDockWidgetArea , extraDock ) ;
auto restoreExtraDock = qhelpers : : forceWidth ( extraDock - > widget ( ) , 600 ) ;
qApp - > processEvents ( ) ;
restoreExtraDock . restoreWidth ( extraDock - > widget ( ) ) ;
}
2019-02-07 16:19:05 +00:00
void MainWindow : : addPluginDockWidget ( QDockWidget * dockWidget , QAction * action )
{
addDockWidget ( Qt : : TopDockWidgetArea , dockWidget ) ;
addDockWidgetAction ( dockWidget , action ) ;
2019-02-21 11:08:02 +00:00
ui - > menuPlugins - > addAction ( action ) ;
2019-02-07 16:19:05 +00:00
tabifyDockWidget ( dashboardDock , dockWidget ) ;
updateDockActionChecked ( action ) ;
}
2019-02-11 19:05:53 +00:00
void MainWindow : : addMenuFileAction ( QAction * action )
{
ui - > menuFile - > addAction ( action ) ;
}
2018-08-18 16:04:45 +00:00
void MainWindow : : openNewFile ( InitialOptions options , bool skipOptionsDialog )
2017-05-13 18:09:36 +00:00
{
2018-08-18 16:04:45 +00:00
setFilename ( options . filename ) ;
2017-05-13 18:09:36 +00:00
2017-12-14 12:45:03 +00:00
/* Prompt to load filename.r2 script */
2018-08-18 16:04:45 +00:00
if ( options . script . isEmpty ( ) ) {
QString script = QString ( " %1.r2 " ) . arg ( this - > filename ) ;
if ( r_file_exists ( script . toStdString ( ) . data ( ) ) ) {
QMessageBox mb ;
mb . setWindowTitle ( tr ( " Script loading " ) ) ;
mb . setText ( tr ( " Do you want to load the '%1' script? " ) . arg ( script ) ) ;
mb . setStandardButtons ( QMessageBox : : Yes | QMessageBox : : No ) ;
if ( mb . exec ( ) = = QMessageBox : : Yes ) {
2018-08-25 11:23:31 +00:00
options . script = script ;
2018-08-18 16:04:45 +00:00
}
2017-12-14 12:45:03 +00:00
}
}
/* Show analysis options dialog */
2018-08-18 16:04:45 +00:00
displayInitialOptionsDialog ( options , skipOptionsDialog ) ;
2018-01-27 10:40:26 +00:00
}
2018-05-08 20:44:53 +00:00
void MainWindow : : openNewFileFailed ( )
{
displayNewFileDialog ( ) ;
QMessageBox mb ( this ) ;
mb . setIcon ( QMessageBox : : Critical ) ;
mb . setStandardButtons ( QMessageBox : : Ok ) ;
mb . setWindowTitle ( tr ( " Cannot open file! " ) ) ;
2018-07-18 10:15:10 +00:00
mb . setText (
tr ( " Could not open the file! Make sure the file exists and that you have the correct permissions. " ) ) ;
2018-05-08 20:44:53 +00:00
mb . exec ( ) ;
}
2019-01-19 20:54:02 +00:00
/*!
* \ brief displays the WelocmeDialog
*
* Upon first execution of Cutter , the WelcomeDialog would be showed to the user .
* The Welcome dialog would be showed after a reset of Cutter ' s preferences by the user .
*/
void MainWindow : : displayWelcomeDialog ( )
{
WelcomeDialog w ;
w . exec ( ) ;
}
2018-02-06 18:23:01 +00:00
void MainWindow : : displayNewFileDialog ( )
{
NewFileDialog * n = new NewFileDialog ( ) ;
2018-02-10 18:04:31 +00:00
newFileDialog = n ;
2018-02-06 18:23:01 +00:00
n - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
n - > show ( ) ;
}
2018-02-10 18:04:31 +00:00
void MainWindow : : closeNewFileDialog ( )
{
if ( newFileDialog ) {
newFileDialog - > close ( ) ;
}
newFileDialog = nullptr ;
}
2018-08-18 16:04:45 +00:00
void MainWindow : : displayInitialOptionsDialog ( const InitialOptions & options , bool skipOptionsDialog )
2018-01-27 10:40:26 +00:00
{
2018-08-18 16:04:45 +00:00
auto o = new InitialOptionsDialog ( this ) ;
2017-05-13 18:09:36 +00:00
o - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
2018-10-12 10:49:29 +00:00
o - > loadOptions ( options ) ;
2017-05-13 18:09:36 +00:00
2018-08-18 16:04:45 +00:00
if ( skipOptionsDialog ) {
o - > setupAndStartAnalysis ( ) ;
2018-10-12 10:49:29 +00:00
} else {
2018-10-11 13:04:57 +00:00
o - > show ( ) ;
}
2017-05-13 18:09:36 +00:00
}
void MainWindow : : openProject ( const QString & project_name )
{
QString filename = core - > cmd ( " Pi " + project_name ) ;
setFilename ( filename . trimmed ( ) ) ;
2017-10-21 19:20:10 +00:00
core - > openProject ( project_name ) ;
2017-05-13 18:09:36 +00:00
initUI ( ) ;
finalizeOpen ( ) ;
}
void MainWindow : : finalizeOpen ( )
{
core - > getOpcodes ( ) ;
2018-09-06 17:32:12 +00:00
core - > updateSeek ( ) ;
2018-08-27 11:16:48 +00:00
core - > message ( tr ( " > Populating UI " ) ) ;
2017-11-19 12:56:10 +00:00
refreshAll ( ) ;
2017-05-13 18:09:36 +00:00
2018-08-27 11:16:48 +00:00
core - > message ( tr ( " > Finished, happy reversing :) " ) ) ;
2017-05-13 18:09:36 +00:00
// Add fortune message
2018-08-27 11:16:48 +00:00
core - > message ( " \n " + core - > cmd ( " fo " ) ) ;
2017-05-13 18:09:36 +00:00
showMaximized ( ) ;
}
2017-10-21 19:20:10 +00:00
bool MainWindow : : saveProject ( bool quit )
2017-05-13 18:09:36 +00:00
{
2017-10-21 19:20:10 +00:00
QString projectName = core - > getConfig ( " prj.name " ) ;
2018-03-21 20:32:32 +00:00
if ( projectName . isEmpty ( ) ) {
2017-10-21 19:20:10 +00:00
return saveProjectAs ( quit ) ;
2018-03-21 20:32:32 +00:00
} else {
2017-10-21 19:20:10 +00:00
core - > saveProject ( projectName ) ;
return true ;
}
}
bool MainWindow : : saveProjectAs ( bool quit )
{
2017-11-03 17:22:54 +00:00
SaveProjectDialog dialog ( quit , this ) ;
2018-10-14 15:43:15 +00:00
return SaveProjectDialog : : Rejected ! = dialog . exec ( ) ;
2017-03-29 10:18:37 +00:00
}
2017-04-27 18:59:27 +00:00
void MainWindow : : refreshOmniBar ( const QStringList & flags )
{
omnibar - > refresh ( flags ) ;
}
2017-04-28 13:38:01 +00:00
void MainWindow : : setFilename ( const QString & fn )
2017-04-13 15:36:20 +00:00
{
2017-03-29 10:18:37 +00:00
// Add file name to window title
this - > filename = fn ;
2018-09-27 11:16:07 +00:00
this - > setWindowTitle ( APPNAME " – " + fn ) ;
2017-03-29 10:18:37 +00:00
}
void MainWindow : : closeEvent ( QCloseEvent * event )
{
2017-09-25 12:55:41 +00:00
QMessageBox : : StandardButton ret = QMessageBox : : question ( this , APPNAME ,
2019-02-07 10:52:08 +00:00
tr ( " Do you really want to exit? \n Save your project before closing! " ) ,
( QMessageBox : : StandardButtons ) ( QMessageBox : : Save | QMessageBox : : Discard | QMessageBox : : Cancel ) ) ;
2018-10-12 07:08:04 +00:00
if ( ret = = QMessageBox : : Cancel ) {
event - > ignore ( ) ;
return ;
}
if ( ret = = QMessageBox : : Save & & ! saveProject ( true ) ) {
2017-03-29 10:18:37 +00:00
event - > ignore ( ) ;
2018-10-12 07:08:04 +00:00
return ;
}
if ( ! core - > currentlyDebugging ) {
saveSettings ( ) ;
} else {
core - > stopDebug ( ) ;
2017-03-29 10:18:37 +00:00
}
2018-10-12 07:08:04 +00:00
QMainWindow : : closeEvent ( event ) ;
2017-03-29 10:18:37 +00:00
}
void MainWindow : : readSettings ( )
{
2017-04-03 00:18:09 +00:00
QSettings settings ;
2017-03-29 10:18:37 +00:00
QByteArray geo = settings . value ( " geometry " , QByteArray ( ) ) . toByteArray ( ) ;
restoreGeometry ( geo ) ;
QByteArray state = settings . value ( " state " , QByteArray ( ) ) . toByteArray ( ) ;
restoreState ( state ) ;
this - > responsive = settings . value ( " responsive " ) . toBool ( ) ;
2017-12-17 13:49:03 +00:00
panelLock = settings . value ( " panelLock " ) . toBool ( ) ;
setPanelLock ( ) ;
tabsOnTop = settings . value ( " tabsOnTop " ) . toBool ( ) ;
setTabLocation ( ) ;
2018-07-23 23:12:36 +00:00
QPoint pos = settings . value ( " pos " , QPoint ( 200 , 200 ) ) . toPoint ( ) ;
QSize size = settings . value ( " size " , QSize ( 400 , 400 ) ) . toSize ( ) ;
resize ( size ) ;
move ( pos ) ;
2017-12-21 15:47:36 +00:00
updateDockActionsChecked ( ) ;
2017-12-17 13:49:03 +00:00
}
void MainWindow : : saveSettings ( )
{
QSettings settings ;
settings . setValue ( " geometry " , saveGeometry ( ) ) ;
settings . setValue ( " size " , size ( ) ) ;
settings . setValue ( " pos " , pos ( ) ) ;
settings . setValue ( " state " , saveState ( ) ) ;
settings . setValue ( " panelLock " , panelLock ) ;
settings . setValue ( " tabsOnTop " , tabsOnTop ) ;
}
2018-07-23 23:12:36 +00:00
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 ( ) ) ;
}
2017-12-17 13:49:03 +00:00
void MainWindow : : setPanelLock ( )
{
2018-03-21 20:32:32 +00:00
if ( panelLock ) {
2018-05-04 07:58:32 +00:00
for ( QDockWidget * dockWidget : findChildren < QDockWidget * > ( ) ) {
2017-12-17 13:49:03 +00:00
dockWidget - > setFeatures ( QDockWidget : : NoDockWidgetFeatures ) ;
}
ui - > actionLock - > setChecked ( false ) ;
2018-03-21 20:32:32 +00:00
} else {
2018-05-04 07:58:32 +00:00
for ( QDockWidget * dockWidget : findChildren < QDockWidget * > ( ) ) {
2017-12-17 13:49:03 +00:00
dockWidget - > setFeatures ( QDockWidget : : AllDockWidgetFeatures ) ;
}
ui - > actionLock - > setChecked ( true ) ;
}
}
void MainWindow : : setTabLocation ( )
{
2018-03-21 20:32:32 +00:00
if ( tabsOnTop ) {
2017-12-17 13:49:03 +00:00
this - > setTabPosition ( Qt : : AllDockWidgetAreas , QTabWidget : : North ) ;
ui - > actionTabs_on_Top - > setChecked ( true ) ;
2018-03-21 20:32:32 +00:00
} else {
2017-12-17 13:49:03 +00:00
this - > setTabPosition ( Qt : : AllDockWidgetAreas , QTabWidget : : South ) ;
ui - > actionTabs_on_Top - > setChecked ( false ) ;
}
2017-03-29 10:18:37 +00:00
}
2017-11-19 12:56:10 +00:00
void MainWindow : : refreshAll ( )
2017-04-09 19:55:06 +00:00
{
2018-08-27 11:16:48 +00:00
core - > triggerRefreshAll ( ) ;
2017-03-29 10:18:37 +00:00
}
void MainWindow : : lockUnlock_Docks ( bool what )
{
2018-03-21 20:32:32 +00:00
if ( what ) {
2018-05-04 07:58:32 +00:00
for ( QDockWidget * dockWidget : findChildren < QDockWidget * > ( ) ) {
2017-03-29 10:18:37 +00:00
dockWidget - > setFeatures ( QDockWidget : : NoDockWidgetFeatures ) ;
}
2018-03-21 20:32:32 +00:00
} else {
2018-05-04 07:58:32 +00:00
for ( QDockWidget * dockWidget : findChildren < QDockWidget * > ( ) ) {
2017-03-29 10:18:37 +00:00
dockWidget - > setFeatures ( QDockWidget : : AllDockWidgetFeatures ) ;
}
}
}
void MainWindow : : restoreDocks ( )
{
2017-12-10 16:55:42 +00:00
// In the upper half the functions are the first widget
2019-01-13 17:55:02 +00:00
addDockWidget ( Qt : : TopDockWidgetArea , functionsDock ) ;
2019-01-24 17:13:04 +00:00
addDockWidget ( Qt : : TopDockWidgetArea , overviewDock ) ;
2017-10-13 13:53:23 +00:00
2018-12-24 15:25:55 +00:00
// Function | Dashboard
2019-01-24 17:13:04 +00:00
splitDockWidget ( overviewDock , dashboardDock , Qt : : Horizontal ) ;
splitDockWidget ( functionsDock , overviewDock , Qt : : Vertical ) ;
2017-11-03 17:22:54 +00:00
2017-12-10 16:55:42 +00:00
// In the lower half the console is the first widget
addDockWidget ( Qt : : BottomDockWidgetArea , consoleDock ) ;
// Console | Sections
2019-01-13 17:55:02 +00:00
splitDockWidget ( consoleDock , sectionsDock , Qt : : Horizontal ) ;
splitDockWidget ( consoleDock , segmentsDock , Qt : : Horizontal ) ;
2017-11-03 17:22:54 +00:00
2018-01-09 12:09:25 +00:00
// Tabs for center (must be applied after splitDockWidget())
2019-01-13 17:55:02 +00:00
tabifyDockWidget ( sectionsDock , commentsDock ) ;
tabifyDockWidget ( segmentsDock , commentsDock ) ;
2017-11-03 17:22:54 +00:00
tabifyDockWidget ( dashboardDock , disassemblyDock ) ;
tabifyDockWidget ( dashboardDock , graphDock ) ;
tabifyDockWidget ( dashboardDock , hexdumpDock ) ;
2019-01-13 17:55:02 +00:00
tabifyDockWidget ( dashboardDock , pseudocodeDock ) ;
tabifyDockWidget ( dashboardDock , entrypointDock ) ;
tabifyDockWidget ( dashboardDock , flagsDock ) ;
tabifyDockWidget ( dashboardDock , stringsDock ) ;
tabifyDockWidget ( dashboardDock , relocsDock ) ;
tabifyDockWidget ( dashboardDock , importsDock ) ;
tabifyDockWidget ( dashboardDock , exportsDock ) ;
tabifyDockWidget ( dashboardDock , typesDock ) ;
tabifyDockWidget ( dashboardDock , searchDock ) ;
tabifyDockWidget ( dashboardDock , headersDock ) ;
tabifyDockWidget ( dashboardDock , zignaturesDock ) ;
tabifyDockWidget ( dashboardDock , symbolsDock ) ;
tabifyDockWidget ( dashboardDock , classesDock ) ;
tabifyDockWidget ( dashboardDock , resourcesDock ) ;
tabifyDockWidget ( dashboardDock , vTablesDock ) ;
2019-02-13 06:38:47 +00:00
tabifyDockWidget ( dashboardDock , sdbDock ) ;
2018-06-06 11:05:20 +00:00
// Add Stack, Registers and Backtrace vertically stacked
2019-01-13 18:11:59 +00:00
addDockWidget ( Qt : : TopDockWidgetArea , stackDock ) ;
splitDockWidget ( stackDock , registersDock , Qt : : Vertical ) ;
tabifyDockWidget ( stackDock , backtraceDock ) ;
2018-07-19 14:35:46 +00:00
// MemoryMap/Breakpoint/RegRefs widget goes in the center tabs
2019-01-13 18:11:59 +00:00
tabifyDockWidget ( dashboardDock , memoryMapDock ) ;
tabifyDockWidget ( dashboardDock , breakpointDock ) ;
tabifyDockWidget ( dashboardDock , registerRefsDock ) ;
2018-03-02 13:15:53 +00:00
# ifdef CUTTER_ENABLE_JUPYTER
2019-01-13 17:55:02 +00:00
tabifyDockWidget ( dashboardDock , jupyterDock ) ;
2018-03-02 13:15:53 +00:00
# endif
2017-11-03 17:22:54 +00:00
2017-12-21 15:47:36 +00:00
updateDockActionsChecked ( ) ;
2017-03-29 10:18:37 +00:00
}
2017-11-03 17:22:54 +00:00
2017-03-29 10:18:37 +00:00
void MainWindow : : hideAllDocks ( )
{
2018-03-21 20:32:32 +00:00
for ( auto w : dockWidgets ) {
2018-01-09 12:09:25 +00:00
removeDockWidget ( w ) ;
2017-04-13 15:36:20 +00:00
}
2017-12-21 15:47:36 +00:00
updateDockActionsChecked ( ) ;
}
void MainWindow : : updateDockActionsChecked ( )
{
2018-03-21 20:32:32 +00:00
for ( auto i = dockWidgetActions . constBegin ( ) ; i ! = dockWidgetActions . constEnd ( ) ; i + + ) {
2017-12-21 15:47:36 +00:00
i . key ( ) - > setChecked ( ! i . value ( ) - > isHidden ( ) ) ;
}
2017-03-29 10:18:37 +00:00
}
2018-10-25 21:22:34 +00:00
void MainWindow : : updateDockActionChecked ( QAction * action )
2018-10-16 06:25:09 +00:00
{
action - > setChecked ( ! dockWidgetActions [ action ] - > isHidden ( ) ) ;
}
2018-05-25 14:30:59 +00:00
void MainWindow : : showZenDocks ( )
{
const QList < QDockWidget * > zenDocks = { functionsDock ,
2018-09-30 20:00:44 +00:00
dashboardDock ,
2018-05-25 14:30:59 +00:00
stringsDock ,
graphDock ,
disassemblyDock ,
hexdumpDock ,
2018-09-30 20:00:44 +00:00
searchDock ,
importsDock ,
# ifdef CUTTER_ENABLE_JUPYTER
jupyterDock
# endif
2018-07-18 10:15:10 +00:00
} ;
2018-05-25 14:30:59 +00:00
for ( auto w : dockWidgets ) {
if ( zenDocks . contains ( w ) ) {
w - > show ( ) ;
}
}
updateDockActionsChecked ( ) ;
}
2018-06-12 15:42:38 +00:00
void MainWindow : : showDebugDocks ( )
{
const QList < QDockWidget * > debugDocks = { functionsDock ,
2018-07-18 10:15:10 +00:00
stringsDock ,
graphDock ,
disassemblyDock ,
hexdumpDock ,
searchDock ,
stackDock ,
registersDock ,
backtraceDock ,
memoryMapDock ,
breakpointDock
2018-06-12 15:42:38 +00:00
} ;
for ( auto w : dockWidgets ) {
if ( debugDocks . contains ( w ) ) {
w - > show ( ) ;
}
}
updateDockActionsChecked ( ) ;
}
2018-10-22 18:06:30 +00:00
void MainWindow : : enableDebugWidgetsMenu ( bool enable )
{
ui - > menuAddDebugWidgets - > setEnabled ( enable ) ;
}
2019-02-24 07:15:40 +00:00
void MainWindow : : enableOverviewMenu ( bool enable )
{
ui - > actionOverview - > setEnabled ( enable ) ;
ui - > actionOverview - > setChecked ( enable ) ;
}
2017-11-03 17:22:54 +00:00
void MainWindow : : resetToDefaultLayout ( )
2018-05-25 14:30:59 +00:00
{
hideAllDocks ( ) ;
restoreDocks ( ) ;
showZenDocks ( ) ;
2018-09-30 20:00:44 +00:00
dashboardDock - > raise ( ) ;
2018-05-25 14:30:59 +00:00
2018-09-30 20:00:44 +00:00
// Ugly workaround to set the default widths of functions docks
2018-05-25 14:30:59 +00:00
// if anyone finds a way to do this cleaner that also works, feel free to change it!
auto restoreFunctionDock = qhelpers : : forceWidth ( functionsDock - > widget ( ) , 200 ) ;
2019-01-24 17:13:04 +00:00
auto restoreOverviewDock = qhelpers : : forceWidth ( overviewDock - > widget ( ) , 200 ) ;
2018-05-25 14:30:59 +00:00
qApp - > processEvents ( ) ;
restoreFunctionDock . restoreWidth ( functionsDock - > widget ( ) ) ;
2019-01-24 17:13:04 +00:00
restoreOverviewDock . restoreWidth ( overviewDock - > widget ( ) ) ;
2018-05-25 14:30:59 +00:00
2018-08-27 11:16:48 +00:00
core - > setMemoryWidgetPriority ( CutterCore : : MemoryWidgetType : : Disassembly ) ;
2018-05-25 14:30:59 +00:00
}
2018-06-12 15:42:38 +00:00
void MainWindow : : resetToDebugLayout ( )
2019-01-14 08:17:10 +00:00
{
CutterCore : : MemoryWidgetType memType = core - > getMemoryWidgetPriority ( ) ;
hideAllDocks ( ) ;
restoreDocks ( ) ;
showDebugDocks ( ) ;
core - > raisePrioritizedMemoryWidget ( memType ) ;
auto restoreStackDock = qhelpers : : forceWidth ( stackDock - > widget ( ) , 400 ) ;
qApp - > processEvents ( ) ;
restoreStackDock . restoreWidth ( stackDock - > widget ( ) ) ;
}
void MainWindow : : restoreDebugLayout ( )
2018-06-12 15:42:38 +00:00
{
2018-08-27 11:16:48 +00:00
CutterCore : : MemoryWidgetType memType = core - > getMemoryWidgetPriority ( ) ;
2018-07-24 23:12:15 +00:00
bool isMaxim = isMaximized ( ) ;
2018-06-12 15:42:38 +00:00
hideAllDocks ( ) ;
restoreDocks ( ) ;
showDebugDocks ( ) ;
2018-07-23 23:12:36 +00:00
readDebugSettings ( ) ;
2018-08-27 11:16:48 +00:00
core - > raisePrioritizedMemoryWidget ( memType ) ;
2018-07-24 23:12:15 +00:00
if ( isMaxim ) {
showMaximized ( ) ;
} else {
showNormal ( ) ;
}
2018-06-12 15:42:38 +00:00
}
2018-01-16 14:09:51 +00:00
void MainWindow : : on_actionLock_triggered ( )
{
panelLock = ! panelLock ;
setPanelLock ( ) ;
}
void MainWindow : : on_actionLockUnlock_triggered ( )
{
2018-03-21 20:32:32 +00:00
if ( ui - > actionLockUnlock - > isChecked ( ) ) {
2018-05-04 07:58:32 +00:00
for ( QDockWidget * dockWidget : findChildren < QDockWidget * > ( ) ) {
2018-01-16 14:09:51 +00:00
dockWidget - > setFeatures ( QDockWidget : : NoDockWidgetFeatures ) ;
}
ui - > actionLockUnlock - > setIcon ( QIcon ( " :/lock " ) ) ;
2018-03-21 20:32:32 +00:00
} else {
2018-05-04 07:58:32 +00:00
for ( QDockWidget * dockWidget : findChildren < QDockWidget * > ( ) ) {
2018-01-16 14:09:51 +00:00
dockWidget - > setFeatures ( QDockWidget : : AllDockWidgetFeatures ) ;
}
ui - > actionLockUnlock - > setIcon ( QIcon ( " :/unlock " ) ) ;
}
2017-03-29 10:18:37 +00:00
}
void MainWindow : : on_actionFunctionsRename_triggered ( )
{
2017-04-09 19:55:06 +00:00
RenameDialog * r = new RenameDialog ( this ) ;
2017-03-29 10:18:37 +00:00
// Get function based on click position
//r->setFunctionName(fcn_name);
r - > open ( ) ;
}
2018-01-16 14:09:51 +00:00
void MainWindow : : on_actionDefault_triggered ( )
2017-03-29 10:18:37 +00:00
{
2019-01-14 08:17:10 +00:00
if ( core - > currentlyDebugging ) {
resetToDebugLayout ( ) ;
} else {
resetToDefaultLayout ( ) ;
}
2017-03-29 10:18:37 +00:00
}
2019-01-14 08:17:10 +00:00
2018-06-20 09:24:28 +00:00
/**
* @ brief MainWindow : : on_actionNew_triggered
* Open a new Cutter session .
*/
2017-03-29 10:18:37 +00:00
void MainWindow : : on_actionNew_triggered ( )
{
2018-06-20 09:24:28 +00:00
// Create a new Cutter process
QProcess process ( this ) ;
process . setEnvironment ( QProcess : : systemEnvironment ( ) ) ;
process . startDetached ( qApp - > applicationFilePath ( ) ) ;
2017-03-29 10:18:37 +00:00
}
void MainWindow : : on_actionSave_triggered ( )
{
2017-05-13 18:09:36 +00:00
saveProject ( ) ;
2017-03-29 10:18:37 +00:00
}
2017-10-21 19:20:10 +00:00
void MainWindow : : on_actionSaveAs_triggered ( )
{
2017-11-03 17:22:54 +00:00
saveProjectAs ( ) ;
2017-10-21 19:20:10 +00:00
}
2017-03-29 10:18:37 +00:00
void MainWindow : : on_actionRun_Script_triggered ( )
{
QFileDialog dialog ( this ) ;
dialog . setFileMode ( QFileDialog : : ExistingFile ) ;
dialog . setViewMode ( QFileDialog : : Detail ) ;
dialog . setDirectory ( QDir : : home ( ) ) ;
2019-02-07 10:52:08 +00:00
const QString & fileName = QDir : : toNativeSeparators ( dialog . getOpenFileName ( this ,
tr ( " Select radare2 script " ) ) ) ;
2018-11-02 06:48:17 +00:00
if ( fileName . isEmpty ( ) ) // Cancel was pressed
2017-04-09 20:36:17 +00:00
return ;
2019-01-28 13:37:20 +00:00
RunScriptTask * runScriptTask = new RunScriptTask ( ) ;
runScriptTask - > setFileName ( fileName ) ;
AsyncTask : : Ptr runScriptTaskPtr ( runScriptTask ) ;
AsyncTaskDialog * taskDialog = new AsyncTaskDialog ( runScriptTaskPtr , this ) ;
taskDialog - > setInterruptOnClose ( true ) ;
taskDialog - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
taskDialog - > show ( ) ;
Core ( ) - > getAsyncTaskManager ( ) - > start ( runScriptTaskPtr ) ;
2017-03-29 10:18:37 +00:00
}
2018-06-20 09:24:28 +00:00
/**
* @ brief MainWindow : : on_actionOpen_triggered
* Open a file as in " load (add) a file in current session " .
*/
2018-01-16 14:09:51 +00:00
void MainWindow : : on_actionOpen_triggered ( )
2017-03-29 10:18:37 +00:00
{
2018-06-20 09:24:28 +00:00
OpenFileDialog dialog ( this ) ;
dialog . exec ( ) ;
2017-03-29 10:18:37 +00:00
}
2017-04-09 19:55:06 +00:00
void MainWindow : : toggleResponsive ( bool maybe )
{
2017-03-29 10:18:37 +00:00
this - > responsive = maybe ;
// Save options in settings
2017-04-03 00:18:09 +00:00
QSettings settings ;
2017-03-29 10:18:37 +00:00
settings . setValue ( " responsive " , this - > responsive ) ;
}
void MainWindow : : on_actionTabs_on_Top_triggered ( )
{
this - > on_actionTabs_triggered ( ) ;
}
void MainWindow : : on_actionReset_settings_triggered ( )
{
2017-05-19 07:45:26 +00:00
QMessageBox : : StandardButton ret =
2017-09-25 12:55:41 +00:00
( QMessageBox : : StandardButton ) QMessageBox : : question ( this , APPNAME ,
2019-02-07 10:52:08 +00:00
tr ( " Do you really want to clear all settings? " ) ,
QMessageBox : : Ok | QMessageBox : : Cancel ) ;
2018-03-21 20:32:32 +00:00
if ( ret = = QMessageBox : : Ok ) {
2017-12-03 12:10:09 +00:00
Config ( ) - > resetAll ( ) ;
2017-03-29 10:18:37 +00:00
}
}
2017-03-31 21:54:06 +00:00
void MainWindow : : on_actionQuit_triggered ( )
{
close ( ) ;
}
2017-04-12 21:04:39 +00:00
2018-03-08 09:11:19 +00:00
void MainWindow : : on_actionBackward_triggered ( )
{
2018-08-27 11:16:48 +00:00
core - > seekPrev ( ) ;
2018-03-08 09:11:19 +00:00
}
2018-01-16 14:09:51 +00:00
void MainWindow : : on_actionForward_triggered ( )
{
2018-08-27 11:16:48 +00:00
core - > seekNext ( ) ;
2018-03-08 09:11:19 +00:00
}
void MainWindow : : on_actionUndoSeek_triggered ( )
{
2018-08-27 11:16:48 +00:00
core - > seekPrev ( ) ;
2018-03-08 09:11:19 +00:00
}
void MainWindow : : on_actionRedoSeek_triggered ( )
{
2018-08-27 11:16:48 +00:00
core - > seekNext ( ) ;
2018-01-16 14:09:51 +00:00
}
void MainWindow : : on_actionDisasAdd_comment_triggered ( )
{
CommentsDialog * c = new CommentsDialog ( this ) ;
c - > exec ( ) ;
delete c ;
}
2017-05-26 08:52:17 +00:00
void MainWindow : : on_actionRefresh_contents_triggered ( )
{
2017-11-19 12:56:10 +00:00
refreshAll ( ) ;
2017-05-26 08:52:17 +00:00
}
2017-08-31 17:43:46 +00:00
2017-12-14 13:42:24 +00:00
void MainWindow : : on_actionPreferences_triggered ( )
2017-08-31 17:43:46 +00:00
{
2017-12-14 13:42:24 +00:00
auto dialog = new PreferencesDialog ( this ) ;
2017-10-01 14:36:40 +00:00
dialog - > show ( ) ;
2017-09-02 08:17:48 +00:00
}
2017-10-21 19:20:10 +00:00
2018-01-16 14:09:51 +00:00
void MainWindow : : on_actionTabs_triggered ( )
{
tabsOnTop = ! tabsOnTop ;
setTabLocation ( ) ;
}
void MainWindow : : on_actionAbout_triggered ( )
{
AboutDialog * a = new AboutDialog ( this ) ;
2019-02-06 14:30:29 +00:00
a - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
2018-01-16 14:09:51 +00:00
a - > open ( ) ;
}
2019-02-07 10:52:08 +00:00
void MainWindow : : on_actionIssue_triggered ( )
{
QString url , osInfo , format , arch , type ;
//Pull in info needed for git issue
osInfo = QString ( QSysInfo : : productType ( ) ) + " " + QString ( QSysInfo : : productVersion ( ) ) ;
QJsonDocument docu = Core ( ) - > getFileInfo ( ) ;
QJsonObject coreObj = docu . object ( ) [ " core " ] . toObject ( ) ;
QJsonObject binObj = docu . object ( ) [ " bin " ] . toObject ( ) ;
if ( ! binObj . QJsonObject : : isEmpty ( ) ) {
format = coreObj [ " format " ] . toString ( ) ;
arch = binObj [ " arch " ] . toString ( ) ;
if ( ! binObj [ " type " ] . isUndefined ( ) ) {
type = coreObj [ " type " ] . toString ( ) ;
} else {
type = " N/A " ;
}
} else {
format = coreObj [ " format " ] . toString ( ) ;
arch = " N/A " ;
type = " N/A " ;
}
url =
" https://github.com/radareorg/cutter/issues/new?&body=**Environment information** \n * Operating System: "
+ osInfo + " \n * Cutter version: " + CUTTER_VERSION_FULL +
" \n * File format: " + format + " \n * Arch: " + arch + " \n * Type: " + type +
" \n \n **Describe the bug** \n A clear and concise description of what the bug is. \n \n **To Reproduce** \n Steps to reproduce the behavior: \n 1. Go to '...' \n 2. Click on '....' \n 3. Scroll down to '....' \n 4. See error \n \n **Expected behavior** \n A clear and concise description of what you expected to happen. \n \n **Screenshots** \n If applicable, add screenshots to help explain your problem. \n \n **Additional context** \n Add any other context about the problem here. " ;
QDesktopServices : : openUrl ( QUrl ( url , QUrl : : TolerantMode ) ) ;
}
2018-01-16 14:09:51 +00:00
void MainWindow : : on_actionRefresh_Panels_triggered ( )
{
this - > refreshAll ( ) ;
}
2018-01-27 10:40:26 +00:00
void MainWindow : : on_actionAnalyze_triggered ( )
{
2018-08-18 16:04:45 +00:00
// TODO: implement this, but do NOT open InitialOptionsDialog!!
2018-01-27 10:40:26 +00:00
}
2018-01-16 14:09:51 +00:00
void MainWindow : : on_actionImportPDB_triggered ( )
{
QFileDialog dialog ( this ) ;
dialog . setWindowTitle ( tr ( " Select PDB file " ) ) ;
dialog . setNameFilters ( { tr ( " PDB file (*.pdb) " ) , tr ( " All files (*) " ) } ) ;
2018-03-21 20:32:32 +00:00
if ( ! dialog . exec ( ) ) {
2018-01-16 14:09:51 +00:00
return ;
}
2018-11-02 06:48:17 +00:00
const QString & pdbFile = QDir : : toNativeSeparators ( dialog . selectedFiles ( ) . first ( ) ) ;
2018-01-16 14:09:51 +00:00
2018-03-21 20:32:32 +00:00
if ( ! pdbFile . isEmpty ( ) ) {
2018-08-27 11:16:48 +00:00
core - > loadPDB ( pdbFile ) ;
core - > message ( tr ( " %1 loaded. " ) . arg ( pdbFile ) ) ;
2018-11-17 10:10:44 +00:00
this - > refreshAll ( ) ;
2018-01-16 14:09:51 +00:00
}
}
2018-08-24 22:36:15 +00:00
void MainWindow : : on_actionExport_as_code_triggered ( )
{
QStringList filters ;
QMap < QString , QString > cmdMap ;
filters < < tr ( " C uin8_t array (*.c) " ) ;
cmdMap [ filters . last ( ) ] = " pc " ;
filters < < tr ( " C uin16_t array (*.c) " ) ;
cmdMap [ filters . last ( ) ] = " pch " ;
filters < < tr ( " C uin32_t array (*.c) " ) ;
cmdMap [ filters . last ( ) ] = " pcw " ;
filters < < tr ( " C uin64_t array (*.c) " ) ;
cmdMap [ filters . last ( ) ] = " pcd " ;
filters < < tr ( " C string (*.c) " ) ;
cmdMap [ filters . last ( ) ] = " pcs " ;
filters < < tr ( " Shell-script that reconstructs the bin (*.sh) " ) ;
cmdMap [ filters . last ( ) ] = " pcS " ;
filters < < tr ( " JSON array (*.json) " ) ;
cmdMap [ filters . last ( ) ] = " pcj " ;
filters < < tr ( " JavaScript array (*.js) " ) ;
cmdMap [ filters . last ( ) ] = " pcJ " ;
filters < < tr ( " Python array (*.py) " ) ;
cmdMap [ filters . last ( ) ] = " pcp " ;
filters < < tr ( " Print 'wx' r2 commands (*.r2) " ) ;
cmdMap [ filters . last ( ) ] = " pc* " ;
2018-10-25 21:22:34 +00:00
filters < < tr ( " GAS .byte blob (*.asm, *.s) " ) ;
2018-08-24 22:36:15 +00:00
cmdMap [ filters . last ( ) ] = " pca " ;
filters < < tr ( " .bytes with instructions in comments (*.txt) " ) ;
cmdMap [ filters . last ( ) ] = " pcA " ;
QFileDialog dialog ( this , tr ( " Export as code " ) ) ;
dialog . setAcceptMode ( QFileDialog : : AcceptSave ) ;
dialog . setFileMode ( QFileDialog : : AnyFile ) ;
dialog . setNameFilters ( filters ) ;
dialog . selectFile ( " dump " ) ;
dialog . setDefaultSuffix ( " c " ) ;
if ( ! dialog . exec ( ) )
return ;
QFile file ( dialog . selectedFiles ( ) [ 0 ] ) ;
if ( ! file . open ( QIODevice : : WriteOnly | QIODevice : : Text ) ) {
qWarning ( ) < < " Can't open file " ;
return ;
}
TempConfig tempConfig ;
tempConfig . set ( " io.va " , false ) ;
QTextStream fileOut ( & file ) ;
QString & cmd = cmdMap [ dialog . selectedNameFilter ( ) ] ;
fileOut < < Core ( ) - > cmd ( cmd + " $s @ 0 " ) ;
}
2018-11-02 06:48:17 +00:00
void MainWindow : : projectSaved ( bool successfully , const QString & name )
2017-10-21 19:20:10 +00:00
{
2018-11-02 06:48:17 +00:00
if ( successfully )
core - > message ( tr ( " Project saved: %1 " ) . arg ( name ) ) ;
else
core - > message ( tr ( " Failed to save project: %1 " ) . arg ( name ) ) ;
2017-10-21 19:20:10 +00:00
}
2018-03-16 21:46:57 +00:00
2018-06-12 15:42:38 +00:00
void MainWindow : : changeDebugView ( )
{
saveSettings ( ) ;
2019-01-14 08:17:10 +00:00
restoreDebugLayout ( ) ;
2018-10-22 18:06:30 +00:00
enableDebugWidgetsMenu ( true ) ;
2018-06-12 15:42:38 +00:00
}
void MainWindow : : changeDefinedView ( )
{
2018-07-23 23:12:36 +00:00
saveDebugSettings ( ) ;
2018-08-27 11:16:48 +00:00
CutterCore : : MemoryWidgetType memType = core - > getMemoryWidgetPriority ( ) ;
2018-07-23 23:12:36 +00:00
hideAllDocks ( ) ;
restoreDocks ( ) ;
2018-06-12 15:42:38 +00:00
readSettings ( ) ;
2018-10-22 18:06:30 +00:00
enableDebugWidgetsMenu ( false ) ;
2018-08-27 11:16:48 +00:00
core - > raisePrioritizedMemoryWidget ( memType ) ;
2018-06-12 15:42:38 +00:00
}
2018-05-13 07:50:01 +00:00
void MainWindow : : mousePressEvent ( QMouseEvent * event )
{
switch ( event - > button ( ) ) {
case Qt : : BackButton :
2018-08-27 11:16:48 +00:00
core - > seekPrev ( ) ;
2018-05-13 07:50:01 +00:00
break ;
case Qt : : ForwardButton :
2018-08-27 11:16:48 +00:00
core - > seekNext ( ) ;
2018-05-13 07:50:01 +00:00
break ;
default :
break ;
}
}
bool MainWindow : : eventFilter ( QObject * , QEvent * event )
{
if ( event - > type ( ) = = QEvent : : MouseButtonPress ) {
2018-07-18 10:15:10 +00:00
QMouseEvent * mouseEvent = static_cast < QMouseEvent * > ( event ) ;
2018-05-13 07:50:01 +00:00
if ( mouseEvent - > button ( ) = = Qt : : ForwardButton | | mouseEvent - > button ( ) = = Qt : : BackButton ) {
mousePressEvent ( mouseEvent ) ;
return true ;
}
}
return false ;
}
2018-03-21 20:32:32 +00:00
void MainWindow : : addToDockWidgetList ( QDockWidget * dockWidget )
{
2018-03-16 21:46:57 +00:00
this - > dockWidgets . push_back ( dockWidget ) ;
}
2018-03-21 20:32:32 +00:00
void MainWindow : : addDockWidgetAction ( QDockWidget * dockWidget , QAction * action )
{
2018-03-16 21:46:57 +00:00
this - > dockWidgetActions [ action ] = dockWidget ;
}
2019-02-11 19:05:53 +00:00
/*!
* \ brief Show a warning message box .
*
* This API can either be used in Cutter internals , or by Python plugins .
*/
void MainWindow : : messageBoxWarning ( QString title , QString message )
{
QMessageBox mb ( this ) ;
mb . setIcon ( QMessageBox : : Warning ) ;
mb . setStandardButtons ( QMessageBox : : Ok ) ;
mb . setWindowTitle ( title ) ;
mb . setText ( message ) ;
mb . exec ( ) ;
}