Moved Insight target widgets to "Widgets" sub-folder.

This commit is contained in:
Nav
2021-07-07 20:54:45 +01:00
parent d8f53e4f9f
commit 2e4810389f
25 changed files with 43 additions and 44 deletions

View File

@@ -0,0 +1,66 @@
#include <QPainter>
#include "BodyWidget.hpp"
#include "src/Logger/Logger.hpp"
#include "src/Exceptions/Exception.hpp"
using namespace Bloom::Widgets::InsightTargetWidgets::Dip;
using namespace Bloom::Exceptions;
void BodyWidget::paintEvent(QPaintEvent* event) {
auto painter = QPainter(this);
this->drawWidget(painter);
}
void BodyWidget::drawWidget(QPainter& painter) {
auto parentWidget = this->parentWidget();
if (parentWidget == nullptr) {
throw Exception("BodyWidget requires a parent widget");
}
painter.setRenderHints(QPainter::RenderHint::Antialiasing | QPainter::RenderHint::SmoothPixmapTransform, true);
// Draw target body
auto targetBodyColor = this->getBodyColor();
auto backgroundColor = QColor("#3C3F41");
if (!this->isEnabled()) {
targetBodyColor.setAlpha(this->getDisableAlphaLevel());
}
painter.setPen(Qt::PenStyle::NoPen);
painter.setBrush(targetBodyColor);
auto parentContainerWidth = parentWidget->width();
auto targetBodyHeight = 150;
auto targetBodyWidth = parentContainerWidth;
this->setFixedSize(targetBodyWidth, targetBodyHeight);
auto targetBodyPoint = QPoint(
0,
0
);
painter.drawRect(
targetBodyPoint.x(),
targetBodyPoint.y(),
targetBodyWidth,
targetBodyHeight
);
painter.setPen(Qt::PenStyle::NoPen);
painter.setBrush(backgroundColor);
painter.drawEllipse(QRectF(
targetBodyPoint.x() + 10,
targetBodyPoint.y() + (targetBodyHeight - 30),
20,
20
));
painter.drawEllipse(QRectF(
targetBodyPoint.x() - 15,
targetBodyPoint.y() + (targetBodyHeight / 2) - 15,
30,
30
));
}

View File

@@ -0,0 +1,43 @@
#pragma once
#include <QWidget>
namespace Bloom::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)
private:
// These properties can be modified via Qt style sheets (see Stylesheets/DualInlinePackage.qss)
QColor bodyColor = QColor("#AFB1B3");
int disableAlphaLevel = 100;
protected:
void paintEvent(QPaintEvent* event) override;
void drawWidget(QPainter& painter);
public:
explicit BodyWidget(QWidget* parent): QWidget(parent) {
this->setObjectName("target-body");
}
[[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;
}
};
}

View File

@@ -0,0 +1,128 @@
#include <QPainter>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <vector>
#include <QEvent>
#include <QFile>
#include "../../../InsightWindow.hpp"
#include "DualInlinePackageWidget.hpp"
#include "src/Logger/Logger.hpp"
#include "src/Exceptions/Exception.hpp"
#include "src/Helpers/Paths.hpp"
#include "PinWidget.hpp"
#include "BodyWidget.hpp"
using namespace Bloom::Widgets::InsightTargetWidgets::Dip;
using namespace Bloom::Exceptions;
using Bloom::Targets::TargetVariant;
DualInlinePackageWidget::DualInlinePackageWidget(
const TargetVariant& targetVariant,
QObject* insightWindowObj,
QWidget* parent
): TargetPackageWidget(targetVariant, insightWindowObj, parent) {
auto stylesheetFile = QFile(QString::fromStdString(
Paths::compiledResourcesPath()
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets/DIP/Stylesheets/DualInlinePackage.qss"
)
);
stylesheetFile.open(QFile::ReadOnly);
this->setStyleSheet(stylesheetFile.readAll());
this->pinWidgets.reserve(targetVariant.pinDescriptorsByNumber.size());
this->layout = new QVBoxLayout();
this->layout->setSpacing(8);
this->layout->setMargin(0);
this->topPinLayout = new QHBoxLayout();
this->topPinLayout->setSpacing(8);
this->topPinLayout->setDirection(QBoxLayout::Direction::RightToLeft);
this->bottomPinLayout = new QHBoxLayout();
this->bottomPinLayout->setSpacing(8);
auto insightWindow = qobject_cast<InsightWindow*>(insightWindowObj);
assert(insightWindow != nullptr);
for (const auto& [targetPinNumber, targetPinDescriptor]: targetVariant.pinDescriptorsByNumber) {
auto pinWidget = new PinWidget(this, targetPinDescriptor, targetVariant);
this->pinWidgets.push_back(pinWidget);
if (targetPinNumber <= (targetVariant.pinDescriptorsByNumber.size() / 2)) {
this->bottomPinLayout->addWidget(pinWidget, 0, Qt::AlignmentFlag::AlignHCenter);
} else {
this->topPinLayout->addWidget(pinWidget, 0, Qt::AlignmentFlag::AlignRight);
}
connect(pinWidget, &TargetPinWidget::toggleIoState, insightWindow, &InsightWindow::togglePinIoState);
}
this->layout->addLayout(this->topPinLayout);
this->bodyWidget = new BodyWidget(this);
this->layout->addWidget(this->bodyWidget);
this->layout->addLayout(this->bottomPinLayout);
this->setLayout(this->layout);
auto insightWindowWidget = this->window();
assert(insightWindowWidget != nullptr);
insightWindowWidget->setMinimumHeight(500);
insightWindowWidget->setMinimumWidth(1000);
}
void DualInlinePackageWidget::paintEvent(QPaintEvent* event) {
// Logger::debug("Drawing main package widget");
auto painter = QPainter(this);
this->drawWidget(painter);
}
void DualInlinePackageWidget::resizeEvent(QResizeEvent* event) {
// Logger::debug("RESIZE EVENT");
}
void DualInlinePackageWidget::drawWidget(QPainter& painter) {
auto parentWidget = this->parentWidget();
if (parentWidget == nullptr) {
throw Exception("DualInlinePackageWidget requires a parent widget");
}
auto parentContainerHeight = parentWidget->height();
auto parentContainerWidth = parentWidget->width();
auto width = ((PinWidget::MINIMUM_WIDTH + 8) * static_cast<int>(this->pinWidgets.size() / 2)) + 46;
this->topPinLayout->setGeometry(QRect(0, 0, width, PinWidget::MAXIMUM_HEIGHT));
auto bodyGeometry = QRect(0, this->topPinLayout->geometry().height() + 8, width, this->bodyWidget->height());
this->bodyWidget->setGeometry(bodyGeometry);
this->bottomPinLayout->setGeometry(
QRect(
0,
bodyGeometry.top() + bodyGeometry.height() + 8,
width,
PinWidget::MAXIMUM_HEIGHT
)
);
this->topPinLayout->setContentsMargins(
static_cast<int>(width * 0.04),
0,
static_cast<int>(width * 0.04),
0
);
this->bottomPinLayout->setContentsMargins(
static_cast<int>(width * 0.04),
0,
static_cast<int>(width * 0.04),
0
);
auto height = (PinWidget::MAXIMUM_HEIGHT * 2) + bodyGeometry.height() + (8 * 3);
this->setGeometry(
(parentContainerWidth / 2) - (width / 2),
(parentContainerHeight / 2) - (height / 2),
width,
height
);
}

