New memory region manager window

This commit is contained in:
Nav
2021-12-23 01:26:58 +00:00
parent a6843e5baa
commit 5c97fb76aa
19 changed files with 2417 additions and 18 deletions

View File

@@ -198,6 +198,12 @@ add_executable(Bloom
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteItem.cpp 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/ByteAddressContainer.cpp
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteAddressItem.cpp src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteAddressItem.cpp
# Focused memory region manager window
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/MemoryRegionManagerWindow.cpp
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/RegionItem.cpp
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/FocusedRegionItem.cpp
src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/ExcludedRegionItem.cpp
) )
set_target_properties(Bloom PROPERTIES OUTPUT_NAME bloom) set_target_properties(Bloom PROPERTIES OUTPUT_NAME bloom)

View File

@@ -0,0 +1,40 @@
#include "ExcludedRegionItem.hpp"
#include <QFile>
#include "src/Helpers/Paths.hpp"
#include "src/Exceptions/Exception.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/UiLoader.hpp"
using namespace Bloom;
using namespace Bloom::Widgets;
ExcludedRegionItem::ExcludedRegionItem(
const ExcludedMemoryRegion& region,
QWidget* parent
): memoryRegion(region), RegionItem(region, parent) {
auto formUiFile = QFile(
QString::fromStdString(Paths::compiledResourcesPath()
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane"
+ "/MemoryRegionManager/UiFiles/ExcludedMemoryRegionForm.ui"
)
);
if (!formUiFile.open(QFile::ReadOnly)) {
throw Bloom::Exceptions::Exception("Failed to open excluded region item form UI file");
}
auto uiLoader = UiLoader(this);
this->formWidget = uiLoader.load(&formUiFile, this);
this->initFormInputs();
}
ExcludedMemoryRegion ExcludedRegionItem::generateExcludedMemoryRegionFromInput() {
this->memoryRegion.name = this->nameInput->text();
this->memoryRegion.addressRange.startAddress = this->startAddressInput->text().toUInt(nullptr, 16);
this->memoryRegion.addressRange.endAddress = this->endAddressInput->text().toUInt(nullptr, 16);
this->memoryRegion.addressRangeType = this->getSelectedAddressType();
return this->memoryRegion;
}

View File

@@ -0,0 +1,24 @@
#pragma once
#include "RegionItem.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/ExcludedMemoryRegion.hpp"
namespace Bloom::Widgets
{
class ExcludedRegionItem: public RegionItem
{
Q_OBJECT
public:
ExcludedRegionItem(const ExcludedMemoryRegion& region, QWidget *parent);
[[nodiscard]] const MemoryRegion& getMemoryRegion() const override {
return this->memoryRegion;
};
[[nodiscard]] virtual ExcludedMemoryRegion generateExcludedMemoryRegionFromInput();
private:
ExcludedMemoryRegion memoryRegion;
};
}

View File

@@ -0,0 +1,70 @@
#include "FocusedRegionItem.hpp"
#include <QFile>
#include "src/Helpers/Paths.hpp"
#include "src/Exceptions/Exception.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/UiLoader.hpp"
using namespace Bloom;
using namespace Bloom::Widgets;
FocusedRegionItem::FocusedRegionItem(
const FocusedMemoryRegion& region,
QWidget* parent
): memoryRegion(region), RegionItem(region, parent) {
auto formUiFile = QFile(
QString::fromStdString(Paths::compiledResourcesPath()
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane"
+ "/MemoryRegionManager/UiFiles/FocusedMemoryRegionForm.ui"
)
);
if (!formUiFile.open(QFile::ReadOnly)) {
throw Bloom::Exceptions::Exception("Failed to open focused region item form UI file");
}
auto uiLoader = UiLoader(this);
this->formWidget = uiLoader.load(&formUiFile, this);
this->initFormInputs();
}
FocusedMemoryRegion FocusedRegionItem::generateFocusedMemoryRegionFromInput() {
this->memoryRegion.name = this->nameInput->text();
this->memoryRegion.addressRange.startAddress = this->startAddressInput->text().toUInt(nullptr, 16);
this->memoryRegion.addressRange.endAddress = this->endAddressInput->text().toUInt(nullptr, 16);
this->memoryRegion.addressRangeType = this->getSelectedAddressType();
auto selectedDataTypeOptionName = this->dataTypeInput->currentData().toString();
if (FocusedRegionItem::dataTypeOptionsByName.contains(selectedDataTypeOptionName)) {
this->memoryRegion.dataType = FocusedRegionItem::dataTypeOptionsByName.at(selectedDataTypeOptionName).dataType;
}
return this->memoryRegion;
}
void FocusedRegionItem::initFormInputs() {
RegionItem::initFormInputs();
const auto& region = this->memoryRegion;
this->dataTypeInput = this->formWidget->findChild<QComboBox*>("data-type-input");
for (const auto& [optionName, option] : FocusedRegionItem::dataTypeOptionsByName) {
this->dataTypeInput->addItem(option.text, optionName);
}
switch (region.dataType) {
case MemoryRegionDataType::INTEGER: {
this->dataTypeInput->setCurrentText(FocusedRegionItem::dataTypeOptionsByName.at("integer").text);
break;
}
case MemoryRegionDataType::ASCII_STRING: {
this->dataTypeInput->setCurrentText(FocusedRegionItem::dataTypeOptionsByName.at("ascii").text);
break;
}
default: {
this->dataTypeInput->setCurrentText(FocusedRegionItem::dataTypeOptionsByName.at("other").text);
}
}
}

View File

@@ -0,0 +1,45 @@
#pragma once
#include "RegionItem.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/FocusedMemoryRegion.hpp"
namespace Bloom::Widgets
{
struct DataTypeOption
{
QString text;
MemoryRegionDataType dataType = MemoryRegionDataType::UNKNOWN;
DataTypeOption(const QString& text, MemoryRegionDataType dataType)
: text(text), dataType(dataType) {};
};
class FocusedRegionItem: public RegionItem
{
Q_OBJECT
public:
FocusedRegionItem(const FocusedMemoryRegion& region, QWidget *parent);
[[nodiscard]] const MemoryRegion& getMemoryRegion() const override {
return this->memoryRegion;
};
[[nodiscard]] virtual FocusedMemoryRegion generateFocusedMemoryRegionFromInput();
protected:
void initFormInputs() override;
private:
FocusedMemoryRegion memoryRegion;
QComboBox* dataTypeInput = nullptr;
static inline const std::map<QString, DataTypeOption> dataTypeOptionsByName = std::map<
QString, DataTypeOption
>({
{"other", DataTypeOption("Other", MemoryRegionDataType::UNKNOWN)},
{"integer", DataTypeOption("Integer", MemoryRegionDataType::INTEGER)},
{"ascii", DataTypeOption("ASCII String", MemoryRegionDataType::ASCII_STRING)},
});
};
}

View File

