WIP First PoC to draw only visible after seek

This commit is contained in:
xarkes 2019-01-12 18:02:51 +01:00
parent 7f80f96c55
commit f4c720cffa
14 changed files with 134 additions and 72 deletions

View File

@ -177,44 +177,44 @@ void MainWindow::initUI()
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 // Add graph view as dockable
graphDock = new GraphWidget(this, ui->actionGraph); graphDock = new GraphWidget(this, ui->actionGraph);
sectionsDock = new SectionsWidget(this, ui->actionSections); //sectionsDock = new SectionsWidget(this, ui->actionSections);
segmentsDock = new SegmentsWidget(this, ui->actionSegments); //segmentsDock = new SegmentsWidget(this, ui->actionSegments);
entrypointDock = new EntrypointWidget(this, ui->actionEntrypoints); //entrypointDock = new EntrypointWidget(this, ui->actionEntrypoints);
functionsDock = new FunctionsWidget(this, ui->actionFunctions); functionsDock = new FunctionsWidget(this, ui->actionFunctions);
importsDock = new ImportsWidget(this, ui->actionImports); //importsDock = new ImportsWidget(this, ui->actionImports);
exportsDock = new ExportsWidget(this, ui->actionExports); //exportsDock = new ExportsWidget(this, ui->actionExports);
headersDock = new HeadersWidget(this, ui->actionHeaders); //headersDock = new HeadersWidget(this, ui->actionHeaders);
zignaturesDock = new ZignaturesWidget(this, ui->actionZignatures); //zignaturesDock = new ZignaturesWidget(this, ui->actionZignatures);
typesDock = new TypesWidget(this, ui->actionTypes); //typesDock = new TypesWidget(this, ui->actionTypes);
searchDock = new SearchWidget(this, ui->actionSearch); //searchDock = new SearchWidget(this, ui->actionSearch);
symbolsDock = new SymbolsWidget(this, ui->actionSymbols); //symbolsDock = new SymbolsWidget(this, ui->actionSymbols);
relocsDock = new RelocsWidget(this, ui->actionRelocs); //relocsDock = new RelocsWidget(this, ui->actionRelocs);
commentsDock = new CommentsWidget(this, ui->actionComments); //commentsDock = new CommentsWidget(this, ui->actionComments);
stringsDock = new StringsWidget(this, ui->actionStrings); //stringsDock = new StringsWidget(this, ui->actionStrings);
flagsDock = new FlagsWidget(this, ui->actionFlags); //flagsDock = new FlagsWidget(this, ui->actionFlags);
stackDock = new StackWidget(this, ui->actionStack); //stackDock = new StackWidget(this, ui->actionStack);
backtraceDock = new BacktraceWidget(this, ui->actionBacktrace); //backtraceDock = new BacktraceWidget(this, ui->actionBacktrace);
registersDock = new RegistersWidget(this, ui->actionRegisters); //registersDock = new RegistersWidget(this, ui->actionRegisters);
memoryMapDock = new MemoryMapWidget(this, ui->actionMemoryMap); //memoryMapDock = new MemoryMapWidget(this, ui->actionMemoryMap);
breakpointDock = new BreakpointWidget(this, ui->actionBreakpoint); //breakpointDock = new BreakpointWidget(this, ui->actionBreakpoint);
registerRefsDock = new RegisterRefsWidget(this, ui->actionRegisterRefs); //registerRefsDock = new RegisterRefsWidget(this, ui->actionRegisterRefs);
#ifdef CUTTER_ENABLE_JUPYTER #ifdef CUTTER_ENABLE_JUPYTER
jupyterDock = new JupyterWidget(this, ui->actionJupyter); //jupyterDock = new JupyterWidget(this, ui->actionJupyter);
#else #else
ui->actionJupyter->setEnabled(false); ui->actionJupyter->setEnabled(false);
ui->actionJupyter->setVisible(false); ui->actionJupyter->setVisible(false);
#endif #endif
dashboardDock = new Dashboard(this, ui->actionDashboard); dashboardDock = new Dashboard(this, ui->actionDashboard);
sdbDock = new SdbDock(this, ui->actionSDBBrowser); //sdbDock = new SdbDock(this, ui->actionSDBBrowser);
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);
// Set up dock widgets default layout // Set up dock widgets default layout
@ -543,7 +543,7 @@ void MainWindow::lockUnlock_Docks(bool what)
void MainWindow::restoreDocks() void MainWindow::restoreDocks()
{ {
// In the upper half the functions are the first widget // In the upper half the functions are the first widget
addDockWidget(Qt::TopDockWidgetArea, functionsDock); //addDockWidget(Qt::TopDockWidgetArea, functionsDock);
// Function | Dashboard // Function | Dashboard
splitDockWidget(functionsDock, dashboardDock, Qt::Horizontal); splitDockWidget(functionsDock, dashboardDock, Qt::Horizontal);
@ -552,41 +552,41 @@ void MainWindow::restoreDocks()
addDockWidget(Qt::BottomDockWidgetArea, consoleDock); addDockWidget(Qt::BottomDockWidgetArea, consoleDock);
// Console | Sections // Console | Sections
splitDockWidget(consoleDock, sectionsDock, Qt::Horizontal); //splitDockWidget(consoleDock, sectionsDock, Qt::Horizontal);
splitDockWidget(consoleDock, segmentsDock, Qt::Horizontal); //splitDockWidget(consoleDock, segmentsDock, Qt::Horizontal);
// Tabs for center (must be applied after splitDockWidget()) // Tabs for center (must be applied after splitDockWidget())
tabifyDockWidget(sectionsDock, commentsDock); //tabifyDockWidget(sectionsDock, commentsDock);
tabifyDockWidget(segmentsDock, commentsDock); //tabifyDockWidget(segmentsDock, commentsDock);
tabifyDockWidget(dashboardDock, disassemblyDock); tabifyDockWidget(dashboardDock, disassemblyDock);
tabifyDockWidget(dashboardDock, graphDock); tabifyDockWidget(dashboardDock, graphDock);
tabifyDockWidget(dashboardDock, hexdumpDock); tabifyDockWidget(dashboardDock, hexdumpDock);
tabifyDockWidget(dashboardDock, pseudocodeDock); //tabifyDockWidget(dashboardDock, pseudocodeDock);
tabifyDockWidget(dashboardDock, entrypointDock); //tabifyDockWidget(dashboardDock, entrypointDock);
tabifyDockWidget(dashboardDock, flagsDock); //tabifyDockWidget(dashboardDock, flagsDock);
tabifyDockWidget(dashboardDock, stringsDock); //tabifyDockWidget(dashboardDock, stringsDock);
tabifyDockWidget(dashboardDock, relocsDock); //tabifyDockWidget(dashboardDock, relocsDock);
tabifyDockWidget(dashboardDock, importsDock); //tabifyDockWidget(dashboardDock, importsDock);
tabifyDockWidget(dashboardDock, exportsDock); //tabifyDockWidget(dashboardDock, exportsDock);
tabifyDockWidget(dashboardDock, typesDock); //tabifyDockWidget(dashboardDock, typesDock);
tabifyDockWidget(dashboardDock, searchDock); //tabifyDockWidget(dashboardDock, searchDock);
tabifyDockWidget(dashboardDock, headersDock); //tabifyDockWidget(dashboardDock, headersDock);
tabifyDockWidget(dashboardDock, zignaturesDock); //tabifyDockWidget(dashboardDock, zignaturesDock);
tabifyDockWidget(dashboardDock, symbolsDock); //tabifyDockWidget(dashboardDock, symbolsDock);
tabifyDockWidget(dashboardDock, classesDock); //tabifyDockWidget(dashboardDock, classesDock);
tabifyDockWidget(dashboardDock, resourcesDock); //tabifyDockWidget(dashboardDock, resourcesDock);
tabifyDockWidget(dashboardDock, vTablesDock); //tabifyDockWidget(dashboardDock, vTablesDock);
// Add Stack, Registers and Backtrace vertically stacked // Add Stack, Registers and Backtrace vertically stacked
addDockWidget(Qt::TopDockWidgetArea, stackDock); //addDockWidget(Qt::TopDockWidgetArea, stackDock);
splitDockWidget(stackDock, registersDock, Qt::Vertical); //splitDockWidget(stackDock, registersDock, Qt::Vertical);
tabifyDockWidget(stackDock, backtraceDock); //tabifyDockWidget(stackDock, backtraceDock);
// MemoryMap/Breakpoint/RegRefs widget goes in the center tabs // MemoryMap/Breakpoint/RegRefs widget goes in the center tabs
tabifyDockWidget(dashboardDock, memoryMapDock); //tabifyDockWidget(dashboardDock, memoryMapDock);
tabifyDockWidget(dashboardDock, breakpointDock); //tabifyDockWidget(dashboardDock, breakpointDock);
tabifyDockWidget(dashboardDock, registerRefsDock); //tabifyDockWidget(dashboardDock, registerRefsDock);
#ifdef CUTTER_ENABLE_JUPYTER #ifdef CUTTER_ENABLE_JUPYTER
tabifyDockWidget(dashboardDock, jupyterDock); //tabifyDockWidget(dashboardDock, jupyterDock);
#endif #endif
updateDockActionsChecked(); updateDockActionsChecked();

View File

@ -57,6 +57,8 @@ private:
void removeLastLine(); void removeLastLine();
void executeCommand(const QString &command); void executeCommand(const QString &command);
void refreshContent() override { }
QSharedPointer<CommandTask> commandTask; QSharedPointer<CommandTask> commandTask;
std::unique_ptr<Ui::ConsoleWidget> ui; std::unique_ptr<Ui::ConsoleWidget> ui;

View File

@ -11,8 +11,21 @@ CutterDockWidget::CutterDockWidget(MainWindow *main, QAction *action) :
main->addDockWidgetAction(this, action); main->addDockWidgetAction(this, action);
connect(action, &QAction::triggered, this, &CutterDockWidget::toggleDockWidget); connect(action, &QAction::triggered, this, &CutterDockWidget::toggleDockWidget);
} }
// Install event filter to catch redraw widgets when needed
installEventFilter(this);
} }
CutterDockWidget::~CutterDockWidget() {}
bool CutterDockWidget::eventFilter(QObject *object, QEvent *event)
{
if (event->type() == QEvent::FocusIn || event->type() == QEvent::Paint) {
qDebug() << object << "is now focused in";
refreshIfNeeded();
}
return QDockWidget::eventFilter(object, event);
}
void CutterDockWidget::toggleDockWidget(bool show) void CutterDockWidget::toggleDockWidget(bool show)
{ {
@ -21,6 +34,15 @@ void CutterDockWidget::toggleDockWidget(bool show)
} else { } else {
this->show(); this->show();
this->raise(); this->raise();
this->refreshIfNeeded();
}
}
void CutterDockWidget::refreshIfNeeded()
{
if (doRefresh) {
refreshContent();
doRefresh = false;
} }
} }
@ -32,4 +54,13 @@ void CutterDockWidget::closeEvent(QCloseEvent *event)
QDockWidget::closeEvent(event); QDockWidget::closeEvent(event);
} }
CutterDockWidget::~CutterDockWidget() {} bool CutterDockWidget::isVisibleToUser()
{
// Check if the user can actually see the widget.
bool visibleToUser = this->isVisible() && !this->visibleRegion().isEmpty();
if (!visibleToUser) {
// If this is called and not visible, it must be refreshed later
doRefresh = true;
}
return visibleToUser;
}

