Added annotation items in the hex viewer, for focused regions
Corrected issue with unexpected horizontal scrolling in hex viewer Added highlighting of focused byte items, in the hex viewer widget
This commit is contained in:
@@ -198,6 +198,7 @@ add_executable(Bloom
|
||||
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteItem.cpp
|
||||
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteAddressContainer.cpp
|
||||
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteAddressItem.cpp
|
||||
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/AnnotationItem.cpp
|
||||
|
||||
# Memory region manager window
|
||||
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/MemoryRegionManagerWindow.cpp
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#include "AnnotationItem.hpp"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include "ByteItem.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
AnnotationItem::AnnotationItem(std::uint32_t startAddress, std::size_t size, QString labelText, AnnotationItemPosition position)
|
||||
: QGraphicsItem(nullptr),
|
||||
startAddress(startAddress),
|
||||
size(size),
|
||||
endAddress(static_cast<std::uint32_t>(startAddress + size - 1)),
|
||||
labelText(std::move(labelText)),
|
||||
position(position),
|
||||
width(static_cast<int>((ByteItem::WIDTH + ByteItem::RIGHT_MARGIN) * size - ByteItem::RIGHT_MARGIN)),
|
||||
height(position == AnnotationItemPosition::TOP ? AnnotationItem::TOP_HEIGHT : AnnotationItem::BOTTOM_HEIGHT) {
|
||||
this->setAcceptHoverEvents(true);
|
||||
this->setToolTip(this->labelText);
|
||||
}
|
||||
|
||||
void AnnotationItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
static auto lineColor = this->getLineColor();
|
||||
static auto labelFontColor = this->getLabelFontColor();
|
||||
|
||||
const auto isEnabled = this->isEnabled();
|
||||
|
||||
lineColor.setAlpha(isEnabled ? 255 : 100);
|
||||
labelFontColor.setAlpha(isEnabled ? 255 : 100);
|
||||
|
||||
const auto fontMetrics = painter->fontMetrics();
|
||||
auto labelSize = fontMetrics.size(Qt::TextSingleLine, this->labelText);
|
||||
if (labelSize.width() > this->width) {
|
||||
labelSize.setWidth(this->width);
|
||||
this->labelText = fontMetrics.elidedText(this->labelText, Qt::TextElideMode::ElideRight, this->width);
|
||||
}
|
||||
|
||||
constexpr auto verticalLineLength = 5;
|
||||
const auto verticalLineYStart = this->position == AnnotationItemPosition::BOTTOM ? 0 : AnnotationItem::TOP_HEIGHT;
|
||||
const auto verticalLineYEnd = this->position == AnnotationItemPosition::BOTTOM ?
|
||||
verticalLineLength : AnnotationItem::TOP_HEIGHT - verticalLineLength;
|
||||
|
||||
const auto labelRect = QRect(
|
||||
(this->width - labelSize.width()) / 2,
|
||||
verticalLineYEnd - (this->position == AnnotationItemPosition::BOTTOM ? -6: labelSize.height() + 6),
|
||||
labelSize.width(),
|
||||
labelSize.height()
|
||||
);
|
||||
|
||||
painter->setPen(lineColor);
|
||||
painter->drawLine(QLine(
|
||||
ByteItem::WIDTH / 2,
|
||||
verticalLineYStart,
|
||||
ByteItem::WIDTH / 2,
|
||||
verticalLineYEnd
|
||||
));
|
||||
|
||||
painter->drawLine(QLine(
|
||||
this->width - (ByteItem::WIDTH / 2),
|
||||
verticalLineYStart,
|
||||
this->width - (ByteItem::WIDTH / 2),
|
||||
verticalLineYEnd
|
||||
));
|
||||
|
||||
painter->drawLine(QLine(
|
||||
ByteItem::WIDTH / 2,
|
||||
verticalLineYEnd,
|
||||
(ByteItem::WIDTH / 2) + (this->width - ByteItem::WIDTH),
|
||||
verticalLineYEnd
|
||||
));
|
||||
|
||||
painter->drawLine(QLine(
|
||||
this->width / 2,
|
||||
verticalLineYEnd,
|
||||
this->width / 2,
|
||||
(this->position == AnnotationItemPosition::BOTTOM ? verticalLineYEnd + 4 : verticalLineYEnd - 4)
|
||||
));
|
||||
|
||||
painter->setPen(labelFontColor);
|
||||
painter->drawText(labelRect, Qt::AlignCenter, this->labelText);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
enum class AnnotationItemPosition: std::uint8_t
|
||||
{
|
||||
TOP,
|
||||
BOTTOM,
|
||||
};
|
||||
|
||||
class AnnotationItem: public QGraphicsItem
|
||||
{
|
||||
public:
|
||||
static constexpr int TOP_HEIGHT = 26;
|
||||
static constexpr int BOTTOM_HEIGHT = 26;
|
||||
|
||||
const int width;
|
||||
const int height;
|
||||
const std::uint32_t startAddress;
|
||||
const std::uint32_t endAddress;
|
||||
AnnotationItemPosition position = AnnotationItemPosition::TOP;
|
||||
|
||||
AnnotationItem(
|
||||
std::uint32_t startAddress,
|
||||
std::size_t size,
|
||||
QString labelText,
|
||||
AnnotationItemPosition position
|
||||
);
|
||||
|
||||
[[nodiscard]] QRectF boundingRect() const override {
|
||||
return QRectF(0, 0, this->width, this->height);
|
||||
}
|
||||
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
|
||||
|
||||
protected:
|
||||
[[nodiscard]] QColor getLineColor() const {
|
||||
return QColor(0x4F, 0x4F, 0x4F);
|
||||
}
|
||||
|
||||
[[nodiscard]] QColor getLabelFontColor() const {
|
||||
return QColor(0x8A, 0x8A, 0x8D);
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t size = 0;
|
||||
QString labelText;
|
||||
};
|
||||
}
|
||||
@@ -3,20 +3,20 @@
|
||||
#include <QPainter>
|
||||
#include <QStyle>
|
||||
|
||||
#include "src/Logger/Logger.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
|
||||
ByteItem::ByteItem(
|
||||
std::size_t byteIndex,
|
||||
std::uint32_t address,
|
||||
std::optional<ByteItem*>& hoveredByteItem,
|
||||
std::optional<AnnotationItem*>& hoveredAnnotationItem,
|
||||
const HexViewerWidgetSettings& settings
|
||||
):
|
||||
QGraphicsItem(nullptr),
|
||||
byteIndex(byteIndex),
|
||||
address(address),
|
||||
hoveredByteItem(hoveredByteItem),
|
||||
hoveredAnnotationItem(hoveredAnnotationItem),
|
||||
settings(settings)
|
||||
{
|
||||
this->setCacheMode(
|
||||
@@ -51,25 +51,40 @@ void ByteItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
|
||||
static const auto valueChangedTextColor = QColor(0x54, 0x7F, 0xBA);
|
||||
static auto font = QFont("'Ubuntu', sans-serif");
|
||||
|
||||
static const auto stackMemoryBackgroundColor = QColor(0x5E, 0x50, 0x27, 255);
|
||||
static const auto focusedRegionBackgroundColor = QColor(0x25, 0x5A, 0x49, 210);
|
||||
static const auto stackMemoryBackgroundColor = QColor(0x67, 0x57, 0x20, 210);
|
||||
static const auto hoveredBackgroundColor = QColor(0x8E, 0x8B, 0x83, 70);
|
||||
static const auto hoveredNeighbourBackgroundColor = QColor(0x8E, 0x8B, 0x83, 30);
|
||||
static const auto hoveredAnnotationBackgroundColor = QColor(0x8E, 0x8B, 0x83, 50);
|
||||
|
||||
const auto isEnabled = this->isEnabled();
|
||||
auto textColor = this->valueChanged ? valueChangedTextColor : standardTextColor;
|
||||
auto backgroundColor = std::optional<QColor>();
|
||||
|
||||
font.setPixelSize(11);
|
||||
painter->setFont(font);
|
||||
|
||||
if (this->settings.highlightStackMemory && this->settings.stackPointerAddress.has_value()
|
||||
if (this->settings.highlightFocusedMemory && this->focusedMemoryRegion != nullptr) {
|
||||
// This byte is within a focused region
|
||||
backgroundColor = focusedRegionBackgroundColor;
|
||||
|
||||
} else if (this->settings.highlightStackMemory && this->settings.stackPointerAddress.has_value()
|
||||
&& this->address > this->settings.stackPointerAddress
|
||||
) {
|
||||
// This byte is within the stack memory
|
||||
painter->setBrush(stackMemoryBackgroundColor);
|
||||
painter->drawRect(widgetRect);
|
||||
backgroundColor = stackMemoryBackgroundColor;
|
||||
}
|
||||
|
||||
const auto* hoveredByteItem = this->hoveredByteItem.value_or(nullptr);
|
||||
const auto* hoveredAnnotationItem = this->hoveredAnnotationItem.value_or(nullptr);
|
||||
if (hoveredByteItem != nullptr) {
|
||||
if (hoveredByteItem == this) {
|
||||
painter->setBrush(hoveredBackgroundColor);
|
||||
if (backgroundColor.has_value()) {
|
||||
backgroundColor->setAlpha(255);
|
||||
|
||||
} else {
|
||||
backgroundColor = hoveredBackgroundColor;
|
||||
}
|
||||
|
||||
} else if (this->settings.highlightHoveredRowAndCol
|
||||
&& (
|
||||
@@ -77,16 +92,34 @@ void ByteItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option,
|
||||
|| hoveredByteItem->currentRowIndex == this->currentRowIndex
|
||||
)
|
||||
) {
|
||||
painter->setBrush(hoveredNeighbourBackgroundColor);
|
||||
if (backgroundColor.has_value()) {
|
||||
backgroundColor->setAlpha(220);
|
||||
|
||||
} else {
|
||||
backgroundColor = hoveredNeighbourBackgroundColor;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (
|
||||
!this->settings.highlightFocusedMemory
|
||||
&& hoveredAnnotationItem != nullptr
|
||||
&& this->address >= hoveredAnnotationItem->startAddress
|
||||
&& this->address <= hoveredAnnotationItem->endAddress
|
||||
) {
|
||||
backgroundColor = hoveredAnnotationBackgroundColor;
|
||||
}
|
||||
|
||||
if (backgroundColor.has_value()) {
|
||||
if (!isEnabled) {
|
||||
backgroundColor->setAlpha(100);
|
||||
}
|
||||
|
||||
painter->setBrush(backgroundColor.value());
|
||||
painter->drawRect(widgetRect);
|
||||
}
|
||||
|
||||
auto textColor = this->valueChanged ? valueChangedTextColor : standardTextColor;
|
||||
|
||||
if (this->valueInitialised) {
|
||||
if (!this->isEnabled()) {
|
||||
if (this->valueInitialised && this->excludedMemoryRegion == nullptr) {
|
||||
if (!isEnabled) {
|
||||
textColor.setAlpha(100);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,11 @@
|
||||
#include <QGraphicsItem>
|
||||
#include <optional>
|
||||
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/ClickableWidget.hpp"
|
||||
#include "HexViewerWidgetSettings.hpp"
|
||||
#include "AnnotationItem.hpp"
|
||||
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/FocusedMemoryRegion.hpp"
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/ExcludedMemoryRegion.hpp"
|
||||
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
@@ -28,10 +31,14 @@ namespace Bloom::Widgets
|
||||
std::size_t currentRowIndex = 0;
|
||||
std::size_t currentColumnIndex = 0;
|
||||
|
||||
const FocusedMemoryRegion* focusedMemoryRegion = nullptr;
|
||||
const ExcludedMemoryRegion* excludedMemoryRegion = nullptr;
|
||||
|
||||
ByteItem(
|
||||
std::size_t byteIndex,
|
||||
std::uint32_t address,
|
||||
std::optional<ByteItem*>& hoveredByteItem,
|
||||
std::optional<AnnotationItem*>& hoveredAnnotationItem,
|
||||
const HexViewerWidgetSettings& settings
|
||||
);
|
||||
|
||||
@@ -58,5 +65,6 @@ namespace Bloom::Widgets
|
||||
std::optional<QString> asciiValue;
|
||||
|
||||
std::optional<ByteItem*>& hoveredByteItem;
|
||||
std::optional<AnnotationItem*>& hoveredAnnotationItem;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
#include "ByteItemContainerGraphicsView.hpp"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QTableWidget>
|
||||
#include <QScrollBar>
|
||||
#include <QPainter>
|
||||
#include <cmath>
|
||||
|
||||
#include "src/Logger/Logger.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
using Bloom::Targets::TargetMemoryDescriptor;
|
||||
|
||||
ByteItemContainerGraphicsView::ByteItemContainerGraphicsView(
|
||||
const TargetMemoryDescriptor& targetMemoryDescriptor,
|
||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||
InsightWorker& insightWorker,
|
||||
const HexViewerWidgetSettings& settings,
|
||||
QLabel* hoveredAddressLabel,
|
||||
@@ -29,6 +22,8 @@ ByteItemContainerGraphicsView::ByteItemContainerGraphicsView(
|
||||
|
||||
this->scene = new ByteItemGraphicsScene(
|
||||
targetMemoryDescriptor,
|
||||
focusedMemoryRegions,
|
||||
excludedMemoryRegions,
|
||||
insightWorker,
|
||||
settings,
|
||||
hoveredAddressLabel,
|
||||
@@ -49,6 +44,6 @@ bool ByteItemContainerGraphicsView::event(QEvent* event) {
|
||||
}
|
||||
|
||||
void ByteItemContainerGraphicsView::resizeEvent(QResizeEvent* event) {
|
||||
this->scene->adjustByteWidgets();
|
||||
QGraphicsView::resizeEvent(event);
|
||||
this->scene->adjustSize();
|
||||
}
|
||||
|
||||
@@ -3,18 +3,10 @@
|
||||
#include <QGraphicsView>
|
||||
#include <QWidget>
|
||||
#include <QLabel>
|
||||
#include <QToolButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <QSize>
|
||||
#include <QString>
|
||||
#include <QEvent>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <optional>
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
#include "src/Targets/TargetState.hpp"
|
||||
|
||||
#include "src/Insight/InsightWorker/InsightWorker.hpp"
|
||||
|
||||
@@ -30,6 +22,8 @@ namespace Bloom::Widgets
|
||||
public:
|
||||
ByteItemContainerGraphicsView(
|
||||
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
|
||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||
InsightWorker& insightWorker,
|
||||
const HexViewerWidgetSettings& settings,
|
||||
QLabel* hoveredAddressLabel,
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
#include "ByteItemGraphicsScene.hpp"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QTableWidget>
|
||||
#include <QScrollBar>
|
||||
#include <QPainter>
|
||||
#include <cmath>
|
||||
|
||||
#include "src/Logger/Logger.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
@@ -15,33 +9,34 @@ using Bloom::Targets::TargetMemoryDescriptor;
|
||||
|
||||
ByteItemGraphicsScene::ByteItemGraphicsScene(
|
||||
const TargetMemoryDescriptor& targetMemoryDescriptor,
|
||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||
InsightWorker& insightWorker,
|
||||
const HexViewerWidgetSettings& settings,
|
||||
QLabel* hoveredAddressLabel,
|
||||
QWidget* parent
|
||||
): QGraphicsScene(parent),
|
||||
targetMemoryDescriptor(targetMemoryDescriptor),
|
||||
insightWorker(insightWorker),
|
||||
settings(settings),
|
||||
hoveredAddressLabel(hoveredAddressLabel),
|
||||
parent(parent) {
|
||||
QGraphicsView* parent
|
||||
):
|
||||
QGraphicsScene(parent),
|
||||
targetMemoryDescriptor(targetMemoryDescriptor),
|
||||
focusedMemoryRegions(focusedMemoryRegions),
|
||||
excludedMemoryRegions(excludedMemoryRegions),
|
||||
insightWorker(insightWorker),
|
||||
settings(settings),
|
||||
hoveredAddressLabel(hoveredAddressLabel),
|
||||
parent(parent)
|
||||
{
|
||||
this->setObjectName("byte-widget-container");
|
||||
|
||||
this->byteAddressContainer = new ByteAddressContainer();
|
||||
this->addItem(this->byteAddressContainer);
|
||||
|
||||
/*
|
||||
* Construct ByteWidget objects
|
||||
*
|
||||
* No need to position them here - the subsequent call to resizeEvent() will do that.
|
||||
*/
|
||||
// Construct ByteWidget objects
|
||||
const auto memorySize = this->targetMemoryDescriptor.size();
|
||||
const auto startAddress = this->targetMemoryDescriptor.addressRange.startAddress;
|
||||
Logger::error("Constructing bytes begin");
|
||||
for (std::uint32_t i = 0; i < memorySize; i++) {
|
||||
const auto address = startAddress + i;
|
||||
|
||||
auto* byteWidget = new ByteItem(i, address, this->hoveredByteWidget, settings);
|
||||
auto* byteWidget = new ByteItem(i, address, this->hoveredByteWidget, this->hoveredAnnotationItem, settings);
|
||||
this->byteItemsByAddress.insert(std::pair(
|
||||
address,
|
||||
byteWidget
|
||||
@@ -49,8 +44,6 @@ parent(parent) {
|
||||
|
||||
this->addItem(byteWidget);
|
||||
}
|
||||
Logger::error("Constructing bytes end");
|
||||
this->adjustByteWidgets();
|
||||
|
||||
QObject::connect(
|
||||
&insightWorker,
|
||||
@@ -58,6 +51,9 @@ parent(parent) {
|
||||
this,
|
||||
&ByteItemGraphicsScene::onTargetStateChanged
|
||||
);
|
||||
|
||||
this->refreshRegions();
|
||||
this->adjustSize();
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::updateValues(const Targets::TargetMemoryBuffer& buffer) {
|
||||
@@ -67,61 +63,101 @@ void ByteItemGraphicsScene::updateValues(const Targets::TargetMemoryBuffer& buff
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::adjustByteWidgets() {
|
||||
const auto margins = QMargins(10, 10, 10, 10);
|
||||
const auto width = std::max(600, static_cast<int>(this->parent->width()));
|
||||
void ByteItemGraphicsScene::refreshRegions() {
|
||||
for (auto& [byteAddress, byteWidget] : this->byteItemsByAddress) {
|
||||
byteWidget->focusedMemoryRegion = nullptr;
|
||||
byteWidget->excludedMemoryRegion = nullptr;
|
||||
|
||||
constexpr auto byteWidgetWidth = ByteItem::WIDTH + ByteItem::RIGHT_MARGIN;
|
||||
constexpr auto byteWidgetHeight = ByteItem::HEIGHT + ByteItem::BOTTOM_MARGIN;
|
||||
const auto rowCapacity = static_cast<std::size_t>(
|
||||
std::floor((width - margins.left() - margins.right() - ByteAddressContainer::WIDTH) / byteWidgetWidth)
|
||||
);
|
||||
const auto rowCount = static_cast<int>(
|
||||
std::ceil(static_cast<double>(this->byteItemsByAddress.size()) / static_cast<double>(rowCapacity))
|
||||
);
|
||||
for (const auto& focusedRegion : this->focusedMemoryRegions) {
|
||||
const auto addressRange = focusedRegion.getAbsoluteAddressRange();
|
||||
if (byteAddress >= addressRange.startAddress && byteAddress <= addressRange.endAddress) {
|
||||
byteWidget->focusedMemoryRegion = &focusedRegion;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->setSceneRect(
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
std::max(((rowCount * byteWidgetHeight) + margins.top() + margins.bottom()), this->parent->height())
|
||||
);
|
||||
|
||||
// Don't bother recalculating the byte item positions if the number of rows & columns have not changed.
|
||||
if (rowCount == this->byteItemsByRowIndex.size() && rowCapacity == this->byteItemsByColumnIndex.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<std::size_t, std::vector<ByteItem*>> byteWidgetsByRowIndex;
|
||||
std::map<std::size_t, std::vector<ByteItem*>> byteWidgetsByColumnIndex;
|
||||
|
||||
for (auto& [address, byteWidget] : this->byteItemsByAddress) {
|
||||
const auto rowIndex = static_cast<std::size_t>(
|
||||
std::ceil(static_cast<double>(byteWidget->byteIndex + 1) / static_cast<double>(rowCapacity)) - 1
|
||||
);
|
||||
const auto columnIndex = static_cast<std::size_t>(
|
||||
static_cast<double>(byteWidget->byteIndex)
|
||||
- (std::floor(byteWidget->byteIndex / rowCapacity) * static_cast<double>(rowCapacity))
|
||||
);
|
||||
|
||||
byteWidget->setPos(
|
||||
static_cast<int>(columnIndex * byteWidgetWidth + margins.left() + ByteAddressContainer::WIDTH),
|
||||
static_cast<int>(rowIndex * byteWidgetHeight + static_cast<std::size_t>(margins.top()))
|
||||
);
|
||||
|
||||
byteWidget->currentRowIndex = static_cast<std::size_t>(rowIndex);
|
||||
byteWidget->currentColumnIndex = static_cast<std::size_t>(columnIndex);
|
||||
|
||||
byteWidgetsByRowIndex[byteWidget->currentRowIndex].emplace_back(byteWidget);
|
||||
byteWidgetsByColumnIndex[byteWidget->currentColumnIndex].emplace_back(byteWidget);
|
||||
for (const auto& excludedRegion : this->excludedMemoryRegions) {
|
||||
const auto addressRange = excludedRegion.getAbsoluteAddressRange();
|
||||
if (byteAddress >= addressRange.startAddress && byteAddress <= addressRange.endAddress) {
|
||||
byteWidget->excludedMemoryRegion = &excludedRegion;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
byteWidget->update();
|
||||
}
|
||||
|
||||
this->byteItemsByRowIndex = std::move(byteWidgetsByRowIndex);
|
||||
this->byteItemsByColumnIndex = std::move(byteWidgetsByColumnIndex);
|
||||
// Refresh annotation items
|
||||
for (auto [startAddress, annotationItem] : this->annotationItemsByStartAddress) {
|
||||
this->removeItem(annotationItem);
|
||||
delete annotationItem;
|
||||
}
|
||||
|
||||
this->byteAddressContainer->adjustAddressLabels(this->byteItemsByRowIndex);
|
||||
this->annotationItemsByStartAddress.clear();
|
||||
|
||||
for (const auto& focusedRegion : this->focusedMemoryRegions) {
|
||||
const auto addressRange = focusedRegion.getAbsoluteAddressRange();
|
||||
auto* annotationItem = new AnnotationItem(
|
||||
addressRange.startAddress,
|
||||
addressRange.endAddress - addressRange.startAddress + 1,
|
||||
focusedRegion.name,
|
||||
AnnotationItemPosition::BOTTOM
|
||||
);
|
||||
this->addItem(annotationItem);
|
||||
this->annotationItemsByStartAddress.insert(std::pair(addressRange.startAddress, annotationItem));
|
||||
}
|
||||
|
||||
this->adjustSize(true);
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::adjustSize(bool forced) {
|
||||
const auto width = this->getSceneWidth();
|
||||
|
||||
const auto columnCount = static_cast<std::size_t>(
|
||||
std::floor(
|
||||
(width - this->margins.left() - this->margins.right() - ByteAddressContainer::WIDTH + ByteItem::RIGHT_MARGIN)
|
||||
/ (ByteItem::WIDTH + ByteItem::RIGHT_MARGIN)
|
||||
)
|
||||
);
|
||||
const auto rowCount = static_cast<int>(
|
||||
std::ceil(static_cast<double>(this->byteItemsByAddress.size()) / static_cast<double>(columnCount))
|
||||
);
|
||||
|
||||
// Don't bother recalculating the byte item & annotation positions if the number of rows & columns have not changed.
|
||||
if (this->byteItemsByAddress.empty()
|
||||
|| (
|
||||
!forced
|
||||
&& rowCount == this->byteItemsByRowIndex.size()
|
||||
&& columnCount == this->byteItemsByColumnIndex.size()
|
||||
)
|
||||
) {
|
||||
this->setSceneRect(
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
std::max(static_cast<int>(this->sceneRect().height()), this->parent->viewport()->height())
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->byteItemsByAddress.empty()) {
|
||||
this->adjustByteItemPositions();
|
||||
this->adjustAnnotationItemPositions();
|
||||
|
||||
const auto lastByteItemPosition = (--this->byteItemsByAddress.end())->second->pos();
|
||||
this->setSceneRect(
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
std::max(
|
||||
static_cast<int>(lastByteItemPosition.y() + ByteItem::HEIGHT + this->margins.bottom()),
|
||||
this->parent->height()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
this->update();
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::setEnabled(bool enabled) {
|
||||
@@ -132,11 +168,178 @@ void ByteItemGraphicsScene::setEnabled(bool enabled) {
|
||||
byteItem->setEnabled(this->enabled);
|
||||
}
|
||||
|
||||
for (auto& [startAddress, annotationItem] : this->annotationItemsByStartAddress) {
|
||||
annotationItem->setEnabled(this->enabled);
|
||||
}
|
||||
|
||||
this->byteAddressContainer->setEnabled(enabled);
|
||||
this->byteAddressContainer->update();
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::invalidateChildItemCaches() {
|
||||
for (auto& [address, byteWidget] : this->byteItemsByAddress) {
|
||||
byteWidget->update();
|
||||
}
|
||||
|
||||
for (auto& [startAddress, annotationItem] : this->annotationItemsByStartAddress) {
|
||||
annotationItem->update();
|
||||
}
|
||||
}
|
||||
|
||||
bool ByteItemGraphicsScene::event(QEvent* event) {
|
||||
if (event->type() == QEvent::Type::GraphicsSceneLeave && this->hoveredByteWidget.has_value()) {
|
||||
this->onByteWidgetLeave();
|
||||
}
|
||||
|
||||
return QGraphicsScene::event(event);
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent) {
|
||||
auto hoveredItems = this->items(mouseEvent->scenePos());
|
||||
ByteItem* hoveredByteItem = nullptr;
|
||||
AnnotationItem* hoveredAnnotationItem = nullptr;
|
||||
|
||||
if (!hoveredItems.empty()) {
|
||||
hoveredByteItem = dynamic_cast<ByteItem*>(hoveredItems.at(0));
|
||||
hoveredAnnotationItem = dynamic_cast<AnnotationItem*>(hoveredItems.at(0));
|
||||
}
|
||||
|
||||
if (hoveredByteItem != nullptr) {
|
||||
this->onByteWidgetEnter(hoveredByteItem);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->hoveredByteWidget.has_value()) {
|
||||
this->onByteWidgetLeave();
|
||||
}
|
||||
|
||||
if (hoveredAnnotationItem != nullptr) {
|
||||
this->onAnnotationItemEnter(hoveredAnnotationItem);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->hoveredAnnotationItem.has_value()) {
|
||||
this->onAnnotationItemLeave();
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::adjustByteItemPositions() {
|
||||
const auto columnCount = static_cast<std::size_t>(
|
||||
std::floor(
|
||||
(this->getSceneWidth() - this->margins.left() - this->margins.right() - ByteAddressContainer::WIDTH + ByteItem::RIGHT_MARGIN)
|
||||
/ (ByteItem::WIDTH + ByteItem::RIGHT_MARGIN)
|
||||
)
|
||||
);
|
||||
|
||||
std::map<std::size_t, std::vector<ByteItem*>> byteWidgetsByRowIndex;
|
||||
std::map<std::size_t, std::vector<ByteItem*>> byteWidgetsByColumnIndex;
|
||||
|
||||
auto rowIndicesWithTopAnnotations = std::set<std::size_t>();
|
||||
auto rowIndicesWithBottomAnnotations = std::set<std::size_t>();
|
||||
const auto& memoryAddressRange = this->targetMemoryDescriptor.addressRange;
|
||||
|
||||
for (auto [startAddress, annotationItem] : this->annotationItemsByStartAddress) {
|
||||
const auto firstByteRowIndex = static_cast<std::size_t>(
|
||||
std::ceil(static_cast<double>((startAddress - memoryAddressRange.startAddress) + 1)
|
||||
/ static_cast<double>(columnCount)) - 1
|
||||
);
|
||||
|
||||
const auto lastByteRowIndex = static_cast<std::size_t>(
|
||||
std::ceil(static_cast<double>((annotationItem->endAddress - memoryAddressRange.startAddress) + 1)
|
||||
/ static_cast<double>(columnCount)) - 1
|
||||
);
|
||||
|
||||
// We only display annotations that span a single row.
|
||||
if (firstByteRowIndex == lastByteRowIndex) {
|
||||
annotationItem->show();
|
||||
rowIndicesWithBottomAnnotations.insert(firstByteRowIndex);
|
||||
|
||||
} else {
|
||||
annotationItem->hide();
|
||||
}
|
||||
}
|
||||
|
||||
constexpr auto annotationTopHeight = AnnotationItem::TOP_HEIGHT;
|
||||
constexpr auto annotationBottomHeight = AnnotationItem::BOTTOM_HEIGHT;
|
||||
|
||||
std::size_t lastRowIndex = 0;
|
||||
int rowYPosition = margins.top();
|
||||
auto currentRowAnnotatedTop = false;
|
||||
|
||||
for (auto& [address, byteWidget] : this->byteItemsByAddress) {
|
||||
const auto rowIndex = static_cast<std::size_t>(
|
||||
std::ceil(static_cast<double>(byteWidget->byteIndex + 1) / static_cast<double>(columnCount)) - 1
|
||||
);
|
||||
const auto columnIndex = static_cast<std::size_t>(
|
||||
static_cast<double>(byteWidget->byteIndex)
|
||||
- (std::floor(byteWidget->byteIndex / columnCount) * static_cast<double>(columnCount))
|
||||
);
|
||||
|
||||
if (rowIndex != lastRowIndex) {
|
||||
rowYPosition += ByteItem::HEIGHT + ByteItem::BOTTOM_MARGIN;
|
||||
currentRowAnnotatedTop = false;
|
||||
|
||||
if (rowIndicesWithBottomAnnotations.contains(lastRowIndex)) {
|
||||
rowYPosition += annotationBottomHeight;
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentRowAnnotatedTop && rowIndicesWithTopAnnotations.contains(rowIndex)) {
|
||||
rowYPosition += annotationTopHeight;
|
||||
currentRowAnnotatedTop = true;
|
||||
}
|
||||
|
||||
byteWidget->setPos(
|
||||
static_cast<int>(
|
||||
columnIndex * (ByteItem::WIDTH + ByteItem::RIGHT_MARGIN) + this->margins.left() + ByteAddressContainer::WIDTH),
|
||||
rowYPosition
|
||||
);
|
||||
|
||||
byteWidget->currentRowIndex = rowIndex;
|
||||
byteWidget->currentColumnIndex = columnIndex;
|
||||
|
||||
byteWidgetsByRowIndex[byteWidget->currentRowIndex].emplace_back(byteWidget);
|
||||
byteWidgetsByColumnIndex[byteWidget->currentColumnIndex].emplace_back(byteWidget);
|
||||
|
||||
lastRowIndex = rowIndex;
|
||||
}
|
||||
|
||||
this->byteItemsByRowIndex = std::move(byteWidgetsByRowIndex);
|
||||
this->byteItemsByColumnIndex = std::move(byteWidgetsByColumnIndex);
|
||||
|
||||
this->byteAddressContainer->adjustAddressLabels(this->byteItemsByRowIndex);
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::adjustAnnotationItemPositions() {
|
||||
if (this->byteItemsByAddress.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& [startAddress, annotationItem] : this->annotationItemsByStartAddress) {
|
||||
if (!this->byteItemsByAddress.contains(startAddress)) {
|
||||
annotationItem->hide();
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto firstByteItemPosition = this->byteItemsByAddress.at(startAddress)->pos();
|
||||
|
||||
if (annotationItem->position == AnnotationItemPosition::TOP) {
|
||||
annotationItem->setPos(
|
||||
firstByteItemPosition.x(),
|
||||
firstByteItemPosition.y() - AnnotationItem::TOP_HEIGHT
|
||||
);
|
||||
|
||||
} else if (annotationItem->position == AnnotationItemPosition::BOTTOM) {
|
||||
annotationItem->setPos(
|
||||
firstByteItemPosition.x(),
|
||||
firstByteItemPosition.y() + ByteItem::HEIGHT
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::onTargetStateChanged(Targets::TargetState newState) {
|
||||
using Targets::TargetState;
|
||||
this->targetState = newState;
|
||||
@@ -147,10 +350,9 @@ void ByteItemGraphicsScene::onByteWidgetEnter(ByteItem* widget) {
|
||||
if (this->hoveredByteWidget.value() == widget) {
|
||||
// This byte item is already marked as hovered
|
||||
return;
|
||||
|
||||
} else {
|
||||
this->onByteWidgetLeave();
|
||||
}
|
||||
|
||||
this->onByteWidgetLeave();
|
||||
}
|
||||
|
||||
this->hoveredByteWidget = widget;
|
||||
@@ -174,7 +376,7 @@ void ByteItemGraphicsScene::onByteWidgetEnter(ByteItem* widget) {
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::onByteWidgetLeave() {
|
||||
const auto byteItem = this->hoveredByteWidget.value();
|
||||
auto* byteItem = this->hoveredByteWidget.value();
|
||||
this->hoveredByteWidget = std::nullopt;
|
||||
|
||||
this->hoveredAddressLabel->setText("Relative Address (Absolute Address):");
|
||||
@@ -193,24 +395,35 @@ void ByteItemGraphicsScene::onByteWidgetLeave() {
|
||||
}
|
||||
}
|
||||
|
||||
bool ByteItemGraphicsScene::event(QEvent* event) {
|
||||
if (event->type() == QEvent::Type::GraphicsSceneLeave && this->hoveredByteWidget.has_value()) {
|
||||
this->onByteWidgetLeave();
|
||||
}
|
||||
|
||||
return QGraphicsScene::event(event);
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent) {
|
||||
auto hoveredItems = this->items(mouseEvent->scenePos());
|
||||
if (!hoveredItems.empty()) {
|
||||
auto hoveredByteWidget = dynamic_cast<ByteItem*>(hoveredItems.at(0));
|
||||
|
||||
if (hoveredByteWidget != nullptr) {
|
||||
this->onByteWidgetEnter(hoveredByteWidget);
|
||||
void ByteItemGraphicsScene::onAnnotationItemEnter(AnnotationItem* annotationItem) {
|
||||
if (this->hoveredAnnotationItem.has_value()) {
|
||||
if (this->hoveredAnnotationItem.value() == annotationItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (this->hoveredByteWidget.has_value()) {
|
||||
this->onByteWidgetLeave();
|
||||
this->onAnnotationItemLeave();
|
||||
}
|
||||
|
||||
this->hoveredAnnotationItem = annotationItem;
|
||||
|
||||
for (
|
||||
auto byteItemAddress = annotationItem->startAddress;
|
||||
byteItemAddress <= annotationItem->endAddress;
|
||||
byteItemAddress++
|
||||
) {
|
||||
this->byteItemsByAddress.at(byteItemAddress)->update();
|
||||
}
|
||||
}
|
||||
|
||||
void ByteItemGraphicsScene::onAnnotationItemLeave() {
|
||||
auto* annotationItem = this->hoveredAnnotationItem.value();
|
||||
this->hoveredAnnotationItem = std::nullopt;
|
||||
|
||||
for (
|
||||
auto byteItemAddress = annotationItem->startAddress;
|
||||
byteItemAddress <= annotationItem->endAddress;
|
||||
byteItemAddress++
|
||||
) {
|
||||
this->byteItemsByAddress.at(byteItemAddress)->update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsView>
|
||||
#include <QScrollBar>
|
||||
#include <QWidget>
|
||||
#include <QLabel>
|
||||
#include <QToolButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <QSize>
|
||||
#include <QString>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QGraphicsSceneWheelEvent>
|
||||
#include <optional>
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
@@ -19,8 +23,13 @@
|
||||
|
||||
#include "ByteItem.hpp"
|
||||
#include "ByteAddressContainer.hpp"
|
||||
#include "AnnotationItem.hpp"
|
||||
#include "HexViewerWidgetSettings.hpp"
|
||||
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegion.hpp"
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/FocusedMemoryRegion.hpp"
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/ExcludedMemoryRegion.hpp"
|
||||
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
class ByteItemGraphicsScene: public QGraphicsScene
|
||||
@@ -29,24 +38,23 @@ namespace Bloom::Widgets
|
||||
|
||||
public:
|
||||
std::optional<ByteItem*> hoveredByteWidget;
|
||||
|
||||
std::map<std::uint32_t, ByteItem*> byteItemsByAddress;
|
||||
std::map<std::size_t, std::vector<ByteItem*>> byteItemsByRowIndex;
|
||||
std::map<std::size_t, std::vector<ByteItem*>> byteItemsByColumnIndex;
|
||||
std::optional<AnnotationItem*> hoveredAnnotationItem;
|
||||
|
||||
ByteItemGraphicsScene(
|
||||
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
|
||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||
InsightWorker& insightWorker,
|
||||
const HexViewerWidgetSettings& settings,
|
||||
QLabel* hoveredAddressLabel,
|
||||
QWidget* parent
|
||||
QGraphicsView* parent
|
||||
);
|
||||
|
||||
void updateValues(const Targets::TargetMemoryBuffer& buffer);
|
||||
|
||||
void adjustByteWidgets();
|
||||
|
||||
void refreshRegions();
|
||||
void adjustSize(bool forced = false);
|
||||
void setEnabled(bool enabled);
|
||||
void invalidateChildItemCaches();
|
||||
|
||||
signals:
|
||||
void byteWidgetsAdjusted();
|
||||
@@ -57,21 +65,43 @@ namespace Bloom::Widgets
|
||||
|
||||
private:
|
||||
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor;
|
||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions;
|
||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions;
|
||||
|
||||
std::map<std::uint32_t, ByteItem*> byteItemsByAddress;
|
||||
std::map<std::uint32_t, AnnotationItem*> annotationItemsByStartAddress;
|
||||
std::map<std::size_t, std::vector<ByteItem*>> byteItemsByRowIndex;
|
||||
std::map<std::size_t, std::vector<ByteItem*>> byteItemsByColumnIndex;
|
||||
|
||||
Targets::TargetState targetState = Targets::TargetState::UNKNOWN;
|
||||
InsightWorker& insightWorker;
|
||||
|
||||
const QMargins margins = QMargins(10, 10, 10, 10);
|
||||
const HexViewerWidgetSettings& settings;
|
||||
|
||||
QWidget* parent = nullptr;
|
||||
QGraphicsView* parent = nullptr;
|
||||
QLabel* hoveredAddressLabel = nullptr;
|
||||
|
||||
ByteAddressContainer* byteAddressContainer = nullptr;
|
||||
|
||||
bool enabled = true;
|
||||
|
||||
private slots:
|
||||
int getSceneWidth() {
|
||||
/*
|
||||
* Minus 2 for the QSS margin on the vertical scrollbar (which isn't accounted for during viewport
|
||||
* size calculation).
|
||||
*
|
||||
* See https://bugreports.qt.io/browse/QTBUG-99189 for more on this.
|
||||
*/
|
||||
return std::max(this->parent->viewport()->width(), 400) - 2;
|
||||
}
|
||||
|
||||
void adjustByteItemPositions();
|
||||
void adjustAnnotationItemPositions();
|
||||
void onTargetStateChanged(Targets::TargetState newState);
|
||||
void onByteWidgetEnter(Bloom::Widgets::ByteItem* widget);
|
||||
void onByteWidgetLeave();
|
||||
void onAnnotationItemEnter(Bloom::Widgets::AnnotationItem* annotationItem);
|
||||
void onAnnotationItemLeave();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
#include "HexViewerWidget.hpp"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QScrollBar>
|
||||
#include <QScrollArea>
|
||||
#include <QPainter>
|
||||
#include <cmath>
|
||||
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/UiLoader.hpp"
|
||||
|
||||
#include "src/Helpers/Paths.hpp"
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
#include "src/Logger/Logger.hpp"
|
||||
|
||||
using namespace Bloom::Widgets;
|
||||
using namespace Bloom::Exceptions;
|
||||
@@ -19,9 +12,17 @@ using Bloom::Targets::TargetMemoryDescriptor;
|
||||
|
||||
HexViewerWidget::HexViewerWidget(
|
||||
const TargetMemoryDescriptor& targetMemoryDescriptor,
|
||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||
InsightWorker& insightWorker,
|
||||
QWidget* parent
|
||||
): QWidget(parent), targetMemoryDescriptor(targetMemoryDescriptor), insightWorker(insightWorker) {
|
||||
):
|
||||
QWidget(parent),
|
||||
targetMemoryDescriptor(targetMemoryDescriptor),
|
||||
focusedMemoryRegions(focusedMemoryRegions),
|
||||
excludedMemoryRegions(excludedMemoryRegions),
|
||||
insightWorker(insightWorker)
|
||||
{
|
||||
this->setObjectName("hex-viewer-widget");
|
||||
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
|
||||
@@ -63,8 +64,10 @@ HexViewerWidget::HexViewerWidget(
|
||||
|
||||
this->byteItemGraphicsViewContainer = this->container->findChild<QWidget*>("graphics-view-container");
|
||||
this->byteItemGraphicsView = new ByteItemContainerGraphicsView(
|
||||
targetMemoryDescriptor,
|
||||
insightWorker,
|
||||
this->targetMemoryDescriptor,
|
||||
this->focusedMemoryRegions,
|
||||
this->excludedMemoryRegions,
|
||||
this->insightWorker,
|
||||
this->settings,
|
||||
this->hoveredAddressLabel,
|
||||
this->byteItemGraphicsViewContainer
|
||||
@@ -116,9 +119,13 @@ void HexViewerWidget::updateValues(const Targets::TargetMemoryBuffer& buffer) {
|
||||
this->byteItemGraphicsScene->updateValues(buffer);
|
||||
}
|
||||
|
||||
void HexViewerWidget::refreshRegions() {
|
||||
this->byteItemGraphicsScene->refreshRegions();
|
||||
}
|
||||
|
||||
void HexViewerWidget::setStackPointer(std::uint32_t stackPointer) {
|
||||
this->settings.stackPointerAddress = stackPointer;
|
||||
this->byteItemGraphicsScene->update();
|
||||
this->byteItemGraphicsScene->invalidateChildItemCaches();
|
||||
}
|
||||
|
||||
void HexViewerWidget::resizeEvent(QResizeEvent* event) {
|
||||
@@ -143,19 +150,19 @@ void HexViewerWidget::setStackMemoryHighlightingEnabled(bool enabled) {
|
||||
this->highlightStackMemoryButton->setChecked(enabled);
|
||||
this->settings.highlightStackMemory = enabled;
|
||||
|
||||
this->byteItemGraphicsScene->update();
|
||||
this->byteItemGraphicsScene->invalidateChildItemCaches();
|
||||
}
|
||||
|
||||
void HexViewerWidget::setHoveredRowAndColumnHighlightingEnabled(bool enabled) {
|
||||
this->highlightHoveredRowAndColumnButton->setChecked(enabled);
|
||||
this->settings.highlightHoveredRowAndCol = enabled;
|
||||
|
||||
this->byteItemGraphicsScene->update();
|
||||
this->byteItemGraphicsScene->invalidateChildItemCaches();
|
||||
}
|
||||
|
||||
void HexViewerWidget::setFocusedMemoryHighlightingEnabled(bool enabled) {
|
||||
this->highlightFocusedMemoryButton->setChecked(enabled);
|
||||
this->settings.highlightFocusedMemory = enabled;
|
||||
|
||||
this->byteItemGraphicsScene->update();
|
||||
this->byteItemGraphicsScene->invalidateChildItemCaches();
|
||||
}
|
||||
|
||||
@@ -2,25 +2,23 @@
|
||||
|
||||
#include <QWidget>
|
||||
#include <QLabel>
|
||||
#include <QGraphicsView>
|
||||
#include <QVBoxLayout>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <QSize>
|
||||
#include <QString>
|
||||
#include <QEvent>
|
||||
#include <QResizeEvent>
|
||||
#include <QShowEvent>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "src/Targets/TargetMemory.hpp"
|
||||
#include "src/Targets/TargetState.hpp"
|
||||
|
||||
#include "src/Insight/InsightWorker/InsightWorker.hpp"
|
||||
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/SvgToolButton.hpp"
|
||||
|
||||
#include "HexViewerWidgetSettings.hpp"
|
||||
#include "ByteItemContainerGraphicsView.hpp"
|
||||
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/SvgToolButton.hpp"
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegion.hpp"
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/FocusedMemoryRegion.hpp"
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/ExcludedMemoryRegion.hpp"
|
||||
|
||||
namespace Bloom::Widgets
|
||||
{
|
||||
@@ -33,12 +31,14 @@ namespace Bloom::Widgets
|
||||
|
||||
HexViewerWidget(
|
||||
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
|
||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
|
||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
|
||||
InsightWorker& insightWorker,
|
||||
QWidget* parent
|
||||
);
|
||||
|
||||
void updateValues(const Targets::TargetMemoryBuffer& buffer);
|
||||
|
||||
void refreshRegions();
|
||||
void setStackPointer(std::uint32_t stackPointer);
|
||||
|
||||
protected:
|
||||
@@ -47,6 +47,9 @@ namespace Bloom::Widgets
|
||||
|
||||
private:
|
||||
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor;
|
||||
std::vector<FocusedMemoryRegion>& focusedMemoryRegions;
|
||||
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions;
|
||||
|
||||
InsightWorker& insightWorker;
|
||||
|
||||
HexViewerWidgetSettings settings = HexViewerWidgetSettings();
|
||||
@@ -66,7 +69,6 @@ namespace Bloom::Widgets
|
||||
|
||||
Targets::TargetState targetState = Targets::TargetState::UNKNOWN;
|
||||
|
||||
private slots:
|
||||
void onTargetStateChanged(Targets::TargetState newState);
|
||||
void setStackMemoryHighlightingEnabled(bool enabled);
|
||||
void setHoveredRowAndColumnHighlightingEnabled(bool enabled);
|
||||
|
||||
@@ -382,6 +382,7 @@ void MemoryRegionManagerWindow::applyChanges() {
|
||||
this->focusedMemoryRegions = std::move(processedFocusedMemoryRegions);
|
||||
this->excludedMemoryRegions = std::move(processedExcludedMemoryRegions);
|
||||
this->close();
|
||||
emit this->changesApplied();
|
||||
}
|
||||
|
||||
void MemoryRegionManagerWindow::openHelpPage() {
|
||||
|
||||
@@ -37,6 +37,9 @@ namespace Bloom::Widgets
|
||||
|
||||
void refreshRegions();
|
||||
|
||||
signals:
|
||||
void changesApplied();
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent* event) override;
|
||||
|
||||
|
||||
@@ -49,7 +49,13 @@ TargetMemoryInspectionPane::TargetMemoryInspectionPane(
|
||||
|
||||
auto* subContainerLayout = this->container->findChild<QHBoxLayout*>("sub-container-layout");
|
||||
this->manageMemoryRegionsButton = this->container->findChild<SvgToolButton*>("manage-memory-regions-btn");
|
||||
this->hexViewerWidget = new HexViewerWidget(this->targetMemoryDescriptor, this->insightWorker, this);
|
||||
this->hexViewerWidget = new HexViewerWidget(
|
||||
this->targetMemoryDescriptor,
|
||||
this->focusedMemoryRegions,
|
||||
this->excludedMemoryRegions,
|
||||
this->insightWorker,
|
||||
this
|
||||
);
|
||||
this->hexViewerWidget->setDisabled(true);
|
||||
|
||||
subContainerLayout->addWidget(this->hexViewerWidget);
|
||||
@@ -187,6 +193,13 @@ void TargetMemoryInspectionPane::openMemoryRegionManagerWindow() {
|
||||
this->excludedMemoryRegions,
|
||||
this
|
||||
);
|
||||
|
||||
QObject::connect(
|
||||
this->memoryRegionManagerWindow,
|
||||
&MemoryRegionManagerWindow::changesApplied,
|
||||
this,
|
||||
&TargetMemoryInspectionPane::onMemoryRegionsChange
|
||||
);
|
||||
}
|
||||
|
||||
if (!this->memoryRegionManagerWindow->isVisible()) {
|
||||
@@ -197,3 +210,7 @@ void TargetMemoryInspectionPane::openMemoryRegionManagerWindow() {
|
||||
this->memoryRegionManagerWindow->activateWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void TargetMemoryInspectionPane::onMemoryRegionsChange() {
|
||||
this->hexViewerWidget->refreshRegions();
|
||||
}
|
||||
|
||||
@@ -64,5 +64,6 @@ namespace Bloom::Widgets
|
||||
void onTargetStateChanged(Targets::TargetState newState);
|
||||
void onMemoryRead(const Targets::TargetMemoryBuffer& buffer);
|
||||
void openMemoryRegionManagerWindow();
|
||||
void onMemoryRegionsChange();
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user