From 8a473473db96414573035eef3fe65da9c49f315a Mon Sep 17 00:00:00 2001 From: Nav Date: Tue, 18 Feb 2025 00:35:39 +0000 Subject: [PATCH] Insight GUI changes: - New target pinout widgets - Made auto-refresh of registers and GPIO pad states optional (via context menu on refresh tool button) --- src/Insight/CMakeLists.txt | 34 +- .../InsightWindow/InsightWindow.cpp | 251 +++----- .../InsightWindow/InsightWindow.hpp | 21 +- .../Stylesheets/InsightWindow.qss | 4 + .../InsightWindow/UiFiles/InsightWindow.ui | 50 +- .../UserInterfaces/InsightWindow/UiLoader.cpp | 10 - .../Widgets/PinoutWidgets/Dip/DipPinout.cpp | 335 +++++++++++ .../Widgets/PinoutWidgets/Dip/DipPinout.hpp | 70 +++ .../PinoutWidgets/GpioDirectionLabel.cpp | 17 + .../PinoutWidgets/GpioDirectionLabel.hpp | 18 + .../PinoutWidgets/GpioDisabledLabel.cpp | 9 + .../PinoutWidgets/GpioDisabledLabel.hpp | 12 + .../Widgets/PinoutWidgets/GpioStateLabel.cpp | 22 + .../Widgets/PinoutWidgets/GpioStateLabel.hpp | 20 + .../PinoutWidgets/HorizontalLabelGroup.cpp | 108 ++++ .../PinoutWidgets/HorizontalLabelGroup.hpp | 69 +++ .../HorizontalLabelGroupPinPair.hpp | 13 + .../PinoutWidgets/HorizontalLabelGroupSet.cpp | 55 ++ .../PinoutWidgets/HorizontalLabelGroupSet.hpp | 34 ++ .../Widgets/PinoutWidgets/Label.cpp | 45 ++ .../Widgets/PinoutWidgets/Label.hpp | 45 ++ .../PinoutWidgets/LabelGroupInterface.hpp | 15 + .../Widgets/PinoutWidgets/PadLabels.cpp | 18 + .../Widgets/PinoutWidgets/PadLabels.hpp | 17 + .../Widgets/PinoutWidgets/PadNameLabel.cpp | 26 + .../Widgets/PinoutWidgets/PadNameLabel.hpp | 25 + .../Widgets/PinoutWidgets/Pin.cpp | 51 ++ .../Widgets/PinoutWidgets/Pin.hpp | 47 ++ .../Widgets/PinoutWidgets/PinNumberLabel.cpp | 22 + .../Widgets/PinoutWidgets/PinNumberLabel.hpp | 22 + .../Widgets/PinoutWidgets/PinoutContainer.cpp | 52 ++ .../Widgets/PinoutWidgets/PinoutContainer.hpp | 28 + .../Widgets/PinoutWidgets/PinoutItem.hpp | 12 + .../Widgets/PinoutWidgets/PinoutScene.cpp | 414 +++++++++++++ .../Widgets/PinoutWidgets/PinoutScene.hpp | 62 ++ .../Widgets/PinoutWidgets/PinoutState.hpp | 12 + .../Widgets/PinoutWidgets/Qfp/QfpPinout.cpp | 552 ++++++++++++++++++ .../Widgets/PinoutWidgets/Qfp/QfpPinout.hpp | 81 +++ .../PinoutWidgets/VerticalLabelGroup.cpp | 187 ++++++ .../PinoutWidgets/VerticalLabelGroup.hpp | 57 ++ .../VerticalLabelGroupPinPair.hpp | 13 + .../PinoutWidgets/VerticalLabelGroupSet.cpp | 120 ++++ .../PinoutWidgets/VerticalLabelGroupSet.hpp | 39 ++ .../Widgets/TargetWidgets/DIP/BodyWidget.cpp | 87 --- .../Widgets/TargetWidgets/DIP/BodyWidget.hpp | 49 -- .../DIP/DualInlinePackageWidget.cpp | 273 --------- .../DIP/DualInlinePackageWidget.hpp | 47 -- .../TargetWidgets/DIP/PinBodyWidget.cpp | 49 -- .../TargetWidgets/DIP/PinBodyWidget.hpp | 30 - .../Widgets/TargetWidgets/DIP/PinWidget.cpp | 58 -- .../Widgets/TargetWidgets/DIP/PinWidget.hpp | 62 -- .../DIP/Stylesheets/DualInlinePackage.qss | 20 - .../Widgets/TargetWidgets/QFP/BodyWidget.cpp | 52 -- .../Widgets/TargetWidgets/QFP/BodyWidget.hpp | 43 -- .../TargetWidgets/QFP/PinBodyWidget.cpp | 57 -- .../TargetWidgets/QFP/PinBodyWidget.hpp | 35 -- .../Widgets/TargetWidgets/QFP/PinWidget.cpp | 114 ---- .../Widgets/TargetWidgets/QFP/PinWidget.hpp | 63 -- .../QFP/QuadFlatPackageWidget.cpp | 448 -------------- .../QFP/QuadFlatPackageWidget.hpp | 48 -- .../QFP/Stylesheets/QuadFlatPackage.qss | 7 - .../TargetWidgets/TargetPackageWidget.cpp | 93 --- .../TargetWidgets/TargetPackageWidget.hpp | 55 -- .../TargetPackageWidgetContainer.cpp | 30 - .../TargetPackageWidgetContainer.hpp | 25 - .../TargetWidgets/TargetPinBodyWidget.cpp | 92 --- .../TargetWidgets/TargetPinBodyWidget.hpp | 118 ---- .../Widgets/TargetWidgets/TargetPinWidget.cpp | 56 -- .../Widgets/TargetWidgets/TargetPinWidget.hpp | 55 -- src/ProjectSettings.cpp | 11 + src/ProjectSettings.hpp | 3 + src/Targets/Microchip/Avr8/Avr8.cpp | 4 +- src/Targets/RiscV/Wch/WchRiscV.cpp | 16 +- .../TargetDescriptionFile.cpp | 2 +- src/Targets/TargetGpioPadState.hpp | 15 +- 75 files changed, 2927 insertions(+), 2304 deletions(-) create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Dip/DipPinout.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Dip/DipPinout.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDirectionLabel.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDirectionLabel.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDisabledLabel.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDisabledLabel.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioStateLabel.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioStateLabel.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/HorizontalLabelGroup.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/HorizontalLabelGroup.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/HorizontalLabelGroupPinPair.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/HorizontalLabelGroupSet.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/HorizontalLabelGroupSet.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Label.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Label.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/LabelGroupInterface.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PadLabels.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PadLabels.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PadNameLabel.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PadNameLabel.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Pin.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Pin.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PinNumberLabel.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PinNumberLabel.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PinoutContainer.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PinoutContainer.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PinoutItem.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PinoutScene.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PinoutScene.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PinoutState.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Qfp/QfpPinout.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Qfp/QfpPinout.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/VerticalLabelGroup.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/VerticalLabelGroup.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/VerticalLabelGroupPinPair.hpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/VerticalLabelGroupSet.cpp create mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/VerticalLabelGroupSet.hpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/BodyWidget.cpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/BodyWidget.hpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/DualInlinePackageWidget.cpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/DualInlinePackageWidget.hpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/PinBodyWidget.cpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/PinBodyWidget.hpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/PinWidget.cpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/PinWidget.hpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/Stylesheets/DualInlinePackage.qss delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/BodyWidget.cpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/BodyWidget.hpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/PinBodyWidget.cpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/PinBodyWidget.hpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/PinWidget.cpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/PinWidget.hpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/QuadFlatPackageWidget.cpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/QuadFlatPackageWidget.hpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/Stylesheets/QuadFlatPackage.qss delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/TargetPackageWidget.cpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/TargetPackageWidget.hpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/TargetPackageWidgetContainer.cpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/TargetPackageWidgetContainer.hpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/TargetPinBodyWidget.cpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/TargetPinBodyWidget.hpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/TargetPinWidget.cpp delete mode 100644 src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/TargetPinWidget.hpp diff --git a/src/Insight/CMakeLists.txt b/src/Insight/CMakeLists.txt index fa28394f..77b315bf 100755 --- a/src/Insight/CMakeLists.txt +++ b/src/Insight/CMakeLists.txt @@ -54,19 +54,23 @@ target_sources( ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/Dialog/Dialog.cpp ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/ConfirmationDialog.cpp - # Target package widgets - ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetWidgets/TargetPackageWidgetContainer.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetWidgets/TargetPackageWidget.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetWidgets/TargetPinWidget.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetWidgets/TargetPinBodyWidget.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/DualInlinePackageWidget.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/PinWidget.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/PinBodyWidget.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/BodyWidget.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/QuadFlatPackageWidget.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/PinWidget.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/PinBodyWidget.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/BodyWidget.cpp + # Target pinouts + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PinoutContainer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PinoutScene.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/VerticalLabelGroup.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/VerticalLabelGroupSet.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/HorizontalLabelGroup.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/HorizontalLabelGroupSet.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Label.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PadLabels.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PinNumberLabel.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PadNameLabel.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDirectionLabel.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioStateLabel.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDisabledLabel.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Pin.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Qfp/QfpPinout.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Dip/DipPinout.cpp # Target register side pane ${CMAKE_CURRENT_SOURCE_DIR}/UserInterfaces/InsightWindow/Widgets/TargetRegistersPane/TargetRegistersPaneWidget.cpp @@ -149,10 +153,6 @@ qt_add_resources( "./UserInterfaces/InsightWindow/Widgets/TaskWindow/UiFiles/TaskWindow.ui" "./UserInterfaces/InsightWindow/Widgets/TaskWindow/Stylesheets/TaskWindow.qss" - # Target package widgets - "./UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/Stylesheets/DualInlinePackage.qss" - "./UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/Stylesheets/QuadFlatPackage.qss" - # Target registers pane "./UserInterfaces/InsightWindow/Widgets/TargetRegistersPane/UiFiles/TargetRegistersSidePane.ui" "./UserInterfaces/InsightWindow/Widgets/TargetRegistersPane/Images/collapse-all.svg" diff --git a/src/Insight/UserInterfaces/InsightWindow/InsightWindow.cpp b/src/Insight/UserInterfaces/InsightWindow/InsightWindow.cpp index 00775043..f5cbd51b 100644 --- a/src/Insight/UserInterfaces/InsightWindow/InsightWindow.cpp +++ b/src/Insight/UserInterfaces/InsightWindow/InsightWindow.cpp @@ -7,9 +7,6 @@ #include "UiLoader.hpp" #include "Widgets/RotatableLabel.hpp" -#include "Widgets/TargetWidgets/DIP/DualInlinePackageWidget.hpp" -#include "Widgets/TargetWidgets/QFP/QuadFlatPackageWidget.hpp" - #include "Widgets/TargetMemoryInspectionPane/ToolButton.hpp" #include "src/Logger/Logger.hpp" @@ -28,14 +25,14 @@ using Targets::TargetExecutionState; using Targets::TargetPinDescriptor; InsightWindow::InsightWindow( - InsightProjectSettings& insightProjectSettings, + InsightProjectSettings& settings, const InsightConfig& insightConfig, const EnvironmentConfig& environmentConfig, const TargetDescriptor& targetDescriptor, const TargetState& targetState ) : QMainWindow(nullptr) - , insightProjectSettings(insightProjectSettings) + , settings(settings) , insightConfig(insightConfig) , environmentConfig(environmentConfig) , targetConfig(environmentConfig.targetConfig) @@ -48,10 +45,10 @@ InsightWindow::InsightWindow( constexpr auto defaultWindowSize = QSize{1000, 500}; - const auto windowSize = this->insightProjectSettings.mainWindowSize.has_value() + const auto windowSize = this->settings.mainWindowSize.has_value() ? QSize{ - std::max(this->insightProjectSettings.mainWindowSize->width(), defaultWindowSize.width()), - std::max(this->insightProjectSettings.mainWindowSize->height(), defaultWindowSize.height()) + std::max(this->settings.mainWindowSize->width(), defaultWindowSize.width()), + std::max(this->settings.mainWindowSize->height(), defaultWindowSize.height()) } : defaultWindowSize; @@ -95,9 +92,6 @@ InsightWindow::InsightWindow( this->mainMenuBar = this->windowContainer->findChild("menu-bar"); this->layoutContainer->layout()->setMenuBar(this->mainMenuBar); this->container = this->layoutContainer->findChild("container"); - this->ioContainerWidget = this->windowContainer->findChild( - "io-container" - ); auto* horizontalContentLayout = this->container->findChild("horizontal-content-layout"); auto* verticalContentLayout = this->container->findChild("vertical-content-layout"); @@ -110,21 +104,27 @@ InsightWindow::InsightWindow( auto* openAboutWindowAction = helpMenu->findChild("open-about-dialogue"); this->header = this->windowContainer->findChild("header"); + this->refreshIoInspectionButton = this->header->findChild("refresh-io-inspection-btn"); + this->refreshRegistersOnTargetStopAction = this->refreshIoInspectionButton->findChild("refresh-regs"); + this->refreshGpioOnTargetStopAction = this->refreshIoInspectionButton->findChild("refresh-gpio"); + + this->setRefreshRegistersOnTargetStopped(this->settings.refreshRegistersOnTargetStopped); + this->setRefreshGpioOnTargetStopped(this->settings.refreshGpioOnTargetStopped); // Create panel states - if (!this->insightProjectSettings.leftPanelState.has_value()) { - this->insightProjectSettings.leftPanelState = PanelState{}; + if (!this->settings.leftPanelState.has_value()) { + this->settings.leftPanelState = PanelState{}; } - if (!this->insightProjectSettings.bottomPanelState.has_value()) { - this->insightProjectSettings.bottomPanelState = PanelState{}; + if (!this->settings.bottomPanelState.has_value()) { + this->settings.bottomPanelState = PanelState{}; } this->leftMenuBar = this->container->findChild("left-side-menu-bar"); this->leftPanel = new PanelWidget{ PanelWidgetType::LEFT, - this->insightProjectSettings.leftPanelState.value(), + this->settings.leftPanelState.value(), this->container }; this->leftPanel->setObjectName("left-panel"); @@ -139,11 +139,15 @@ InsightWindow::InsightWindow( registersBtnLabel->setContentsMargins(4, 4, 10, 2); targetRegisterButtonLayout->insertWidget(0, registersBtnLabel, 0, Qt::AlignTop); + this->pinoutContainerWidget = new PinoutWidgets::PinoutContainer{this->targetDescriptor, this}; + this->pinoutScene = this->pinoutContainerWidget->pinoutScene; + horizontalContentLayout->insertWidget(1, this->pinoutContainerWidget); + this->bottomMenuBar = this->container->findChild("bottom-menu-bar"); this->bottomMenuBarLayout = this->bottomMenuBar->findChild(); this->bottomPanel = new PanelWidget{ PanelWidgetType::BOTTOM, - this->insightProjectSettings.bottomPanelState.value(), + this->settings.bottomPanelState.value(), this->container }; this->bottomPanel->setObjectName("bottom-panel"); @@ -228,7 +232,27 @@ InsightWindow::InsightWindow( this->refreshIoInspectionButton, &QToolButton::clicked, this, - &InsightWindow::refresh + [this] () { + this->refresh(true, true); + } + ); + + QObject::connect( + this->refreshRegistersOnTargetStopAction, + &QAction::triggered, + this, + [this] (bool checked) { + this->setRefreshRegistersOnTargetStopped(checked); + } + ); + + QObject::connect( + this->refreshGpioOnTargetStopAction, + &QAction::triggered, + this, + [this] (bool checked) { + this->setRefreshGpioOnTargetStopped(checked); + } ); // Panel connections @@ -276,7 +300,7 @@ void InsightWindow::resizeEvent(QResizeEvent* event) { this->adjustPanels(); - this->insightProjectSettings.mainWindowSize = windowSize; + this->settings.mainWindowSize = windowSize; } void InsightWindow::showEvent(QShowEvent* event) { @@ -288,46 +312,6 @@ void InsightWindow::closeEvent(QCloseEvent* event) { return QMainWindow::closeEvent(event); } -bool InsightWindow::isPinoutSupported(const Targets::TargetPinoutDescriptor& pinoutDescriptor) { - using Targets::TargetPinoutType; - - const auto pinCount = pinoutDescriptor.pinDescriptors.size(); - - if (pinCount > 100) { - return false; - } - - if ( - pinoutDescriptor.type != TargetPinoutType::DIP - && pinoutDescriptor.type != TargetPinoutType::SOIC - && pinoutDescriptor.type != TargetPinoutType::SSOP - && pinoutDescriptor.type != TargetPinoutType::QFP - && pinoutDescriptor.type != TargetPinoutType::QFN - ) { - return false; - } - - if ( - ( - pinoutDescriptor.type == TargetPinoutType::DIP - || pinoutDescriptor.type == TargetPinoutType::SOIC - || pinoutDescriptor.type == TargetPinoutType::SSOP - ) - && pinCount % 2 != 0 - ) { - return false; - } - - if ( - (pinoutDescriptor.type == TargetPinoutType::QFP || pinoutDescriptor.type == TargetPinoutType::QFN) - && (pinCount % 4 != 0 || pinCount <= 4) - ) { - return false; - } - - return true; -} - void InsightWindow::setUiDisabled(bool disable) { this->uiDisabled = disable; @@ -346,7 +330,7 @@ void InsightWindow::populateVariantMenu() { QString::fromStdString(variantDescriptor.name + " (" + pinoutDescriptor.name + ")") ); - if (InsightWindow::isPinoutSupported(pinoutDescriptor)) { + if (this->pinoutScene->isPinoutSupported(pinoutDescriptor)) { QObject::connect( variantAction, &QAction::triggered, @@ -384,17 +368,15 @@ void InsightWindow::selectDefaultVariant() { const auto& descriptor = variantDescriptor->get(); const auto& pinoutDescriptor = this->targetDescriptor.getPinoutDescriptor(descriptor.pinoutKey); - if (InsightWindow::isPinoutSupported(pinoutDescriptor)) { + if (this->pinoutScene->isPinoutSupported(pinoutDescriptor)) { this->selectVariant(&descriptor); return; - - } else { - Logger::error( - "Unsupported target variant (\"" + descriptor.name - + "\") provided via 'defaultVariantKey' parameter" - ); } + Logger::error( + "Unsupported target variant (\"" + descriptor.name + "\") provided via 'defaultVariantKey' parameter" + ); + } else { Logger::error( "Invalid target variant key `" + *(this->insightConfig.defaultVariantKey) @@ -404,16 +386,16 @@ void InsightWindow::selectDefaultVariant() { } // Try the previously selected variant - if (this->insightProjectSettings.selectedVariantKey.has_value()) { + if (this->settings.selectedVariantKey.has_value()) { const auto variantDescriptor = this->targetDescriptor.tryGetVariantDescriptor( - *(this->insightProjectSettings.selectedVariantKey) + *(this->settings.selectedVariantKey) ); if (variantDescriptor.has_value()) { const auto& descriptor = variantDescriptor->get(); const auto& pinoutDescriptor = this->targetDescriptor.getPinoutDescriptor(descriptor.pinoutKey); - if (InsightWindow::isPinoutSupported(pinoutDescriptor)) { + if (this->pinoutScene->isPinoutSupported(pinoutDescriptor)) { this->selectVariant(&descriptor); return; } @@ -427,7 +409,7 @@ void InsightWindow::selectDefaultVariant() { for (const auto& [variantKey, variantDescriptor] : this->targetDescriptor.variantDescriptorsByKey) { const auto& pinoutDescriptor = this->targetDescriptor.getPinoutDescriptor(variantDescriptor.pinoutKey); - if (InsightWindow::isPinoutSupported(pinoutDescriptor)) { + if (this->pinoutScene->isPinoutSupported(pinoutDescriptor)) { this->selectVariant(&variantDescriptor); return; } @@ -445,65 +427,26 @@ void InsightWindow::selectVariant(const Targets::TargetVariantDescriptor* varian } const auto& pinoutDescriptor = this->targetDescriptor.getPinoutDescriptor(variantDescriptor->pinoutKey); - if (!InsightWindow::isPinoutSupported(pinoutDescriptor)) { - Logger::error("Attempted to select unsupported target variant."); - return; - } + assert(this->pinoutScene->isPinoutSupported(pinoutDescriptor)); - if (this->targetPackageWidget != nullptr) { - this->targetPackageWidget->hide(); - this->targetPackageWidget->deleteLater(); - this->targetPackageWidget = nullptr; - this->ioContainerWidget->setPackageWidget(this->targetPackageWidget); - } + this->pinoutScene->setPinout(pinoutDescriptor); this->selectedVariantDescriptor = variantDescriptor; - this->insightProjectSettings.selectedVariantKey = variantDescriptor->key; + this->settings.selectedVariantKey = variantDescriptor->key; this->variantMenu->setTitle(QString::fromStdString(variantDescriptor->name + " (" + pinoutDescriptor.name + ")")); - - if ( - pinoutDescriptor.type == TargetPinoutType::DIP - || pinoutDescriptor.type == TargetPinoutType::SOIC - || pinoutDescriptor.type == TargetPinoutType::SSOP - ) { - this->targetPackageWidget = new InsightTargetWidgets::Dip::DualInlinePackageWidget{ - *variantDescriptor, - pinoutDescriptor, - this->targetDescriptor, - this->targetState, - this->ioContainerWidget - }; - - } else if (pinoutDescriptor.type == TargetPinoutType::QFP || pinoutDescriptor.type == TargetPinoutType::QFN) { - this->targetPackageWidget = new InsightTargetWidgets::Qfp::QuadFlatPackageWidget{ - *variantDescriptor, - pinoutDescriptor, - this->targetDescriptor, - this->targetState, - this->ioContainerWidget - }; - } - - if (this->targetPackageWidget != nullptr) { - this->ioContainerWidget->setPackageWidget(this->targetPackageWidget); - - this->adjustPanels(); - this->adjustMinimumSize(); - this->targetPackageWidget->show(); - } } void InsightWindow::createPanes() { // Target registers pane - if (!this->insightProjectSettings.registersPaneState.has_value()) { - this->insightProjectSettings.registersPaneState = PaneState{false, true, std::nullopt}; + if (!this->settings.registersPaneState.has_value()) { + this->settings.registersPaneState = PaneState{false, true, std::nullopt}; } auto* leftPanelLayout = this->leftPanel->layout(); this->targetRegistersSidePane = new TargetRegistersPaneWidget{ this->targetDescriptor, this->targetState, - *(this->insightProjectSettings.registersPaneState), + *(this->settings.registersPaneState), this->leftPanel }; leftPanelLayout->addWidget(this->targetRegistersSidePane); @@ -538,11 +481,11 @@ void InsightWindow::createPanes() { segmentDescriptor, this->targetDescriptor, this->targetState, - this->insightProjectSettings.findOrCreateMemoryInspectionPaneSettings( + this->settings.findOrCreateMemoryInspectionPaneSettings( QString::fromStdString(addressSpaceDescriptor.key), QString::fromStdString(segmentDescriptor.key) ), - this->insightProjectSettings.findOrCreateMemoryInspectionPaneState( + this->settings.findOrCreateMemoryInspectionPaneState( QString::fromStdString(addressSpaceDescriptor.key), QString::fromStdString(segmentDescriptor.key) ), @@ -598,29 +541,13 @@ void InsightWindow::createPanes() { } void InsightWindow::adjustPanels() { - const auto targetPackageWidgetSize = (this->targetPackageWidget != nullptr) - ? this->targetPackageWidget->size() : QSize{}; const auto containerSize = this->size(); if (!this->isVisible()) { return; } - /* - * 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. - */ - this->leftPanel->setMaximumResize( - std::max( - this->leftPanel->getMinimumResize(), - containerSize.width() - targetPackageWidgetSize.width() - this->leftMenuBar->width() - 20 - ) - ); - - /* - * Allow the bottom panel to overlap the target package widget (because the target package widget can - * occupy a lot of space and become an annoyance if the bottom panel is restricted too much). - */ + this->leftPanel->setMaximumResize(std::max(this->leftPanel->getMinimumResize(), containerSize.width() / 2)); this->bottomPanel->setMaximumResize( std::max( this->bottomPanel->getMinimumResize(), @@ -632,26 +559,10 @@ void InsightWindow::adjustPanels() { } void InsightWindow::adjustMinimumSize() { - static const auto absoluteMinimum = QSize{900, 400}; - - /* - * On X11, the QScreen::availableGeometry() function may return the full geometry of the screen, without - * accounting for reserved areas for window managers and other decorations. - * - * Because of this, we always use QScreen::geometry() and account for reserved areas ourselves. It's near - * impossible to do this accurately, so we just subtract 200 from the width and height, and hope that it's - * enough. - */ - const auto screenSize = this->screen()->availableGeometry().size(); - const auto absoluteMaximum = QSize{screenSize.width() - 200, screenSize.height() - 200}; + static constexpr auto absoluteMinimum = QSize{900, 400}; auto minSize = QSize{}; - if (this->targetPackageWidget != nullptr) { - minSize.setWidth(this->targetPackageWidget->width() + 250); - minSize.setHeight(this->targetPackageWidget->height() + 150); - } - if (this->leftPanel->isVisible()) { minSize.setWidth(minSize.width() + this->leftPanel->getMinimumResize()); } @@ -661,8 +572,8 @@ void InsightWindow::adjustMinimumSize() { } this->setMinimumSize( - std::min(std::max(minSize.width(), absoluteMinimum.width()), absoluteMaximum.width()), - std::min(std::max(minSize.height(), absoluteMinimum.height()), absoluteMaximum.height()) + std::max(minSize.width(), absoluteMinimum.width()), + std::max(minSize.height(), absoluteMinimum.height()) ); } @@ -670,10 +581,15 @@ void InsightWindow::onTargetStateUpdate(TargetState newState, Targets::TargetSta const auto targetStopped = newState.executionState == TargetExecutionState::STOPPED; this->setUiDisabled(!targetStopped); - if (this->targetPackageWidget != nullptr) { - this->targetPackageWidget->setDisabled(!targetStopped); + if (targetStopped && (this->settings.refreshRegistersOnTargetStopped || this->settings.refreshGpioOnTargetStopped)) { + this->refresh( + this->settings.refreshRegistersOnTargetStopped, + this->settings.refreshGpioOnTargetStopped + ); } + this->pinoutScene->setDisabled(!targetStopped); + switch (newState.executionState) { case TargetExecutionState::STOPPED: { this->targetStatusLabel->setText("Stopped"); @@ -698,8 +614,17 @@ void InsightWindow::onTargetStateUpdate(TargetState newState, Targets::TargetSta ); } +void InsightWindow::setRefreshRegistersOnTargetStopped(bool enabled) { + this->refreshRegistersOnTargetStopAction->setChecked(enabled); + this->settings.refreshRegistersOnTargetStopped = enabled; +} -void InsightWindow::refresh() { +void InsightWindow::setRefreshGpioOnTargetStopped(bool enabled) { + this->refreshGpioOnTargetStopAction->setChecked(enabled); + this->settings.refreshGpioOnTargetStopped = enabled; +} + +void InsightWindow::refresh(bool refreshRegisters, bool refreshGpio) { if (this->targetState.executionState != TargetExecutionState::STOPPED) { return; } @@ -707,18 +632,18 @@ void InsightWindow::refresh() { this->refreshIoInspectionButton->startSpin(); this->refreshIoInspectionButton->setDisabled(true); - if (this->targetPackageWidget != nullptr) { + if (refreshGpio) { this->refreshPadStates(); } const auto callback = [this] { this->refreshIoInspectionButton->stopSpin(); this->refreshIoInspectionButton->setDisabled( - this->targetState.executionState != TargetExecutionState::STOPPED + this->targetState.executionState != TargetExecutionState::STOPPED ); }; - if (this->targetRegistersSidePane != nullptr && this->targetRegistersSidePane->state.activated) { + if (refreshRegisters && this->targetRegistersSidePane != nullptr && this->targetRegistersSidePane->state.activated) { this->targetRegistersSidePane->refreshRegisterValues(std::nullopt, callback); } else { @@ -727,11 +652,11 @@ void InsightWindow::refresh() { } void InsightWindow::refreshPadStates() { - this->targetPackageWidget->setDisabled(true); + this->pinoutScene->setDisabled(true); - this->targetPackageWidget->refreshPadStates([this] { + this->pinoutScene->refreshPadStates([this] { if (this->targetState.executionState == TargetExecutionState::STOPPED) { - this->targetPackageWidget->setDisabled(false); + this->pinoutScene->setDisabled(false); } }); } diff --git a/src/Insight/UserInterfaces/InsightWindow/InsightWindow.hpp b/src/Insight/UserInterfaces/InsightWindow/InsightWindow.hpp index a5158ee6..32aae4fd 100644 --- a/src/Insight/UserInterfaces/InsightWindow/InsightWindow.hpp +++ b/src/Insight/UserInterfaces/InsightWindow/InsightWindow.hpp @@ -17,8 +17,8 @@ #include "Widgets/Label.hpp" #include "Widgets/SvgToolButton.hpp" -#include "Widgets/TargetWidgets/TargetPackageWidgetContainer.hpp" -#include "Widgets/TargetWidgets/TargetPackageWidget.hpp" +#include "Widgets/PinoutWidgets/PinoutContainer.hpp" +#include "Widgets/PinoutWidgets/PinoutScene.hpp" #include "Widgets/PanelWidget.hpp" #include "Widgets/TargetRegistersPane/TargetRegistersPaneWidget.hpp" #include "Widgets/TargetMemoryInspectionPane/TargetMemoryInspectionPane.hpp" @@ -33,7 +33,7 @@ class InsightWindow: public QMainWindow public: InsightWindow( - InsightProjectSettings& insightProjectSettings, + InsightProjectSettings& settings, const InsightConfig& insightConfig, const EnvironmentConfig& environmentConfig, const Targets::TargetDescriptor& targetDescriptor, @@ -46,7 +46,7 @@ protected: void closeEvent(QCloseEvent* event) override; private: - InsightProjectSettings& insightProjectSettings; + InsightProjectSettings& settings; InsightConfig insightConfig; EnvironmentConfig environmentConfig; @@ -65,15 +65,18 @@ private: AboutWindow* aboutWindowWidget = nullptr; QWidget* header = nullptr; + Widgets::SvgToolButton* refreshIoInspectionButton = nullptr; + QAction* refreshRegistersOnTargetStopAction = nullptr; + QAction* refreshGpioOnTargetStopAction = nullptr; QWidget* leftMenuBar = nullptr; Widgets::PanelWidget* leftPanel = nullptr; Widgets::TargetRegistersPaneWidget* targetRegistersSidePane = nullptr; QToolButton* targetRegistersButton = nullptr; - Widgets::InsightTargetWidgets::TargetPackageWidgetContainer* ioContainerWidget = nullptr; - Widgets::InsightTargetWidgets::TargetPackageWidget* targetPackageWidget = nullptr; + Widgets::PinoutWidgets::PinoutContainer* pinoutContainerWidget = nullptr; + Widgets::PinoutWidgets::PinoutScene* pinoutScene = nullptr; QWidget* bottomMenuBar = nullptr; QHBoxLayout* bottomMenuBarLayout = nullptr; @@ -88,8 +91,6 @@ private: const Targets::TargetVariantDescriptor* selectedVariantDescriptor = nullptr; bool uiDisabled = false; - static bool isPinoutSupported(const Targets::TargetPinoutDescriptor& pinoutDescriptor); - void setUiDisabled(bool disable); void populateVariantMenu(); @@ -101,7 +102,9 @@ private: void adjustMinimumSize(); void onTargetStateUpdate(Targets::TargetState newState, Targets::TargetState previousState); - void refresh(); + void setRefreshRegistersOnTargetStopped(bool enabled); + void setRefreshGpioOnTargetStopped(bool enabled); + void refresh(bool refreshRegisters, bool refreshGpio); void refreshPadStates(); void openReportIssuesUrl(); void openGettingStartedUrl(); diff --git a/src/Insight/UserInterfaces/InsightWindow/Stylesheets/InsightWindow.qss b/src/Insight/UserInterfaces/InsightWindow/Stylesheets/InsightWindow.qss index 2ad74ea0..1b50786b 100644 --- a/src/Insight/UserInterfaces/InsightWindow/Stylesheets/InsightWindow.qss +++ b/src/Insight/UserInterfaces/InsightWindow/Stylesheets/InsightWindow.qss @@ -180,6 +180,10 @@ QToolTip { border: none; } +#pinout-widget-container { + background-color: transparent; +} + /* Bottom menu bar & panels */ #bottom-menu-bar { background-color: transparent; diff --git a/src/Insight/UserInterfaces/InsightWindow/UiFiles/InsightWindow.ui b/src/Insight/UserInterfaces/InsightWindow/UiFiles/InsightWindow.ui index 0f80dfa4..65280ec0 100644 --- a/src/Insight/UserInterfaces/InsightWindow/UiFiles/InsightWindow.ui +++ b/src/Insight/UserInterfaces/InsightWindow/UiFiles/InsightWindow.ui @@ -87,8 +87,34 @@ :/compiled/src/Insight/UserInterfaces/InsightWindow/Images/refresh-disabled.svg - Refresh Registers And GPIO Pin States + Refresh registers and GPIO pad states (right-click for auto-refresh options) + + QToolButton::InstantPopup + + + true + + + + + + + Refresh registers after target execution stops + + + true + + + + + Refresh GPIO pad states after target execution stops + + + true + + + @@ -198,27 +224,7 @@ 0 - - - - - - - - - - false - - Qt::AlignCenter - - - - - - - - - - + diff --git a/src/Insight/UserInterfaces/InsightWindow/UiLoader.cpp b/src/Insight/UserInterfaces/InsightWindow/UiLoader.cpp index b02edb65..11abc690 100644 --- a/src/Insight/UserInterfaces/InsightWindow/UiLoader.cpp +++ b/src/Insight/UserInterfaces/InsightWindow/UiLoader.cpp @@ -12,7 +12,6 @@ #include "Widgets/SvgWidget.hpp" #include "Widgets/SvgToolButton.hpp" #include "Widgets/ExpandingHeightScrollAreaWidget.hpp" -#include "Widgets/TargetWidgets/TargetPackageWidgetContainer.hpp" using namespace Widgets; @@ -101,15 +100,6 @@ UiLoader::UiLoader(QObject* parent) return widget; } }, - { - "TargetPackageWidgetContainer", - [this] (QWidget* parent, const QString& name) { - auto* widget = new InsightTargetWidgets::TargetPackageWidgetContainer{parent}; - widget->setObjectName(name); - widget->setStyleSheet(parent->styleSheet()); - return widget; - } - }, }; } diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Dip/DipPinout.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Dip/DipPinout.cpp new file mode 100644 index 00000000..d9d82fc2 --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Dip/DipPinout.cpp @@ -0,0 +1,335 @@ +#include "DipPinout.hpp" + +#include +#include + +#include "src/Services/StringService.hpp" + +namespace Widgets::PinoutWidgets +{ + DipPinout::DipPinout( + const Targets::TargetPinoutDescriptor& pinoutDescriptor, + const Targets::TargetDescriptor& targetDescriptor, + const PinoutState& pinoutState + ) + : packageBodySize({ + (Pin::WIDTH + DipPinout::PIN_MARGIN) * static_cast(pinoutDescriptor.pinDescriptors.size() / 2) + - DipPinout::PIN_MARGIN + (DipPinout::PACKAGE_PADDING * 2), + std::max( + std::min(static_cast(pinoutDescriptor.pinDescriptors.size()) * 8, DipPinout::MAX_PACKAGE_HEIGHT), + DipPinout::MIN_PACKAGE_HEIGHT + ) + }) + , packageBodyPosition({}) + , pinoutDescriptor(pinoutDescriptor) + , pinoutState(pinoutState) + { + assert((pinoutDescriptor.pinDescriptors.size() % 2) == 0); + auto sortedPinDescriptors = std::vector{}; + sortedPinDescriptors.reserve(pinoutDescriptor.pinDescriptors.size()); + + std::transform( + pinoutDescriptor.pinDescriptors.begin(), + pinoutDescriptor.pinDescriptors.end(), + std::back_inserter(sortedPinDescriptors), + [] (const auto& pinDescriptor) { + return &pinDescriptor; + } + ); + + std::sort( + sortedPinDescriptors.begin(), + sortedPinDescriptors.end(), + [] (const Targets::TargetPinDescriptor* descA, const Targets::TargetPinDescriptor* descB) { + return + Services::StringService::toUint16(descA->position, 10) + < Services::StringService::toUint16(descB->position, 10); + } + ); + + this->bottomQuadrantLabelGroupSet->setParentItem(this); + this->topQuadrantLabelGroupSet->setParentItem(this); + + const auto setSize = sortedPinDescriptors.size() / 2; + + for (auto i = std::size_t{0}; i < setSize; i++) { + // Bottom pins + const auto& pinDescriptor = *sortedPinDescriptors[i]; + auto* labelGroup = new VerticalLabelGroup{ + pinDescriptor, + pinDescriptor.padKey.has_value() + ? std::optional{std::cref(targetDescriptor.getPadDescriptor(*(pinDescriptor.padKey)))} + : std::nullopt, + this->pinoutState + }; + + labelGroup->setParentItem(this->bottomQuadrantLabelGroupSet); + this->bottomQuadrantLabelGroupSet->labelGroups.emplace_back(labelGroup); + + auto* pin = new Pin{ + pinDescriptor, + pinDescriptor.padKey.has_value() + ? std::optional{std::cref(targetDescriptor.getPadDescriptor(*(pinDescriptor.padKey)))} + : std::nullopt, + Pin::Orientation::VERTICAL, + this->pinoutState + }; + pin->setParentItem(this); + + this->bottomLabelGroupPinPairs.emplace_back( + VerticalLabelGroupPinPair{.labelGroup = labelGroup, .pin = pin} + ); + } + + for (auto i = setSize; i < (setSize * 2); i++) { + // Top pins + const auto& pinDescriptor = *sortedPinDescriptors[i]; + auto* labelGroup = new VerticalLabelGroup{ + pinDescriptor, + pinDescriptor.padKey.has_value() + ? std::optional{std::cref(targetDescriptor.getPadDescriptor(*(pinDescriptor.padKey)))} + : std::nullopt, + this->pinoutState + }; + + labelGroup->setParentItem(this->topQuadrantLabelGroupSet); + this->topQuadrantLabelGroupSet->labelGroups.emplace_back(labelGroup); + + auto* pin = new Pin{ + pinDescriptor, + pinDescriptor.padKey.has_value() + ? std::optional{std::cref(targetDescriptor.getPadDescriptor(*(pinDescriptor.padKey)))} + : std::nullopt, + Pin::Orientation::VERTICAL, + this->pinoutState + }; + pin->setParentItem(this); + + this->topLabelGroupPinPairs.emplace_back( + VerticalLabelGroupPinPair{.labelGroup = labelGroup, .pin = pin} + ); + } + } + + std::vector> DipPinout::padDescriptorLabelGroupPairs() { + auto output = std::vector>{}; + + for (auto& [labelGroup, pin] : this->bottomLabelGroupPinPairs) { + if (!pin->padDescriptor.has_value()) { + continue; + } + + output.emplace_back(pin->padDescriptor->get(), labelGroup); + } + + for (auto& [labelGroup, pin] : this->topLabelGroupPinPairs) { + if (!pin->padDescriptor.has_value()) { + continue; + } + + output.emplace_back(pin->padDescriptor->get(), labelGroup); + } + + return output; + } + + void DipPinout::refreshGeometry() { + this->bottomQuadrantLabelGroupSet->refreshGeometry(); + this->topQuadrantLabelGroupSet->refreshGeometry(); + + const auto setSize = this->pinoutDescriptor.pinDescriptors.size() / 2; + const auto maxVerticalPinLineAHeight = static_cast( + DipPinout::MIN_LINE_A_LENGTH + (DipPinout::PIN_LINE_A_SPACING + * std::ceil(static_cast(setSize) / static_cast(2))) + ); + this->packageBodyPosition.setX( + std::max(this->bottomQuadrantLabelGroupSet->size.width(), this->topQuadrantLabelGroupSet->size.width()) / 2 + - (this->packageBodySize.width() / 2) + ); + this->packageBodyPosition.setY( + this->topQuadrantLabelGroupSet->size.height() + + maxVerticalPinLineAHeight + DipPinout::PIN_LINE_MARGIN + Pin::HEIGHT + DipPinout::PIN_MARGIN + ); + + this->size.setWidth( + std::max(this->bottomQuadrantLabelGroupSet->size.width(), this->topQuadrantLabelGroupSet->size.width()) + ); + this->size.setHeight( + this->topQuadrantLabelGroupSet->size.height() + this->packageBodySize.height() + + ((maxVerticalPinLineAHeight + DipPinout::PIN_LINE_MARGIN + Pin::HEIGHT + DipPinout::PIN_MARGIN) * 2) + + this->bottomQuadrantLabelGroupSet->size.height() + ); + + // Position the pins + auto bottomPinXPosition = this->packageBodyPosition.x() + DipPinout::PACKAGE_PADDING; + for (auto& [labelGroup, pin] : this->bottomLabelGroupPinPairs) { + pin->setPos( + bottomPinXPosition, + this->packageBodyPosition.y() + this->packageBodySize.height() + DipPinout::PIN_MARGIN + ); + + bottomPinXPosition += Pin::WIDTH + DipPinout::PIN_MARGIN; + } + + auto topPinXPosition = this->packageBodyPosition.x() + this->packageBodySize.width() + - DipPinout::PACKAGE_PADDING - Pin::WIDTH; + for (auto& [labelGroup, pin] : this->topLabelGroupPinPairs) { + pin->setPos( + topPinXPosition, + this->packageBodyPosition.y() - DipPinout::PIN_MARGIN - Pin::HEIGHT + ); + + topPinXPosition -= Pin::WIDTH + DipPinout::PIN_MARGIN; + } + + this->topQuadrantLabelGroupSet->setPos( + this->packageBodyPosition.x() + (this->packageBodySize.width() / 2) + - (this->topQuadrantLabelGroupSet->size.width() / 2), + 0 + ); + + this->bottomQuadrantLabelGroupSet->setPos( + this->packageBodyPosition.x() + (this->packageBodySize.width() / 2) + - (this->bottomQuadrantLabelGroupSet->size.width() / 2), + this->packageBodyPosition.y() + this->packageBodySize.height() + DipPinout::PIN_MARGIN + Pin::HEIGHT + + DipPinout::PIN_LINE_MARGIN + maxVerticalPinLineAHeight + ); + } + + QRectF DipPinout::boundingRect() const { + return QRectF{QPointF{0, 0}, this->size}; + } + + void DipPinout::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { + static constexpr auto BODY_COLOR = QColor{0x7D, 0x7D, 0x7D}; + static constexpr auto DISABLED_BODY_COLOR = QColor{0x7D, 0x7D, 0x7D, 153}; + static constexpr auto BG_COLOR = QColor{0x37, 0x38, 0x35}; + static constexpr auto LINE_COLOR = QColor{0x5E, 0x5C, 0x59}; + static constexpr auto HIGHLIGHTED_LINE_COLOR = QColor{0x7D, 0x7D, 0x7D}; + + painter->setRenderHints(QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform, true); + + painter->setBrush(!this->isEnabled() ? DISABLED_BODY_COLOR : BODY_COLOR); + painter->setPen(Qt::PenStyle::NoPen); + + // Package body + painter->drawRect( + this->packageBodyPosition.x(), + this->packageBodyPosition.y(), + this->packageBodySize.width(), + this->packageBodySize.height() + ); + + painter->setBrush(BG_COLOR); + painter->drawEllipse( + this->packageBodyPosition.x() - (DipPinout::P1_EDGE_INDICATOR_DIAMETER / 2), + this->packageBodyPosition.y() + (this->packageBodySize.height() / 2) + - (DipPinout::P1_EDGE_INDICATOR_DIAMETER / 2), + DipPinout::P1_EDGE_INDICATOR_DIAMETER, + DipPinout::P1_EDGE_INDICATOR_DIAMETER + ); + painter->drawEllipse( + this->packageBodyPosition.x() + DipPinout::P1_INDICATOR_MARGIN, + this->packageBodyPosition.y() + this->packageBodySize.height() - DipPinout::P1_INDICATOR_DIAMETER + - DipPinout::P1_INDICATOR_MARGIN, + DipPinout::P1_INDICATOR_DIAMETER, + DipPinout::P1_INDICATOR_DIAMETER + ); + + painter->setRenderHints(QPainter::RenderHint::Antialiasing, false); + + // Pin lines + const auto setSize = this->pinoutDescriptor.pinDescriptors.size() / 2; + + { + // Bottom pin lines + auto lineAEndYOffset = int{0}; + for (auto pinIndex = std::size_t{0}; pinIndex < this->bottomLabelGroupPinPairs.size(); ++pinIndex) { + const auto* pin = this->bottomLabelGroupPinPairs[pinIndex].pin; + const auto* labelGroup = this->bottomLabelGroupPinPairs[pinIndex].labelGroup; + + painter->setPen( + this->pinoutState.hoveredPinNumber.has_value() && this->pinoutState.hoveredPinNumber == pin->number + ? HIGHLIGHTED_LINE_COLOR + : LINE_COLOR + ); + + const auto lineAStartX = static_cast(pin->pos().x() + (Pin::WIDTH / 2)); + const auto lineAStartY = static_cast(pin->pos().y() + Pin::HEIGHT + DipPinout::PIN_LINE_MARGIN); + const auto lineAEndY = static_cast(lineAStartY + DipPinout::MIN_LINE_A_LENGTH + lineAEndYOffset); + + painter->drawLine(lineAStartX, lineAStartY, lineAStartX, lineAEndY); + + if (setSize % 2 != 0 || pinIndex != (setSize / 2 - 1)) { + lineAEndYOffset = pinIndex <= (setSize / 2 - 1) + ? lineAEndYOffset + DipPinout::PIN_LINE_A_SPACING + : lineAEndYOffset - DipPinout::PIN_LINE_A_SPACING; + } + + const auto lineBStartX = lineAStartX; + const auto lineBEndX = static_cast( + this->bottomQuadrantLabelGroupSet->pos().x() + labelGroup->pos().x() + + (labelGroup->size.width() / 2) + ); + const auto lineBStartY = lineAEndY; + + painter->drawLine(lineBStartX, lineBStartY, lineBEndX, lineBStartY); + + const auto lineCStartX = lineBEndX; + const auto lineCStartY = lineBStartY; + const auto lineCEndY = static_cast( + this->bottomQuadrantLabelGroupSet->pos().y() + labelGroup->pos().y() - 5 + ); + + painter->drawLine(lineCStartX, lineCStartY, lineCStartX, lineCEndY); + } + } + + { + // Top pin lines + auto lineAEndYOffset = int{0}; + for (auto pinIndex = std::size_t{0}; pinIndex < this->topLabelGroupPinPairs.size(); ++pinIndex) { + const auto* pin = this->topLabelGroupPinPairs[pinIndex].pin; + const auto* labelGroup = this->topLabelGroupPinPairs[pinIndex].labelGroup; + + painter->setPen( + this->pinoutState.hoveredPinNumber.has_value() && this->pinoutState.hoveredPinNumber == pin->number + ? HIGHLIGHTED_LINE_COLOR + : LINE_COLOR + ); + + const auto lineAStartX = static_cast(pin->pos().x() + (Pin::WIDTH / 2)); + const auto lineAStartY = static_cast(pin->pos().y() - DipPinout::PIN_LINE_MARGIN); + const auto lineAEndY = lineAStartY - (DipPinout::MIN_LINE_A_LENGTH + lineAEndYOffset); + + painter->drawLine(lineAStartX, lineAStartY, lineAStartX, lineAEndY); + + if (setSize % 2 != 0 || pinIndex != (setSize / 2 - 1)) { + lineAEndYOffset = pinIndex <= (setSize / 2 - 1) + ? lineAEndYOffset + DipPinout::PIN_LINE_A_SPACING + : lineAEndYOffset - DipPinout::PIN_LINE_A_SPACING; + } + + const auto lineBStartX = lineAStartX; + const auto lineBEndX = static_cast( + this->topQuadrantLabelGroupSet->pos().x() + labelGroup->pos().x() + + (labelGroup->size.width() / 2) + ); + const auto lineBStartY = lineAEndY; + + painter->drawLine(lineBStartX, lineBStartY, lineBEndX, lineBStartY); + + const auto lineCStartX = lineBEndX; + const auto lineCStartY = lineBStartY; + const auto lineCEndY = static_cast( + this->topQuadrantLabelGroupSet->pos().y() + labelGroup->pos().y() + labelGroup->size.height() + 5 + ); + + painter->drawLine(lineCStartX, lineCStartY, lineCStartX, lineCEndY); + } + } + } +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Dip/DipPinout.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Dip/DipPinout.hpp new file mode 100644 index 00000000..a2b8162b --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Dip/DipPinout.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include +#include + +#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PinoutItem.hpp" + +#include "src/Targets/TargetPinoutDescriptor.hpp" +#include "src/Targets/TargetDescriptor.hpp" +#include "src/Targets/TargetPadDescriptor.hpp" + +#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/PinoutState.hpp" +#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/Pin.hpp" +#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/LabelGroupInterface.hpp" + +#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/VerticalLabelGroup.hpp" +#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/VerticalLabelGroupSet.hpp" +#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/VerticalLabelGroupPinPair.hpp" + +#include "src/Helpers/Pair.hpp" + +namespace Widgets::PinoutWidgets +{ + class DipPinout: public PinoutItem + { + public: + static constexpr int PACKAGE_PADDING = 15; + static constexpr int MAX_PACKAGE_HEIGHT = 88; + static constexpr int MIN_PACKAGE_HEIGHT = 65; + static constexpr int PIN_MARGIN = 2; + static constexpr int PIN_LINE_A_SPACING = 15; + static constexpr int PIN_LINE_MARGIN = 5; + static constexpr int MIN_LINE_A_LENGTH = 10; + static constexpr int P1_INDICATOR_DIAMETER = 12; + static constexpr int P1_INDICATOR_MARGIN = 8; + static constexpr int P1_EDGE_INDICATOR_DIAMETER = 18; + + QSize size = {}; + + QSize packageBodySize; + QPoint packageBodyPosition; + + DipPinout( + const Targets::TargetPinoutDescriptor& pinoutDescriptor, + const Targets::TargetDescriptor& targetDescriptor, + const PinoutState& pinoutState + ); + + std::vector> padDescriptorLabelGroupPairs(); + void refreshGeometry() override; + [[nodiscard]] QRectF boundingRect() const override; + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override; + + private: + const Targets::TargetPinoutDescriptor& pinoutDescriptor; + const PinoutState& pinoutState; + + VerticalLabelGroupSet* topQuadrantLabelGroupSet = new VerticalLabelGroupSet{ + VerticalLabelGroupSet::Position::TOP + }; + VerticalLabelGroupSet* bottomQuadrantLabelGroupSet = new VerticalLabelGroupSet{ + VerticalLabelGroupSet::Position::BOTTOM + }; + + std::vector topLabelGroupPinPairs = {}; + std::vector bottomLabelGroupPinPairs = {}; + }; +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDirectionLabel.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDirectionLabel.cpp new file mode 100644 index 00000000..4b398c86 --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDirectionLabel.cpp @@ -0,0 +1,17 @@ +#include "GpioDirectionLabel.hpp" + +namespace Widgets::PinoutWidgets +{ + GpioDirectionLabel::GpioDirectionLabel(const Targets::TargetGpioPadState& padeState) + : padeState(padeState) + {} + + const QString& GpioDirectionLabel::text() const { + static const auto INPUT_TEXT = QString{"INPUT"}; + static const auto OUTPUT_TEXT = QString{"OUTPUT"}; + + return this->padeState.direction == Targets::TargetGpioPadState::DataDirection::INPUT + ? INPUT_TEXT + : OUTPUT_TEXT; + } +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDirectionLabel.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDirectionLabel.hpp new file mode 100644 index 00000000..abdec281 --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDirectionLabel.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "Label.hpp" + +#include "src/Targets/TargetGpioPadState.hpp" + +namespace Widgets::PinoutWidgets +{ + class GpioDirectionLabel: public Label + { + public: + explicit GpioDirectionLabel(const Targets::TargetGpioPadState& padeState); + [[nodiscard]] const QString& text() const override; + + protected: + const Targets::TargetGpioPadState& padeState; + }; +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDisabledLabel.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDisabledLabel.cpp new file mode 100644 index 00000000..c1d93985 --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDisabledLabel.cpp @@ -0,0 +1,9 @@ +#include "GpioDisabledLabel.hpp" + +namespace Widgets::PinoutWidgets +{ + const QString& GpioDisabledLabel::text() const { + static const auto TEXT = QString{"GPIO PORT DISABLED"}; + return TEXT; + } +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDisabledLabel.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDisabledLabel.hpp new file mode 100644 index 00000000..46513198 --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioDisabledLabel.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "Label.hpp" + +namespace Widgets::PinoutWidgets +{ + class GpioDisabledLabel: public Label + { + public: + [[nodiscard]] const QString& text() const override; + }; +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioStateLabel.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioStateLabel.cpp new file mode 100644 index 00000000..24c31238 --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioStateLabel.cpp @@ -0,0 +1,22 @@ +#include "GpioStateLabel.hpp" + +namespace Widgets::PinoutWidgets +{ + GpioStateLabel::GpioStateLabel(const Targets::TargetGpioPadState& padeState) + : padeState(padeState) + {} + + const QString& GpioStateLabel::text() const { + static const auto HIGH_TEXT = QString{"HIGH"}; + static const auto LOW_TEXT = QString{"LOW"}; + + return this->padeState.value == Targets::TargetGpioPadState::State::HIGH + ? HIGH_TEXT + : LOW_TEXT; + } + + const QColor& GpioStateLabel::rectColor() const { + static constexpr auto RECT_COLOR = QColor{0x52, 0x46, 0x52}; + return RECT_COLOR; + } +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioStateLabel.hpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioStateLabel.hpp new file mode 100644 index 00000000..46dc2f7f --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/GpioStateLabel.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "Label.hpp" + +#include "src/Targets/TargetGpioPadState.hpp" + +namespace Widgets::PinoutWidgets +{ + class GpioStateLabel: public Label + { + public: + explicit GpioStateLabel(const Targets::TargetGpioPadState& padeState); + [[nodiscard]] const QString& text() const override; + + protected: + const Targets::TargetGpioPadState& padeState; + + [[nodiscard]] const QColor& rectColor() const override; + }; +} diff --git a/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/HorizontalLabelGroup.cpp b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/HorizontalLabelGroup.cpp new file mode 100644 index 00000000..cad91528 --- /dev/null +++ b/src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/HorizontalLabelGroup.cpp @@ -0,0 +1,108 @@ +#include "HorizontalLabelGroup.hpp" + +#include "src/Services/StringService.hpp" + +namespace Widgets::PinoutWidgets +{ + HorizontalLabelGroup::HorizontalLabelGroup( + const Targets::TargetPinDescriptor& pinDescriptor, + std::optional> padDescriptor, + Direction direction, + const PinoutState& pinoutState + ) + : pinDescriptor(pinDescriptor) + , padDescriptor(padDescriptor) + , pinNumber(Services::StringService::toUint16(this->pinDescriptor.position, 10)) + , size({0, 0}) + , direction(direction) + , pinoutState(pinoutState) + , pinNumberLabel(PinNumberLabel{this->pinDescriptor}) + , padNameLabel(PadNameLabel{this->padDescriptor}) + {} + + void HorizontalLabelGroup::insertLabel(std::unique_ptr