@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 4.2333334 4.2333333"
version="1.1"
id="svg974"
sodipodi:docname="add-region.svg"
inkscape:version="1.0.1 (1.0.1+r75)">
<defs
id="defs968" />
<sodipodi:namedview
id="base"
pagecolor="#343532"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="11.211368"
inkscape:cy="6.5583178"
inkscape:document-units="px"
inkscape:current-layer="layer2"
inkscape:document-rotation="0"
showgrid="false"
units="px"
inkscape:snap-page="true"
inkscape:window-width="3440"
inkscape:window-height="1353"
inkscape:window-x="2560"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-bbox-edge-midpoints="true" />
<metadata
id="metadata971">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Main"
style="display:inline">
<rect
style="fill:#8f8c84;fill-opacity:1;stroke-width:0.0520832"
id="rect1537-3-6"
width="0.52916664"
height="1.0583333"
x="1.8520833"
y="0.79375011" />
<rect
style="display:inline;fill:#8f8c84;fill-opacity:1;stroke-width:0.0520832"
id="rect1537-3-6-3"
width="0.52916664"
height="1.0583333"
x="1.8520833"
y="2.3812499" />
<rect
style="display:inline;fill:#8f8c84;fill-opacity:1;stroke-width:0.0823503"
id="rect1537-3-6-3-6"
width="2.6458333"
height="0.52916664"
x="0.79375005"
y="1.8520834" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="65"
height="54"
viewBox="0 0 17.197917 14.2875"
version="1.1"
id="svg974"
sodipodi:docname="icon.svg"
inkscape:version="1.0.1 (1.0.1+r75)">
<defs
id="defs968" />
<sodipodi:namedview
id="base"
pagecolor="#343532"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="11.2"
inkscape:cx="74.919115"
inkscape:cy="39.986431"
inkscape:document-units="px"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
units="px"
inkscape:snap-page="true"
inkscape:window-width="3440"
inkscape:window-height="1353"
inkscape:window-x="2560"
inkscape:window-y="34"
inkscape:window-maximized="1"
fit-margin-top="6"
fit-margin-left="6"
fit-margin-right="6"
fit-margin-bottom="6"
lock-margins="true" />
<metadata
id="metadata971">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(1.3229167,1.0583334)">
<rect
style="fill:#7b5e38;fill-opacity:1;stroke-width:0.318943"
id="rect1537"
width="6.6145835"
height="3.175"
x="0.26458332"
y="0.52916664" />
<rect
style="fill:#908d85;fill-opacity:0.9958061;stroke-width:0.318943"
id="rect1537-5"
width="6.6145835"
height="3.175"
x="7.6729169"
y="0.52916664" />
<rect
style="fill:#908d85;fill-opacity:0.9958061;stroke-width:0.318942"
id="rect1537-6"
width="6.6145835"
height="3.175"
x="0.26458332"
y="4.4979167" />
<rect
style="fill:#908d85;fill-opacity:0.9958061;stroke-width:0.318942"
id="rect1537-5-2"
width="6.6145825"
height="3.175"
x="7.6729178"
y="4.4979167" />
<rect
style="fill:#908d85;fill-opacity:0.9958061;stroke-width:0.318942"
id="rect1537-6-9"
width="6.6145835"
height="3.175"
x="0.26458332"
y="8.4666672" />
<rect
style="fill:#7b5e38;fill-opacity:1;stroke-width:0.318942"
id="rect1537-5-2-1"
width="6.6145825"
height="3.175"
x="7.6729169"
y="8.4666672" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
viewBox="0 0 4.2333334 4.2333333"
version="1.1"
id="svg974"
sodipodi:docname="remove-region.svg"
inkscape:version="1.0.1 (1.0.1+r75)">
<defs
id="defs968" />
<sodipodi:namedview
id="base"
pagecolor="#343532"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="11.211368"
inkscape:cy="6.5583178"
inkscape:document-units="px"
inkscape:current-layer="layer2"
inkscape:document-rotation="0"
showgrid="false"
units="px"
inkscape:snap-page="true"
inkscape:window-width="3440"
inkscape:window-height="1353"
inkscape:window-x="2560"
inkscape:window-y="34"
inkscape:window-maximized="1"
inkscape:snap-smooth-nodes="true"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-bbox-edge-midpoints="true" />
<metadata
id="metadata971">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Main"
style="display:inline">
<rect
style="display:inline;fill:#8f8c84;fill-opacity:1;stroke-width:0.0823503"
id="rect1537-3-6-3-6"
width="2.6458333"
height="0.52916664"
x="0.79375005"
y="1.8520834" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,391 @@
#include "MemoryRegionManagerWindow.hpp"
#include <QFile>
#include <QSize>
#include <QDesktopServices>
#include "src/Insight/UserInterfaces/InsightWindow/UiLoader.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/ErrorDialogue/ErrorDialogue.hpp"
#include "src/Helpers/Paths.hpp"
#include "src/Exceptions/Exception.hpp"
using namespace Bloom;
using namespace Bloom::Widgets;
using Bloom::Exceptions::Exception;
MemoryRegionManagerWindow::MemoryRegionManagerWindow(
const Targets::TargetMemoryDescriptor& memoryDescriptor,
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
QWidget* parent
):
QWidget(parent),
memoryDescriptor(memoryDescriptor),
focusedMemoryRegions(focusedMemoryRegions),
excludedMemoryRegions(excludedMemoryRegions)
{
this->setWindowFlag(Qt::Window);
this->setObjectName("memory-region-manager-window");
this->setWindowTitle(
"Memory Regions - "
+ QString(this->memoryDescriptor.type == Targets::TargetMemoryType::EEPROM ? "EEPROM" : "RAM")
);
auto windowUiFile = QFile(
QString::fromStdString(Paths::compiledResourcesPath()
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane"
+ "/MemoryRegionManager/UiFiles/MemoryRegionManagerWindow.ui"
)
);
auto windowStylesheet = QFile(
QString::fromStdString(Paths::compiledResourcesPath()
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane"
+ "/MemoryRegionManager/Stylesheets/MemoryRegionManagerWindow.qss"
)
);
if (!windowUiFile.open(QFile::ReadOnly)) {
throw Exception("Failed to open MemoryRegionManagerWindow UI file");
}
if (!windowStylesheet.open(QFile::ReadOnly)) {
throw Exception("Failed to open MemoryRegionManagerWindow stylesheet file");
}
this->setStyleSheet(windowStylesheet.readAll());
this->setFixedSize(QSize(860, 470));
auto uiLoader = UiLoader(this);
this->container = uiLoader.load(&windowUiFile, this);
this->container->setFixedSize(this->size());
this->container->setContentsMargins(0, 0, 0, 0);
this->regionSelector = this->container->findChild<QWidget*>("region-selector");
auto* regionSelectorToolBar = this->regionSelector->findChild<QWidget*>("region-selector-tool-bar");
this->addRegionButton = this->regionSelector->findChild<SvgToolButton*>("add-region-btn");
this->removeRegionButton = this->regionSelector->findChild<SvgToolButton*>("remove-region-btn");
this->addFocusedRegionMenuAction = this->addRegionButton->findChild<QAction*>("add-focused-region");
this->addExcludedRegionMenuAction = this->addRegionButton->findChild<QAction*>("add-excluded-region");
this->regionItemScrollArea = this->regionSelector->findChild<QScrollArea*>("region-item-scroll-area");
this->regionItemScrollAreaViewport = this->regionItemScrollArea->findChild<QWidget*>("item-container");
this->regionItemScrollAreaViewportLayout = this->regionItemScrollAreaViewport->findChild<QVBoxLayout*>(
"item-container-layout"
);
this->stackedFormLayout = this->container->findChild<QStackedLayout*>("stacked-form-layout");
this->applyButton = this->container->findChild<QPushButton*>("apply-btn");
this->helpButton = this->container->findChild<QPushButton*>("help-btn");
this->closeButton = this->container->findChild<QPushButton*>("close-btn");
regionSelectorToolBar->setContentsMargins(0, 0, 0, 0);
this->regionItemScrollArea->setContentsMargins(0, 0, 0, 0);
this->regionItemScrollAreaViewport->setContentsMargins(0, 0, 0, 0);
this->regionItemScrollAreaViewportLayout->setContentsMargins(0, 0, 0, 0);
this->regionItemScrollAreaViewportLayout->setDirection(QBoxLayout::Direction::TopToBottom);
QObject::connect(
this->addFocusedRegionMenuAction,
&QAction::triggered,
this,
&MemoryRegionManagerWindow::onNewFocusedRegionTrigger
);
QObject::connect(
this->addExcludedRegionMenuAction,
&QAction::triggered,
this,
&MemoryRegionManagerWindow::onNewExcludedRegionTrigger
);
QObject::connect(
this->removeRegionButton,
&QToolButton::clicked,
this,
&MemoryRegionManagerWindow::onDeleteRegionTrigger
);
QObject::connect(this->closeButton, &QPushButton::clicked, this, &QWidget::close);
QObject::connect(this->applyButton, &QPushButton::clicked, this, &MemoryRegionManagerWindow::applyChanges);
QObject::connect(this->helpButton, &QPushButton::clicked, this, &MemoryRegionManagerWindow::openHelpPage);
this->refreshRegions();
// Position the inspection window at the center of the main Insight window
this->move(parent->window()->geometry().center() - this->rect().center());
this->show();
}
void MemoryRegionManagerWindow::refreshRegions() {
this->clearRegions();
for (const auto& focusedRegion: this->focusedMemoryRegions) {
this->addFocusedRegion(focusedRegion);
}
for (const auto& excludedRegion: this->excludedMemoryRegions) {
this->addExcludedRegion(excludedRegion);
}
this->sortRegionItems();
}
void MemoryRegionManagerWindow::showEvent(QShowEvent* event) {
if (this->selectedRegion == nullptr && this->regionItemScrollAreaViewportLayout->count() > 0) {
auto* firstRegionItem = qobject_cast<RegionItem*>(
this->regionItemScrollAreaViewportLayout->itemAt(0)->widget()
);
if (firstRegionItem != nullptr) {
firstRegionItem->setSelected(true);
}
}
}
void MemoryRegionManagerWindow::clearRegions() {
this->selectedRegion = nullptr;
for (auto* focusedRegionItem: this->focusedRegionItems) {
this->regionItemScrollAreaViewportLayout->removeWidget(focusedRegionItem);
focusedRegionItem->getFormWidget()->deleteLater();
focusedRegionItem->deleteLater();
}
for (auto* excludedRegionItem: this->excludedRegionItems) {
this->regionItemScrollAreaViewportLayout->removeWidget(excludedRegionItem);
excludedRegionItem->getFormWidget()->deleteLater();
excludedRegionItem->deleteLater();
}
this->focusedRegionItems.clear();
this->excludedRegionItems.clear();
}
void MemoryRegionManagerWindow::sortRegionItems() {
/*
* This isn't very pretty.
*
* Because the insertion order is persisted in QBoxLayouts, sorting the items requires removing them from the
* layout, and then re-inserting them in the correct order.
*/
auto regionItemCompare = [] (RegionItem* itemA, RegionItem* itemB) {
return itemA->getMemoryRegion().id < itemB->getMemoryRegion().id;
};
auto sortedRegionItems = std::set<RegionItem*, decltype(regionItemCompare)>(regionItemCompare);
QLayoutItem* layoutItem = nullptr;
while ((layoutItem = this->regionItemScrollAreaViewportLayout->takeAt(0)) != nullptr) {
auto* regionItem = qobject_cast<RegionItem*>(layoutItem->widget());
if (regionItem != nullptr) {
sortedRegionItems.insert(regionItem);
}
delete layoutItem;
}
for (auto* regionItem: sortedRegionItems) {
this->regionItemScrollAreaViewportLayout->addWidget(regionItem);
}
}
FocusedRegionItem* MemoryRegionManagerWindow::addFocusedRegion(const FocusedMemoryRegion& region) {
auto* focusedRegionItem = new FocusedRegionItem(region, this->regionItemScrollAreaViewport);
this->focusedRegionItems.insert(focusedRegionItem);
this->regionItemScrollAreaViewportLayout->addWidget(focusedRegionItem);
this->stackedFormLayout->addWidget(focusedRegionItem->getFormWidget());
QObject::connect(focusedRegionItem, &RegionItem::selected, this, &MemoryRegionManagerWindow::onRegionSelected);
return focusedRegionItem;
}
ExcludedRegionItem* MemoryRegionManagerWindow::addExcludedRegion(const ExcludedMemoryRegion& region) {
auto* excludedRegionItem = new ExcludedRegionItem(region, this->regionItemScrollAreaViewport);
this->excludedRegionItems.insert(excludedRegionItem);
this->regionItemScrollAreaViewportLayout->addWidget(excludedRegionItem);
this->stackedFormLayout->addWidget(excludedRegionItem->getFormWidget());
QObject::connect(excludedRegionItem, &RegionItem::selected, this, &MemoryRegionManagerWindow::onRegionSelected);
return excludedRegionItem;
}
void MemoryRegionManagerWindow::onRegionSelected(RegionItem* selectedRegion) {
if (this->selectedRegion != nullptr && this->selectedRegion != selectedRegion) {
this->selectedRegion->setSelected(false);
}
this->selectedRegion = selectedRegion;
this->stackedFormLayout->setCurrentWidget(this->selectedRegion->getFormWidget());
}
void MemoryRegionManagerWindow::onNewFocusedRegionTrigger() {
using Targets::TargetMemoryAddressRange;
auto* region = this->addFocusedRegion(FocusedMemoryRegion(
"Untitled Region",
this->memoryDescriptor,
TargetMemoryAddressRange(
this->memoryDescriptor.addressRange.startAddress,
this->memoryDescriptor.addressRange.startAddress + 10
)
));
region->setSelected(true);
}
void MemoryRegionManagerWindow::onNewExcludedRegionTrigger() {
using Targets::TargetMemoryAddressRange;
auto* region = this->addExcludedRegion(ExcludedMemoryRegion(
"Untitled Region",
this->memoryDescriptor,
TargetMemoryAddressRange(
this->memoryDescriptor.addressRange.startAddress,
this->memoryDescriptor.addressRange.startAddress + 10
)
));
region->setSelected(true);
}
void MemoryRegionManagerWindow::onDeleteRegionTrigger() {
if (this->selectedRegion == nullptr) {
return;
}
auto* regionItem = this->selectedRegion;
const auto& region = regionItem->getMemoryRegion();
if (region.type == MemoryRegionType::FOCUSED) {
auto* focusedRegionItem = qobject_cast<FocusedRegionItem*>(regionItem);
if (focusedRegionItem != nullptr) {
this->focusedRegionItems.erase(focusedRegionItem);
}
} else {
auto* excludedRegionItem = qobject_cast<ExcludedRegionItem*>(regionItem);
if (excludedRegionItem != nullptr) {
this->excludedRegionItems.erase(excludedRegionItem);
}
}
regionItem->getFormWidget()->deleteLater();
this->regionItemScrollAreaViewportLayout->removeWidget(regionItem);
regionItem->deleteLater();
this->selectedRegion = nullptr;
if (this->regionItemScrollAreaViewportLayout->count() > 0) {
auto* regionItem = qobject_cast<RegionItem*>(
this->regionItemScrollAreaViewportLayout->itemAt(0)->widget()
);
if (regionItem != nullptr) {
regionItem->setSelected(true);
}
}
}
void MemoryRegionManagerWindow::applyChanges() {
auto processedFocusedMemoryRegions = std::vector<FocusedMemoryRegion>();
auto processedExcludedMemoryRegions = std::vector<ExcludedMemoryRegion>();
for (auto* focusedRegionItem : this->focusedRegionItems) {
const auto validationFailures = focusedRegionItem->getValidationFailures();
if (!validationFailures.empty()) {
auto* errorDialogue = new ErrorDialogue(
"Invalid memory region",
"Invalid memory region \"" + focusedRegionItem->getRegionNameInputValue() + "\""
+ "<br/><br/>- " + validationFailures.join("<br/>- "),
this
);
errorDialogue->show();
return;
}
auto focusedRegion = focusedRegionItem->generateFocusedMemoryRegionFromInput();
for (const auto& processedFocusedRegion : processedFocusedMemoryRegions) {
if (processedFocusedRegion.intersectsWith(focusedRegion)) {
auto* errorDialogue = new ErrorDialogue(
"Intersection region found",
"Region \"" + focusedRegionItem->getRegionNameInputValue()
+ "\" intersects with region \"" + processedFocusedRegion.name + "\". "
+ "Regions cannot intersect. Please review the relevant address ranges.",
this
);
errorDialogue->show();
return;
}
}
processedFocusedMemoryRegions.emplace_back(focusedRegion);
}
for (auto* excludedRegionItem : this->excludedRegionItems) {
const auto validationFailures = excludedRegionItem->getValidationFailures();
if (!validationFailures.empty()) {
auto* errorDialogue = new ErrorDialogue(
"Invalid memory region",
"Invalid memory region \"" + excludedRegionItem->getRegionNameInputValue() + "\""
+ "<br/><br/>- " + validationFailures.join("<br/>- "),
this
);
errorDialogue->show();
return;
}
auto excludedRegion = excludedRegionItem->generateExcludedMemoryRegionFromInput();
for (const auto& processedFocusedRegion : processedFocusedMemoryRegions) {
if (processedFocusedRegion.intersectsWith(excludedRegion)) {
auto* errorDialogue = new ErrorDialogue(
"Intersecting region found",
"Region \"" + excludedRegionItem->getRegionNameInputValue()
+ "\" intersects with region \"" + processedFocusedRegion.name + "\". "
+ "Regions cannot intersect. Please review the relevant address ranges.",
this
);
errorDialogue->show();
return;
}
}
for (const auto& processedExcludedRegion : processedExcludedMemoryRegions) {
if (processedExcludedRegion.intersectsWith(excludedRegion)) {
auto* errorDialogue = new ErrorDialogue(
"Intersecting region found",
"Region \"" + excludedRegionItem->getRegionNameInputValue()
+ "\" intersects with region \"" + processedExcludedRegion.name + "\". "
+ "Regions cannot intersect. Please review the relevant address ranges.",
this
);
errorDialogue->show();
return;
}
}
processedExcludedMemoryRegions.emplace_back(excludedRegion);
}
this->focusedMemoryRegions = std::move(processedFocusedMemoryRegions);
this->excludedMemoryRegions = std::move(processedExcludedMemoryRegions);
this->close();
}
void MemoryRegionManagerWindow::openHelpPage() {
QDesktopServices::openUrl(
QUrl(QString::fromStdString(Paths::homeDomainName() + "/docs/manage-memory-regions"))
);
}