View File

@@ -0,0 +1,35 @@
#pragma once
#include <QWidget>
#include <vector>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include "../TargetPackageWidget.hpp"
#include "PinWidget.hpp"
#include "BodyWidget.hpp"
#include "src/Targets/TargetVariant.hpp"
namespace Bloom::Widgets::InsightTargetWidgets::Dip
{
/**
* The DualInlinePackageWidget implements a custom Qt widget for the Dual-inline package target variants.
*/
class DualInlinePackageWidget: public TargetPackageWidget
{
Q_OBJECT
private:
QVBoxLayout* layout = nullptr;
QHBoxLayout* topPinLayout = nullptr;
QHBoxLayout* bottomPinLayout = nullptr;
BodyWidget* bodyWidget = nullptr;
protected:
void paintEvent(QPaintEvent* event) override;
void resizeEvent(QResizeEvent* event) override;
void drawWidget(QPainter& painter);
public:
DualInlinePackageWidget(const Targets::TargetVariant& targetVariant, QObject* insightWindowObj, QWidget* parent);
};
}

View File

@@ -0,0 +1,88 @@
#include <QPainter>
#include <QLayout>
#include <QEvent>
#include <QMenu>
#include <QContextMenuEvent>
#include "PinBodyWidget.hpp"
#include "src/Logger/Logger.hpp"
using namespace Bloom::Widgets::InsightTargetWidgets::Dip;
using namespace Bloom::Targets;
void PinBodyWidget::paintEvent(QPaintEvent* event) {
auto painter = QPainter(this);
this->drawWidget(painter);
}
bool PinBodyWidget::event(QEvent* event) {
if (this->isEnabled() && this->pinState.has_value() && this->pinState->ioDirection == TargetPinState::IoDirection::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);
}
void PinBodyWidget::drawWidget(QPainter& painter) {
auto parentWidget = this->parentWidget();
if (parentWidget == nullptr) {
Logger::error("PinBodyWidget requires a parent widget");
}
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();
if (this->pinDescriptor.type == TargetPinType::VCC) {
pinColor = QColor("#ff3d43");
} else if (this->pinDescriptor.type == TargetPinType::GND) {
pinColor = QColor("#575757");
}
if (this->pinState.has_value()) {
if (this->pinState->ioState.has_value()
&& this->pinState->ioDirection.has_value()
&& this->pinState->ioState.value() == TargetPinState::IoState::HIGH
) {
pinColor = this->pinState->ioDirection.value() == TargetPinState::IoDirection::OUTPUT ?
QColor("#3D7F96") : QColor("#A47E3E");
}
}
if (!this->hoverActive) {
pinColor.setAlpha(225);
}
if (!this->isEnabled()) {
pinColor.setAlpha(this->getDisableAlphaLevel());
}
painter.setPen(Qt::PenStyle::NoPen);
painter.setBrush(pinColor);
painter.drawRect(
0,
0,
pinWidth,
pinHeight
);
}

View File