View File

@ -7,21 +7,29 @@ class MainWindow;
class CutterDockWidget : public QDockWidget class CutterDockWidget : public QDockWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CutterDockWidget(MainWindow *main, QAction *action = nullptr); explicit CutterDockWidget(MainWindow *main, QAction *action = nullptr);
~CutterDockWidget(); ~CutterDockWidget() override;
bool eventFilter(QObject *object, QEvent *event) override;
public slots: public slots:
void toggleDockWidget(bool show); void toggleDockWidget(bool show);
private: private:
QAction *action; QAction *action;
/**
* @brief doRefresh tells if the widget must refresh its content.
*/
bool doRefresh = false;
void refreshIfNeeded();
protected: protected:
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
bool isVisibleToUser();
virtual void refreshContent() = 0;
}; };
#endif // CUTTERWIDGET_H #endif // CUTTERWIDGET_H

View File

@ -25,6 +25,8 @@ private slots:
private: private:
std::unique_ptr<Ui::Dashboard> ui; std::unique_ptr<Ui::Dashboard> ui;
void refreshContent() override { };
}; };
#endif // DASHBOARD_H #endif // DASHBOARD_H

View File

@ -268,6 +268,11 @@ void DisassemblyWidget::refreshDisasm(RVA offset)
mDisasTextEdit->horizontalScrollBar()->setValue(horizontalScrollValue); mDisasTextEdit->horizontalScrollBar()->setValue(horizontalScrollValue);
} }
void DisassemblyWidget::refreshContent()
{
refreshDisasm();
}
void DisassemblyWidget::scrollInstructions(int count) void DisassemblyWidget::scrollInstructions(int count)
{ {
@ -576,7 +581,7 @@ void DisassemblyWidget::moveCursorRelative(bool up, bool page)
bool DisassemblyWidget::eventFilter(QObject *obj, QEvent *event) bool DisassemblyWidget::eventFilter(QObject *obj, QEvent *event)
{ {
if ((obj == mDisasTextEdit || obj == mDisasTextEdit->viewport()) /*if ((obj == mDisasTextEdit || obj == mDisasTextEdit->viewport())
&& event->type() == QEvent::MouseButtonDblClick) { && event->type() == QEvent::MouseButtonDblClick) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event); QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
@ -599,8 +604,8 @@ bool DisassemblyWidget::eventFilter(QObject *obj, QEvent *event)
} }
return true; return true;
} }*/
return QDockWidget::eventFilter(obj, event); return CutterDockWidget::eventFilter(obj, event);
} }
void DisassemblyWidget::on_seekChanged(RVA offset) void DisassemblyWidget::on_seekChanged(RVA offset)

View File

@ -24,7 +24,6 @@ public:
public slots: public slots:
void highlightCurrentLine(); void highlightCurrentLine();
void showDisasContextMenu(const QPoint &pt); void showDisasContextMenu(const QPoint &pt);
void refreshDisasm(RVA offset = RVA_INVALID);
void fontsUpdatedSlot(); void fontsUpdatedSlot();
void colorsUpdatedSlot(); void colorsUpdatedSlot();
void seekPrev(); void seekPrev();
@ -32,6 +31,7 @@ public slots:
private slots: private slots:
void on_seekChanged(RVA offset); void on_seekChanged(RVA offset);
void refreshDisasm(RVA offset = RVA_INVALID);
void raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType type); void raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType type);
void scrollInstructions(int count); void scrollInstructions(int count);
@ -59,10 +59,12 @@ private:
RVA readCurrentDisassemblyOffset(); RVA readCurrentDisassemblyOffset();
RVA readDisassemblyOffset(QTextCursor tc); RVA readDisassemblyOffset(QTextCursor tc);
bool eventFilter(QObject *obj, QEvent *event); bool eventFilter(QObject *obj, QEvent *event) override;
QList<RVA> breakpoints; QList<RVA> breakpoints;
void refreshContent() override;
void setupFonts(); void setupFonts();
void setupColors(); void setupColors();

View File

@ -137,6 +137,8 @@ private:
CutterTreeWidget *tree; CutterTreeWidget *tree;
void setScrollMode(); void setScrollMode();
void refreshContent() override { }
}; };