View File

@@ -0,0 +1,82 @@
#pragma once
#include <QWidget>
#include <QPushButton>
#include <set>
#include <vector>
#include <QShowEvent>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QStackedLayout>
#include <QAction>
#include "src/Targets/TargetMemory.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"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/SvgToolButton.hpp"
#include "RegionItem.hpp"
#include "FocusedRegionItem.hpp"
#include "ExcludedRegionItem.hpp"
namespace Bloom::Widgets
{
class MemoryRegionManagerWindow: public QWidget
{
Q_OBJECT
public:
explicit MemoryRegionManagerWindow(
const Targets::TargetMemoryDescriptor& memoryDescriptor,
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
QWidget* parent = nullptr
);
void refreshRegions();
protected:
void showEvent(QShowEvent* event) override;
private:
const Targets::TargetMemoryDescriptor& memoryDescriptor;
std::vector<FocusedMemoryRegion>& focusedMemoryRegions;
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions;
QWidget* container = nullptr;
QWidget* regionSelector = nullptr;
QPushButton* applyButton = nullptr;
QPushButton* helpButton = nullptr;
QPushButton* closeButton = nullptr;
SvgToolButton* addRegionButton = nullptr;
QAction* addFocusedRegionMenuAction = nullptr;
QAction* addExcludedRegionMenuAction = nullptr;
SvgToolButton* removeRegionButton = nullptr;
QScrollArea* regionItemScrollArea = nullptr;
QWidget* regionItemScrollAreaViewport = nullptr;
QVBoxLayout* regionItemScrollAreaViewportLayout = nullptr;
QStackedLayout* stackedFormLayout = nullptr;
std::set<FocusedRegionItem*> focusedRegionItems;
std::set<ExcludedRegionItem*> excludedRegionItems;
RegionItem* selectedRegion = nullptr;
void clearRegions();
void sortRegionItems();
FocusedRegionItem* addFocusedRegion(const FocusedMemoryRegion& region);
ExcludedRegionItem* addExcludedRegion(const ExcludedMemoryRegion& region);
void onRegionSelected(RegionItem* selectedRegion);
void onNewFocusedRegionTrigger();
void onNewExcludedRegionTrigger();
void onDeleteRegionTrigger();
void applyChanges();
void openHelpPage();
};
}