@@ -0,0 +1,71 @@
#pragma once
#include <QWidget>
#include <QMouseEvent>
#include <utility>
#include "src/Targets/TargetPinDescriptor.hpp"
namespace Bloom::Widgets::InsightTargetWidgets::Dip
{
class PinBodyWidget: public QWidget
{
Q_OBJECT
Q_PROPERTY(QColor bodyColor READ getBodyColor WRITE setBodyColor DESIGNABLE true)
Q_PROPERTY(int disableAlphaLevel READ getDisableAlphaLevel WRITE setDisableAlphaLevel DESIGNABLE true)
private:
Targets::TargetPinDescriptor pinDescriptor;
std::optional<Targets::TargetPinState> pinState;
QColor bodyColor = QColor("#AFB1B3");
int disableAlphaLevel = 100;
protected:
bool hoverActive = false;
void paintEvent(QPaintEvent* event) override;
void drawWidget(QPainter& painter);
bool event(QEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override {
if (event->button() == Qt::MouseButton::LeftButton) {
emit this->clicked();
}
QWidget::mouseReleaseEvent(event);
}
public:
static const int WIDTH = 30;
static const int HEIGHT = 40;
PinBodyWidget(
QWidget* parent,
Targets::TargetPinDescriptor pinDescriptor
): QWidget(parent), pinDescriptor(std::move(pinDescriptor)) {
this->setFixedSize(PinBodyWidget::WIDTH, PinBodyWidget::HEIGHT);
this->setObjectName("target-pin-body");
}
void setPinState(const Targets::TargetPinState& pinState) {
this->pinState = pinState;
}
QColor getBodyColor() const {
return this->bodyColor;
}
void setBodyColor(const QColor& color) {
this->bodyColor = color;
}
int getDisableAlphaLevel() const {
return this->disableAlphaLevel;
}
void setDisableAlphaLevel(int level) {
this->disableAlphaLevel = level;
}
signals:
void clicked();
};
}

View File

@@ -0,0 +1,63 @@
#include <QWidget>
#include <QPainter>
#include <QLayout>
#include <cmath>
#include <QEvent>
#include "PinWidget.hpp"
#include "PinBodyWidget.hpp"
#include "src/Logger/Logger.hpp"
using namespace Bloom::Widgets::InsightTargetWidgets::Dip;
using namespace Bloom::Targets;
PinWidget::PinWidget(QWidget* parent, const TargetPinDescriptor& pinDescriptor, const TargetVariant& targetVariant):
TargetPinWidget(parent, pinDescriptor, targetVariant) {
this->layout = new QVBoxLayout();
this->layout->setMargin(0);
this->layout->setSpacing(0);
this->bodyWidget = new PinBodyWidget(this, this->pinDescriptor);
bool isTopWidget = pinDescriptor.number > (targetVariant.pinDescriptorsByNumber.size() / 2);
this->layout->setAlignment(isTopWidget ? (Qt::AlignmentFlag::AlignHCenter | Qt::AlignmentFlag::AlignBottom)
: (Qt::AlignmentFlag::AlignHCenter | Qt::AlignmentFlag::AlignTop));
this->pinDirectionLabel = new QLabel(this);
this->pinDirectionLabel->setObjectName("target-pin-direction");
this->pinDirectionLabel->setAlignment(Qt::AlignmentFlag::AlignCenter);
auto pinName = QString::fromStdString(pinDescriptor.name).toUpper();
this->pinNameLabel = new QLabel(this);
this->pinNameLabel->setObjectName("target-pin-name");
this->pinNameLabel->setToolTip(pinName);
if (pinName.size() > 4) {
pinName.truncate(4);
}
this->pinNameLabel->setText(pinName);
this->pinNameLabel->setAlignment(Qt::AlignmentFlag::AlignCenter);
this->pinNumberLabel = new QLabel(this);
this->pinNumberLabel->setObjectName("target-pin-number");
this->pinNumberLabel->setText(QString::number(pinDescriptor.number));
this->pinNumberLabel->setAlignment(Qt::AlignmentFlag::AlignCenter);
if (isTopWidget) {
this->layout->setDirection(QBoxLayout::Direction::BottomToTop);
}
this->layout->addWidget(this->bodyWidget);
this->layout->insertSpacing(1, 3);
this->layout->addWidget(this->pinNumberLabel);
this->layout->insertSpacing(3, 2);
this->layout->addWidget(this->pinNameLabel);
this->layout->insertSpacing(5, 2);
this->layout->addWidget(this->pinDirectionLabel);
this->pinNameLabel->setFixedSize(PinBodyWidget::WIDTH, PinWidget::LABEL_HEIGHT - 2);
this->pinNumberLabel->setFixedSize(PinBodyWidget::WIDTH, PinWidget::LABEL_HEIGHT - 2);
this->setFixedSize(PinWidget::MINIMUM_WIDTH, PinWidget::MAXIMUM_HEIGHT);
this->setLayout(this->layout);
connect(this->bodyWidget, &PinBodyWidget::clicked, this, &TargetPinWidget::onWidgetBodyClicked);
}

View File

@@ -0,0 +1,61 @@
#pragma once
#include <QWidget>
#include <QLabel>
#include "../TargetPinWidget.hpp"
#include "PinBodyWidget.hpp"
#include "src/Targets/TargetVariant.hpp"
namespace Bloom::Widgets::InsightTargetWidgets::Dip
{
class PinWidget: public TargetPinWidget
{
Q_OBJECT
private:
QVBoxLayout* layout = nullptr;
QLabel* pinNumberLabel = nullptr;
QLabel* pinNameLabel = nullptr;
QLabel* pinDirectionLabel = nullptr;
PinBodyWidget* bodyWidget = nullptr;
void setLabelColor(const QString& hexColor) {
auto style = QString("QLabel { color: " + hexColor + "; }");
if (this->pinNameLabel != nullptr) {
this->pinNameLabel->setStyleSheet(style);
}
}
public:
static const int MINIMUM_WIDTH = 30;
static const int MAXIMUM_LABEL_COUNT = 3;
static const int LABEL_HEIGHT = 20;
static const int MAXIMUM_HEIGHT = PinBodyWidget::HEIGHT
+ (PinWidget::LABEL_HEIGHT * PinWidget::MAXIMUM_LABEL_COUNT);
PinWidget(
QWidget* parent,
const Targets::TargetPinDescriptor& pinDescriptor,
const Targets::TargetVariant& targetVariant
);
void updatePinState(const Targets::TargetPinState& pinState) override {
TargetPinWidget::updatePinState(pinState);
if (pinState.ioDirection.has_value()) {
this->pinDirectionLabel->setText(
pinState.ioDirection.value() == Targets::TargetPinState::IoDirection::INPUT ? "IN" : "OUT"
);
} else {
this->pinDirectionLabel->setText("");
}
if (this->bodyWidget != nullptr) {
this->bodyWidget->setPinState(pinState);
}
this->setLabelColor(this->pinStateChanged ? "#6FA0FF" : "#a6a7aa");
}
};
}

View File

@@ -0,0 +1,30 @@
#target-pin-number,
#target-pin-number {
font-size: 14px;
}
#target-pin-name,
#target-pin-direction {
font-size: 11px;
}
#target-pin-name {
color: #a6a7aa;
}
#target-pin-direction {
color: #8a8a8d;
}
#target-pin-number-top {
}
#target-body {
qproperty-bodyColor: #A6A8AB;
qproperty-disableAlphaLevel: 100;
}
#target-pin-body {
qproperty-bodyColor: #A6A8AB;
qproperty-disableAlphaLevel: 100;
}

