Refactored hex viewer widget to use QGraphicsView items as opposed to widgets, for byte items in the hex viewer.

This requirement became apparent when testing the initial approach with large memory sizes - the GUI became unresponsive due to the number of widgets being constructed.
This was along side other performance issues that arose from the large number of widgets
This commit is contained in:
Nav
2021-10-24 20:40:53 +01:00
parent 8d82af3689
commit e2c4dcb97f
13 changed files with 364 additions and 312 deletions

View File

@@ -177,8 +177,9 @@ add_executable(Bloom
# Target memory inspection pane
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/TargetMemoryInspectionPane.cpp
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/HexViewerWidget.cpp
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteWidgetContainer.cpp
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteWidget.cpp
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteItemContainerGraphicsView.cpp
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteItemGraphicsScene.cpp
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteItem.cpp
)
set_target_properties(Bloom PROPERTIES OUTPUT_NAME bloom)

View File

@@ -179,6 +179,7 @@ QScrollBar:vertical {
QScrollBar:handle:vertical {
border: none;
background-color: rgba(69, 69, 66, 0.6);
min-height: 30px;
}
QScrollBar:handle:vertical:hover {
@@ -379,26 +380,29 @@ QScrollBar::sub-line:vertical {
}
#hex-viewer-container QScrollArea,
#hex-viewer-container #byte-widget-scroll-area-container {
#hex-viewer-container #graphics-view-container,
#hex-viewer-container #graphics-view-container #graphics-view {
background-color: #323330;
border: none;
font-size: 11px;
}
#hex-viewer-container #graphics-view-container {
background-color: #50504b;
border: none;
}
#hex-viewer-container #byte-widget-scroll-area-container #address-container {
#hex-viewer-container #graphics-view-container #address-container {
background-color: #353633;
border-right: 1px solid #41423f;
}
#hex-viewer-container #byte-widget-scroll-area-container #address-container QLabel {
#hex-viewer-container #graphics-view-container #address-container QLabel {
background-color: transparent;
font-size: 12px;
color: rgba(175, 177, 179, 0.72);
}
#hex-viewer-container #byte-widget-scroll-area-container #address-container QLabel:disabled {
#hex-viewer-container #graphics-view-container #address-container QLabel:disabled {
color: rgba(175, 177, 179, 0.3);
}
#hex-viewer-container #byte {
font-size: 11px;
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include <QGraphicsItem>
#include <cstdint>
#include <QEvent>
#include <QGraphicsScene>
#include <optional>
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/ClickableWidget.hpp"
namespace Bloom::Widgets
{
class ByteAddressContainer: public QGraphicsItem
{
public:
static constexpr int WIDTH = 85;
static constexpr int RIGHT_MARGIN = 5;
static constexpr int BOTTOM_MARGIN = 5;
std::size_t byteIndex;
unsigned char value = 0x00;
std::uint32_t address = 0x00;
QString addressHex;
QString relativeAddressHex;
bool valueInitialised = false;
std::size_t currentRowIndex = 0;
std::size_t currentColumnIndex = 0;
ByteAddressContainer();
[[nodiscard]] QRectF boundingRect() const override {
return QRectF(
0,
0,
ByteAddressContainer::WIDTH,
this->scene()->height()
);
}
private:
};
}

View File