View File

@@ -0,0 +1,202 @@
#include "RegionItem.hpp"
#include <QHBoxLayout>
#include <QString>
using namespace Bloom;
using namespace Bloom::Widgets;
RegionItem::RegionItem(
const MemoryRegion& region,
QWidget* parent
): ClickableWidget(parent) {
this->setObjectName("region-item");
this->setFixedHeight(50);
this->layout->setContentsMargins(5, 5, 5, 0);
this->timeLabel->setText(region.createdDate.toString("hh:mm"));
this->timeLabel->setObjectName("time-label");
auto regionName = region.name;
regionName.truncate(RegionItem::NAME_LABEL_MAX_LENGTH);
this->nameLabel->setText(regionName);
this->nameLabel->setObjectName("name-label");
this->typeLabel->setText(region.type == MemoryRegionType::FOCUSED ? "Focused" : "Excluded");
this->typeLabel->setObjectName("type-label");
auto addressRange = region.getAbsoluteAddressRange();
this->addressRangeLabel->setText(
"0x" + QString::number(addressRange.startAddress, 16).toUpper() + QString(" -> ")
+ "0x" + QString::number(addressRange.endAddress, 16).toUpper()
);
this->addressRangeLabel->setObjectName("address-label");
auto* topLabelLayout = new QHBoxLayout();
topLabelLayout->setSpacing(0);
topLabelLayout->setContentsMargins(0, 0, 0, 0);
topLabelLayout->addWidget(this->nameLabel, 0, Qt::AlignmentFlag::AlignLeft);
topLabelLayout->addStretch(1);
topLabelLayout->addWidget(this->typeLabel, 0, Qt::AlignmentFlag::AlignRight);
auto* bottomLabelLayout = new QHBoxLayout();
bottomLabelLayout->setSpacing(0);
bottomLabelLayout->setContentsMargins(0, 0, 0, 0);
bottomLabelLayout->addWidget(this->addressRangeLabel, 0, Qt::AlignmentFlag::AlignLeft);
bottomLabelLayout->addStretch(1);
bottomLabelLayout->addWidget(this->timeLabel, 0, Qt::AlignmentFlag::AlignRight);
this->layout->setSpacing(5);
this->layout->addLayout(topLabelLayout);
this->layout->addLayout(bottomLabelLayout);
this->layout->addStretch(1);
auto onClick = [this] {
this->setSelected(true);
};
QObject::connect(this, &ClickableWidget::clicked, this, onClick);
QObject::connect(this, &ClickableWidget::rightClicked, this, onClick);
this->setSelected(false);
}
void RegionItem::setSelected(bool selected) {
this->setProperty("selected", selected);
this->style()->unpolish(this);
this->style()->polish(this);
if (selected) {
emit this->selected(this);
}
}
QStringList RegionItem::getValidationFailures() const {
auto validationFailures = QStringList();
const auto& memoryDescriptor = this->getMemoryRegion().memoryDescriptor;
if (this->nameInput->text().isEmpty()) {
validationFailures.emplace_back("Missing region name.");
}
bool conversionOk = false;
std::uint32_t startAddress = this->startAddressInput->text().toUInt(&conversionOk, 16);
if (!conversionOk) {
validationFailures.emplace_back("Invalid start address.");
}
std::uint32_t endAddress = this->endAddressInput->text().toUInt(&conversionOk, 16);
if (!conversionOk) {
validationFailures.emplace_back("Invalid end address.");
}
if (startAddress > endAddress) {
validationFailures.emplace_back("The start address exceeds the end address.");
}
auto addressType = this->getSelectedAddressType();
const auto memoryAddressRange = memoryDescriptor.addressRange;
const auto memoryAddressRangeStr = QString(
"0x" + QString::number(memoryAddressRange.startAddress, 16).toUpper() + QString(" -> ")
+ "0x" + QString::number(memoryAddressRange.endAddress, 16).toUpper()
);
std::uint32_t absoluteStartAddress = addressType == MemoryRegionAddressType::RELATIVE ?
memoryAddressRange.startAddress + startAddress : startAddress;
std::uint32_t absoluteEndAddress = addressType == MemoryRegionAddressType::RELATIVE ?
memoryAddressRange.startAddress + endAddress : endAddress;
if (absoluteStartAddress < memoryAddressRange.startAddress
|| absoluteStartAddress > memoryAddressRange.endAddress
) {
validationFailures.emplace_back(
"The start address is not within the absolute memory address range (" + memoryAddressRangeStr + ")."
);
}
if (absoluteEndAddress < memoryAddressRange.startAddress || absoluteEndAddress > memoryAddressRange.endAddress) {
validationFailures.emplace_back(
"The end address not within the absolute memory address range (" + memoryAddressRangeStr + ")."
);
}
return validationFailures;
}
void RegionItem::initFormInputs() {
const auto& region = this->getMemoryRegion();
this->nameInput = this->formWidget->findChild<TextInput*>("name-input");
this->addressTypeInput = this->formWidget->findChild<QComboBox*>("address-type-input");
this->startAddressInput = this->formWidget->findChild<TextInput*>("start-address-input");
this->endAddressInput = this->formWidget->findChild<TextInput*>("end-address-input");
this->sizeInput = this->formWidget->findChild<TextInput*>("size-input");
this->nameInput->setText(region.name);
this->sizeInput->setText(QString::number((region.addressRange.endAddress - region.addressRange.startAddress) + 1));
for (const auto& [optionName, option] : RegionItem::addressRangeTypeOptionsByName) {
this->addressTypeInput->addItem(option.text, optionName);
}
if (region.addressRangeType == MemoryRegionAddressType::RELATIVE) {
this->addressTypeInput->setCurrentText(RegionItem::addressRangeTypeOptionsByName.at("relative").text);
auto addressRange = region.getRelativeAddressRange();
this->startAddressInput->setText("0x" + QString::number(addressRange.startAddress, 16).toUpper());
this->endAddressInput->setText("0x" + QString::number(addressRange.endAddress, 16).toUpper());
} else {
this->addressTypeInput->setCurrentText(RegionItem::addressRangeTypeOptionsByName.at("absolute").text);
auto addressRange = region.getAbsoluteAddressRange();
this->startAddressInput->setText("0x" + QString::number(addressRange.startAddress, 16).toUpper());
this->endAddressInput->setText("0x" + QString::number(addressRange.endAddress, 16).toUpper());
}
QObject::connect(this->startAddressInput, &QLineEdit::textEdited, this, &RegionItem::onAddressRangeInputChange);
QObject::connect(this->endAddressInput, &QLineEdit::textEdited, this, &RegionItem::onAddressRangeInputChange);
QObject::connect(this->sizeInput, &QLineEdit::textEdited, this, &RegionItem::onSizeInputChange);
QObject::connect(this->nameInput, &QLineEdit::textEdited, this, &RegionItem::onNameInputChange);
}
MemoryRegionAddressType RegionItem::getSelectedAddressType() const {
auto selectedAddressTypeOptionName = this->addressTypeInput->currentData().toString();
if (RegionItem::addressRangeTypeOptionsByName.contains(selectedAddressTypeOptionName)) {
return RegionItem::addressRangeTypeOptionsByName.at(selectedAddressTypeOptionName).addressType;
}
return MemoryRegionAddressType::ABSOLUTE;
}
void RegionItem::onAddressRangeInputChange() {
bool startAddressConversionOk = false;
bool endAddressConversionOk = false;
std::uint32_t startAddress = this->startAddressInput->text().toUInt(&startAddressConversionOk, 16);
std::uint32_t endAddress = this->endAddressInput->text().toUInt(&endAddressConversionOk, 16);
if (startAddressConversionOk && endAddressConversionOk && startAddress <= endAddress) {
this->sizeInput->setText(QString::number((endAddress - startAddress) + 1));
}
}
void RegionItem::onSizeInputChange() {
bool startAddressConversionOk = false;
bool sizeConversionOk = false;
std::uint32_t startAddress = this->startAddressInput->text().toUInt(&startAddressConversionOk, 16);
std::uint32_t size = this->sizeInput->text().toUInt(&sizeConversionOk, 10);
if (startAddressConversionOk && sizeConversionOk && size > 0) {
this->endAddressInput->setText("0x" + QString::number((startAddress + size) - 1, 16).toUpper());
}
}
void RegionItem::onNameInputChange() {
auto newName = this->nameInput->text();
newName.truncate(RegionItem::NAME_LABEL_MAX_LENGTH);
this->nameLabel->setText(newName);
}

