Persisted panel and pane states

This commit is contained in:
Nav
2022-02-06 20:28:46 +00:00
parent 7e992f781e
commit 3dcdc4b90b
14 changed files with 434 additions and 253 deletions

View File

@@ -140,6 +140,7 @@ add_executable(Bloom
src/Insight/UserInterfaces/InsightWindow/BloomProxyStyle.cpp
src/Insight/UserInterfaces/InsightWindow/InsightWindow.cpp
src/Insight/UserInterfaces/InsightWindow/AboutWindow.cpp
src/Insight/UserInterfaces/InsightWindow/Widgets/PaneWidget.hpp
src/Insight/UserInterfaces/InsightWindow/Widgets/PanelWidget.cpp
src/Insight/UserInterfaces/InsightWindow/Widgets/RotatableLabel.cpp
src/Insight/UserInterfaces/InsightWindow/Widgets/LabeledSeparator.cpp

View File

@@ -136,5 +136,7 @@ namespace Bloom
void toggleTargetRegistersPane();
void toggleRamInspectionPane();
void toggleEepromInspectionPane();
void recordInsightSettings();
};
}

View File

@@ -0,0 +1,11 @@
#pragma once
namespace Bloom::Widgets
{
struct PaneState
{
bool activated = false;
explicit PaneState(bool activated): activated(activated) {};
};
}

View File

@@ -0,0 +1,26 @@
#pragma once
#include <QWidget>
#include "PanelWidget.hpp"
#include "PaneState.hpp"
namespace Bloom::Widgets
{
class PaneWidget: public QWidget
{
Q_OBJECT
public:
bool activated = false;
PanelWidget* parentPanel = nullptr;
explicit PaneWidget(PanelWidget* parent): QWidget(parent), parentPanel(parent) {};
[[nodiscard]] PaneState getCurrentState() const {
return PaneState(
this->activated
);
}
};
}

View File

@@ -0,0 +1,12 @@
#pragma once
namespace Bloom::Widgets
{
struct PanelState
{
int size = 0;
bool open = false;
PanelState(int size, bool open): size(size), open(open) {};
};
}

View File