View File

@@ -0,0 +1,49 @@
#include <QPainter>
#include "BodyWidget.hpp"
#include "src/Logger/Logger.hpp"
using namespace Bloom::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("#3C3F41");
if (!this->isEnabled()) {
targetBodyColor.setAlpha(this->getDisableAlphaLevel());
}
painter.setPen(Qt::PenStyle::NoPen);
painter.setBrush(targetBodyColor);
auto containerGeometry = this->geometry();
auto targetBodyWidth = containerGeometry.width() - 16;
auto targetBodyHeight = containerGeometry.height() - 16;
auto targetBodyPoint = QPoint(
(containerGeometry.width() / 2) - (targetBodyWidth / 2),
(containerGeometry.height() / 2) - (targetBodyHeight / 2)
);
painter.drawRect(
targetBodyPoint.x(),
targetBodyPoint.y(),
targetBodyWidth,
targetBodyHeight
);
painter.setBrush(backgroundColor);
painter.drawEllipse(QRectF(
targetBodyPoint.x() + 10,
targetBodyPoint.y() + 10,
15,
15
));
}

View File

@@ -0,0 +1,43 @@
#pragma once
#include <QWidget>
namespace Bloom::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)
private:
// These properties can be modified via Qt style sheets (see Stylesheets/QuadFlatPackage.qss)
QColor bodyColor = QColor("#AFB1B3");
int disableAlphaLevel = 100;
protected:
void paintEvent(QPaintEvent* event) override;
void drawWidget(QPainter& painter);
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;
}
};
}

View File

@@ -0,0 +1,88 @@
#include <QPainter>
#include <QLayout>
#include <QEvent>
#include <QMenu>
#include <QContextMenuEvent>
#include "PinBodyWidget.hpp"
#include "src/Logger/Logger.hpp"
using namespace Bloom::Widgets::InsightTargetWidgets::Qfp;
using namespace Bloom::Targets;
void PinBodyWidget::paintEvent(QPaintEvent* event) {
auto painter = QPainter(this);
this->drawWidget(painter);
}
bool PinBodyWidget::event(QEvent* event) {
if (this->isEnabled() && this->pinState.has_value() && this->pinState->ioDirection == TargetPinState::IoDirection::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);
}
void PinBodyWidget::drawWidget(QPainter& painter) {
auto parentWidget = this->parentWidget();
if (parentWidget == nullptr) {
Logger::error("PinBodyWidget requires a parent widget");
}
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();
if (this->pinDescriptor.type == TargetPinType::VCC) {
pinColor = QColor("#ff3d43");
} else if (this->pinDescriptor.type == TargetPinType::GND) {
pinColor = QColor("#575757");
}
if (this->pinState.has_value()) {
if (this->pinState->ioState.has_value()
&& this->pinState->ioDirection.has_value()
&& this->pinState->ioState.value() == TargetPinState::IoState::HIGH
) {
pinColor = this->pinState->ioDirection.value() == TargetPinState::IoDirection::OUTPUT ?
QColor("#3D7F96") : QColor("#A47E3E");
}
}
if (!this->hoverActive) {
pinColor.setAlpha(225);
}
if (!this->isEnabled()) {
pinColor.setAlpha(this->getDisableAlphaLevel());
}
painter.setPen(Qt::PenStyle::NoPen);
painter.setBrush(pinColor);
painter.drawRect(
0,
0,
pinWidth,
pinHeight
);
}

View File

