Reimplemented hex viewer item renderer to draw additional graphics to highlighting changes in snapshot diff window

This commit is contained in:
Nav
2023-05-07 00:58:44 +01:00
parent db158a0eda
commit 76192df641
8 changed files with 268 additions and 1 deletions

View File

@@ -115,6 +115,7 @@ target_sources(
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerWidget.cpp
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsView.cpp
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsScene.cpp
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerItemRenderer.cpp
# Memory region manager window
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/MemoryRegionManagerWindow.cpp

View File

@@ -0,0 +1,176 @@
#include "DifferentialHexViewerItemRenderer.hpp"
#include <QScrollBar>
#include <QPointF>
#include <array>
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteAddressContainer.hpp"
namespace Bloom::Widgets
{
DifferentialHexViewerItemRenderer::DifferentialHexViewerItemRenderer(
DifferentialHexViewerWidgetType differentialHexViewerWidgetType,
const HexViewerSharedState& hexViewerState,
const HexViewerItemIndex& itemIndex,
const QGraphicsView* view
)
: HexViewerItemRenderer(
hexViewerState,
itemIndex,
view
)
, differentialHexViewerWidgetType(differentialHexViewerWidgetType)
{}
void DifferentialHexViewerItemRenderer::setOther(const DifferentialHexViewerItemRenderer* other) {
this->other = other;
}
void DifferentialHexViewerItemRenderer::paint(
QPainter* painter,
const QStyleOptionGraphicsItem* option,
QWidget* widget
) {
if (this->other == nullptr) {
return;
}
const auto vScrollBarValue = this->view->verticalScrollBar()->value();
const auto otherVScrollBarValue = this->other->view->verticalScrollBar()->value();
const auto viewportHeight = this->view->viewport()->height();
const auto visibleItems = this->itemIndex.items(
vScrollBarValue,
vScrollBarValue + viewportHeight + (ByteItem::HEIGHT * 2)
);
painter->setRenderHints(QPainter::RenderHint::Antialiasing, false);
// Paint the ancestors of the first visible item
const auto& firstItem = *(visibleItems.begin());
auto* parentItem = firstItem->parent;
while (parentItem != nullptr) {
painter->setOpacity(1);
this->paintItem(parentItem, painter);
parentItem = parentItem->parent;
}
const ByteItem* previousLineFirstByteItem = nullptr;
const ByteItem* previousLineLastByteItem = nullptr;
auto changedByteOnCurrentLine = false;
const auto& byteItemYPosByAddress = this->itemIndex.byteItemYStartPositionsByAddress;
painter->setOpacity(1);
for (auto& item : visibleItems) {
const auto* byteItem = dynamic_cast<const ByteItem*>(item);
if (byteItem != nullptr) {
if (
previousLineLastByteItem == nullptr
|| previousLineLastByteItem->position().y() != byteItemYPosByAddress.at(byteItem->startAddress)
) {
if (changedByteOnCurrentLine) {
this->paintChangedLinePolygon(
previousLineFirstByteItem,
previousLineLastByteItem,
viewportHeight,
vScrollBarValue,
otherVScrollBarValue,
painter
);
changedByteOnCurrentLine = false;
}
previousLineFirstByteItem = byteItem;
}
changedByteOnCurrentLine = changedByteOnCurrentLine || byteItem->changed;
previousLineLastByteItem = byteItem;
}
}
if (changedByteOnCurrentLine) {
this->paintChangedLinePolygon(
previousLineFirstByteItem,
previousLineLastByteItem,
viewportHeight,
vScrollBarValue,
otherVScrollBarValue,
painter
);
}
for (auto& item : visibleItems) {
painter->setOpacity(1);
this->paintItem(item, painter);
}
}
void DifferentialHexViewerItemRenderer::paintChangedLinePolygon(
const ByteItem* firstByteItem,
const ByteItem* lastByteItem,
int viewportHeight,
int vScrollBarValue,
int otherVScrollBarValue,
QPainter* painter
) {
static constexpr auto backgroundColor = QColor(0x3A, 0x37, 0x39, 255);
painter->setBrush(backgroundColor);
painter->setPen(Qt::NoPen);
const auto firstByteItemYPos = this->itemIndex.byteItemYStartPositionsByAddress.at(firstByteItem->startAddress);
if (this->differentialHexViewerWidgetType == DifferentialHexViewerWidgetType::SECONDARY) {
painter->drawRect(
ByteAddressContainer::WIDTH,
firstByteItemYPos - (ByteItem::BOTTOM_MARGIN / 2) + 1,
this->size.width(),
ByteItem::HEIGHT + ByteItem::BOTTOM_MARGIN - 1
);
return;
}
static constexpr auto rightSpacing = 20;
const auto vScrollDifference = otherVScrollBarValue - vScrollBarValue;
const auto& otherByteItemYPosByAddress = this->other->itemIndex.byteItemYStartPositionsByAddress;
const auto otherFirstByteItemYPos = otherByteItemYPosByAddress.at(
firstByteItem->startAddress
) - vScrollDifference;
const auto otherLastByteItemYPos = otherByteItemYPosByAddress.at(
lastByteItem->startAddress
) - vScrollDifference;
const auto otherYStart = std::max(
vScrollBarValue,
std::min(
otherFirstByteItemYPos - (ByteItem::BOTTOM_MARGIN / 2) + 1,
vScrollBarValue + viewportHeight
)
);
const auto otherYEnd = std::max(
vScrollBarValue,
std::min(
otherLastByteItemYPos + ByteItem::HEIGHT + (ByteItem::BOTTOM_MARGIN / 2),
vScrollBarValue + viewportHeight
)
);
const auto points = std::array{
QPointF(ByteAddressContainer::WIDTH, firstByteItemYPos - (ByteItem::BOTTOM_MARGIN / 2) + 1),
QPointF(this->size.width() - rightSpacing, firstByteItemYPos - (ByteItem::BOTTOM_MARGIN / 2) + 1),
QPointF(this->size.width(), otherYStart),
QPointF(this->size.width(), otherYEnd),
QPointF(this->size.width() - rightSpacing, firstByteItemYPos + ByteItem::HEIGHT + (ByteItem::BOTTOM_MARGIN / 2)),
QPointF(ByteAddressContainer::WIDTH, firstByteItemYPos + ByteItem::HEIGHT + (ByteItem::BOTTOM_MARGIN / 2)),
};
painter->drawPolygon(points.data(), points.size());
}
}

View File

@@ -0,0 +1,35 @@
#pragma once
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/HexViewerItemRenderer.hpp"
#include "DifferentialHexViewerWidgetType.hpp"
namespace Bloom::Widgets
{
class DifferentialHexViewerItemRenderer: public HexViewerItemRenderer
{
public:
DifferentialHexViewerItemRenderer(
DifferentialHexViewerWidgetType differentialHexViewerWidgetType,
const HexViewerSharedState& hexViewerState,
const HexViewerItemIndex& itemIndex,
const QGraphicsView* view
);
void setOther(const DifferentialHexViewerItemRenderer* other);
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
protected:
DifferentialHexViewerWidgetType differentialHexViewerWidgetType;
const DifferentialHexViewerItemRenderer* other = nullptr;
inline void paintChangedLinePolygon(
const ByteItem* firstByteItem,
const ByteItem* lastByteItem,
int viewportHeight,
int vScrollBarValue,
int otherVScrollBarValue,
QPainter* painter
) __attribute__((__always_inline__));
};
}

View File

@@ -31,6 +31,7 @@ namespace Bloom::Widgets
void DifferentialHexViewerWidget::init() {
this->differentialView = new DifferentialItemGraphicsView(
this->type,
this->state,
this->snapshotDiffSettings,
this->targetMemoryDescriptor,

View File

@@ -2,9 +2,12 @@
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsView.hpp"
#include "DifferentialHexViewerItemRenderer.hpp"
namespace Bloom::Widgets
{
DifferentialItemGraphicsScene::DifferentialItemGraphicsScene(
DifferentialHexViewerWidgetType differentialHexViewerWidgetType,
DifferentialHexViewerSharedState& state,
const SnapshotDiffSettings& snapshotDiffSettings,
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
@@ -22,6 +25,7 @@ namespace Bloom::Widgets
settings,
parent
)
, differentialHexViewerWidgetType(differentialHexViewerWidgetType)
, diffHexViewerState(state)
, snapshotDiffSettings(snapshotDiffSettings)
{}
@@ -29,6 +33,12 @@ namespace Bloom::Widgets
void DifferentialItemGraphicsScene::setOther(DifferentialItemGraphicsScene* other) {
this->other = other;
assert(this->other->differentialHexViewerItemRenderer != nullptr);
if (this->differentialHexViewerItemRenderer != nullptr) {
this->differentialHexViewerItemRenderer->setOther(this->other->differentialHexViewerItemRenderer);
}
QObject::connect(
this->other,
&DifferentialItemGraphicsScene::hoveredAddress,
@@ -56,6 +66,29 @@ namespace Bloom::Widgets
this->update();
}
void DifferentialItemGraphicsScene::initRenderer() {
this->differentialHexViewerItemRenderer = new DifferentialHexViewerItemRenderer(
this->differentialHexViewerWidgetType,
this->state,
*(this->itemIndex.get()),
this->views().first()
);
if (this->other != nullptr && this->other->differentialHexViewerItemRenderer != nullptr) {
this->differentialHexViewerItemRenderer->setOther(this->other->differentialHexViewerItemRenderer);
}
this->renderer = this->differentialHexViewerItemRenderer;
this->renderer->setPos(0, 0);
this->addItem(this->renderer);
}
QMargins DifferentialItemGraphicsScene::margins() {
auto margins = ItemGraphicsScene::margins();
margins.setRight(DifferentialItemGraphicsScene::CENTER_WIDTH / 2);
return margins;
}
void DifferentialItemGraphicsScene::onOtherHoveredAddress(
const std::optional<Targets::TargetMemoryAddress>& address
) {

View File

@@ -2,7 +2,9 @@
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.hpp"
#include "DifferentialHexViewerWidgetType.hpp"
#include "DifferentialHexViewerSharedState.hpp"
#include "DifferentialHexViewerItemRenderer.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/SnapshotDiffSettings.hpp"
@@ -14,6 +16,7 @@ namespace Bloom::Widgets
public:
DifferentialItemGraphicsScene(
DifferentialHexViewerWidgetType differentialHexViewerWidgetType,
DifferentialHexViewerSharedState& state,
const SnapshotDiffSettings& snapshotDiffSettings,
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
@@ -29,10 +32,17 @@ namespace Bloom::Widgets
void updateByteItemChangedStates();
protected:
static constexpr auto CENTER_WIDTH = 46;
DifferentialHexViewerWidgetType differentialHexViewerWidgetType;
DifferentialHexViewerSharedState& diffHexViewerState;
const SnapshotDiffSettings& snapshotDiffSettings;
DifferentialHexViewerItemRenderer* differentialHexViewerItemRenderer = nullptr;
DifferentialItemGraphicsScene* other = nullptr;
void initRenderer() override;
QMargins margins() override;
void onOtherHoveredAddress(const std::optional<Targets::TargetMemoryAddress>& address);
void onOtherSelectionChanged(
const std::unordered_map<Targets::TargetMemoryAddress, ByteItem*>& selectedByteItemsByAddress

View File

@@ -3,6 +3,7 @@
namespace Bloom::Widgets
{
DifferentialItemGraphicsView::DifferentialItemGraphicsView(
DifferentialHexViewerWidgetType differentialHexViewerWidgetType,
DifferentialHexViewerSharedState& state,
const SnapshotDiffSettings& snapshotDiffSettings,
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
@@ -20,12 +21,14 @@ namespace Bloom::Widgets
settings,
parent
)
, differentialHexViewerWidgetType(differentialHexViewerWidgetType)
, state(state)
, snapshotDiffSettings(snapshotDiffSettings)
{}
void DifferentialItemGraphicsView::initScene() {
this->differentialScene = new DifferentialItemGraphicsScene(
this->differentialHexViewerWidgetType,
this->state,
this->snapshotDiffSettings,
this->targetMemoryDescriptor,
@@ -73,7 +76,12 @@ namespace Bloom::Widgets
void DifferentialItemGraphicsView::scrollContentsBy(int dx, int dy) {
ItemGraphicsView::scrollContentsBy(dx, dy);
if (!this->snapshotDiffSettings.syncHexViewerScroll || this->state.syncingScroll) {
if (!this->snapshotDiffSettings.syncHexViewerScroll) {
this->other->update();
return;
}
if (this->state.syncingScroll) {
return;
}

View File

@@ -2,6 +2,7 @@
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsView.hpp"
#include "DifferentialHexViewerWidgetType.hpp"
#include "DifferentialHexViewerSharedState.hpp"
#include "DifferentialItemGraphicsScene.hpp"
@@ -15,6 +16,7 @@ namespace Bloom::Widgets
public:
DifferentialItemGraphicsView(
DifferentialHexViewerWidgetType differentialHexViewerWidgetType,
DifferentialHexViewerSharedState& state,
const SnapshotDiffSettings& snapshotDiffSettings,
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
@@ -31,6 +33,7 @@ namespace Bloom::Widgets
void alignScroll(Targets::TargetMemoryAddress otherByteItemAddress, int otherByteItemYOffset);
protected:
DifferentialHexViewerWidgetType differentialHexViewerWidgetType;
DifferentialHexViewerSharedState& state;
const SnapshotDiffSettings& snapshotDiffSettings;