6#include <QCoreApplication>
10#include <QRegularExpression>
11#include <QSvgRenderer>
27QByteArray recoloredSegmentSvg(
const QByteArray &svgBytes,
const QColor &color)
29 static const QRegularExpression fillHex(QStringLiteral(
"fill:#[0-9a-fA-F]{6}"));
30 QString svg = QString::fromUtf8(svgBytes);
31 svg.replace(fillHex, QStringLiteral(
"fill:%1").arg(color.name()));
40 .type = ElementType::Display7,
41 .group = ElementGroup::Output,
44 .canChangeAppearance =
true,
47 .rotatesGraphic =
false,
49 static_assert(
validate(constraints));
54 meta.pixmapPath = []{
return QStringLiteral(
":/Components/Output/Counter/counter_on.svg"); };
55 meta.titleText = QT_TRANSLATE_NOOP(
"Display7",
"7-SEGMENT DISPLAY");
56 meta.translatedName = QT_TRANSLATE_NOOP(
"Display7",
"7-Segment Display");
57 meta.trContext =
"Display7";
58 meta.defaultAppearances = QStringList({
59 ":/Components/Output/Counter/counter_off.svg",
60 ":/Components/Output/Counter/counter_a.svg",
61 ":/Components/Output/Counter/counter_b.svg",
62 ":/Components/Output/Counter/counter_c.svg",
63 ":/Components/Output/Counter/counter_d.svg",
64 ":/Components/Output/Counter/counter_e.svg",
65 ":/Components/Output/Counter/counter_f.svg",
66 ":/Components/Output/Counter/counter_g.svg",
67 ":/Components/Output/Counter/counter_dp.svg",
96 Q_ASSERT(QCoreApplication::instance()->thread() == QThread::currentThread());
98 static QHash<QString, QVector<std::shared_ptr<QSvgRenderer>>> cache;
100 auto it = cache.find(resourcePath);
101 if (it != cache.end()) {
105 QFile file(resourcePath);
106 const QByteArray svgBytes = file.open(QIODevice::ReadOnly) ? file.readAll() : QByteArray();
109 static const QColor colors[] = {
110 QColor(255, 255, 255), QColor(255, 0, 0), QColor(0, 255, 0), QColor(0, 0, 255), QColor(255, 0, 255)
113 QVector<std::shared_ptr<QSvgRenderer>> renderers;
114 renderers.reserve(5);
115 for (
const QColor &
color : colors) {
116 renderers.append(std::make_shared<QSvgRenderer>(recoloredSegmentSvg(svgBytes,
color)));
119 cache.insert(resourcePath, renderers);
133 if (
auto *port =
inputPort(0)) { port->setPos( 0, 8); port->setName(
"G (" + tr(
"middle") +
")"); }
134 if (
auto *port =
inputPort(1)) { port->setPos( 0, 24); port->setName(
"F (" + tr(
"upper left") +
")"); }
135 if (
auto *port =
inputPort(2)) { port->setPos( 0, 40); port->setName(
"E (" + tr(
"lower left") +
")"); }
136 if (
auto *port =
inputPort(3)) { port->setPos( 0, 56); port->setName(
"D (" + tr(
"bottom") +
")"); }
137 if (
auto *port =
inputPort(4)) { port->setPos(64, 8); port->setName(
"A (" + tr(
"top") +
")"); }
138 if (
auto *port =
inputPort(5)) { port->setPos(64, 24); port->setName(
"B (" + tr(
"upper right") +
")"); }
139 if (
auto *port =
inputPort(6)) { port->setPos(64, 40); port->setName(
"DP (" + tr(
"dot") +
")"); }
140 if (
auto *port =
inputPort(7)) { port->setPos(64, 56); port->setName(
"C (" + tr(
"lower right") +
")"); }
142 for (
auto *in :
inputs()) {
144 in->setRequired(
false);
145 in->setDefaultStatus(Status::Inactive);
153void Display7::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget)
160 const QRectF body(0, 0, 64, 64);
161 if (
auto *port =
inputPort(0); port && port->
status() == Status::Active) { g.at(m_colorNumber)->render(painter, body); }
162 if (
auto *port =
inputPort(1); port && port->
status() == Status::Active) { f.at(m_colorNumber)->render(painter, body); }
163 if (
auto *port =
inputPort(2); port && port->
status() == Status::Active) { e.at(m_colorNumber)->render(painter, body); }
164 if (
auto *port =
inputPort(3); port && port->
status() == Status::Active) { d.at(m_colorNumber)->render(painter, body); }
165 if (
auto *port =
inputPort(4); port && port->
status() == Status::Active) { a.at(m_colorNumber)->render(painter, body); }
166 if (
auto *port =
inputPort(5); port && port->
status() == Status::Active) { b.at(m_colorNumber)->render(painter, body); }
167 if (
auto *port =
inputPort(6); port && port->
status() == Status::Active) { dp.at(m_colorNumber)->render(painter, body); }
168 if (
auto *port =
inputPort(7); port && port->
status() == Status::Active) { c.at(m_colorNumber)->render(painter, body); }
186 QMap<QString, QVariant> map;
190 map.insert(
"color",
color());
211 qCDebug(zero) <<
"Remapping inputs.";
212 QVector<int> order{2, 1, 4, 5, 0, 7, 3, 6};
213 QVector<InputPort *> aux =
inputs();
215 if (aux.size() == order.size()) {
216 for (
int i = 0; i < aux.size(); ++i) {
217 aux[order[i]] =
inputs().value(i);
227 qCDebug(zero) <<
"Remapping inputs.";
228 QVector<int> order{2, 5, 4, 0, 7, 3, 6, 1};
229 QVector<InputPort *> aux =
inputs();
231 if (aux.size() == order.size()) {
232 for (
int i = 0; i < aux.size(); ++i) {
233 aux[order[i]] =
inputs().value(i);
250 if (map.contains(
"color")) {
251 setColor(map.value(
"color").toString());
Common logging utilities, the Pandaception error type, and helper macros.
#define qCDebug(category)
Graphic element for the 7-segment LED display.
Singleton factory for all circuit element types.
Self-registering element trait template and compile-time constraint validation.
ElementMetadata metadataFromConstraints(const ElementConstraints &c)
Converts ElementConstraints to an ElementMetadata with all constraint-derived fields set.
constexpr bool validate(const ElementConstraints &c)
Validates element constraints at compile time.
Enums::ElementType ElementType
Port classes: Port (base), InputPort, and OutputPort.
Deserialization/serialization context structs passed through load()/save() call chains.
Circuit and waveform file serialization/deserialization utilities.
Named version predicates for file-format compatibility checks.
7-segment LED display output element (7 segments + decimal point = 8 inputs).
QString color() const override
Returns the current display color name.
void load(QDataStream &stream, SerializationContext &context) override
void save(QDataStream &stream, SerializationOptions options) const override
Serializes the color selection to stream.
void updatePortsProperties() override
Updates port positions (fixed at 8 inputs).
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
void refresh() override
Refreshes the displayed segments based on current input states.
static constexpr const char * kDefaultColor
static QVector< std::shared_ptr< QSvgRenderer > > cachedSegmentRenderers(const QString &resourcePath)
Display7(QGraphicsItem *parent=nullptr)
Constructs the element with optional parent.
void setColor(const QString &color) override
Sets the display color.
static void registerCreator(ElementType type, std::function< GraphicElement *()> creator)
Registers a creator lambda for type, used by buildElement().
GraphicElement(ElementType type, QGraphicsItem *parent=nullptr)
Constructs a graphic element of the given type, fetching all properties from the metadata registry.
ElementAppearance m_appearance
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override
Paints the element onto the scene.
virtual void load(QDataStream &stream, SerializationContext &context)
Loads the graphic element through a binary data stream.
InputPort * inputPort(const int index=0) const
Returns the input port at index (default 0).
void setInputs(const QVector< InputPort * > &inputs)
Replaces the input port vector with inputs.
static int colorNameToIndex(const QString &color)
Maps a color name ("White","Red","Green","Blue","Purple") to indices 0–4.
virtual void save(QDataStream &stream, SerializationOptions options) const
const QVector< InputPort * > & inputs() const
Returns a const reference to the vector of all input ports.
Status status() const
Returns the current logical status (Active/Inactive/Unknown/Error).
static QString readBoundedString(QDataStream &stream)
Reads a QString from stream, refusing to allocate more bytes than remain in the stream (prevents OOM ...
static QMap< QString, QVariant > readBoundedMetadata(QDataStream &stream)
Reads the file-level metadata QMap<QString,QVariant> from stream without calling QList::reserve() wit...
bool hasLockState(const QVersionNumber &v)
V3.1: Lock state for input elements; color for some display/button types.
bool hasQMapFormat(const QVersionNumber &v)
V4.1: Format changed from flat binary to keyed QMap; port serial IDs; rotation fix.
bool hasDisplay7Color(const QVersionNumber &v)
V1.6: Display7 first color support.
bool hasDisplay7ExtColor(const QVersionNumber &v)
V1.7: Display7 additional color support.
Compile-time-validatable subset of ElementMetadata.
static ElementMetadata metadata()
static constexpr ElementConstraints constraints
static const bool registered
Self-registering element information trait.
Bundles all per-deserialization state so that load() overrides receive it through one explicit parame...
QVersionNumber version
File-format version read from the stream header.
Options passed to GraphicElement::save() (and friends); the save-side counterpart of SerializationCon...
SerializationPurpose purpose
What this serialization is for; see SerializationPurpose. Mandatory, no default.