@@ -0,0 +1,77 @@
#pragma once
#include <QWidget>
#include <QMouseEvent>
#include <utility>
#include "src/Targets/TargetPinDescriptor.hpp"
namespace Bloom::Widgets::InsightTargetWidgets::Qfp
{
class PinBodyWidget: public QWidget
{
Q_OBJECT
Q_PROPERTY(QColor bodyColor READ getBodyColor WRITE setBodyColor DESIGNABLE true)
Q_PROPERTY(int disableAlphaLevel READ getDisableAlphaLevel WRITE setDisableAlphaLevel DESIGNABLE true)
private:
Targets::TargetPinDescriptor pinDescriptor;
std::optional<Targets::TargetPinState> pinState;
QColor bodyColor = QColor("#AFB1B3");
int disableAlphaLevel = 100;
bool isVertical = false;
protected:
bool hoverActive = false;
void paintEvent(QPaintEvent* event) override;
void drawWidget(QPainter& painter);
bool event(QEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override {
if (event->button() == Qt::MouseButton::LeftButton) {
emit this->clicked();
}
QWidget::mouseReleaseEvent(event);
}
public:
static const int WIDTH = 30;
static const int HEIGHT = 40;
PinBodyWidget(QWidget* parent, Targets::TargetPinDescriptor pinDescriptor, bool isVertical):
QWidget(parent), pinDescriptor(std::move(pinDescriptor)), isVertical(isVertical) {
this->setObjectName("target-pin-body");
if (isVertical) {
this->setFixedSize(PinBodyWidget::WIDTH, PinBodyWidget::HEIGHT);
} else {
this->setFixedSize(PinBodyWidget::HEIGHT, PinBodyWidget::WIDTH);
}
}
void setPinState(const Targets::TargetPinState& pinState) {
this->pinState = pinState;
}
QColor getBodyColor() const {
return this->bodyColor;
}
void setBodyColor(const QColor& color) {
this->bodyColor = color;
}
int getDisableAlphaLevel() const {
return this->disableAlphaLevel;
}
void setDisableAlphaLevel(int level) {
this->disableAlphaLevel = level;
}
signals:
void clicked();
};
}

View File

@@ -0,0 +1,100 @@
#include <QWidget>
#include <QPainter>
#include <QLayout>
#include <cmath>
#include <QEvent>
#include "PinWidget.hpp"
#include "PinBodyWidget.hpp"
#include "src/Logger/Logger.hpp"
using namespace Bloom::Widgets::InsightTargetWidgets::Qfp;
using namespace Bloom::Targets;
PinWidget::PinWidget(QWidget* parent, const TargetPinDescriptor& pinDescriptor, const TargetVariant& targetVariant):
TargetPinWidget(parent, pinDescriptor, targetVariant) {
this->layout = new QVBoxLayout();
this->layout->setMargin(0);
this->layout->setSpacing(0);
auto pinCountPerLayout = (targetVariant.pinDescriptorsByNumber.size() / 4);
this->isLeftLayout = pinDescriptor.number <= pinCountPerLayout;
this->isBottomLayout = pinDescriptor.number > pinCountPerLayout && pinDescriptor.number <= (pinCountPerLayout * 2);
this->isRightLayout = pinDescriptor.number > (pinCountPerLayout * 2) && pinDescriptor.number <= (pinCountPerLayout * 3);
this->isTopLayout = pinDescriptor.number > (pinCountPerLayout * 3) && pinDescriptor.number <= (pinCountPerLayout * 4);
this->bodyWidget = new PinBodyWidget(this, this->pinDescriptor, (this->isTopLayout || this->isBottomLayout));
this->pinDirectionLabel = new QLabel(this);
this->pinDirectionLabel->setObjectName("target-pin-direction");
this->pinDirectionLabel->setAlignment(Qt::AlignmentFlag::AlignCenter);
auto pinName = QString::fromStdString(pinDescriptor.name).toUpper();
this->pinNameLabel = new QLabel(this);
this->pinNameLabel->setObjectName("target-pin-name");
this->pinNameLabel->setToolTip(pinName);
if (pinName.size() > 4) {
pinName.truncate(4);
}
this->pinNameLabel->setText(pinName);
this->pinNameLabel->setAlignment(Qt::AlignmentFlag::AlignCenter);
this->pinNumberLabel = new QLabel(this);
this->pinNumberLabel->setObjectName("target-pin-number");
auto pinNumberText = QString::number(pinDescriptor.number);
pinNumberText.truncate(5);
this->pinNumberLabel->setText(QString::number(pinDescriptor.number));
this->pinNumberLabel->setAlignment(Qt::AlignmentFlag::AlignCenter);
if (this->isLeftLayout) {
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->isBottomLayout) {
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->isRightLayout) {
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->isTopLayout) {
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->insertSpacing(1, 3);
if (this->isLeftLayout || this->isRightLayout) {
auto stackedLabelLayout = new QVBoxLayout();
stackedLabelLayout->addWidget(this->pinNameLabel);
stackedLabelLayout->insertSpacing(3, 2);
stackedLabelLayout->addWidget(this->pinNumberLabel);
this->layout->insertSpacing(2, 4);
this->layout->addLayout(stackedLabelLayout);
// Adjust the pin name label width for horizontal pins to accommodate for pin names up to 5 characters in length
this->pinNameLabel->setFixedSize(PinWidget::MAXIMUM_LABEL_WIDTH + 5, PinWidget::MAXIMUM_HORIZONTAL_HEIGHT / 2);
this->pinNumberLabel->setFixedSize(PinWidget::MAXIMUM_LABEL_WIDTH + 5, PinWidget::MAXIMUM_HORIZONTAL_HEIGHT / 2);
} else if (this-isTopLayout || this->isBottomLayout) {
this->layout->addWidget(this->pinNumberLabel);
this->layout->insertSpacing(3, 2);
this->layout->addWidget(this->pinNameLabel);
this->pinNameLabel->setFixedSize(PinBodyWidget::WIDTH, PinWidget::LABEL_HEIGHT - 2);
this->pinNumberLabel->setFixedSize(PinBodyWidget::WIDTH, PinWidget::LABEL_HEIGHT - 2);
}
this->layout->insertSpacing(5, 2);
this->layout->addWidget(this->pinDirectionLabel);
this->setLayout(this->layout);
connect(this->bodyWidget, &PinBodyWidget::clicked, this, &TargetPinWidget::onWidgetBodyClicked);
}

View File

@@ -0,0 +1,73 @@
#pragma once
#include <QWidget>
#include <QLabel>
#include "../TargetPinWidget.hpp"
#include "PinBodyWidget.hpp"
#include "src/Targets/TargetVariant.hpp"
namespace Bloom::Widgets::InsightTargetWidgets::Qfp
{
class PinWidget: public TargetPinWidget
{
Q_OBJECT
private:
QVBoxLayout* layout = nullptr;
QLabel* pinNumberLabel = nullptr;
QLabel* pinNameLabel = nullptr;
QLabel* pinDirectionLabel = nullptr;
PinBodyWidget* bodyWidget = nullptr;
bool isLeftLayout = false;
bool isBottomLayout = false;
bool isRightLayout = false;
bool isTopLayout = false;
void setLabelColor(const QString& hexColor) {
auto style = QString("QLabel { color: " + hexColor + "; }");
if (this->pinNameLabel != nullptr) {
this->pinNameLabel->setStyleSheet(style);
}
}
public:
static const int MAXIMUM_SPACING = 8;
static const int MAXIMUM_LABEL_COUNT = 3;
static const int LABEL_HEIGHT = 20;
static const int MAXIMUM_LABEL_WIDTH = PinBodyWidget::WIDTH;
static const int MAXIMUM_LABEL_HEIGHT = 20;
static const int MAXIMUM_HORIZONTAL_WIDTH = PinBodyWidget::HEIGHT
+ (PinWidget::MAXIMUM_LABEL_WIDTH * PinWidget::MAXIMUM_LABEL_COUNT);
static const int MAXIMUM_HORIZONTAL_HEIGHT = PinBodyWidget::WIDTH;
static const int MAXIMUM_VERTICAL_HEIGHT = PinBodyWidget::HEIGHT
+ (PinWidget::MAXIMUM_LABEL_HEIGHT * PinWidget::MAXIMUM_LABEL_COUNT);
static const int MAXIMUM_VERTICAL_WIDTH = PinBodyWidget::WIDTH;
PinWidget(
QWidget* parent,
const Targets::TargetPinDescriptor& pinDescriptor,
const Targets::TargetVariant& targetVariant
);
void updatePinState(const Targets::TargetPinState& pinState) override {
TargetPinWidget::updatePinState(pinState);
if (pinState.ioDirection.has_value()) {
this->pinDirectionLabel->setText(
pinState.ioDirection.value() == Targets::TargetPinState::IoDirection::INPUT ? "IN" : "OUT"
);
} else {
this->pinDirectionLabel->setText("");
}
if (this->bodyWidget != nullptr) {
this->bodyWidget->setPinState(pinState);
}
this->setLabelColor(this->pinStateChanged ? "#6FA0FF" : "#a6a7aa");
}
};
}

View File

@@ -0,0 +1,220 @@
#include <QPainter>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <vector>
#include <QEvent>
#include <QFile>
#include "../../../InsightWindow.hpp"
#include "QuadFlatPackageWidget.hpp"
#include "src/Helpers/Paths.hpp"
#include "PinWidget.hpp"
#include "BodyWidget.hpp"
using namespace Bloom::Widgets::InsightTargetWidgets::Qfp;
using namespace Bloom::Targets;
QuadFlatPackageWidget::QuadFlatPackageWidget(
const TargetVariant& targetVariant,
QObject* insightWindowObj,
QWidget* parent
): TargetPackageWidget(targetVariant, insightWindowObj, parent) {
assert((targetVariant.pinDescriptorsByNumber.size() % 4) == 0);
auto stylesheetFile = QFile(QString::fromStdString(
Paths::compiledResourcesPath()
+ "/src/Insight/UserInterfaces/InsightWindow/Widgets/TargetWidgets//QFP/Stylesheets/QuadFlatPackage.qss"
)
);
stylesheetFile.open(QFile::ReadOnly);
this->setStyleSheet(stylesheetFile.readAll());
this->pinWidgets.reserve(targetVariant.pinDescriptorsByNumber.size());
this->layout = new QVBoxLayout();
this->layout->setSpacing(0);
this->layout->setMargin(0);
this->horizontalLayout = new QHBoxLayout();
this->horizontalLayout->setSpacing(0);
this->horizontalLayout->setDirection(QBoxLayout::Direction::LeftToRight);
this->topPinLayout = new QHBoxLayout();
this->topPinLayout->setSpacing(QuadFlatPackageWidget::PIN_WIDGET_SPACING);
this->topPinLayout->setDirection(QBoxLayout::Direction::RightToLeft);
this->rightPinLayout = new QVBoxLayout();
this->rightPinLayout->setSpacing(QuadFlatPackageWidget::PIN_WIDGET_SPACING);
this->rightPinLayout->setDirection(QBoxLayout::Direction::BottomToTop);
this->bottomPinLayout = new QHBoxLayout();
this->bottomPinLayout->setSpacing(QuadFlatPackageWidget::PIN_WIDGET_SPACING);
this->bottomPinLayout->setDirection(QBoxLayout::Direction::LeftToRight);
this->leftPinLayout = new QVBoxLayout();
this->leftPinLayout->setSpacing(QuadFlatPackageWidget::PIN_WIDGET_SPACING);
this->leftPinLayout->setDirection(QBoxLayout::Direction::TopToBottom);
auto insightWindow = qobject_cast<InsightWindow*>(insightWindowObj);
assert(insightWindow != nullptr);
auto pinCountPerLayout = (targetVariant.pinDescriptorsByNumber.size() / 4);
for (const auto& [targetPinNumber, targetPinDescriptor]: targetVariant.pinDescriptorsByNumber) {
auto pinWidget = new PinWidget(this, targetPinDescriptor, targetVariant);
this->pinWidgets.push_back(pinWidget);
if (targetPinNumber <= pinCountPerLayout) {
this->leftPinLayout->addWidget(pinWidget, 0, Qt::AlignmentFlag::AlignRight);
} else if (targetPinNumber > pinCountPerLayout && targetPinNumber <= (pinCountPerLayout * 2)) {
this->bottomPinLayout->addWidget(pinWidget, 0, Qt::AlignmentFlag::AlignTop);
} else if (targetPinNumber > (pinCountPerLayout * 2) && targetPinNumber <= (pinCountPerLayout * 3)) {
this->rightPinLayout->addWidget(pinWidget, 0, Qt::AlignmentFlag::AlignLeft);
} else if (targetPinNumber > (pinCountPerLayout * 3) && targetPinNumber <= (pinCountPerLayout * 4)) {
this->topPinLayout->addWidget(pinWidget, 0, Qt::AlignmentFlag::AlignBottom);
}
connect(pinWidget, &TargetPinWidget::toggleIoState, insightWindow, &InsightWindow::togglePinIoState);
}
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);
auto insightWindowWidget = this->window();
assert(insightWindowWidget != nullptr);
insightWindowWidget->setMinimumHeight(
std::max(
500,
static_cast<int>((PinWidget::MAXIMUM_HORIZONTAL_HEIGHT * pinCountPerLayout)
+ (PinWidget::MAXIMUM_VERTICAL_HEIGHT * 2)) + 300
)
);
insightWindowWidget->setMinimumWidth(
std::max(
1000,
static_cast<int>((PinWidget::MAXIMUM_VERTICAL_WIDTH * pinCountPerLayout)
+ (PinWidget::MAXIMUM_VERTICAL_WIDTH * 2)) + 300
)
);
}
void QuadFlatPackageWidget::paintEvent(QPaintEvent* event) {
auto painter = QPainter(this);
this->drawWidget(painter);
}
void QuadFlatPackageWidget::drawWidget(QPainter& painter) {
auto parentWidget = this->parentWidget();
assert(parentWidget != nullptr);
auto parentContainerHeight = parentWidget->height();
auto parentContainerWidth = parentWidget->width();
auto verticalPinWidgetHeight = PinWidget::MAXIMUM_VERTICAL_HEIGHT;
auto verticalPinWidgetWidth = PinWidget::MAXIMUM_VERTICAL_WIDTH;
auto horizontalPinWidgetHeight = PinWidget::MAXIMUM_HORIZONTAL_HEIGHT;
auto horizontalPinWidgetWidth = PinWidget::MAXIMUM_HORIZONTAL_WIDTH;
auto pinCountPerLayout = static_cast<int>(this->pinWidgets.size() / 4);
/*
* 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.
*/
auto horizontalLayoutHeight = ((horizontalPinWidgetHeight + QuadFlatPackageWidget::PIN_WIDGET_SPACING) * pinCountPerLayout
+ QuadFlatPackageWidget::PIN_WIDGET_LAYOUT_PADDING - QuadFlatPackageWidget::PIN_WIDGET_SPACING);
auto verticalLayoutWidth = ((verticalPinWidgetWidth + QuadFlatPackageWidget::PIN_WIDGET_SPACING) * pinCountPerLayout
+ QuadFlatPackageWidget::PIN_WIDGET_LAYOUT_PADDING - QuadFlatPackageWidget::PIN_WIDGET_SPACING);
auto containerWidth = verticalLayoutWidth + (horizontalPinWidgetWidth * 2);
this->topPinLayout->setGeometry(QRect(
horizontalPinWidgetWidth,
0,
verticalLayoutWidth,
verticalPinWidgetHeight
));
this->horizontalLayout->setGeometry(QRect(
0,
verticalPinWidgetHeight,
containerWidth,
horizontalLayoutHeight
));
this->leftPinLayout->setGeometry(QRect(
0,
verticalPinWidgetHeight,
horizontalPinWidgetWidth,
horizontalLayoutHeight
));
this->bodyWidget->setGeometry(QRect(
horizontalPinWidgetWidth,
verticalPinWidgetHeight,
horizontalLayoutHeight,
horizontalLayoutHeight
));
this->rightPinLayout->setGeometry(QRect(
horizontalLayoutHeight + horizontalPinWidgetWidth,
verticalPinWidgetHeight,
horizontalPinWidgetWidth,
horizontalLayoutHeight
));
this->bottomPinLayout->setGeometry(QRect(
horizontalPinWidgetWidth,
verticalPinWidgetHeight + horizontalLayoutHeight,
verticalLayoutWidth,
verticalPinWidgetHeight
));
auto pinWidgetLayoutMargin = QuadFlatPackageWidget::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
);
auto containerHeight = horizontalLayoutHeight + (verticalPinWidgetHeight * 2);
this->setGeometry(
(parentContainerWidth / 2) - (containerWidth / 2),
(parentContainerHeight / 2) - (containerHeight / 2),
containerWidth,
containerHeight
);
}

