From bd371d1830425c5163274492ab0cd126325d4f0c Mon Sep 17 00:00:00 2001 From: Nav Date: Sun, 30 May 2021 16:53:24 +0100 Subject: [PATCH] Insight handling of TC suspension --- src/Insight/Insight.cpp | 11 +- src/Insight/InsightWorker.cpp | 21 ++ src/Insight/InsightWorker.hpp | 6 + .../InsightWindow/InsightWindow.cpp | 229 ++++++++++++------ .../InsightWindow/InsightWindow.hpp | 41 ++-- .../Stylesheets/InsightWindow.qss | 4 + .../InsightWindow/UiFiles/InsightWindow.ui | 7 +- 7 files changed, 221 insertions(+), 98 deletions(-) diff --git a/src/Insight/Insight.cpp b/src/Insight/Insight.cpp index b5522f51..6657de01 100644 --- a/src/Insight/Insight.cpp +++ b/src/Insight/Insight.cpp @@ -55,17 +55,20 @@ void Insight::startup() { this->application = new QApplication(this->qtApplicationArgc, this->qtApplicationArgv.data()); this->application->setQuitOnLastWindowClosed(true); + qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType>(); + this->mainWindow.setInsightConfig(this->insightConfig); + this->mainWindow.setEnvironmentConfig(this->environmentConfig); + this->mainWindow.init( *(this->application), - targetDescriptor, - this->insightConfig, - this->environmentConfig.targetConfig + targetDescriptor ); + this->mainWindow.show(); /* @@ -87,6 +90,8 @@ void Insight::startup() { connect(this->workerThread, &QThread::finished, worker, &QObject::deleteLater); connect(this->workerThread, &QThread::finished, this->workerThread, &QThread::deleteLater); + connect(worker, &InsightWorker::targetControllerSuspended, &(this->mainWindow), &InsightWindow::onTargetControllerSuspended); + connect(worker, &InsightWorker::targetControllerResumed, &(this->mainWindow), &InsightWindow::onTargetControllerResumed); connect(worker, &InsightWorker::targetStateUpdated, &(this->mainWindow), &InsightWindow::onTargetStateUpdate); connect(worker, &InsightWorker::targetProgramCounterUpdated, &(this->mainWindow), &InsightWindow::onTargetProgramCounterUpdate); connect(worker, &InsightWorker::targetPinStatesUpdated, &(this->mainWindow), &InsightWindow::onTargetPinStatesUpdate); diff --git a/src/Insight/InsightWorker.cpp b/src/Insight/InsightWorker.cpp index fe7c17dc..302c4d07 100644 --- a/src/Insight/InsightWorker.cpp +++ b/src/Insight/InsightWorker.cpp @@ -19,6 +19,10 @@ void InsightWorker::startup() { Logger::debug("Starting InsightWorker thread"); this->eventManager.registerListener(this->eventListener); + this->eventListener->registerCallbackForEventType( + std::bind(&InsightWorker::onTargetControllerStateReported, this, std::placeholders::_1) + ); + this->eventListener->registerCallbackForEventType( std::bind(&InsightWorker::onTargetStoppedEvent, this, std::placeholders::_1) ); @@ -100,4 +104,21 @@ void InsightWorker::onTargetIoPortsUpdatedEvent(EventPointertargetIoPortsUpdated(); } +void InsightWorker::onTargetControllerStateReported(EventPointer event) { + if (this->lastTargetControllerState == TargetControllerState::ACTIVE + && event->state == TargetControllerState::SUSPENDED + ) { + emit this->targetControllerSuspended(); + } else if (this->lastTargetControllerState == TargetControllerState::SUSPENDED + && event->state == TargetControllerState::ACTIVE + ) { + try { + emit this->targetControllerResumed(this->targetControllerConsole.getTargetDescriptor()); + + } catch (const Exception& exception) { + Logger::error("Insight resume failed - " + exception.getMessage()); + } + } + this->lastTargetControllerState = event->state; +} diff --git a/src/Insight/InsightWorker.hpp b/src/Insight/InsightWorker.hpp index ee519066..6f9b599d 100644 --- a/src/Insight/InsightWorker.hpp +++ b/src/Insight/InsightWorker.hpp @@ -9,6 +9,7 @@ #include "src/EventManager/EventManager.hpp" #include "src/EventManager/EventListener.hpp" #include "src/TargetController/TargetControllerConsole.hpp" +#include "src/TargetController/TargetControllerState.hpp" namespace Bloom { @@ -28,12 +29,15 @@ namespace Bloom *(this->eventListener) ); + TargetControllerState lastTargetControllerState = TargetControllerState::ACTIVE; + QTimer* eventDispatchTimer = nullptr; void onTargetStoppedEvent(Events::EventPointer event); void onTargetResumedEvent(Events::EventPointer event); void onTargetPinStatesRetrievedEvent(Events::EventPointer event); void onTargetIoPortsUpdatedEvent(Events::EventPointer event); + void onTargetControllerStateReported(Events::EventPointer event); public: InsightWorker(EventManager& eventManager): eventManager(eventManager) {}; @@ -56,6 +60,8 @@ namespace Bloom void targetProgramCounterUpdated(quint32 programCounter); void targetPinStatesUpdated(int variantId, Bloom::Targets::TargetPinStateMappingType pinStatesByNumber); void targetIoPortsUpdated(); + void targetControllerSuspended(); + void targetControllerResumed(const Bloom::Targets::TargetDescriptor& targetDescriptor); }; } diff --git a/src/Insight/UserInterfaces/InsightWindow/InsightWindow.cpp b/src/Insight/UserInterfaces/InsightWindow/InsightWindow.cpp index 81a7ee41..32fc59bd 100644 --- a/src/Insight/UserInterfaces/InsightWindow/InsightWindow.cpp +++ b/src/Insight/UserInterfaces/InsightWindow/InsightWindow.cpp @@ -21,9 +21,7 @@ using Bloom::Targets::TargetPackage; void InsightWindow::init( QApplication& application, - TargetDescriptor targetDescriptor, - const InsightConfig& config, - const TargetConfig& targetConfig + TargetDescriptor targetDescriptor ) { this->targetDescriptor = targetDescriptor; @@ -44,7 +42,7 @@ void InsightWindow::init( application.setWindowIcon(QIcon(":/compiled/Insight/UserInterfaces/InsightWindow/Images/BloomIcon.svg")); this->ioContainerWidget = this->mainWindowWidget->findChild("io-container"); - this->ioUnavailableWidget = this->mainWindowWidget->findChild("io-inspection-unavailable"); + this->ioUnavailableWidget = this->mainWindowWidget->findChild("io-inspection-unavailable"); this->mainMenuBar = this->mainWindowWidget->findChild("menu-bar"); auto fileMenu = this->mainMenuBar->findChild("file-menu"); @@ -70,67 +68,10 @@ void InsightWindow::init( }); this->footer = this->mainWindowWidget->findChild("footer"); - auto targetNameLabel = this->footer->findChild("target-name"); - auto targetIdLabel = this->footer->findChild("target-id"); this->targetStatusLabel = this->footer->findChild("target-state"); this->programCounterValueLabel = this->footer->findChild("target-program-counter-value"); - targetNameLabel->setText(QString::fromStdString(this->targetDescriptor.name)); - targetIdLabel->setText("0x" + QString::fromStdString(this->targetDescriptor.id).remove("0x").toUpper()); - this->variantMenu = this->footer->findChild("target-variant-menu"); - - for (const auto& targetVariant: this->targetDescriptor.variants) { - auto variantAction = new QAction(this->variantMenu); - variantAction->setText( - QString::fromStdString(targetVariant.name + " (" + targetVariant.packageName + ")") - ); - - if (this->isVariantSupported(targetVariant)) { - this->supportedVariantsByName.insert( - std::pair(QString::fromStdString(targetVariant.name).toLower().toStdString(), targetVariant) - ); - - connect( - variantAction, - &QAction::triggered, - this, - [this, &targetVariant] { - this->selectVariant(&targetVariant); - } - ); - - } else { - variantAction->setEnabled(false); - variantAction->setText(variantAction->text() + " (unsupported)"); - - }; - - this->variantMenu->addAction(variantAction); - } - - Logger::debug("Number of target variants supported by Insight: " + std::to_string(supportedVariantsByName.size())); - - if (!this->supportedVariantsByName.empty()) { - if (!targetConfig.variantName.empty() && this->supportedVariantsByName.contains(targetConfig.variantName)) { - // The user has specified a valid variant name in their config file, so use that as the default - this->selectVariant(&(this->supportedVariantsByName.at(targetConfig.variantName))); - - } else { - if (!targetConfig.variantName.empty()) { - Logger::error("Invalid target variant name \"" + targetConfig.variantName - + "\" - no such variant with the given name was found."); - } - - this->selectVariant(&(this->supportedVariantsByName.begin()->second)); - } - - } else { - if (this->targetDescriptor.variants.empty()) { - this->variantMenu->parentWidget()->hide(); - } - - this->ioUnavailableWidget->show(); - } + this->activate(); /* * Do not delete svgWidget. It seems like it's absolutely pointless, but it's really not. I know this is gross but @@ -155,6 +96,134 @@ void InsightWindow::init( auto svgWidget = QSvgWidget(); } +void InsightWindow::activate() { + auto targetNameLabel = this->footer->findChild("target-name"); + auto targetIdLabel = this->footer->findChild("target-id"); + targetNameLabel->setText(QString::fromStdString(this->targetDescriptor.name)); + targetIdLabel->setText("0x" + QString::fromStdString(this->targetDescriptor.id).remove("0x").toUpper()); + this->variantMenu = this->footer->findChild("target-variant-menu"); + + this->ioUnavailableWidget->hide(); + + std::optional previouslySelectedVariantName; + if (this->selectedVariant != nullptr) { + previouslySelectedVariantName = QString::fromStdString(this->selectedVariant->name).toLower(); + this->selectedVariant = nullptr; + } + + this->supportedVariantsByName.clear(); + + for (const auto& targetVariant: this->targetDescriptor.variants) { + auto variantAction = new QAction(this->variantMenu); + variantAction->setText( + QString::fromStdString(targetVariant.name + " (" + targetVariant.packageName + ")") + ); + + if (this->isVariantSupported(targetVariant)) { + auto supportedVariantPtr = &(this->supportedVariantsByName.insert( + std::pair(QString::fromStdString(targetVariant.name).toLower(), targetVariant) + ).first->second); + + connect( + variantAction, + &QAction::triggered, + this, + [this, supportedVariantPtr] { + this->selectVariant(supportedVariantPtr); + } + ); + + } else { + variantAction->setEnabled(false); + variantAction->setText(variantAction->text() + " (unsupported)"); + } + + this->variantMenu->addAction(variantAction); + } + + this->variantMenu->setEnabled(true); + + Logger::debug("Number of target variants supported by Insight: " + std::to_string(supportedVariantsByName.size())); + + if (!this->supportedVariantsByName.empty()) { + if (previouslySelectedVariantName.has_value() + && this->supportedVariantsByName.contains(previouslySelectedVariantName.value()) + ) { + this->selectVariant(&(this->supportedVariantsByName.at(previouslySelectedVariantName.value()))); + + } else if (this->targetConfig.variantName.has_value()) { + auto selectedVariantName = QString::fromStdString(this->targetConfig.variantName.value()); + if (this->supportedVariantsByName.contains(selectedVariantName)) { + // The user has specified a valid variant name in their config file, so use that as the default + this->selectVariant(&(this->supportedVariantsByName.at(selectedVariantName))); + } + + } else { + if (this->targetConfig.variantName.has_value()) { + Logger::error("Invalid target variant name \"" + this->targetConfig.variantName.value() + + "\" - no such variant with the given name was found."); + } + + this->selectVariant(&(this->supportedVariantsByName.begin()->second)); + } + + } else { + if (this->targetDescriptor.variants.empty()) { + this->variantMenu->parentWidget()->hide(); + } + + this->ioUnavailableWidget->setText( + "GPIO inspection is not available for this target. " + "Please report this to Bloom developers by clicking Help -> Report An Issue" + ); + this->ioUnavailableWidget->show(); + } + + this->toggleUi(this->targetState != TargetState::STOPPED); + this->activated = true; +} + +void InsightWindow::deactivate() { + if (this->targetPackageWidget != nullptr) { + this->targetPackageWidget->hide(); + this->targetPackageWidget->deleteLater(); + this->targetPackageWidget = nullptr; + } + + this->ioUnavailableWidget->setText( + "Insight deactivated - Bloom has been disconnected from the target.\n" + "Bloom will attempt to reconnect upon the start of a debug session." + ); + this->ioUnavailableWidget->show(); + + this->targetStatusLabel->setText("Unknown"); + this->programCounterValueLabel->setText("-"); + + this->variantMenu->clear(); + this->variantMenu->setEnabled(false); + + this->toggleUi(true); + this->activated = false; +} + +bool InsightWindow::isVariantSupported(const TargetVariant& variant) { + if (variant.package == TargetPackage::DIP) { + // All DIP variants must have a pin count that is a multiple of two + if (variant.pinDescriptorsByNumber.size() % 2 == 0) { + return true; + } + } + + if (variant.package == TargetPackage::QFP) { + // All QFP variants must have a pin count that is a multiple of four + if (variant.pinDescriptorsByNumber.size() % 4 == 0) { + return true; + } + } + + return false; +} + void InsightWindow::selectVariant(const TargetVariant* variant) { if (!this->isVariantSupported(*variant)) { Logger::error("Attempted to select unsupported target variant."); @@ -168,6 +237,7 @@ void InsightWindow::selectVariant(const TargetVariant* variant) { if (this->targetPackageWidget != nullptr) { this->targetPackageWidget->hide(); this->targetPackageWidget->deleteLater(); + this->targetPackageWidget = nullptr; } this->selectedVariant = variant; @@ -209,22 +279,31 @@ void InsightWindow::close() { } } -bool InsightWindow::isVariantSupported(const TargetVariant& variant) { - if (variant.package == TargetPackage::DIP) { - // All DIP variants must have a pin count that is a multiple of two - if (variant.pinDescriptorsByNumber.size() % 2 == 0) { - return true; - } +void InsightWindow::toggleUi(bool disable) { + this->uiDisabled = disable; + + if (this->refreshIoInspectionButton != nullptr) { + this->refreshIoInspectionButton->setDisabled(disable); + this->refreshIoInspectionButton->repaint(); } - if (variant.package == TargetPackage::QFP) { - // All QFP variants must have a pin count that is a multiple of four - if (variant.pinDescriptorsByNumber.size() % 4 == 0) { - return true; - } + if (this->ioContainerWidget != nullptr) { + this->ioContainerWidget->setDisabled(disable); + this->ioContainerWidget->repaint(); } +} - return false; +void InsightWindow::onTargetControllerSuspended() { + if (this->activated) { + this->deactivate(); + } +} + +void InsightWindow::onTargetControllerResumed(const TargetDescriptor& targetDescriptor) { + if (!this->activated) { + this->targetDescriptor = targetDescriptor; + this->activate(); + } } void InsightWindow::openReportIssuesUrl() { @@ -324,4 +403,4 @@ void InsightWindow::togglePinIoState(TargetPinWidget* pinWidget) { TargetPinState::IoState::LOW : TargetPinState::IoState::HIGH; emit this->setTargetPinState(this->selectedVariant->id, pinDescriptor, pinState.value()); } -} \ No newline at end of file +} diff --git a/src/Insight/UserInterfaces/InsightWindow/InsightWindow.hpp b/src/Insight/UserInterfaces/InsightWindow/InsightWindow.hpp index 5ce19629..aca8e44d 100644 --- a/src/Insight/UserInterfaces/InsightWindow/InsightWindow.hpp +++ b/src/Insight/UserInterfaces/InsightWindow/InsightWindow.hpp @@ -19,6 +19,12 @@ namespace Bloom { Q_OBJECT private: + InsightConfig insightConfig; + EnvironmentConfig environmentConfig; + TargetConfig targetConfig; + + bool activated = false; + Targets::TargetDescriptor targetDescriptor; Targets::TargetState targetState = Targets::TargetState::UNKNOWN; @@ -31,14 +37,14 @@ namespace Bloom QToolButton* refreshIoInspectionButton = nullptr; QWidget* ioContainerWidget = nullptr; - QWidget* ioUnavailableWidget = nullptr; + QLabel* ioUnavailableWidget = nullptr; InsightTargetWidgets::TargetPackageWidget* targetPackageWidget = nullptr; QWidget* footer = nullptr; QLabel* targetStatusLabel = nullptr; QLabel* programCounterValueLabel = nullptr; - std::map supportedVariantsByName; + std::map supportedVariantsByName; const Targets::TargetVariant* selectedVariant = nullptr; bool uiDisabled = false; @@ -46,33 +52,32 @@ namespace Bloom void selectVariant(const Targets::TargetVariant* variant); - void toggleUi(bool disable) { - this->uiDisabled = disable; - - if (this->refreshIoInspectionButton != nullptr) { - this->refreshIoInspectionButton->setDisabled(disable); - this->refreshIoInspectionButton->repaint(); - } - - if (this->ioContainerWidget != nullptr) { - this->ioContainerWidget->setDisabled(disable); - this->ioContainerWidget->repaint(); - } - } + void toggleUi(bool disable); + void activate(); + void deactivate(); public: InsightWindow() = default; + void setEnvironmentConfig(const EnvironmentConfig& environmentConfig) { + this->environmentConfig = environmentConfig; + this->targetConfig = environmentConfig.targetConfig; + } + + void setInsightConfig(const InsightConfig& insightConfig) { + this->insightConfig = insightConfig; + } + void init( QApplication& application, - Targets::TargetDescriptor targetDescriptor, - const InsightConfig& config, - const TargetConfig& targetConfig + Targets::TargetDescriptor targetDescriptor ); void show(); public slots: + void onTargetControllerSuspended(); + void onTargetControllerResumed(const Bloom::Targets::TargetDescriptor& targetDescriptor); void onTargetPinStatesUpdate(int variantId, Bloom::Targets::TargetPinStateMappingType pinStatesByNumber); void onTargetStateUpdate(Targets::TargetState newState); void onTargetProgramCounterUpdate(quint32 programCounter); diff --git a/src/Insight/UserInterfaces/InsightWindow/Stylesheets/InsightWindow.qss b/src/Insight/UserInterfaces/InsightWindow/Stylesheets/InsightWindow.qss index e809fb52..d9579076 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Stylesheets/InsightWindow.qss +++ b/src/Insight/UserInterfaces/InsightWindow/Stylesheets/InsightWindow.qss @@ -188,3 +188,7 @@ QToolTip { #target-variant-menu::item { padding: 4px 10px 4px 10px; } + +#io-inspection-unavailable { + color: #838386; +} diff --git a/src/Insight/UserInterfaces/InsightWindow/UiFiles/InsightWindow.ui b/src/Insight/UserInterfaces/InsightWindow/UiFiles/InsightWindow.ui index 2aefe7fd..d77af5d8 100644 --- a/src/Insight/UserInterfaces/InsightWindow/UiFiles/InsightWindow.ui +++ b/src/Insight/UserInterfaces/InsightWindow/UiFiles/InsightWindow.ui @@ -88,8 +88,11 @@ false + + Qt::AlignCenter + - IO inspection is not available for this target. Please report this to Bloom developers by clicking Help -> Report An Issue + - @@ -186,4 +189,4 @@ - \ No newline at end of file +