View File

@ -39,3 +39,8 @@ GraphWidget::GraphWidget(MainWindow *main, QAction *action) :
} }
GraphWidget::~GraphWidget() {} GraphWidget::~GraphWidget() {}
void GraphWidget::refreshContent()
{
graphView->refreshView();
}

View File

@ -12,11 +12,13 @@ class GraphWidget : public CutterDockWidget
public: public:
explicit GraphWidget(MainWindow *main, QAction *action = nullptr); explicit GraphWidget(MainWindow *main, QAction *action = nullptr);
~GraphWidget(); ~GraphWidget() override;
private: private:
DisassemblerGraphView *graphView; DisassemblerGraphView *graphView;
void refreshContent() override;
}; };
#endif // GRAPHWIDGET_H #endif // GRAPHWIDGET_H

View File

@ -116,7 +116,7 @@ HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) :
connect(ui->hexHexText, &QTextEdit::cursorPositionChanged, this, &HexdumpWidget::selectionChanged); connect(ui->hexHexText, &QTextEdit::cursorPositionChanged, this, &HexdumpWidget::selectionChanged);
connect(ui->hexASCIIText, &QTextEdit::cursorPositionChanged, this, connect(ui->hexASCIIText, &QTextEdit::cursorPositionChanged, this,
&HexdumpWidget::selectionChanged); &HexdumpWidget::selectionChanged);
connect(seekable, &CutterSeekable::seekableSeekChanged, this, &HexdumpWidget::on_seekChanged); connect(seekable, &CutterSeekable::seekableSeekChanged, this, &HexdumpWidget::onSeekChanged);
connect(&rangeDialog, &QDialog::accepted, this, &HexdumpWidget::on_rangeDialogAccepted); connect(&rangeDialog, &QDialog::accepted, this, &HexdumpWidget::on_rangeDialogAccepted);
format = Format::Hex; format = Format::Hex;
@ -208,13 +208,15 @@ void HexdumpWidget::setupScrollSync()
asciiHexFunc); asciiHexFunc);
} }
void HexdumpWidget::on_seekChanged(RVA addr) void HexdumpWidget::onSeekChanged(RVA addr)
{ {
if (sent_seek) { if (sent_seek) {
sent_seek = false; sent_seek = false;
return; return;
} }
refresh(addr); if (isVisibleToUser()) {
refreshContent();
}
} }
void HexdumpWidget::raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType type) void HexdumpWidget::raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType type)

