2021-09-04 18:11:52 +01:00
|
|
|
#include "InsightWindow.hpp"
|
|
|
|
|
|
2021-04-04 21:04:12 +01:00
|
|
|
#include <QtSvg/QtSvg>
|
2021-09-21 21:21:57 +01:00
|
|
|
#include <QDesktopServices>
|
2021-06-21 00:14:31 +01:00
|
|
|
#include <utility>
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2021-09-04 18:11:52 +01:00
|
|
|
#include "UiLoader.hpp"
|
|
|
|
|
#include "Widgets/RotatableLabel.hpp"
|
|
|
|
|
|
2021-07-07 20:54:45 +01:00
|
|
|
#include "Widgets/TargetWidgets/DIP/DualInlinePackageWidget.hpp"
|
|
|
|
|
#include "Widgets/TargetWidgets/QFP/QuadFlatPackageWidget.hpp"
|
2021-09-02 21:19:46 +01:00
|
|
|
|
2021-04-04 21:04:12 +01:00
|
|
|
#include "src/Logger/Logger.hpp"
|
|
|
|
|
#include "src/Exceptions/Exception.hpp"
|
2021-05-30 19:05:18 +01:00
|
|
|
#include "src/Helpers/Paths.hpp"
|
2021-09-02 21:19:46 +01:00
|
|
|
#include "src/Targets/TargetDescriptor.hpp"
|
|
|
|
|
|
|
|
|
|
#include "AboutWindow.hpp"
|
2021-04-04 21:04:12 +01:00
|
|
|
|
|
|
|
|
using namespace Bloom;
|
2021-05-24 20:58:49 +01:00
|
|
|
using namespace Bloom::Exceptions;
|
2021-07-07 20:54:45 +01:00
|
|
|
using namespace Bloom::Widgets;
|
2021-05-24 20:58:49 +01:00
|
|
|
|
|
|
|
|
using Bloom::Targets::TargetDescriptor;
|
|
|
|
|
using Bloom::Targets::TargetState;
|
|
|
|
|
using Bloom::Targets::TargetPinState;
|
|
|
|
|
using Bloom::Targets::TargetVariant;
|
|
|
|
|
using Bloom::Targets::TargetPackage;
|
2021-06-20 22:57:09 +01:00
|
|
|
using Bloom::Targets::TargetPinDescriptor;
|
2021-10-17 20:44:40 +01:00
|
|
|
using Bloom::Targets::TargetMemoryType;
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2021-10-06 00:39:40 +01:00
|
|
|
InsightWindow::InsightWindow(InsightWorker& insightWorker): QMainWindow(nullptr), insightWorker(insightWorker) {
|
|
|
|
|
this->setObjectName("main-window");
|
|
|
|
|
this->setWindowTitle("Bloom Insight");
|
|
|
|
|
this->setMinimumSize(1000, 500);
|
|
|
|
|
|
2021-05-30 19:05:18 +01:00
|
|
|
auto mainWindowUiFile = QFile(
|
|
|
|
|
QString::fromStdString(Paths::compiledResourcesPath()
|
|
|
|
|
+ "/src/Insight/UserInterfaces/InsightWindow/UiFiles/InsightWindow.ui"
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
auto mainWindowStylesheet = QFile(
|
|
|
|
|
QString::fromStdString(Paths::compiledResourcesPath()
|
|
|
|
|
+ "/src/Insight/UserInterfaces/InsightWindow/Stylesheets/InsightWindow.qss"
|
|
|
|
|
)
|
|
|
|
|
);
|
2021-04-04 21:04:12 +01:00
|
|
|
|
|
|
|
|
if (!mainWindowUiFile.open(QFile::ReadOnly)) {
|
|
|
|
|
throw Exception("Failed to open InsightWindow UI file");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!mainWindowStylesheet.open(QFile::ReadOnly)) {
|
|
|
|
|
throw Exception("Failed to open InsightWindow stylesheet file");
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-04 18:11:52 +01:00
|
|
|
auto uiLoader = UiLoader(this);
|
2021-10-06 00:39:40 +01:00
|
|
|
this->windowContainer = uiLoader.load(&mainWindowUiFile, this);
|
|
|
|
|
this->windowContainer->setStyleSheet(mainWindowStylesheet.readAll());
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2021-09-04 18:11:52 +01:00
|
|
|
mainWindowUiFile.close();
|
|
|
|
|
mainWindowStylesheet.close();
|
|
|
|
|
|
2021-06-21 00:14:31 +01:00
|
|
|
QApplication::setWindowIcon(QIcon(
|
2021-05-30 19:05:18 +01:00
|
|
|
QString::fromStdString(Paths::compiledResourcesPath()
|
|
|
|
|
+ "/src/Insight/UserInterfaces/InsightWindow/Images/BloomIcon.svg"
|
|
|
|
|
)
|
|
|
|
|
));
|
2021-10-06 00:39:40 +01:00
|
|
|
|
|
|
|
|
this->layoutContainer = this->windowContainer->findChild<QWidget*>("layout-container");
|
|
|
|
|
this->mainMenuBar = this->windowContainer->findChild<QMenuBar*>("menu-bar");
|
|
|
|
|
this->layoutContainer->layout()->setMenuBar(this->mainMenuBar);
|
|
|
|
|
this->container = this->layoutContainer->findChild<QWidget*>("container");
|
|
|
|
|
this->ioContainerWidget = this->windowContainer->findChild<InsightTargetWidgets::TargetPackageWidgetContainer*>(
|
2021-09-26 18:18:12 +01:00
|
|
|
"io-container"
|
|
|
|
|
);
|
2021-10-06 00:39:40 +01:00
|
|
|
this->ioUnavailableWidget = this->windowContainer->findChild<QLabel*>("io-inspection-unavailable");
|
2021-04-04 21:04:12 +01:00
|
|
|
|
|
|
|
|
auto fileMenu = this->mainMenuBar->findChild<QMenu*>("file-menu");
|
|
|
|
|
auto helpMenu = this->mainMenuBar->findChild<QMenu*>("help-menu");
|
|
|
|
|
auto quitAction = fileMenu->findChild<QAction*>("close-insight");
|
|
|
|
|
auto openReportIssuesUrlAction = helpMenu->findChild<QAction*>("open-report-issues-url");
|
2021-04-08 21:22:14 +01:00
|
|
|
auto openGettingStartedUrlAction = helpMenu->findChild<QAction*>("open-getting-started-url");
|
2021-04-04 21:04:12 +01:00
|
|
|
auto openAboutWindowAction = helpMenu->findChild<QAction*>("open-about-dialogue");
|
|
|
|
|
|
|
|
|
|
connect(quitAction, &QAction::triggered, this, &InsightWindow::close);
|
|
|
|
|
connect(openReportIssuesUrlAction, &QAction::triggered, this, &InsightWindow::openReportIssuesUrl);
|
2021-04-08 21:22:14 +01:00
|
|
|
connect(openGettingStartedUrlAction, &QAction::triggered, this, &InsightWindow::openGettingStartedUrl);
|
2021-04-04 21:04:12 +01:00
|
|
|
connect(openAboutWindowAction, &QAction::triggered, this, &InsightWindow::openAboutWindow);
|
|
|
|
|
|
2021-10-06 00:39:40 +01:00
|
|
|
this->header = this->windowContainer->findChild<QWidget*>("header");
|
2021-04-04 21:04:12 +01:00
|
|
|
this->refreshIoInspectionButton = this->header->findChild<QToolButton*>("refresh-io-inspection-btn");
|
|
|
|
|
|
|
|
|
|
connect(this->refreshIoInspectionButton, &QToolButton::clicked, this, [this] {
|
2021-09-04 18:11:52 +01:00
|
|
|
// TODO: Move this into a member function - getting too big for a lambda
|
2021-04-04 21:04:12 +01:00
|
|
|
if (this->targetState == TargetState::STOPPED && this->selectedVariant != nullptr) {
|
|
|
|
|
this->toggleUi(true);
|
2021-09-04 18:11:52 +01:00
|
|
|
if (this->targetPackageWidget != nullptr) {
|
|
|
|
|
this->targetPackageWidget->setDisabled(true);
|
|
|
|
|
this->targetPackageWidget->refreshPinStates([this] {
|
|
|
|
|
if (this->targetState == TargetState::STOPPED) {
|
|
|
|
|
this->targetPackageWidget->setDisabled(false);
|
|
|
|
|
|
|
|
|
|
if (this->targetRegistersSidePane == nullptr || !this->targetRegistersSidePane->activated) {
|
|
|
|
|
this->toggleUi(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this->targetRegistersSidePane != nullptr && this->targetRegistersSidePane->activated) {
|
|
|
|
|
this->targetRegistersSidePane->refreshRegisterValues([this] {
|
|
|
|
|
this->toggleUi(false);
|
|
|
|
|
});
|
|
|
|
|
}
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2021-10-06 00:39:40 +01:00
|
|
|
this->leftMenuBar = this->container->findChild<QWidget*>("left-side-menu-bar");
|
|
|
|
|
this->leftPanel = this->container->findChild<PanelWidget*>("left-panel");
|
2021-09-04 18:11:52 +01:00
|
|
|
|
2021-10-06 00:39:40 +01:00
|
|
|
this->targetRegistersButton = this->container->findChild<QToolButton*>("target-registers-btn");
|
2021-09-04 18:11:52 +01:00
|
|
|
auto targetRegisterButtonLayout = this->targetRegistersButton->findChild<QVBoxLayout*>();
|
2021-10-28 20:44:38 +01:00
|
|
|
auto* registersBtnLabel = new RotatableLabel(270, "Registers", this->targetRegistersButton);
|
2021-09-04 18:11:52 +01:00
|
|
|
registersBtnLabel->setObjectName("target-registers-btn-label");
|
|
|
|
|
registersBtnLabel->setContentsMargins(5,0,9,0);
|
|
|
|
|
targetRegisterButtonLayout->insertWidget(0, registersBtnLabel, 0, Qt::AlignTop);
|
|
|
|
|
|
|
|
|
|
connect(this->targetRegistersButton, &QToolButton::clicked, this, &InsightWindow::toggleTargetRegistersPane);
|
|
|
|
|
|
2021-10-06 00:39:40 +01:00
|
|
|
this->bottomMenuBar = this->container->findChild<QWidget*>("bottom-menu-bar");
|
|
|
|
|
this->bottomPanel = this->container->findChild<PanelWidget*>("bottom-panel");
|
|
|
|
|
|
2021-10-06 23:29:05 +01:00
|
|
|
this->ramInspectionButton = this->container->findChild<QToolButton*>("ram-inspection-btn");
|
|
|
|
|
|
|
|
|
|
connect(this->ramInspectionButton, &QToolButton::clicked, this, &InsightWindow::toggleRamInspectionPane);
|
|
|
|
|
|
2021-10-06 00:39:40 +01:00
|
|
|
this->footer = this->windowContainer->findChild<QWidget*>("footer");
|
2021-04-04 21:04:12 +01:00
|
|
|
this->targetStatusLabel = this->footer->findChild<QLabel*>("target-state");
|
|
|
|
|
this->programCounterValueLabel = this->footer->findChild<QLabel*>("target-program-counter-value");
|
2021-10-06 00:39:40 +01:00
|
|
|
|
|
|
|
|
const auto windowSize = this->size();
|
|
|
|
|
this->windowContainer->setFixedSize(windowSize);
|
|
|
|
|
this->layoutContainer->setFixedSize(windowSize);
|
2021-09-02 21:19:46 +01:00
|
|
|
}
|
2021-05-30 16:53:24 +01:00
|
|
|
|
2021-09-02 21:19:46 +01:00
|
|
|
void InsightWindow::init(TargetDescriptor targetDescriptor) {
|
|
|
|
|
this->targetDescriptor = std::move(targetDescriptor);
|
2021-05-30 16:53:24 +01:00
|
|
|
this->activate();
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-06 21:12:31 +01:00
|
|
|
void InsightWindow::onTargetControllerSuspended() {
|
|
|
|
|
if (this->activated) {
|
|
|
|
|
this->deactivate();
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-10-06 00:39:40 +01:00
|
|
|
|
2021-10-06 21:12:31 +01:00
|
|
|
void InsightWindow::onTargetControllerResumed(const TargetDescriptor& targetDescriptor) {
|
|
|
|
|
if (!this->activated) {
|
|
|
|
|
this->targetDescriptor = targetDescriptor;
|
|
|
|
|
this->activate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InsightWindow::onTargetStateUpdate(TargetState newState) {
|
|
|
|
|
this->targetState = newState;
|
|
|
|
|
|
|
|
|
|
if (newState == TargetState::RUNNING) {
|
|
|
|
|
this->targetStatusLabel->setText("Running");
|
|
|
|
|
this->programCounterValueLabel->setText("-");
|
|
|
|
|
|
|
|
|
|
} else if (newState == TargetState::STOPPED) {
|
|
|
|
|
this->targetStatusLabel->setText("Stopped");
|
|
|
|
|
this->toggleUi(false);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
this->targetStatusLabel->setText("Unknown");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InsightWindow::onTargetProgramCounterUpdate(quint32 programCounter) {
|
|
|
|
|
this->programCounterValueLabel->setText(
|
|
|
|
|
"0x" + QString::number(programCounter, 16).toUpper() + " (" + QString::number(programCounter) + ")"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InsightWindow::openReportIssuesUrl() {
|
2021-11-02 23:26:11 +00:00
|
|
|
auto url = QUrl(QString::fromStdString(Paths::homeDomainName() + "/report-issue"));
|
2021-10-06 21:12:31 +01:00
|
|
|
/*
|
|
|
|
|
* The https://bloom.oscillate.io/report-issue URL just redirects to the Bloom GitHub issue page.
|
|
|
|
|
*
|
|
|
|
|
* We can use query parameters in the URL to pre-fill the body of the issue. We use this to include some
|
|
|
|
|
* target information.
|
|
|
|
|
*/
|
|
|
|
|
auto urlQuery = QUrlQuery();
|
|
|
|
|
auto issueBody = QString("Issue reported via Bloom Insight.\nTarget name: "
|
|
|
|
|
+ QString::fromStdString(this->targetDescriptor.name) + "\n"
|
|
|
|
|
+ "Target ID: " + QString::fromStdString(this->targetDescriptor.id) + "\n"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (this->selectedVariant != nullptr) {
|
|
|
|
|
issueBody += "Target variant: " + QString::fromStdString(this->selectedVariant->name) + "\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
issueBody += "\nPlease describe your issue below. Include as much detail as possible.";
|
|
|
|
|
urlQuery.addQueryItem("body", issueBody);
|
|
|
|
|
url.setQuery(urlQuery);
|
|
|
|
|
|
|
|
|
|
QDesktopServices::openUrl(url);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InsightWindow::openGettingStartedUrl() {
|
2021-11-02 23:26:11 +00:00
|
|
|
QDesktopServices::openUrl(QUrl(QString::fromStdString(Paths::homeDomainName() + "/docs/getting-started")));
|
2021-10-06 21:12:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InsightWindow::openAboutWindow() {
|
|
|
|
|
if (this->aboutWindowWidget == nullptr) {
|
2021-10-06 21:46:22 +01:00
|
|
|
this->aboutWindowWidget = new AboutWindow(this);
|
2021-10-06 21:12:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->aboutWindowWidget->show();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InsightWindow::toggleTargetRegistersPane() {
|
|
|
|
|
if (this->targetRegistersSidePane->activated) {
|
|
|
|
|
this->targetRegistersSidePane->deactivate();
|
|
|
|
|
this->targetRegistersButton->setChecked(false);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Given that the target registers side pane is currently the only pane in the left panel, the panel will be
|
|
|
|
|
* empty so no need to leave it visible.
|
|
|
|
|
*/
|
|
|
|
|
this->leftPanel->setVisible(false);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
this->targetRegistersSidePane->activate();
|
|
|
|
|
this->targetRegistersButton->setChecked(true);
|
|
|
|
|
this->leftPanel->setVisible(true);
|
2021-10-06 00:39:40 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-06 23:29:05 +01:00
|
|
|
void InsightWindow::toggleRamInspectionPane() {
|
|
|
|
|
if (this->bottomPanel->isVisible()) {
|
2021-10-17 20:44:40 +01:00
|
|
|
this->ramInspectionPane->deactivate();
|
2021-10-06 23:29:05 +01:00
|
|
|
this->bottomPanel->hide();
|
|
|
|
|
this->ramInspectionButton->setChecked(false);
|
|
|
|
|
|
|
|
|
|
} else {
|
2021-10-17 20:44:40 +01:00
|
|
|
this->ramInspectionPane->activate();
|
2021-10-06 23:29:05 +01:00
|
|
|
this->bottomPanel->show();
|
|
|
|
|
this->ramInspectionButton->setChecked(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-06 21:12:31 +01:00
|
|
|
void InsightWindow::resizeEvent(QResizeEvent* event) {
|
|
|
|
|
const auto windowSize = this->size();
|
|
|
|
|
|
|
|
|
|
this->windowContainer->setFixedSize(windowSize);
|
|
|
|
|
this->layoutContainer->setFixedSize(windowSize);
|
|
|
|
|
|
|
|
|
|
this->adjustPanels();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InsightWindow::showEvent(QShowEvent* event) {
|
|
|
|
|
this->adjustPanels();
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-06 00:39:40 +01:00
|
|
|
bool InsightWindow::isVariantSupported(const TargetVariant& variant) {
|
|
|
|
|
/*
|
|
|
|
|
* Because the size of the pin body widget is fixed, for all of our target package widgets, we run out of screen
|
|
|
|
|
* estate for target variants with more than 100 pins.
|
|
|
|
|
*
|
|
|
|
|
* This will be addressed at some point, but for now, we just won't support variants with more than 100 pins.
|
|
|
|
|
*/
|
|
|
|
|
if (variant.pinDescriptorsByNumber.size() > 100) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (variant.package == TargetPackage::DIP
|
|
|
|
|
|| variant.package == TargetPackage::SOIC
|
|
|
|
|
|| variant.package == TargetPackage::SSOP
|
|
|
|
|
) {
|
|
|
|
|
// All DIP, SOIC and SSOP 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 || variant.package == TargetPackage::QFN) {
|
|
|
|
|
// All QFP and QFN 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.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this->selectedVariant != nullptr && this->selectedVariant->id == variant->id) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this->targetPackageWidget != nullptr) {
|
|
|
|
|
this->targetPackageWidget->hide();
|
|
|
|
|
this->targetPackageWidget->deleteLater();
|
|
|
|
|
this->targetPackageWidget = nullptr;
|
|
|
|
|
this->ioContainerWidget->setPackageWidget(this->targetPackageWidget);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->selectedVariant = variant;
|
|
|
|
|
this->variantMenu->setTitle(QString::fromStdString(variant->name + " (" + variant->packageName + ")"));
|
|
|
|
|
|
|
|
|
|
if (variant->package == TargetPackage::DIP
|
|
|
|
|
|| variant->package == TargetPackage::SOIC
|
|
|
|
|
|| variant->package == TargetPackage::SSOP
|
|
|
|
|
) {
|
|
|
|
|
this->targetPackageWidget = new InsightTargetWidgets::Dip::DualInlinePackageWidget(
|
|
|
|
|
*variant,
|
|
|
|
|
this->insightWorker,
|
|
|
|
|
this->ioContainerWidget
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
} else if (variant->package == TargetPackage::QFP || variant->package == TargetPackage::QFN) {
|
|
|
|
|
this->targetPackageWidget = new InsightTargetWidgets::Qfp::QuadFlatPackageWidget(
|
|
|
|
|
*variant,
|
|
|
|
|
this->insightWorker,
|
|
|
|
|
this->ioContainerWidget
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this->targetPackageWidget != nullptr) {
|
|
|
|
|
this->ioContainerWidget->setPackageWidget(this->targetPackageWidget);
|
|
|
|
|
this->targetPackageWidget->setTargetState(this->targetState);
|
|
|
|
|
|
|
|
|
|
if (this->targetState == TargetState::STOPPED) {
|
|
|
|
|
this->targetPackageWidget->refreshPinStates([this] {
|
|
|
|
|
if (this->targetState == TargetState::STOPPED) {
|
|
|
|
|
this->targetPackageWidget->setDisabled(false);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->setMinimumSize(
|
|
|
|
|
this->targetPackageWidget->width() + 700,
|
|
|
|
|
this->targetPackageWidget->height() + 450
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this->adjustSize();
|
|
|
|
|
this->targetPackageWidget->show();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-06 21:12:31 +01:00
|
|
|
void InsightWindow::toggleUi(bool disable) {
|
|
|
|
|
this->uiDisabled = disable;
|
|
|
|
|
|
|
|
|
|
if (this->refreshIoInspectionButton != nullptr) {
|
|
|
|
|
this->refreshIoInspectionButton->setDisabled(disable);
|
|
|
|
|
this->refreshIoInspectionButton->repaint();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-30 16:53:24 +01:00
|
|
|
void InsightWindow::activate() {
|
|
|
|
|
auto targetNameLabel = this->footer->findChild<QLabel*>("target-name");
|
|
|
|
|
auto targetIdLabel = this->footer->findChild<QLabel*>("target-id");
|
2021-04-04 21:04:12 +01:00
|
|
|
targetNameLabel->setText(QString::fromStdString(this->targetDescriptor.name));
|
|
|
|
|
targetIdLabel->setText("0x" + QString::fromStdString(this->targetDescriptor.id).remove("0x").toUpper());
|
|
|
|
|
this->variantMenu = this->footer->findChild<QMenu*>("target-variant-menu");
|
|
|
|
|
|
2021-05-30 16:53:24 +01:00
|
|
|
this->ioUnavailableWidget->hide();
|
|
|
|
|
|
|
|
|
|
std::optional<QString> previouslySelectedVariantName;
|
|
|
|
|
if (this->selectedVariant != nullptr) {
|
|
|
|
|
previouslySelectedVariantName = QString::fromStdString(this->selectedVariant->name).toLower();
|
|
|
|
|
this->selectedVariant = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->supportedVariantsByName.clear();
|
|
|
|
|
|
2021-06-20 22:57:09 +01:00
|
|
|
/*
|
|
|
|
|
* We don't want to present the user with duplicate target variants.
|
|
|
|
|
*
|
2021-09-04 18:12:32 +01:00
|
|
|
* In the context of Insight, a variant that doesn't differ in package type or pinout configuration is
|
|
|
|
|
* considered a duplicate.
|
2021-06-20 22:57:09 +01:00
|
|
|
*/
|
|
|
|
|
auto processedVariants = std::vector<TargetVariant>();
|
2021-10-08 23:08:15 +01:00
|
|
|
auto isDuplicateVariant = [&processedVariants] (const TargetVariant& variantA) {
|
2021-06-20 22:57:09 +01:00
|
|
|
return std::ranges::any_of(
|
|
|
|
|
processedVariants.begin(),
|
|
|
|
|
processedVariants.end(),
|
2021-10-08 23:08:15 +01:00
|
|
|
[&variantA, &processedVariants] (const TargetVariant& variantB) {
|
2021-06-20 22:57:09 +01:00
|
|
|
if (variantA.package != variantB.package) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (variantA.pinDescriptorsByNumber.size() != variantB.pinDescriptorsByNumber.size()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (variantA.pinDescriptorsByNumber != variantB.pinDescriptorsByNumber) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2021-04-04 21:04:12 +01:00
|
|
|
for (const auto& targetVariant: this->targetDescriptor.variants) {
|
2021-06-20 22:57:09 +01:00
|
|
|
if (isDuplicateVariant(targetVariant)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-28 20:44:38 +01:00
|
|
|
auto* variantAction = new QAction(this->variantMenu);
|
2021-04-04 21:04:12 +01:00
|
|
|
variantAction->setText(
|
|
|
|
|
QString::fromStdString(targetVariant.name + " (" + targetVariant.packageName + ")")
|
|
|
|
|
);
|
|
|
|
|
|
2021-06-21 00:14:31 +01:00
|
|
|
if (InsightWindow::isVariantSupported(targetVariant)) {
|
2021-05-30 16:53:24 +01:00
|
|
|
auto supportedVariantPtr = &(this->supportedVariantsByName.insert(
|
|
|
|
|
std::pair(QString::fromStdString(targetVariant.name).toLower(), targetVariant)
|
|
|
|
|
).first->second);
|
2021-04-09 20:33:24 +01:00
|
|
|
|
2021-04-04 21:04:12 +01:00
|
|
|
connect(
|
|
|
|
|
variantAction,
|
|
|
|
|
&QAction::triggered,
|
|
|
|
|
this,
|
2021-05-30 16:53:24 +01:00
|
|
|
[this, supportedVariantPtr] {
|
|
|
|
|
this->selectVariant(supportedVariantPtr);
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
variantAction->setEnabled(false);
|
|
|
|
|
variantAction->setText(variantAction->text() + " (unsupported)");
|
2021-05-30 16:53:24 +01:00
|
|
|
}
|
2021-04-04 21:04:12 +01:00
|
|
|
|
|
|
|
|
this->variantMenu->addAction(variantAction);
|
2021-06-20 22:57:09 +01:00
|
|
|
processedVariants.push_back(targetVariant);
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|
|
|
|
|
|
2021-05-30 16:53:24 +01:00
|
|
|
this->variantMenu->setEnabled(true);
|
|
|
|
|
|
2021-10-06 00:39:40 +01:00
|
|
|
Logger::debug("Number of target variants supported by Insight: "
|
|
|
|
|
+ std::to_string(supportedVariantsByName.size()));
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2021-04-09 20:33:24 +01:00
|
|
|
if (!this->supportedVariantsByName.empty()) {
|
2021-05-30 16:53:24 +01:00
|
|
|
if (previouslySelectedVariantName.has_value()
|
|
|
|
|
&& this->supportedVariantsByName.contains(previouslySelectedVariantName.value())
|
2021-10-06 00:39:40 +01:00
|
|
|
) {
|
2021-05-30 16:53:24 +01:00
|
|
|
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)));
|
2021-04-04 21:04:12 +01:00
|
|
|
|
2021-07-17 02:17:13 +01:00
|
|
|
} else {
|
2021-05-30 16:53:24 +01:00
|
|
|
Logger::error("Invalid target variant name \"" + this->targetConfig.variantName.value()
|
2021-04-09 20:33:24 +01:00
|
|
|
+ "\" - no such variant with the given name was found.");
|
2021-04-08 20:42:23 +01:00
|
|
|
}
|
2021-07-17 02:17:13 +01:00
|
|
|
}
|
2021-04-08 20:42:23 +01:00
|
|
|
|
2021-07-17 02:17:13 +01:00
|
|
|
if (this->selectedVariant == nullptr) {
|
|
|
|
|
/*
|
|
|
|
|
* Given that we haven't been able to select a variant at this point, we will just fallback to the first
|
|
|
|
|
* one that is available.
|
|
|
|
|
*/
|
2021-04-09 20:33:24 +01:00
|
|
|
this->selectVariant(&(this->supportedVariantsByName.begin()->second));
|
|
|
|
|
}
|
2021-04-04 21:04:12 +01:00
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
if (this->targetDescriptor.variants.empty()) {
|
|
|
|
|
this->variantMenu->parentWidget()->hide();
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-30 16:53:24 +01:00
|
|
|
this->ioUnavailableWidget->setText(
|
|
|
|
|
"GPIO inspection is not available for this target. "
|
|
|
|
|
"Please report this to Bloom developers by clicking Help -> Report An Issue"
|
|
|
|
|
);
|
2021-04-04 21:04:12 +01:00
|
|
|
this->ioUnavailableWidget->show();
|
|
|
|
|
}
|
2021-04-14 23:17:30 +01:00
|
|
|
|
2021-10-06 00:39:40 +01:00
|
|
|
auto leftPanelLayout = this->leftPanel->layout();
|
2021-09-04 18:11:52 +01:00
|
|
|
this->targetRegistersSidePane = new TargetRegistersPaneWidget(
|
|
|
|
|
this->targetDescriptor,
|
2021-10-17 20:44:40 +01:00
|
|
|
this->insightWorker,
|
2021-10-06 00:39:40 +01:00
|
|
|
this->leftPanel
|
2021-09-04 18:11:52 +01:00
|
|
|
);
|
|
|
|
|
leftPanelLayout->addWidget(this->targetRegistersSidePane);
|
|
|
|
|
this->targetRegistersButton->setChecked(false);
|
|
|
|
|
this->targetRegistersButton->setDisabled(false);
|
|
|
|
|
|
2021-10-17 20:44:40 +01:00
|
|
|
auto bottomPanelLayout = this->bottomPanel->layout();
|
|
|
|
|
if (this->targetDescriptor.memoryDescriptorsByType.contains(TargetMemoryType::RAM)) {
|
|
|
|
|
auto& ramDescriptor = this->targetDescriptor.memoryDescriptorsByType.at(TargetMemoryType::RAM);
|
|
|
|
|
this->ramInspectionPane = new TargetMemoryInspectionPane(
|
|
|
|
|
ramDescriptor,
|
|
|
|
|
this->insightWorker,
|
|
|
|
|
this->bottomPanel
|
|
|
|
|
);
|
|
|
|
|
bottomPanelLayout->addWidget(this->ramInspectionPane);
|
|
|
|
|
this->ramInspectionButton->setChecked(false);
|
|
|
|
|
this->ramInspectionButton->setDisabled(false);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-30 16:53:24 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-04 18:11:52 +01:00
|
|
|
if (this->targetRegistersSidePane != nullptr) {
|
|
|
|
|
this->targetRegistersSidePane->deactivate();
|
|
|
|
|
this->targetRegistersSidePane->deleteLater();
|
|
|
|
|
this->leftPanel->setVisible(false);
|
|
|
|
|
this->targetRegistersButton->setChecked(false);
|
|
|
|
|
this->targetRegistersButton->setDisabled(true);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-30 16:53:24 +01:00
|
|
|
this->ioUnavailableWidget->setText(
|
2021-05-31 00:03:57 +01:00
|
|
|
"Insight deactivated - Bloom has been disconnected from the target.\n\n"
|
|
|
|
|
"Bloom will attempt to reconnect upon the start of a new debug session."
|
2021-05-30 16:53:24 +01:00
|
|
|
);
|
|
|
|
|
this->ioUnavailableWidget->show();
|
|
|
|
|
|
|
|
|
|
this->targetStatusLabel->setText("Unknown");
|
|
|
|
|
this->programCounterValueLabel->setText("-");
|
|
|
|
|
|
|
|
|
|
this->variantMenu->clear();
|
|
|
|
|
this->variantMenu->setEnabled(false);
|
|
|
|
|
|
|
|
|
|
this->toggleUi(true);
|
|
|
|
|
this->activated = false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-06 00:39:40 +01:00
|
|
|
void InsightWindow::adjustPanels() {
|
|
|
|
|
const auto targetPackageWidgetSize = (this->targetPackageWidget != nullptr)
|
|
|
|
|
? this->targetPackageWidget->size() : QSize();
|
|
|
|
|
const auto containerSize = this->container->size();
|
|
|
|
|
|
2021-08-24 20:10:45 +01:00
|
|
|
/*
|
2021-10-06 00:39:40 +01:00
|
|
|
* The purpose of the -20 is to ensure there is some padding between the panel borders and the
|
|
|
|
|
* target package widget. Looks nicer with the padding.
|
2021-08-24 20:10:45 +01:00
|
|
|
*/
|
2021-10-06 00:39:40 +01:00
|
|
|
this->leftPanel->setMaximumResize(
|
|
|
|
|
std::max(
|
|
|
|
|
this->leftPanel->getMinimumResize(),
|
|
|
|
|
containerSize.width() - targetPackageWidgetSize.width() - this->leftMenuBar->width() - 20
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
this->bottomPanel->setMaximumResize(
|
|
|
|
|
std::max(
|
|
|
|
|
this->bottomPanel->getMinimumResize(),
|
|
|
|
|
containerSize.height() - targetPackageWidgetSize.height() - this->bottomMenuBar->height() - 20
|
|
|
|
|
)
|
|
|
|
|
);
|
2021-04-04 21:04:12 +01:00
|
|
|
}
|