View File

@@ -0,0 +1,39 @@
#pragma once
#include <QWidget>
#include <vector>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include "../TargetPackageWidget.hpp"
#include "PinWidget.hpp"
#include "BodyWidget.hpp"
#include "src/Targets/TargetVariant.hpp"
namespace Bloom::Widgets::InsightTargetWidgets::Qfp
{
/**
* QuadFlatPackageWidget implements a custom Qt widget for Quad-flat package variants.
*/
class QuadFlatPackageWidget: public TargetPackageWidget
{
Q_OBJECT
private:
QVBoxLayout* layout = nullptr;
QHBoxLayout* horizontalLayout = nullptr;
QHBoxLayout* topPinLayout = nullptr;
QVBoxLayout* rightPinLayout = nullptr;
QHBoxLayout* bottomPinLayout = nullptr;
QVBoxLayout* leftPinLayout = nullptr;
BodyWidget* bodyWidget = nullptr;
protected:
void paintEvent(QPaintEvent* event) override;
void drawWidget(QPainter& painter);
public:
static const int PIN_WIDGET_LAYOUT_PADDING = 46;
static const int PIN_WIDGET_SPACING = 8;
QuadFlatPackageWidget(const Targets::TargetVariant& targetVariant, QObject* insightWindowObj, QWidget* parent);
};
}