@@ -0,0 +1,68 @@
#include "ByteItem.hpp"
#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
): QGraphicsItem(nullptr), byteIndex(byteIndex), address(address), hoveredByteItem(hoveredByteItem) {
this->setAcceptHoverEvents(true);
this->addressHex = "0x" + QString::number(this->address, 16).rightJustified(8, '0').toUpper();
this->relativeAddressHex = "0x" + QString::number(this->byteIndex, 16).rightJustified(8, '0').toUpper();
this->setSelected(false);
}
void ByteItem::setValue(unsigned char value) {
this->valueChanged = this->valueInitialised && this->value != value;
this->value = value;
this->hexValue = QString::number(this->value, 16).rightJustified(2, '0').toUpper();
this->asciiValue = (this->value >= 32 && this->value <= 126)
? std::optional(QString(QChar(this->value))) : std::nullopt;
this->valueInitialised = true;
}
void ByteItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
painter->setRenderHints(QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform, true);
painter->setPen(Qt::PenStyle::NoPen);
static const auto widgetRect = this->boundingRect();
if (this->hoveredByteItem.has_value()) {
const auto hoveredWidget = this->hoveredByteItem.value();
if (hoveredWidget->currentColumnIndex == this->currentColumnIndex
|| hoveredWidget->currentRowIndex == this->currentRowIndex
){
painter->setBrush(QColor(0x8E, 0x8B, 0x83, hoveredWidget == this ? 70 : 30));
painter->drawRect(widgetRect);
}
}
auto textColor = QColor(this->valueChanged ? "#547fba" : "#afb1b3");
if (this->valueInitialised) {
if (!this->isEnabled()) {
textColor.setAlpha(100);
}
painter->setPen(textColor);
painter->drawText(widgetRect, Qt::AlignCenter, this->hexValue);
} else {
textColor.setAlpha(100);
painter->setPen(textColor);
static const auto placeholderString = QString("??");
painter->drawText(widgetRect, Qt::AlignCenter, placeholderString);
}
}

View File

@@ -2,16 +2,15 @@
#include <cstdint>
#include <QEvent>
#include <QGraphicsItem>
#include <optional>
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/ClickableWidget.hpp"
namespace Bloom::Widgets
{
class ByteWidget: public ClickableWidget
class ByteItem: public QGraphicsItem
{
Q_OBJECT
public:
static constexpr int WIDTH = 25;
static constexpr int HEIGHT = 20;
@@ -29,35 +28,34 @@ namespace Bloom::Widgets
std::size_t currentRowIndex = 0;
std::size_t currentColumnIndex = 0;
ByteWidget(
ByteItem(
std::size_t byteNumber,
std::uint32_t address,
std::optional<ByteWidget*>& hoveredByteWidget,
QWidget* parent
std::optional<ByteItem*>& hoveredByteItem
);
void setValue(unsigned char value);
public slots:
void setSelected(bool selected);
[[nodiscard]] QRectF boundingRect() const override {
return QRectF(
0,
0,
ByteItem::WIDTH,
ByteItem::HEIGHT
);
}
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
signals:
void selected(Bloom::Widgets::ByteWidget*);
void enter(Bloom::Widgets::ByteWidget*);
void leave(Bloom::Widgets::ByteWidget*);
protected:
virtual void postSetSelected(bool selected) {};
bool event(QEvent* event) override;
void paintEvent(QPaintEvent* event) override;
void drawWidget(QPainter& painter);
void selected(Bloom::Widgets::ByteItem*);
void enter(Bloom::Widgets::ByteItem*);
void leave(Bloom::Widgets::ByteItem*);
private:
bool hoverActive = false;
bool valueChanged = false;
QString hexValue;
std::optional<QString> asciiValue;
std::optional<ByteWidget*>& hoveredByteWidget;
std::optional<ByteItem*>& hoveredByteItem;
};
}

View File

@@ -0,0 +1,41 @@
#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,
InsightWorker& insightWorker,
QLabel* hoveredAddressLabel,
QWidget* parent
): QGraphicsView(parent) {
this->setObjectName("graphics-view");
this->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
this->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded);
this->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
this->scene = new ByteItemGraphicsScene(
targetMemoryDescriptor,
insightWorker,
hoveredAddressLabel,
this
);
this->setScene(this->scene);
}
void ByteItemContainerGraphicsView::resizeEvent(QResizeEvent* event) {
Logger::warning("Resizing");
this->scene->adjustByteWidgets();
}

View File

@@ -0,0 +1,47 @@
#pragma once
#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"
#include "ByteItemGraphicsScene.hpp"
namespace Bloom::Widgets
{
class ByteItemContainerGraphicsView: public QGraphicsView
{
Q_OBJECT
public:
ByteItemContainerGraphicsView(
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
InsightWorker& insightWorker,
QLabel* hoveredAddressLabel,
QWidget* parent
);
[[nodiscard]] ByteItemGraphicsScene* getScene() const {
return this->scene;
}
protected:
void resizeEvent(QResizeEvent* event) override;
private:
ByteItemGraphicsScene* scene = nullptr;
};
}

View File