View File

@@ -0,0 +1,79 @@
#pragma once
#include <QVBoxLayout>
#include <QLabel>
#include <QComboBox>
#include <map>
#include <QString>
#include <QStringList>
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/ClickableWidget.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TextInput.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegion.hpp"
namespace Bloom::Widgets
{
struct AddressRangeTypeOption
{
QString text;
MemoryRegionAddressType addressType;
AddressRangeTypeOption(const QString& text, MemoryRegionAddressType addressType)
: text(text), addressType(addressType) {};
};
class RegionItem: public ClickableWidget
{
Q_OBJECT
public:
RegionItem(const MemoryRegion& region, QWidget *parent);
void setSelected(bool selected);
[[nodiscard]] QWidget* getFormWidget() const {
return this->formWidget;
}
[[nodiscard]] QString getRegionNameInputValue() const {
return this->nameInput->text();
}
[[nodiscard]] virtual const MemoryRegion& getMemoryRegion() const = 0;
[[nodiscard]] virtual QStringList getValidationFailures() const;
signals:
void selected(RegionItem*);
protected:
static constexpr int NAME_LABEL_MAX_LENGTH = 34;
QWidget* formWidget = nullptr;
TextInput* nameInput = nullptr;
QComboBox* addressTypeInput = nullptr;
TextInput* startAddressInput = nullptr;
TextInput* endAddressInput = nullptr;
TextInput* sizeInput = nullptr;
virtual void initFormInputs();
[[nodiscard]] MemoryRegionAddressType getSelectedAddressType() const;
private:
QVBoxLayout* layout = new QVBoxLayout(this);
QLabel* nameLabel = new QLabel(this);
QLabel* typeLabel = new QLabel(this);
QLabel* addressRangeLabel = new QLabel(this);
QLabel* timeLabel = new QLabel(this);
static inline const std::map<QString, AddressRangeTypeOption> addressRangeTypeOptionsByName = std::map<
QString, AddressRangeTypeOption
>({
{"absolute", AddressRangeTypeOption("Absolute", MemoryRegionAddressType::ABSOLUTE)},
{"relative", AddressRangeTypeOption("Relative", MemoryRegionAddressType::RELATIVE)},
});
void onAddressRangeInputChange();
void onSizeInputChange();
void onNameInputChange();
};
}