View File

@@ -0,0 +1,30 @@
#target-pin-number,
#target-pin-number {
font-size: 14px;
}
#target-pin-name,
#target-pin-direction {
font-size: 11px;
}
#target-pin-name {
color: #a6a7aa;
}
#target-pin-direction {
color: #8a8a8d;
}
#target-pin-number {
}
#target-body {
qproperty-bodyColor: #A6A8AB;
qproperty-disableAlphaLevel: 100;
}
#target-pin-body {
qproperty-bodyColor: #A6A8AB;
qproperty-disableAlphaLevel: 100;
}

View File

@@ -0,0 +1,37 @@
#pragma once
#include <QWidget>
#include <utility>
#include <vector>
#include <map>
#include "TargetPinWidget.hpp"
#include "src/Targets/TargetVariant.hpp"
#include "src/Targets/TargetDescriptor.hpp"
namespace Bloom::Widgets::InsightTargetWidgets
{
/**
* Each custom target package widget should be derived from this class.
*/
class TargetPackageWidget: public QWidget
{
Q_OBJECT
protected:
Targets::TargetVariant targetVariant;
std::vector<TargetPinWidget*> pinWidgets;
public:
TargetPackageWidget(Targets::TargetVariant targetVariant, QObject* insightWindowObj, QWidget* parent):
QWidget(parent), targetVariant(std::move(targetVariant)) {};
virtual void updatePinStates(std::map<int, Targets::TargetPinState> pinStatesByNumber) {
for (auto& pinWidget : this->pinWidgets) {
auto pinNumber = pinWidget->getPinNumber();
if (pinStatesByNumber.contains(pinNumber)) {
pinWidget->updatePinState(pinStatesByNumber.at(pinNumber));
}
}
}
};
}

