2019-02-22 16:50:45 +00:00
|
|
|
#include "core/MainWindow.h"
|
2019-01-24 17:13:04 +00:00
|
|
|
#include "OverviewWidget.h"
|
2019-04-14 12:18:24 +00:00
|
|
|
#include "GraphWidget.h"
|
2019-01-24 17:13:04 +00:00
|
|
|
#include "OverviewView.h"
|
|
|
|
|
|
|
|
OverviewWidget::OverviewWidget(MainWindow *main, QAction *action) :
|
|
|
|
CutterDockWidget(main, action)
|
|
|
|
{
|
2019-03-18 06:44:14 +00:00
|
|
|
setWindowTitle("Graph Overview");
|
|
|
|
setObjectName("Graph Overview");
|
|
|
|
setAllowedAreas(Qt::AllDockWidgetAreas);
|
|
|
|
graphView = new OverviewView(this);
|
|
|
|
setWidget(graphView);
|
2019-04-14 12:18:24 +00:00
|
|
|
targetGraphWidget = nullptr;
|
2019-01-24 17:13:04 +00:00
|
|
|
|
2019-04-14 12:18:24 +00:00
|
|
|
connect(graphView, SIGNAL(mouseMoved()), this, SLOT(updateTargetView()));
|
|
|
|
|
|
|
|
graphDataRefreshDeferrer = createRefreshDeferrer([this]() {
|
|
|
|
updateGraphData();
|
2019-01-24 17:13:04 +00:00
|
|
|
});
|
2019-07-22 19:28:11 +00:00
|
|
|
|
|
|
|
// Zoom shortcuts
|
|
|
|
QShortcut *shortcut_zoom_in = new QShortcut(QKeySequence(Qt::Key_Plus), this);
|
|
|
|
shortcut_zoom_in->setContext(Qt::WidgetWithChildrenShortcut);
|
|
|
|
connect(shortcut_zoom_in, &QShortcut::activated, this, [this](){ zoomTarget(1); });
|
|
|
|
QShortcut *shortcut_zoom_out = new QShortcut(QKeySequence(Qt::Key_Minus), this);
|
|
|
|
shortcut_zoom_out->setContext(Qt::WidgetWithChildrenShortcut);
|
|
|
|
connect(shortcut_zoom_out, &QShortcut::activated, this, [this](){ zoomTarget(-1); });
|
2019-01-24 17:13:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
OverviewWidget::~OverviewWidget() {}
|
|
|
|
|
2019-01-24 18:04:39 +00:00
|
|
|
void OverviewWidget::resizeEvent(QResizeEvent *event)
|
|
|
|
{
|
|
|
|
graphView->refreshView();
|
2019-04-14 12:18:24 +00:00
|
|
|
updateRangeRect();
|
2019-01-24 18:04:39 +00:00
|
|
|
QDockWidget::resizeEvent(event);
|
2019-02-07 20:39:37 +00:00
|
|
|
emit resized();
|
2019-01-24 18:04:39 +00:00
|
|
|
}
|
|
|
|
|
2019-04-14 12:18:24 +00:00
|
|
|
void OverviewWidget::showEvent(QShowEvent *event)
|
2019-01-24 17:13:04 +00:00
|
|
|
{
|
2019-04-14 12:18:24 +00:00
|
|
|
CutterDockWidget::showEvent(event);
|
|
|
|
setUserOpened(true);
|
2019-01-24 17:13:04 +00:00
|
|
|
}
|
2019-03-08 18:57:57 +00:00
|
|
|
|
|
|
|
void OverviewWidget::closeEvent(QCloseEvent *event)
|
|
|
|
{
|
|
|
|
CutterDockWidget::closeEvent(event);
|
2019-04-14 12:18:24 +00:00
|
|
|
setUserOpened(false);
|
2019-03-08 18:57:57 +00:00
|
|
|
}
|
2019-03-27 08:24:54 +00:00
|
|
|
|
2019-04-14 12:18:24 +00:00
|
|
|
void OverviewWidget::setIsAvailable(bool isAvailable)
|
2019-03-27 08:24:54 +00:00
|
|
|
{
|
2019-04-14 12:18:24 +00:00
|
|
|
if (this->isAvailable == isAvailable) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this->isAvailable = isAvailable;
|
|
|
|
if(!isAvailable) {
|
|
|
|
hide();
|
|
|
|
} else if(userOpened) {
|
|
|
|
show();
|
|
|
|
}
|
|
|
|
emit isAvailableChanged(isAvailable);
|
2019-03-27 08:24:54 +00:00
|
|
|
}
|
|
|
|
|
2019-04-14 12:18:24 +00:00
|
|
|
void OverviewWidget::setUserOpened(bool userOpened)
|
2019-03-27 08:24:54 +00:00
|
|
|
{
|
2019-04-14 12:18:24 +00:00
|
|
|
if (this->userOpened == userOpened) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this->userOpened = userOpened;
|
|
|
|
emit userOpenedChanged(userOpened);
|
2019-03-27 08:24:54 +00:00
|
|
|
}
|
|
|
|
|
2019-07-22 19:28:11 +00:00
|
|
|
void OverviewWidget::zoomTarget(int d)
|
|
|
|
{
|
|
|
|
if (!targetGraphWidget) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
targetGraphWidget->getGraphView()->zoom(QPointF(0.5, 0.5), d);
|
|
|
|
}
|
|
|
|
|
2019-04-14 12:18:24 +00:00
|
|
|
void OverviewWidget::setTargetGraphWidget(GraphWidget *widget)
|
2019-03-27 08:24:54 +00:00
|
|
|
{
|
2019-04-14 12:18:24 +00:00
|
|
|
if (widget == targetGraphWidget) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (targetGraphWidget) {
|
|
|
|
disconnect(targetGraphWidget->getGraphView(), &DisassemblerGraphView::viewRefreshed, this, &OverviewWidget::updateGraphData);
|
|
|
|
disconnect(targetGraphWidget->getGraphView(), &DisassemblerGraphView::resized, this, &OverviewWidget::updateRangeRect);
|
|
|
|
disconnect(targetGraphWidget->getGraphView(), &GraphView::viewOffsetChanged, this, &OverviewWidget::updateRangeRect);
|
|
|
|
disconnect(targetGraphWidget->getGraphView(), &GraphView::viewScaleChanged, this, &OverviewWidget::updateRangeRect);
|
|
|
|
disconnect(targetGraphWidget, &GraphWidget::graphClosed, this, &OverviewWidget::targetClosed);
|
|
|
|
}
|
|
|
|
targetGraphWidget = widget;
|
|
|
|
if (targetGraphWidget) {
|
|
|
|
connect(targetGraphWidget->getGraphView(), &DisassemblerGraphView::viewRefreshed, this, &OverviewWidget::updateGraphData);
|
|
|
|
connect(targetGraphWidget->getGraphView(), &DisassemblerGraphView::resized, this, &OverviewWidget::updateRangeRect);
|
|
|
|
connect(targetGraphWidget->getGraphView(), &GraphView::viewOffsetChanged, this, &OverviewWidget::updateRangeRect);
|
|
|
|
connect(targetGraphWidget->getGraphView(), &GraphView::viewScaleChanged, this, &OverviewWidget::updateRangeRect);
|
|
|
|
connect(targetGraphWidget, &GraphWidget::graphClosed, this, &OverviewWidget::targetClosed);
|
|
|
|
}
|
|
|
|
updateGraphData();
|
|
|
|
updateRangeRect();
|
|
|
|
setIsAvailable(targetGraphWidget != nullptr);
|
|
|
|
}
|
|
|
|
|
2019-07-22 19:28:11 +00:00
|
|
|
void OverviewWidget::wheelEvent(QWheelEvent *event)
|
|
|
|
{
|
|
|
|
zoomTarget(event->angleDelta().y() / 90);
|
|
|
|
graphView->centreRect();
|
|
|
|
}
|
|
|
|
|
2019-04-14 12:18:24 +00:00
|
|
|
void OverviewWidget::targetClosed()
|
|
|
|
{
|
|
|
|
setTargetGraphWidget(nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void OverviewWidget::updateTargetView()
|
|
|
|
{
|
2019-05-12 04:08:48 +00:00
|
|
|
if (!targetGraphWidget) {
|
|
|
|
return;
|
|
|
|
}
|
2019-04-14 12:18:24 +00:00
|
|
|
qreal curScale = graphView->getViewScale();
|
|
|
|
int rectx = graphView->getRangeRect().x();
|
|
|
|
int recty = graphView->getRangeRect().y();
|
|
|
|
int overview_offset_x = graphView->getViewOffset().x();
|
|
|
|
int overview_offset_y = graphView->getViewOffset().y();
|
|
|
|
QPoint newOffset;
|
|
|
|
newOffset.rx() = rectx / curScale + overview_offset_x;
|
|
|
|
newOffset.ry() = recty / curScale + overview_offset_y;
|
|
|
|
targetGraphWidget->getGraphView()->setViewOffset(newOffset);
|
|
|
|
targetGraphWidget->getGraphView()->viewport()->update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void OverviewWidget::updateGraphData()
|
|
|
|
{
|
|
|
|
if (!graphDataRefreshDeferrer->attemptRefresh(nullptr)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (targetGraphWidget && !targetGraphWidget->getGraphView()->isGraphEmpty()) {
|
|
|
|
graphView->currentFcnAddr = targetGraphWidget->getGraphView()->currentFcnAddr;
|
|
|
|
auto &mainGraphView = *targetGraphWidget->getGraphView();
|
|
|
|
graphView->setData(mainGraphView.getWidth(), mainGraphView.getHeight(),
|
|
|
|
mainGraphView.getBlocks(), mainGraphView.getEdgeConfigurations());
|
|
|
|
} else {
|
|
|
|
graphView->currentFcnAddr = RVA_INVALID;
|
|
|
|
graphView->setData(0, 0, {}, {});
|
|
|
|
graphView->setRangeRect(QRectF(0, 0, 0, 0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OverviewWidget::updateRangeRect() {
|
|
|
|
if (targetGraphWidget) {
|
|
|
|
qreal curScale = graphView->getViewScale();
|
|
|
|
qreal baseScale = targetGraphWidget->getGraphView()->getViewScale();
|
|
|
|
qreal w = targetGraphWidget->getGraphView()->viewport()->width() * curScale / baseScale;
|
|
|
|
qreal h = targetGraphWidget->getGraphView()->viewport()->height() * curScale / baseScale;
|
|
|
|
int graph_offset_x = targetGraphWidget->getGraphView()->getViewOffset().x();
|
|
|
|
int graph_offset_y = targetGraphWidget->getGraphView()->getViewOffset().y();
|
|
|
|
int overview_offset_x = graphView->getViewOffset().x();
|
|
|
|
int overview_offset_y = graphView->getViewOffset().y();
|
|
|
|
int rangeRectX = graph_offset_x * curScale - overview_offset_x * curScale;
|
|
|
|
int rangeRectY = graph_offset_y * curScale - overview_offset_y * curScale;
|
|
|
|
graphView->setRangeRect(QRectF(rangeRectX, rangeRectY, w, h));
|
|
|
|
} else {
|
|
|
|
graphView->setRangeRect(QRectF(0, 0, 0, 0));
|
|
|
|
}
|
2019-03-27 08:24:54 +00:00
|
|
|
}
|