View File

@@ -0,0 +1,122 @@
#memory-region-manager-window {
background-color: #373835;
}
#title-label {
font-size: 15px;
}
#region-selector {
border-right: 1px solid #2F2F2D;
}
#region-selector #region-item-scroll-area {
border-top: none;
border-bottom: none;
border-left: none;
}
#region-selector-tool-bar {
border-bottom: 1px solid #2F2F2D;
margin: 0;
}
#region-selector-tool-bar QToolButton {
background-color: transparent;
border: none;
padding: 0;
qproperty-buttonWidth: 20;
qproperty-buttonHeight: 18;
}
#region-selector-tool-bar QToolButton::menu-indicator {
image: none;
}
#region-selector-tool-bar QToolButton:hover {
background-color: #41413b;
border: none;
padding: 0;
}
#region-selector-tool-bar QToolButton:checked {
background-color: #43433d;
border: none;
}
#region-selector-tool-bar QToolButton:checked:disabled {
background-color: #3d3d39;
border: none;
}
#region-selector-tool-bar #separator {
background-color: transparent;
border-right: 1px solid #41423f;
padding: 0;
min-width: 1px;
max-width: 1px;
}
#region-selector #region-item-scroll-area,
#region-selector #region-item-scroll-area #item-container {
background-color: transparent;
}
#region-selector #region-item {
border-bottom: 1px solid #2e2e2e;
background-color: transparent;
}
#region-selector #region-item[selected=true] {
background-color: #355A80;
}
#region-selector #region-item #name-label {
font-size: 14px
}
#region-selector #region-item #address-label {
font-size: 13px;
font-style: italic;
color: #8a8a8d;
}
#region-selector #region-item #type-label,
#region-selector #region-item #time-label {
font-size: 13px;
color: #8a8a8d;
}
/* Region form */
#form-container #name-label {
min-width: 60px;
max-width: 60px;
}
#form-container #address-type-label,
#form-container #start-address-label,
#form-container #end-address-label {
min-width: 130px;
max-width: 130px;
}
#form-container #size-label {
min-width: 30px;
max-width: 30px;
}
#form-container #address-range-description-label,
#form-container #value-annotations-description-label {
color: #8a8a8d;
}
/* Actions */
#actions {
border-top: 1px solid #2F2F2D;
min-height: 50px;
}
#apply-btn {
background-color: #353C41;
border: 1px solid #454C52;
}

View File

@@ -0,0 +1,351 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<widget class="QWidget" name="form-container">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"/>
</property>
<layout class="QVBoxLayout" name="form-container-layout">
<property name="spacing">
<number>0</number>
</property>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>10</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="name-row">
<item alignment="Qt::AlignVCenter">
<widget class="QLabel" name="name-label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"/>
</property>
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>20</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item alignment="Qt::AlignVCenter">
<widget class="TextInput" name="name-input">
<property name="minimumWidth">
<number>300</number>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>300</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>15</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<widget class="LabeledSeparator" name="address-range-separator">
<property name="title">
<string>Address Range</string>
</property>
</widget>
</item>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>15</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="address-range-description-label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="text">
<string>The region's address range can be specified in relative or absolute form. Absolute addresses must account for any relevant offsets. Address ranges displayed in the region selector will always be in absolute form.</string>
</property>
</widget>
</item>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>15</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="address-type-row">
<item alignment="Qt::AlignVCenter">
<widget class="QLabel" name="address-type-label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"/>
</property>
<property name="text">
<string>Address type:</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>20</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item alignment="Qt::AlignVCenter">
<widget class="QComboBox" name="address-type-input">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"/>
</property>
<property name="minimumWidth">
<number>350</number>
</property>
<property name="frame">
<bool>false</bool>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>10</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>10</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="start-address-row">
<item alignment="Qt::AlignVCenter">
<widget class="QLabel" name="start-address-label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"/>
</property>
<property name="text">
<string>Start address:</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>20</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item alignment="Qt::AlignVCenter">
<widget class="TextInput" name="start-address-input">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"/>
</property>
<property name="minimumWidth">
<number>350</number>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>10</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>10</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="end-address-row">
<item alignment="Qt::AlignVCenter">
<widget class="QLabel" name="end-address-label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"/>
</property>
<property name="text">
<string>End address:</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>20</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item alignment="Qt::AlignVCenter">
<widget class="TextInput" name="end-address-input">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"/>
</property>
<property name="minimumWidth">
<number>150</number>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>10</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item alignment="Qt::AlignVCenter">
<widget class="QLabel" name="size-label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"/>
</property>
<property name="text">
<string>Size:</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>5</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item alignment="Qt::AlignVCenter">
<widget class="TextInput" name="size-input">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"/>
</property>
<property name="maximumWidth">
<number>60</number>
</property>
<property name="minimumWidth">
<number>60</number>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>10</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="vertical-spacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</spacer>
</item>
</layout>
</widget>
</ui>

