Turns out we can't construct a QGraphicsScene on a different thread - causes issues with Qt's internal event posting code.

Instead, we now construct just the ByteItem objects on the worker thread. At some point, I'd like to move the item positioning onto
a worker thread, but that's for another day.
This commit is contained in:
Nav
2022-09-13 22:40:55 +01:00
parent 59986b052a
commit 9aff8183dd
11 changed files with 139 additions and 122 deletions

View File

@@ -31,7 +31,7 @@ target_sources(
${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/ReadProgramCounter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/GetTargetState.cpp
${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/GetTargetDescriptor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/ConstructHexViewerByteItemScene.cpp
${CMAKE_CURRENT_SOURCE_DIR}/InsightWorker/Tasks/ConstructHexViewerByteItems.cpp
# Error dialogue window
${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/ErrorDialogue/ErrorDialogue.cpp

View File

@@ -1,32 +0,0 @@
#include "ConstructHexViewerByteItemScene.hpp"
namespace Bloom
{
ConstructHexViewerByteItemScene::ConstructHexViewerByteItemScene(
const Targets::TargetMemoryDescriptor& memoryDescriptor,
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
Widgets::HexViewerWidgetSettings& settings,
Widgets::Label* hoveredAddressLabel
)
: memoryDescriptor(memoryDescriptor)
, focusedMemoryRegions(focusedMemoryRegions)
, excludedMemoryRegions(excludedMemoryRegions)
, settings(settings)
, hoveredAddressLabel(hoveredAddressLabel)
{}
void ConstructHexViewerByteItemScene::run(TargetController::TargetControllerConsole&) {
auto* scene = new Widgets::ByteItemGraphicsScene(
this->memoryDescriptor,
this->focusedMemoryRegions,
this->excludedMemoryRegions,
this->settings,
this->hoveredAddressLabel,
nullptr
);
scene->moveToThread(nullptr);
emit this->sceneCreated(scene);
}
}

View File

@@ -0,0 +1,41 @@
#include "ConstructHexViewerByteItems.hpp"
namespace Bloom
{
ConstructHexViewerByteItems::ConstructHexViewerByteItems(
const Targets::TargetMemoryDescriptor& memoryDescriptor,
std::optional<Targets::TargetStackPointer>& currentStackPointer,
Widgets::ByteItem** hoveredByteItem,
std::set<Widgets::ByteItem*>& highlightedByteItems,
Widgets::HexViewerWidgetSettings& settings
)
: memoryDescriptor(memoryDescriptor)
, currentStackPointer(currentStackPointer)
, hoveredByteItem(hoveredByteItem)
, highlightedByteItems(highlightedByteItems)
, settings(settings)
{}
void ConstructHexViewerByteItems::run(TargetController::TargetControllerConsole&) {
const auto memorySize = this->memoryDescriptor.size();
const auto startAddress = this->memoryDescriptor.addressRange.startAddress;
for (Targets::TargetMemorySize i = 0; i < memorySize; i++) {
const auto address = startAddress + i;
this->byteItemsByAddress.emplace(
address,
new Widgets::ByteItem(
i,
address,
this->currentStackPointer,
this->hoveredByteItem,
this->highlightedByteItems,
settings
)
);
}
emit this->byteItems(this->byteItemsByAddress);
}
}

View File

@@ -1,5 +1,8 @@
#pragma once
#include <optional>
#include <set>
#include "InsightWorkerTask.hpp"
#include "src/Targets/TargetMemory.hpp"
@@ -7,21 +10,22 @@
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/FocusedMemoryRegion.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/ExcludedMemoryRegion.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteItemGraphicsScene.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetMemoryInspectionPane/HexViewerWidget/ByteItem.hpp"
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/Label.hpp"
namespace Bloom
{
class ConstructHexViewerByteItemScene: public InsightWorkerTask
class ConstructHexViewerByteItems: public InsightWorkerTask
{
Q_OBJECT
public:
ConstructHexViewerByteItemScene(
ConstructHexViewerByteItems(
const Targets::TargetMemoryDescriptor& memoryDescriptor,
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
Widgets::HexViewerWidgetSettings& settings,
Widgets::Label* hoveredAddressLabel
std::optional<Targets::TargetStackPointer>& currentStackPointer,
Widgets::ByteItem** hoveredByteItem,
std::set<Widgets::ByteItem*>& highlightedByteItems,
Widgets::HexViewerWidgetSettings& settings
);
TaskGroups getTaskGroups() const override {
@@ -30,15 +34,18 @@ namespace Bloom
signals:
void sceneCreated(Widgets::ByteItemGraphicsScene* scene);
void byteItems(std::map<Targets::TargetMemoryAddress, Widgets::ByteItem*>& byteItemsByAddress);
protected:
void run(TargetController::TargetControllerConsole& targetControllerConsole) override;
void run(TargetController::TargetControllerConsole&) override;
private:
std::map<Targets::TargetMemoryAddress, Widgets::ByteItem*> byteItemsByAddress;
const Targets::TargetMemoryDescriptor& memoryDescriptor;
std::vector<FocusedMemoryRegion>& focusedMemoryRegions;
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions;
std::optional<Targets::TargetStackPointer>& currentStackPointer;
Widgets::ByteItem** hoveredByteItem;
std::set<Widgets::ByteItem*>& highlightedByteItems;
Widgets::HexViewerWidgetSettings& settings;
Widgets::Label* hoveredAddressLabel;
};
}

View File

@@ -9,7 +9,6 @@ namespace Bloom::Widgets
Targets::TargetMemoryAddress address,
std::optional<Targets::TargetStackPointer>& currentStackPointer,
ByteItem** hoveredByteItem,
AnnotationItem** hoveredAnnotationItem,
std::set<ByteItem*>& highlightedByteItems,
const HexViewerWidgetSettings& settings
)
@@ -18,7 +17,6 @@ namespace Bloom::Widgets
, address(address)
, currentStackPointer(currentStackPointer)
, hoveredByteItem(hoveredByteItem)
, hoveredAnnotationItem(hoveredAnnotationItem)
, highlightedByteItems(highlightedByteItems)
, settings(settings)
{

View File

@@ -45,7 +45,6 @@ namespace Bloom::Widgets
Targets::TargetMemoryAddress address,
std::optional<Targets::TargetStackPointer>& currentStackPointer,
ByteItem** hoveredByteItem,
AnnotationItem** hoveredAnnotationItem,
std::set<ByteItem*>& highlightedByteItems,
const HexViewerWidgetSettings& settings
);
@@ -72,7 +71,6 @@ namespace Bloom::Widgets
std::optional<QString> asciiValue;
ByteItem** hoveredByteItem;
AnnotationItem** hoveredAnnotationItem;
std::optional<Targets::TargetStackPointer>& currentStackPointer;
std::set<ByteItem*>& highlightedByteItems;

View File

@@ -1,13 +1,20 @@
#include "ByteItemContainerGraphicsView.hpp"
#include "src/Insight/InsightWorker/InsightWorker.hpp"
#include "src/Insight/InsightWorker/Tasks/ConstructHexViewerByteItemScene.hpp"
#include "src/Insight/InsightWorker/Tasks/ConstructHexViewerByteItems.hpp"
namespace Bloom::Widgets
{
using Bloom::Targets::TargetMemoryDescriptor;
ByteItemContainerGraphicsView::ByteItemContainerGraphicsView(QWidget* parent)
ByteItemContainerGraphicsView::ByteItemContainerGraphicsView(
const TargetMemoryDescriptor& targetMemoryDescriptor,
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
HexViewerWidgetSettings& settings,
Label* hoveredAddressLabel,
QWidget* parent
)
: QGraphicsView(parent)
{
this->setObjectName("graphics-view");
@@ -19,41 +26,31 @@ namespace Bloom::Widgets
this->setOptimizationFlag(QGraphicsView::DontSavePainterState, true);
this->setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, true);
this->setCacheMode(QGraphicsView::CacheBackground);
}
void ByteItemContainerGraphicsView::initScene(
const TargetMemoryDescriptor& targetMemoryDescriptor,
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
HexViewerWidgetSettings& settings,
Label* hoveredAddressLabel
) {
auto* constructSceneTask = new ConstructHexViewerByteItemScene(
this->scene = new ByteItemGraphicsScene(
targetMemoryDescriptor,
focusedMemoryRegions,
excludedMemoryRegions,
settings,
hoveredAddressLabel
hoveredAddressLabel,
this
);
this->setScene(this->scene);
}
void ByteItemContainerGraphicsView::initScene() {
QObject::connect(
constructSceneTask,
&ConstructHexViewerByteItemScene::sceneCreated,
this->scene,
&ByteItemGraphicsScene::ready,
this,
[this] (ByteItemGraphicsScene* scene) {
scene->moveToThread(this->thread());
scene->setParent(this);
this->scene = scene;
this->scene->refreshRegions();
[this] {
this->scene->setEnabled(this->isEnabled());
this->setScene(this->scene);
emit this->ready();
emit this->sceneReady();
}
);
InsightWorker::queueTask(constructSceneTask);
this->scene->init();
}
void ByteItemContainerGraphicsView::scrollToByteItemAtAddress(Targets::TargetMemoryAddress address) {

View File

@@ -18,16 +18,17 @@ namespace Bloom::Widgets
Q_OBJECT
public:
ByteItemContainerGraphicsView(QWidget* parent);
void initScene(
ByteItemContainerGraphicsView(
const Targets::TargetMemoryDescriptor& targetMemoryDescriptor,
std::vector<FocusedMemoryRegion>& focusedMemoryRegions,
std::vector<ExcludedMemoryRegion>& excludedMemoryRegions,
HexViewerWidgetSettings& settings,
Label* hoveredAddressLabel
Label* hoveredAddressLabel,
QWidget* parent
);
void initScene();
[[nodiscard]] ByteItemGraphicsScene* getScene() const {
return this->scene;
}
@@ -35,7 +36,7 @@ namespace Bloom::Widgets
void scrollToByteItemAtAddress(Targets::TargetMemoryAddress address);
signals:
void ready();
void sceneReady();
protected:
bool event(QEvent* event) override;

View File

@@ -3,8 +3,11 @@
#include <cmath>
#include <QMenu>
#include "src/Insight/InsightWorker/InsightWorker.hpp"
#include "src/Insight/InsightSignals.hpp"
#include "src/Insight/InsightWorker/Tasks/ConstructHexViewerByteItems.hpp"
namespace Bloom::Widgets
{
using Bloom::Targets::TargetMemoryDescriptor;
@@ -17,42 +20,19 @@ namespace Bloom::Widgets
Label* hoveredAddressLabel,
QGraphicsView* parent
)
: QGraphicsScene(parent)
, targetMemoryDescriptor(targetMemoryDescriptor)
: targetMemoryDescriptor(targetMemoryDescriptor)
, focusedMemoryRegions(focusedMemoryRegions)
, excludedMemoryRegions(excludedMemoryRegions)
, settings(settings)
, hoveredAddressLabel(hoveredAddressLabel)
, parent(parent)
, QGraphicsScene(parent)
{
this->setObjectName("byte-widget-container");
this->byteAddressContainer = new ByteAddressContainer(this->settings);
this->addItem(this->byteAddressContainer);
// Construct ByteWidget objects
const auto memorySize = this->targetMemoryDescriptor.size();
const auto startAddress = this->targetMemoryDescriptor.addressRange.startAddress;
for (Targets::TargetMemorySize i = 0; i < memorySize; i++) {
const auto address = startAddress + i;
auto* byteWidget = new ByteItem(
i,
address,
this->currentStackPointer,
&(this->hoveredByteWidget),
&(this->hoveredAnnotationItem),
this->highlightedByteItems,
settings
);
this->byteItemsByAddress.emplace(std::pair(
address,
byteWidget
));
this->addItem(byteWidget);
}
this->displayRelativeAddressAction->setCheckable(true);
this->displayAbsoluteAddressAction->setCheckable(true);
@@ -82,6 +62,35 @@ namespace Bloom::Widgets
this->setAddressType(AddressType::ABSOLUTE);
}
);
this->setSceneRect(0, 0, this->getSceneWidth(), 0);
}
void ByteItemGraphicsScene::init() {
auto* constructByteItemsTask = new ConstructHexViewerByteItems(
this->targetMemoryDescriptor,
this->currentStackPointer,
&(this->hoveredByteWidget),
this->highlightedByteItems,
this->settings
);
QObject::connect(
constructByteItemsTask,
&ConstructHexViewerByteItems::byteItems,
this,
[this] (std::map<Targets::TargetMemoryAddress, ByteItem*>& byteItemsByAddress) {
this->byteItemsByAddress = std::move(byteItemsByAddress);
for (const auto& [address, byteItem] : this->byteItemsByAddress) {
this->addItem(byteItem);
}
this->refreshRegions();
emit this->ready();
}
);
InsightWorker::queueTask(constructByteItemsTask);
}
void ByteItemGraphicsScene::updateValues(const Targets::TargetMemoryBuffer& buffer) {
@@ -173,7 +182,6 @@ namespace Bloom::Widgets
}
void ByteItemGraphicsScene::adjustSize(bool forced) {
const auto* parent = this->getParent();
const auto width = this->getSceneWidth();
const auto columnCount = static_cast<std::size_t>(
@@ -198,7 +206,7 @@ namespace Bloom::Widgets
0,
0,
width,
std::max(static_cast<int>(this->sceneRect().height()), parent->viewport()->height())
std::max(static_cast<int>(this->sceneRect().height()), this->parent->viewport()->height())
);
return;
@@ -220,7 +228,7 @@ namespace Bloom::Widgets
0,
0,
width,
std::max(sceneHeight, parent->height())
std::max(sceneHeight, this->parent->height())
);
}
}
@@ -414,7 +422,7 @@ namespace Bloom::Widgets
void ByteItemGraphicsScene::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) {
if (event->scenePos().x() <= ByteAddressContainer::WIDTH) {
auto* menu = new QMenu(this->getParent());
auto* menu = new QMenu(this->parent);
menu->setObjectName("byte-item-address-container-context-menu");
auto* addressTypeMenu = new QMenu("Address Type", menu);

View File

@@ -52,6 +52,7 @@ namespace Bloom::Widgets
QGraphicsView* parent
);
void init();
void updateValues(const Targets::TargetMemoryBuffer& buffer);
void updateStackPointer(Targets::TargetStackPointer stackPointer);
void setHighlightedAddresses(const std::set<Targets::TargetMemoryAddress>& highlightedAddresses);
@@ -62,6 +63,7 @@ namespace Bloom::Widgets
QPointF getByteItemPositionByAddress(Targets::TargetMemoryAddress address);
signals:
void ready();
void byteWidgetsAdjusted();
protected:
@@ -97,6 +99,7 @@ namespace Bloom::Widgets
const QMargins margins = QMargins(10, 10, 10, 10);
HexViewerWidgetSettings& settings;
QGraphicsView* parent = nullptr;
Label* hoveredAddressLabel = nullptr;
ByteAddressContainer* byteAddressContainer = nullptr;
@@ -112,10 +115,6 @@ namespace Bloom::Widgets
QAction* displayRelativeAddressAction = new QAction("Relative", this);
QAction* displayAbsoluteAddressAction = new QAction("Absolute", this);
QGraphicsView* getParent() const {
return dynamic_cast<QGraphicsView*>(this->parent());
}
int getSceneWidth() {
/*
* Minus 2 for the QSS margin on the vertical scrollbar (which isn't accounted for during viewport
@@ -123,8 +122,7 @@ namespace Bloom::Widgets
*
* See https://bugreports.qt.io/browse/QTBUG-99189 for more on this.
*/
auto* parent = this->getParent();
return std::max(parent != nullptr ? parent->viewport()->width() : 400, 400) - 2;
return std::max(this->parent->viewport()->width(), 400) - 2;
}
void updateAnnotationValues(const Targets::TargetMemoryBuffer& buffer);

View File

@@ -74,6 +74,15 @@ namespace Bloom::Widgets
this->loadingHexViewerLabel = this->container->findChild<Label*>("loading-hex-viewer-label");
this->byteItemGraphicsViewContainer = this->container->findChild<QWidget*>("graphics-view-container");
this->byteItemGraphicsView = new ByteItemContainerGraphicsView(
this->targetMemoryDescriptor,
this->focusedMemoryRegions,
this->excludedMemoryRegions,
this->settings,
this->hoveredAddressLabel,
this->byteItemGraphicsViewContainer
);
this->setHoveredRowAndColumnHighlightingEnabled(this->settings.highlightHoveredRowAndCol);
this->setFocusedMemoryHighlightingEnabled(this->settings.highlightFocusedMemory);
this->setAnnotationsEnabled(this->settings.displayAnnotations);
@@ -158,11 +167,9 @@ namespace Bloom::Widgets
}
void HexViewerWidget::init() {
this->byteItemGraphicsView = new ByteItemContainerGraphicsView(this->byteItemGraphicsViewContainer);
QObject::connect(
this->byteItemGraphicsView,
&ByteItemContainerGraphicsView::ready,
&ByteItemContainerGraphicsView::sceneReady,
this,
[this] {
this->byteItemGraphicsScene = this->byteItemGraphicsView->getScene();
@@ -174,13 +181,7 @@ namespace Bloom::Widgets
}
);
this->byteItemGraphicsView->initScene(
this->targetMemoryDescriptor,
this->focusedMemoryRegions,
this->excludedMemoryRegions,
this->settings,
this->hoveredAddressLabel
);
this->byteItemGraphicsView->initScene();
}
void HexViewerWidget::updateValues(const Targets::TargetMemoryBuffer& buffer) {