From 179024325e257919148fa001f865964d2d938ed8 Mon Sep 17 00:00:00 2001 From: afaina Date: Wed, 20 Jul 2022 14:52:21 +0200 Subject: [PATCH 01/16] fixes bug in macOS when the darkMode is active. In that case, the text of the multimeters changes to white and it is impossible to see. --- src/simulation/simulator.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/simulation/simulator.cpp b/src/simulation/simulator.cpp index b434b2dc1..0bc98858b 100644 --- a/src/simulation/simulator.cpp +++ b/src/simulation/simulator.cpp @@ -457,8 +457,10 @@ void Simulator::updateMultimeterScreen(ItemBase * multimeter, QString msg){ QGraphicsTextItem * schScreen = new QGraphicsTextItem(msg, multimeter); schScreen->setPos(QPointF(10,10)); schScreen->setZValue(std::numeric_limits::max()); + schScreen->setDefaultTextColor(QColor("black")); QFont font("Segment16C", 10, QFont::Normal); bbScreen->setFont(font); + bbScreen->setDefaultTextColor(QColor("black")); //There are issues as the size of the text changes depending on the display settings in windows //This hack scales the text to match the appropiate value QRectF bbMultBoundingBox = m_sch2bbItemHash.value(multimeter)->boundingRect(); From b0f581fe88ddc37bd8b0156e68b07a2f1fa77243 Mon Sep 17 00:00:00 2001 From: afaina Date: Thu, 21 Jul 2022 09:54:01 +0200 Subject: [PATCH 02/16] Center the smoke coming out of the parts (bottom right corner of the smoke at the center of the part) and scale it for big parts --- src/simulation/simulator.cpp | 40 +++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/simulation/simulator.cpp b/src/simulation/simulator.cpp index 0bc98858b..3ee27077a 100644 --- a/src/simulation/simulator.cpp +++ b/src/simulation/simulator.cpp @@ -414,6 +414,44 @@ void Simulator::drawSmoke(ItemBase* part) { bbSmoke->setZValue(std::numeric_limits::max()); bbSmoke->setOpacity(0.7); schSmoke->setOpacity(0.7); + + //Scale the smoke images + QRectF bbPartBoundingBox = m_sch2bbItemHash.value(part)->boundingRectWithoutLegs(); + QRectF schSmokeBoundingBox = schSmoke->boundingRect(); + QRectF schPartBoundingBox = part->boundingRect(); + QRectF bbSmokeBoundingBox = bbSmoke->boundingRect(); + std::cout << "bbSmokeBoundingBox w and h: " << bbSmokeBoundingBox.width() << " " << bbSmokeBoundingBox.height() << std::endl; + + double scaleWidth = bbPartBoundingBox.width()/schSmokeBoundingBox.width(); + double scaleHeight = bbPartBoundingBox.height()/schSmokeBoundingBox.height(); + double scale; + (scaleWidth < scaleHeight) ? scale = scaleWidth : scale = scaleHeight; + if (scale > 1) { + //we can scale the smoke + bbSmoke->setScale(scale); + }else{ + scale = 1; //Do not scale down the smoke + } + + //Center the smoke in bb (bottom right corner of the smoke at the center of the part) + bbSmoke->setPos(QPointF(bbPartBoundingBox.width()/2-bbSmokeBoundingBox.width()*scale, + bbPartBoundingBox.height()/2-bbSmokeBoundingBox.height()*scale)); + + //Scale sch image + scaleWidth = schPartBoundingBox.width()/schSmokeBoundingBox.width(); + scaleHeight = schPartBoundingBox.height()/schSmokeBoundingBox.height(); + (scaleWidth < scaleHeight) ? scale = scaleWidth : scale = scaleHeight; + if (scale > 1) { + //we can scale the smoke + schSmoke->setScale(scale); + }else{ + scale = 1; //Do not scale down the smoke + } + + //Center the smoke in sch view (bottom right corner of the smoke at the center of the part) + schSmoke->setPos(QPointF(schPartBoundingBox.width()/2-schSmokeBoundingBox.width()*scale, + schPartBoundingBox.height()/2-schSmokeBoundingBox.height()*scale)); + part->addSimulationGraphicsItem(schSmoke); m_sch2bbItemHash.value(part)->addSimulationGraphicsItem(bbSmoke); } @@ -472,7 +510,7 @@ void Simulator::updateMultimeterScreen(ItemBase * multimeter, QString msg){ bbScreen->setScale((0.8*bbMultBoundingBox.width())/bbBoundingBox.width()); schScreen->setScale((0.5*schMultBoundingBox.width())/schBoundingBox.width()); - //Update the boundiong box after scaling them + //Update the bounding box after scaling them bbBoundingBox = bbScreen->mapRectToParent(bbScreen->boundingRect()); schBoundingBox = schScreen->mapRectToParent(schScreen->boundingRect()); From 445a1c38fc43680de10f76be7604801e8caeb824 Mon Sep 17 00:00:00 2001 From: afaina Date: Thu, 21 Jul 2022 10:38:20 +0200 Subject: [PATCH 03/16] fixes light of the LED, centered at the LED and do not take the legs of the LED into account --- src/items/led.h | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/items/led.h b/src/items/led.h index 3753c039b..8d5932bbf 100644 --- a/src/items/led.h +++ b/src/items/led.h @@ -39,19 +39,22 @@ class LedLight : public QGraphicsEllipseItem { void setLight(double brightness, int red, int green, int blue){ if (brightness < 0.15) brightness = 0.0; - double radious = std::min(parentItem()->boundingRect().width()/2, - parentItem()->boundingRect().height()/2) * brightness * 4; - prepareGeometryChange(); - setRect(-radious + parentItem()->boundingRect().width()/2, - -radious + parentItem()->boundingRect().width()/5, - radious*2, radious*2); - QRadialGradient gradient = QRadialGradient(0.5, 0.5, 0.5); - gradient.setCoordinateMode(QGradient::ObjectBoundingMode); - gradient.setColorAt(0, QColor(red, green, blue, 255)); - gradient.setColorAt(0.3, QColor(red, green, blue, 230)); - gradient.setColorAt(1, QColor(red, green, blue, 0)); - setBrush(gradient); - this->show(); + Capacitor* led = dynamic_cast(parentItem()); + if (led) { + double radious = std::min(led->boundingRectWithoutLegs().width()/2, + led->boundingRectWithoutLegs().height()/2) * brightness * 4; + prepareGeometryChange(); + setRect(-radious + led->boundingRectWithoutLegs().width()/2, + -radious + led->boundingRectWithoutLegs().width()/2, + radious*2, radious*2); + QRadialGradient gradient = QRadialGradient(0.5, 0.5, 0.5); + gradient.setCoordinateMode(QGradient::ObjectBoundingMode); + gradient.setColorAt(0, QColor(red, green, blue, 255)); + gradient.setColorAt(0.3, QColor(red, green, blue, 230)); + gradient.setColorAt(1, QColor(red, green, blue, 0)); + setBrush(gradient); + this->show(); + } }; }; From 36769b067c20f3574e2b2b365ce30b7871128155 Mon Sep 17 00:00:00 2001 From: afaina Date: Thu, 21 Jul 2022 10:56:56 +0200 Subject: [PATCH 04/16] make LED light and color more noticeable at low currents --- src/items/led.cpp | 9 ++++++--- src/items/led.h | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/items/led.cpp b/src/items/led.cpp index 01d4eb478..7069bc4eb 100644 --- a/src/items/led.cpp +++ b/src/items/led.cpp @@ -183,9 +183,12 @@ void LED::setBrightness(double brightness){ if (brightness < 0) brightness = 0; //Find the new color values - red = offColor*red + brightness*red; - green = offColor*green + brightness*green; - blue = offColor*blue + brightness*blue; + //The color achives maximum intensity when brightness = 0.25 + double brightnessColor = brightness * 4.0; + if (brightnessColor > 1) brightnessColor = 1; + red = offColor*red + brightnessColor*red; + green = offColor*green + brightnessColor*green; + blue = offColor*blue + brightnessColor*blue; if(red > 255) red = 255; if(green > 255) green = 255; if(blue > 255) blue = 255; diff --git a/src/items/led.h b/src/items/led.h index 8d5932bbf..46864d536 100644 --- a/src/items/led.h +++ b/src/items/led.h @@ -37,7 +37,8 @@ class LedLight : public QGraphicsEllipseItem { ~LedLight() { }; void setLight(double brightness, int red, int green, int blue){ - if (brightness < 0.15) + //Only set light coming out if brightness is bigger than 0.25 + if (brightness < 0.25) brightness = 0.0; Capacitor* led = dynamic_cast(parentItem()); if (led) { From 534ad251c1542db6f99a53f788a8f5c8aacbe1fc Mon Sep 17 00:00:00 2001 From: afaina Date: Thu, 21 Jul 2022 12:16:01 +0200 Subject: [PATCH 05/16] improvements to the arrow image when the motor turns (scaled and centered) --- src/simulation/simulator.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/simulation/simulator.cpp b/src/simulation/simulator.cpp index 3ee27077a..f7edfe3af 100644 --- a/src/simulation/simulator.cpp +++ b/src/simulation/simulator.cpp @@ -1095,6 +1095,32 @@ void Simulator::updateDcMotor(ItemBase * part) { schRotate = new QGraphicsSvgItem(image, part); if (!bbRotate || !schRotate) return; + //Scale the smoke images + QRectF bbPartBoundingBox = m_sch2bbItemHash.value(part)->boundingRectWithoutLegs(); + QRectF schRotateBoundingBox = schRotate->boundingRect(); + QRectF schPartBoundingBox = part->boundingRect(); + QRectF bbRotateBoundingBox = bbRotate->boundingRect(); + + + double scaleWidth = bbPartBoundingBox.width()/bbRotateBoundingBox.width(); + double scaleHeight = bbPartBoundingBox.height()/bbRotateBoundingBox.height(); + double scale; + scale = std::max(scaleWidth, scaleHeight)*0.5; + bbRotate->setScale(scale); + + //Center the arrow in bb + bbRotate->setPos(QPointF(bbPartBoundingBox.width()/2-bbRotateBoundingBox.width()*scale/2, + bbPartBoundingBox.height()/2-bbRotateBoundingBox.height()*scale/2)); + + scaleWidth = schPartBoundingBox.width()/schRotateBoundingBox.width(); + scaleHeight = schPartBoundingBox.height()/schRotateBoundingBox.height(); + scale = std::max(scaleWidth, scaleHeight)*0.5; + schRotate->setScale(scale); + + //Center the arrow in bb + schRotate->setPos(QPointF(schPartBoundingBox.width()/2-schRotateBoundingBox.width()*scale/2, + schPartBoundingBox.height()/2-schRotateBoundingBox.height()*scale/2)); + schRotate->setZValue(std::numeric_limits::max()); bbRotate->setZValue(std::numeric_limits::max()); part->addSimulationGraphicsItem(schRotate); From 8596d33a4e86af7f3e65a579bccbf7ec1c46ebf2 Mon Sep 17 00:00:00 2001 From: afaina Date: Thu, 21 Jul 2022 15:45:13 +0200 Subject: [PATCH 06/16] show the main properties of the components after the family property in the Inspector pane --- src/items/capacitor.cpp | 13 +++++++++++++ src/items/capacitor.h | 1 + src/items/led.cpp | 11 +++++++++++ src/items/led.h | 1 + src/items/resistor.cpp | 15 +++++++++++++++ src/items/resistor.h | 1 + 6 files changed, 42 insertions(+) diff --git a/src/items/capacitor.cpp b/src/items/capacitor.cpp index c19b9cb06..f67376395 100644 --- a/src/items/capacitor.cpp +++ b/src/items/capacitor.cpp @@ -229,3 +229,16 @@ void Capacitor::getProperties(QHash & hash) { hash.insert(propertyDef->name, m_propertyDefs.value(propertyDef)); } } + +QHash Capacitor::prepareProps(ModelPart * modelPart, bool wantDebug, QStringList & keys) +{ + QHash props = ItemBase::prepareProps(modelPart, wantDebug, keys); + + // ensure capacitance and other properties are after family, if it is a capacitor; + if (keys.removeOne("capacitance")) { + keys.insert(1, "capacitance"); + if (keys.removeOne("voltage")) keys.insert(2, "voltage"); + } + + return props; +} diff --git a/src/items/capacitor.h b/src/items/capacitor.h index 5898b2353..b58e9e232 100644 --- a/src/items/capacitor.h +++ b/src/items/capacitor.h @@ -37,6 +37,7 @@ class Capacitor : public PaletteItem bool collectExtraInfo(QWidget * parent, const QString & family, const QString & prop, const QString & value, bool swappingEnabled, QString & returnProp, QString & returnValue, QWidget * & returnWidget, bool & hide); void setProp(const QString & prop, const QString & value); void getProperties(QHash &); + QHash prepareProps(ModelPart * modelPart, bool wantDebug, QStringList & keys); public slots: void textModified(QValidator::State state); diff --git a/src/items/led.cpp b/src/items/led.cpp index 7069bc4eb..d3c959972 100644 --- a/src/items/led.cpp +++ b/src/items/led.cpp @@ -262,3 +262,14 @@ ViewLayer::ViewID LED::useViewIDForPixmap(ViewLayer::ViewID vid, bool swappingEn return ItemBase::useViewIDForPixmap(vid, swappingEnabled); } + +QHash LED::prepareProps(ModelPart * modelPart, bool wantDebug, QStringList & keys) +{ + QHash props = ItemBase::prepareProps(modelPart, wantDebug, keys); + + // ensure color and other properties are after family; + if (keys.removeOne("color")) keys.insert(1, "color"); + if (keys.removeOne("current")) keys.insert(2, "current"); + + return props; +} diff --git a/src/items/led.h b/src/items/led.h index 46864d536..f6b23a201 100644 --- a/src/items/led.h +++ b/src/items/led.h @@ -82,6 +82,7 @@ class LED : public Capacitor ViewLayer::ViewID useViewIDForPixmap(ViewLayer::ViewID, bool swappingEnabled); void setBrightness(double); void resetBrightness(); + QHash prepareProps(ModelPart * modelPart, bool wantDebug, QStringList & keys); protected: void setColor(const QString & color); diff --git a/src/items/resistor.cpp b/src/items/resistor.cpp index 69afc954f..a47a7d526 100644 --- a/src/items/resistor.cpp +++ b/src/items/resistor.cpp @@ -414,3 +414,18 @@ ViewLayer::ViewID Resistor::useViewIDForPixmap(ViewLayer::ViewID vid, bool swapp return ItemBase::useViewIDForPixmap(vid, swappingEnabled); } + +QHash Resistor::prepareProps(ModelPart * modelPart, bool wantDebug, QStringList & keys) +{ + QHash props = ItemBase::prepareProps(modelPart, wantDebug, keys); + + // ensure resistance and other properties are after family; + if (keys.removeOne("resistance")) + keys.insert(1, "resistance"); + if (keys.removeOne("tolerance")) + keys.insert(2, "tolerance"); + if (keys.removeOne("power")) + keys.insert(3, "power"); + + return props; +} diff --git a/src/items/resistor.h b/src/items/resistor.h index 6b3072f2a..c9b9e7190 100644 --- a/src/items/resistor.h +++ b/src/items/resistor.h @@ -50,6 +50,7 @@ class Resistor : public Capacitor void addedToScene(bool temporary); void setProp(const QString & prop, const QString & value); bool setUpImage(ModelPart* modelPart, const LayerHash & viewLayers, LayerAttributes &); + QHash prepareProps(ModelPart * modelPart, bool wantDebug, QStringList & keys); protected: QString makeSvg(const QString & ohms, ViewLayer::ViewLayerID viewLayerID); From 090c9e8fec4213b4e17478902a8d63c43707e135 Mon Sep 17 00:00:00 2001 From: afaina Date: Sun, 24 Jul 2022 22:36:21 +0200 Subject: [PATCH 07/16] make spice field and tags selectable (and able to copy them) --- src/infoview/htmlinfoview.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/infoview/htmlinfoview.cpp b/src/infoview/htmlinfoview.cpp index d7e5c7b68..a33815c7a 100644 --- a/src/infoview/htmlinfoview.cpp +++ b/src/infoview/htmlinfoview.cpp @@ -285,6 +285,7 @@ void HtmlInfoView::init(bool tinyMode) { m_spiceTextLabel = new TagLabel(this); m_spiceTextLabel->setWordWrap(true); m_spiceTextLabel->setObjectName("tagsValue"); + m_spiceTextLabel->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse); vlo->addWidget(m_spiceTextLabel); m_tagLabel = new QLabel(tr("Tags"), NULL); @@ -295,6 +296,7 @@ void HtmlInfoView::init(bool tinyMode) { m_tagsTextLabel = new TagLabel(this); m_tagsTextLabel->setWordWrap(true); m_tagsTextLabel->setObjectName("tagsValue"); + m_tagsTextLabel->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse); vlo->addWidget(m_tagsTextLabel); if (tinyMode) m_tagsTextLabel->setVisible(false); From ba67d05f83869a629efa7afc783617c6eab91533 Mon Sep 17 00:00:00 2001 From: afaina Date: Mon, 25 Jul 2022 21:45:36 +0200 Subject: [PATCH 08/16] code to handle RGB leds --- src/items/led.cpp | 82 +++++++++++++++++++++++++++++++----- src/items/led.h | 6 +++ src/simulation/simulator.cpp | 45 +++++++++++++++----- 3 files changed, 111 insertions(+), 22 deletions(-) diff --git a/src/items/led.cpp b/src/items/led.cpp index d3c959972..320305121 100644 --- a/src/items/led.cpp +++ b/src/items/led.cpp @@ -62,7 +62,10 @@ QString LED::retrieveSvg(ViewLayer::ViewLayerID viewLayerID, QHashscene()) { + //Check if this an RGB led + QString rgbString = this->getProperty("rgb"); + if (this->scene() && rgbString.isEmpty()) { + //Set the color for the LED, does not apply if is is an RGB led setColor(prop("color")); } @@ -140,7 +143,7 @@ void LED::setColor(const QString & color) * @brief Restores the original brightness of an LED. */ void LED::resetBrightness() { - setBrightness(1-offColor); + setBrightness((1-offColor)/brigtnessMultiplier); if(m_ledLight && this->viewID()==ViewLayer::ViewID::BreadboardView) { m_ledLight->hide(); } @@ -155,7 +158,7 @@ void LED::resetBrightness() { * @brief Changes the brightness of an LED. * @param[in] brightness The brightness value, its range is from 0 (off) to 1 (on) */ -void LED::setBrightness(double brightness){ +void LED::setBrightness(double brightness) { QString errorStr; int errorLine; int errorColumn; @@ -166,14 +169,21 @@ void LED::setBrightness(double brightness){ //get the color of the LED QString colorString; - QString color = prop("color"); - foreach (PropertyDef * propertyDef, m_propertyDefs.keys()) { - if (propertyDef->name.compare("color") == 0) { - colorString = propertyDef->adjuncts.value(color, ""); - break; + QString rgbString = this->getProperty("rgb"); + if (rgbString.isEmpty()) { + //If it is just one LED, use color property + QString color = prop("color"); + foreach (PropertyDef * propertyDef, m_propertyDefs.keys()) { + if (propertyDef->name.compare("color") == 0) { + colorString = propertyDef->adjuncts.value(color, ""); + break; + } } + if (colorString.isEmpty()) return; + } else { + // It is an RGB led, set color to grey + colorString = "#E6E6E6"; } - if (colorString.isEmpty()) return; int red = colorString.mid(1,2).toInt(nullptr, 16); int green = colorString.mid(3,2).toInt(nullptr, 16); @@ -183,8 +193,8 @@ void LED::setBrightness(double brightness){ if (brightness < 0) brightness = 0; //Find the new color values - //The color achives maximum intensity when brightness = 0.25 - double brightnessColor = brightness * 4.0; + //The color achives maximum intensity when brightness = 1/brigtnessMultiplier + double brightnessColor = brightness * brigtnessMultiplier; if (brightnessColor > 1) brightnessColor = 1; red = offColor*red + brightnessColor*red; green = offColor*green + brightnessColor*green; @@ -213,6 +223,56 @@ void LED::setBrightness(double brightness){ } } +/** + * Changes the brightness of an RGB LED based on 3 brightness parameters. + * A brightness of 0 reduces scales the color to 30% of the color. + * + * @brief Changes the brightness of an RGB LED. + * @param[in] brightness The brightness values, its range is from 0 (off) to 1 (on) + */ +void LED::setBrightnessRGB(double brightnessR, double brightnessG, double brightnessB) { + QString errorStr; + int errorLine; + int errorColumn; + QDomDocument domDocument; + if (!domDocument.setContent( BreadboardSvg.value(m_filename), &errorStr, &errorLine, &errorColumn)) { + return; + } + + //The color achives maximum intensity when brightness = 0.25 + int red = 40 + (brightnessR * brigtnessMultiplier * 200.0); + int green = 40 + (brightnessG * brigtnessMultiplier * 200.0); + int blue = 40 + (brightnessB * brigtnessMultiplier * 200.0); + double brightness = std::max({brightnessR, brightnessG, brightnessB}); + + int maxColor = 230; //Do not saturate the colors + if (red > 255) red = maxColor; + if (red < 0) red = 0; + if (green > 255) green = maxColor; + if (green < 0) green = 0; + if (blue > 255) blue = maxColor; + if (blue < 0) blue = 0; + + QString newColorStr = QString("#%1%2%3") + .arg(red, 2, 16) + .arg(green, 2, 16) + .arg(blue, 2, 16); + newColorStr.replace(' ', '0'); + + //Change the color of the LED + QDomElement root = domDocument.documentElement(); + slamColor(root, newColorStr); + reloadRenderer(domDocument.toString(),true); + + //Add light comming out of the LED in BreadboardView + if(this->viewID()==ViewLayer::ViewID::BreadboardView) { + if(!m_ledLight) { + m_ledLight = new LedLight(this); + } + m_ledLight->setLight(brightness, red, green, blue); + } +} + QString LED::getColorSVG(const QString & color, ViewLayer::ViewLayerID viewLayerID) { QString errorStr; diff --git a/src/items/led.h b/src/items/led.h index f6b23a201..7559ceaea 100644 --- a/src/items/led.h +++ b/src/items/led.h @@ -66,6 +66,11 @@ class LED : public Capacitor //The color that remains when the brightness is set to 0 static constexpr double offColor = 0.3; + //The maximum color is achived when brigtness*brigtnessMultiplier=1 + //After that, more current increases the light comming out of the LED, + //but it does not change the color + static constexpr double brigtnessMultiplier = 4.0; + public: // after calling this constructor if you want to render the loaded svg (either from model or from file), MUST call LED(ModelPart *, ViewLayer::ViewID, const ViewGeometry & viewGeometry, long id, QMenu * itemMenu, bool doLabel); @@ -81,6 +86,7 @@ class LED : public Capacitor const QString & title(); ViewLayer::ViewID useViewIDForPixmap(ViewLayer::ViewID, bool swappingEnabled); void setBrightness(double); + void setBrightnessRGB(double brightnessR, double brightnessG, double brightnessB); void resetBrightness(); QHash prepareProps(ModelPart * modelPart, bool wantDebug, QStringList & keys); diff --git a/src/simulation/simulator.cpp b/src/simulation/simulator.cpp index f7edfe3af..6984b4bbb 100644 --- a/src/simulation/simulator.cpp +++ b/src/simulation/simulator.cpp @@ -911,17 +911,40 @@ void Simulator::updateDiode(ItemBase * diode) { void Simulator::updateLED(ItemBase * part) { LED* led = dynamic_cast(part); if (led) { - double curr = getCurrent(part); - double maxCurr = getMaxPropValue(part, "current"); - - std::cout << "LED Current: " <(m_sch2bbItemHash.value(part)); - bbLed->setBrightness(curr/maxCurr); - if (curr > maxCurr) { - drawSmoke(part); - bbLed->setBrightness(0); + //Check if this an RGB led + QString rgbString = part->getProperty("rgb"); + + if (rgbString.isEmpty()) { + // Just one LED + double curr = getCurrent(part); + double maxCurr = getMaxPropValue(part, "current"); + + std::cout << "LED Current: " <(m_sch2bbItemHash.value(part)); + bbLed->setBrightness(curr/maxCurr); + if (curr > maxCurr) { + drawSmoke(part); + bbLed->setBrightness(0); + } + } else { + // The part is an RGB LED + double currR = getCurrent(part, "R"); + double currG = getCurrent(part, "G"); + double currB = getCurrent(part, "B"); + double curr = std::max({currR, currG, currB}); + double maxCurr = getMaxPropValue(part, "current"); + + std::cout << "LED Current (R, G, B): " << currR << " " << currG << " " << currB <(m_sch2bbItemHash.value(part)); + bbLed->setBrightnessRGB(currR/maxCurr, currG/maxCurr, currB/maxCurr); + if (curr > maxCurr) { + drawSmoke(part); + bbLed->setBrightness(0); + } } } else { //It is probably an LED display (LED matrix) From 87905debfe2bdb9ce6a7d4caeddc223538f492cf Mon Sep 17 00:00:00 2001 From: afaina Date: Tue, 26 Jul 2022 13:51:11 +0200 Subject: [PATCH 09/16] fix issue when symbols contain character "x" --- src/utils/boundedregexpvalidator.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utils/boundedregexpvalidator.h b/src/utils/boundedregexpvalidator.h index 1bd27924e..1360f44e2 100644 --- a/src/utils/boundedregexpvalidator.h +++ b/src/utils/boundedregexpvalidator.h @@ -61,9 +61,10 @@ class BoundedRegExpValidator : public QRegExpValidator QValidator::State validate ( QString & input, int & pos ) const override { QValidator::State state = QRegExpValidator::validate(input, pos); input.replace(m_symbol, ""); + + state = QRegExpValidator::validate(input, pos); if(!m_symbol.isEmpty()) input.append(m_symbol); - state = QRegExpValidator::validate(input, pos); if ( state == QValidator::Acceptable ) { double converted = m_converter(input, m_symbol); From 219baf25136ec8b92527897e6f3723a9dee8eb1b Mon Sep 17 00:00:00 2001 From: afaina Date: Tue, 26 Jul 2022 13:56:16 +0200 Subject: [PATCH 10/16] add code to be able to simulate photocells --- resources/properties.xml | 13 +++++++++++++ src/items/moduleidnames.cpp | 1 + src/items/moduleidnames.h | 1 + 3 files changed, 15 insertions(+) diff --git a/resources/properties.xml b/resources/properties.xml index f85d65b19..fdc24308a 100644 --- a/resources/properties.xml +++ b/resources/properties.xml @@ -276,6 +276,7 @@ + @@ -315,4 +316,16 @@ + + + + + + + + + + + + diff --git a/src/items/moduleidnames.cpp b/src/items/moduleidnames.cpp index 2da7b6396..aac1a5e8b 100644 --- a/src/items/moduleidnames.cpp +++ b/src/items/moduleidnames.cpp @@ -44,6 +44,7 @@ const QString ModuleIDNames::PowerLabelModuleIDName = "PowerLabelModuleID"; const QString ModuleIDNames::LeftNetLabelModuleIDName = "LeftNetLabelModuleID"; const QString ModuleIDNames::JustPowerModuleIDName = "JustPowerModuleID"; const QString ModuleIDNames::ResistorModuleIDName = "ResistorModuleID"; +const QString ModuleIDNames::PhotocellModuleIDName = "PhotocellModuleID"; const QString ModuleIDNames::LogoTextModuleIDName = "LogoTextModuleID"; const QString ModuleIDNames::LogoImageModuleIDName = "LogoImageModuleID"; const QString ModuleIDNames::Silkscreen0LogoImageModuleIDName = "Silkscreen0LogoImageModuleID"; diff --git a/src/items/moduleidnames.h b/src/items/moduleidnames.h index 1a49a3cc6..679f83c9a 100644 --- a/src/items/moduleidnames.h +++ b/src/items/moduleidnames.h @@ -46,6 +46,7 @@ class ModuleIDNames static const QString LeftNetLabelModuleIDName; static const QString JustPowerModuleIDName; static const QString ResistorModuleIDName; + static const QString PhotocellModuleIDName; static const QString LogoTextModuleIDName; static const QString LogoImageModuleIDName; static const QString Silkscreen0LogoImageModuleIDName; From 7da498293df3832cdbb0a60d553e8ccfedf53564 Mon Sep 17 00:00:00 2001 From: afaina Date: Wed, 27 Jul 2022 23:01:43 +0200 Subject: [PATCH 11/16] Make error message useful. Now, it specifies which SVG file is missing for that ModuleID. The message that shows this errors also specifies the name of the FPZ file. --- src/items/itembase.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/items/itembase.cpp b/src/items/itembase.cpp index e8165cee1..bad4e15cf 100644 --- a/src/items/itembase.cpp +++ b/src/items/itembase.cpp @@ -1303,7 +1303,8 @@ FSvgRenderer * ItemBase::setUpImage(ModelPart * modelPart, LayerAttributes & lay //DebugDialog::debug(QString("set up image elapsed (1) %1").arg(t.elapsed()) ); - QString filename = PartFactory::getSvgFilename(modelPart, modelPartShared->imageFileName(layerAttributes.viewID, layerAttributes.viewLayerID), true, true); + QString imageFilename = modelPartShared->imageFileName(layerAttributes.viewID, layerAttributes.viewLayerID); + QString filename = PartFactory::getSvgFilename(modelPart, imageFilename, true, true); //#ifndef QT_NO_DEBUG //DebugDialog::debug(QString("set up image elapsed (2) %1").arg(t.elapsed()) ); @@ -1311,7 +1312,7 @@ FSvgRenderer * ItemBase::setUpImage(ModelPart * modelPart, LayerAttributes & lay if (filename.isEmpty()) { //QString deleteme = modelPartShared->domDocument()->toString(); - layerAttributes.error = tr("file for %1 %2 not found").arg(modelPartShared->title()).arg(modelPartShared->moduleID()); + layerAttributes.error = tr("file %1 for %2 not found").arg(imageFilename).arg(modelPartShared->moduleID()); return nullptr; } From 8eaa2820301617d4f4659674f00f1c340b7c2b75 Mon Sep 17 00:00:00 2001 From: afaina Date: Mon, 1 Aug 2022 15:39:19 +0200 Subject: [PATCH 12/16] do not grey out net labels or power symbols. Remove parts to be grey out if instanceTitle is the same as the one being simulated (it looks like there are two ItemBase created for each part). --- src/simulation/simulator.cpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/simulation/simulator.cpp b/src/simulation/simulator.cpp index 6984b4bbb..6a3e59171 100644 --- a/src/simulation/simulator.cpp +++ b/src/simulation/simulator.cpp @@ -761,11 +761,17 @@ void Simulator::greyOutNonSimParts(const QSet& simParts) { QList noSimSchParts = m_schematicGraphicsView->scene()->items(); QList noSimBbParts = m_breadboardGraphicsView->scene()->items(); - //Remove the parts that are going to be simulated and the wires connected to them QList bbConnectors; foreach (ItemBase * part, simParts) { - noSimSchParts.removeAll(part); + foreach (QGraphicsItem * schItem, noSimSchParts) { + ItemBase * schPart = dynamic_cast(schItem); + if (!schPart) continue; + if (part->instanceTitle().compare(schPart->instanceTitle()) == 0) { + noSimSchParts.removeAll(schItem); + } + } + noSimBbParts.removeAll(m_sch2bbItemHash.value(part)); bbConnectors.append(m_sch2bbItemHash.value(part)->cachedConnectorItems()); @@ -810,7 +816,8 @@ void Simulator::greyOutParts(const QList & parts) { /** * Removes items that are being simulated but without spice lines. Basically, remove - * the wires and the breadboards, which are part of the simulation and leave the rest. + * the wires, breadboards, power symbols, etc. (which are part of the simulation) and + * leave the rest. * @param[in/out] parts A list of parts which will be filtered to remove parts that * are being simulated */ @@ -884,6 +891,19 @@ void Simulator::removeItemsToBeSimulated(QList & parts) { parts.removeAll(part); continue; } + + ItemBase* item = dynamic_cast(part); + if (!item) { + //We only remove the parts, we do not touch other elements of the scene (text of the net labels, etc.) + parts.removeAll(part); + } else { + if (item->family().compare("power label") == 0 + || item->family().compare("net label") == 0 + || item->family().compare("breadboard") == 0) //hack as half+ is not generated as breadboard object, see #3873 + { + parts.removeAll(part); + } + } } } From a999f12d77c27d8d91373d8f912a0d05773a9338 Mon Sep 17 00:00:00 2001 From: afaina Date: Mon, 1 Aug 2022 20:31:44 +0200 Subject: [PATCH 13/16] do not explode capacitors or IR sensors if voltage is negative but very low --- src/simulation/simulator.cpp | 5 +++-- src/simulation/simulator.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/simulation/simulator.cpp b/src/simulation/simulator.cpp index 6a3e59171..fc88411ac 100644 --- a/src/simulation/simulator.cpp +++ b/src/simulation/simulator.cpp @@ -1001,7 +1001,7 @@ void Simulator::updateCapacitor(ItemBase * part) { } } else { //This is an electrolytic o tantalum capacitor (polarized) - if (v > maxV/2 || v < 0) { + if (v > maxV/2 || v < HarmfulNegativeVoltage) { drawSmoke(part); } } @@ -1094,7 +1094,8 @@ void Simulator::updateIRSensor(ItemBase * part) { i = getCurrent(part, "a"); //voltage applied to the motor } std::cout << "IR sensor Max Iout: " << maxIout << ", current Iout " << i << std::endl; - if (v > maxV || v < 0 || abs(i) > maxIout) { + std::cout << "IR sensor Max V: " << maxV << ", current V " << v << std::endl; + if (v > maxV || v < HarmfulNegativeVoltage || abs(i) > maxIout) { drawSmoke(part); return; } diff --git a/src/simulation/simulator.h b/src/simulation/simulator.h index 52d6ece5c..774ec4eaf 100644 --- a/src/simulation/simulator.h +++ b/src/simulation/simulator.h @@ -95,6 +95,7 @@ public slots: QList* m_instanceTitleSim; QTimer *m_simTimer; static constexpr int SimDelay = 200; + static constexpr double HarmfulNegativeVoltage = -0.5; }; From ad59e648e78f5acd3df95f43e1db0eeb4500e2cd Mon Sep 17 00:00:00 2001 From: afaina Date: Mon, 1 Aug 2022 20:39:37 +0200 Subject: [PATCH 14/16] add reason for not simulate a part: No SPICE or not connected --- src/simulation/simulator.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/simulation/simulator.cpp b/src/simulation/simulator.cpp index fc88411ac..08871b96e 100644 --- a/src/simulation/simulator.cpp +++ b/src/simulation/simulator.cpp @@ -811,6 +811,42 @@ void Simulator::greyOutParts(const QList & parts) { QGraphicsColorizeEffect * schEffect = new QGraphicsColorizeEffect(); schEffect->setColor(QColor(100,100,100)); part->setGraphicsEffect(schEffect); + + //Add a reason for not simulate them + ItemBase* item = dynamic_cast(part); + if (item) { + QString msg = "NOT SIMULATED:"; + if (item->spice().isEmpty()) { + //There is no SPICE model + msg += "\nNO SPICE"; + } else { + msg += "\nNOT CONNECTED"; + } + QGraphicsTextItem * infoText = new QGraphicsTextItem(msg, part); + infoText->setZValue(std::numeric_limits::max()); + infoText->setDefaultTextColor(QColor("black")); + QFont font("OCRA", 4, QFont::Normal); + infoText->setFont(font); + + //There are issues as the size of the text changes depending on the display settings in windows + //This hack scales the text to match the appropiate value + QRectF partBoundingBox = item->boundingRectWithoutLegs(); + QRectF infoTextBoundingBox = infoText->boundingRect(); + + if (infoTextBoundingBox.width() > partBoundingBox.width()) { + //Scale down the text to 90% percent of the partsĀ“s width + double scale = partBoundingBox.width()/infoTextBoundingBox.width()*0.9; + infoText->setScale(scale); + } + + //Update the bounding box after scaling them + infoTextBoundingBox = infoText->mapRectToParent(infoText->boundingRect()); + + //Set text on top of part + infoText->setPos(QPointF(0,-infoTextBoundingBox.height())); + + item->addSimulationGraphicsItem(infoText); + } } } From 435f295c2c3fcdc21cb7043b64e3a65d9791456f Mon Sep 17 00:00:00 2001 From: afaina Date: Mon, 1 Aug 2022 20:45:45 +0200 Subject: [PATCH 15/16] increased time to trigguer the simulation. we hope to reduce random crahes when the simulator is active. --- src/simulation/simulator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simulation/simulator.h b/src/simulation/simulator.h index 774ec4eaf..359750682 100644 --- a/src/simulation/simulator.h +++ b/src/simulation/simulator.h @@ -94,7 +94,7 @@ public slots: QList* m_instanceTitleSim; QTimer *m_simTimer; - static constexpr int SimDelay = 200; + static constexpr int SimDelay = 400; static constexpr double HarmfulNegativeVoltage = -0.5; }; From 9f35f5083d73c1f06ced3454508ad279c4e6e5e1 Mon Sep 17 00:00:00 2001 From: afaina Date: Wed, 26 Apr 2023 14:47:26 +0200 Subject: [PATCH 16/16] show infinity in captal letters ("INF") in the multimeter --- src/simulation/simulator.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/simulation/simulator.cpp b/src/simulation/simulator.cpp index 08871b96e..d426dc30a 100644 --- a/src/simulation/simulator.cpp +++ b/src/simulation/simulator.cpp @@ -470,6 +470,7 @@ void Simulator::updateMultimeterScreen(ItemBase * multimeter, double number){ int indexPoint = textToDisplay.indexOf('.'); textToDisplay = TextUtils::convertToPowerPrefix(number, 'f', 4 - indexPoint); textToDisplay.replace('k', 'K'); + textToDisplay.replace("inf", "INF"); updateMultimeterScreen(multimeter, textToDisplay); }