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);
hexdumpDock = new HexdumpWidget(this, ui->actionHexdump);
pseudocodeDock = new PseudocodeWidget(this, ui->actionPseudocode);
//pseudocodeDock = new PseudocodeWidget(this, ui->actionPseudocode);
consoleDock = new ConsoleWidget(this, ui->actionConsole);
// Add graph view as dockable
graphDock = new GraphWidget(this, ui->actionGraph);
sectionsDock = new SectionsWidget(this, ui->actionSections);
segmentsDock = new SegmentsWidget(this, ui->actionSegments);
entrypointDock = new EntrypointWidget(this, ui->actionEntrypoints);
//sectionsDock = new SectionsWidget(this, ui->actionSections);
//segmentsDock = new SegmentsWidget(this, ui->actionSegments);
//entrypointDock = new EntrypointWidget(this, ui->actionEntrypoints);
functionsDock = new FunctionsWidget(this, ui->actionFunctions);
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);
commentsDock = new CommentsWidget(this, ui->actionComments);
stringsDock = new StringsWidget(this, ui->actionStrings);
flagsDock = new FlagsWidget(this, ui->actionFlags);
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);
//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);
//commentsDock = new CommentsWidget(this, ui->actionComments);
//stringsDock = new StringsWidget(this, ui->actionStrings);
//flagsDock = new FlagsWidget(this, ui->actionFlags);
//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);
#ifdef CUTTER_ENABLE_JUPYTER
jupyterDock = new JupyterWidget(this, ui->actionJupyter);
//jupyterDock = new JupyterWidget(this, ui->actionJupyter);
#else
ui->actionJupyter->setEnabled(false);
ui->actionJupyter->setVisible(false);
#endif
dashboardDock = new Dashboard(this, ui->actionDashboard);
sdbDock = new SdbDock(this, ui->actionSDBBrowser);
classesDock = new ClassesWidget(this, ui->actionClasses);
resourcesDock = new ResourcesWidget(this, ui->actionResources);
vTablesDock = new VTablesWidget(this, ui->actionVTables);
//sdbDock = new SdbDock(this, ui->actionSDBBrowser);
//classesDock = new ClassesWidget(this, ui->actionClasses);
//resourcesDock = new ResourcesWidget(this, ui->actionResources);
//vTablesDock = new VTablesWidget(this, ui->actionVTables);
// Set up dock widgets default layout
@ -543,7 +543,7 @@ void MainWindow::lockUnlock_Docks(bool what)
void MainWindow::restoreDocks()
{
// In the upper half the functions are the first widget
addDockWidget(Qt::TopDockWidgetArea, functionsDock);
//addDockWidget(Qt::TopDockWidgetArea, functionsDock);
// Function | Dashboard
splitDockWidget(functionsDock, dashboardDock, Qt::Horizontal);
@ -552,41 +552,41 @@ void MainWindow::restoreDocks()
addDockWidget(Qt::BottomDockWidgetArea, consoleDock);
// Console | Sections
splitDockWidget(consoleDock, sectionsDock, Qt::Horizontal);
splitDockWidget(consoleDock, segmentsDock, Qt::Horizontal);
//splitDockWidget(consoleDock, sectionsDock, Qt::Horizontal);
//splitDockWidget(consoleDock, segmentsDock, Qt::Horizontal);
// Tabs for center (must be applied after splitDockWidget())
tabifyDockWidget(sectionsDock, commentsDock);
tabifyDockWidget(segmentsDock, commentsDock);
//tabifyDockWidget(sectionsDock, commentsDock);
//tabifyDockWidget(segmentsDock, commentsDock);
tabifyDockWidget(dashboardDock, disassemblyDock);
tabifyDockWidget(dashboardDock, graphDock);
tabifyDockWidget(dashboardDock, hexdumpDock);
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);
//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);
// Add Stack, Registers and Backtrace vertically stacked
addDockWidget(Qt::TopDockWidgetArea, stackDock);
splitDockWidget(stackDock, registersDock, Qt::Vertical);
tabifyDockWidget(stackDock, backtraceDock);
//addDockWidget(Qt::TopDockWidgetArea, stackDock);
//splitDockWidget(stackDock, registersDock, Qt::Vertical);
//tabifyDockWidget(stackDock, backtraceDock);
// MemoryMap/Breakpoint/RegRefs widget goes in the center tabs
tabifyDockWidget(dashboardDock, memoryMapDock);
tabifyDockWidget(dashboardDock, breakpointDock);
tabifyDockWidget(dashboardDock, registerRefsDock);
//tabifyDockWidget(dashboardDock, memoryMapDock);
//tabifyDockWidget(dashboardDock, breakpointDock);
//tabifyDockWidget(dashboardDock, registerRefsDock);
#ifdef CUTTER_ENABLE_JUPYTER
tabifyDockWidget(dashboardDock, jupyterDock);
//tabifyDockWidget(dashboardDock, jupyterDock);
#endif
updateDockActionsChecked();

View File

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

View File

@ -11,8 +11,21 @@ CutterDockWidget::CutterDockWidget(MainWindow *main, QAction *action) :
main->addDockWidgetAction(this, action);
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)
{
@ -21,6 +34,15 @@ void CutterDockWidget::toggleDockWidget(bool show)
} else {
this->show();
this->raise();
this->refreshIfNeeded();
}
}
void CutterDockWidget::refreshIfNeeded()
{
if (doRefresh) {
refreshContent();
doRefresh = false;
}
}
@ -32,4 +54,13 @@ void CutterDockWidget::closeEvent(QCloseEvent *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
{
Q_OBJECT
public:
explicit CutterDockWidget(MainWindow *main, QAction *action = nullptr);
~CutterDockWidget();
~CutterDockWidget() override;
bool eventFilter(QObject *object, QEvent *event) override;
public slots:
void toggleDockWidget(bool show);
private:
QAction *action;
/**
* @brief doRefresh tells if the widget must refresh its content.
*/
bool doRefresh = false;
void refreshIfNeeded();
protected:
void closeEvent(QCloseEvent *event) override;
bool isVisibleToUser();
virtual void refreshContent() = 0;
};
#endif // CUTTERWIDGET_H

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -12,11 +12,13 @@ class GraphWidget : public CutterDockWidget
public:
explicit GraphWidget(MainWindow *main, QAction *action = nullptr);
~GraphWidget();
~GraphWidget() override;
private:
DisassemblerGraphView *graphView;
void refreshContent() override;
};
#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->hexASCIIText, &QTextEdit::cursorPositionChanged, this,
&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);
format = Format::Hex;
@ -208,13 +208,15 @@ void HexdumpWidget::setupScrollSync()
asciiHexFunc);
}
void HexdumpWidget::on_seekChanged(RVA addr)
void HexdumpWidget::onSeekChanged(RVA addr)
{
if (sent_seek) {
sent_seek = false;
return;
}
refresh(addr);
if (isVisibleToUser()) {
refreshContent();
}
}
void HexdumpWidget::raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType type)

View File

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

View File

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

View File

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