From 76192df6414486bede552565d23ffadf8e248557 Mon Sep 17 00:00:00 2001 From: Nav Date: Sun, 7 May 2023 00:58:44 +0100 Subject: [PATCH] Reimplemented hex viewer item renderer to draw additional graphics to highlighting changes in snapshot diff window --- src/Insight/CMakeLists.txt | 1 + .../DifferentialHexViewerItemRenderer.cpp | 176 ++++++++++++++++++ .../DifferentialHexViewerItemRenderer.hpp | 35 ++++ .../DifferentialHexViewerWidget.cpp | 1 + .../DifferentialItemGraphicsScene.cpp | 33 ++++ .../DifferentialItemGraphicsScene.hpp | 10 + .../DifferentialItemGraphicsView.cpp | 10 +- .../DifferentialItemGraphicsView.hpp | 3 + 8 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerItemRenderer.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerItemRenderer.hpp diff --git a/src/Insight/CMakeLists.txt b/src/Insight/CMakeLists.txt index 20f0c5ae..155f1781 100755 --- a/src/Insight/CMakeLists.txt +++ b/src/Insight/CMakeLists.txt @@ -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 diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerItemRenderer.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerItemRenderer.cpp new file mode 100644 index 00000000..d5fbec64 --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerItemRenderer.cpp @@ -0,0 +1,176 @@ +#include "DifferentialHexViewerItemRenderer.hpp" + +#include +#include +#include + +#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(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()); + } +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerItemRenderer.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerItemRenderer.hpp new file mode 100644 index 00000000..e0fc1e2f --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerItemRenderer.hpp @@ -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__)); + }; +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerWidget.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerWidget.cpp index 88325233..eaa3d813 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerWidget.cpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialHexViewerWidget.cpp @@ -31,6 +31,7 @@ namespace Bloom::Widgets void DifferentialHexViewerWidget::init() { this->differentialView = new DifferentialItemGraphicsView( + this->type, this->state, this->snapshotDiffSettings, this->targetMemoryDescriptor, diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsScene.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsScene.cpp index 42144019..9f73c820 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsScene.cpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsScene.cpp @@ -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& address ) { diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsScene.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsScene.hpp index 31281e0d..718f028c 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsScene.hpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsScene.hpp @@ -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& address); void onOtherSelectionChanged( const std::unordered_map& selectedByteItemsByAddress diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsView.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsView.cpp index 8156d8ad..43d5eecc 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsView.cpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsView.cpp @@ -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; } diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsView.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsView.hpp index 60bc8313..0601cc19 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsView.hpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotDiff/DifferentialHexViewerWidget/DifferentialItemGraphicsView.hpp @@ -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;