#include "RegisterWidget.hpp" #include #include #include #include #include "src/Helpers/Paths.hpp" #include "src/Insight/InsightWorker/Tasks/ReadTargetRegisters.hpp" using namespace Bloom::Widgets; using namespace Bloom::Exceptions; using Bloom::Targets::TargetRegisterDescriptor; RegisterWidget::RegisterWidget( TargetRegisterDescriptor descriptor, InsightWorker& insightWorker, QWidget *parent ): ItemWidget(parent), descriptor(std::move(descriptor)), insightWorker(insightWorker) { this->setObjectName("register-item"); this->setFixedHeight(25); this->nameLabel->setText(QString::fromStdString(this->descriptor.name.value()).toUpper()); this->valueLabel->setObjectName("value"); this->registerIcon->setObjectName("register-icon"); auto static registerIconPath = QString::fromStdString( Paths::compiledResourcesPath() + "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetRegistersPane/Images/register.svg" ); this->registerIcon->setSvgFilePath(registerIconPath); this->registerIcon->setContainerHeight(15); this->registerIcon->setContainerWidth(15); this->layout->setContentsMargins(47, 0, 0, 0); this->layout->setSpacing(0); this->layout->addWidget(this->registerIcon); this->layout->addSpacing(7); this->layout->addWidget(this->nameLabel); this->layout->addSpacing(5); this->layout->addWidget(this->valueLabel); this->layout->addStretch(1); QObject::connect(this, &ClickableWidget::doubleClicked, this, &RegisterWidget::openInspectionWindow); QObject::connect(this->openInspectionWindowAction, &QAction::triggered, this, &RegisterWidget::openInspectionWindow); QObject::connect(this->refreshValueAction, &QAction::triggered, this, &RegisterWidget::refreshValue); QObject::connect(this->copyValueNameAction, &QAction::triggered, this, &RegisterWidget::copyName); QObject::connect(this->copyValueHexAction, &QAction::triggered, this, &RegisterWidget::copyValueHex); QObject::connect(this->copyValueDecimalAction, &QAction::triggered, this, &RegisterWidget::copyValueDecimal); QObject::connect(this->copyValueBinaryAction, &QAction::triggered, this, &RegisterWidget::copyValueBinary); QObject::connect( &(this->insightWorker), &InsightWorker::targetStateUpdated, this, &RegisterWidget::onTargetStateChange ); } void RegisterWidget::setRegisterValue(const Targets::TargetRegister& targetRegister) { const auto valueChanged = this->currentRegister.has_value() && this->currentRegister.value().value != targetRegister.value; this->currentRegister = targetRegister; auto valueByteArray = QByteArray( reinterpret_cast(targetRegister.value.data()), static_cast(targetRegister.value.size()) ); auto hexValueByteArray = valueByteArray.toHex(); auto registerValue = ": 0x" + QString(hexValueByteArray).toUpper() + " | " + QString::number(hexValueByteArray.toUInt(nullptr, 16)); if (targetRegister.value.size() == 1 && targetRegister.value[0] >= 32 && targetRegister.value[0] <= 126) { registerValue += " | '" + QString(valueByteArray) + "'"; } this->valueLabel->setProperty("changed", valueChanged); this->valueLabel->style()->unpolish(this->valueLabel); this->valueLabel->style()->polish(this->valueLabel); this->valueLabel->setText(registerValue); if (this->inspectWindow != nullptr) { this->inspectWindow->setValue(targetRegister.value); } } void RegisterWidget::clearInlineValue() { this->valueLabel->clear(); } void RegisterWidget::contextMenuEvent(QContextMenuEvent* event) { this->setSelected(true); auto* menu = new QMenu(this); menu->addAction(this->openInspectionWindowAction); menu->addAction(this->refreshValueAction); menu->addSeparator(); auto* copyMenu = new QMenu("Copy", this); copyMenu->addAction(this->copyValueNameAction); copyMenu->addSeparator(); copyMenu->addAction(this->copyValueDecimalAction); copyMenu->addAction(this->copyValueHexAction); copyMenu->addAction(this->copyValueBinaryAction); menu->addMenu(copyMenu); this->openInspectionWindowAction->setEnabled(TargetRegisterInspectorWindow::registerSupported(this->descriptor)); const auto targetStopped = this->targetState == Targets::TargetState::STOPPED; const auto targetStoppedAndValuePresent = targetStopped && this->currentRegister.has_value(); this->refreshValueAction->setEnabled(targetStopped); this->copyValueDecimalAction->setEnabled(targetStoppedAndValuePresent); this->copyValueHexAction->setEnabled(targetStoppedAndValuePresent); this->copyValueBinaryAction->setEnabled(targetStoppedAndValuePresent); menu->exec(event->globalPos()); } void RegisterWidget::openInspectionWindow() { if (!TargetRegisterInspectorWindow::registerSupported(this->descriptor)) { return; } if (this->inspectWindow == nullptr) { this->inspectWindow = new TargetRegisterInspectorWindow( this->descriptor, this->insightWorker, this->targetState, this->currentRegister.has_value() ? std::optional(this->currentRegister->value) : std::nullopt, this ); } else { if (this->currentRegister.has_value()) { this->inspectWindow->setValue(this->currentRegister->value); } if (!this->inspectWindow->isVisible()) { this->inspectWindow->show(); } else { this->inspectWindow->activateWindow(); } } } void RegisterWidget::refreshValue() { auto* readRegisterTask = new ReadTargetRegisters({this->descriptor}); QObject::connect( readRegisterTask, &ReadTargetRegisters::targetRegistersRead, this, [this] (Targets::TargetRegisters registers) { for (const auto& targetRegister : registers) { if (targetRegister.descriptor == this->descriptor) { this->setRegisterValue(targetRegister); } } } ); this->insightWorker.queueTask(readRegisterTask); } void RegisterWidget::copyName() { if (this->nameLabel != nullptr) { QApplication::clipboard()->setText(this->nameLabel->text()); } } void RegisterWidget::copyValueHex() { if (this->currentRegister.has_value()) { auto valueByteArray = QByteArray( reinterpret_cast(this->currentRegister.value().value.data()), static_cast(this->currentRegister.value().value.size()) ).toHex(); QApplication::clipboard()->setText(QString(valueByteArray).toUpper()); } } void RegisterWidget::copyValueDecimal() { if (this->currentRegister.has_value()) { auto valueByteArray = QByteArray( reinterpret_cast(this->currentRegister.value().value.data()), static_cast(this->currentRegister.value().value.size()) ).toHex(); QApplication::clipboard()->setText(QString::number(valueByteArray.toUInt(nullptr, 16))); } } void RegisterWidget::copyValueBinary() { if (this->currentRegister.has_value()) { const auto registerValueSize = static_cast(this->currentRegister.value().size()); auto valueByteArray = QByteArray( reinterpret_cast(this->currentRegister.value().value.data()), registerValueSize ).toHex(); auto bitString = QString::number(valueByteArray.toUInt(nullptr, 16), 2); if (bitString.size() < (registerValueSize * 8)) { bitString = bitString.rightJustified((registerValueSize * 8), '0'); } QApplication::clipboard()->setText(bitString); } } void RegisterWidget::postSetSelected(bool selected) { auto valueLabelStyle = this->valueLabel->style(); valueLabelStyle->unpolish(this->valueLabel); valueLabelStyle->polish(this->valueLabel); } void RegisterWidget::onTargetStateChange(Targets::TargetState newState) { this->targetState = newState; if (this->targetState == Targets::TargetState::RUNNING) { this->clearInlineValue(); } }