@@ -48,9 +48,18 @@ namespace Bloom::Widgets
}
}
void PanelWidget::setSize(int size) {
if (this->panelType == PanelWidgetType::LEFT) {
this->setFixedWidth(std::min(std::max(size, this->minimumResize), this->maximumResize));
} else if (this->panelType == PanelWidgetType::BOTTOM) {
this->setFixedHeight(std::min(std::max(size, this->minimumResize), this->maximumResize));
}
}
bool PanelWidget::event(QEvent* event) {
if (event->type() == QEvent::Type::HoverMove) {
auto hoverEvent = static_cast<QHoverEvent*>(event);
auto* hoverEvent = dynamic_cast<QHoverEvent*>(event);
if (this->resizingActive || this->isPositionWithinHandleArea(hoverEvent->position().toPoint())) {
this->setCursor(this->resizeCursor);
@@ -91,24 +100,10 @@ namespace Bloom::Widgets
void PanelWidget::mouseMoveEvent(QMouseEvent* event) {
if (this->resizingActive) {
const auto position = event->pos();
if (this->panelType == PanelWidgetType::LEFT) {
this->setFixedWidth(
std::max(
this->minimumResize,
std::min(this->maximumResize, position.x() + this->resizingOffset)
)
this->setSize(this->panelType == PanelWidgetType::LEFT
? event->pos().x() + this->resizingOffset
: this->height() + (-event->pos().y()) + this->resizingOffset
);
} else if (this->panelType == PanelWidgetType::BOTTOM) {
this->setFixedHeight(
std::max(
this->minimumResize,
std::min(this->maximumResize, this->height() + (-position.y()) + this->resizingOffset)
)
);
}
}
}
@@ -120,14 +115,13 @@ namespace Bloom::Widgets
QPoint(currentSize.width() - this->handleSize, 0),
QPoint(currentSize.width(), currentSize.height())
);
}
} else {
return std::pair(
QPoint(0, 0),
QPoint(currentSize.width(), this->handleSize)
);
}
}
bool PanelWidget::isPositionWithinHandleArea(const QPoint& position) const {
const auto handleArea = this->getHandleArea();

View File

@@ -6,6 +6,8 @@
#include <QMouseEvent>
#include <QEnterEvent>
#include "PanelState.hpp"
namespace Bloom::Widgets
{
Q_NAMESPACE
@@ -37,6 +39,8 @@ namespace Bloom::Widgets
void setPanelType(PanelWidgetType panelType);
void setSize(int size);
[[nodiscard]] int getHandleSize() const {
return this->handleSize;
}
@@ -53,6 +57,13 @@ namespace Bloom::Widgets
return this->panelType;
}
PanelState getCurrentState() {
return PanelState(
this->panelType == PanelWidgetType::LEFT ? this->width() : this->height(),
this->isVisible()
);
}
protected:
int handleSize = 10;
int minimumResize = 10;

View File

@@ -23,12 +23,11 @@ TargetMemoryInspectionPane::TargetMemoryInspectionPane(
TargetMemoryInspectionPaneSettings& settings,
InsightWorker& insightWorker,
PanelWidget* parent
):
QWidget(parent),
targetMemoryDescriptor(targetMemoryDescriptor),
settings(settings),
insightWorker(insightWorker),
parent(parent)
)
: PaneWidget(parent)
, targetMemoryDescriptor(targetMemoryDescriptor)
, settings(settings)
, insightWorker(insightWorker)
{
this->setObjectName("target-memory-inspection-pane");
@@ -175,7 +174,7 @@ void TargetMemoryInspectionPane::deactivate() {
}
void TargetMemoryInspectionPane::resizeEvent(QResizeEvent* event) {
const auto parentSize = this->parent->size();
const auto parentSize = this->parentPanel->size();
const auto width = parentSize.width() - 1;
this->container->setFixedSize(width, parentSize.height());
}

View File

@@ -4,11 +4,12 @@
#include <QResizeEvent>
#include <vector>
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PaneWidget.hpp"
#include "src/Insight/InsightWorker/InsightWorker.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"
@@ -19,13 +20,12 @@
namespace Bloom::Widgets
{
class TargetMemoryInspectionPane: public QWidget
class TargetMemoryInspectionPane: public PaneWidget
{
Q_OBJECT
public:
TargetMemoryInspectionPaneSettings& settings;
bool activated = false;
TargetMemoryInspectionPane(
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
@@ -48,7 +48,6 @@ namespace Bloom::Widgets
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor;
InsightWorker& insightWorker;
PanelWidget* parent = nullptr;
QWidget* container = nullptr;
QWidget* titleBar = nullptr;

View File

@@ -11,9 +11,10 @@ namespace Bloom::Widgets
{
struct TargetMemoryInspectionPaneSettings
{
bool activated = false;
HexViewerWidgetSettings hexViewerWidgetSettings;
std::vector<FocusedMemoryRegion> focusedMemoryRegions;
std::vector<ExcludedMemoryRegion> excludedMemoryRegions;
HexViewerWidgetSettings hexViewerWidgetSettings;
};
}

View File

@@ -25,7 +25,7 @@ namespace Bloom::Widgets
const TargetDescriptor& targetDescriptor,
InsightWorker& insightWorker,
PanelWidget* parent
): QWidget(parent), parent(parent), targetDescriptor(targetDescriptor), insightWorker(insightWorker) {
): PaneWidget(parent), targetDescriptor(targetDescriptor), insightWorker(insightWorker) {
this->setObjectName("target-registers-side-pane");
auto targetRegistersPaneUiFile = QFile(
@@ -208,7 +208,7 @@ namespace Bloom::Widgets
}
void TargetRegistersPaneWidget::resizeEvent(QResizeEvent* event) {
const auto parentSize = this->parent->size();
const auto parentSize = this->parentPanel->size();
const auto width = parentSize.width() - 1;
this->container->setFixedWidth(width);
this->searchInput->setFixedWidth(width - 20);
@@ -217,7 +217,7 @@ namespace Bloom::Widgets
* In order to avoid the panel resize handle overlapping the scroll bar handle, we reduce the size of
* the scroll area.
*/
this->itemScrollArea->setFixedWidth(width - this->parent->getHandleSize());
this->itemScrollArea->setFixedWidth(width - this->parentPanel->getHandleSize());
}
void TargetRegistersPaneWidget::postActivate() {

View File

@@ -9,8 +9,10 @@
#include <QEvent>
#include <optional>
#include "ItemWidget.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PaneWidget.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PanelWidget.hpp"
#include "ItemWidget.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/SvgToolButton.hpp"
#include "src/Insight/InsightWorker/InsightWorker.hpp"
#include "src/Targets/TargetState.hpp"
@@ -19,13 +21,11 @@
namespace Bloom::Widgets
{
class RegisterGroupWidget;
class TargetRegistersPaneWidget: public QWidget
class TargetRegistersPaneWidget: public PaneWidget
{
Q_OBJECT
public:
bool activated = false;
TargetRegistersPaneWidget(
const Targets::TargetDescriptor& targetDescriptor,
InsightWorker& insightWorker,
@@ -54,7 +54,6 @@ namespace Bloom::Widgets
const Targets::TargetDescriptor& targetDescriptor;
InsightWorker& insightWorker;
PanelWidget* parent = nullptr;
QWidget* container = nullptr;
QWidget* toolBar = nullptr;

View File

@@ -30,6 +30,36 @@ namespace Bloom
}
}
if (jsonObject.contains("previousLeftPanelState")) {
this->previousLeftPanelState = this->panelStateFromJson(
jsonObject.find("previousLeftPanelState")->toObject()
);
}
if (jsonObject.contains("previousBottomPanelState")) {
this->previousBottomPanelState = this->panelStateFromJson(
jsonObject.find("previousBottomPanelState")->toObject()
);
}
if (jsonObject.contains("previousRegistersPaneState")) {
this->previousRegistersPaneState = this->paneStateFromJson(
jsonObject.find("previousRegistersPaneState")->toObject()
);
}
if (jsonObject.contains("previousRamInspectionPaneState")) {
this->previousRamInspectionPaneState = this->paneStateFromJson(
jsonObject.find("previousRamInspectionPaneState")->toObject()
);
}
if (jsonObject.contains("previousEepromInspectionPaneState")) {
this->previousEepromInspectionPaneState = this->paneStateFromJson(
jsonObject.find("previousEepromInspectionPaneState")->toObject()
);
}
if (jsonObject.contains("memoryInspectionPaneSettings")) {
const auto settingsMappingObj = jsonObject.find("memoryInspectionPaneSettings")->toObject();
@@ -41,12 +71,86 @@ namespace Bloom
continue;
}
const auto memoryType = InsightProjectSettings::memoryTypesByName.at(memoryTypeName);
this->memoryInspectionPaneSettingsByMemoryType.insert(std::pair(
InsightProjectSettings::memoryTypesByName.at(memoryTypeName),
this->memoryInspectionPaneSettingsFromJson(settingsObj)
));
}
}
}
QJsonObject InsightProjectSettings::toJson() const {
auto insightObj = QJsonObject();
if (this->mainWindowSize.has_value()) {
insightObj.insert("mainWindowSize", QJsonObject({
{"width", this->mainWindowSize->width()},
{"height", this->mainWindowSize->height()},
}));
}
auto memoryInspectionPaneSettingsObj = QJsonObject();
for (const auto& [memoryType, inspectionPaneSettings] : this->memoryInspectionPaneSettingsByMemoryType) {
if (!InsightProjectSettings::memoryTypesByName.contains(memoryType)) {
// This is just a precaution - all known memory types should be in the mapping.
continue;
}
memoryInspectionPaneSettingsObj.insert(
InsightProjectSettings::memoryTypesByName.at(memoryType),
this->memoryInspectionPaneSettingsToJson(inspectionPaneSettings)
);
}
insightObj.insert("memoryInspectionPaneSettings", memoryInspectionPaneSettingsObj);
if (this->previousLeftPanelState.has_value()) {
insightObj.insert(
"previousLeftPanelState",
this->panelStateToJson(this->previousLeftPanelState.value())
);
}
if (this->previousBottomPanelState.has_value()) {
insightObj.insert(
"previousBottomPanelState",
this->panelStateToJson(this->previousBottomPanelState.value())
);
}
if (this->previousRegistersPaneState.has_value()) {
insightObj.insert(
"previousRegistersPaneState",
this->paneStateToJson(this->previousRegistersPaneState.value())
);
}
if (this->previousRamInspectionPaneState.has_value()) {
insightObj.insert(
"previousRamInspectionPaneState",
this->paneStateToJson(this->previousRamInspectionPaneState.value())
);
}
if (this->previousEepromInspectionPaneState.has_value()) {
insightObj.insert(
"previousEepromInspectionPaneState",
this->paneStateToJson(this->previousEepromInspectionPaneState.value())
);
}
return insightObj;
}
Widgets::TargetMemoryInspectionPaneSettings InsightProjectSettings::memoryInspectionPaneSettingsFromJson(
const QJsonObject& jsonObject
) const {
auto inspectionPaneSettings = Widgets::TargetMemoryInspectionPaneSettings();
if (settingsObj.contains("hexViewerSettings")) {
if (jsonObject.contains("hexViewerSettings")) {
auto& hexViewerSettings = inspectionPaneSettings.hexViewerWidgetSettings;
const auto hexViewerSettingsObj = settingsObj.find("hexViewerSettings")->toObject();
const auto hexViewerSettingsObj = jsonObject.find("hexViewerSettings")->toObject();
if (hexViewerSettingsObj.contains("highlightStackMemory")) {
hexViewerSettings.highlightStackMemory =
@@ -74,8 +178,8 @@ namespace Bloom
}
}
if (settingsObj.contains("focusedRegions")) {
const auto focusedRegions = settingsObj.find("focusedRegions")->toArray();
if (jsonObject.contains("focusedRegions")) {
const auto focusedRegions = jsonObject.find("focusedRegions")->toArray();
for (const auto& regionValue : focusedRegions) {
const auto regionObj = regionValue.toObject();
@@ -99,10 +203,8 @@ namespace Bloom
auto region = FocusedMemoryRegion(
regionObj.find("name")->toString(),
{
static_cast<std::uint32_t>(addressRangeObj.find("startAddress")
->toInteger()),
static_cast<std::uint32_t>(addressRangeObj.find("endAddress")
->toInteger()),
static_cast<std::uint32_t>(addressRangeObj.find("startAddress")->toInteger()),
static_cast<std::uint32_t>(addressRangeObj.find("endAddress")->toInteger()),
}
);
@@ -136,8 +238,8 @@ namespace Bloom
}
}
if (settingsObj.contains("excludedRegions")) {
const auto excludedRegions = settingsObj.find("excludedRegions")->toArray();
if (jsonObject.contains("excludedRegions")) {
const auto excludedRegions = jsonObject.find("excludedRegions")->toArray();
for (const auto& regionValue : excludedRegions) {
const auto regionObj = regionValue.toObject();
@@ -160,10 +262,8 @@ namespace Bloom
auto region = ExcludedMemoryRegion(
regionObj.find("name")->toString(),
{
static_cast<std::uint32_t>(addressRangeObj.find("startAddress")
->toInteger()),
static_cast<std::uint32_t>(addressRangeObj.find("endAddress")
->toInteger()),
static_cast<std::uint32_t>(addressRangeObj.find("startAddress")->toInteger()),
static_cast<std::uint32_t>(addressRangeObj.find("endAddress")->toInteger()),
}
);
@@ -181,29 +281,25 @@ namespace Bloom
}
}
this->memoryInspectionPaneSettingsByMemoryType.insert(std::pair(memoryType, inspectionPaneSettings));
}
}
return inspectionPaneSettings;
}
QJsonObject InsightProjectSettings::toJson() const {
auto insightObj = QJsonObject();
if (this->mainWindowSize.has_value()) {
insightObj.insert("mainWindowSize", QJsonObject({
{"width", this->mainWindowSize->width()},
{"height", this->mainWindowSize->height()},
}));
Widgets::PanelState InsightProjectSettings::panelStateFromJson(const QJsonObject& jsonObject) const {
return Widgets::PanelState(
(jsonObject.contains("size") ? static_cast<int>(jsonObject.value("size").toInteger()) : 0),
(jsonObject.contains("open") ? jsonObject.value("open").toBool() : false)
);
}
auto memoryInspectionPaneSettingsObj = QJsonObject();
for (const auto& [memoryType, inspectionPaneSettings] : this->memoryInspectionPaneSettingsByMemoryType) {
if (!InsightProjectSettings::memoryTypesByName.contains(memoryType)) {
// This is just a precaution - all known memory types should be in the mapping.
continue;
Widgets::PaneState InsightProjectSettings::paneStateFromJson(const QJsonObject& jsonObject) const {
return Widgets::PaneState(
(jsonObject.contains("activated") ? jsonObject.value("activated").toBool() : false)
);
}
QJsonObject InsightProjectSettings::memoryInspectionPaneSettingsToJson(
const Widgets::TargetMemoryInspectionPaneSettings& inspectionPaneSettings
) const {
auto settingsObj = QJsonObject();
const auto& hexViewerSettings = inspectionPaneSettings.hexViewerWidgetSettings;
@@ -268,13 +364,20 @@ namespace Bloom
settingsObj.insert("focusedRegions", focusedRegions);
settingsObj.insert("excludedRegions", excludedRegions);
memoryInspectionPaneSettingsObj.insert(
InsightProjectSettings::memoryTypesByName.at(memoryType),
settingsObj
);
return settingsObj;
}
insightObj.insert("memoryInspectionPaneSettings", memoryInspectionPaneSettingsObj);
return insightObj;
QJsonObject InsightProjectSettings::panelStateToJson(const Widgets::PanelState& panelState) const {
return QJsonObject({
{"size", panelState.size},
{"open", panelState.open},
});
}
QJsonObject InsightProjectSettings::paneStateToJson(const Widgets::PaneState& paneState) const {
return QJsonObject({
{"activated", paneState.activated},
});
}
}

View File

@@ -8,6 +8,8 @@
#include <QJsonObject>
#include "src/Targets/TargetMemory.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PanelState.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PaneState.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/TargetMemoryInspectionPaneSettings.hpp"
#include "src/Helpers/BiMap.hpp"
@@ -18,6 +20,11 @@ namespace Bloom
{
public:
std::optional<QSize> mainWindowSize;
std::optional<Widgets::PanelState> previousLeftPanelState;
std::optional<Widgets::PanelState> previousBottomPanelState;
std::optional<Widgets::PaneState> previousRegistersPaneState;
std::optional<Widgets::PaneState> previousRamInspectionPaneState;
std::optional<Widgets::PaneState> previousEepromInspectionPaneState;
std::map<
Targets::TargetMemoryType,
@@ -51,6 +58,22 @@ namespace Bloom
{MemoryRegionAddressInputType::ABSOLUTE, "absolute"},
{MemoryRegionAddressInputType::RELATIVE, "relative"},
};
[[nodiscard]] Widgets::TargetMemoryInspectionPaneSettings memoryInspectionPaneSettingsFromJson(
const QJsonObject& jsonObject
) const;
[[nodiscard]] Widgets::PanelState panelStateFromJson(const QJsonObject& jsonObject) const;
[[nodiscard]] Widgets::PaneState paneStateFromJson(const QJsonObject& jsonObject) const;
[[nodiscard]] QJsonObject memoryInspectionPaneSettingsToJson(
const Widgets::TargetMemoryInspectionPaneSettings& inspectionPaneSettings
) const;
[[nodiscard]] QJsonObject panelStateToJson(const Widgets::PanelState& panelState) const;
[[nodiscard]] QJsonObject paneStateToJson(const Widgets::PaneState& paneState) const;
};
struct ProjectSettings