Insight GUI changes:
- New target pinout widgets - Made auto-refresh of registers and GPIO pad states optional (via context menu on refresh tool button)
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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<QMenuBar*>("menu-bar");
|
||||
this->layoutContainer->layout()->setMenuBar(this->mainMenuBar);
|
||||
this->container = this->layoutContainer->findChild<QWidget*>("container");
|
||||
this->ioContainerWidget = this->windowContainer->findChild<InsightTargetWidgets::TargetPackageWidgetContainer*>(
|
||||
"io-container"
|
||||
);
|
||||
|
||||
auto* horizontalContentLayout = this->container->findChild<QHBoxLayout*>("horizontal-content-layout");
|
||||
auto* verticalContentLayout = this->container->findChild<QVBoxLayout*>("vertical-content-layout");
|
||||
@@ -110,21 +104,27 @@ InsightWindow::InsightWindow(
|
||||
auto* openAboutWindowAction = helpMenu->findChild<QAction*>("open-about-dialogue");
|
||||
|
||||
this->header = this->windowContainer->findChild<QWidget*>("header");
|
||||
|
||||
this->refreshIoInspectionButton = this->header->findChild<SvgToolButton*>("refresh-io-inspection-btn");
|
||||
this->refreshRegistersOnTargetStopAction = this->refreshIoInspectionButton->findChild<QAction*>("refresh-regs");
|
||||
this->refreshGpioOnTargetStopAction = this->refreshIoInspectionButton->findChild<QAction*>("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<QWidget*>("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<QWidget*>("bottom-menu-bar");
|
||||
this->bottomMenuBarLayout = this->bottomMenuBar->findChild<QHBoxLayout*>();
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -180,6 +180,10 @@ QToolTip {
|
||||
border: none;
|
||||
}
|
||||
|
||||
#pinout-widget-container {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* Bottom menu bar & panels */
|
||||
#bottom-menu-bar {
|
||||
background-color: transparent;
|
||||
|
||||
@@ -87,8 +87,34 @@
|
||||
<string>:/compiled/src/Insight/UserInterfaces/InsightWindow/Images/refresh-disabled.svg</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Refresh Registers And GPIO Pin States</string>
|
||||
<string>Refresh registers and GPIO pad states (right-click for auto-refresh options)</string>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::InstantPopup</enum>
|
||||
</property>
|
||||
<property name="contextMenuEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QMenu" name="refresh-menu">
|
||||
<addaction name="refresh-regs"/>
|
||||
<addaction name="refresh-gpio"/>
|
||||
<action name="refresh-regs">
|
||||
<property name="text">
|
||||
<string>Refresh registers after target execution stops</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
<action name="refresh-gpio">
|
||||
<property name="text">
|
||||
<string>Refresh GPIO pad states after target execution stops</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -198,27 +224,7 @@
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<!-- The left panel is inserted here. See InsightWindow::InsightWindow() for more -->
|
||||
<item>
|
||||
<widget class="TargetPackageWidgetContainer" name="io-container">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"/>
|
||||
</property>
|
||||
<layout class="QHBoxLayout">
|
||||
<item alignment="Qt::AlignHCenter">
|
||||
<widget class="Label" name="io-inspection-unavailable">
|
||||
<property name="visible"><bool>false</bool></property>
|
||||
<property name="alignment">
|
||||
<enum>Qt::AlignCenter</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<!-- The left panel, along with the pinout widget container, is inserted here. See InsightWindow::InsightWindow() for more -->
|
||||
</layout>
|
||||
</item>
|
||||
<!-- The bottom panel is inserted here. See InsightWindow::InsightWindow() for more -->
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
#include "DipPinout.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
#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<int>(pinoutDescriptor.pinDescriptors.size() / 2)
|
||||
- DipPinout::PIN_MARGIN + (DipPinout::PACKAGE_PADDING * 2),
|
||||
std::max(
|
||||
std::min(static_cast<int>(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<const Targets::TargetPinDescriptor*>{};
|
||||
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<Pair<
|
||||
const Targets::TargetPadDescriptor&,
|
||||
LabelGroupInterface*
|
||||
>> DipPinout::padDescriptorLabelGroupPairs() {
|
||||
auto output = std::vector<Pair<const Targets::TargetPadDescriptor&, LabelGroupInterface*>>{};
|
||||
|
||||
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<int>(
|
||||
DipPinout::MIN_LINE_A_LENGTH + (DipPinout::PIN_LINE_A_SPACING
|
||||
* std::ceil(static_cast<float>(setSize) / static_cast<float>(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<int>(pin->pos().x() + (Pin::WIDTH / 2));
|
||||
const auto lineAStartY = static_cast<int>(pin->pos().y() + Pin::HEIGHT + DipPinout::PIN_LINE_MARGIN);
|
||||
const auto lineAEndY = static_cast<int>(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<int>(
|
||||
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<int>(
|
||||
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<int>(pin->pos().x() + (Pin::WIDTH / 2));
|
||||
const auto lineAStartY = static_cast<int>(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<int>(
|
||||
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<int>(
|
||||
this->topQuadrantLabelGroupSet->pos().y() + labelGroup->pos().y() + labelGroup->size.height() + 5
|
||||
);
|
||||
|
||||
painter->drawLine(lineCStartX, lineCStartY, lineCStartX, lineCEndY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
#pragma once
|
||||
|
||||
#include <QSize>
|
||||
#include <QPoint>
|
||||
#include <QPainter>
|
||||
#include <vector>
|
||||
|
||||
#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<Pair<const Targets::TargetPadDescriptor&, LabelGroupInterface*>> 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<VerticalLabelGroupPinPair> topLabelGroupPinPairs = {};
|
||||
std::vector<VerticalLabelGroupPinPair> bottomLabelGroupPinPairs = {};
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "Label.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
class GpioDisabledLabel: public Label
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] const QString& text() const override;
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
#include "HorizontalLabelGroup.hpp"
|
||||
|
||||
#include "src/Services/StringService.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
HorizontalLabelGroup::HorizontalLabelGroup(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> 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<Label>&& label) {
|
||||
this->secondaryLabels.emplace_back(std::move(label));
|
||||
}
|
||||
|
||||
void HorizontalLabelGroup::refreshGeometry() {
|
||||
this->enabledSecondaryLabels.clear();
|
||||
|
||||
this->pinNumberLabel.refreshGeometry();
|
||||
this->padNameLabel.refreshGeometry();
|
||||
|
||||
if (this->pinNumberLabel.width < HorizontalLabelGroup::MIN_PIN_NUMBER_LABEL_WIDTH) {
|
||||
this->pinNumberLabel.width = HorizontalLabelGroup::MIN_PIN_NUMBER_LABEL_WIDTH;
|
||||
}
|
||||
|
||||
if (this->padNameLabel.width < HorizontalLabelGroup::MIN_LABEL_WIDTH) {
|
||||
this->padNameLabel.width = HorizontalLabelGroup::MIN_LABEL_WIDTH;
|
||||
}
|
||||
|
||||
auto totalWidth = this->pinNumberLabel.width + HorizontalLabelGroup::LABEL_MARGIN + this->padNameLabel.width
|
||||
+ (!this->secondaryLabels.empty() ? HorizontalLabelGroup::SECONDARY_LABEL_SEPARATOR_SPACING : 0);
|
||||
|
||||
for (const auto& secondaryLabel : this->secondaryLabels) {
|
||||
if (!secondaryLabel->enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this->enabledSecondaryLabels.emplace_back(secondaryLabel.get());
|
||||
secondaryLabel->refreshGeometry();
|
||||
|
||||
if (secondaryLabel->width < HorizontalLabelGroup::MIN_LABEL_WIDTH) {
|
||||
secondaryLabel->width = HorizontalLabelGroup::MIN_LABEL_WIDTH;
|
||||
}
|
||||
|
||||
totalWidth += HorizontalLabelGroup::LABEL_MARGIN + secondaryLabel->width;
|
||||
}
|
||||
|
||||
this->size.setWidth(totalWidth);
|
||||
this->size.setHeight(Label::HEIGHT);
|
||||
}
|
||||
|
||||
QRectF HorizontalLabelGroup::boundingRect() const {
|
||||
return QRectF{QPointF{0, 0}, this->size};
|
||||
}
|
||||
|
||||
void HorizontalLabelGroup::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
static constexpr auto LINE_COLOR = QColor{0x5E, 0x5C, 0x59};
|
||||
|
||||
painter->setOpacity(this->isEnabled() ? 1 : 0.6);
|
||||
painter->setPen(Qt::PenStyle::NoPen);
|
||||
auto xPos = int{0};
|
||||
|
||||
this->pinNumberLabel.paint(painter, this->transformLabelXPos(xPos, this->pinNumberLabel), 0);
|
||||
xPos += this->pinNumberLabel.width + HorizontalLabelGroup::LABEL_MARGIN;
|
||||
|
||||
this->padNameLabel.paint(painter, this->transformLabelXPos(xPos, this->padNameLabel), 0);
|
||||
xPos += this->padNameLabel.width + HorizontalLabelGroup::LABEL_MARGIN;
|
||||
|
||||
if (!this->enabledSecondaryLabels.empty()) {
|
||||
painter->setPen(LINE_COLOR);
|
||||
static constexpr auto centerY = Label::HEIGHT / 2;
|
||||
const auto separatorLineXStart = this->direction == Direction::LEFT ? this->size.width() - xPos : xPos;
|
||||
painter->drawLine(
|
||||
separatorLineXStart,
|
||||
centerY,
|
||||
separatorLineXStart + (
|
||||
this->direction == Direction::LEFT
|
||||
? (HorizontalLabelGroup::SECONDARY_LABEL_SEPARATOR_SPACING * -1) + HorizontalLabelGroup::LABEL_MARGIN
|
||||
: HorizontalLabelGroup::SECONDARY_LABEL_SEPARATOR_SPACING - HorizontalLabelGroup::LABEL_MARGIN
|
||||
),
|
||||
centerY
|
||||
);
|
||||
painter->setPen(Qt::PenStyle::NoPen);
|
||||
|
||||
xPos += HorizontalLabelGroup::SECONDARY_LABEL_SEPARATOR_SPACING;
|
||||
|
||||
for (const auto& label : this->enabledSecondaryLabels) {
|
||||
label->paint(painter, this->transformLabelXPos(xPos, *label), 0);
|
||||
xPos += label->width + HorizontalLabelGroup::LABEL_MARGIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int HorizontalLabelGroup::transformLabelXPos(int xPos, const Label& label) const {
|
||||
return this->direction == Direction::LEFT ? this->size.width() - xPos - label.width : xPos;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include <QSize>
|
||||
#include <QRectF>
|
||||
#include <QPainter>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "src/Targets/TargetPinDescriptor.hpp"
|
||||
#include "src/Targets/TargetPadDescriptor.hpp"
|
||||
|
||||
#include "LabelGroupInterface.hpp"
|
||||
#include "PinoutState.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "PinNumberLabel.hpp"
|
||||
#include "PadNameLabel.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
class HorizontalLabelGroup
|
||||
: public LabelGroupInterface
|
||||
, public QGraphicsItem
|
||||
{
|
||||
public:
|
||||
static constexpr int LABEL_MARGIN = 4;
|
||||
static constexpr int MIN_PIN_NUMBER_LABEL_WIDTH = 45;
|
||||
static constexpr int MIN_LABEL_WIDTH = 55;
|
||||
static constexpr int SECONDARY_LABEL_SEPARATOR_SPACING = 10;
|
||||
|
||||
enum Direction: std::uint8_t
|
||||
{
|
||||
LEFT,
|
||||
RIGHT,
|
||||
};
|
||||
|
||||
const Targets::TargetPinDescriptor& pinDescriptor;
|
||||
const std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor;
|
||||
std::uint16_t pinNumber;
|
||||
QSize size = {};
|
||||
const Direction direction;
|
||||
|
||||
HorizontalLabelGroup(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
Direction direction,
|
||||
const PinoutState& pinoutState
|
||||
);
|
||||
|
||||
void insertLabel(std::unique_ptr<Label>&& label) override;
|
||||
void refreshGeometry();
|
||||
[[nodiscard]] QRectF boundingRect() const override;
|
||||
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
|
||||
|
||||
private:
|
||||
const PinoutState& pinoutState;
|
||||
PinNumberLabel pinNumberLabel;
|
||||
PadNameLabel padNameLabel;
|
||||
|
||||
std::vector<std::unique_ptr<Label>> secondaryLabels;
|
||||
std::vector<Label*> enabledSecondaryLabels;
|
||||
|
||||
[[nodiscard]] inline int transformLabelXPos(
|
||||
int xPos,
|
||||
const Label& label
|
||||
) const __attribute__((__always_inline__));
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "HorizontalLabelGroup.hpp"
|
||||
#include "Pin.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
struct HorizontalLabelGroupPinPair
|
||||
{
|
||||
HorizontalLabelGroup* labelGroup;
|
||||
Pin* pin;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "HorizontalLabelGroupSet.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <ranges>
|
||||
#include <QPoint>
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
HorizontalLabelGroupSet::HorizontalLabelGroupSet(Position position)
|
||||
: labelGroups({})
|
||||
, size({0, 0})
|
||||
, position(position)
|
||||
{}
|
||||
|
||||
void HorizontalLabelGroupSet::refreshGeometry() {
|
||||
auto maxWidth = int{0};
|
||||
|
||||
for (auto* labelGroup : this->labelGroups) {
|
||||
labelGroup->refreshGeometry();
|
||||
maxWidth = std::max(labelGroup->size.width(), maxWidth);
|
||||
}
|
||||
|
||||
auto yPos = int{0};
|
||||
|
||||
const auto positionLabelGroup = [&] (HorizontalLabelGroup* labelGroup) {
|
||||
labelGroup->setPos(
|
||||
this->position == HorizontalLabelGroupSet::Position::LEFT ? maxWidth - labelGroup->size.width() : 0,
|
||||
yPos
|
||||
);
|
||||
yPos += labelGroup->size.height() + HorizontalLabelGroupSet::GROUP_VERTICAL_MARGIN;
|
||||
};
|
||||
|
||||
if (this->position == Position::RIGHT) {
|
||||
for (auto groupIt = this->labelGroups.rbegin(); groupIt < this->labelGroups.rend(); ++groupIt) {
|
||||
positionLabelGroup(*groupIt);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (auto groupIt = this->labelGroups.begin(); groupIt < this->labelGroups.end(); ++groupIt) {
|
||||
positionLabelGroup(*groupIt);
|
||||
}
|
||||
}
|
||||
|
||||
this->size.setWidth(maxWidth);
|
||||
this->size.setHeight(yPos - HorizontalLabelGroupSet::GROUP_VERTICAL_MARGIN);
|
||||
}
|
||||
|
||||
QRectF HorizontalLabelGroupSet::boundingRect() const {
|
||||
return QRectF{QPointF{0, 0}, this->size};
|
||||
}
|
||||
|
||||
void HorizontalLabelGroupSet::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
// Nothing to do here...
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include <QSize>
|
||||
#include <QRectF>
|
||||
#include <QPainter>
|
||||
#include <vector>
|
||||
|
||||
#include "HorizontalLabelGroup.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
class HorizontalLabelGroupSet: public QGraphicsItem
|
||||
{
|
||||
public:
|
||||
static constexpr int GROUP_VERTICAL_MARGIN = 5;
|
||||
|
||||
enum Position: std::uint8_t
|
||||
{
|
||||
LEFT,
|
||||
RIGHT
|
||||
};
|
||||
|
||||
std::vector<HorizontalLabelGroup*> labelGroups;
|
||||
QSize size;
|
||||
const Position position;
|
||||
|
||||
explicit HorizontalLabelGroupSet(Position position);
|
||||
|
||||
void refreshGeometry();
|
||||
[[nodiscard]] QRectF boundingRect() const override;
|
||||
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "Label.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
void Label::refreshGeometry() {
|
||||
this->minimumWidth = Label::FONT_METRICS.boundingRect(this->text()).width() + (Label::HORIZ_PADDING * 2);
|
||||
this->width = this->minimumWidth;
|
||||
}
|
||||
|
||||
void Label::paint(QPainter* painter, int startX, int startY) const {
|
||||
painter->setFont(Label::FONT);
|
||||
|
||||
painter->setBrush(this->rectColor());
|
||||
painter->setPen(Qt::PenStyle::NoPen);
|
||||
|
||||
const auto rect = QRect{startX, startY, this->width, Label::HEIGHT};
|
||||
painter->drawRect(rect);
|
||||
|
||||
painter->setPen(this->changed ? this->changedFontColor() : this->fontColor());
|
||||
painter->drawText(rect, Qt::AlignCenter, this->text());
|
||||
}
|
||||
|
||||
const QColor& Label::rectColor() const {
|
||||
static constexpr auto RECT_COLOR = QColor{0x42, 0x42, 0x42};
|
||||
return RECT_COLOR;
|
||||
}
|
||||
|
||||
const QColor& Label::fontColor() const {
|
||||
static constexpr auto FONT_COLOR = QColor{0xA2, 0xA2, 0xA2};
|
||||
return FONT_COLOR;
|
||||
}
|
||||
|
||||
const QColor& Label::changedFontColor() const {
|
||||
/*
|
||||
* I spent a considerable amount of time attempting to find a good font color for highlighting changes.
|
||||
* I failed miserably. Have given up, for now.
|
||||
*
|
||||
* TODO: Revisit after v2.0.0
|
||||
*/
|
||||
return this->fontColor();
|
||||
|
||||
// static constexpr auto FONT_COLOR = QColor{0x54, 0x7F, 0xBA};
|
||||
// return FONT_COLOR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <QGraphicsItem>
|
||||
#include <QString>
|
||||
#include <QFont>
|
||||
#include <QFontMetrics>
|
||||
#include <QPainter>
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
class Label
|
||||
{
|
||||
public:
|
||||
static constexpr int HEIGHT = 22;
|
||||
static constexpr int FONT_SIZE_POINTS = 8;
|
||||
static constexpr int HORIZ_PADDING = 10;
|
||||
|
||||
int minimumWidth = 0;
|
||||
int width = 0;
|
||||
|
||||
/*
|
||||
* This flag isn't respected for pin number and pad name labels. Not a big deal, as we don't currently disable
|
||||
* them. Will fix later, if necessary.
|
||||
*/
|
||||
bool enabled = true;
|
||||
|
||||
bool changed = false;
|
||||
|
||||
Label() = default;
|
||||
virtual ~Label() = default;
|
||||
|
||||
[[nodiscard]] virtual const QString& text() const = 0;
|
||||
void refreshGeometry();
|
||||
virtual void paint(QPainter* painter, int startX, int startY) const;
|
||||
|
||||
protected:
|
||||
static const inline auto FONT = QFont{"'Ubuntu', sans-serif", Label::FONT_SIZE_POINTS, QFont::Normal};
|
||||
static const inline auto FONT_METRICS = QFontMetrics{Label::FONT};
|
||||
|
||||
[[nodiscard]] virtual const QColor& rectColor() const;
|
||||
[[nodiscard]] virtual const QColor& fontColor() const;
|
||||
[[nodiscard]] virtual const QColor& changedFontColor() const;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Label.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
class LabelGroupInterface
|
||||
{
|
||||
public:
|
||||
virtual ~LabelGroupInterface() = default;
|
||||
virtual void insertLabel(std::unique_ptr<Label>&& label) = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "PadLabels.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
void PadLabels::disableGpioLabels() const {
|
||||
if (this->gpioDirection != nullptr) {
|
||||
this->gpioDirection->enabled = false;
|
||||
}
|
||||
|
||||
if (this->gpioState != nullptr) {
|
||||
this->gpioState->enabled = false;
|
||||
}
|
||||
|
||||
if (this->gpioDisabled != nullptr) {
|
||||
this->gpioDisabled->enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "GpioDirectionLabel.hpp"
|
||||
#include "GpioStateLabel.hpp"
|
||||
#include "GpioDisabledLabel.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
struct PadLabels
|
||||
{
|
||||
GpioDirectionLabel* gpioDirection = nullptr;
|
||||
GpioStateLabel* gpioState = nullptr;
|
||||
GpioDisabledLabel* gpioDisabled = nullptr;
|
||||
|
||||
void disableGpioLabels() const;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "PadNameLabel.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
PadNameLabel::PadNameLabel(std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor)
|
||||
: padName(
|
||||
padDescriptor.has_value()
|
||||
? QString::fromStdString(padDescriptor->get().name)
|
||||
: "NOT CONNECTED"
|
||||
)
|
||||
{}
|
||||
|
||||
const QString& PadNameLabel::text() const {
|
||||
return this->padName;
|
||||
}
|
||||
|
||||
const QColor& PadNameLabel::rectColor() const {
|
||||
static constexpr auto RECT_COLOR = QColor{0x38, 0x46, 0x45};
|
||||
return RECT_COLOR;
|
||||
}
|
||||
|
||||
const QColor& PadNameLabel::fontColor() const {
|
||||
static constexpr auto FONT_COLOR = QColor{0xA0, 0xA0, 0xA0};
|
||||
return FONT_COLOR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
|
||||
#include "Label.hpp"
|
||||
|
||||
#include "src/Targets/TargetPadDescriptor.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
class PadNameLabel: public Label
|
||||
{
|
||||
public:
|
||||
explicit PadNameLabel(std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor);
|
||||
|
||||
[[nodiscard]] const QString& text() const override;
|
||||
|
||||
protected:
|
||||
QString padName;
|
||||
|
||||
[[nodiscard]] const QColor& rectColor() const override;
|
||||
[[nodiscard]] const QColor& fontColor() const override;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "Pin.hpp"
|
||||
|
||||
#include "src/Services/StringService.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
Pin::Pin(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
Orientation orientation,
|
||||
const PinoutState& pinoutState
|
||||
)
|
||||
: pinDescriptor(pinDescriptor)
|
||||
, padDescriptor(padDescriptor)
|
||||
, orientation(orientation)
|
||||
, number(Services::StringService::toUint16(this->pinDescriptor.position, 10))
|
||||
, pinoutState(pinoutState)
|
||||
{}
|
||||
|
||||
QRectF Pin::boundingRect() const {
|
||||
return QRectF{
|
||||
QPointF{0, 0},
|
||||
this->orientation == Orientation::VERTICAL
|
||||
? QSize{Pin::WIDTH, Pin::HEIGHT}
|
||||
: QSize{Pin::HEIGHT, Pin::WIDTH}
|
||||
};
|
||||
}
|
||||
|
||||
void Pin::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
using Targets::TargetPadType;
|
||||
|
||||
static constexpr auto DEFAULT_COLOR = QColor{0x7D, 0x7D, 0x7D};
|
||||
static constexpr auto HIGHLIGHT_COLOR = QColor{0x53, 0x67, 0x5D};
|
||||
|
||||
painter->setBrush(
|
||||
this->pinoutState.hoveredPinNumber.has_value() && this->pinoutState.hoveredPinNumber == this->number
|
||||
? HIGHLIGHT_COLOR
|
||||
: DEFAULT_COLOR
|
||||
);
|
||||
painter->setPen(Qt::PenStyle::NoPen);
|
||||
painter->setOpacity(this->isEnabled() ? 1 : 0.6);
|
||||
|
||||
|
||||
if (this->orientation == Orientation::VERTICAL) {
|
||||
painter->drawRect(0, 0, Pin::WIDTH, Pin::HEIGHT);
|
||||
|
||||
} else {
|
||||
painter->drawRect(0, 0, Pin::HEIGHT, Pin::WIDTH);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include <QSize>
|
||||
#include <QRectF>
|
||||
#include <QPainter>
|
||||
#include <functional>
|
||||
|
||||
#include "src/Targets/TargetPinDescriptor.hpp"
|
||||
#include "src/Targets/TargetPadDescriptor.hpp"
|
||||
|
||||
#include "PinoutState.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
class Pin: public QGraphicsItem
|
||||
{
|
||||
public:
|
||||
static constexpr int WIDTH = 11;
|
||||
static constexpr int HEIGHT = 17;
|
||||
|
||||
enum Orientation: std::uint8_t
|
||||
{
|
||||
VERTICAL,
|
||||
HORIZONTAL
|
||||
};
|
||||
|
||||
const Targets::TargetPinDescriptor& pinDescriptor;
|
||||
const std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor;
|
||||
const Orientation orientation;
|
||||
std::uint16_t number;
|
||||
|
||||
Pin(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
Orientation orientation,
|
||||
const PinoutState& pinoutState
|
||||
);
|
||||
|
||||
[[nodiscard]] QRectF boundingRect() const override;
|
||||
|
||||
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
|
||||
|
||||
protected:
|
||||
const PinoutState& pinoutState;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#include "PinNumberLabel.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
PinNumberLabel::PinNumberLabel(const Targets::TargetPinDescriptor& pinDescriptor)
|
||||
: pinNumber(QString::fromStdString(pinDescriptor.position))
|
||||
{}
|
||||
|
||||
const QString& PinNumberLabel::text() const {
|
||||
return this->pinNumber;
|
||||
}
|
||||
|
||||
const QColor& PinNumberLabel::rectColor() const {
|
||||
static constexpr auto RECT_COLOR = QColor{0x40, 0x53, 0x51};
|
||||
return RECT_COLOR;
|
||||
}
|
||||
|
||||
const QColor& PinNumberLabel::fontColor() const {
|
||||
static constexpr auto FONT_COLOR = QColor{0xA8, 0xA8, 0xA8};
|
||||
return FONT_COLOR;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "Label.hpp"
|
||||
|
||||
#include "src/Targets/TargetPinDescriptor.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
class PinNumberLabel: public Label
|
||||
{
|
||||
public:
|
||||
explicit PinNumberLabel(const Targets::TargetPinDescriptor& pinDescriptor);
|
||||
|
||||
[[nodiscard]] const QString& text() const override;
|
||||
|
||||
protected:
|
||||
QString pinNumber;
|
||||
|
||||
[[nodiscard]] const QColor& rectColor() const override;
|
||||
[[nodiscard]] const QColor& fontColor() const override;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "PinoutContainer.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
PinoutContainer::PinoutContainer(const Targets::TargetDescriptor& targetDescriptor, QWidget* parent)
|
||||
: QGraphicsView(parent)
|
||||
, pinoutScene(new PinoutScene{targetDescriptor, this})
|
||||
, targetDescriptor(targetDescriptor)
|
||||
{
|
||||
this->setObjectName("pinout-widget-container");
|
||||
this->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
|
||||
this->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||
this->setViewportUpdateMode(QGraphicsView::ViewportUpdateMode::MinimalViewportUpdate);
|
||||
this->setFrameShape(QFrame::NoFrame);
|
||||
this->setDragMode(QGraphicsView::DragMode::NoDrag);
|
||||
this->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
|
||||
this->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
|
||||
this->setMouseTracking(true);
|
||||
|
||||
this->setScene(this->pinoutScene);
|
||||
}
|
||||
|
||||
void PinoutContainer::resizeEvent(QResizeEvent* event) {
|
||||
QGraphicsView::resizeEvent(event);
|
||||
}
|
||||
|
||||
void PinoutContainer::keyPressEvent(QKeyEvent* event) {
|
||||
const auto viewSize = this->size();
|
||||
const auto sceneRect = this->pinoutScene->sceneRect();
|
||||
|
||||
const auto key = event->key();
|
||||
if (key == Qt::Key_Control) {
|
||||
this->setDragMode(
|
||||
sceneRect.width() > viewSize.width() || sceneRect.height() > viewSize.height()
|
||||
? QGraphicsView::DragMode::ScrollHandDrag
|
||||
: QGraphicsView::DragMode::NoDrag
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
QGraphicsView::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void PinoutContainer::keyReleaseEvent(QKeyEvent* event) {
|
||||
const auto key = event->key();
|
||||
if (key == Qt::Key_Control) {
|
||||
this->setDragMode(QGraphicsView::DragMode::NoDrag);
|
||||
}
|
||||
|
||||
QGraphicsView::keyReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsView>
|
||||
#include <QResizeEvent>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "src/Targets/TargetDescriptor.hpp"
|
||||
|
||||
#include "PinoutScene.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
class PinoutContainer: public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PinoutScene* pinoutScene;
|
||||
|
||||
PinoutContainer(const Targets::TargetDescriptor& targetDescriptor, QWidget* parent);
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
void keyReleaseEvent(QKeyEvent* event) override;
|
||||
|
||||
protected:
|
||||
const Targets::TargetDescriptor& targetDescriptor;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsItem>
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
class PinoutItem: public QGraphicsItem
|
||||
{
|
||||
public:
|
||||
virtual void refreshGeometry() = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,414 @@
|
||||
#include "PinoutScene.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <ranges>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <QAction>
|
||||
|
||||
#include "Qfp/QfpPinout.hpp"
|
||||
#include "Dip/DipPinout.hpp"
|
||||
|
||||
#include "GpioDirectionLabel.hpp"
|
||||
#include "GpioStateLabel.hpp"
|
||||
#include "GpioDisabledLabel.hpp"
|
||||
#include "VerticalLabelGroup.hpp"
|
||||
#include "HorizontalLabelGroup.hpp"
|
||||
#include "Pin.hpp"
|
||||
|
||||
#include "src/Insight/InsightSignals.hpp"
|
||||
#include "src/Insight/InsightWorker/InsightWorker.hpp"
|
||||
#include "src/Insight/InsightWorker/Tasks/ReadTargetGpioPadStates.hpp"
|
||||
#include "src/Insight/InsightWorker/Tasks/SetTargetGpioPadState.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
using Targets::TargetGpioPadState;
|
||||
|
||||
PinoutScene::PinoutScene(const Targets::TargetDescriptor& targetDescriptor, QGraphicsView* parent)
|
||||
: QGraphicsScene(parent)
|
||||
, parentView(parent)
|
||||
, targetDescriptor(targetDescriptor)
|
||||
{
|
||||
for (const auto& padDescriptor : std::views::values(this->targetDescriptor.padDescriptorsByKey)) {
|
||||
if (padDescriptor.type != Targets::TargetPadType::GPIO) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this->gpioPadDescriptors.emplace_back(&padDescriptor);
|
||||
this->gpioPadStatesByPadId.emplace(
|
||||
padDescriptor.id,
|
||||
TargetGpioPadState{
|
||||
.disabled = true,
|
||||
.value = TargetGpioPadState::State::UNKNOWN,
|
||||
.direction = TargetGpioPadState::DataDirection::UNKNOWN,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool PinoutScene::isPinoutSupported(const Targets::TargetPinoutDescriptor& pinoutDescriptor) {
|
||||
using Targets::TargetPinoutType;
|
||||
|
||||
const auto pinCount = pinoutDescriptor.pinDescriptors.size();
|
||||
|
||||
// return pinoutDescriptor.type == TargetPinoutType::QFP || pinoutDescriptor.type == TargetPinoutType::QFN;
|
||||
|
||||
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 PinoutScene::setPinout(const Targets::TargetPinoutDescriptor& pinoutDescriptor) {
|
||||
using Targets::TargetPinoutType;
|
||||
|
||||
assert(this->isPinoutSupported(pinoutDescriptor));
|
||||
this->padLabelsByPadId.clear();
|
||||
|
||||
if (this->pinoutItem != nullptr) {
|
||||
this->removeItem(this->pinoutItem);
|
||||
delete this->pinoutItem;
|
||||
this->pinoutItem = nullptr;
|
||||
}
|
||||
|
||||
if (pinoutDescriptor.type == TargetPinoutType::QFP || pinoutDescriptor.type == TargetPinoutType::QFN) {
|
||||
auto* pinoutItem = new QfpPinout{pinoutDescriptor, this->targetDescriptor, this->pinoutState};
|
||||
this->populatePadLabels(pinoutItem->padDescriptorLabelGroupPairs());
|
||||
this->pinoutItem = pinoutItem;
|
||||
}
|
||||
|
||||
if (
|
||||
pinoutDescriptor.type == TargetPinoutType::DIP
|
||||
|| pinoutDescriptor.type == TargetPinoutType::SOIC
|
||||
|| pinoutDescriptor.type == TargetPinoutType::SSOP
|
||||
) {
|
||||
auto* pinoutItem = new DipPinout{pinoutDescriptor, this->targetDescriptor, this->pinoutState};
|
||||
this->populatePadLabels(pinoutItem->padDescriptorLabelGroupPairs());
|
||||
this->pinoutItem = pinoutItem;
|
||||
}
|
||||
|
||||
assert(this->pinoutItem != nullptr);
|
||||
this->pinoutItem->refreshGeometry();
|
||||
this->addItem(this->pinoutItem);
|
||||
|
||||
this->adjustSize();
|
||||
this->update();
|
||||
}
|
||||
|
||||
void PinoutScene::setDisabled(bool disabled) {
|
||||
if (this->pinoutItem == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->pinoutItem->setEnabled(!disabled);
|
||||
this->update();
|
||||
}
|
||||
|
||||
void PinoutScene::refreshPadStates(const std::optional<std::function<void(void)>>& callback) {
|
||||
const auto refreshTask = QSharedPointer<ReadTargetGpioPadStates>{
|
||||
new ReadTargetGpioPadStates{this->gpioPadDescriptors},
|
||||
&QObject::deleteLater
|
||||
};
|
||||
|
||||
QObject::connect(
|
||||
refreshTask.get(),
|
||||
&ReadTargetGpioPadStates::targetGpioPadStatesRead,
|
||||
this,
|
||||
&PinoutScene::updatePadStates
|
||||
);
|
||||
|
||||
if (callback.has_value()) {
|
||||
QObject::connect(
|
||||
refreshTask.get(),
|
||||
&InsightWorkerTask::completed,
|
||||
this,
|
||||
callback.value()
|
||||
);
|
||||
}
|
||||
|
||||
InsightWorker::queueTask(refreshTask);
|
||||
}
|
||||
|
||||
void PinoutScene::adjustSize() {
|
||||
if (this->pinoutItem == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->setSceneRect(this->pinoutItem->boundingRect());
|
||||
}
|
||||
|
||||
void PinoutScene::populatePadLabels(
|
||||
const std::vector<
|
||||
Pair<const Targets::TargetPadDescriptor&, LabelGroupInterface*>
|
||||
>& padDescriptorLabelGroupPairs
|
||||
) {
|
||||
for (auto& [padDescriptor, labelGroup] : padDescriptorLabelGroupPairs) {
|
||||
auto padLabels = PadLabels{};
|
||||
|
||||
auto gpioPadStateIt = this->gpioPadStatesByPadId.find(padDescriptor.id);
|
||||
if (gpioPadStateIt != this->gpioPadStatesByPadId.end()) {
|
||||
const auto& gpioPadState = gpioPadStateIt->second;
|
||||
|
||||
if (padDescriptor.type == Targets::TargetPadType::GPIO) {
|
||||
auto gpioDirectionLabel = std::make_unique<GpioDirectionLabel>(gpioPadState);
|
||||
auto gpioStateLabel = std::make_unique<GpioStateLabel>(gpioPadState);
|
||||
auto gpioDisabledLabel = std::make_unique<GpioDisabledLabel>();
|
||||
|
||||
gpioDirectionLabel->enabled = false;
|
||||
gpioStateLabel->enabled = false;
|
||||
gpioDisabledLabel->enabled = false;
|
||||
|
||||
padLabels.gpioDirection = gpioDirectionLabel.get();
|
||||
padLabels.gpioState = gpioStateLabel.get();
|
||||
padLabels.gpioDisabled = gpioDisabledLabel.get();
|
||||
|
||||
labelGroup->insertLabel(std::move(gpioDirectionLabel));
|
||||
labelGroup->insertLabel(std::move(gpioStateLabel));
|
||||
labelGroup->insertLabel(std::move(gpioDisabledLabel));
|
||||
}
|
||||
}
|
||||
|
||||
this->padLabelsByPadId.emplace(padDescriptor.id, padLabels);
|
||||
}
|
||||
}
|
||||
|
||||
void PinoutScene::updatePadStates(const Targets::TargetGpioPadDescriptorAndStatePairs& padStatePairs) {
|
||||
if (this->pinoutItem == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& [padDescriptor, padState] : padStatePairs) {
|
||||
const auto currentPadStateIt = this->gpioPadStatesByPadId.find(padDescriptor.id);
|
||||
if (currentPadStateIt == this->gpioPadStatesByPadId.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& currentPadState = currentPadStateIt->second;
|
||||
|
||||
const auto padLabelsIt = this->padLabelsByPadId.find(padDescriptor.id);
|
||||
if (padLabelsIt == this->padLabelsByPadId.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& padLabels = padLabelsIt->second;
|
||||
padLabels.disableGpioLabels();
|
||||
|
||||
if (!padState.disabled) {
|
||||
if (padState.direction != TargetGpioPadState::DataDirection::UNKNOWN) {
|
||||
padLabels.gpioDirection->enabled = true;
|
||||
padLabels.gpioDirection->changed = padState.direction != currentPadState.direction;
|
||||
}
|
||||
|
||||
if (padState.value != TargetGpioPadState::State::UNKNOWN) {
|
||||
padLabels.gpioState->enabled = true;
|
||||
padLabels.gpioState->changed = padState.value != currentPadState.value;
|
||||
}
|
||||
} else {
|
||||
padLabels.gpioDisabled->enabled = true;
|
||||
}
|
||||
|
||||
currentPadState = padState;
|
||||
}
|
||||
|
||||
this->pinoutItem->refreshGeometry();
|
||||
this->adjustSize();
|
||||
this->update();
|
||||
}
|
||||
|
||||
void PinoutScene::mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent) {
|
||||
if (!this->pinoutItem->isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto mousePosition = mouseEvent->scenePos();
|
||||
|
||||
const auto hoveredItems = this->items(mousePosition);
|
||||
if (!hoveredItems.empty()) {
|
||||
this->update();
|
||||
const auto* hoveredItem = hoveredItems.first();
|
||||
|
||||
const auto* hoveredVerticalLabelGroup = dynamic_cast<const VerticalLabelGroup*>(hoveredItem);
|
||||
if (hoveredVerticalLabelGroup != nullptr) {
|
||||
this->pinoutState.hoveredPinNumber = hoveredVerticalLabelGroup->pinNumber;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* hoveredHorizontalLabelGroup = dynamic_cast<const HorizontalLabelGroup*>(hoveredItem);
|
||||
if (hoveredHorizontalLabelGroup != nullptr) {
|
||||
this->pinoutState.hoveredPinNumber = hoveredHorizontalLabelGroup->pinNumber;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* hoveredPin = dynamic_cast<const Pin*>(hoveredItem);
|
||||
if (hoveredPin != nullptr) {
|
||||
this->pinoutState.hoveredPinNumber = hoveredPin->number;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->pinoutState.hoveredPinNumber.has_value()) {
|
||||
this->pinoutState.hoveredPinNumber = std::nullopt;
|
||||
this->update();
|
||||
}
|
||||
}
|
||||
|
||||
void PinoutScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* mouseEvent) {
|
||||
if (mouseEvent->button() != Qt::MouseButton::LeftButton) {
|
||||
return QGraphicsScene::mouseReleaseEvent(mouseEvent);
|
||||
}
|
||||
|
||||
const auto mousePosition = mouseEvent->scenePos();
|
||||
|
||||
const auto clickedItems = this->items(mousePosition);
|
||||
if (clickedItems.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* clickedPinItem = dynamic_cast<const Pin*>(clickedItems.first());
|
||||
if (clickedPinItem == nullptr || !clickedPinItem->padDescriptor.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->toggleOutputPad(clickedPinItem->padDescriptor->get());
|
||||
}
|
||||
|
||||
void PinoutScene::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) {
|
||||
const auto screenPosition = event->screenPos();
|
||||
|
||||
const auto clickedItems = this->items(event->scenePos());
|
||||
if (clickedItems.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* clickedPinItem = dynamic_cast<const Pin*>(clickedItems.first());
|
||||
if (clickedPinItem != nullptr) {
|
||||
if (!clickedPinItem->padDescriptor.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* menu = this->contextMenuForPad(clickedPinItem->padDescriptor->get());
|
||||
menu->exec(screenPosition);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* clickedVerticalLabelGroupItem = dynamic_cast<const VerticalLabelGroup*>(clickedItems.first());
|
||||
if (clickedVerticalLabelGroupItem != nullptr) {
|
||||
if (!clickedVerticalLabelGroupItem->padDescriptor.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* menu = this->contextMenuForPad(clickedVerticalLabelGroupItem->padDescriptor->get());
|
||||
menu->exec(screenPosition);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto* clickedHorizontalLabelGroupItem = dynamic_cast<const HorizontalLabelGroup*>(clickedItems.first());
|
||||
if (clickedHorizontalLabelGroupItem != nullptr) {
|
||||
if (!clickedHorizontalLabelGroupItem->padDescriptor.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* menu = this->contextMenuForPad(clickedHorizontalLabelGroupItem->padDescriptor->get());
|
||||
menu->exec(screenPosition);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QMenu* PinoutScene::contextMenuForPad(const Targets::TargetPadDescriptor& padDescriptor) {
|
||||
using Targets::TargetGpioPadState;
|
||||
|
||||
auto* menu = new QMenu{this->parentView};
|
||||
menu->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
auto* toggleOutputAction = new QAction{"Toggle output state", menu};
|
||||
QObject::connect(
|
||||
toggleOutputAction,
|
||||
&QAction::triggered,
|
||||
this,
|
||||
[this, &padDescriptor] () {
|
||||
this->toggleOutputPad(padDescriptor);
|
||||
}
|
||||
);
|
||||
|
||||
const auto currentPadStateIt = this->gpioPadStatesByPadId.find(padDescriptor.id);
|
||||
if (
|
||||
currentPadStateIt == this->gpioPadStatesByPadId.end()
|
||||
|| currentPadStateIt->second.direction != TargetGpioPadState::DataDirection::OUTPUT
|
||||
) {
|
||||
toggleOutputAction->setDisabled(true);
|
||||
}
|
||||
|
||||
menu->addAction(toggleOutputAction);
|
||||
return menu;
|
||||
}
|
||||
|
||||
void PinoutScene::toggleOutputPad(const Targets::TargetPadDescriptor& padDescriptor) {
|
||||
using Targets::TargetGpioPadState;
|
||||
|
||||
const auto currentPadStateIt = this->gpioPadStatesByPadId.find(padDescriptor.id);
|
||||
if (currentPadStateIt == this->gpioPadStatesByPadId.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& currentPadState = currentPadStateIt->second;
|
||||
if (currentPadState.disabled || currentPadState.direction != TargetGpioPadState::DataDirection::OUTPUT) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto newPadState = currentPadState;
|
||||
newPadState.value = currentPadState.value == TargetGpioPadState::State::HIGH
|
||||
? TargetGpioPadState::State::LOW
|
||||
: TargetGpioPadState::State::HIGH;
|
||||
|
||||
const auto setPadStateTask = QSharedPointer<SetTargetGpioPadState>{
|
||||
new SetTargetGpioPadState{padDescriptor, newPadState},
|
||||
&QObject::deleteLater
|
||||
};
|
||||
|
||||
QObject::connect(
|
||||
setPadStateTask.get(),
|
||||
&InsightWorkerTask::completed,
|
||||
this,
|
||||
[this, &padDescriptor, newPadState] {
|
||||
this->updatePadStates(Targets::TargetGpioPadDescriptorAndStatePairs{{padDescriptor, newPadState}});
|
||||
}
|
||||
);
|
||||
|
||||
QObject::connect(setPadStateTask.get(), &InsightWorkerTask::finished, this, [this] {
|
||||
this->setDisabled(false);
|
||||
});
|
||||
|
||||
this->setDisabled(true);
|
||||
InsightWorker::queueTask(setPadStateTask);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsView>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QGraphicsSceneContextMenuEvent>
|
||||
#include <unordered_map>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
#include <QMenu>
|
||||
|
||||
#include "src/Targets/TargetDescriptor.hpp"
|
||||
#include "src/Targets/TargetPinoutDescriptor.hpp"
|
||||
#include "src/Targets/TargetPadDescriptor.hpp"
|
||||
#include "src/Targets/TargetGpioPadState.hpp"
|
||||
|
||||
#include "PinoutState.hpp"
|
||||
#include "PinoutItem.hpp"
|
||||
#include "PadLabels.hpp"
|
||||
#include "LabelGroupInterface.hpp"
|
||||
|
||||
#include "src/Helpers/Pair.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
class PinoutScene: public QGraphicsScene
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PinoutScene(const Targets::TargetDescriptor& targetDescriptor, QGraphicsView* parent);
|
||||
|
||||
bool isPinoutSupported(const Targets::TargetPinoutDescriptor& pinoutDescriptor);
|
||||
void setPinout(const Targets::TargetPinoutDescriptor& pinoutDescriptor);
|
||||
void setDisabled(bool disabled);
|
||||
void refreshPadStates(const std::optional<std::function<void(void)>>& callback = std::nullopt);
|
||||
|
||||
protected:
|
||||
QGraphicsView* parentView = nullptr;
|
||||
const Targets::TargetDescriptor& targetDescriptor;
|
||||
PinoutState pinoutState = {};
|
||||
PinoutItem* pinoutItem = nullptr;
|
||||
|
||||
std::unordered_map<Targets::TargetPadId, PadLabels> padLabelsByPadId;
|
||||
Targets::TargetPadDescriptors gpioPadDescriptors;
|
||||
std::unordered_map<Targets::TargetPadId, Targets::TargetGpioPadState> gpioPadStatesByPadId;
|
||||
|
||||
void adjustSize();
|
||||
void populatePadLabels(
|
||||
const std::vector<
|
||||
Pair<const Targets::TargetPadDescriptor&, LabelGroupInterface*>
|
||||
>& padDescriptorLabelGroupPairs
|
||||
);
|
||||
void updatePadStates(const Targets::TargetGpioPadDescriptorAndStatePairs& padStatePairs);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent) override;
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent* mouseEvent) override;
|
||||
void contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override;
|
||||
QMenu* contextMenuForPad(const Targets::TargetPadDescriptor& padDescriptor);
|
||||
|
||||
void toggleOutputPad(const Targets::TargetPadDescriptor& padDescriptor);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
struct PinoutState
|
||||
{
|
||||
std::optional<std::uint16_t> hoveredPinNumber = std::nullopt;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,552 @@
|
||||
#include "QfpPinout.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
#include "src/Services/StringService.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
QfpPinout::QfpPinout(
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor,
|
||||
const Targets::TargetDescriptor& targetDescriptor,
|
||||
const PinoutState& pinoutState
|
||||
)
|
||||
: packageBodySize({
|
||||
(Pin::WIDTH + QfpPinout::PIN_MARGIN) * static_cast<int>(pinoutDescriptor.pinDescriptors.size() / 4)
|
||||
- QfpPinout::PIN_MARGIN + (QfpPinout::PACKAGE_PADDING * 2),
|
||||
(Pin::WIDTH + QfpPinout::PIN_MARGIN) * static_cast<int>(pinoutDescriptor.pinDescriptors.size() / 4)
|
||||
- QfpPinout::PIN_MARGIN + (QfpPinout::PACKAGE_PADDING * 2)
|
||||
})
|
||||
, packageBodyPosition({})
|
||||
, pinoutDescriptor(pinoutDescriptor)
|
||||
, pinoutState(pinoutState)
|
||||
{
|
||||
assert((pinoutDescriptor.pinDescriptors.size() % 4) == 0);
|
||||
auto sortedPinDescriptors = std::vector<const Targets::TargetPinDescriptor*>{};
|
||||
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->leftQuadrantLabelGroupSet->setParentItem(this);
|
||||
this->bottomQuadrantLabelGroupSet->setParentItem(this);
|
||||
this->rightQuadrantLabelGroupSet->setParentItem(this);
|
||||
this->topQuadrantLabelGroupSet->setParentItem(this);
|
||||
|
||||
const auto quadSize = sortedPinDescriptors.size() / 4;
|
||||
|
||||
for (auto i = std::size_t{0}; i < quadSize; i++) {
|
||||
// Left pins
|
||||
const auto& pinDescriptor = *sortedPinDescriptors[i];
|
||||
auto* labelGroup = new HorizontalLabelGroup{
|
||||
pinDescriptor,
|
||||
pinDescriptor.padKey.has_value()
|
||||
? std::optional{std::cref(targetDescriptor.getPadDescriptor(*(pinDescriptor.padKey)))}
|
||||
: std::nullopt,
|
||||
HorizontalLabelGroup::Direction::LEFT,
|
||||
this->pinoutState
|
||||
};
|
||||
|
||||
labelGroup->setParentItem(this->leftQuadrantLabelGroupSet);
|
||||
this->leftQuadrantLabelGroupSet->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::HORIZONTAL,
|
||||
this->pinoutState
|
||||
};
|
||||
pin->setParentItem(this);
|
||||
|
||||
this->leftLabelGroupPinPairs.emplace_back(
|
||||
HorizontalLabelGroupPinPair{.labelGroup = labelGroup, .pin = pin}
|
||||
);
|
||||
}
|
||||
|
||||
for (auto i = quadSize; i < (quadSize * 2); 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 = quadSize * 2; i < (quadSize * 3); i++) {
|
||||
// Right pins
|
||||
const auto& pinDescriptor = *sortedPinDescriptors[i];
|
||||
auto* labelGroup = new HorizontalLabelGroup{
|
||||
pinDescriptor,
|
||||
pinDescriptor.padKey.has_value()
|
||||
? std::optional{std::cref(targetDescriptor.getPadDescriptor(*(pinDescriptor.padKey)))}
|
||||
: std::nullopt,
|
||||
HorizontalLabelGroup::Direction::RIGHT,
|
||||
this->pinoutState
|
||||
};
|
||||
|
||||
labelGroup->setParentItem(this->rightQuadrantLabelGroupSet);
|
||||
this->rightQuadrantLabelGroupSet->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::HORIZONTAL,
|
||||
this->pinoutState
|
||||
};
|
||||
pin->setParentItem(this);
|
||||
|
||||
this->rightLabelGroupPinPairs.emplace_back(
|
||||
HorizontalLabelGroupPinPair{.labelGroup = labelGroup, .pin = pin}
|
||||
);
|
||||
}
|
||||
|
||||
for (auto i = quadSize * 3; i < (quadSize * 4); 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<Pair<
|
||||
const Targets::TargetPadDescriptor&,
|
||||
LabelGroupInterface*
|
||||
>> QfpPinout::padDescriptorLabelGroupPairs() {
|
||||
auto output = std::vector<Pair<const Targets::TargetPadDescriptor&, LabelGroupInterface*>>{};
|
||||
|
||||
for (auto& [labelGroup, pin] : this->leftLabelGroupPinPairs) {
|
||||
if (!pin->padDescriptor.has_value()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
output.emplace_back(pin->padDescriptor->get(), labelGroup);
|
||||
}
|
||||
|
||||
for (auto& [labelGroup, pin] : this->bottomLabelGroupPinPairs) {
|
||||
if (!pin->padDescriptor.has_value()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
output.emplace_back(pin->padDescriptor->get(), labelGroup);
|
||||
}
|
||||
|
||||
for (auto& [labelGroup, pin] : this->rightLabelGroupPinPairs) {
|
||||
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 QfpPinout::refreshGeometry() {
|
||||
this->leftQuadrantLabelGroupSet->refreshGeometry();
|
||||
this->bottomQuadrantLabelGroupSet->refreshGeometry();
|
||||
this->rightQuadrantLabelGroupSet->refreshGeometry();
|
||||
this->topQuadrantLabelGroupSet->refreshGeometry();
|
||||
|
||||
const auto quadSize = this->pinoutDescriptor.pinDescriptors.size() / 4;
|
||||
const auto maxHorizontalPinLineAHeight = static_cast<int>(
|
||||
QfpPinout::MIN_LINE_A_LENGTH + (QfpPinout::PIN_LINE_A_SPACING
|
||||
* std::ceil(static_cast<float>(quadSize) / static_cast<float>(2)))
|
||||
);
|
||||
|
||||
const auto maxVerticalPinLineAHeight = this->minVerticalLineALength() + static_cast<int>(
|
||||
QfpPinout::PIN_LINE_A_SPACING * std::ceil(static_cast<float>(quadSize) / static_cast<float>(2))
|
||||
);
|
||||
|
||||
this->packageBodyPosition.setX(
|
||||
std::max(
|
||||
this->leftQuadrantLabelGroupSet->size.width() + maxHorizontalPinLineAHeight + QfpPinout::PIN_LINE_MARGIN + Pin::HEIGHT + QfpPinout::PIN_MARGIN,
|
||||
(std::max(this->bottomQuadrantLabelGroupSet->size.width(), this->topQuadrantLabelGroupSet->size.width()) / 2) - (this->packageBodySize.width() / 2)
|
||||
)
|
||||
);
|
||||
this->packageBodyPosition.setY(
|
||||
this->topQuadrantLabelGroupSet->size.height()
|
||||
+ maxVerticalPinLineAHeight + QfpPinout::PIN_LINE_MARGIN + Pin::HEIGHT + QfpPinout::PIN_MARGIN
|
||||
);
|
||||
|
||||
this->size.setWidth(
|
||||
std::max(
|
||||
std::max(
|
||||
this->bottomQuadrantLabelGroupSet->size.width(),
|
||||
this->topQuadrantLabelGroupSet->size.width()
|
||||
),
|
||||
this->leftQuadrantLabelGroupSet->size.width() + this->packageBodySize.width() + (
|
||||
(maxHorizontalPinLineAHeight + QfpPinout::PIN_LINE_MARGIN + Pin::HEIGHT + QfpPinout::PIN_MARGIN) * 2
|
||||
) + this->rightQuadrantLabelGroupSet->size.width()
|
||||
)
|
||||
);
|
||||
this->size.setHeight(
|
||||
this->topQuadrantLabelGroupSet->size.height() + this->packageBodySize.height()
|
||||
+ ((maxVerticalPinLineAHeight + QfpPinout::PIN_LINE_MARGIN + Pin::HEIGHT + QfpPinout::PIN_MARGIN) * 2)
|
||||
+ this->bottomQuadrantLabelGroupSet->size.height()
|
||||
);
|
||||
|
||||
// Position the pins
|
||||
auto leftPinYPosition = this->packageBodyPosition.y() + QfpPinout::PACKAGE_PADDING;
|
||||
for (auto& [labelGroup, pin] : this->leftLabelGroupPinPairs) {
|
||||
pin->setPos(
|
||||
this->packageBodyPosition.x() - Pin::HEIGHT - QfpPinout::PIN_MARGIN,
|
||||
leftPinYPosition
|
||||
);
|
||||
|
||||
leftPinYPosition += Pin::WIDTH + QfpPinout::PIN_MARGIN;
|
||||
}
|
||||
|
||||
auto bottomPinXPosition = this->packageBodyPosition.x() + QfpPinout::PACKAGE_PADDING;
|
||||
for (auto& [labelGroup, pin] : this->bottomLabelGroupPinPairs) {
|
||||
pin->setPos(
|
||||
bottomPinXPosition,
|
||||
this->packageBodyPosition.y() + this->packageBodySize.height() + QfpPinout::PIN_MARGIN
|
||||
);
|
||||
|
||||
bottomPinXPosition += Pin::WIDTH + QfpPinout::PIN_MARGIN;
|
||||
}
|
||||
|
||||
auto rightPinYPosition = this->packageBodyPosition.y() + this->packageBodySize.height()
|
||||
- QfpPinout::PACKAGE_PADDING - Pin::WIDTH;
|
||||
for (auto& [labelGroup, pin] : this->rightLabelGroupPinPairs) {
|
||||
pin->setPos(
|
||||
this->packageBodyPosition.x() + this->packageBodySize.width() + QfpPinout::PIN_MARGIN,
|
||||
rightPinYPosition
|
||||
);
|
||||
|
||||
rightPinYPosition -= Pin::WIDTH + QfpPinout::PIN_MARGIN;
|
||||
}
|
||||
|
||||
auto topPinXPosition = this->packageBodyPosition.x() + this->packageBodySize.width()
|
||||
- QfpPinout::PACKAGE_PADDING - Pin::WIDTH;
|
||||
for (auto& [labelGroup, pin] : this->topLabelGroupPinPairs) {
|
||||
pin->setPos(
|
||||
topPinXPosition,
|
||||
this->packageBodyPosition.y() - QfpPinout::PIN_MARGIN - Pin::HEIGHT
|
||||
);
|
||||
|
||||
topPinXPosition -= Pin::WIDTH + QfpPinout::PIN_MARGIN;
|
||||
}
|
||||
|
||||
this->leftQuadrantLabelGroupSet->setPos(
|
||||
this->packageBodyPosition.x() - QfpPinout::PIN_MARGIN - Pin::HEIGHT - QfpPinout::PIN_LINE_MARGIN
|
||||
- maxHorizontalPinLineAHeight - this->leftQuadrantLabelGroupSet->size.width(),
|
||||
this->packageBodyPosition.y() + (this->packageBodySize.height() / 2) - (this->leftQuadrantLabelGroupSet->size.height() / 2)
|
||||
);
|
||||
|
||||
this->topQuadrantLabelGroupSet->setPos(
|
||||
this->packageBodyPosition.x() + (this->packageBodySize.width() / 2)
|
||||
- (this->topQuadrantLabelGroupSet->size.width() / 2),
|
||||
0
|
||||
);
|
||||
|
||||
this->rightQuadrantLabelGroupSet->setPos(
|
||||
this->packageBodyPosition.x() + this->packageBodySize.width() + QfpPinout::PIN_MARGIN + Pin::HEIGHT + QfpPinout::PIN_LINE_MARGIN
|
||||
+ maxHorizontalPinLineAHeight,
|
||||
this->packageBodyPosition.y() + (this->packageBodySize.height() / 2) - (this->leftQuadrantLabelGroupSet->size.height() / 2)
|
||||
);
|
||||
|
||||
this->bottomQuadrantLabelGroupSet->setPos(
|
||||
this->packageBodyPosition.x() + (this->packageBodySize.width() / 2)
|
||||
- (this->bottomQuadrantLabelGroupSet->size.width() / 2),
|
||||
this->packageBodyPosition.y() + this->packageBodySize.height() + QfpPinout::PIN_MARGIN + Pin::HEIGHT
|
||||
+ QfpPinout::PIN_LINE_MARGIN + maxVerticalPinLineAHeight
|
||||
);
|
||||
}
|
||||
|
||||
QRectF QfpPinout::boundingRect() const {
|
||||
return QRectF{QPointF{0, 0}, this->size};
|
||||
}
|
||||
|
||||
void QfpPinout::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() + 10,
|
||||
this->packageBodyPosition.y() + 10,
|
||||
14,
|
||||
14
|
||||
);
|
||||
|
||||
painter->setRenderHints(QPainter::RenderHint::Antialiasing, false);
|
||||
|
||||
// Pin lines
|
||||
const auto quadSize = this->pinoutDescriptor.pinDescriptors.size() / 4;
|
||||
|
||||
{
|
||||
// Left pin lines
|
||||
auto lineAEndXOffset = int{0};
|
||||
for (auto pinIndex = std::size_t{0}; pinIndex < this->leftLabelGroupPinPairs.size(); ++pinIndex) {
|
||||
const auto* pin = this->leftLabelGroupPinPairs[pinIndex].pin;
|
||||
const auto* labelGroup = this->leftLabelGroupPinPairs[pinIndex].labelGroup;
|
||||
|
||||
painter->setPen(
|
||||
this->pinoutState.hoveredPinNumber.has_value() && this->pinoutState.hoveredPinNumber == pin->number
|
||||
? HIGHLIGHTED_LINE_COLOR
|
||||
: LINE_COLOR
|
||||
);
|
||||
|
||||
const auto lineAStartX = static_cast<int>(pin->pos().x() - QfpPinout::PIN_LINE_MARGIN);
|
||||
const auto lineAStartY = static_cast<int>(pin->pos().y() + (Pin::WIDTH / 2));
|
||||
const auto lineAEndX = static_cast<int>(lineAStartX - QfpPinout::MIN_LINE_A_LENGTH - lineAEndXOffset);
|
||||
|
||||
painter->drawLine(lineAStartX, lineAStartY, lineAEndX, lineAStartY);
|
||||
|
||||
if (quadSize % 2 != 0 || pinIndex != (quadSize / 2 - 1)) {
|
||||
lineAEndXOffset = pinIndex <= (quadSize / 2 - 1)
|
||||
? lineAEndXOffset + QfpPinout::PIN_LINE_A_SPACING
|
||||
: lineAEndXOffset - QfpPinout::PIN_LINE_A_SPACING;
|
||||
}
|
||||
|
||||
const auto lineBStartX = lineAEndX;
|
||||
const auto lineBStartY = lineAStartY;
|
||||
const auto lineBEndY = static_cast<int>(
|
||||
this->leftQuadrantLabelGroupSet->pos().y() + labelGroup->pos().y()
|
||||
+ (labelGroup->size.height() / 2)
|
||||
);
|
||||
|
||||
painter->drawLine(lineBStartX, lineBStartY, lineBStartX, lineBEndY);
|
||||
|
||||
const auto lineCStartX = lineBStartX;
|
||||
const auto lineCStartY = lineBEndY;
|
||||
const auto lineCEndX = static_cast<int>(
|
||||
this->leftQuadrantLabelGroupSet->pos().x() + labelGroup->pos().x() + labelGroup->size.width() + QfpPinout::PIN_LINE_MARGIN
|
||||
);
|
||||
|
||||
painter->drawLine(lineCStartX, lineCStartY, lineCEndX, lineCStartY);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// 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<int>(pin->pos().x() + (Pin::WIDTH / 2));
|
||||
const auto lineAStartY = static_cast<int>(pin->pos().y() + Pin::HEIGHT + QfpPinout::PIN_LINE_MARGIN);
|
||||
const auto lineAEndY = static_cast<int>(lineAStartY + this->minVerticalLineALength() + lineAEndYOffset);
|
||||
|
||||
painter->drawLine(lineAStartX, lineAStartY, lineAStartX, lineAEndY);
|
||||
|
||||
if (quadSize % 2 != 0 || pinIndex != (quadSize / 2 - 1)) {
|
||||
lineAEndYOffset = pinIndex <= (quadSize / 2 - 1)
|
||||
? lineAEndYOffset + QfpPinout::PIN_LINE_A_SPACING
|
||||
: lineAEndYOffset - QfpPinout::PIN_LINE_A_SPACING;
|
||||
}
|
||||
|
||||
const auto lineBStartX = lineAStartX;
|
||||
const auto lineBEndX = static_cast<int>(
|
||||
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<int>(
|
||||
this->bottomQuadrantLabelGroupSet->pos().y() + labelGroup->pos().y() - 5
|
||||
);
|
||||
|
||||
painter->drawLine(lineCStartX, lineCStartY, lineCStartX, lineCEndY);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Right pin lines
|
||||
auto lineAEndXOffset = int{0};
|
||||
for (auto pinIndex = std::size_t{0}; pinIndex < this->rightLabelGroupPinPairs.size(); ++pinIndex) {
|
||||
const auto* pin = this->rightLabelGroupPinPairs[pinIndex].pin;
|
||||
const auto* labelGroup = this->rightLabelGroupPinPairs[pinIndex].labelGroup;
|
||||
|
||||
painter->setPen(
|
||||
this->pinoutState.hoveredPinNumber.has_value() && this->pinoutState.hoveredPinNumber == pin->number
|
||||
? HIGHLIGHTED_LINE_COLOR
|
||||
: LINE_COLOR
|
||||
);
|
||||
|
||||
const auto lineAStartX = static_cast<int>(pin->pos().x() + Pin::HEIGHT + QfpPinout::PIN_LINE_MARGIN);
|
||||
const auto lineAStartY = static_cast<int>(pin->pos().y() + (Pin::WIDTH / 2));
|
||||
const auto lineAEndX = static_cast<int>(lineAStartX + QfpPinout::MIN_LINE_A_LENGTH + lineAEndXOffset);
|
||||
|
||||
painter->drawLine(lineAStartX, lineAStartY, lineAEndX, lineAStartY);
|
||||
|
||||
if (quadSize % 2 != 0 || pinIndex != (quadSize / 2 - 1)) {
|
||||
lineAEndXOffset = pinIndex <= (quadSize / 2 - 1)
|
||||
? lineAEndXOffset + QfpPinout::PIN_LINE_A_SPACING
|
||||
: lineAEndXOffset - QfpPinout::PIN_LINE_A_SPACING;
|
||||
}
|
||||
|
||||
const auto lineBStartX = lineAEndX;
|
||||
const auto lineBStartY = lineAStartY;
|
||||
const auto lineBEndY = static_cast<int>(
|
||||
this->rightQuadrantLabelGroupSet->pos().y() + labelGroup->pos().y()
|
||||
+ (labelGroup->size.height() / 2)
|
||||
);
|
||||
|
||||
painter->drawLine(lineBStartX, lineBStartY, lineBStartX, lineBEndY);
|
||||
|
||||
const auto lineCStartX = lineBStartX;
|
||||
const auto lineCStartY = lineBEndY;
|
||||
const auto lineCEndX = static_cast<int>(
|
||||
this->rightQuadrantLabelGroupSet->pos().x() + labelGroup->pos().x() - QfpPinout::PIN_LINE_MARGIN
|
||||
);
|
||||
|
||||
painter->drawLine(lineCStartX, lineCStartY, lineCEndX, lineCStartY);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// 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<int>(pin->pos().x() + (Pin::WIDTH / 2));
|
||||
const auto lineAStartY = static_cast<int>(pin->pos().y() - QfpPinout::PIN_LINE_MARGIN);
|
||||
const auto lineAEndY = lineAStartY - (this->minVerticalLineALength() + lineAEndYOffset);
|
||||
|
||||
painter->drawLine(lineAStartX, lineAStartY, lineAStartX, lineAEndY);
|
||||
|
||||
if (quadSize % 2 != 0 || pinIndex != (quadSize / 2 - 1)) {
|
||||
lineAEndYOffset = pinIndex <= (quadSize / 2 - 1)
|
||||
? lineAEndYOffset + QfpPinout::PIN_LINE_A_SPACING
|
||||
: lineAEndYOffset - QfpPinout::PIN_LINE_A_SPACING;
|
||||
}
|
||||
|
||||
const auto lineBStartX = lineAStartX;
|
||||
const auto lineBEndX = static_cast<int>(
|
||||
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<int>(
|
||||
this->topQuadrantLabelGroupSet->pos().y() + labelGroup->pos().y() + labelGroup->size.height() + 5
|
||||
);
|
||||
|
||||
painter->drawLine(lineCStartX, lineCStartY, lineCStartX, lineCEndY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int QfpPinout::minVerticalLineALength() const {
|
||||
return std::max(
|
||||
(
|
||||
this->leftQuadrantLabelGroupSet->size.height() - (this->packageBodySize.height()
|
||||
+ ((QfpPinout::PIN_MARGIN + Pin::HEIGHT + QfpPinout::PIN_LINE_MARGIN) * 2)
|
||||
) + 10
|
||||
) / 2,
|
||||
0
|
||||
) + QfpPinout::MIN_LINE_A_LENGTH;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
#include <QSize>
|
||||
#include <QPoint>
|
||||
#include <QPainter>
|
||||
#include <vector>
|
||||
|
||||
#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/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/HorizontalLabelGroup.hpp"
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/HorizontalLabelGroupSet.hpp"
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/PinoutWidgets/HorizontalLabelGroupPinPair.hpp"
|
||||
|
||||
#include "src/Helpers/Pair.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
class QfpPinout: public PinoutItem
|
||||
{
|
||||
public:
|
||||
static constexpr int PACKAGE_PADDING = 15;
|
||||
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;
|
||||
|
||||
QSize size = {};
|
||||
|
||||
QSize packageBodySize;
|
||||
QPoint packageBodyPosition;
|
||||
|
||||
QfpPinout(
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor,
|
||||
const Targets::TargetDescriptor& targetDescriptor,
|
||||
const PinoutState& pinoutState
|
||||
);
|
||||
|
||||
std::vector<Pair<const Targets::TargetPadDescriptor&, LabelGroupInterface*>> 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;
|
||||
|
||||
HorizontalLabelGroupSet* leftQuadrantLabelGroupSet = new HorizontalLabelGroupSet{
|
||||
HorizontalLabelGroupSet::Position::LEFT
|
||||
};
|
||||
HorizontalLabelGroupSet* rightQuadrantLabelGroupSet = new HorizontalLabelGroupSet{
|
||||
HorizontalLabelGroupSet::Position::RIGHT
|
||||
};
|
||||
|
||||
VerticalLabelGroupSet* topQuadrantLabelGroupSet = new VerticalLabelGroupSet{
|
||||
VerticalLabelGroupSet::Position::TOP
|
||||
};
|
||||
VerticalLabelGroupSet* bottomQuadrantLabelGroupSet = new VerticalLabelGroupSet{
|
||||
VerticalLabelGroupSet::Position::BOTTOM
|
||||
};
|
||||
|
||||
std::vector<HorizontalLabelGroupPinPair> leftLabelGroupPinPairs = {};
|
||||
std::vector<HorizontalLabelGroupPinPair> rightLabelGroupPinPairs = {};
|
||||
|
||||
std::vector<VerticalLabelGroupPinPair> topLabelGroupPinPairs = {};
|
||||
std::vector<VerticalLabelGroupPinPair> bottomLabelGroupPinPairs = {};
|
||||
|
||||
int minVerticalLineALength() const;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
#include "VerticalLabelGroup.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <ranges>
|
||||
|
||||
#include "src/Services/StringService.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
VerticalLabelGroup::VerticalLabelGroup(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
const PinoutState& pinoutState
|
||||
)
|
||||
: pinDescriptor(pinDescriptor)
|
||||
, padDescriptor(padDescriptor)
|
||||
, pinNumber(Services::StringService::toUint16(this->pinDescriptor.position, 10))
|
||||
, pinoutState(pinoutState)
|
||||
, pinNumberLabel(PinNumberLabel{this->pinDescriptor})
|
||||
, padNameLabel(PadNameLabel{this->padDescriptor})
|
||||
{
|
||||
this->setAcceptedMouseButtons(Qt::MouseButton::NoButton);
|
||||
}
|
||||
|
||||
void VerticalLabelGroup::insertLabel(std::unique_ptr<Label>&& label) {
|
||||
this->secondaryLabels.emplace_back(std::move(label));
|
||||
}
|
||||
|
||||
void VerticalLabelGroup::refreshGeometry() {
|
||||
this->secondaryLabelsByRowIndex.clear();
|
||||
|
||||
this->pinNumberLabel.refreshGeometry();
|
||||
this->padNameLabel.refreshGeometry();
|
||||
|
||||
const auto primaryRowWidth = this->pinNumberLabel.minimumWidth + VerticalLabelGroup::LABEL_MARGIN
|
||||
+ this->padNameLabel.minimumWidth;
|
||||
auto maxLabelWidth = std::max(primaryRowWidth, VerticalLabelGroup::MIN_LABEL_WIDTH);
|
||||
|
||||
for (const auto& secondaryLabel : this->secondaryLabels) {
|
||||
if (!secondaryLabel->enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
secondaryLabel->refreshGeometry();
|
||||
|
||||
if (secondaryLabel->width > maxLabelWidth) {
|
||||
maxLabelWidth = secondaryLabel->width;
|
||||
}
|
||||
}
|
||||
|
||||
const auto addLabelToRow = [this, maxLabelWidth] (Label& label) -> std::size_t {
|
||||
for (auto& [rowIndex, rowLabels] : this->secondaryLabelsByRowIndex) {
|
||||
const auto occupiedRowWidth = std::accumulate(
|
||||
rowLabels.begin(),
|
||||
rowLabels.end(),
|
||||
int{0},
|
||||
[] (int width, const Label* label) {
|
||||
return width + label->minimumWidth + VerticalLabelGroup::LABEL_MARGIN;
|
||||
}
|
||||
) - VerticalLabelGroup::LABEL_MARGIN;
|
||||
const auto availableRowWidth = maxLabelWidth - occupiedRowWidth;
|
||||
|
||||
if (label.minimumWidth <= availableRowWidth) {
|
||||
rowLabels.emplace_back(&label);
|
||||
return rowIndex;
|
||||
}
|
||||
}
|
||||
|
||||
const auto newRowIndex = this->secondaryLabelsByRowIndex.empty()
|
||||
? 0
|
||||
: this->secondaryLabelsByRowIndex.size();
|
||||
this->secondaryLabelsByRowIndex.emplace(newRowIndex, std::vector{&label});
|
||||
return newRowIndex;
|
||||
};
|
||||
|
||||
for (auto& secondaryLabel : this->secondaryLabels) {
|
||||
if (!secondaryLabel->enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
addLabelToRow(*secondaryLabel);
|
||||
}
|
||||
|
||||
// Resize label widths to fill any excess row space
|
||||
for (const auto& rowLabels : std::views::values(this->secondaryLabelsByRowIndex)) {
|
||||
const auto occupiedRowWidth = std::accumulate(
|
||||
rowLabels.begin(),
|
||||
rowLabels.end(),
|
||||
int{0},
|
||||
[] (int width, const Label* label) {
|
||||
return width + label->minimumWidth + VerticalLabelGroup::LABEL_MARGIN;
|
||||
}
|
||||
) - VerticalLabelGroup::LABEL_MARGIN;
|
||||
const auto excessWidth = maxLabelWidth - occupiedRowWidth;
|
||||
|
||||
if (excessWidth == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto* label : rowLabels) {
|
||||
label->width += excessWidth / static_cast<int>(rowLabels.size());
|
||||
}
|
||||
|
||||
// Add the remainder to the first label in the row
|
||||
(*rowLabels.begin())->width += excessWidth % static_cast<int>(rowLabels.size());
|
||||
}
|
||||
|
||||
if (primaryRowWidth < maxLabelWidth) {
|
||||
this->padNameLabel.width += maxLabelWidth - primaryRowWidth;
|
||||
}
|
||||
|
||||
this->size.setWidth(maxLabelWidth + (VerticalLabelGroup::HORIZ_PADDING * 2));
|
||||
this->size.setHeight(
|
||||
(
|
||||
static_cast<int>(this->secondaryLabelsByRowIndex.size() + 1)
|
||||
* (Label::HEIGHT + VerticalLabelGroup::LABEL_MARGIN)
|
||||
) - VerticalLabelGroup::LABEL_MARGIN + (VerticalLabelGroup::VERTICAL_PADDING * 2)
|
||||
+ (!this->secondaryLabelsByRowIndex.empty() ? VerticalLabelGroup::SECONDARY_LABEL_SEPARATOR_SPACING : 0)
|
||||
);
|
||||
}
|
||||
|
||||
QRectF VerticalLabelGroup::boundingRect() const {
|
||||
return QRectF{QPointF{0, 0}, this->size};
|
||||
}
|
||||
|
||||
void VerticalLabelGroup::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
static constexpr auto LINE_COLOR = QColor{0x5E, 0x5C, 0x59};
|
||||
static constexpr auto HIGHLIGHTED_LINE_COLOR = QColor{0x7D, 0x7D, 0x7D};
|
||||
|
||||
painter->setOpacity(this->isEnabled() ? 1 : 0.6);
|
||||
painter->setPen(Qt::PenStyle::NoPen);
|
||||
constexpr auto START_X = VerticalLabelGroup::HORIZ_PADDING;
|
||||
auto yPos = VerticalLabelGroup::VERTICAL_PADDING;
|
||||
|
||||
this->pinNumberLabel.paint(painter, START_X, yPos);
|
||||
this->padNameLabel.paint(
|
||||
painter,
|
||||
START_X + this->pinNumberLabel.width + VerticalLabelGroup::LABEL_MARGIN,
|
||||
yPos
|
||||
);
|
||||
yPos += Label::HEIGHT + VerticalLabelGroup::LABEL_MARGIN;
|
||||
|
||||
const auto& lineColor = this->pinoutState.hoveredPinNumber.has_value()
|
||||
&& this->pinoutState.hoveredPinNumber == this->pinNumber
|
||||
? HIGHLIGHTED_LINE_COLOR
|
||||
: LINE_COLOR;
|
||||
|
||||
if (!this->secondaryLabelsByRowIndex.empty()) {
|
||||
painter->setPen(lineColor);
|
||||
const auto centerX = this->size.width() / 2;
|
||||
painter->drawLine(
|
||||
centerX,
|
||||
yPos,
|
||||
centerX,
|
||||
yPos + VerticalLabelGroup::SECONDARY_LABEL_SEPARATOR_SPACING - VerticalLabelGroup::LABEL_MARGIN
|
||||
);
|
||||
painter->setPen(Qt::PenStyle::NoPen);
|
||||
|
||||
yPos += VerticalLabelGroup::SECONDARY_LABEL_SEPARATOR_SPACING;
|
||||
|
||||
for (const auto& rowLabels : std::views::values(this->secondaryLabelsByRowIndex)) {
|
||||
auto xPos = START_X;
|
||||
|
||||
for (const auto* label : rowLabels) {
|
||||
label->paint(painter, xPos, yPos);
|
||||
xPos += label->width + VerticalLabelGroup::LABEL_MARGIN;
|
||||
}
|
||||
|
||||
yPos += Label::HEIGHT + VerticalLabelGroup::LABEL_MARGIN;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr auto VERTICAL_BORDER_LENGTH = 10;
|
||||
painter->setPen(lineColor);
|
||||
painter->drawLine(0, 0, 0, VERTICAL_BORDER_LENGTH);
|
||||
painter->drawLine(0, 0, this->size.width(), 0);
|
||||
painter->drawLine(this->size.width(), 0, this->size.width(), VERTICAL_BORDER_LENGTH);
|
||||
|
||||
painter->drawLine(0, this->size.height() - 1, 0, this->size.height() - 1 - VERTICAL_BORDER_LENGTH);
|
||||
painter->drawLine(0, this->size.height() - 1, this->size.width(), this->size.height() - 1);
|
||||
painter->drawLine(
|
||||
this->size.width(),
|
||||
this->size.height() - 1, this->size.width(),
|
||||
this->size.height() - 1 - VERTICAL_BORDER_LENGTH
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include <QSize>
|
||||
#include <QRectF>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "src/Targets/TargetPinDescriptor.hpp"
|
||||
#include "src/Targets/TargetPadDescriptor.hpp"
|
||||
|
||||
#include "LabelGroupInterface.hpp"
|
||||
#include "PinoutState.hpp"
|
||||
#include "Label.hpp"
|
||||
#include "PinNumberLabel.hpp"
|
||||
#include "PadNameLabel.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
class VerticalLabelGroup
|
||||
: public LabelGroupInterface
|
||||
, public QGraphicsItem
|
||||
{
|
||||
public:
|
||||
static constexpr int VERTICAL_PADDING = 6;
|
||||
static constexpr int HORIZ_PADDING = 6;
|
||||
static constexpr int LABEL_MARGIN = 4;
|
||||
static constexpr int MIN_LABEL_WIDTH = 150;
|
||||
static constexpr int SECONDARY_LABEL_SEPARATOR_SPACING = 10;
|
||||
|
||||
const Targets::TargetPinDescriptor& pinDescriptor;
|
||||
const std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor;
|
||||
std::uint16_t pinNumber;
|
||||
QSize size = {};
|
||||
|
||||
VerticalLabelGroup(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
const PinoutState& pinoutState
|
||||
);
|
||||
|
||||
void insertLabel(std::unique_ptr<Label>&& label) override;
|
||||
void refreshGeometry();
|
||||
[[nodiscard]] QRectF boundingRect() const override;
|
||||
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
|
||||
|
||||
private:
|
||||
const PinoutState& pinoutState;
|
||||
PinNumberLabel pinNumberLabel;
|
||||
PadNameLabel padNameLabel;
|
||||
|
||||
std::vector<std::unique_ptr<Label>> secondaryLabels;
|
||||
std::map<std::size_t, std::vector<Label*>> secondaryLabelsByRowIndex;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "VerticalLabelGroup.hpp"
|
||||
#include "Pin.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
struct VerticalLabelGroupPinPair
|
||||
{
|
||||
VerticalLabelGroup* labelGroup;
|
||||
Pin* pin;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
#include "VerticalLabelGroupSet.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <ranges>
|
||||
#include <QPoint>
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
VerticalLabelGroupSet::VerticalLabelGroupSet(Position position)
|
||||
: labelGroups({})
|
||||
, size({0, 0})
|
||||
, position(position)
|
||||
{}
|
||||
|
||||
void VerticalLabelGroupSet::refreshGeometry() {
|
||||
for (auto* labelGroup : this->labelGroups) {
|
||||
labelGroup->refreshGeometry();
|
||||
}
|
||||
|
||||
const auto firstRowHeight = this->getFirstRowHeight();
|
||||
|
||||
auto maxHeight = int{0};
|
||||
auto firstRowXPos = int{0};
|
||||
auto secondRowXPos = int{0};
|
||||
|
||||
const auto positionLabelGroup = [&] (VerticalLabelGroup* labelGroup) {
|
||||
|
||||
if (this->isGroupOnFirstRow(labelGroup)) {
|
||||
auto position = QPoint{
|
||||
firstRowXPos + VerticalLabelGroupSet::GROUP_HORIZONTAL_MARGIN,
|
||||
0
|
||||
};
|
||||
|
||||
if (
|
||||
this->position == Position::TOP
|
||||
|| (this->labelGroups.size() % 2 != 0 && firstRowXPos == 0 && secondRowXPos > 0)
|
||||
) {
|
||||
const auto groupCenterX = position.x() + (labelGroup->size.width() / 2);
|
||||
const auto secondRowMinX = secondRowXPos + (VerticalLabelGroupSet::GROUP_HORIZONTAL_MARGIN / 2);
|
||||
|
||||
if (groupCenterX < secondRowMinX) {
|
||||
position.setX(position.x() + (secondRowMinX - groupCenterX));
|
||||
|
||||
} else {
|
||||
secondRowXPos = groupCenterX - (VerticalLabelGroupSet::GROUP_HORIZONTAL_MARGIN / 2);
|
||||
}
|
||||
}
|
||||
|
||||
labelGroup->setPos(position);
|
||||
firstRowXPos = position.x() + labelGroup->size.width();
|
||||
|
||||
} else {
|
||||
auto position = QPoint{
|
||||
secondRowXPos + VerticalLabelGroupSet::GROUP_HORIZONTAL_MARGIN,
|
||||
firstRowHeight + VerticalLabelGroupSet::GROUP_VERTICAL_MARGIN
|
||||
};
|
||||
|
||||
if (
|
||||
this->position == Position::BOTTOM
|
||||
|| (this->labelGroups.size() % 2 != 0 && secondRowXPos == 0 && firstRowXPos > 0)
|
||||
) {
|
||||
const auto groupCenterX = position.x() + (labelGroup->size.width() / 2);
|
||||
const auto firstRowMinX = firstRowXPos + (VerticalLabelGroupSet::GROUP_HORIZONTAL_MARGIN / 2);
|
||||
|
||||
if (groupCenterX < firstRowMinX) {
|
||||
position.setX(position.x() + (firstRowMinX - groupCenterX));
|
||||
|
||||
} else {
|
||||
firstRowXPos = groupCenterX - (VerticalLabelGroupSet::GROUP_HORIZONTAL_MARGIN / 2);
|
||||
}
|
||||
}
|
||||
|
||||
labelGroup->setPos(position);
|
||||
secondRowXPos = position.x() + labelGroup->size.width();
|
||||
}
|
||||
|
||||
maxHeight = std::max(static_cast<int>(labelGroup->pos().y() + labelGroup->size.height()), maxHeight);
|
||||
};
|
||||
|
||||
if (this->position == Position::TOP) {
|
||||
for (auto groupIt = this->labelGroups.rbegin(); groupIt < this->labelGroups.rend(); ++groupIt) {
|
||||
positionLabelGroup(*groupIt);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (auto groupIt = this->labelGroups.begin(); groupIt < this->labelGroups.end(); ++groupIt) {
|
||||
positionLabelGroup(*groupIt);
|
||||
}
|
||||
}
|
||||
|
||||
this->size.setWidth(std::max(firstRowXPos, secondRowXPos));
|
||||
this->size.setHeight(maxHeight);
|
||||
}
|
||||
|
||||
QRectF VerticalLabelGroupSet::boundingRect() const {
|
||||
return QRectF{QPointF{0, 0}, this->size};
|
||||
}
|
||||
|
||||
void VerticalLabelGroupSet::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
|
||||
// Nothing to do here...
|
||||
}
|
||||
|
||||
bool VerticalLabelGroupSet::isGroupOnFirstRow(const VerticalLabelGroup* group) const {
|
||||
return (group->pinNumber % 2) != 0;
|
||||
}
|
||||
|
||||
int VerticalLabelGroupSet::getFirstRowHeight() const {
|
||||
auto height = int{0};
|
||||
|
||||
for (const auto* labelGroup : this->labelGroups) {
|
||||
if (!this->isGroupOnFirstRow(labelGroup)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
height = std::max(labelGroup->size.height(), height);
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include <QSize>
|
||||
#include <QRectF>
|
||||
#include <QPainter>
|
||||
#include <vector>
|
||||
|
||||
#include "VerticalLabelGroup.hpp"
|
||||
|
||||
namespace Widgets::PinoutWidgets
|
||||
{
|
||||
class VerticalLabelGroupSet: public QGraphicsItem
|
||||
{
|
||||
public:
|
||||
static constexpr int GROUP_HORIZONTAL_MARGIN = 16;
|
||||
static constexpr int GROUP_VERTICAL_MARGIN = 10;
|
||||
|
||||
enum Position: std::uint8_t
|
||||
{
|
||||
TOP,
|
||||
BOTTOM
|
||||
};
|
||||
|
||||
std::vector<VerticalLabelGroup*> labelGroups;
|
||||
QSize size;
|
||||
const Position position;
|
||||
|
||||
explicit VerticalLabelGroupSet(Position position);
|
||||
|
||||
void refreshGeometry();
|
||||
[[nodiscard]] QRectF boundingRect() const override;
|
||||
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) override;
|
||||
|
||||
private:
|
||||
bool isGroupOnFirstRow(const VerticalLabelGroup* group) const;
|
||||
int getFirstRowHeight() const;
|
||||
};
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
#include "BodyWidget.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Dip
|
||||
{
|
||||
BodyWidget::BodyWidget(QWidget* parent, std::size_t pinCount)
|
||||
: QWidget(parent)
|
||||
{
|
||||
this->setObjectName("target-body");
|
||||
|
||||
/*
|
||||
* The DIP package widget looks awkward when the body height is fixed. For this reason, the body height and
|
||||
* indicator sizes are proportional to the pin count.
|
||||
*
|
||||
* The proportionality constants used below were chosen because they look the nicest. No other reason.
|
||||
*/
|
||||
this->setFixedHeight(
|
||||
std::min(
|
||||
BodyWidget::MAXIMUM_BODY_HEIGHT,
|
||||
std::max(
|
||||
BodyWidget::MINIMUM_BODY_HEIGHT,
|
||||
static_cast<int>(std::ceil(3.6 * static_cast<double>(pinCount)))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
this->firstPinIndicatorDiameter = std::min(
|
||||
BodyWidget::MAXIMUM_FIRST_PIN_INDICATOR_HEIGHT,
|
||||
std::max(BodyWidget::MINIMUM_FIRST_PIN_INDICATOR_HEIGHT, static_cast<int>(std::floor(pinCount / 2)))
|
||||
);
|
||||
|
||||
this->orientationIndicatorDiameter = this->firstPinIndicatorDiameter % 2 == 0 ?
|
||||
this->firstPinIndicatorDiameter + 3
|
||||
: this->firstPinIndicatorDiameter + 2;
|
||||
}
|
||||
|
||||
void BodyWidget::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter{this};
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
|
||||
void BodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setRenderHints(
|
||||
QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform,
|
||||
true
|
||||
);
|
||||
const auto bodyHeight = this->height();
|
||||
const auto bodyRect = QRectF(
|
||||
0,
|
||||
0,
|
||||
this->width(),
|
||||
bodyHeight
|
||||
);
|
||||
|
||||
// The first pin indicator is just a circle positioned close to the first pin
|
||||
const auto firstPinIndicatorRect = QRectF(
|
||||
6,
|
||||
(bodyHeight - this->firstPinIndicatorDiameter - 6),
|
||||
this->firstPinIndicatorDiameter,
|
||||
this->firstPinIndicatorDiameter
|
||||
);
|
||||
|
||||
/*
|
||||
* The orientation indicator is just a half-circle cut-out, positioned on the side of the DIP package
|
||||
* closest to the first pin.
|
||||
*/
|
||||
const auto orientationIndicatorRect = QRectF(
|
||||
-(this->orientationIndicatorDiameter / 2),
|
||||
(bodyHeight / 2) - (this->orientationIndicatorDiameter / 2),
|
||||
this->orientationIndicatorDiameter,
|
||||
this->orientationIndicatorDiameter
|
||||
);
|
||||
|
||||
static const auto backgroundColor = QColor{0x37, 0x38, 0x35};
|
||||
auto targetBodyColor = this->getBodyColor();
|
||||
|
||||
if (!this->isEnabled()) {
|
||||
targetBodyColor.setAlpha(this->getDisableAlphaLevel());
|
||||
}
|
||||
|
||||
painter.setPen(Qt::PenStyle::NoPen);
|
||||
painter.setBrush(targetBodyColor);
|
||||
painter.drawRect(bodyRect);
|
||||
painter.setBrush(backgroundColor);
|
||||
painter.drawEllipse(firstPinIndicatorRect);
|
||||
painter.drawEllipse(orientationIndicatorRect);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPainter>
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Dip
|
||||
{
|
||||
class BodyWidget: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QColor bodyColor READ getBodyColor WRITE setBodyColor DESIGNABLE true)
|
||||
Q_PROPERTY(int disableAlphaLevel READ getDisableAlphaLevel WRITE setDisableAlphaLevel DESIGNABLE true)
|
||||
|
||||
public:
|
||||
explicit BodyWidget(QWidget* parent, std::size_t pinCount);
|
||||
|
||||
[[nodiscard]] QColor getBodyColor() const {
|
||||
return this->bodyColor;
|
||||
}
|
||||
|
||||
void setBodyColor(const QColor& color) {
|
||||
this->bodyColor = color;
|
||||
}
|
||||
|
||||
[[nodiscard]] int getDisableAlphaLevel() const {
|
||||
return this->disableAlphaLevel;
|
||||
}
|
||||
|
||||
void setDisableAlphaLevel(int level) {
|
||||
this->disableAlphaLevel = level;
|
||||
}
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
void drawWidget(QPainter& painter);
|
||||
|
||||
private:
|
||||
static constexpr int MAXIMUM_BODY_HEIGHT = 156;
|
||||
static constexpr int MINIMUM_BODY_HEIGHT = 96;
|
||||
static constexpr int MAXIMUM_FIRST_PIN_INDICATOR_HEIGHT = 16;
|
||||
static constexpr int MINIMUM_FIRST_PIN_INDICATOR_HEIGHT = 12;
|
||||
|
||||
// These properties can be modified via Qt style sheets (see Stylesheets/DualInlinePackage.qss)
|
||||
QColor bodyColor = {"#8E8B83"};
|
||||
int disableAlphaLevel = 100;
|
||||
int firstPinIndicatorDiameter = 14;
|
||||
int orientationIndicatorDiameter = 16;
|
||||
};
|
||||
}
|
||||
@@ -1,273 +0,0 @@
|
||||
#include "DualInlinePackageWidget.hpp"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <vector>
|
||||
#include <QEvent>
|
||||
#include <QFile>
|
||||
|
||||
#include "src/Services/PathService.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Dip
|
||||
{
|
||||
DualInlinePackageWidget::DualInlinePackageWidget(
|
||||
const Targets::TargetVariantDescriptor& variantDescriptor,
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor,
|
||||
const Targets::TargetDescriptor& targetDescriptor,
|
||||
const Targets::TargetState& targetState,
|
||||
QWidget* parent
|
||||
)
|
||||
: TargetPackageWidget(
|
||||
variantDescriptor,
|
||||
pinoutDescriptor,
|
||||
targetState,
|
||||
parent
|
||||
)
|
||||
{
|
||||
auto stylesheetFile = QFile{QString::fromStdString(
|
||||
Services::PathService::compiledResourcesPath()
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/Stylesheets/"
|
||||
"DualInlinePackage.qss"
|
||||
)
|
||||
};
|
||||
stylesheetFile.open(QFile::ReadOnly);
|
||||
this->setStyleSheet(stylesheetFile.readAll());
|
||||
|
||||
this->pinWidgets.reserve(this->pinoutDescriptor.pinDescriptors.size());
|
||||
this->layout = new QVBoxLayout{};
|
||||
this->layout->setSpacing(PinWidget::WIDTH_SPACING);
|
||||
this->layout->setContentsMargins(0, 0, 0, 0);
|
||||
this->layout->setAlignment(Qt::AlignmentFlag::AlignVCenter);
|
||||
|
||||
this->topPinLayout = new QHBoxLayout{};
|
||||
this->topPinLayout->setSpacing(PinWidget::WIDTH_SPACING);
|
||||
this->topPinLayout->setDirection(QBoxLayout::Direction::RightToLeft);
|
||||
this->topPinLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter);
|
||||
this->bottomPinLayout = new QHBoxLayout{};
|
||||
this->bottomPinLayout->setSpacing(PinWidget::WIDTH_SPACING);
|
||||
this->bottomPinLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter);
|
||||
|
||||
for (const auto& pinDescriptor : this->pinoutDescriptor.pinDescriptors) {
|
||||
auto* pinWidget = new PinWidget{
|
||||
pinDescriptor,
|
||||
pinDescriptor.padKey.has_value()
|
||||
? targetDescriptor.tryGetPadDescriptor(*(pinDescriptor.padKey))
|
||||
: std::nullopt,
|
||||
this->pinoutDescriptor,
|
||||
this
|
||||
};
|
||||
this->pinWidgets.push_back(pinWidget);
|
||||
TargetPackageWidget::pinWidgetsByPosition.emplace(pinDescriptor.numericPosition, pinWidget);
|
||||
|
||||
if (pinWidget->padDescriptor.has_value()) {
|
||||
const auto& padDescriptor = pinWidget->padDescriptor->get();
|
||||
TargetPackageWidget::pinWidgetsByPadId.emplace(padDescriptor.id, pinWidget);
|
||||
TargetPackageWidget::padDescriptors.push_back(&padDescriptor);
|
||||
}
|
||||
|
||||
if (pinDescriptor.numericPosition <= (this->pinoutDescriptor.pinDescriptors.size() / 2)) {
|
||||
this->bottomPinLayout->addWidget(pinWidget, 0, Qt::AlignmentFlag::AlignHCenter);
|
||||
} else {
|
||||
this->topPinLayout->addWidget(pinWidget, 0, Qt::AlignmentFlag::AlignHCenter);
|
||||
}
|
||||
}
|
||||
|
||||
this->bodyWidget = new BodyWidget{this, this->pinoutDescriptor.pinDescriptors.size()};
|
||||
|
||||
this->layout->addLayout(this->topPinLayout);
|
||||
this->layout->addWidget(this->bodyWidget, 0, Qt::AlignmentFlag::AlignVCenter);
|
||||
this->layout->addLayout(this->bottomPinLayout);
|
||||
this->setLayout(this->layout);
|
||||
|
||||
const auto bodyWidgetHeight = this->bodyWidget->height();
|
||||
const auto bodyWidgetWidth = ((PinWidget::MINIMUM_WIDTH + PinWidget::WIDTH_SPACING)
|
||||
* static_cast<int>(this->pinWidgets.size() / 2)) - PinWidget::WIDTH_SPACING + 46;
|
||||
|
||||
this->bodyWidget->setGeometry(
|
||||
0,
|
||||
PinWidget::MAXIMUM_HEIGHT + PinWidget::WIDTH_SPACING,
|
||||
bodyWidgetWidth,
|
||||
bodyWidgetHeight
|
||||
);
|
||||
|
||||
const auto width = bodyWidgetWidth;
|
||||
const auto height = (
|
||||
(
|
||||
PinWidget::MAXIMUM_HEIGHT + PinWidget::WIDTH_SPACING + PinWidget::PIN_NAME_LABEL_LONG_LINE_LENGTH
|
||||
+ PinWidget::PIN_DIRECTION_LABEL_LONG_LINE_LENGTH + (
|
||||
(PinWidget::LABEL_HEIGHT + PinWidget::PIN_LABEL_SPACING) * 2
|
||||
)
|
||||
) * 2) + bodyWidgetHeight;
|
||||
|
||||
this->topPinLayout->setGeometry(QRect{0, 0, width, PinWidget::MAXIMUM_HEIGHT});
|
||||
this->bottomPinLayout->setGeometry(
|
||||
QRect(
|
||||
0,
|
||||
(PinWidget::MAXIMUM_HEIGHT + bodyWidgetHeight + (PinWidget::WIDTH_SPACING * 2)),
|
||||
width,
|
||||
PinWidget::MAXIMUM_HEIGHT
|
||||
)
|
||||
);
|
||||
this->topPinLayout->setContentsMargins(23, 0, 23, 0);
|
||||
this->bottomPinLayout->setContentsMargins( 23, 0, 23, 0);
|
||||
|
||||
this->setFixedSize(width, height);
|
||||
|
||||
this->setGeometry(
|
||||
(parent->width() / 2) - (width / 2),
|
||||
(parent->height() / 2) - (height / 2),
|
||||
width,
|
||||
height
|
||||
);
|
||||
}
|
||||
|
||||
void DualInlinePackageWidget::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter{this};
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
|
||||
void DualInlinePackageWidget::drawWidget(QPainter& painter) {
|
||||
using Targets::TargetGpioPadState;
|
||||
|
||||
static auto pinNameFont = QFont{"'Ubuntu', sans-serif"};
|
||||
static auto pinDirectionFont = pinNameFont;
|
||||
pinNameFont.setPixelSize(11);
|
||||
pinDirectionFont.setPixelSize(10);
|
||||
|
||||
static const auto lineColor = QColor{0x4F, 0x4F, 0x4F};
|
||||
static const auto pinNameFontColor = QColor{0xA6, 0xA7, 0xAA};
|
||||
static const auto pinDirectionFontColor = QColor{0x8A, 0x8A, 0x8D};
|
||||
static const auto pinChangedFontColor = QColor{0x4D, 0x7B, 0xBA};
|
||||
|
||||
static const auto inDirectionText = QString{"IN"};
|
||||
static const auto outDirectionText = QString{"OUT"};
|
||||
|
||||
for (const auto* pinWidget : this->pinWidgets) {
|
||||
const auto pinGeoPosition = pinWidget->pos();
|
||||
|
||||
painter.setFont(pinNameFont);
|
||||
|
||||
if (pinWidget->position == Position::TOP) {
|
||||
painter.setPen(lineColor);
|
||||
const auto pinNameLabelLineLength = (pinWidget->getPinNumber() % 2 == 0
|
||||
? PinWidget::PIN_NAME_LABEL_LONG_LINE_LENGTH
|
||||
: PinWidget::PIN_NAME_LABEL_SHORT_LINE_LENGTH
|
||||
);
|
||||
const auto pinDirectionLabelLineLength = (pinWidget->getPinNumber() % 2 == 0
|
||||
? PinWidget::PIN_DIRECTION_LABEL_SHORT_LINE_LENGTH
|
||||
: PinWidget::PIN_DIRECTION_LABEL_LONG_LINE_LENGTH
|
||||
);
|
||||
|
||||
painter.drawLine(QLine(
|
||||
pinGeoPosition.x() + (PinWidget::MINIMUM_WIDTH / 2),
|
||||
pinGeoPosition.y() - pinNameLabelLineLength,
|
||||
pinGeoPosition.x() + (PinWidget::MINIMUM_WIDTH / 2),
|
||||
pinGeoPosition.y()
|
||||
));
|
||||
|
||||
painter.setPen(pinWidget->padStateChanged ? pinChangedFontColor : pinNameFontColor);
|
||||
painter.drawText(
|
||||
QRect(
|
||||
pinGeoPosition.x() + (PinWidget::MINIMUM_WIDTH / 2)
|
||||
- (PinWidget::MAXIMUM_LABEL_WIDTH / 2),
|
||||
pinGeoPosition.y() - pinNameLabelLineLength - PinWidget::MAXIMUM_LABEL_HEIGHT,
|
||||
PinWidget::MAXIMUM_LABEL_WIDTH,
|
||||
PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
),
|
||||
Qt::AlignCenter,
|
||||
pinWidget->pinNameLabelText
|
||||
);
|
||||
|
||||
if (pinWidget->padState.has_value()) {
|
||||
painter.setFont(pinDirectionFont);
|
||||
|
||||
painter.setPen(lineColor);
|
||||
painter.drawLine(QLine(
|
||||
pinGeoPosition.x() + (PinWidget::MINIMUM_WIDTH / 2),
|
||||
pinGeoPosition.y() - pinNameLabelLineLength - PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
- pinDirectionLabelLineLength,
|
||||
pinGeoPosition.x() + (PinWidget::MINIMUM_WIDTH / 2),
|
||||
pinGeoPosition.y() - pinNameLabelLineLength - PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
));
|
||||
|
||||
painter.setPen(pinDirectionFontColor);
|
||||
painter.drawText(
|
||||
QRect(
|
||||
pinGeoPosition.x() + (PinWidget::MINIMUM_WIDTH / 2)
|
||||
- (PinWidget::MAXIMUM_LABEL_WIDTH / 2),
|
||||
pinGeoPosition.y() - pinNameLabelLineLength - pinDirectionLabelLineLength
|
||||
- (PinWidget::MAXIMUM_LABEL_HEIGHT * 2),
|
||||
PinWidget::MAXIMUM_LABEL_WIDTH,
|
||||
PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
),
|
||||
Qt::AlignCenter,
|
||||
pinWidget->padState->direction == TargetGpioPadState::DataDirection::INPUT
|
||||
? inDirectionText
|
||||
: outDirectionText
|
||||
);
|
||||
}
|
||||
|
||||
} else if (pinWidget->position == Position::BOTTOM) {
|
||||
painter.setPen(lineColor);
|
||||
const auto pinNameLabelLineLength = (pinWidget->getPinNumber() % 2 == 0
|
||||
? PinWidget::PIN_NAME_LABEL_LONG_LINE_LENGTH
|
||||
: PinWidget::PIN_NAME_LABEL_SHORT_LINE_LENGTH
|
||||
);
|
||||
const auto pinDirectionLabelLineLength = (pinWidget->getPinNumber() % 2 == 0
|
||||
? PinWidget::PIN_DIRECTION_LABEL_SHORT_LINE_LENGTH
|
||||
: PinWidget::PIN_DIRECTION_LABEL_LONG_LINE_LENGTH
|
||||
);
|
||||
|
||||
painter.drawLine(QLine(
|
||||
pinGeoPosition.x() + (PinWidget::MINIMUM_WIDTH / 2),
|
||||
pinGeoPosition.y() + PinWidget::MAXIMUM_HEIGHT,
|
||||
pinGeoPosition.x() + (PinWidget::MINIMUM_WIDTH / 2),
|
||||
pinGeoPosition.y() + PinWidget::MAXIMUM_HEIGHT + pinNameLabelLineLength
|
||||
));
|
||||
|
||||
painter.setPen(pinWidget->padStateChanged ? pinChangedFontColor : pinNameFontColor);
|
||||
painter.drawText(
|
||||
QRect(
|
||||
pinGeoPosition.x() + (PinWidget::MINIMUM_WIDTH / 2)
|
||||
- (PinWidget::MAXIMUM_LABEL_WIDTH / 2),
|
||||
pinGeoPosition.y() + + PinWidget::MAXIMUM_HEIGHT + pinNameLabelLineLength,
|
||||
PinWidget::MAXIMUM_LABEL_WIDTH,
|
||||
PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
),
|
||||
Qt::AlignCenter,
|
||||
pinWidget->pinNameLabelText
|
||||
);
|
||||
|
||||
if (pinWidget->padState.has_value()) {
|
||||
painter.setFont(pinDirectionFont);
|
||||
|
||||
painter.setPen(lineColor);
|
||||
painter.drawLine(QLine(
|
||||
pinGeoPosition.x() + (PinWidget::MINIMUM_WIDTH / 2),
|
||||
pinGeoPosition.y() + PinWidget::MAXIMUM_HEIGHT + pinNameLabelLineLength
|
||||
+ PinWidget::MAXIMUM_LABEL_HEIGHT,
|
||||
pinGeoPosition.x() + (PinWidget::MINIMUM_WIDTH / 2),
|
||||
pinGeoPosition.y() + PinWidget::MAXIMUM_HEIGHT + pinNameLabelLineLength
|
||||
+ PinWidget::MAXIMUM_LABEL_HEIGHT + pinDirectionLabelLineLength
|
||||
));
|
||||
|
||||
painter.setPen(pinDirectionFontColor);
|
||||
painter.drawText(
|
||||
QRect(
|
||||
pinGeoPosition.x() + (PinWidget::MINIMUM_WIDTH / 2)
|
||||
- (PinWidget::MAXIMUM_LABEL_WIDTH / 2),
|
||||
pinGeoPosition.y() + PinWidget::MAXIMUM_HEIGHT + pinNameLabelLineLength
|
||||
+ PinWidget::MAXIMUM_LABEL_HEIGHT + pinDirectionLabelLineLength,
|
||||
PinWidget::MAXIMUM_LABEL_WIDTH,
|
||||
PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
),
|
||||
Qt::AlignCenter,
|
||||
pinWidget->padState->direction == TargetGpioPadState::DataDirection::INPUT
|
||||
? inDirectionText
|
||||
: outDirectionText
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <vector>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QPaintEvent>
|
||||
#include <QPainter>
|
||||
|
||||
#include "../TargetPackageWidget.hpp"
|
||||
|
||||
#include "PinWidget.hpp"
|
||||
#include "BodyWidget.hpp"
|
||||
|
||||
#include "src/Targets/TargetDescriptor.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Dip
|
||||
{
|
||||
/**
|
||||
* The DualInlinePackageWidget implements a custom Qt widget for the Dual-inline package target variants.
|
||||
*/
|
||||
class DualInlinePackageWidget: public TargetPackageWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DualInlinePackageWidget(
|
||||
const Targets::TargetVariantDescriptor& variantDescriptor,
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor,
|
||||
const Targets::TargetDescriptor& targetDescriptor,
|
||||
const Targets::TargetState& targetState,
|
||||
QWidget* parent
|
||||
);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
void drawWidget(QPainter& painter);
|
||||
|
||||
private:
|
||||
QVBoxLayout* layout = nullptr;
|
||||
QHBoxLayout* topPinLayout = nullptr;
|
||||
QHBoxLayout* bottomPinLayout = nullptr;
|
||||
BodyWidget* bodyWidget = nullptr;
|
||||
|
||||
std::vector<PinWidget*> pinWidgets;
|
||||
};
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#include "PinBodyWidget.hpp"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Dip
|
||||
{
|
||||
using namespace Targets;
|
||||
|
||||
PinBodyWidget::PinBodyWidget(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
QWidget* parent
|
||||
)
|
||||
: TargetPinBodyWidget(
|
||||
pinDescriptor,
|
||||
padDescriptor,
|
||||
parent
|
||||
)
|
||||
{
|
||||
this->setFixedSize(PinBodyWidget::WIDTH, PinBodyWidget::HEIGHT);
|
||||
}
|
||||
|
||||
void PinBodyWidget::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter{this};
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
|
||||
void PinBodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setRenderHints(
|
||||
QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform,
|
||||
true
|
||||
);
|
||||
auto pinWidth = PinBodyWidget::WIDTH;
|
||||
auto pinHeight = PinBodyWidget::HEIGHT;
|
||||
this->setFixedSize(pinWidth, pinHeight);
|
||||
|
||||
auto pinColor = this->getBodyColor();
|
||||
|
||||
painter.setPen(Qt::PenStyle::NoPen);
|
||||
painter.setBrush(pinColor);
|
||||
|
||||
painter.drawRect(
|
||||
0,
|
||||
0,
|
||||
pinWidth,
|
||||
pinHeight
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QEvent>
|
||||
|
||||
#include "../TargetPinBodyWidget.hpp"
|
||||
|
||||
#include "src/Targets/TargetPinDescriptor.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Dip
|
||||
{
|
||||
class PinBodyWidget: public TargetPinBodyWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static const int WIDTH = 19;
|
||||
static const int HEIGHT = 28;
|
||||
|
||||
PinBodyWidget(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
QWidget* parent
|
||||
);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
void drawWidget(QPainter& painter);
|
||||
};
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
#include "PinWidget.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Dip
|
||||
{
|
||||
using namespace Targets;
|
||||
|
||||
PinWidget::PinWidget(
|
||||
const TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor,
|
||||
QWidget* parent
|
||||
)
|
||||
: TargetPinWidget(
|
||||
pinDescriptor,
|
||||
padDescriptor,
|
||||
pinoutDescriptor,
|
||||
parent
|
||||
)
|
||||
{
|
||||
this->setFixedSize(PinWidget::MINIMUM_WIDTH, PinWidget::MAXIMUM_HEIGHT);
|
||||
|
||||
this->layout = new QVBoxLayout{};
|
||||
this->layout->setContentsMargins(0, 0, 0, 0);
|
||||
this->layout->setSpacing(0);
|
||||
|
||||
this->bodyWidget = new PinBodyWidget{this->pinDescriptor, padDescriptor, this};
|
||||
this->position = (pinDescriptor.numericPosition > (pinoutDescriptor.pinDescriptors.size() / 2))
|
||||
? Position::TOP : Position::BOTTOM;
|
||||
|
||||
const bool isTopWidget = this->position == Position::TOP;
|
||||
|
||||
this->layout->setAlignment(isTopWidget ? (Qt::AlignmentFlag::AlignHCenter | Qt::AlignmentFlag::AlignBottom)
|
||||
: (Qt::AlignmentFlag::AlignHCenter | Qt::AlignmentFlag::AlignTop));
|
||||
|
||||
this->pinNameLabelText = QString::fromStdString(
|
||||
this->padDescriptor.has_value() ? padDescriptor->get().name : "NC"
|
||||
);
|
||||
this->pinNameLabelText.truncate(5);
|
||||
|
||||
this->pinNumberLabel = new Label{this};
|
||||
this->pinNumberLabel->setObjectName("target-pin-number");
|
||||
this->pinNumberLabel->setText(QString::number(pinDescriptor.numericPosition));
|
||||
this->pinNumberLabel->setAlignment(Qt::AlignmentFlag::AlignCenter);
|
||||
|
||||
if (isTopWidget) {
|
||||
this->layout->setDirection(QBoxLayout::Direction::BottomToTop);
|
||||
}
|
||||
|
||||
this->layout->addWidget(this->bodyWidget, 0, Qt::AlignmentFlag::AlignHCenter);
|
||||
this->layout->insertSpacing(1, PinWidget::PIN_LABEL_SPACING);
|
||||
this->layout->addWidget(this->pinNumberLabel, 0, Qt::AlignmentFlag::AlignHCenter);
|
||||
this->pinNumberLabel->setFixedHeight(PinWidget::LABEL_HEIGHT);
|
||||
|
||||
this->setLayout(this->layout);
|
||||
|
||||
connect(this->bodyWidget, &PinBodyWidget::clicked, this, &TargetPinWidget::onWidgetBodyClicked);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <cstdint>
|
||||
#include <QVBoxLayout>
|
||||
#include <QPainter>
|
||||
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/Label.hpp"
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/TargetPinWidget.hpp"
|
||||
|
||||
#include "PinBodyWidget.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Dip
|
||||
{
|
||||
enum class Position: std::uint8_t
|
||||
{
|
||||
TOP,
|
||||
BOTTOM
|
||||
};
|
||||
|
||||
class PinWidget: public TargetPinWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static constexpr int MINIMUM_WIDTH = PinBodyWidget::WIDTH;
|
||||
static constexpr int WIDTH_SPACING = 4;
|
||||
static constexpr int PIN_LABEL_SPACING = 2;
|
||||
static constexpr int PIN_NAME_LABEL_LONG_LINE_LENGTH = 25;
|
||||
static constexpr int PIN_NAME_LABEL_SHORT_LINE_LENGTH = 5;
|
||||
static constexpr int PIN_DIRECTION_LABEL_LONG_LINE_LENGTH = 22;
|
||||
static constexpr int PIN_DIRECTION_LABEL_SHORT_LINE_LENGTH = 21;
|
||||
static constexpr int LABEL_HEIGHT = 20;
|
||||
static constexpr int MAXIMUM_LABEL_WIDTH = 42;
|
||||
static constexpr int MAXIMUM_LABEL_HEIGHT = 20;
|
||||
static constexpr int MAXIMUM_HEIGHT = PinBodyWidget::HEIGHT + PinWidget::PIN_LABEL_SPACING
|
||||
+ PinWidget::LABEL_HEIGHT;
|
||||
|
||||
Position position = Position::TOP;
|
||||
QString pinNameLabelText;
|
||||
|
||||
PinWidget(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor,
|
||||
QWidget* parent
|
||||
);
|
||||
|
||||
void updatePadState(const Targets::TargetGpioPadState& padState) override {
|
||||
TargetPinWidget::updatePadState(padState);
|
||||
|
||||
if (this->bodyWidget != nullptr) {
|
||||
this->bodyWidget->setPadState(padState);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QVBoxLayout* layout = nullptr;
|
||||
Label* pinNumberLabel = nullptr;
|
||||
PinBodyWidget* bodyWidget = nullptr;
|
||||
};
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#target-pin-number {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
#target-pin-name {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
#target-pin-name {
|
||||
color: #a6a7aa;
|
||||
}
|
||||
|
||||
#target-pin-direction {
|
||||
color: #8a8a8d;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
#target-pin-body {
|
||||
qproperty-disableAlphaLevel: 100;
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
#include "BodyWidget.hpp"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Qfp
|
||||
{
|
||||
void BodyWidget::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter{this};
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
|
||||
void BodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setRenderHints(
|
||||
QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform,
|
||||
true
|
||||
);
|
||||
|
||||
auto targetBodyColor = this->getBodyColor();
|
||||
auto backgroundColor = QColor{"#373835"};
|
||||
|
||||
if (!this->isEnabled()) {
|
||||
targetBodyColor.setAlpha(this->getDisableAlphaLevel());
|
||||
}
|
||||
|
||||
painter.setPen(Qt::PenStyle::NoPen);
|
||||
painter.setBrush(targetBodyColor);
|
||||
|
||||
const auto containerSize = this->size();
|
||||
const auto targetBodyWidth = containerSize.width() - 8;
|
||||
const auto targetBodyHeight = containerSize.height() - 8;
|
||||
|
||||
auto targetBodyPoint = QPoint(
|
||||
(containerSize.width() / 2) - (targetBodyWidth / 2),
|
||||
(containerSize.height() / 2) - (targetBodyHeight / 2)
|
||||
);
|
||||
|
||||
painter.drawRect(
|
||||
targetBodyPoint.x(),
|
||||
targetBodyPoint.y(),
|
||||
targetBodyWidth,
|
||||
targetBodyHeight
|
||||
);
|
||||
|
||||
painter.setBrush(backgroundColor);
|
||||
painter.drawEllipse(QRectF(
|
||||
targetBodyPoint.x() + 13,
|
||||
targetBodyPoint.y() + 13,
|
||||
18,
|
||||
18
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Qfp
|
||||
{
|
||||
class BodyWidget: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QColor bodyColor READ getBodyColor WRITE setBodyColor DESIGNABLE true)
|
||||
Q_PROPERTY(int disableAlphaLevel READ getDisableAlphaLevel WRITE setDisableAlphaLevel DESIGNABLE true)
|
||||
|
||||
public:
|
||||
explicit BodyWidget(QWidget* parent): QWidget(parent) {
|
||||
this->setObjectName("target-body");
|
||||
}
|
||||
|
||||
[[nodiscard]] QColor getBodyColor() const {
|
||||
return this->bodyColor;
|
||||
}
|
||||
|
||||
void setBodyColor(QColor color) {
|
||||
this->bodyColor = color;
|
||||
}
|
||||
|
||||
[[nodiscard]] int getDisableAlphaLevel() const {
|
||||
return this->disableAlphaLevel;
|
||||
}
|
||||
|
||||
void setDisableAlphaLevel(int level) {
|
||||
this->disableAlphaLevel = level;
|
||||
}
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
void drawWidget(QPainter& painter);
|
||||
|
||||
private:
|
||||
// These properties can be modified via Qt style sheets (see Stylesheets/QuadFlatPackage.qss)
|
||||
QColor bodyColor = {"#8E8B83"};
|
||||
int disableAlphaLevel = 100;
|
||||
};
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
#include "PinBodyWidget.hpp"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QEvent>
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Qfp
|
||||
{
|
||||
using namespace Targets;
|
||||
|
||||
PinBodyWidget::PinBodyWidget(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
bool isVertical,
|
||||
QWidget* parent
|
||||
)
|
||||
: TargetPinBodyWidget(
|
||||
pinDescriptor,
|
||||
padDescriptor,
|
||||
parent
|
||||
)
|
||||
, isVertical(isVertical)
|
||||
{
|
||||
if (isVertical) {
|
||||
this->setFixedSize(PinBodyWidget::WIDTH, PinBodyWidget::HEIGHT);
|
||||
|
||||
} else {
|
||||
this->setFixedSize(PinBodyWidget::HEIGHT, PinBodyWidget::WIDTH);
|
||||
}
|
||||
}
|
||||
|
||||
void PinBodyWidget::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter{this};
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
|
||||
void PinBodyWidget::drawWidget(QPainter& painter) {
|
||||
painter.setRenderHints(
|
||||
QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform,
|
||||
true
|
||||
);
|
||||
auto pinWidth = this->isVertical ? PinBodyWidget::WIDTH : PinBodyWidget::HEIGHT;
|
||||
auto pinHeight = this->isVertical ? PinBodyWidget::HEIGHT : PinBodyWidget::WIDTH;
|
||||
this->setFixedSize(pinWidth, pinHeight);
|
||||
|
||||
auto pinColor = this->getBodyColor();
|
||||
|
||||
painter.setPen(Qt::PenStyle::NoPen);
|
||||
painter.setBrush(pinColor);
|
||||
|
||||
painter.drawRect(
|
||||
0,
|
||||
0,
|
||||
pinWidth,
|
||||
pinHeight
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QMouseEvent>
|
||||
#include <utility>
|
||||
|
||||
#include "../TargetPinBodyWidget.hpp"
|
||||
|
||||
#include "src/Targets/TargetPinDescriptor.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Qfp
|
||||
{
|
||||
class PinBodyWidget: public TargetPinBodyWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static const int WIDTH = 17;
|
||||
static const int HEIGHT = 26;
|
||||
|
||||
PinBodyWidget(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
bool isVertical,
|
||||
QWidget* parent
|
||||
);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
void drawWidget(QPainter& painter);
|
||||
|
||||
private:
|
||||
bool isVertical = false;
|
||||
};
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
#include <QWidget>
|
||||
#include <QPainter>
|
||||
#include <QLayout>
|
||||
#include <cmath>
|
||||
#include <QEvent>
|
||||
|
||||
#include "PinWidget.hpp"
|
||||
#include "PinBodyWidget.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Qfp
|
||||
{
|
||||
using namespace Targets;
|
||||
|
||||
PinWidget::PinWidget(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor,
|
||||
QWidget* parent
|
||||
)
|
||||
: TargetPinWidget(
|
||||
pinDescriptor,
|
||||
padDescriptor,
|
||||
pinoutDescriptor,
|
||||
parent
|
||||
)
|
||||
{
|
||||
this->layout = new QBoxLayout{QBoxLayout::TopToBottom};
|
||||
this->layout->setContentsMargins(0, 0, 0, 0);
|
||||
this->layout->setSpacing(0);
|
||||
const auto pinNumber = pinDescriptor.numericPosition;
|
||||
|
||||
auto pinCountPerLayout = (pinoutDescriptor.pinDescriptors.size() / 4);
|
||||
|
||||
if (pinNumber <= pinCountPerLayout) {
|
||||
this->position = Position::LEFT;
|
||||
|
||||
} else if (pinNumber > pinCountPerLayout && pinNumber <= (pinCountPerLayout * 2)) {
|
||||
this->position = Position::BOTTOM;
|
||||
|
||||
} else if (pinNumber > (pinCountPerLayout * 2) && pinNumber <= (pinCountPerLayout * 3)) {
|
||||
this->position = Position::RIGHT;
|
||||
|
||||
} else if (pinNumber > (pinCountPerLayout * 3) && pinNumber <= (pinCountPerLayout * 4)) {
|
||||
this->position = Position::TOP;
|
||||
}
|
||||
|
||||
this->bodyWidget = new PinBodyWidget{
|
||||
this->pinDescriptor,
|
||||
padDescriptor,
|
||||
(this->position == Position::TOP || this->position == Position::BOTTOM),
|
||||
this
|
||||
};
|
||||
|
||||
this->pinNameLabelText = QString::fromStdString(
|
||||
this->padDescriptor.has_value() ? padDescriptor->get().name : "NC"
|
||||
);
|
||||
this->pinNameLabelText.truncate(5);
|
||||
|
||||
this->pinNumberLabel = new Label{this};
|
||||
this->pinNumberLabel->setObjectName("target-pin-number");
|
||||
auto pinNumberText = QString::number(pinNumber);
|
||||
pinNumberText.truncate(5);
|
||||
this->pinNumberLabel->setText(QString::number(pinNumber));
|
||||
this->pinNumberLabel->setAlignment(Qt::AlignmentFlag::AlignCenter);
|
||||
|
||||
if (this->position == Position::LEFT) {
|
||||
this->layout->setAlignment((Qt::AlignmentFlag::AlignVCenter | Qt::AlignmentFlag::AlignRight));
|
||||
this->layout->setDirection(QBoxLayout::Direction::RightToLeft);
|
||||
this->setFixedSize(PinWidget::MAXIMUM_HORIZONTAL_WIDTH, PinWidget::MAXIMUM_HORIZONTAL_HEIGHT);
|
||||
|
||||
} else if (this->position == Position::BOTTOM) {
|
||||
this->layout->setAlignment(Qt::AlignmentFlag::AlignHCenter | Qt::AlignmentFlag::AlignTop);
|
||||
this->layout->setDirection(QBoxLayout::Direction::TopToBottom);
|
||||
this->setFixedSize(PinWidget::MAXIMUM_VERTICAL_WIDTH, PinWidget::MAXIMUM_VERTICAL_HEIGHT);
|
||||
|
||||
} else if (this->position == Position::RIGHT) {
|
||||
this->layout->setAlignment((Qt::AlignmentFlag::AlignVCenter | Qt::AlignmentFlag::AlignLeft));
|
||||
this->layout->setDirection(QBoxLayout::Direction::LeftToRight);
|
||||
this->setFixedSize(PinWidget::MAXIMUM_HORIZONTAL_WIDTH, PinWidget::MAXIMUM_HORIZONTAL_HEIGHT);
|
||||
|
||||
} else if (this->position == Position::TOP) {
|
||||
this->layout->setAlignment((Qt::AlignmentFlag::AlignHCenter | Qt::AlignmentFlag::AlignBottom));
|
||||
this->layout->setDirection(QBoxLayout::Direction::BottomToTop);
|
||||
this->setFixedSize(PinWidget::MAXIMUM_VERTICAL_WIDTH, PinWidget::MAXIMUM_VERTICAL_HEIGHT);
|
||||
}
|
||||
|
||||
this->layout->addWidget(this->bodyWidget);
|
||||
this->layout->addSpacing(3);
|
||||
this->layout->addWidget(this->pinNumberLabel);
|
||||
|
||||
if (this->position == Position::LEFT || this->position == Position::RIGHT) {
|
||||
this->pinNumberLabel->setFixedSize(
|
||||
PinWidget::MAXIMUM_PIN_NUMBER_LABEL_WIDTH,
|
||||
PinWidget::MAXIMUM_HORIZONTAL_HEIGHT
|
||||
);
|
||||
|
||||
} else if (this->position == Position::TOP || this->position == Position::BOTTOM) {
|
||||
this->pinNumberLabel->setFixedSize(PinBodyWidget::WIDTH, PinWidget::LABEL_HEIGHT - 2);
|
||||
}
|
||||
|
||||
this->layout->addStretch(1);
|
||||
this->setLayout(this->layout);
|
||||
|
||||
connect(this->bodyWidget, &PinBodyWidget::clicked, this, &TargetPinWidget::onWidgetBodyClicked);
|
||||
}
|
||||
|
||||
void PinWidget::updatePadState(const Targets::TargetGpioPadState& padState) {
|
||||
TargetPinWidget::updatePadState(padState);
|
||||
|
||||
if (this->bodyWidget != nullptr) {
|
||||
this->bodyWidget->setPadState(padState);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <cstdint>
|
||||
#include <QBoxLayout>
|
||||
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/Label.hpp"
|
||||
#include "src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/TargetPinWidget.hpp"
|
||||
|
||||
#include "PinBodyWidget.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Qfp
|
||||
{
|
||||
enum class Position: std::uint8_t
|
||||
{
|
||||
TOP,
|
||||
BOTTOM,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
};
|
||||
|
||||
class PinWidget: public TargetPinWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static constexpr int PIN_WIDGET_LAYOUT_PADDING = 46;
|
||||
static constexpr int WIDTH_SPACING = 4;
|
||||
static constexpr int PIN_NAME_LABEL_LONG_LINE_LENGTH = 25;
|
||||
static constexpr int PIN_NAME_LABEL_SHORT_LINE_LENGTH = 5;
|
||||
static constexpr int PIN_DIRECTION_LABEL_LONG_LINE_LENGTH = 22;
|
||||
static constexpr int PIN_DIRECTION_LABEL_SHORT_LINE_LENGTH = 21;
|
||||
static constexpr int PIN_LABEL_SPACING = 2;
|
||||
static constexpr int LABEL_HEIGHT = 20;
|
||||
static constexpr int MAXIMUM_PIN_NUMBER_LABEL_WIDTH = 26;
|
||||
static constexpr int MAXIMUM_PIN_DIRECTION_LABEL_WIDTH = 24;
|
||||
static constexpr int MAXIMUM_LABEL_WIDTH = 42;
|
||||
static constexpr int MAXIMUM_LABEL_HEIGHT = 20;
|
||||
static constexpr int MAXIMUM_HORIZONTAL_WIDTH = PinBodyWidget::HEIGHT + PinWidget::MAXIMUM_PIN_NUMBER_LABEL_WIDTH + 3;
|
||||
static constexpr int MAXIMUM_HORIZONTAL_HEIGHT = PinBodyWidget::WIDTH;
|
||||
static constexpr int MAXIMUM_VERTICAL_HEIGHT = PinBodyWidget::HEIGHT + PinWidget::LABEL_HEIGHT + 3;
|
||||
static constexpr int MAXIMUM_VERTICAL_WIDTH = PinBodyWidget::WIDTH;
|
||||
|
||||
Position position;
|
||||
QString pinNameLabelText;
|
||||
|
||||
PinWidget(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor,
|
||||
QWidget* parent
|
||||
);
|
||||
|
||||
void updatePadState(const Targets::TargetGpioPadState& padState) override;
|
||||
|
||||
private:
|
||||
QBoxLayout* layout = nullptr;
|
||||
Label* pinNumberLabel = nullptr;
|
||||
Label* pinNameLabel = nullptr;
|
||||
Label* pinDirectionLabel = nullptr;
|
||||
PinBodyWidget* bodyWidget = nullptr;
|
||||
};
|
||||
}
|
||||
@@ -1,448 +0,0 @@
|
||||
#include "QuadFlatPackageWidget.hpp"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <vector>
|
||||
#include <QFile>
|
||||
#include <QLine>
|
||||
|
||||
#include "src/Services/PathService.hpp"
|
||||
#include "PinWidget.hpp"
|
||||
#include "BodyWidget.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Qfp
|
||||
{
|
||||
using namespace Targets;
|
||||
|
||||
QuadFlatPackageWidget::QuadFlatPackageWidget(
|
||||
const Targets::TargetVariantDescriptor& variantDescriptor,
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor,
|
||||
const Targets::TargetDescriptor& targetDescriptor,
|
||||
const Targets::TargetState& targetState,
|
||||
QWidget* parent
|
||||
)
|
||||
: TargetPackageWidget(
|
||||
variantDescriptor,
|
||||
pinoutDescriptor,
|
||||
targetState,
|
||||
parent
|
||||
)
|
||||
{
|
||||
assert((this->pinoutDescriptor.pinDescriptors.size() % 4) == 0);
|
||||
|
||||
auto stylesheetFile = QFile{QString::fromStdString(
|
||||
Services::PathService::compiledResourcesPath()
|
||||
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/QFP/Stylesheets/QuadFlatPackage.qss"
|
||||
)
|
||||
};
|
||||
stylesheetFile.open(QFile::ReadOnly);
|
||||
this->setStyleSheet(stylesheetFile.readAll());
|
||||
|
||||
this->pinWidgets.reserve(this->pinoutDescriptor.pinDescriptors.size());
|
||||
this->layout = new QVBoxLayout{};
|
||||
this->layout->setSpacing(0);
|
||||
this->layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
this->horizontalLayout = new QHBoxLayout{};
|
||||
this->horizontalLayout->setSpacing(0);
|
||||
this->horizontalLayout->setDirection(QBoxLayout::Direction::LeftToRight);
|
||||
this->horizontalLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter);
|
||||
|
||||
this->topPinLayout = new QHBoxLayout{};
|
||||
this->topPinLayout->setSpacing(PinWidget::WIDTH_SPACING);
|
||||
this->topPinLayout->setDirection(QBoxLayout::Direction::RightToLeft);
|
||||
this->topPinLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter);
|
||||
|
||||
this->rightPinLayout = new QVBoxLayout();
|
||||
this->rightPinLayout->setSpacing(PinWidget::WIDTH_SPACING);
|
||||
this->rightPinLayout->setDirection(QBoxLayout::Direction::BottomToTop);
|
||||
this->rightPinLayout->setAlignment(Qt::AlignmentFlag::AlignVCenter);
|
||||
|
||||
this->bottomPinLayout = new QHBoxLayout{};
|
||||
this->bottomPinLayout->setSpacing(PinWidget::WIDTH_SPACING);
|
||||
this->bottomPinLayout->setDirection(QBoxLayout::Direction::LeftToRight);
|
||||
this->bottomPinLayout->setAlignment(Qt::AlignmentFlag::AlignHCenter);
|
||||
|
||||
this->leftPinLayout = new QVBoxLayout{};
|
||||
this->leftPinLayout->setSpacing(PinWidget::WIDTH_SPACING);
|
||||
this->leftPinLayout->setDirection(QBoxLayout::Direction::TopToBottom);
|
||||
this->leftPinLayout->setAlignment(Qt::AlignmentFlag::AlignVCenter);
|
||||
|
||||
const auto pinCountPerLayout = static_cast<int>(this->pinoutDescriptor.pinDescriptors.size() / 4);
|
||||
for (const auto& pinDescriptor: this->pinoutDescriptor.pinDescriptors) {
|
||||
auto* pinWidget = new PinWidget{
|
||||
pinDescriptor,
|
||||
pinDescriptor.padKey.has_value()
|
||||
? targetDescriptor.tryGetPadDescriptor(*(pinDescriptor.padKey))
|
||||
: std::nullopt,
|
||||
this->pinoutDescriptor,
|
||||
this
|
||||
};
|
||||
this->pinWidgets.push_back(pinWidget);
|
||||
TargetPackageWidget::pinWidgetsByPosition.emplace(pinDescriptor.numericPosition, pinWidget);
|
||||
|
||||
if (pinWidget->padDescriptor.has_value()) {
|
||||
const auto& padDescriptor = pinWidget->padDescriptor->get();
|
||||
TargetPackageWidget::pinWidgetsByPadId.emplace(padDescriptor.id, pinWidget);
|
||||
TargetPackageWidget::padDescriptors.push_back(&padDescriptor);
|
||||
}
|
||||
|
||||
if (pinWidget->position == Position::LEFT) {
|
||||
this->leftPinLayout->addWidget(pinWidget, 0, Qt::AlignmentFlag::AlignRight);
|
||||
|
||||
} else if (pinWidget->position == Position::BOTTOM) {
|
||||
this->bottomPinLayout->addWidget(pinWidget, 0, Qt::AlignmentFlag::AlignTop);
|
||||
|
||||
} else if (pinWidget->position == Position::RIGHT) {
|
||||
this->rightPinLayout->addWidget(pinWidget, 0, Qt::AlignmentFlag::AlignLeft);
|
||||
|
||||
} else if (pinWidget->position == Position::TOP) {
|
||||
this->topPinLayout->addWidget(pinWidget, 0, Qt::AlignmentFlag::AlignBottom);
|
||||
}
|
||||
}
|
||||
|
||||
this->bodyWidget = new BodyWidget{this};
|
||||
this->layout->addLayout(this->topPinLayout);
|
||||
this->horizontalLayout->addLayout(this->leftPinLayout);
|
||||
this->horizontalLayout->addWidget(this->bodyWidget);
|
||||
this->horizontalLayout->addLayout(this->rightPinLayout);
|
||||
this->layout->addLayout(this->horizontalLayout);
|
||||
this->layout->addLayout(this->bottomPinLayout);
|
||||
this->setLayout(this->layout);
|
||||
|
||||
// Layout sizing, positioning and padding
|
||||
const auto verticalPinWidgetHeight = PinWidget::MAXIMUM_VERTICAL_HEIGHT;
|
||||
const auto verticalPinWidgetWidth = PinWidget::MAXIMUM_VERTICAL_WIDTH;
|
||||
const auto horizontalPinWidgetHeight = PinWidget::MAXIMUM_HORIZONTAL_HEIGHT;
|
||||
const auto horizontalPinWidgetWidth = PinWidget::MAXIMUM_HORIZONTAL_WIDTH;
|
||||
|
||||
/*
|
||||
* Horizontal layouts are the right and left pin layouts - the ones that hold horizontal pin widgets.
|
||||
* The bottom and top layouts are vertical layouts, as they hold the vertical pin widgets.
|
||||
*/
|
||||
const auto horizontalLayoutHeight = ((horizontalPinWidgetHeight + PinWidget::WIDTH_SPACING) * pinCountPerLayout
|
||||
+ PinWidget::PIN_WIDGET_LAYOUT_PADDING - PinWidget::WIDTH_SPACING);
|
||||
|
||||
const auto verticalLayoutWidth = ((verticalPinWidgetWidth + PinWidget::WIDTH_SPACING) * pinCountPerLayout
|
||||
+ PinWidget::PIN_WIDGET_LAYOUT_PADDING - PinWidget::WIDTH_SPACING);
|
||||
|
||||
const auto height = horizontalLayoutHeight + (verticalPinWidgetHeight * 2) + (
|
||||
(
|
||||
PinWidget::PIN_NAME_LABEL_LONG_LINE_LENGTH
|
||||
+ PinWidget::PIN_DIRECTION_LABEL_LONG_LINE_LENGTH
|
||||
+ (PinWidget::MAXIMUM_LABEL_HEIGHT * 2)
|
||||
+ (PinWidget::PIN_LABEL_SPACING * 3)
|
||||
) * 2
|
||||
);
|
||||
const auto width = verticalLayoutWidth + (horizontalPinWidgetWidth * 2) + (
|
||||
(
|
||||
PinWidget::PIN_NAME_LABEL_LONG_LINE_LENGTH
|
||||
+ PinWidget::MAXIMUM_LABEL_WIDTH
|
||||
+ PinWidget::MAXIMUM_PIN_DIRECTION_LABEL_WIDTH
|
||||
+ (PinWidget::PIN_LABEL_SPACING * 2)
|
||||
) * 2
|
||||
);
|
||||
|
||||
this->topPinLayout->insertSpacing(0, horizontalPinWidgetWidth);
|
||||
this->topPinLayout->addSpacing(horizontalPinWidgetWidth);
|
||||
|
||||
this->bottomPinLayout->insertSpacing(0, horizontalPinWidgetWidth);
|
||||
this->bottomPinLayout->addSpacing(horizontalPinWidgetWidth);
|
||||
|
||||
this->leftPinLayout->setGeometry(QRect(
|
||||
0,
|
||||
verticalPinWidgetHeight,
|
||||
horizontalPinWidgetWidth,
|
||||
horizontalLayoutHeight
|
||||
));
|
||||
|
||||
this->bodyWidget->setFixedSize(verticalLayoutWidth, horizontalLayoutHeight);
|
||||
|
||||
this->rightPinLayout->setGeometry(QRect(
|
||||
horizontalLayoutHeight + horizontalPinWidgetWidth,
|
||||
verticalPinWidgetHeight,
|
||||
horizontalPinWidgetWidth,
|
||||
horizontalLayoutHeight
|
||||
));
|
||||
|
||||
const auto pinWidgetLayoutMargin = PinWidget::PIN_WIDGET_LAYOUT_PADDING / 2;
|
||||
|
||||
this->topPinLayout->setContentsMargins(
|
||||
pinWidgetLayoutMargin,
|
||||
0,
|
||||
pinWidgetLayoutMargin,
|
||||
0
|
||||
);
|
||||
|
||||
this->bottomPinLayout->setContentsMargins(
|
||||
pinWidgetLayoutMargin,
|
||||
0,
|
||||
pinWidgetLayoutMargin,
|
||||
0
|
||||
);
|
||||
|
||||
this->leftPinLayout->setContentsMargins(
|
||||
0,
|
||||
pinWidgetLayoutMargin,
|
||||
0,
|
||||
pinWidgetLayoutMargin
|
||||
);
|
||||
|
||||
this->rightPinLayout->setContentsMargins(
|
||||
0,
|
||||
pinWidgetLayoutMargin,
|
||||
0,
|
||||
pinWidgetLayoutMargin
|
||||
);
|
||||
|
||||
this->setFixedSize(width, height);
|
||||
|
||||
// Set the fixed size and center the widget
|
||||
this->setGeometry(
|
||||
(parent->width() / 2) - (width / 2),
|
||||
(parent->height() / 2) - (height / 2),
|
||||
width,
|
||||
height
|
||||
);
|
||||
}
|
||||
|
||||
void QuadFlatPackageWidget::paintEvent(QPaintEvent* event) {
|
||||
auto painter = QPainter{this};
|
||||
this->drawWidget(painter);
|
||||
}
|
||||
|
||||
void QuadFlatPackageWidget::drawWidget(QPainter& painter) {
|
||||
static auto pinNameFont = QFont{"'Ubuntu', sans-serif"};
|
||||
static auto pinDirectionFont = pinNameFont;
|
||||
pinNameFont.setPixelSize(11);
|
||||
pinDirectionFont.setPixelSize(10);
|
||||
|
||||
static const auto lineColor = QColor{0x4F, 0x4F, 0x4F};
|
||||
static const auto pinNameFontColor = QColor{0xA6, 0xA7, 0xAA};
|
||||
static const auto pinDirectionFontColor = QColor{0x8A, 0x8A, 0x8D};
|
||||
static const auto pinChangedFontColor = QColor{0x4D, 0x7B, 0xBA};
|
||||
|
||||
static const auto inDirectionText = QString{"IN"};
|
||||
static const auto outDirectionText = QString{"OUT"};
|
||||
|
||||
for (const auto* pinWidget : this->pinWidgets) {
|
||||
const auto pinGeoPosition = pinWidget->pos();
|
||||
const auto& padState = pinWidget->getPadState();
|
||||
const auto padStateChanged = pinWidget->hasPadStateChanged();
|
||||
|
||||
painter.setFont(pinNameFont);
|
||||
|
||||
if (pinWidget->position == Position::LEFT) {
|
||||
painter.setPen(lineColor);
|
||||
painter.drawLine(QLine{
|
||||
pinGeoPosition.x() - PinWidget::PIN_NAME_LABEL_LONG_LINE_LENGTH,
|
||||
pinGeoPosition.y() + (PinWidget::MAXIMUM_HORIZONTAL_HEIGHT / 2),
|
||||
pinGeoPosition.x(),
|
||||
pinGeoPosition.y() + (PinWidget::MAXIMUM_HORIZONTAL_HEIGHT / 2)
|
||||
});
|
||||
|
||||
painter.setPen(padStateChanged ? pinChangedFontColor : pinNameFontColor);
|
||||
painter.drawText(
|
||||
QRect(
|
||||
pinGeoPosition.x() - PinWidget::PIN_NAME_LABEL_LONG_LINE_LENGTH
|
||||
- PinWidget::MAXIMUM_LABEL_WIDTH - (PinWidget::PIN_LABEL_SPACING * 2),
|
||||
pinGeoPosition.y() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2)
|
||||
- (PinWidget::MAXIMUM_LABEL_HEIGHT / 2),
|
||||
PinWidget::MAXIMUM_LABEL_WIDTH,
|
||||
PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
),
|
||||
Qt::AlignCenter,
|
||||
pinWidget->pinNameLabelText
|
||||
);
|
||||
|
||||
if (padState.has_value()) {
|
||||
painter.setFont(pinDirectionFont);
|
||||
|
||||
painter.setPen(pinDirectionFontColor);
|
||||
painter.drawText(
|
||||
QRect(
|
||||
pinGeoPosition.x() - PinWidget::PIN_NAME_LABEL_LONG_LINE_LENGTH
|
||||
- PinWidget::MAXIMUM_LABEL_WIDTH - (PinWidget::PIN_LABEL_SPACING * 3)
|
||||
- PinWidget::MAXIMUM_PIN_DIRECTION_LABEL_WIDTH,
|
||||
pinGeoPosition.y() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2)
|
||||
- (PinWidget::MAXIMUM_LABEL_HEIGHT / 2),
|
||||
PinWidget::MAXIMUM_PIN_DIRECTION_LABEL_WIDTH,
|
||||
PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
),
|
||||
Qt::AlignCenter,
|
||||
padState->direction == TargetGpioPadState::DataDirection::INPUT
|
||||
? inDirectionText
|
||||
: outDirectionText
|
||||
);
|
||||
}
|
||||
|
||||
} else if (pinWidget->position == Position::RIGHT) {
|
||||
painter.setPen(lineColor);
|
||||
painter.drawLine(QLine{
|
||||
pinGeoPosition.x() + PinWidget::MAXIMUM_HORIZONTAL_WIDTH,
|
||||
pinGeoPosition.y() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2),
|
||||
pinGeoPosition.x() + PinWidget::MAXIMUM_HORIZONTAL_WIDTH
|
||||
+ PinWidget::PIN_NAME_LABEL_LONG_LINE_LENGTH,
|
||||
pinGeoPosition.y() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2)
|
||||
});
|
||||
|
||||
painter.setPen(padStateChanged ? pinChangedFontColor : pinNameFontColor);
|
||||
painter.drawText(
|
||||
QRect(
|
||||
pinGeoPosition.x() + PinWidget::MAXIMUM_HORIZONTAL_WIDTH
|
||||
+ PinWidget::PIN_NAME_LABEL_LONG_LINE_LENGTH + 8,
|
||||
pinGeoPosition.y() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2)
|
||||
- (PinWidget::MAXIMUM_LABEL_HEIGHT / 2),
|
||||
PinWidget::MAXIMUM_LABEL_WIDTH,
|
||||
PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
),
|
||||
Qt::AlignCenter,
|
||||
pinWidget->pinNameLabelText
|
||||
);
|
||||
|
||||
if (padState.has_value()) {
|
||||
painter.setFont(pinDirectionFont);
|
||||
|
||||
painter.setPen(pinDirectionFontColor);
|
||||
painter.drawText(
|
||||
QRect(
|
||||
pinGeoPosition.x() + PinWidget::MAXIMUM_HORIZONTAL_WIDTH
|
||||
+ PinWidget::PIN_NAME_LABEL_LONG_LINE_LENGTH + PinWidget::MAXIMUM_LABEL_WIDTH
|
||||
+ (PinWidget::PIN_LABEL_SPACING * 3),
|
||||
pinGeoPosition.y() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2)
|
||||
- (PinWidget::MAXIMUM_LABEL_HEIGHT / 2),
|
||||
PinWidget::MAXIMUM_PIN_DIRECTION_LABEL_WIDTH,
|
||||
PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
),
|
||||
Qt::AlignCenter,
|
||||
padState->direction == TargetGpioPadState::DataDirection::INPUT
|
||||
? inDirectionText
|
||||
: outDirectionText
|
||||
);
|
||||
}
|
||||
|
||||
} else if (pinWidget->position == Position::TOP) {
|
||||
painter.setPen(lineColor);
|
||||
const auto pinNameLabelLineLength = (pinWidget->getPinNumber() % 2 == 0
|
||||
? PinWidget::PIN_NAME_LABEL_LONG_LINE_LENGTH
|
||||
: PinWidget::PIN_NAME_LABEL_SHORT_LINE_LENGTH
|
||||
);
|
||||
const auto pinDirectionLabelLineLength = (pinWidget->getPinNumber() % 2 == 0
|
||||
? PinWidget::PIN_DIRECTION_LABEL_SHORT_LINE_LENGTH
|
||||
: PinWidget::PIN_DIRECTION_LABEL_LONG_LINE_LENGTH
|
||||
);
|
||||
|
||||
painter.drawLine(QLine{
|
||||
pinGeoPosition.x() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2),
|
||||
pinGeoPosition.y() - pinNameLabelLineLength,
|
||||
pinGeoPosition.x() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2),
|
||||
pinGeoPosition.y()
|
||||
});
|
||||
|
||||
painter.setPen(padStateChanged ? pinChangedFontColor : pinNameFontColor);
|
||||
painter.drawText(
|
||||
QRect(
|
||||
pinGeoPosition.x() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2)
|
||||
- (PinWidget::MAXIMUM_LABEL_WIDTH / 2),
|
||||
pinGeoPosition.y() - pinNameLabelLineLength - PinWidget::MAXIMUM_LABEL_HEIGHT,
|
||||
PinWidget::MAXIMUM_LABEL_WIDTH,
|
||||
PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
),
|
||||
Qt::AlignCenter,
|
||||
pinWidget->pinNameLabelText
|
||||
);
|
||||
|
||||
if (padState.has_value()) {
|
||||
painter.setFont(pinDirectionFont);
|
||||
|
||||
painter.setPen(lineColor);
|
||||
painter.drawLine(QLine{
|
||||
pinGeoPosition.x() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2),
|
||||
pinGeoPosition.y() - pinNameLabelLineLength - PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
- pinDirectionLabelLineLength,
|
||||
pinGeoPosition.x() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2),
|
||||
pinGeoPosition.y() - pinNameLabelLineLength - PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
});
|
||||
|
||||
painter.setPen(pinDirectionFontColor);
|
||||
painter.drawText(
|
||||
QRect(
|
||||
pinGeoPosition.x() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2)
|
||||
- (PinWidget::MAXIMUM_LABEL_WIDTH / 2),
|
||||
pinGeoPosition.y() - pinNameLabelLineLength - pinDirectionLabelLineLength
|
||||
- (PinWidget::MAXIMUM_LABEL_HEIGHT * 2),
|
||||
PinWidget::MAXIMUM_LABEL_WIDTH,
|
||||
PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
),
|
||||
Qt::AlignCenter,
|
||||
padState->direction == TargetGpioPadState::DataDirection::INPUT
|
||||
? inDirectionText
|
||||
: outDirectionText
|
||||
);
|
||||
}
|
||||
|
||||
} else if (pinWidget->position == Position::BOTTOM) {
|
||||
painter.setPen(lineColor);
|
||||
const auto pinNameLabelLineLength = (pinWidget->getPinNumber() % 2 == 0
|
||||
? PinWidget::PIN_NAME_LABEL_LONG_LINE_LENGTH
|
||||
: PinWidget::PIN_NAME_LABEL_SHORT_LINE_LENGTH
|
||||
);
|
||||
const auto pinDirectionLabelLineLength = (pinWidget->getPinNumber() % 2 == 0
|
||||
? PinWidget::PIN_DIRECTION_LABEL_SHORT_LINE_LENGTH
|
||||
: PinWidget::PIN_DIRECTION_LABEL_LONG_LINE_LENGTH
|
||||
);
|
||||
|
||||
painter.drawLine(QLine{
|
||||
pinGeoPosition.x() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2),
|
||||
pinGeoPosition.y() + PinWidget::MAXIMUM_VERTICAL_HEIGHT,
|
||||
pinGeoPosition.x() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2),
|
||||
pinGeoPosition.y() + PinWidget::MAXIMUM_VERTICAL_HEIGHT + pinNameLabelLineLength
|
||||
});
|
||||
|
||||
painter.setPen(padStateChanged ? pinChangedFontColor : pinNameFontColor);
|
||||
painter.drawText(
|
||||
QRect(
|
||||
pinGeoPosition.x() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2)
|
||||
- (PinWidget::MAXIMUM_LABEL_WIDTH / 2),
|
||||
pinGeoPosition.y() + + PinWidget::MAXIMUM_VERTICAL_HEIGHT + pinNameLabelLineLength,
|
||||
PinWidget::MAXIMUM_LABEL_WIDTH,
|
||||
PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
),
|
||||
Qt::AlignCenter,
|
||||
pinWidget->pinNameLabelText
|
||||
);
|
||||
|
||||
if (padState.has_value()) {
|
||||
painter.setFont(pinDirectionFont);
|
||||
|
||||
painter.setPen(lineColor);
|
||||
painter.drawLine(QLine{
|
||||
pinGeoPosition.x() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2),
|
||||
pinGeoPosition.y() + PinWidget::MAXIMUM_VERTICAL_HEIGHT + pinNameLabelLineLength
|
||||
+ PinWidget::MAXIMUM_LABEL_HEIGHT,
|
||||
pinGeoPosition.x() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2),
|
||||
pinGeoPosition.y() + PinWidget::MAXIMUM_VERTICAL_HEIGHT + pinNameLabelLineLength
|
||||
+ PinWidget::MAXIMUM_LABEL_HEIGHT + pinDirectionLabelLineLength
|
||||
});
|
||||
|
||||
painter.setPen(pinDirectionFontColor);
|
||||
painter.drawText(
|
||||
QRect(
|
||||
pinGeoPosition.x() + (PinWidget::MAXIMUM_VERTICAL_WIDTH / 2)
|
||||
- (PinWidget::MAXIMUM_LABEL_WIDTH / 2),
|
||||
pinGeoPosition.y() + PinWidget::MAXIMUM_VERTICAL_HEIGHT + pinNameLabelLineLength
|
||||
+ PinWidget::MAXIMUM_LABEL_HEIGHT + pinDirectionLabelLineLength,
|
||||
PinWidget::MAXIMUM_LABEL_WIDTH,
|
||||
PinWidget::MAXIMUM_LABEL_HEIGHT
|
||||
),
|
||||
Qt::AlignCenter,
|
||||
padState->direction == TargetGpioPadState::DataDirection::INPUT
|
||||
? inDirectionText
|
||||
: outDirectionText
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <vector>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "../TargetPackageWidget.hpp"
|
||||
#include "PinWidget.hpp"
|
||||
#include "BodyWidget.hpp"
|
||||
|
||||
#include "src/Targets/TargetDescriptor.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets::Qfp
|
||||
{
|
||||
/**
|
||||
* QuadFlatPackageWidget implements a custom Qt widget for Quad-flat package variants.
|
||||
*/
|
||||
class QuadFlatPackageWidget: public TargetPackageWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QuadFlatPackageWidget(
|
||||
const Targets::TargetVariantDescriptor& variantDescriptor,
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor,
|
||||
const Targets::TargetDescriptor& targetDescriptor,
|
||||
const Targets::TargetState& targetState,
|
||||
QWidget* parent
|
||||
);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
void drawWidget(QPainter& painter);
|
||||
|
||||
private:
|
||||
QVBoxLayout* layout = nullptr;
|
||||
QHBoxLayout* horizontalLayout = nullptr;
|
||||
QHBoxLayout* topPinLayout = nullptr;
|
||||
QVBoxLayout* rightPinLayout = nullptr;
|
||||
QHBoxLayout* bottomPinLayout = nullptr;
|
||||
QVBoxLayout* leftPinLayout = nullptr;
|
||||
BodyWidget* bodyWidget = nullptr;
|
||||
|
||||
std::vector<PinWidget*> pinWidgets;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#target-pin-number {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
#target-pin-body {
|
||||
qproperty-disableAlphaLevel: 100;
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
#include "TargetPackageWidget.hpp"
|
||||
|
||||
#include <QEvent>
|
||||
|
||||
#include "src/Insight/InsightSignals.hpp"
|
||||
#include "src/Insight/InsightWorker/InsightWorker.hpp"
|
||||
#include "src/Insight/InsightWorker/Tasks/ReadTargetGpioPadStates.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets
|
||||
{
|
||||
using Targets::TargetState;
|
||||
using Targets::TargetExecutionState;
|
||||
|
||||
TargetPackageWidget::TargetPackageWidget(
|
||||
const Targets::TargetVariantDescriptor& variantDescriptor,
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor,
|
||||
const Targets::TargetState& targetState,
|
||||
QWidget* parent
|
||||
)
|
||||
: QWidget(parent)
|
||||
, variantDescriptor(variantDescriptor)
|
||||
, pinoutDescriptor(pinoutDescriptor)
|
||||
, targetState(targetState)
|
||||
{
|
||||
auto* insightSignals = InsightSignals::instance();
|
||||
|
||||
QObject::connect(
|
||||
insightSignals,
|
||||
&InsightSignals::programmingModeEnabled,
|
||||
this,
|
||||
&TargetPackageWidget::onProgrammingModeEnabled
|
||||
);
|
||||
|
||||
QObject::connect(
|
||||
insightSignals,
|
||||
&InsightSignals::programmingModeDisabled,
|
||||
this,
|
||||
&TargetPackageWidget::onProgrammingModeDisabled
|
||||
);
|
||||
|
||||
this->setDisabled(true);
|
||||
}
|
||||
|
||||
void TargetPackageWidget::refreshPadStates(std::optional<std::function<void(void)>> callback) {
|
||||
const auto refreshTask = QSharedPointer<ReadTargetGpioPadStates>{
|
||||
new ReadTargetGpioPadStates{this->padDescriptors},
|
||||
&QObject::deleteLater
|
||||
};
|
||||
|
||||
QObject::connect(
|
||||
refreshTask.get(),
|
||||
&ReadTargetGpioPadStates::targetGpioPadStatesRead,
|
||||
this,
|
||||
&TargetPackageWidget::updatePadStates
|
||||
);
|
||||
|
||||
if (callback.has_value()) {
|
||||
QObject::connect(
|
||||
refreshTask.get(),
|
||||
&InsightWorkerTask::completed,
|
||||
this,
|
||||
callback.value()
|
||||
);
|
||||
}
|
||||
|
||||
InsightWorker::queueTask(refreshTask);
|
||||
}
|
||||
|
||||
void TargetPackageWidget::updatePadStates(const Targets::TargetGpioPadDescriptorAndStatePairs& padStatePairs) {
|
||||
for (const auto& [padDescriptor, padState] : padStatePairs) {
|
||||
const auto widgetIt = this->pinWidgetsByPadId.find(padDescriptor.id);
|
||||
if (widgetIt == this->pinWidgetsByPadId.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
widgetIt->second->updatePadState(padState);
|
||||
}
|
||||
|
||||
this->update();
|
||||
}
|
||||
|
||||
void TargetPackageWidget::onProgrammingModeEnabled() {
|
||||
if (this->targetState.executionState == TargetExecutionState::STOPPED) {
|
||||
this->setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void TargetPackageWidget::onProgrammingModeDisabled() {
|
||||
if (this->targetState.executionState == TargetExecutionState::STOPPED) {
|
||||
this->setDisabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <utility>
|
||||
#include <unordered_map>
|
||||
#include <optional>
|
||||
|
||||
#include "src/Targets/TargetVariantDescriptor.hpp"
|
||||
#include "src/Targets/TargetPinoutDescriptor.hpp"
|
||||
#include "src/Targets/TargetPadDescriptor.hpp"
|
||||
#include "src/Targets/TargetGpioPadState.hpp"
|
||||
#include "src/Targets/TargetState.hpp"
|
||||
|
||||
#include "TargetPinWidget.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets
|
||||
{
|
||||
/**
|
||||
* Each custom target package widget should be derived from this class.
|
||||
*/
|
||||
class TargetPackageWidget: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TargetPackageWidget(
|
||||
const Targets::TargetVariantDescriptor& variantDescriptor,
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor,
|
||||
const Targets::TargetState& targetState,
|
||||
QWidget* parent
|
||||
);
|
||||
virtual void refreshPadStates(std::optional<std::function<void(void)>> callback = std::nullopt);
|
||||
|
||||
QSize sizeHint() const override {
|
||||
return this->minimumSize();
|
||||
}
|
||||
|
||||
QSize minimumSizeHint() const override {
|
||||
return this->sizeHint();
|
||||
}
|
||||
|
||||
protected:
|
||||
const Targets::TargetVariantDescriptor& variantDescriptor;
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor;
|
||||
const Targets::TargetState& targetState;
|
||||
|
||||
std::unordered_map<std::uint16_t, TargetPinWidget*> pinWidgetsByPosition;
|
||||
std::unordered_map<Targets::TargetPadId, TargetPinWidget*> pinWidgetsByPadId;
|
||||
Targets::TargetPadDescriptors padDescriptors;
|
||||
|
||||
virtual void updatePadStates(const Targets::TargetGpioPadDescriptorAndStatePairs& padStatePairs);
|
||||
void onProgrammingModeEnabled();
|
||||
void onProgrammingModeDisabled();
|
||||
};
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#include "TargetPackageWidgetContainer.hpp"
|
||||
|
||||
#include <QLayout>
|
||||
|
||||
namespace Widgets::InsightTargetWidgets
|
||||
{
|
||||
TargetPackageWidgetContainer::TargetPackageWidgetContainer(QWidget* parent): QWidget(parent) {}
|
||||
|
||||
void TargetPackageWidgetContainer::setPackageWidget(TargetPackageWidget* packageWidget) {
|
||||
this->packageWidget = packageWidget;
|
||||
|
||||
if (packageWidget != nullptr) {
|
||||
this->layout()->addWidget(packageWidget);
|
||||
}
|
||||
}
|
||||
|
||||
void TargetPackageWidgetContainer::resizeEvent(QResizeEvent* event) {
|
||||
if (this->packageWidget == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto packageSize = this->packageWidget->size();
|
||||
this->packageWidget->setGeometry(
|
||||
(this->width() / 2) - (packageSize.width() / 2),
|
||||
(this->height() / 2) - (packageSize.height() / 2),
|
||||
packageSize.width(),
|
||||
packageSize.height()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QResizeEvent>
|
||||
|
||||
#include "TargetPackageWidget.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets
|
||||
{
|
||||
class TargetPackageWidgetContainer: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TargetPackageWidgetContainer(QWidget* parent);
|
||||
|
||||
void setPackageWidget(TargetPackageWidget* packageWidget);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
private:
|
||||
TargetPackageWidget* packageWidget = nullptr;
|
||||
};
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
#include <QEvent>
|
||||
|
||||
#include "TargetPinBodyWidget.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets
|
||||
{
|
||||
using namespace Targets;
|
||||
|
||||
TargetPinBodyWidget::TargetPinBodyWidget(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
QWidget* parent
|
||||
)
|
||||
: QWidget(parent)
|
||||
, pinDescriptor(pinDescriptor)
|
||||
, padDescriptor(padDescriptor)
|
||||
{
|
||||
this->setObjectName("target-pin-body");
|
||||
this->setToolTip(
|
||||
this->padDescriptor.has_value()
|
||||
? QString::fromStdString(this->padDescriptor->get().name).toUpper()
|
||||
: "Not connected"
|
||||
);
|
||||
}
|
||||
|
||||
QColor TargetPinBodyWidget::getBodyColor() {
|
||||
using Targets::TargetGpioPadState;
|
||||
|
||||
auto pinColor = this->defaultBodyColor;
|
||||
|
||||
if (this->padDescriptor.has_value()) {
|
||||
const auto& padDescriptor = this->padDescriptor->get();
|
||||
|
||||
if (padDescriptor.type == TargetPadType::VCC) {
|
||||
pinColor = this->vccBodyColor;
|
||||
|
||||
} else if (padDescriptor.type == TargetPadType::GND) {
|
||||
pinColor = this->gndBodyColor;
|
||||
|
||||
} else if (padDescriptor.type == TargetPadType::GPIO) {
|
||||
if (this->padState.has_value()) {
|
||||
if (this->padState->value == TargetGpioPadState::State::HIGH) {
|
||||
pinColor = this->padState->direction == TargetGpioPadState::DataDirection::OUTPUT
|
||||
? this->outputHighBodyColor
|
||||
: this->inputHighBodyColor;
|
||||
}
|
||||
|
||||
if (
|
||||
(
|
||||
this->padState->direction == TargetGpioPadState::DataDirection::OUTPUT
|
||||
|| (
|
||||
this->padState->direction == TargetGpioPadState::DataDirection::INPUT
|
||||
&& this->padState->value == TargetGpioPadState::State::LOW
|
||||
)
|
||||
)
|
||||
&& !this->hoverActive
|
||||
) {
|
||||
pinColor.setAlpha(220);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->isEnabled()) {
|
||||
pinColor.setAlpha(this->disableAlphaLevel);
|
||||
}
|
||||
|
||||
return pinColor;
|
||||
}
|
||||
|
||||
bool TargetPinBodyWidget::event(QEvent* event) {
|
||||
if (this->padState.has_value() && this->padState->direction == TargetGpioPadState::DataDirection::OUTPUT) {
|
||||
switch (event->type()) {
|
||||
case QEvent::Enter: {
|
||||
this->hoverActive = true;
|
||||
this->repaint();
|
||||
break;
|
||||
}
|
||||
case QEvent::Leave: {
|
||||
this->hoverActive = false;
|
||||
this->repaint();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QWidget::event(event);
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
|
||||
#include "src/Targets/TargetPinDescriptor.hpp"
|
||||
#include "src/Targets/TargetPadDescriptor.hpp"
|
||||
#include "src/Targets/TargetGpioPadState.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets
|
||||
{
|
||||
class TargetPinBodyWidget: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
/*
|
||||
* Pin body colors can be set in QSS files.
|
||||
*/
|
||||
Q_PROPERTY(QColor defaultBodyColor READ getDefaultBodyColor WRITE setDefaultBodyColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor vccBodyColor READ getVccBodyColor WRITE setVccBodyColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor gndBodyColor READ getGndBodyColor WRITE setGndBodyColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor outputHighBodyColor READ getOutputHighBodyColor WRITE setOutputHighBodyColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor inputHighBodyColor READ getInputHighBodyColor WRITE setInputHighBodyColor DESIGNABLE true)
|
||||
|
||||
Q_PROPERTY(int disableAlphaLevel READ getDisableAlphaLevel WRITE setDisableAlphaLevel DESIGNABLE true)
|
||||
|
||||
public:
|
||||
TargetPinBodyWidget(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
QWidget* parent
|
||||
);
|
||||
|
||||
void setPadState(const Targets::TargetGpioPadState& padState) {
|
||||
this->padState = padState;
|
||||
}
|
||||
|
||||
const QColor& getDefaultBodyColor() const {
|
||||
return this->defaultBodyColor;
|
||||
}
|
||||
|
||||
void setDefaultBodyColor(const QColor& color) {
|
||||
this->defaultBodyColor = color;
|
||||
}
|
||||
|
||||
const QColor& getVccBodyColor() const {
|
||||
return this->vccBodyColor;
|
||||
}
|
||||
|
||||
void setVccBodyColor(const QColor& vccBodyColor) {
|
||||
this->vccBodyColor = vccBodyColor;
|
||||
}
|
||||
|
||||
const QColor& getGndBodyColor() const {
|
||||
return this->gndBodyColor;
|
||||
}
|
||||
|
||||
void setGndBodyColor(const QColor& gndBodyColor) {
|
||||
this->gndBodyColor = gndBodyColor;
|
||||
}
|
||||
|
||||
const QColor& getOutputHighBodyColor() const {
|
||||
return this->outputHighBodyColor;
|
||||
}
|
||||
|
||||
void setOutputHighBodyColor(const QColor& outputHighBodyColor) {
|
||||
this->outputHighBodyColor = outputHighBodyColor;
|
||||
}
|
||||
|
||||
const QColor& getInputHighBodyColor() const {
|
||||
return this->inputHighBodyColor;
|
||||
}
|
||||
|
||||
void setInputHighBodyColor(const QColor& inputHighBodyColor) {
|
||||
this->inputHighBodyColor = inputHighBodyColor;
|
||||
}
|
||||
|
||||
int getDisableAlphaLevel() const {
|
||||
return this->disableAlphaLevel;
|
||||
}
|
||||
|
||||
void setDisableAlphaLevel(int level) {
|
||||
this->disableAlphaLevel = level;
|
||||
}
|
||||
|
||||
signals:
|
||||
void clicked();
|
||||
|
||||
protected:
|
||||
const Targets::TargetPinDescriptor& pinDescriptor;
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor;
|
||||
std::optional<Targets::TargetGpioPadState> padState;
|
||||
|
||||
bool hoverActive = false;
|
||||
|
||||
QColor defaultBodyColor = {"#908D85"};
|
||||
QColor vccBodyColor = {"#70383A"};
|
||||
QColor gndBodyColor = {"#484A4B"};
|
||||
QColor outputHighBodyColor = {"#3C5E62"};
|
||||
QColor inputHighBodyColor = {"#7B5E38"};
|
||||
|
||||
int disableAlphaLevel = 100;
|
||||
|
||||
QColor getBodyColor();
|
||||
|
||||
bool event(QEvent* event) override;
|
||||
|
||||
void mouseReleaseEvent(QMouseEvent* event) override {
|
||||
if (event->button() == Qt::MouseButton::LeftButton) {
|
||||
emit this->clicked();
|
||||
}
|
||||
|
||||
QWidget::mouseReleaseEvent(event);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
#include "TargetPinWidget.hpp"
|
||||
|
||||
#include "src/Insight/InsightWorker/InsightWorker.hpp"
|
||||
#include "src/Insight/InsightWorker/Tasks/SetTargetGpioPadState.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets
|
||||
{
|
||||
TargetPinWidget::TargetPinWidget(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor,
|
||||
QWidget* parent
|
||||
)
|
||||
: QWidget(parent)
|
||||
, pinDescriptor(pinDescriptor)
|
||||
, padDescriptor(padDescriptor)
|
||||
, pinoutDescriptor(pinoutDescriptor)
|
||||
{
|
||||
if (!this->padDescriptor.has_value() || this->padDescriptor->get().type == Targets::TargetPadType::OTHER) {
|
||||
this->setDisabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void TargetPinWidget::onWidgetBodyClicked() {
|
||||
using Targets::TargetGpioPadState;
|
||||
|
||||
if (
|
||||
this->padDescriptor.has_value()
|
||||
&& this->padState.has_value()
|
||||
&& this->padState->direction == TargetGpioPadState::DataDirection::OUTPUT
|
||||
) {
|
||||
this->setDisabled(true);
|
||||
|
||||
auto newPadState = *this->padState;
|
||||
newPadState.value = this->padState->value == TargetGpioPadState::State::HIGH
|
||||
? TargetGpioPadState::State::LOW
|
||||
: TargetGpioPadState::State::HIGH;
|
||||
|
||||
const auto setPadStateTask = QSharedPointer<SetTargetGpioPadState>{
|
||||
new SetTargetGpioPadState{this->padDescriptor->get(), newPadState},
|
||||
&QObject::deleteLater
|
||||
};
|
||||
|
||||
QObject::connect(setPadStateTask.get(), &InsightWorkerTask::completed, this, [this, newPadState] {
|
||||
this->updatePadState(newPadState);
|
||||
this->setDisabled(false);
|
||||
});
|
||||
|
||||
QObject::connect(setPadStateTask.get(), &InsightWorkerTask::failed, this, [this] {
|
||||
this->setDisabled(false);
|
||||
});
|
||||
|
||||
InsightWorker::queueTask(setPadStateTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <utility>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
|
||||
#include "src/Targets/TargetPinDescriptor.hpp"
|
||||
#include "src/Targets/TargetPadDescriptor.hpp"
|
||||
#include "src/Targets/TargetPinoutDescriptor.hpp"
|
||||
#include "src/Targets/TargetGpioPadState.hpp"
|
||||
|
||||
#include "src/Services/StringService.hpp"
|
||||
|
||||
namespace Widgets::InsightTargetWidgets
|
||||
{
|
||||
class TargetPinWidget: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
const Targets::TargetPinDescriptor& pinDescriptor;
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor;
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor;
|
||||
std::optional<Targets::TargetGpioPadState> padState;
|
||||
bool padStateChanged = false;
|
||||
|
||||
TargetPinWidget(
|
||||
const Targets::TargetPinDescriptor& pinDescriptor,
|
||||
std::optional<std::reference_wrapper<const Targets::TargetPadDescriptor>> padDescriptor,
|
||||
const Targets::TargetPinoutDescriptor& pinoutDescriptor,
|
||||
QWidget* parent
|
||||
);
|
||||
|
||||
int getPinNumber() const {
|
||||
return Services::StringService::toUint8(this->pinDescriptor.position, 10);
|
||||
}
|
||||
|
||||
const std::optional<Targets::TargetGpioPadState>& getPadState() const {
|
||||
return this->padState;
|
||||
}
|
||||
|
||||
virtual void updatePadState(const Targets::TargetGpioPadState& padState) {
|
||||
this->padStateChanged = !this->padState.has_value() || this->padState != padState;
|
||||
this->padState = padState;
|
||||
}
|
||||
|
||||
bool hasPadStateChanged() const {
|
||||
return this->padStateChanged;
|
||||
}
|
||||
|
||||
public slots:
|
||||
virtual void onWidgetBodyClicked();
|
||||
};
|
||||
}
|
||||
@@ -50,6 +50,14 @@ InsightProjectSettings::InsightProjectSettings(const QJsonObject& jsonObject) {
|
||||
this->registersPaneState = this->paneStateFromJson(jsonObject.find("registersPaneState")->toObject());
|
||||
}
|
||||
|
||||
if (jsonObject.contains("refreshRegistersOnTargetStopped")) {
|
||||
this->refreshRegistersOnTargetStopped = jsonObject.value("refreshRegistersOnTargetStopped").toBool();
|
||||
}
|
||||
|
||||
if (jsonObject.contains("refreshGpioOnTargetStopped")) {
|
||||
this->refreshGpioOnTargetStopped = jsonObject.value("refreshGpioOnTargetStopped").toBool();
|
||||
}
|
||||
|
||||
if (jsonObject.contains("selectedVariantKey")) {
|
||||
this->selectedVariantKey = jsonObject.find("selectedVariantKey")->toString().toStdString();
|
||||
}
|
||||
@@ -99,6 +107,9 @@ QJsonObject InsightProjectSettings::toJson() const {
|
||||
insightObj.insert("registersPaneState", this->paneStateToJson(this->registersPaneState.value()));
|
||||
}
|
||||
|
||||
insightObj.insert("refreshRegistersOnTargetStopped", this->refreshRegistersOnTargetStopped);
|
||||
insightObj.insert("refreshGpioOnTargetStopped", this->refreshGpioOnTargetStopped);
|
||||
|
||||
if (this->selectedVariantKey.has_value()) {
|
||||
insightObj.insert("selectedVariantKey", QString::fromStdString(this->selectedVariantKey.value()));
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ public:
|
||||
std::optional<Widgets::PanelState> bottomPanelState;
|
||||
std::optional<Widgets::PaneState> registersPaneState;
|
||||
|
||||
bool refreshRegistersOnTargetStopped = false;
|
||||
bool refreshGpioOnTargetStopped = false;
|
||||
|
||||
/**
|
||||
* The key of the previously selected variant
|
||||
*/
|
||||
|
||||
@@ -602,10 +602,10 @@ namespace Targets::Microchip::Avr8
|
||||
output.emplace_back(
|
||||
*padDescriptor,
|
||||
TargetGpioPadState{
|
||||
(readGpioReg(stateRegisterDescriptor) & gpioPadDescriptor.registerMask) != 0
|
||||
.value = (readGpioReg(stateRegisterDescriptor) & gpioPadDescriptor.registerMask) != 0
|
||||
? TargetGpioPadState::State::HIGH
|
||||
: TargetGpioPadState::State::LOW,
|
||||
ddrValue
|
||||
.direction = ddrValue
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -443,6 +443,14 @@ namespace Targets::RiscV::Wch
|
||||
const auto& portClockEnableRegisterValue = readGpioReg(this->portPeripheralClockEnableRegisterDescriptor);
|
||||
if (!portClockEnableRegisterValue.bitFieldAs<bool>(gpioPadDescriptor.peripheralClockEnableBitFieldDescriptor)) {
|
||||
// The port peripheral is currently disabled. We cannot obtain any meaningful state for this pad
|
||||
output.emplace_back(
|
||||
*padDescriptor,
|
||||
TargetGpioPadState{
|
||||
.disabled = true,
|
||||
.value = TargetGpioPadState::State::UNKNOWN,
|
||||
.direction = TargetGpioPadState::DataDirection::UNKNOWN
|
||||
}
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -453,10 +461,10 @@ namespace Targets::RiscV::Wch
|
||||
output.emplace_back(
|
||||
*padDescriptor,
|
||||
TargetGpioPadState{
|
||||
readGpioReg(gpioPadDescriptor.inputDataRegisterDescriptor).bitFieldAs<bool>(
|
||||
.value = readGpioReg(gpioPadDescriptor.inputDataRegisterDescriptor).bitFieldAs<bool>(
|
||||
gpioPadDescriptor.inputDataBitFieldDescriptor
|
||||
) ? TargetGpioPadState::State::HIGH : TargetGpioPadState::State::LOW,
|
||||
TargetGpioPadState::DataDirection::INPUT
|
||||
.direction = TargetGpioPadState::DataDirection::INPUT
|
||||
}
|
||||
);
|
||||
|
||||
@@ -466,10 +474,10 @@ namespace Targets::RiscV::Wch
|
||||
output.emplace_back(
|
||||
*padDescriptor,
|
||||
TargetGpioPadState{
|
||||
readGpioReg(gpioPadDescriptor.outputDataRegisterDescriptor).bitFieldAs<bool>(
|
||||
.value = readGpioReg(gpioPadDescriptor.outputDataRegisterDescriptor).bitFieldAs<bool>(
|
||||
gpioPadDescriptor.outputDataBitFieldDescriptor
|
||||
) ? TargetGpioPadState::State::HIGH : TargetGpioPadState::State::LOW,
|
||||
TargetGpioPadState::DataDirection::OUTPUT
|
||||
.direction = TargetGpioPadState::DataDirection::OUTPUT
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1186,7 +1186,7 @@ namespace Targets::TargetDescription
|
||||
return TargetPadType::VCC;
|
||||
}
|
||||
|
||||
if (padNameLower.find("gnd") == 0 || padNameLower.find("agnd") == 0) {
|
||||
if (padNameLower.find("gnd") == 0 || padNameLower.find("agnd") == 0 || padNameLower.find("vss") == 0) {
|
||||
return TargetPadType::GND;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,24 +15,19 @@ namespace Targets
|
||||
{
|
||||
HIGH,
|
||||
LOW,
|
||||
UNKNOWN,
|
||||
};
|
||||
|
||||
enum class DataDirection: std::uint8_t
|
||||
{
|
||||
INPUT,
|
||||
OUTPUT,
|
||||
UNKNOWN,
|
||||
};
|
||||
|
||||
State value;
|
||||
DataDirection direction;
|
||||
|
||||
TargetGpioPadState(
|
||||
State value,
|
||||
DataDirection direction
|
||||
)
|
||||
: value(value)
|
||||
, direction(direction)
|
||||
{}
|
||||
bool disabled = false;
|
||||
State value = State::UNKNOWN;
|
||||
DataDirection direction = DataDirection::UNKNOWN;
|
||||
|
||||
bool operator == (const TargetGpioPadState& other) const {
|
||||
return this->value == other.value && this->direction == other.direction;
|
||||
|
||||
Reference in New Issue
Block a user