From fb0a5fef3bed0dd4aec3adb0b1fca850e815661c Mon Sep 17 00:00:00 2001 From: Nav Date: Mon, 10 Apr 2023 16:41:24 +0100 Subject: [PATCH] Support external context menu actions in the HexViewerWidget --- .../HexViewerWidget/ContextMenuAction.cpp | 13 ++++++ .../HexViewerWidget/ContextMenuAction.hpp | 46 +++++++++++++++++++ .../HexViewerWidget/HexViewerWidget.cpp | 5 ++ .../HexViewerWidget/HexViewerWidget.hpp | 2 + .../HexViewerWidget/ItemGraphicsScene.cpp | 25 ++++++++++ .../HexViewerWidget/ItemGraphicsScene.hpp | 4 ++ 6 files changed, 95 insertions(+) create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ContextMenuAction.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ContextMenuAction.hpp diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ContextMenuAction.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ContextMenuAction.cpp new file mode 100644 index 00000000..39e3cce7 --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ContextMenuAction.cpp @@ -0,0 +1,13 @@ +#include "ContextMenuAction.hpp" + +namespace Bloom::Widgets +{ + ContextMenuAction::ContextMenuAction( + const QString& text, + std::optional isEnabledCallback, + QWidget* parent + ) + : isEnabledCallback(isEnabledCallback) + , QAction(text, parent) + {} +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ContextMenuAction.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ContextMenuAction.hpp new file mode 100644 index 00000000..609f8a41 --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ContextMenuAction.hpp @@ -0,0 +1,46 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "src/Targets/TargetMemory.hpp" +#include "ByteItem.hpp" + +namespace Bloom::Widgets +{ + class ContextMenuAction: public QAction + { + Q_OBJECT + + /* + * The ContextMenuAction::isEnabledCallback member is just a callback function that implements any specific + * rules which determine if the action should be enabled (in the context menu). + * + * If the callback returns false, the menu action will be disabled. + * + * The callback is called just before the context menu is presented to the user, everytime the context menu + * is requested. + * + * If no callback is specified (ContextMenuAction::isEnabledCallback == std::nullopt), the menu action will + * always be enabled. + */ + using IsEnabledCallbackType = std::function< + bool(const std::unordered_map&) + >; + + public: + std::optional isEnabledCallback; + + ContextMenuAction( + const QString& text, + std::optional isEnabledCallback, + QWidget* parent + ); + + signals: + void invoked(const std::unordered_map& selectedByteItemsByAddress); + }; +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/HexViewerWidget.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/HexViewerWidget.cpp index 8c43c2ac..6f445687 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/HexViewerWidget.cpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/HexViewerWidget.cpp @@ -237,6 +237,11 @@ namespace Bloom::Widgets } } + void HexViewerWidget::addExternalContextMenuAction(ContextMenuAction* action) { + assert(this->byteItemGraphicsScene != nullptr); + this->byteItemGraphicsScene->addExternalContextMenuAction(action); + } + void HexViewerWidget::resizeEvent(QResizeEvent* event) { this->container->setFixedSize( this->width(), diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/HexViewerWidget.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/HexViewerWidget.hpp index 8ba7ce49..dbed5544 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/HexViewerWidget.hpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/HexViewerWidget.hpp @@ -15,6 +15,7 @@ #include "HexViewerWidgetSettings.hpp" #include "ItemGraphicsView.hpp" +#include "ContextMenuAction.hpp" #include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/MemoryRegion.hpp" #include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/FocusedMemoryRegion.hpp" @@ -40,6 +41,7 @@ namespace Bloom::Widgets void updateValues(); void refreshRegions(); void setStackPointer(Targets::TargetStackPointer stackPointer); + void addExternalContextMenuAction(ContextMenuAction* action); signals: void ready(); diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.cpp index d227ccf7..755198f3 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.cpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.cpp @@ -321,6 +321,14 @@ namespace Bloom::Widgets this->update(); } + void ItemGraphicsScene::addExternalContextMenuAction(ContextMenuAction* action) { + QObject::connect(action, &QAction::triggered, this, [this, action] () { + emit action->invoked(this->selectedByteItemsByAddress); + }); + + this->externalContextMenuActions.push_back(action); + } + bool ItemGraphicsScene::event(QEvent* event) { if (event->type() == QEvent::Type::GraphicsSceneLeave && this->state.hoveredByteItem != nullptr) { this->onByteItemLeave(); @@ -549,6 +557,23 @@ namespace Bloom::Widgets this->deselectByteItemsAction->setEnabled(itemsSelected); menu->addMenu(copyMenu); + + if (!this->externalContextMenuActions.empty()) { + menu->addSeparator(); + + for (auto& externalAction : this->externalContextMenuActions) { + menu->addAction(externalAction); + externalAction->setEnabled( + itemsSelected + && ( + !externalAction->isEnabledCallback.has_value() + || externalAction->isEnabledCallback.value()(this->selectedByteItemsByAddress) + ) + + ); + } + } + menu->exec(event->screenPos()); } diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.hpp index 62209d2a..c6700401 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.hpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.hpp @@ -27,6 +27,7 @@ #include "GroupItem.hpp" #include "ByteItem.hpp" #include "ByteAddressContainer.hpp" +#include "ContextMenuAction.hpp" #include "HexViewerSharedState.hpp" @@ -60,6 +61,7 @@ namespace Bloom::Widgets void refreshValues(); QPointF getByteItemPositionByAddress(Targets::TargetMemoryAddress address); void allocateGraphicsItems(); + void addExternalContextMenuAction(ContextMenuAction* action); signals: void ready(); @@ -121,6 +123,8 @@ namespace Bloom::Widgets QAction* displayRelativeAddressAction = new QAction("Relative", this); QAction* displayAbsoluteAddressAction = new QAction("Absolute", this); + std::vector externalContextMenuActions; + int getSceneWidth() { /* * Minus 2 for the QSS margin on the vertical scrollbar (which isn't accounted for during viewport