Support external context menu actions in the HexViewerWidget

This commit is contained in:
Nav
2023-04-10 16:41:24 +01:00
parent 8efacae10b
commit fb0a5fef3b
6 changed files with 95 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
#include "ContextMenuAction.hpp"
namespace Bloom::Widgets
{
ContextMenuAction::ContextMenuAction(
const QString& text,
std::optional<IsEnabledCallbackType> isEnabledCallback,
QWidget* parent
)
: isEnabledCallback(isEnabledCallback)
, QAction(text, parent)
{}
}

View File

@@ -0,0 +1,46 @@
#pragma once
#include <QAction>
#include <QWidget>
#include <functional>
#include <QString>
#include <optional>
#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<Targets::TargetMemoryAddress, ByteItem*>&)
>;
public:
std::optional<IsEnabledCallbackType> isEnabledCallback;
ContextMenuAction(
const QString& text,
std::optional<IsEnabledCallbackType> isEnabledCallback,
QWidget* parent
);
signals:
void invoked(const std::unordered_map<Targets::TargetMemoryAddress, ByteItem*>& selectedByteItemsByAddress);
};
}

View File

@@ -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(),

View File

@@ -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();

View File

@@ -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());
}

View File

@@ -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<ContextMenuAction*> externalContextMenuActions;
int getSceneWidth() {
/*
* Minus 2 for the QSS margin on the vertical scrollbar (which isn't accounted for during viewport