Implemented rubber-band selection rectangle in memory inspection hex viewer
This commit is contained in:
@@ -94,6 +94,7 @@ namespace Bloom::Widgets
|
|||||||
* color variant, so that we don't have to make copies or call QColor::setAlpha() for each ByteItem.
|
* color variant, so that we don't have to make copies or call QColor::setAlpha() for each ByteItem.
|
||||||
*/
|
*/
|
||||||
static const auto highlightedBackgroundColor = QColor(0x3C, 0x59, 0x5C, 255);
|
static const auto highlightedBackgroundColor = QColor(0x3C, 0x59, 0x5C, 255);
|
||||||
|
static const auto selectedBackgroundColor = QColor(0x3C, 0x59, 0x5C, 255);
|
||||||
static const auto focusedRegionBackgroundColor = QColor(0x44, 0x44, 0x41, 255);
|
static const auto focusedRegionBackgroundColor = QColor(0x44, 0x44, 0x41, 255);
|
||||||
static const auto stackMemoryBackgroundColor = QColor(0x67, 0x57, 0x20, 210);
|
static const auto stackMemoryBackgroundColor = QColor(0x67, 0x57, 0x20, 210);
|
||||||
|
|
||||||
@@ -104,6 +105,13 @@ namespace Bloom::Widgets
|
|||||||
100
|
100
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static const auto disabledSelectedBackgroundColor = QColor(
|
||||||
|
selectedBackgroundColor.red(),
|
||||||
|
selectedBackgroundColor.green(),
|
||||||
|
selectedBackgroundColor.blue(),
|
||||||
|
100
|
||||||
|
);
|
||||||
|
|
||||||
static const auto disabledFocusedRegionBackgroundColor = QColor(
|
static const auto disabledFocusedRegionBackgroundColor = QColor(
|
||||||
focusedRegionBackgroundColor.red(),
|
focusedRegionBackgroundColor.red(),
|
||||||
focusedRegionBackgroundColor.green(),
|
focusedRegionBackgroundColor.green(),
|
||||||
@@ -133,6 +141,10 @@ namespace Bloom::Widgets
|
|||||||
return &(highlightedBackgroundColor);
|
return &(highlightedBackgroundColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->selected) {
|
||||||
|
return &(selectedBackgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
const auto* hoveredByteItem = *(this->hoveredByteItem);
|
const auto* hoveredByteItem = *(this->hoveredByteItem);
|
||||||
const auto hovered = hoveredByteItem == this;
|
const auto hovered = hoveredByteItem == this;
|
||||||
const auto hoveredNeighbour =
|
const auto hoveredNeighbour =
|
||||||
@@ -169,6 +181,10 @@ namespace Bloom::Widgets
|
|||||||
return &(disabledHighlightedBackgroundColor);
|
return &(disabledHighlightedBackgroundColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->selected) {
|
||||||
|
return &(disabledSelectedBackgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this->settings.highlightStackMemory
|
this->settings.highlightStackMemory
|
||||||
&& this->currentStackPointer.has_value()
|
&& this->currentStackPointer.has_value()
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ namespace Bloom::Widgets
|
|||||||
std::size_t currentColumnIndex = 0;
|
std::size_t currentColumnIndex = 0;
|
||||||
|
|
||||||
bool highlighted = false;
|
bool highlighted = false;
|
||||||
|
bool selected = false;
|
||||||
const FocusedMemoryRegion* focusedMemoryRegion = nullptr;
|
const FocusedMemoryRegion* focusedMemoryRegion = nullptr;
|
||||||
const ExcludedMemoryRegion* excludedMemoryRegion = nullptr;
|
const ExcludedMemoryRegion* excludedMemoryRegion = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -248,14 +248,109 @@ namespace Bloom::Widgets
|
|||||||
return QGraphicsScene::event(event);
|
return QGraphicsScene::event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ByteItemGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent) {
|
||||||
|
static const auto rubberBandRectBackgroundColor = QColor(0x3C, 0x59, 0x5C, 0x82);
|
||||||
|
static const auto rubberBandRectBorderColor = QColor(0x3C, 0x59, 0x5C, 255);
|
||||||
|
|
||||||
|
const auto mousePosition = mouseEvent->buttonDownScenePos(Qt::MouseButton::LeftButton);
|
||||||
|
|
||||||
|
if (mousePosition.x() <= this->byteAddressContainer->boundingRect().width()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->clearSelectionRectItem();
|
||||||
|
|
||||||
|
this->rubberBandInitPoint = std::move(mousePosition);
|
||||||
|
this->rubberBandRectItem = new QGraphicsRectItem(
|
||||||
|
this->rubberBandInitPoint->x(),
|
||||||
|
this->rubberBandInitPoint->y(),
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
this->rubberBandRectItem->setBrush(rubberBandRectBackgroundColor);
|
||||||
|
this->rubberBandRectItem->setPen(rubberBandRectBorderColor);
|
||||||
|
this->addItem(this->rubberBandRectItem);
|
||||||
|
|
||||||
|
const auto modifiers = mouseEvent->modifiers();
|
||||||
|
if ((modifiers & (Qt::ControlModifier | Qt::ShiftModifier)) == 0) {
|
||||||
|
this->clearByteItemSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto clickedItems = this->items(mousePosition);
|
||||||
|
|
||||||
|
if (!clickedItems.empty()) {
|
||||||
|
auto* clickedByteItem = dynamic_cast<ByteItem*>(clickedItems.last());
|
||||||
|
|
||||||
|
if (clickedByteItem != nullptr) {
|
||||||
|
|
||||||
|
if ((modifiers & Qt::ShiftModifier) != 0) {
|
||||||
|
for (
|
||||||
|
auto i = clickedByteItem->address;
|
||||||
|
i >= this->targetMemoryDescriptor.addressRange.startAddress;
|
||||||
|
--i
|
||||||
|
) {
|
||||||
|
auto* byteItem = this->byteItemsByAddress.at(i);
|
||||||
|
|
||||||
|
if (byteItem->selected) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->toggleByteItemSelection(byteItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->toggleByteItemSelection(clickedByteItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void ByteItemGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent) {
|
void ByteItemGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent) {
|
||||||
auto hoveredItems = this->items(mouseEvent->scenePos());
|
const auto mousePosition = mouseEvent->scenePos();
|
||||||
|
auto hoveredItems = this->items(mousePosition);
|
||||||
|
|
||||||
|
if (this->rubberBandRectItem != nullptr && this->rubberBandInitPoint.has_value()) {
|
||||||
|
const auto oldRect = this->rubberBandRectItem->rect();
|
||||||
|
|
||||||
|
this->rubberBandRectItem->setRect(
|
||||||
|
qMin(mousePosition.x(), this->rubberBandInitPoint->x()),
|
||||||
|
qMin(mousePosition.y(), this->rubberBandInitPoint->y()),
|
||||||
|
qAbs(mousePosition.x() - this->rubberBandInitPoint->x()),
|
||||||
|
qAbs(mousePosition.y() - this->rubberBandInitPoint->y())
|
||||||
|
);
|
||||||
|
|
||||||
|
if ((mouseEvent->modifiers() & Qt::ControlModifier) == 0) {
|
||||||
|
this->clearByteItemSelection();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const auto oldItems = this->items(oldRect, Qt::IntersectsItemShape);
|
||||||
|
for (auto* item : oldItems) {
|
||||||
|
auto* byteItem = dynamic_cast<ByteItem*>(item);
|
||||||
|
|
||||||
|
if (byteItem != nullptr && byteItem->selected) {
|
||||||
|
this->deselectByteItem(byteItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto items = this->items(this->rubberBandRectItem->rect(), Qt::IntersectsItemShape);
|
||||||
|
for (auto* item : items) {
|
||||||
|
auto* byteItem = dynamic_cast<ByteItem*>(item);
|
||||||
|
|
||||||
|
if (byteItem != nullptr && !byteItem->selected) {
|
||||||
|
this->selectByteItem(byteItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ByteItem* hoveredByteItem = nullptr;
|
ByteItem* hoveredByteItem = nullptr;
|
||||||
AnnotationItem* hoveredAnnotationItem = nullptr;
|
AnnotationItem* hoveredAnnotationItem = nullptr;
|
||||||
|
|
||||||
if (!hoveredItems.empty()) {
|
if (!hoveredItems.empty()) {
|
||||||
hoveredByteItem = dynamic_cast<ByteItem*>(hoveredItems.at(0));
|
hoveredByteItem = dynamic_cast<ByteItem*>(hoveredItems.last());
|
||||||
hoveredAnnotationItem = dynamic_cast<AnnotationItem*>(hoveredItems.at(0));
|
hoveredAnnotationItem = dynamic_cast<AnnotationItem*>(hoveredItems.last());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hoveredByteItem != nullptr) {
|
if (hoveredByteItem != nullptr) {
|
||||||
@@ -277,6 +372,10 @@ namespace Bloom::Widgets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ByteItemGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* mouseEvent) {
|
||||||
|
this->clearSelectionRectItem();
|
||||||
|
}
|
||||||
|
|
||||||
void ByteItemGraphicsScene::updateAnnotationValues(const Targets::TargetMemoryBuffer& buffer) {
|
void ByteItemGraphicsScene::updateAnnotationValues(const Targets::TargetMemoryBuffer& buffer) {
|
||||||
const auto memoryStartAddress = this->targetMemoryDescriptor.addressRange.startAddress;
|
const auto memoryStartAddress = this->targetMemoryDescriptor.addressRange.startAddress;
|
||||||
for (auto* valueAnnotationItem : this->valueAnnotationItems) {
|
for (auto* valueAnnotationItem : this->valueAnnotationItems) {
|
||||||
@@ -504,4 +603,43 @@ namespace Bloom::Widgets
|
|||||||
this->byteItemsByAddress.at(byteItemAddress)->update();
|
this->byteItemsByAddress.at(byteItemAddress)->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ByteItemGraphicsScene::clearSelectionRectItem() {
|
||||||
|
if (this->rubberBandRectItem != nullptr) {
|
||||||
|
this->removeItem(this->rubberBandRectItem);
|
||||||
|
delete this->rubberBandRectItem;
|
||||||
|
this->rubberBandRectItem = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ByteItemGraphicsScene::selectByteItem(ByteItem* byteItem) {
|
||||||
|
byteItem->selected = true;
|
||||||
|
this->selectedByteItems.insert(byteItem);
|
||||||
|
byteItem->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ByteItemGraphicsScene::deselectByteItem(ByteItem* byteItem) {
|
||||||
|
byteItem->selected = false;
|
||||||
|
this->selectedByteItems.erase(byteItem);
|
||||||
|
byteItem->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ByteItemGraphicsScene::toggleByteItemSelection(ByteItem* byteItem) {
|
||||||
|
if (byteItem->selected) {
|
||||||
|
this->deselectByteItem(byteItem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->selectByteItem(byteItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ByteItemGraphicsScene::clearByteItemSelection() {
|
||||||
|
for (auto* byteItem : this->selectedByteItems) {
|
||||||
|
byteItem->selected = false;
|
||||||
|
byteItem->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
this->selectedByteItems.clear();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include <QGraphicsSceneWheelEvent>
|
#include <QGraphicsSceneWheelEvent>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <QGraphicsRectItem>
|
||||||
|
#include <QPointF>
|
||||||
|
|
||||||
#include "src/Targets/TargetMemory.hpp"
|
#include "src/Targets/TargetMemory.hpp"
|
||||||
#include "src/Targets/TargetState.hpp"
|
#include "src/Targets/TargetState.hpp"
|
||||||
@@ -63,7 +65,9 @@ namespace Bloom::Widgets
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool event(QEvent* event) override;
|
bool event(QEvent* event) override;
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent) override;
|
||||||
void mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent) override;
|
void mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent) override;
|
||||||
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent* mouseEvent) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor;
|
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor;
|
||||||
@@ -97,6 +101,10 @@ namespace Bloom::Widgets
|
|||||||
ByteAddressContainer* byteAddressContainer = nullptr;
|
ByteAddressContainer* byteAddressContainer = nullptr;
|
||||||
|
|
||||||
std::set<ByteItem*> highlightedByteItems;
|
std::set<ByteItem*> highlightedByteItems;
|
||||||
|
std::set<ByteItem*> selectedByteItems;
|
||||||
|
|
||||||
|
QGraphicsRectItem* rubberBandRectItem = nullptr;
|
||||||
|
std::optional<QPointF> rubberBandInitPoint = std::nullopt;
|
||||||
|
|
||||||
int getSceneWidth() {
|
int getSceneWidth() {
|
||||||
/*
|
/*
|
||||||
@@ -116,5 +124,10 @@ namespace Bloom::Widgets
|
|||||||
void onByteWidgetLeave();
|
void onByteWidgetLeave();
|
||||||
void onAnnotationItemEnter(Bloom::Widgets::AnnotationItem* annotationItem);
|
void onAnnotationItemEnter(Bloom::Widgets::AnnotationItem* annotationItem);
|
||||||
void onAnnotationItemLeave();
|
void onAnnotationItemLeave();
|
||||||
|
void clearSelectionRectItem();
|
||||||
|
void selectByteItem(ByteItem* byteItem);
|
||||||
|
void deselectByteItem(ByteItem* byteItem);
|
||||||
|
void toggleByteItemSelection(ByteItem* byteItem);
|
||||||
|
void clearByteItemSelection();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user