View File

@@ -0,0 +1,69 @@
#pragma once
#include <QWidget>
#include <utility>
#include "src/Targets/TargetVariant.hpp"
#include "src/Targets/TargetPinDescriptor.hpp"
namespace Bloom::Widgets::InsightTargetWidgets
{
class TargetPinWidget: public QWidget
{
Q_OBJECT
protected:
Targets::TargetVariant targetVariant;
Targets::TargetPinDescriptor pinDescriptor;
std::optional<Targets::TargetPinState> pinState;
bool pinStateChanged = false;
public:
TargetPinWidget(
QWidget* parent,
Targets::TargetPinDescriptor pinDescriptor,
Targets::TargetVariant targetVariant
): QWidget(parent), targetVariant(std::move(targetVariant)), pinDescriptor(std::move(pinDescriptor)) {
this->setDisabled(false);
};
int getPinNumber() const {
return this->pinDescriptor.number;
}
const Targets::TargetPinDescriptor& getPinDescriptor() const {
return this->pinDescriptor;
}
std::optional<Targets::TargetPinState> getPinState() const {
return this->pinState;
}
virtual void updatePinState(const Targets::TargetPinState& pinState) {
this->pinStateChanged = !this->pinState.has_value()
|| this->pinState->ioState != pinState.ioState
|| this->pinState->ioDirection != pinState.ioDirection;
this->pinState = pinState;
}
void setDisabled(bool disabled) {
if (pinDescriptor.type != Targets::TargetPinType::GND
&& pinDescriptor.type != Targets::TargetPinType::VCC
&& pinDescriptor.type != Targets::TargetPinType::UNKNOWN
) {
QWidget::setDisabled(disabled);
} else {
QWidget::setDisabled(true);
}
}
public slots:
void onWidgetBodyClicked() {
emit this->toggleIoState(this);
}
signals:
void toggleIoState(TargetPinWidget* pinWidget);
};
}