View File

@ -72,6 +72,7 @@ private:
RVA last_loaded_address = RVA_INVALID; RVA last_loaded_address = RVA_INVALID;
void refresh(RVA addr = RVA_INVALID); void refresh(RVA addr = RVA_INVALID);
void refreshContent() override { refresh(); }
void selectHexPreview(); void selectHexPreview();
void updateHeaders(); void updateHeaders();
@ -110,7 +111,7 @@ private:
CutterSeekable *seekable; CutterSeekable *seekable;
private slots: private slots:
void on_seekChanged(RVA addr); void onSeekChanged(RVA addr);
void raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType type); void raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType type);
// Currently unused/untested // Currently unused/untested

View File

@ -31,7 +31,7 @@ PseudocodeWidget::PseudocodeWidget(MainWindow *main, QAction *action) :
}); });
connect(ui->refreshButton, &QAbstractButton::clicked, this, [this]() { connect(ui->refreshButton, &QAbstractButton::clicked, this, [this]() {
refresh(Core()->getOffset()); doRefresh(Core()->getOffset());
}); });
if (Core()->getR2DecAvailable()) { if (Core()->getR2DecAvailable()) {
@ -42,13 +42,13 @@ PseudocodeWidget::PseudocodeWidget(MainWindow *main, QAction *action) :
ui->decompilerComboBox->setCurrentIndex(DecompilerCBPdc); ui->decompilerComboBox->setCurrentIndex(DecompilerCBPdc);
} }
refresh(RVA_INVALID); doRefresh(RVA_INVALID);
} }
PseudocodeWidget::~PseudocodeWidget() {} PseudocodeWidget::~PseudocodeWidget() {}
void PseudocodeWidget::refresh(RVA addr) void PseudocodeWidget::doRefresh(RVA addr)
{ {
if (addr == RVA_INVALID) { if (addr == RVA_INVALID) {
ui->textEdit->setText(tr("Click Refresh to generate Pseudocode from current offset.")); ui->textEdit->setText(tr("Click Refresh to generate Pseudocode from current offset."));
@ -78,7 +78,7 @@ void PseudocodeWidget::refresh(RVA addr)
void PseudocodeWidget::refreshPseudocode() void PseudocodeWidget::refreshPseudocode()
{ {
refresh(Core()->getOffset()); doRefresh(Core()->getOffset());
} }
void PseudocodeWidget::raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType type) void PseudocodeWidget::raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType type)

View File

@ -33,7 +33,7 @@ private:
SyntaxHighlighter *syntaxHighLighter; SyntaxHighlighter *syntaxHighLighter;
void refresh(RVA addr); void doRefresh(RVA addr);
void setupFonts(); void setupFonts();
}; };