View File

@@ -0,0 +1,458 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<widget class="QWidget" name="form-container">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"/>
</property>
<layout class="QVBoxLayout" name="form-container-layout">
<property name="spacing">
<number>0</number>
</property>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>10</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="name-row">
<item alignment="Qt::AlignVCenter">
<widget class="QLabel" name="name-label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"/>
</property>
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>20</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item alignment="Qt::AlignVCenter">
<widget class="TextInput" name="name-input">
<property name="minimumWidth">
<number>300</number>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>300</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>15</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<widget class="LabeledSeparator" name="address-range-separator">
<property name="title">
<string>Address Range</string>
</property>
</widget>
</item>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>15</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="address-range-description-label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="text">
<string>The region's address range can be specified in relative or absolute form. Absolute addresses must account for any relevant offsets. Address ranges displayed in the region selector will always be in absolute form.</string>
</property>
</widget>
</item>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>15</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="address-type-row">
<item alignment="Qt::AlignVCenter">
<widget class="QLabel" name="address-type-label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"/>
</property>
<property name="text">
<string>Address type:</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>20</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item alignment="Qt::AlignVCenter">
<widget class="QComboBox" name="address-type-input">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"/>
</property>
<property name="minimumWidth">
<number>350</number>
</property>
<property name="frame">
<bool>false</bool>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>10</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>10</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="start-address-row">
<item alignment="Qt::AlignVCenter">
<widget class="QLabel" name="start-address-label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"/>
</property>
<property name="text">
<string>Start address:</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>20</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item alignment="Qt::AlignVCenter">
<widget class="TextInput" name="start-address-input">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"/>
</property>
<property name="minimumWidth">
<number>350</number>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>10</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>10</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="end-address-row">
<item alignment="Qt::AlignVCenter">
<widget class="QLabel" name="end-address-label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"/>
</property>
<property name="text">
<string>End address:</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>20</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item alignment="Qt::AlignVCenter">
<widget class="TextInput" name="end-address-input">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"/>
</property>
<property name="minimumWidth">
<number>150</number>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>10</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item alignment="Qt::AlignVCenter">
<widget class="QLabel" name="size-label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"/>
</property>
<property name="text">
<string>Size:</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>5</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item alignment="Qt::AlignVCenter">
<widget class="TextInput" name="size-input">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"/>
</property>
<property name="maximumWidth">
<number>60</number>
</property>
<property name="minimumWidth">
<number>60</number>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>10</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>20</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<widget class="LabeledSeparator" name="value-annotations-separator">
<property name="title">
<string>Value Annotation</string>
</property>
</widget>
</item>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>15</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="value-annotations-description-label">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="text">
<string>Specifying the type of data stored in this region will allow Bloom to present the current value of the data, in the form of a value annotation.</string>
</property>
</widget>
</item>
<item>
<spacer name="vertical-spacer">
<property name="sizeHint">
<size>
<height>15</height>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="data-type-row">
<item alignment="Qt::AlignVCenter">
<widget class="QLabel" name="data-type-label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed"/>
</property>
<property name="text">
<string>Data type:</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>20</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item alignment="Qt::AlignVCenter">
<widget class="QComboBox" name="data-type-input">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"/>
</property>
<property name="minimumWidth">
<number>150</number>
</property>
<property name="frame">
<bool>false</bool>
</property>
</widget>
</item>
<item alignment="Qt::AlignVCenter">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>10</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="vertical-spacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</spacer>
</item>
</layout>
</widget>
</ui>

View File

@@ -0,0 +1,233 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<widget class="QWidget" name="container">
<layout class="QVBoxLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item alignment="Qt::AlignLeft">
<layout class="QHBoxLayout" name="content-layout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item alignment="Qt::AlignLeft">
<widget class="QWidget" name="region-selector">
<property name="minimumWidth">
<number>300</number>
</property>
<property name="maximumWidth">
<number>300</number>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding"/>
</property>
<layout class="QVBoxLayout" name="region-selector-layout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="region-selector-tool-bar">
<property name="minimumHeight">
<number>30</number>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"/>
</property>
<layout class="QHBoxLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>5</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<widget class="SvgToolButton" name="add-region-btn">
<property name="checkable">
<bool>false</bool>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
<property name="svgFilePath">
<string>:/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/Images/add-region.svg</string>
</property>
<property name="disabledSvgFilePath">
<string>:/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/Images/add-region.svg</string>
</property>
<property name="toolTip">
<string>Add Memory Region</string>
</property>
<widget class="QMenu" name="add-region-menu">
<addaction name="add-focused-region"/>
<addaction name="add-excluded-region"/>
<action name="add-focused-region">
<property name="text">
<string>Focused Region</string>
</property>
</action>
<action name="add-excluded-region">
<property name="text">
<string>Excluded Region</string>
</property>
</action>
</widget>
</widget>
</item>
<item>
<widget class="SvgToolButton" name="remove-region-btn">
<property name="checkable">
<bool>false</bool>
</property>
<property name="svgFilePath">
<string>:/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/Images/remove-region.svg</string>
</property>
<property name="disabledSvgFilePath">
<string>:/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/Images/remove-region.svg</string>
</property>
<property name="toolTip">
<string>Remove Memory Region</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignLeft">
<spacer name="horizontal-spacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QScrollArea" name="region-item-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="item-container">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"/>
</property>
<layout class="QVBoxLayout" name="item-container-layout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetMinAndMaxSize</enum>
</property>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
<item alignment="Qt::AlignLeft">
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>10</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item alignment="Qt::AlignLeft">
<layout class="QStackedLayout" name="stacked-form-layout"/>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="actions">
<layout class="QHBoxLayout">
<property name="spacing">
<number>15</number>
</property>
<item>
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>10</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="help-btn">
<property name="text">
<string>Help</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontal-spacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="close-btn">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="apply-btn">
<property name="text">
<string>OK</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontal-spacer">
<property name="sizeHint">
<size>
<width>10</width>
</size>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</ui>

View File