@@ -1,4 +1,4 @@
#include "ByteWidgetContainer.hpp"
#include "ByteItemGraphicsScene.hpp"
#include <QVBoxLayout>
#include <QTableWidget>
@@ -6,30 +6,24 @@
#include <QPainter>
#include <cmath>
#include "src/Logger/Logger.hpp"
using namespace Bloom::Widgets;
using namespace Bloom::Exceptions;
using Bloom::Targets::TargetMemoryDescriptor;
ByteWidgetContainer::ByteWidgetContainer(
ByteItemGraphicsScene::ByteItemGraphicsScene(
const TargetMemoryDescriptor& targetMemoryDescriptor,
InsightWorker& insightWorker,
QLabel* hoveredAddressLabel,
QWidget* parent
): QWidget(parent),
): QGraphicsScene(parent),
targetMemoryDescriptor(targetMemoryDescriptor),
insightWorker(insightWorker),
hoveredAddressLabel(hoveredAddressLabel),
parent(parent) {
this->setObjectName("byte-widget-container");
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Ignored);
this->setContentsMargins(
10,
10,
10,
10
);
/*
* Construct ByteWidget objects
@@ -38,49 +32,45 @@ parent(parent) {
*/
const auto memorySize = this->targetMemoryDescriptor.size();
const auto startAddress = this->targetMemoryDescriptor.addressRange.startAddress;
Logger::error("Constructing bytes begin");
for (std::size_t i = 0; i < memorySize; i++) {
const auto address = static_cast<std::uint32_t>(startAddress + i);
auto byteWidget = new ByteWidget(i, address, this->hoveredByteWidget, this);
auto byteWidget = new ByteItem(i, address, this->hoveredByteWidget);
this->byteWidgetsByAddress.insert(std::pair(
address,
byteWidget
));
QObject::connect(byteWidget, &ByteWidget::enter, this, &ByteWidgetContainer::onByteWidgetEnter);
QObject::connect(byteWidget, &ByteWidget::leave, this, &ByteWidgetContainer::onByteWidgetLeave);
this->addItem(byteWidget);
}
Logger::error("Constructing bytes end");
this->adjustByteWidgets();
QObject::connect(
&insightWorker,
&InsightWorker::targetStateUpdated,
this,
&ByteWidgetContainer::onTargetStateChanged
&ByteItemGraphicsScene::onTargetStateChanged
);
this->show();
}
void ByteWidgetContainer::updateValues(const Targets::TargetMemoryBuffer& buffer) {
void ByteItemGraphicsScene::updateValues(const Targets::TargetMemoryBuffer& buffer) {
for (auto& [address, byteWidget] : this->byteWidgetsByAddress) {
byteWidget->setValue(buffer.at(byteWidget->byteIndex));
byteWidget->update();
}
}
void ByteWidgetContainer::resizeEvent(QResizeEvent* event) {
this->adjustByteWidgets();
}
void ByteItemGraphicsScene::adjustByteWidgets() {
std::map<std::size_t, std::vector<ByteItem*>> byteWidgetsByRowIndex;
std::map<std::size_t, std::vector<ByteItem*>> byteWidgetsByColumnIndex;
void ByteWidgetContainer::adjustByteWidgets() {
std::map<std::size_t, std::vector<ByteWidget*>> byteWidgetsByRowIndex;
std::map<std::size_t, std::vector<ByteWidget*>> byteWidgetsByColumnIndex;
const auto margins = QMargins(10, 10, 10, 10);
const auto width = std::max(600, static_cast<int>(this->parent->width()));
const auto margins = this->contentsMargins();
const auto width = this->width();
constexpr auto byteWidgetWidth = ByteWidget::WIDTH + ByteWidget::RIGHT_MARGIN;
constexpr auto byteWidgetHeight = ByteWidget::HEIGHT + ByteWidget::BOTTOM_MARGIN;
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()) / byteWidgetWidth)
);
@@ -97,12 +87,10 @@ void ByteWidgetContainer::adjustByteWidgets() {
- (std::floor(byteWidget->byteIndex / rowCapacity) * static_cast<double>(rowCapacity))
);
byteWidget->setGeometry(QRect(
byteWidget->setPos(
static_cast<int>(columnIndex * byteWidgetWidth + static_cast<std::size_t>(margins.left())),
static_cast<int>(rowIndex * byteWidgetHeight + static_cast<std::size_t>(margins.top())),
ByteWidget::WIDTH,
ByteWidget::HEIGHT
));
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);
@@ -114,8 +102,9 @@ void ByteWidgetContainer::adjustByteWidgets() {
}
const auto minHeight = (rowCount * byteWidgetHeight) + margins.top() + margins.bottom();
this->setMinimumHeight(minHeight);
this->parent->setMinimumHeight(minHeight);
// this->setMinimumHeight(minHeight);
this->setSceneRect(0, 0, width, minHeight);
// this->parent->setMinimumHeight(minHeight);
this->byteWidgetsByRowIndex = std::move(byteWidgetsByRowIndex);
this->byteWidgetsByColumnIndex = std::move(byteWidgetsByColumnIndex);
@@ -123,12 +112,22 @@ void ByteWidgetContainer::adjustByteWidgets() {
emit this->byteWidgetsAdjusted();
}
void ByteWidgetContainer::onTargetStateChanged(Targets::TargetState newState) {
void ByteItemGraphicsScene::onTargetStateChanged(Targets::TargetState newState) {
using Targets::TargetState;
this->targetState = newState;
}
void ByteWidgetContainer::onByteWidgetEnter(ByteWidget* widget) {
void ByteItemGraphicsScene::onByteWidgetEnter(ByteItem* widget) {
if (this->hoveredByteWidget.has_value()) {
if (this->hoveredByteWidget.value() == widget) {
// This byte item is already marked as hovered
return;
} else {
this->onByteWidgetLeave();
}
}
this->hoveredByteWidget = widget;
this->hoveredAddressLabel->setText(
@@ -146,18 +145,33 @@ void ByteWidgetContainer::onByteWidgetEnter(ByteWidget* widget) {
}
}
void ByteWidgetContainer::onByteWidgetLeave(ByteWidget* widget) {
void ByteItemGraphicsScene::onByteWidgetLeave() {
const auto byteItem = this->hoveredByteWidget.value();
this->hoveredByteWidget = std::nullopt;
this->hoveredAddressLabel->setText("Relative Address (Absolute Address):");
if (!this->byteWidgetsByRowIndex.empty()) {
for (auto& byteWidget : this->byteWidgetsByColumnIndex.at(widget->currentColumnIndex)) {
for (auto& byteWidget : this->byteWidgetsByColumnIndex.at(byteItem->currentColumnIndex)) {
byteWidget->update();
}
for (auto& byteWidget : this->byteWidgetsByRowIndex.at(widget->currentRowIndex)) {
for (auto& byteWidget : this->byteWidgetsByRowIndex.at(byteItem->currentRowIndex)) {
byteWidget->update();
}
}
}
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);
}
} else if (this->hoveredByteWidget.has_value()) {
this->onByteWidgetLeave();
}
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include <QGraphicsScene>
#include <QWidget>
#include <QLabel>
#include <QToolButton>
@@ -8,7 +9,7 @@
#include <vector>
#include <QSize>
#include <QString>
#include <QEvent>
#include <QGraphicsSceneMouseEvent>
#include <optional>
#include "src/Targets/TargetMemory.hpp"
@@ -16,22 +17,22 @@
#include "src/Insight/InsightWorker/InsightWorker.hpp"
#include "ByteWidget.hpp"
#include "ByteItem.hpp"
namespace Bloom::Widgets
{
class ByteWidgetContainer: public QWidget
class ByteItemGraphicsScene: public QGraphicsScene
{
Q_OBJECT
public:
std::optional<ByteWidget*> hoveredByteWidget;
std::optional<ByteItem*> hoveredByteWidget;
std::map<std::uint32_t, ByteWidget*> byteWidgetsByAddress;
std::map<std::size_t, std::vector<ByteWidget*>> byteWidgetsByRowIndex;
std::map<std::size_t, std::vector<ByteWidget*>> byteWidgetsByColumnIndex;
std::map<std::uint32_t, ByteItem*> byteWidgetsByAddress;
std::map<std::size_t, std::vector<ByteItem*>> byteWidgetsByRowIndex;
std::map<std::size_t, std::vector<ByteItem*>> byteWidgetsByColumnIndex;
ByteWidgetContainer(
ByteItemGraphicsScene(
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
InsightWorker& insightWorker,
QLabel* hoveredAddressLabel,
@@ -40,11 +41,13 @@ namespace Bloom::Widgets
void updateValues(const Targets::TargetMemoryBuffer& buffer);
void adjustByteWidgets();
signals:
void byteWidgetsAdjusted();
protected:
void resizeEvent(QResizeEvent* event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent) override;
private:
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor;
@@ -54,11 +57,9 @@ namespace Bloom::Widgets
QWidget* parent = nullptr;
QLabel* hoveredAddressLabel = nullptr;
void adjustByteWidgets();
private slots:
void onTargetStateChanged(Targets::TargetState newState);
void onByteWidgetEnter(Bloom::Widgets::ByteWidget* widget);
void onByteWidgetLeave(Bloom::Widgets::ByteWidget* widget);
void onByteWidgetEnter(Bloom::Widgets::ByteItem* widget);
void onByteWidgetLeave();
};
}

View File

@@ -1,114 +0,0 @@
#include "ByteWidget.hpp"
#include <QPainter>
#include <QStyle>
using namespace Bloom::Widgets;
ByteWidget::ByteWidget(
std::size_t byteIndex,
std::uint32_t address,
std::optional<ByteWidget*>& hoveredByteWidget,
QWidget* parent
): ClickableWidget(parent), byteIndex(byteIndex), address(address), hoveredByteWidget(hoveredByteWidget) {
this->setObjectName("byte");
auto onClick = [this] {
this->setSelected(true);
};
this->addressHex = "0x" + QString::number(this->address, 16).rightJustified(8, '0').toUpper();
this->relativeAddressHex = "0x" + QString::number(this->byteIndex, 16).rightJustified(8, '0').toUpper();
QObject::connect(this, &ClickableWidget::clicked, this, onClick);
QObject::connect(this, &ClickableWidget::rightClicked, this, onClick);
this->setSelected(false);
}
void ByteWidget::setValue(unsigned char value) {
this->valueChanged = this->valueInitialised && this->value != value;
this->value = value;
this->hexValue = QString::number(this->value, 16).rightJustified(2, '0').toUpper();
this->asciiValue = (this->value >= 32 && this->value <= 126)
? std::optional(QString(QChar(this->value))) : std::nullopt;
this->valueInitialised = true;
}
void ByteWidget::setSelected(bool selected) {
this->setProperty("selected", selected);
this->style()->unpolish(this);
this->style()->polish(this);
if (selected) {
emit this->selected(this);
}
this->postSetSelected(selected);
}
bool ByteWidget::event(QEvent* event) {
if (this->isEnabled()) {
switch (event->type()) {
case QEvent::Enter: {
this->hoverActive = true;
emit this->enter(this);
this->update();
break;
}
case QEvent::Leave: {
this->hoverActive = false;
emit this->leave(this);
this->update();
break;
}
default: {
break;
}
}
}
return QWidget::event(event);
}
void ByteWidget::paintEvent(QPaintEvent* event) {
auto painter = QPainter(this);
this->drawWidget(painter);
}
void ByteWidget::drawWidget(QPainter& painter) {
painter.setRenderHints(QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform, true);
painter.setPen(Qt::PenStyle::NoPen);
static const auto widgetRect = QRect(0, 0, ByteWidget::WIDTH, ByteWidget::HEIGHT);
if (this->hoveredByteWidget.has_value()
&& (
this->hoveredByteWidget.value()->currentColumnIndex == this->currentColumnIndex
|| this->hoveredByteWidget.value()->currentRowIndex == this->currentRowIndex
)
) {
painter.setBrush(QColor(0x8E, 0x8B, 0x83, this->hoverActive ? 70 : 30));
painter.drawRect(widgetRect);
}
auto textColor = QColor(this->valueChanged ? "#547fba" : "#afb1b3");
if (this->valueInitialised) {
if (!this->isEnabled()) {
textColor.setAlpha(100);
}
painter.setPen(textColor);
painter.drawText(widgetRect, Qt::AlignCenter, this->hexValue);
} else {
textColor.setAlpha(100);
painter.setPen(textColor);
static const auto placeholderString = QString("??");
painter.drawText(widgetRect, Qt::AlignCenter, placeholderString);
}
}

View File

@@ -1,7 +1,6 @@
#include "HexViewerWidget.hpp"
#include <QVBoxLayout>
#include <QTableWidget>
#include <QScrollBar>
#include <QScrollArea>
#include <QPainter>
@@ -11,6 +10,7 @@
#include "src/Helpers/Paths.hpp"
#include "src/Exceptions/Exception.hpp"
#include "src/Logger/Logger.hpp"
using namespace Bloom::Widgets;
using namespace Bloom::Exceptions;
@@ -53,35 +53,19 @@ HexViewerWidget::HexViewerWidget(
this->hoveredAddressLabel = this->bottomBar->findChild<QLabel*>("byte-address-label");
this->byteWidgetScrollArea = this->container->findChild<QScrollArea*>("byte-widget-scroll-area");
auto byteWidgetScrollAreaWidgetContainer = this->byteWidgetScrollArea->findChild<QWidget*>(
"byte-widget-scroll-area-container"
auto byteItemGraphicsViewContainer = this->container->findChild<QWidget*>("graphics-view-container");
auto byteItemGraphicsViewLayout = byteItemGraphicsViewContainer->findChild<QVBoxLayout*>(
"byte-item-container-layout"
);
auto byteWidgetScrollAreaHorizontalLayout = byteWidgetScrollAreaWidgetContainer->findChild<QHBoxLayout*>(
"byte-widget-scroll-area-horizontal-layout"
);
this->byteWidgetContainer = new ByteWidgetContainer(
this->byteItemGraphicsView = new ByteItemContainerGraphicsView(
targetMemoryDescriptor,
insightWorker,
this->hoveredAddressLabel,
byteWidgetScrollAreaHorizontalLayout->parentWidget()
byteItemGraphicsViewContainer
);
this->byteItemGraphicsScene = this->byteItemGraphicsView->getScene();
byteItemGraphicsViewLayout->insertWidget(0, this->byteItemGraphicsView);
byteWidgetScrollAreaHorizontalLayout->addWidget(this->byteWidgetContainer);
this->byteWidgetAddressContainer = byteWidgetScrollAreaWidgetContainer->findChild<QWidget*>(
"address-container"
);
this->byteWidgetAddressLayout = this->byteWidgetAddressContainer->findChild<QVBoxLayout*>();
this->byteWidgetAddressLayout->setContentsMargins(5, 10, 0, 5);
QObject::connect(
this->byteWidgetContainer,
&ByteWidgetContainer::byteWidgetsAdjusted,
this,
&HexViewerWidget::onByteWidgetsAdjusted
);
QObject::connect(
&insightWorker,
&InsightWorker::targetStateUpdated,
@@ -93,7 +77,7 @@ HexViewerWidget::HexViewerWidget(
}
void HexViewerWidget::updateValues(const Targets::TargetMemoryBuffer& buffer) {
this->byteWidgetContainer->updateValues(buffer);
this->byteItemGraphicsScene->updateValues(buffer);
}
void HexViewerWidget::resizeEvent(QResizeEvent* event) {
@@ -109,36 +93,36 @@ void HexViewerWidget::onTargetStateChanged(Targets::TargetState newState) {
}
void HexViewerWidget::onByteWidgetsAdjusted() {
const auto& byteWidgetsByRowIndex = this->byteWidgetContainer->byteWidgetsByRowIndex;
int layoutItemMaxIndex = this->byteWidgetAddressLayout->count() - 1;
for (const auto& mappingPair : byteWidgetsByRowIndex) {
const auto rowIndex = static_cast<int>(mappingPair.first);
const auto& byteWidgets = mappingPair.second;
if (byteWidgets.empty()) {
continue;
}
QLabel* labelWidget;
if (rowIndex > layoutItemMaxIndex) {
labelWidget = new QLabel(this->byteWidgetAddressContainer);
labelWidget->setFixedSize(75, 20);
labelWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
this->byteWidgetAddressLayout->addWidget(labelWidget);
layoutItemMaxIndex++;
} else {
labelWidget = qobject_cast<QLabel*>(this->byteWidgetAddressLayout->itemAt(rowIndex)->widget());
}
labelWidget->setText(byteWidgets.front()->relativeAddressHex);
}
const auto rowCount = static_cast<int>(byteWidgetsByRowIndex.size());
QLayoutItem* labelItem;
while ((labelItem = this->byteWidgetAddressLayout->takeAt(rowCount)) != nullptr) {
labelItem->widget()->deleteLater();
}
// const auto& byteWidgetsByRowIndex = this->byteWidgetContainer->byteWidgetsByRowIndex;
//
// int layoutItemMaxIndex = this->byteWidgetAddressLayout->count() - 1;
// for (const auto& mappingPair : byteWidgetsByRowIndex) {
// const auto rowIndex = static_cast<int>(mappingPair.first);
// const auto& byteWidgets = mappingPair.second;
//
// if (byteWidgets.empty()) {
// continue;
// }
//
// QLabel* labelWidget;
// if (rowIndex > layoutItemMaxIndex) {
// labelWidget = new QLabel(this->byteWidgetAddressContainer);
// labelWidget->setFixedSize(75, 20);
// labelWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
//
// this->byteWidgetAddressLayout->addWidget(labelWidget);
// layoutItemMaxIndex++;
//
// } else {
// labelWidget = qobject_cast<QLabel*>(this->byteWidgetAddressLayout->itemAt(rowIndex)->widget());
// }
//
// labelWidget->setText(byteWidgets.front()->relativeAddressHex);
// }
//
// const auto rowCount = static_cast<int>(byteWidgetsByRowIndex.size());
// QLayoutItem* labelItem;
// while ((labelItem = this->byteWidgetAddressLayout->takeAt(rowCount)) != nullptr) {
// labelItem->widget()->deleteLater();
// }
}

View File

@@ -2,7 +2,7 @@
#include <QWidget>
#include <QLabel>
#include <QToolButton>
#include <QGraphicsView>
#include <QVBoxLayout>
#include <set>
#include <map>
@@ -16,7 +16,7 @@
#include "src/Insight/InsightWorker/InsightWorker.hpp"
#include "ByteWidgetContainer.hpp"
#include "ByteItemContainerGraphicsView.hpp"
namespace Bloom::Widgets
{
@@ -46,7 +46,8 @@ namespace Bloom::Widgets
QWidget* toolBar = nullptr;
QWidget* bottomBar = nullptr;
ByteWidgetContainer* byteWidgetContainer = nullptr;
ByteItemContainerGraphicsView* byteItemGraphicsView = nullptr;
ByteItemGraphicsScene* byteItemGraphicsScene = nullptr;
QWidget* byteWidgetScrollArea = nullptr;
QWidget* byteWidgetAddressContainer = nullptr;
QVBoxLayout* byteWidgetAddressLayout = nullptr;

View File

@@ -53,55 +53,17 @@
</widget>
</item>
<item>
<widget class="ExpandingHeightScrollAreaWidget" name="byte-widget-scroll-area">
<property name="widgetResizable"><bool>true</bool></property>
<property name="verticalScrollBarPolicy"><enum>Qt::ScrollBarAsNeeded</enum></property>
<property name="sizeAdjustPolicy"><enum>QAbstractScrollArea::AdjustToContents</enum></property>
<!-- <property name="horizontalScrollBarPolicy"><enum>Qt::ScrollBarAlwaysOff</enum></property>-->
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"/>
</property>
<widget class="QWidget" name="byte-widget-scroll-area-container">
<widget class="QWidget" name="graphics-view-container">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Ignored"/>
</property>
<layout class="QVBoxLayout" name="byte-widget-scroll-area-vertical-layout">
<layout class="QVBoxLayout" name="byte-item-container-layout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="byte-widget-scroll-area-horizontal-layout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="address-container">
<property name="minimumWidth">
<number>85</number>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Ignored"/>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>5</number>
</property>
<property name="margin">
<number>0</number>
</property>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="vertical-spacer">
<property name="orientation">
@@ -111,7 +73,6 @@
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QWidget" name="bottom-bar">