From c63501ff1117431cdbe1cad000d047076b1d7def Mon Sep 17 00:00:00 2001 From: Nav Date: Sat, 15 Apr 2023 12:38:20 +0100 Subject: [PATCH] Improved preexisting and added new copy-to-clipboard functions in the hex viewer and target registers pane. --- .../HexViewerWidget/ItemGraphicsScene.cpp | 127 +++++++++++++++++- .../HexViewerWidget/ItemGraphicsScene.hpp | 24 +++- .../SnapshotViewer/SnapshotViewer.cpp | 2 +- .../TargetRegistersPaneWidget.hpp | 8 +- 4 files changed, 147 insertions(+), 14 deletions(-) diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.cpp index 8d92e103..1fb12d51 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.cpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include @@ -107,7 +109,18 @@ namespace Bloom::Widgets this->copyHexValuesAction, &QAction::triggered, this, - &ItemGraphicsScene::copyHexValuesToClipboard + [this] { + this->copyHexValuesToClipboard(false); + } + ); + + QObject::connect( + this->copyHexValuesWithDelimitersAction, + &QAction::triggered, + this, + [this] { + this->copyHexValuesToClipboard(true); + } ); QObject::connect( @@ -117,6 +130,38 @@ namespace Bloom::Widgets &ItemGraphicsScene::copyDecimalValuesToClipboard ); + QObject::connect( + this->copyBinaryBitStringValues, + &QAction::triggered, + this, + [this] { + this->copyBinaryBitStringToClipboard(false); + } + ); + + QObject::connect( + this->copyBinaryBitStringWithDelimitersValues, + &QAction::triggered, + this, + [this] { + this->copyBinaryBitStringToClipboard(true); + } + ); + + QObject::connect( + this->copyValueJsonMapAction, + &QAction::triggered, + this, + &ItemGraphicsScene::copyValueMappingToClipboard + ); + + QObject::connect( + this->copyAsciiValuesAction, + &QAction::triggered, + this, + &ItemGraphicsScene::copyAsciiValueToClipboard + ); + this->setSceneRect(0, 0, this->getSceneWidth(), 0); static const auto hoverRectBackgroundColor = QColor(0x8E, 0x8B, 0x83, 30); @@ -548,12 +593,17 @@ namespace Bloom::Widgets menu->addAction(this->deselectByteItemsAction); menu->addSeparator(); - auto* copyMenu = new QMenu("Copy Selected", menu); + auto* copyMenu = new QMenu("Copy Selection", menu); copyMenu->addAction(this->copyAbsoluteAddressAction); copyMenu->addAction(this->copyRelativeAddressAction); copyMenu->addSeparator(); copyMenu->addAction(this->copyHexValuesAction); + copyMenu->addAction(this->copyHexValuesWithDelimitersAction); copyMenu->addAction(this->copyDecimalValuesAction); + copyMenu->addAction(this->copyAsciiValuesAction); + copyMenu->addAction(this->copyBinaryBitStringValues); + copyMenu->addAction(this->copyBinaryBitStringWithDelimitersValues); + copyMenu->addAction(this->copyValueJsonMapAction); copyMenu->setEnabled(itemsSelected); this->deselectByteItemsAction->setEnabled(itemsSelected); @@ -768,7 +818,7 @@ namespace Bloom::Widgets QApplication::clipboard()->setText(std::move(data)); } - void ItemGraphicsScene::copyHexValuesToClipboard() { + void ItemGraphicsScene::copyHexValuesToClipboard(bool withDelimiters) { if (this->selectedByteItemsByAddress.empty()) { return; } @@ -779,7 +829,12 @@ namespace Bloom::Widgets const unsigned char byteValue = byteItem->excluded ? 0x00 : (*this->state.data)[byteItem->startAddress - this->state.memoryDescriptor.addressRange.startAddress]; - data.append("0x" + QString::number(byteValue, 16).rightJustified(2, '0').toUpper() + "\n"); + + data.append( + withDelimiters + ? "0x" + QString::number(byteValue, 16).rightJustified(2, '0').toUpper() + "\n" + : QString::number(byteValue, 16).rightJustified(2, '0').toUpper() + ); } QApplication::clipboard()->setText(std::move(data)); @@ -801,4 +856,68 @@ namespace Bloom::Widgets QApplication::clipboard()->setText(std::move(data)); } + + void ItemGraphicsScene::copyBinaryBitStringToClipboard(bool withDelimiters) { + if (this->selectedByteItemsByAddress.empty()) { + return; + } + + auto data = QString(); + + for (const auto& [address, byteItem] : this->sortedByteItemsByAddress()) { + const unsigned char byteValue = byteItem->excluded + ? 0x00 + : (*this->state.data)[byteItem->startAddress - this->state.memoryDescriptor.addressRange.startAddress]; + + data.append( + withDelimiters + ? "0b" + QString::number(byteValue, 2).rightJustified(8, '0') + "\n" + : QString::number(byteValue, 2).rightJustified(8, '0') + " " + ); + } + + QApplication::clipboard()->setText(std::move(data)); + } + + void ItemGraphicsScene::copyValueMappingToClipboard() { + if (this->selectedByteItemsByAddress.empty() || !this->state.data.has_value()) { + return; + } + + auto data = QJsonObject(); + + for (const auto& [address, byteItem] : this->sortedByteItemsByAddress()) { + const unsigned char byteValue = byteItem->excluded + ? 0x00 + : (*this->state.data)[byteItem->startAddress - this->state.memoryDescriptor.addressRange.startAddress]; + + data.insert( + "0x" + QString::number(address, 16).rightJustified(8, '0').toUpper(), + "0x" + QString::number(byteValue, 16).rightJustified(2, '0').toUpper() + ); + } + + QApplication::clipboard()->setText(QJsonDocument(data).toJson(QJsonDocument::JsonFormat::Indented)); + } + + void ItemGraphicsScene::copyAsciiValueToClipboard() { + if (this->selectedByteItemsByAddress.empty() || !this->state.data.has_value()) { + return; + } + + auto data = QString(); + + for (const auto& [address, byteItem] : this->sortedByteItemsByAddress()) { + const unsigned char byteValue = + (*this->state.data)[byteItem->startAddress - this->state.memoryDescriptor.addressRange.startAddress]; + + if (byteItem->excluded || byteValue < 32 || byteValue > 126) { + continue; + } + + data.append(QChar(byteValue)); + } + + QApplication::clipboard()->setText(std::move(data)); + } } diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.hpp index 9b262234..b84d59e0 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.hpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ItemGraphicsScene.hpp @@ -114,10 +114,21 @@ namespace Bloom::Widgets // Context menu actions QAction* selectAllByteItemsAction = new QAction("Select All", this); QAction* deselectByteItemsAction = new QAction("Deselect All", this); - QAction* copyAbsoluteAddressAction = new QAction("Copy Absolute Addresses", this); - QAction* copyRelativeAddressAction = new QAction("Copy Relative Addresses", this); - QAction* copyHexValuesAction = new QAction("Copy Hexadecimal Values", this); - QAction* copyDecimalValuesAction = new QAction("Copy Decimal Values", this); + QAction* copyAbsoluteAddressAction = new QAction("Absolute Addresses", this); + QAction* copyRelativeAddressAction = new QAction("Relative Addresses", this); + QAction* copyHexValuesAction = new QAction("Values as Hex Stream", this); + QAction* copyBinaryBitStringValues = new QAction("...as Binary Bit String", this); + QAction* copyBinaryBitStringWithDelimitersValues = new QAction( + "...as Prefixed Binary Bit Strings with Line Delimiters", + this + ); + QAction* copyHexValuesWithDelimitersAction = new QAction( + "...as Prefixed Hex Strings with Line Delimiters", + this + ); + QAction* copyDecimalValuesAction = new QAction("...as Decimals with Line Delimiters", this); + QAction* copyValueJsonMapAction = new QAction("...as Address to Value JSON Map", this); + QAction* copyAsciiValuesAction = new QAction("...as ASCII String", this); // Address label container context menu actions QAction* displayRelativeAddressAction = new QAction("Relative", this); @@ -148,7 +159,10 @@ namespace Bloom::Widgets void setAddressType(AddressType type); std::map sortedByteItemsByAddress(); void copyAddressesToClipboard(AddressType type); - void copyHexValuesToClipboard(); + void copyHexValuesToClipboard(bool withDelimiters); void copyDecimalValuesToClipboard(); + void copyBinaryBitStringToClipboard(bool withDelimiters); + void copyValueMappingToClipboard(); + void copyAsciiValueToClipboard(); }; } diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotViewer/SnapshotViewer.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotViewer/SnapshotViewer.cpp index 793fedde..6865a4b4 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotViewer/SnapshotViewer.cpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/SnapshotManager/SnapshotViewer/SnapshotViewer.cpp @@ -123,7 +123,7 @@ namespace Bloom::Widgets memoryRegionsLayout->insertWidget(0, this->memoryRegionListView); } - this->restoreBytesAction = new ContextMenuAction("Restore Selected", std::nullopt, this); + this->restoreBytesAction = new ContextMenuAction("Restore Selection", std::nullopt, this); this->hexViewerWidget = new HexViewerWidget( this->memoryDescriptor, diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegistersPane/TargetRegistersPaneWidget.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegistersPane/TargetRegistersPaneWidget.hpp index 881b5fdc..76bb28e9 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegistersPane/TargetRegistersPaneWidget.hpp +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegistersPane/TargetRegistersPaneWidget.hpp @@ -71,10 +71,10 @@ namespace Bloom::Widgets // Context-menu actions QAction* openInspectionWindowAction = new QAction("Inspect", this); QAction* refreshValueAction = new QAction("Refresh Value", this); - QAction* copyNameAction = new QAction("Copy Register Name", this); - QAction* copyValueHexAction = new QAction("Copy Hexadecimal Value", this); - QAction* copyValueDecimalAction = new QAction("Copy Decimal Value", this); - QAction* copyValueBinaryAction = new QAction("Copy Binary Value", this); + QAction* copyNameAction = new QAction("Register Name", this); + QAction* copyValueDecimalAction = new QAction("Value as Decimal", this); + QAction* copyValueHexAction = new QAction("...as Hex String", this); + QAction* copyValueBinaryAction = new QAction("...as Binary Bit String", this); RegisterItem* contextMenuRegisterItem = nullptr;