@@ -1,9 +1,8 @@
#include "TargetMemoryInspectionPane.hpp" #include "TargetMemoryInspectionPane.hpp"
#include <QVBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include <QToolButton> #include <QToolButton>
#include <set>
#include "src/Insight/UserInterfaces/InsightWindow/UiLoader.hpp" #include "src/Insight/UserInterfaces/InsightWindow/UiLoader.hpp"
@@ -12,7 +11,6 @@
#include "src/Helpers/Paths.hpp" #include "src/Helpers/Paths.hpp"
#include "src/Exceptions/Exception.hpp" #include "src/Exceptions/Exception.hpp"
#include "src/Logger/Logger.hpp"
using namespace Bloom::Widgets; using namespace Bloom::Widgets;
using namespace Bloom::Exceptions; using namespace Bloom::Exceptions;
@@ -44,17 +42,25 @@ TargetMemoryInspectionPane::TargetMemoryInspectionPane(
this->titleBar = this->container->findChild<QWidget*>("title-bar"); this->titleBar = this->container->findChild<QWidget*>("title-bar");
this->titleBar->layout()->setContentsMargins(7, 0, 7, 0); this->titleBar->layout()->setContentsMargins(7, 0, 7, 0);
auto titleLabel = this->titleBar->findChild<QLabel*>("title"); auto* titleLabel = this->titleBar->findChild<QLabel*>("title");
titleLabel->setText( titleLabel->setText(
this->targetMemoryDescriptor.type == TargetMemoryType::EEPROM ? "Internal EEPROM" : "Internal RAM" this->targetMemoryDescriptor.type == TargetMemoryType::EEPROM ? "Internal EEPROM" : "Internal RAM"
); );
auto subContainerLayout = this->container->findChild<QHBoxLayout*>("sub-container-layout"); 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->insightWorker, this);
this->hexViewerWidget->setDisabled(true); this->hexViewerWidget->setDisabled(true);
subContainerLayout->addWidget(this->hexViewerWidget); subContainerLayout->addWidget(this->hexViewerWidget);
QObject::connect(
this->manageMemoryRegionsButton,
&QToolButton::clicked,
this,
&TargetMemoryInspectionPane::openMemoryRegionManagerWindow
);
QObject::connect( QObject::connect(
&insightWorker, &insightWorker,
&InsightWorker::targetStateUpdated, &InsightWorker::targetStateUpdated,
@@ -172,3 +178,22 @@ void TargetMemoryInspectionPane::onTargetStateChanged(Targets::TargetState newSt
void TargetMemoryInspectionPane::onMemoryRead(const Targets::TargetMemoryBuffer& buffer) { void TargetMemoryInspectionPane::onMemoryRead(const Targets::TargetMemoryBuffer& buffer) {
this->hexViewerWidget->updateValues(buffer); this->hexViewerWidget->updateValues(buffer);
} }
void TargetMemoryInspectionPane::openMemoryRegionManagerWindow() {
if (this->memoryRegionManagerWindow == nullptr) {
this->memoryRegionManagerWindow = new MemoryRegionManagerWindow(
this->targetMemoryDescriptor,
this->focusedMemoryRegions,
this->excludedMemoryRegions,
this
);
}
if (!this->memoryRegionManagerWindow->isVisible()) {
this->memoryRegionManagerWindow->refreshRegions();
this->memoryRegionManagerWindow->show();
} else {
this->memoryRegionManagerWindow->activateWindow();
}
}

View File

@@ -1,23 +1,24 @@
#pragma once #pragma once
#include <QWidget> #include <QWidget>
#include <QLineEdit> #include <QResizeEvent>
#include <QScrollArea> #include <vector>
#include <set>
#include <QSize>
#include <QString>
#include <QEvent>
#include <optional>
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PanelWidget.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/SvgToolButton.hpp"
#include "src/Insight/InsightWorker/InsightWorker.hpp" #include "src/Insight/InsightWorker/InsightWorker.hpp"
#include "HexViewerWidget/HexViewerWidget.hpp"
#include "src/Targets/TargetMemory.hpp" #include "src/Targets/TargetMemory.hpp"
#include "src/Targets/TargetState.hpp" #include "src/Targets/TargetState.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PanelWidget.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/SvgToolButton.hpp"
#include "HexViewerWidget/HexViewerWidget.hpp"
#include "MemoryRegionManager/MemoryRegionManagerWindow.hpp"
#include "MemoryRegion.hpp"
#include "FocusedMemoryRegion.hpp"
#include "ExcludedMemoryRegion.hpp"
namespace Bloom::Widgets namespace Bloom::Widgets
{ {
class TargetMemoryInspectionPane: public QWidget class TargetMemoryInspectionPane: public QWidget
@@ -34,7 +35,6 @@ namespace Bloom::Widgets
); );
void refreshMemoryValues(std::optional<std::function<void(void)>> callback = std::nullopt); void refreshMemoryValues(std::optional<std::function<void(void)>> callback = std::nullopt);
void activate(); void activate();
void deactivate(); void deactivate();
@@ -52,12 +52,17 @@ namespace Bloom::Widgets
QWidget* container = nullptr; QWidget* container = nullptr;
QWidget* titleBar = nullptr; QWidget* titleBar = nullptr;
SvgToolButton* manageMemoryRegionsButton = nullptr;
HexViewerWidget* hexViewerWidget = nullptr; HexViewerWidget* hexViewerWidget = nullptr;
Targets::TargetState targetState = Targets::TargetState::UNKNOWN; Targets::TargetState targetState = Targets::TargetState::UNKNOWN;
private slots: std::vector<FocusedMemoryRegion> focusedMemoryRegions;
std::vector<ExcludedMemoryRegion> excludedMemoryRegions;
MemoryRegionManagerWindow* memoryRegionManagerWindow = nullptr;
void onTargetStateChanged(Targets::TargetState newState); void onTargetStateChanged(Targets::TargetState newState);
void onMemoryRead(const Targets::TargetMemoryBuffer& buffer); void onMemoryRead(const Targets::TargetMemoryBuffer& buffer);
void openMemoryRegionManagerWindow();
}; };
} }

View File

@@ -56,6 +56,15 @@
<file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegisterInspector/RegisterHistoryWidget/UiFiles/RegisterHistoryWidget.ui">./Insight/UserInterfaces/InsightWindow/Widgets/TargetRegisterInspector/RegisterHistoryWidget/UiFiles/RegisterHistoryWidget.ui</file> <file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegisterInspector/RegisterHistoryWidget/UiFiles/RegisterHistoryWidget.ui">./Insight/UserInterfaces/InsightWindow/Widgets/TargetRegisterInspector/RegisterHistoryWidget/UiFiles/RegisterHistoryWidget.ui</file>
<file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegisterInspector/Images/icon.svg">./Insight/UserInterfaces/InsightWindow/Widgets/TargetRegisterInspector/Images/icon.svg</file> <file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegisterInspector/Images/icon.svg">./Insight/UserInterfaces/InsightWindow/Widgets/TargetRegisterInspector/Images/icon.svg</file>
<!-- Focused memory region manager window -->
<file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/UiFiles/MemoryRegionManagerWindow.ui">./Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/UiFiles/MemoryRegionManagerWindow.ui</file>
<file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/Stylesheets/MemoryRegionManagerWindow.qss">./Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/Stylesheets/MemoryRegionManagerWindow.qss</file>
<file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/UiFiles/FocusedMemoryRegionForm.ui">./Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/UiFiles/FocusedMemoryRegionForm.ui</file>
<file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/UiFiles/ExcludedMemoryRegionForm.ui">./Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/UiFiles/ExcludedMemoryRegionForm.ui</file>
<file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/Images/icon.svg">./Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/Images/icon.svg</file>
<file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/Images/add-region.svg">./Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/Images/add-region.svg</file>
<file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/Images/remove-region.svg">./Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegionManager/Images/remove-region.svg</file>
<!-- About window --> <!-- About window -->
<file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/UiFiles/AboutWindow.ui">./Insight/UserInterfaces/InsightWindow/UiFiles/AboutWindow.ui</file> <file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/UiFiles/AboutWindow.ui">./Insight/UserInterfaces/InsightWindow/UiFiles/AboutWindow.ui</file>
<file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/Stylesheets/AboutWindow.qss">./Insight/UserInterfaces/InsightWindow/Stylesheets/AboutWindow.qss</file> <file alias="/compiled/src/Insight/UserInterfaces/InsightWindow/Stylesheets/AboutWindow.qss">./Insight/UserInterfaces/InsightWindow/Stylesheets/AboutWindow.qss</file>