From 015811d2433844546707ccc166a20097b03ea9f5 Mon Sep 17 00:00:00 2001 From: Laurent Trinques Date: Sun, 18 Oct 2026 16:24:14 +0200 Subject: [PATCH] Terminal strip editor: add spare terminals, numbered, counted in the nomenclature A spare (reserved) terminal is a terminal of a strip which is drawn on no folio. RealTerminal already foresaw it ("a terminal set by user but not present on any folio") but every terminal needed an element. - RealTerminal::createSpare(): a terminal without element, with its own data (label, type, function, led, informations: section, width, catalog terminal, color, manufacturer...). Saved in the strip: Older versions ignore these terminals. - TerminalStrip::insertSpareTerminals() / insertTerminals(): insert at a position of the strip. Undoable commands AddSpareTerminalsCommand and ChangeSpareTerminalDataCommand. - Terminal strip editor: "Add spare terminals..." button. The terminals are inserted after the selected terminal (at the end if none), numbered from its label ("X1:12" -> "X1:13", "X1:14", leading zeros kept), with its properties if asked. The labels can be changed or removed in the table, like the other cells; the Xref column shows "Spare". Moving a spare terminal to the independent terminals removes it (undoable). - Nomenclature: the spare terminals are in the new spare_terminal table, added to element_nomenclature_view (UNION ALL, same columns), after the folios, in the order of their strip. exclude_from_bom is honoured. - The modified cells of the editor model are kept by real terminal, not by element, since a spare terminal has none. --- .../UndoCommand/addterminaltostripcommand.cpp | 70 +++++ .../UndoCommand/addterminaltostripcommand.h | 43 +++ sources/TerminalStrip/realterminal.cpp | 183 +++++++++++-- sources/TerminalStrip/realterminal.h | 13 + sources/TerminalStrip/terminalstrip.cpp | 69 ++++- sources/TerminalStrip/terminalstrip.h | 2 + sources/TerminalStrip/ui/modelTerminalData.h | 2 + .../TerminalStrip/ui/terminalstripeditor.cpp | 248 +++++++++++++++--- .../TerminalStrip/ui/terminalstripeditor.h | 1 + .../TerminalStrip/ui/terminalstripeditor.ui | 12 +- .../TerminalStrip/ui/terminalstripmodel.cpp | 30 ++- sources/TerminalStrip/ui/terminalstripmodel.h | 3 +- sources/dataBase/projectdatabase.cpp | 107 ++++++++ sources/dataBase/projectdatabase.h | 2 + sources/qetproject.cpp | 31 ++- sources/qetproject.h | 1 + 16 files changed, 747 insertions(+), 70 deletions(-) diff --git a/sources/TerminalStrip/UndoCommand/addterminaltostripcommand.cpp b/sources/TerminalStrip/UndoCommand/addterminaltostripcommand.cpp index 823c0d8c0..ab6a9d59b 100644 --- a/sources/TerminalStrip/UndoCommand/addterminaltostripcommand.cpp +++ b/sources/TerminalStrip/UndoCommand/addterminaltostripcommand.cpp @@ -19,6 +19,7 @@ #include "../../qetgraphicsitem/terminalelement.h" #include "../realterminal.h" #include "../physicalterminal.h" +#include "../terminalstrip.h" /** * @brief AddTerminalToStripCommand::AddTerminalToStripCommand @@ -234,3 +235,72 @@ void MoveTerminalCommand::redo() m_new_strip->addTerminals(m_terminal); } } + +/** + * @brief AddSpareTerminalsCommand::AddSpareTerminalsCommand + * @param strip : the strip where the spare terminals are inserted + * @param pos : position of the first spare terminal in the strip, + * -1 to add them at the end of the strip + * @param spare_terminals : spare terminals made by RealTerminal::createSpare() + * @param parent : parent undo command + */ +AddSpareTerminalsCommand::AddSpareTerminalsCommand(TerminalStrip *strip, int pos, + const QVector> &spare_terminals, + QUndoCommand *parent) : + QUndoCommand{parent}, + m_strip{strip}, + m_pos{pos}, + m_spare_terminals{spare_terminals} +{ + const auto count = spare_terminals.size(); + const auto strip_name = strip ? strip->name() : QString(); + setText(strip_name.isEmpty() + ? QObject::tr("Add %n spare terminals", "", count) + : QObject::tr("Add %n spare terminals to terminal group %1", "", count).arg(strip_name)); +} + +void AddSpareTerminalsCommand::undo() +{ + if (m_strip) { + m_strip->removeTerminals(m_physical_terminals); + } +} + +void AddSpareTerminalsCommand::redo() +{ + if (!m_strip) { + return; + } + //The first time the physical terminals are made, + //after an undo the same ones are inserted again + if (m_physical_terminals.isEmpty()) { + m_physical_terminals = m_strip->insertSpareTerminals(m_pos, m_spare_terminals); + } else { + m_strip->insertTerminals(m_pos, m_physical_terminals); + } +} + +/** + * @brief ChangeSpareTerminalDataCommand::ChangeSpareTerminalDataCommand + * @param spare_terminal : the spare terminal to change + * @param new_data : the new data of the terminal + * @param parent : parent undo command + */ +ChangeSpareTerminalDataCommand::ChangeSpareTerminalDataCommand(const QSharedPointer &spare_terminal, + const ElementData &new_data, + QUndoCommand *parent) : + QUndoCommand{parent}, + m_spare_terminal{spare_terminal}, + m_old_data{spare_terminal->spareData()}, + m_new_data{new_data} +{ + setText(QObject::tr("Modify the spare terminal %1").arg(spare_terminal->label())); +} + +void ChangeSpareTerminalDataCommand::undo() { + m_spare_terminal->setSpareData(m_old_data); +} + +void ChangeSpareTerminalDataCommand::redo() { + m_spare_terminal->setSpareData(m_new_data); +} diff --git a/sources/TerminalStrip/UndoCommand/addterminaltostripcommand.h b/sources/TerminalStrip/UndoCommand/addterminaltostripcommand.h index 3952b97ba..ed101b0a5 100644 --- a/sources/TerminalStrip/UndoCommand/addterminaltostripcommand.h +++ b/sources/TerminalStrip/UndoCommand/addterminaltostripcommand.h @@ -21,6 +21,8 @@ #include #include #include +#include +#include "../../properties/elementdata.h" class TerminalElement; class TerminalStrip; @@ -89,4 +91,45 @@ class MoveTerminalCommand : public QUndoCommand }; +/** + * @brief The AddSpareTerminalsCommand class + * Insert spare terminals (on no folio) in a terminal strip, + * at a position of the strip. + */ +class AddSpareTerminalsCommand : public QUndoCommand +{ + public: + AddSpareTerminalsCommand(TerminalStrip *strip, int pos, + const QVector> &spare_terminals, + QUndoCommand *parent = nullptr); + + void undo() override; + void redo() override; + + private: + QPointer m_strip; + int m_pos = -1; + QVector> m_spare_terminals; + QVector> m_physical_terminals; +}; + +/** + * @brief The ChangeSpareTerminalDataCommand class + * Change the data (label, type, section...) of a spare terminal + */ +class ChangeSpareTerminalDataCommand : public QUndoCommand +{ + public: + ChangeSpareTerminalDataCommand(const QSharedPointer &spare_terminal, + const ElementData &new_data, + QUndoCommand *parent = nullptr); + + void undo() override; + void redo() override; + + private: + QSharedPointer m_spare_terminal; + ElementData m_old_data, m_new_data; +}; + #endif // ADDTERMINALTOSTRIPCOMMAND_H diff --git a/sources/TerminalStrip/realterminal.cpp b/sources/TerminalStrip/realterminal.cpp index 8935cda97..3ec7ad462 100644 --- a/sources/TerminalStrip/realterminal.cpp +++ b/sources/TerminalStrip/realterminal.cpp @@ -33,6 +33,118 @@ RealTerminal::RealTerminal(Element *terminal) : m_element(terminal) {} +/** + * @brief RealTerminal::createSpare + * Create a spare terminal (a reserved terminal) : a terminal of a strip + * which is not drawn on any folio. Its data (label, type, section, + * width...) are its own, stored with the terminal strip. + * @param data : the data of the terminal, only the terminal type, + * function, led and the informations are used. + * @param uuid : the uuid of the spare terminal + * @return the new spare terminal, not yet added to a strip + */ +QSharedPointer RealTerminal::createSpare(const ElementData &data, const QUuid &uuid) +{ + auto raw_ = new RealTerminal(nullptr); + raw_->m_spare = true; + raw_->m_spare_uuid = uuid.isNull() ? QUuid::createUuid() : uuid; + raw_->m_spare_data.m_type = ElementData::Terminal; + raw_->m_spare_data.setTerminalType(data.terminalType()); + raw_->m_spare_data.setTerminalFunction(data.terminalFunction()); + raw_->m_spare_data.setTerminalLED(data.terminalLed()); + raw_->m_spare_data.m_informations = data.m_informations; + return raw_->sharedRef(); +} + +/** + * @brief RealTerminal::spareFromXml + * @param xml_element : a real terminal saved by toXml() + * @return the spare terminal saved in @a xml_element, + * or a null pointer if @a xml_element is not a spare terminal. + */ +QSharedPointer RealTerminal::spareFromXml(const QDomElement &xml_element) +{ + if (xml_element.tagName() != xmlTagName() || + !xml_element.hasAttribute(QStringLiteral("spare_uuid"))) { + return QSharedPointer(); + } + + ElementData data_; + data_.setTerminalType(ElementData::terminalTypeFromString( + xml_element.attribute(QStringLiteral("type")))); + data_.setTerminalFunction(ElementData::terminalFunctionFromString( + xml_element.attribute(QStringLiteral("function")))); + data_.setTerminalLED(QET::infoFlagIsTrue(xml_element.attribute(QStringLiteral("led")))); + data_.m_informations.fromXml(xml_element.firstChildElement(QStringLiteral("informations")), + QStringLiteral("information")); + + return createSpare(data_, QUuid(xml_element.attribute(QStringLiteral("spare_uuid")))); +} + +/** + * @brief RealTerminal::isSpare + * @return true if this terminal is a spare terminal, not drawn on any folio + * @sa createSpare + */ +bool RealTerminal::isSpare() const { + return m_spare; +} + +/** + * @brief RealTerminal::spareData + * @return the data of this spare terminal, an empty ElementData + * if this terminal is not a spare terminal. + */ +ElementData RealTerminal::spareData() const { + return m_spare_data; +} + +/** + * @brief RealTerminal::setSpareData + * Set the data of this spare terminal (nothing is done if this terminal + * is not a spare terminal) and tell the strip, so that it is redrawn. + * @param data + */ +void RealTerminal::setSpareData(const ElementData &data) +{ + if (!m_spare) { + return; + } + m_spare_data.setTerminalType(data.terminalType()); + m_spare_data.setTerminalFunction(data.terminalFunction()); + m_spare_data.setTerminalLED(data.terminalLed()); + m_spare_data.m_informations = data.m_informations; + + if (auto strip_ = parentStrip()) { + strip_->terminalDataChanged(); + } +} + +/** + * @brief RealTerminal::hasData + * @return true if this terminal has data : it is linked to an element, + * or it is a spare terminal. + */ +bool RealTerminal::hasData() const { + return m_spare || !m_element.isNull(); +} + +/** + * @brief RealTerminal::terminalData + * @return the data of this terminal : the data of its element, + * or its own data if it is a spare terminal. + */ +ElementData RealTerminal::terminalData() const +{ + if (m_spare) { + return m_spare_data; + } + if (m_element) { + return m_element->elementData(); + } + return ElementData(); +} + RealTerminal::~RealTerminal() { if (m_physical_terminal) { @@ -82,8 +194,22 @@ QWeakPointer RealTerminal::weakRef() { QDomElement RealTerminal::toXml(QDomDocument &parent_document) const { auto root_elmt = parent_document.createElement(this->xmlTagName()); - if (m_element) + if (m_spare) + { + //A spare terminal is on no folio : its data are saved here + root_elmt.setAttribute(QStringLiteral("spare_uuid"), m_spare_uuid.toString()); + root_elmt.setAttribute(QStringLiteral("type"), ElementData::terminalTypeToString(m_spare_data.terminalType())); + root_elmt.setAttribute(QStringLiteral("function"), ElementData::terminalFunctionToString(m_spare_data.terminalFunction())); + if (m_spare_data.terminalLed()) { + root_elmt.setAttribute(QStringLiteral("led"), QStringLiteral("true")); + } + auto xml_info = parent_document.createElement(QStringLiteral("informations")); + m_spare_data.m_informations.toXml(xml_info, QStringLiteral("information")); + root_elmt.appendChild(xml_info); + } + else if (m_element) { root_elmt.setAttribute(QStringLiteral("element_uuid"), m_element->uuid().toString()); + } return root_elmt; } @@ -137,7 +263,9 @@ int RealTerminal::level() const * @return the label of this real terminal */ QString RealTerminal::label() const { - if (!m_element.isNull()) { + if (m_spare) { + return m_spare_data.m_informations.value(QStringLiteral("label")).toString(); + } else if (!m_element.isNull()) { return m_element->actualLabel(); } else { return QLatin1String(); @@ -164,8 +292,8 @@ QString RealTerminal::Xref() const * The value is stored in the informations of the element. */ QString RealTerminal::cable() const { - if (m_element) { - return m_element->elementData().m_informations.value(cableInfoKey()).toString(); + if (hasData()) { + return terminalData().m_informations.value(cableInfoKey()).toString(); } return QString(); } @@ -175,8 +303,8 @@ QString RealTerminal::cable() const { * @return The color / number of the wire of the cable, connected to this terminal. */ QString RealTerminal::cableWire() const { - if (m_element) { - return m_element->elementData().m_informations.value(cableWireInfoKey()).toString(); + if (hasData()) { + return terminalData().m_informations.value(cableWireInfoKey()).toString(); } return QString(); } @@ -187,9 +315,9 @@ QString RealTerminal::cableWire() const { * and not one of its wires. */ bool RealTerminal::isShield() const { - if (m_element) { + if (hasData()) { return QET::infoFlagIsTrue( - m_element->elementData().m_informations.value(shieldInfoKey()).toString()); + terminalData().m_informations.value(shieldInfoKey()).toString()); } return false; } @@ -204,8 +332,8 @@ bool RealTerminal::isShield() const { QColor RealTerminal::color() const { QColor main_, stripe_; - if (m_element) { - TerminalColor::parse(m_element->elementData().m_informations.value(colorInfoKey()).toString(), + if (hasData()) { + TerminalColor::parse(terminalData().m_informations.value(colorInfoKey()).toString(), &main_, &stripe_); } return main_; @@ -219,8 +347,8 @@ QColor RealTerminal::color() const QColor RealTerminal::stripeColor() const { QColor main_, stripe_; - if (m_element) { - TerminalColor::parse(m_element->elementData().m_informations.value(colorInfoKey()).toString(), + if (hasData()) { + TerminalColor::parse(terminalData().m_informations.value(colorInfoKey()).toString(), &main_, &stripe_); } return stripe_; @@ -235,10 +363,10 @@ QColor RealTerminal::stripeColor() const */ qreal RealTerminal::section() const { - if (m_element) + if (hasData()) { bool ok_ = false; - const auto section_ = m_element->elementData().m_informations.value(sectionInfoKey()).toString().toDouble(&ok_); + const auto section_ = terminalData().m_informations.value(sectionInfoKey()).toString().toDouble(&ok_); if (ok_ && section_ > 0) { return section_; } @@ -255,10 +383,10 @@ qreal RealTerminal::section() const */ qreal RealTerminal::widthMm() const { - if (m_element) + if (hasData()) { bool ok_ = false; - const auto width_ = m_element->elementData().m_informations.value(widthInfoKey()).toString().toDouble(&ok_); + const auto width_ = terminalData().m_informations.value(widthInfoKey()).toString().toDouble(&ok_); if (ok_ && width_ > 0) { return width_; } @@ -276,8 +404,8 @@ qreal RealTerminal::widthMm() const */ QString RealTerminal::catalogEntry() const { - if (m_element) { - return m_element->elementData().m_informations.value(catalogEntryInfoKey()).toString(); + if (hasData()) { + return terminalData().m_informations.value(catalogEntryInfoKey()).toString(); } return QString(); } @@ -334,9 +462,9 @@ void RealTerminal::applyCatalogEntry(DiagramContext &informations, const QString * Used to separate groups of terminals (voltages, functions...). */ bool RealTerminal::hasSeparatorAfter() const { - if (m_element) { + if (hasData()) { return QET::infoFlagIsTrue( - m_element->elementData().m_informations.value(separatorInfoKey()).toString()); + terminalData().m_informations.value(separatorInfoKey()).toString()); } return false; } @@ -361,8 +489,8 @@ QString RealTerminal::conductor() const { * @return */ ElementData::TerminalType RealTerminal::type() const { - if (m_element) { - return m_element->elementData().terminalType(); + if (hasData()) { + return terminalData().terminalType(); } else { return ElementData::TTGeneric; } @@ -373,8 +501,8 @@ ElementData::TerminalType RealTerminal::type() const { * @return */ ElementData::TerminalFunction RealTerminal::function() const { - if (m_element) { - return m_element->elementData().terminalFunction(); + if (hasData()) { + return terminalData().terminalFunction(); } else { return ElementData::TFGeneric; } @@ -385,8 +513,8 @@ ElementData::TerminalFunction RealTerminal::function() const { * @return */ bool RealTerminal::isLed() const { - if (m_element) { - return m_element->elementData().terminalLed(); + if (hasData()) { + return terminalData().terminalLed(); } else { return false; } @@ -443,6 +571,9 @@ Element *RealTerminal::element() const { * else return a null uuid. */ QUuid RealTerminal::elementUuid() const { + if (m_spare) { + return m_spare_uuid; //Used to find the terminal (bridges...) like an element uuid + } if (!m_element.isNull()) { return m_element->uuid(); } else { diff --git a/sources/TerminalStrip/realterminal.h b/sources/TerminalStrip/realterminal.h index c2124d2c0..bf8d39bbd 100644 --- a/sources/TerminalStrip/realterminal.h +++ b/sources/TerminalStrip/realterminal.h @@ -21,6 +21,7 @@ #include #include #include +#include #include "../properties/elementdata.h" class TerminalStrip; @@ -56,6 +57,12 @@ class RealTerminal public: ~RealTerminal(); + static QSharedPointer createSpare(const ElementData &data, const QUuid &uuid = QUuid()); + static QSharedPointer spareFromXml(const QDomElement &xml_element); + bool isSpare() const; + ElementData spareData() const; + void setSpareData(const ElementData &data); + ElementData terminalData() const; TerminalStrip *parentStrip() const noexcept; QSharedPointer physicalTerminal() const noexcept; @@ -107,7 +114,13 @@ class RealTerminal static QString xmlTagName(); private : + bool hasData() const; + QPointer m_element; + //A spare terminal has no element : it is on no folio, its data are its own + bool m_spare = false; + QUuid m_spare_uuid; + ElementData m_spare_data; QWeakPointer m_this_weak; QSharedPointer m_physical_terminal; }; diff --git a/sources/TerminalStrip/terminalstrip.cpp b/sources/TerminalStrip/terminalstrip.cpp index 7740cbef8..80bee260c 100644 --- a/sources/TerminalStrip/terminalstrip.cpp +++ b/sources/TerminalStrip/terminalstrip.cpp @@ -392,6 +392,60 @@ void TerminalStrip::removeTerminals(QVector > p } } +/** + * @brief TerminalStrip::insertSpareTerminals + * Insert in this strip, at position @a pos, one physical terminal + * for each spare terminal of @a spare_terminals. + * @param pos : position of the first inserted terminal, + * out of range (-1...) to add the terminals at the end of the strip. + * @param spare_terminals : spare terminals not owned by a strip + * (RealTerminal::createSpare()) + * @return the inserted physical terminals + */ +QVector> TerminalStrip::insertSpareTerminals(int pos, const QVector> &spare_terminals) +{ + QVector> phy_vector; + for (const auto &real_t : spare_terminals) + { + if (real_t && real_t->isSpare() && !real_t->parentStrip()) { + auto raw_phy_ptr = new PhysicalTerminal(nullptr, QVector>{real_t}); + phy_vector.append(raw_phy_ptr->sharedRef()); + } + } + insertTerminals(pos, phy_vector); + return phy_vector; +} + +/** + * @brief TerminalStrip::insertTerminals + * Insert @a phy_t_vector in this strip at position @a pos, in this order. + * The physical terminals already owned by a strip are ignored. + * @param pos : position of the first inserted terminal, + * out of range (-1...) to add the terminals at the end of the strip. + * @param phy_t_vector + */ +void TerminalStrip::insertTerminals(int pos, const QVector> &phy_t_vector) +{ + if (pos < 0 || pos > m_physical_terminals.size()) { + pos = m_physical_terminals.size(); + } + + bool added_{false}; + for (const auto &phy_t : phy_t_vector) + { + if (!phy_t || phy_t->terminalStrip()) { + continue; + } + m_physical_terminals.insert(pos++, phy_t); + phy_t->setParentStrip(this); + added_ = true; + } + + if (added_) { + emit orderChanged(); + } +} + /** * @brief TerminalStrip::pos * @param terminal @@ -1027,8 +1081,13 @@ bool TerminalStrip::fromXml(QDomElement &xml_element) //tell where any symbol is QSet terminals; const QDomNodeList xml_reals = xml_layout.elementsByTagName(RealTerminal::xmlTagName()); - for (int i = 0 ; i < xml_reals.size() ; ++i) - terminals.insert(QUuid(xml_reals.at(i).toElement().attribute(QStringLiteral("element_uuid")))); + for (int i = 0 ; i < xml_reals.size() ; ++i) { + //A spare terminal is on no folio + const auto element_uuid_ = xml_reals.at(i).toElement().attribute(QStringLiteral("element_uuid")); + if (!element_uuid_.isEmpty()) { + terminals.insert(QUuid(element_uuid_)); + } + } m_project->buildFoliosHoldingSymbols(terminals); //Get all free elements terminal of the project: its own are on @@ -1044,6 +1103,12 @@ bool TerminalStrip::fromXml(QDomElement &xml_element) //Read each real terminal of the current physical terminal of the loop for (auto &xml_real : QETXML::findInDomElement(xml_physical, RealTerminal::xmlTagName())) { + //A spare terminal (on no folio) has its own data + if (auto spare_ = RealTerminal::spareFromXml(xml_real)) { + real_t_vector.append(spare_); + continue; + } + const auto uuid_ = QUuid(xml_real.attribute(QStringLiteral("element_uuid"))); bool found = false; for (auto terminal_elmt : std::as_const(free_terminals)) diff --git a/sources/TerminalStrip/terminalstrip.h b/sources/TerminalStrip/terminalstrip.h index 96111ff99..313f13ee0 100644 --- a/sources/TerminalStrip/terminalstrip.h +++ b/sources/TerminalStrip/terminalstrip.h @@ -95,6 +95,8 @@ class TerminalStrip : public QObject void addTerminals (QVector> phy_t_vector); bool removeTerminal (QSharedPointer phy_t); void removeTerminals (QVector> phy_t_vector); + QVector> insertSpareTerminals(int pos, const QVector> &spare_terminals); + void insertTerminals(int pos, const QVector> &phy_t_vector); int pos(const QSharedPointer &terminal) const; int physicalTerminalCount() const; diff --git a/sources/TerminalStrip/ui/modelTerminalData.h b/sources/TerminalStrip/ui/modelTerminalData.h index a6d422642..2921b33af 100644 --- a/sources/TerminalStrip/ui/modelTerminalData.h +++ b/sources/TerminalStrip/ui/modelTerminalData.h @@ -49,6 +49,7 @@ struct modelRealTerminalData mrtd.element_ = real_t->element(); mrtd.real_terminal = real_t.toWeakRef(); mrtd.bridged_ = real_t->isBridged(); + mrtd.spare_ = real_t->isSpare(); } return mrtd; @@ -69,6 +70,7 @@ struct modelRealTerminalData qreal width_mm_ = 0; //In mm, 0 = no width set by the user QString catalog_entry_; //Terminal chosen in the catalog, empty if the width was typed bool bridged_ = false; + bool spare_ = false; //Spare terminal, on no folio (RealTerminal::isSpare()) ElementData::TerminalType type_ = ElementData::TerminalType::TTGeneric; ElementData::TerminalFunction function_ = ElementData::TerminalFunction::TFGeneric; diff --git a/sources/TerminalStrip/ui/terminalstripeditor.cpp b/sources/TerminalStrip/ui/terminalstripeditor.cpp index 509d106bb..3d748fc69 100644 --- a/sources/TerminalStrip/ui/terminalstripeditor.cpp +++ b/sources/TerminalStrip/ui/terminalstripeditor.cpp @@ -34,10 +34,18 @@ #include "../terminalcolor.h" #include "../terminalcatalog.h" #include "../realterminal.h" +#include "../../qetinformation.h" #include +#include #include +#include +#include +#include #include +#include +#include +#include #include #include @@ -218,37 +226,48 @@ void TerminalStripEditor::apply() { for (const auto &data_ : m_model->modifiedmodelRealTerminalData()) { - if (auto element = data_.element_) - { - auto current_data = element->elementData(); - current_data.setTerminalType(data_.type_); - current_data.setTerminalFunction(data_.function_); - current_data.setTerminalLED(data_.led_); - current_data.m_informations.addValue(QStringLiteral("label"), data_.label_); - //The cable data are only stored when they are used - const auto set_info = [¤t_data](const QString &key, const QString &value) { - if (!value.isEmpty() || current_data.m_informations.contains(key)) { - current_data.m_informations.addValue(key, value); - } - }; - set_info(RealTerminal::cableInfoKey(), data_.cable_); - set_info(RealTerminal::cableWireInfoKey(), data_.cable_wire); - set_info(RealTerminal::shieldInfoKey(), data_.shield_ ? QStringLiteral("true") : QString()); - //The color and the section are stored with the dot as decimal separator, whatever the locale - set_info(RealTerminal::colorInfoKey(), TerminalColor::toSpec(data_.color_, data_.stripe_color_)); - set_info(RealTerminal::sectionInfoKey(), data_.section_ > 0 ? QString::number(data_.section_, 'g', 6) : QString()); - set_info(RealTerminal::widthInfoKey(), data_.width_mm_ > 0 ? QString::number(data_.width_mm_, 'g', 6) : QString()); - //The terminal chosen in the catalog, its manufacturer and its reference - //(only written when the user didn't type them) - RealTerminal::applyCatalogEntry(current_data.m_informations, - data_.width_mm_ > 0 ? data_.catalog_entry_ : QString()); - set_info(RealTerminal::separatorInfoKey(), data_.separator_ ? QStringLiteral("true") : QString()); - - if (element->elementData() != current_data) - m_project->undoStack()->push(new ChangeElementDataCommand(element, current_data)); - if (data_.level_ != data_.real_terminal.toStrongRef()->level()) - m_project->undoStack()->push(new ChangeTerminalLevel(m_current_strip, data_.real_terminal, data_.level_)); + const auto real_t = data_.real_terminal.toStrongRef(); + auto element = data_.element_; + //A spare terminal (on no folio) has its own data, not the data of an element + if (!real_t || (!element && !data_.spare_)) { + continue; } + + const auto old_data = element ? element->elementData() : real_t->spareData(); + auto current_data = old_data; + current_data.setTerminalType(data_.type_); + current_data.setTerminalFunction(data_.function_); + current_data.setTerminalLED(data_.led_); + current_data.m_informations.addValue(QStringLiteral("label"), data_.label_); + //The cable data are only stored when they are used + const auto set_info = [¤t_data](const QString &key, const QString &value) { + if (!value.isEmpty() || current_data.m_informations.contains(key)) { + current_data.m_informations.addValue(key, value); + } + }; + set_info(RealTerminal::cableInfoKey(), data_.cable_); + set_info(RealTerminal::cableWireInfoKey(), data_.cable_wire); + set_info(RealTerminal::shieldInfoKey(), data_.shield_ ? QStringLiteral("true") : QString()); + //The color and the section are stored with the dot as decimal separator, whatever the locale + set_info(RealTerminal::colorInfoKey(), TerminalColor::toSpec(data_.color_, data_.stripe_color_)); + set_info(RealTerminal::sectionInfoKey(), data_.section_ > 0 ? QString::number(data_.section_, 'g', 6) : QString()); + set_info(RealTerminal::widthInfoKey(), data_.width_mm_ > 0 ? QString::number(data_.width_mm_, 'g', 6) : QString()); + //The terminal chosen in the catalog, its manufacturer and its reference + //(only written when the user didn't type them) + RealTerminal::applyCatalogEntry(current_data.m_informations, + data_.width_mm_ > 0 ? data_.catalog_entry_ : QString()); + set_info(RealTerminal::separatorInfoKey(), data_.separator_ ? QStringLiteral("true") : QString()); + + if (old_data != current_data) + { + if (element) { + m_project->undoStack()->push(new ChangeElementDataCommand(element, current_data)); + } else { + m_project->undoStack()->push(new ChangeSpareTerminalDataCommand(real_t, current_data)); + } + } + if (data_.level_ != real_t->level()) + m_project->undoStack()->push(new ChangeTerminalLevel(m_current_strip, data_.real_terminal, data_.level_)); } } @@ -331,10 +350,12 @@ void TerminalStripEditor::selectionChanged() ui->m_bridge_terminals_pb ->setDisabled(true); ui->m_unbridge_terminals_pb->setDisabled(true); ui->m_bridge_color_cb ->setDisabled(true); + ui->m_add_spare_pb ->setDisabled(true); return; } ui->m_auto_ordering_pb->setEnabled(true); + ui->m_add_spare_pb ->setEnabled(true); const auto index_list = ui->m_table_widget->selectionModel()->selectedIndexes(); @@ -1028,3 +1049,170 @@ void TerminalStripEditor::on_m_move_to_pb_clicked() } } + +namespace { +/** + * @brief The NumberedLabel struct + * A terminal label split in a prefix and a number : "X1:12" is "X1:" and 12. + */ +struct NumberedLabel +{ + QString prefix; + int number = 0; ///< 0 if the label has no number + int width = 0; ///< Number of digits, to keep the leading zeros ("X1:05") +}; + +/** + * @brief splitLabel + * @param label : a terminal label, like "X1:12", "12" or "PE" + * @return the label split in a prefix and its last number + */ +NumberedLabel splitLabel(const QString &label) +{ + static const QRegularExpression re_(QStringLiteral("^(.*?)(\\d+)$")); + NumberedLabel numbered_; + const auto match_ = re_.match(label.trimmed()); + if (match_.hasMatch()) + { + numbered_.prefix = match_.captured(1); + numbered_.number = match_.captured(2).toInt(); + const auto digits_ = match_.captured(2); + numbered_.width = digits_.startsWith(QLatin1Char('0')) ? digits_.size() : 0; + } + else { + numbered_.prefix = label.trimmed(); + } + return numbered_; +} + +/** + * @brief numberedLabel + * @return @a prefix followed by @a number, with leading zeros up to @a width digits + */ +QString numberedLabel(const QString &prefix, int number, int width) { + return prefix + QStringLiteral("%1").arg(number, width, 10, QLatin1Char('0')); +} +} + +/** + * @brief TerminalStripEditor::on_m_add_spare_pb_clicked + * Add spare terminals (on no folio) after the selected terminal, + * or at the end of the strip if no terminal is selected. + * The labels continue the number of the selected terminal ("X1:12" -> + * "X1:13", "X1:14"...), the user can change or remove them in the table. + * The properties of the selected terminal (type, section, width, terminal + * of the catalog, color, manufacturer...) can be copied to the spare terminals, + * which then are the same part in the bill of materials. + */ +void TerminalStripEditor::on_m_add_spare_pb_clicked() +{ + if (!m_model || !m_current_strip || !m_project) { + return; + } + + //The last selected physical terminal in the strip, else the last one of the strip + int insert_pos_ = -1; + QSharedPointer reference_; + const auto selected_ = m_model->modelPhysicalTerminalDataForIndex( + ui->m_table_widget->selectionModel()->selectedIndexes()); + for (const auto &data_ : selected_) + { + const auto phy_t = m_current_strip->physicalTerminal(data_.uuid_); + const auto pos_ = m_current_strip->pos(phy_t); + if (phy_t && pos_ >= insert_pos_) { + insert_pos_ = pos_; + reference_ = phy_t; + } + } + if (reference_) { + ++insert_pos_; //After the selected terminal + } else { + insert_pos_ = -1; //At the end of the strip + if (m_current_strip->physicalTerminalCount()) { + reference_ = m_current_strip->physicalTerminal(m_current_strip->physicalTerminalCount() - 1); + } + } + QSharedPointer reference_real_; + if (reference_ && !reference_->realTerminals().isEmpty()) { + reference_real_ = reference_->realTerminals().last(); + } + + //Proposed numbering : the one of the reference terminal, continued + const auto numbered_ = splitLabel(reference_real_ ? reference_real_->label() : QString()); + + QDialog dialog(this); + dialog.setWindowTitle(tr("Add spare terminals")); + auto layout_ = new QFormLayout(&dialog); + + auto count_sb = new QSpinBox(&dialog); + count_sb->setRange(1, 999); + count_sb->setValue(1); + layout_->addRow(tr("Number of terminals :"), count_sb); + + auto numbering_cb = new QCheckBox(tr("Number the terminals"), &dialog); + numbering_cb->setChecked(true); + layout_->addRow(numbering_cb); + + auto prefix_le = new QLineEdit(numbered_.prefix, &dialog); + layout_->addRow(tr("Prefix :"), prefix_le); + + auto first_sb = new QSpinBox(&dialog); + first_sb->setRange(0, 999999); + first_sb->setValue(numbered_.number + 1); + layout_->addRow(tr("First number :"), first_sb); + + connect(numbering_cb, &QCheckBox::toggled, prefix_le, &QWidget::setEnabled); + connect(numbering_cb, &QCheckBox::toggled, first_sb, &QWidget::setEnabled); + + auto copy_cb = new QCheckBox(tr("Same terminal as %1 (type, section, width, color, manufacturer...)") + .arg(reference_real_ && !reference_real_->label().isEmpty() + ? reference_real_->label() : tr("the selected terminal")), + &dialog); + copy_cb->setChecked(!reference_real_.isNull()); + copy_cb->setEnabled(!reference_real_.isNull()); + layout_->addRow(copy_cb); + + auto buttons_ = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &dialog); + connect(buttons_, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + connect(buttons_, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); + layout_->addRow(buttons_); + + if (dialog.exec() != QDialog::Accepted) { + return; + } + + //The data shared by every spare terminal + ElementData model_; + if (copy_cb->isChecked() && reference_real_) + { + const auto reference_data_ = reference_real_->terminalData(); + model_.setTerminalType(reference_data_.terminalType()); + model_.setTerminalFunction(reference_data_.terminalFunction()); + model_.setTerminalLED(reference_data_.terminalLed()); + //What makes the part, not what belongs to this terminal (label, cable...) + for (const auto &key_ : {RealTerminal::sectionInfoKey(), RealTerminal::widthInfoKey(), + RealTerminal::catalogEntryInfoKey(), RealTerminal::colorInfoKey(), + QETInformation::ELMT_MANUFACTURER, QETInformation::ELMT_MANUFACTURER_REF, + QETInformation::ELMT_DESIGNATION, QETInformation::ELMT_PLANT, + QETInformation::ELMT_LOCATION}) + { + const auto value_ = reference_data_.m_informations.value(key_).toString(); + if (!value_.isEmpty()) { + model_.m_informations.addValue(key_, value_); + } + } + } + + QVector> spare_vector; + for (int i = 0 ; i < count_sb->value() ; ++i) + { + auto data_ = model_; + if (numbering_cb->isChecked()) { + data_.m_informations.addValue(QStringLiteral("label"), + numberedLabel(prefix_le->text(), first_sb->value() + i, numbered_.width)); + } + spare_vector.append(RealTerminal::createSpare(data_)); + } + + m_project->undoStack()->push(new AddSpareTerminalsCommand(m_current_strip, insert_pos_, spare_vector)); +} diff --git a/sources/TerminalStrip/ui/terminalstripeditor.h b/sources/TerminalStrip/ui/terminalstripeditor.h index ceef6ac0e..4a38d0e34 100644 --- a/sources/TerminalStrip/ui/terminalstripeditor.h +++ b/sources/TerminalStrip/ui/terminalstripeditor.h @@ -74,6 +74,7 @@ class TerminalStripEditor : public QWidget void on_m_unbridge_terminals_pb_clicked(); void on_m_bridge_color_cb_activated(const QColor &col); void on_m_move_to_pb_clicked(); + void on_m_add_spare_pb_clicked(); private: Ui::TerminalStripEditor *ui; diff --git a/sources/TerminalStrip/ui/terminalstripeditor.ui b/sources/TerminalStrip/ui/terminalstripeditor.ui index d58fc0bf8..2576b819f 100644 --- a/sources/TerminalStrip/ui/terminalstripeditor.ui +++ b/sources/TerminalStrip/ui/terminalstripeditor.ui @@ -212,7 +212,17 @@ - + + + + Add spare terminals, on no folio, after the selected terminal + + + Add spare terminals... + + + + Qt::Vertical diff --git a/sources/TerminalStrip/ui/terminalstripmodel.cpp b/sources/TerminalStrip/ui/terminalstripmodel.cpp index 916eb51ed..4dfdb51e4 100644 --- a/sources/TerminalStrip/ui/terminalstripmodel.cpp +++ b/sources/TerminalStrip/ui/terminalstripmodel.cpp @@ -61,6 +61,14 @@ const int COLUMN_COUNT = 19; static QVector UNMODIFIED_CELL_VECTOR(COLUMN_COUNT, false); +/** + * @brief modifiedCellKey + * @return the key of the real terminal of @a data in the modified cells + */ +static const RealTerminal *modifiedCellKey(const modelRealTerminalData &data) { + return data.real_terminal.toStrongRef().data(); +} + /** * @brief parsePositiveNumber * Convert the text written by the user to a number >= 0 @@ -204,7 +212,7 @@ QVariant TerminalStripModel::data(const QModelIndex &index, int role) const case LEVEL_CELL : return mrtd.level_; case LABEL_CELL : return mrtd.label_; case CONDUCTOR_CELL : return mrtd.conductor_; - case XREF_CELL : return mrtd.Xref_; + case XREF_CELL : return mrtd.spare_ ? tr("Spare") : mrtd.Xref_; case CABLE_CELL : return mrtd.cable_; case CABLE_WIRE_CELL : return mrtd.cable_wire; case TYPE_CELL : return ElementData::translatedTerminalType(mrtd.type_); @@ -254,10 +262,16 @@ QVariant TerminalStripModel::data(const QModelIndex &index, int role) const { return mrtd.separator_ ? Qt::Checked : Qt::Unchecked; } + else if (role == Qt::ForegroundRole && + index.column() == XREF_CELL && mrtd.spare_) + { + return QBrush(Qt::gray); //"Spare" : not a reference to a folio + } else if (role == Qt::BackgroundRole && index.column() < COLUMN_COUNT ) { - if (m_modified_cell.contains(mrtd.element_) && - m_modified_cell.value(mrtd.element_).at(index.column())) + const auto key_ = modifiedCellKey(mrtd); + if (m_modified_cell.contains(key_) && + m_modified_cell.value(key_).at(index.column())) { return QBrush(Qt::yellow); } @@ -425,17 +439,17 @@ bool TerminalStripModel::setData(const QModelIndex &index, const QVariant &value { replaceDataAtRow(mrtd, index.row()); - if (mrtd.element_) + if (const auto key_ = modifiedCellKey(mrtd)) { QVector vector_; - if (m_modified_cell.contains(mrtd.element_)) { - vector_ = m_modified_cell.value(mrtd.element_); + if (m_modified_cell.contains(key_)) { + vector_ = m_modified_cell.value(key_); } else { vector_ = UNMODIFIED_CELL_VECTOR; } vector_.replace(modified_cell, true); - m_modified_cell.insert(mrtd.element_, vector_); + m_modified_cell.insert(key_, vector_); } emit dataChanged(index, index); return true; @@ -509,7 +523,7 @@ QVector TerminalStripModel::modifiedmodelRealTerminalData for (auto j = 0 ; j < ptd_.real_data.size() ; ++j) { auto mrtd_ = ptd_.real_data.at(j); - if (modified_real_terminal.contains(mrtd_.element_)) + if (modified_real_terminal.contains(modifiedCellKey(mrtd_))) { returned_vector.append(m_physical_data.at(i).real_data.at(j)); } diff --git a/sources/TerminalStrip/ui/terminalstripmodel.h b/sources/TerminalStrip/ui/terminalstripmodel.h index cb6aa7e3f..7a95f227a 100644 --- a/sources/TerminalStrip/ui/terminalstripmodel.h +++ b/sources/TerminalStrip/ui/terminalstripmodel.h @@ -107,7 +107,8 @@ class TerminalStripModel : public QAbstractTableModel private: QPointer m_terminal_strip; - QHash, QVector> m_modified_cell; + //Modified cells of each real terminal (spare terminals have no element) + QHash> m_modified_cell; QVector m_physical_data; struct BridgePixmap { diff --git a/sources/dataBase/projectdatabase.cpp b/sources/dataBase/projectdatabase.cpp index 06811c9db..ffae548ad 100644 --- a/sources/dataBase/projectdatabase.cpp +++ b/sources/dataBase/projectdatabase.cpp @@ -40,6 +40,9 @@ #include "../titleblockproperties.h" #include "../ElementsCollection/xmlelementcollection.h" #include "../properties/elementdata.h" +#include "../TerminalStrip/terminalstrip.h" +#include "../TerminalStrip/physicalterminal.h" +#include "../TerminalStrip/realterminal.h" #include #include @@ -125,6 +128,10 @@ void projectDataBase::updateDB() populateDiagramInfoTable(); populateElementTable(); populateElementInfoTable(); + //Not the spare_terminal table : it is not built from the folios, and + //the database is made (and updateDB() called) by the constructor of the + //project, before its terminal strips exist. It is filled when a strip + //is added to the project or changed (spareTerminalsChanged()). populateConductorTable(); populateLinkTable(); populateDrawingItemTables(); @@ -1694,6 +1701,70 @@ void projectDataBase::elementInfoChanged(QList elements) emit dataBaseUpdated(); } +/** + @brief projectDataBase::spareTerminalsChanged + The spare terminals of a terminal strip (on no folio) were added, removed + or changed : fill the spare_terminal table again. +*/ +void projectDataBase::spareTerminalsChanged() +{ + populateSpareTerminalTable(); + emit dataBaseUpdated(); +} + +/** + @brief projectDataBase::populateSpareTerminalTable + Fill the spare_terminal table with the spare terminals of the terminal + strips of the project, lines of the nomenclature like the terminals + drawn on the folios (see createElementNomenclatureView()). +*/ +void projectDataBase::populateSpareTerminalTable() +{ + QSqlQuery query_(m_data_base); + query_.exec(QStringLiteral("DELETE FROM spare_terminal")); + if (!m_project) { + return; + } + + const auto keys_ = QETInformation::elementInfoKeys(); + QString insert_(QStringLiteral("INSERT INTO spare_terminal (uuid, diagram_position, title, folio, position")); + QString values_(QStringLiteral(" VALUES (:uuid, :diagram_position, :title, :folio, :position")); + for (const auto &key_ : keys_) { + insert_ += QStringLiteral(", ") + key_; + values_ += QStringLiteral(", :") + key_; + } + query_.prepare(insert_ + QStringLiteral(")") + values_ + QStringLiteral(")")); + + //After the folios, strip by strip + int strip_index_ = 0; + for (const auto &strip_ : m_project->terminalStrip()) + { + ++strip_index_; + const auto physical_ = strip_->physicalTerminal(); + for (int pos_ = 0 ; pos_ < physical_.size() ; ++pos_) + { + for (const auto &real_t : physical_.at(pos_)->realTerminals()) + { + if (!real_t || !real_t->isSpare()) { + continue; + } + const auto informations_ = real_t->spareData().m_informations; + query_.bindValue(QStringLiteral(":uuid"), real_t->elementUuid().toString()); + query_.bindValue(QStringLiteral(":diagram_position"), 1000000 + strip_index_); + query_.bindValue(QStringLiteral(":title"), QVariant()); + query_.bindValue(QStringLiteral(":folio"), QVariant()); + query_.bindValue(QStringLiteral(":position"), pos_); + for (const auto &key_ : keys_) { + query_.bindValue(QStringLiteral(":") + key_, informations_.value(key_).toString()); + } + if (!query_.exec()) { + qDebug() << "projectDataBase::populateSpareTerminalTable insert error : " << query_.lastError(); + } + } + } + } +} + void projectDataBase::addDiagram(Diagram *diagram) { m_content_changed = true; @@ -2698,6 +2769,21 @@ bool projectDataBase::createDataBase() } } + //The spare terminals of the terminal strips : terminals on no folio, + //lines of the nomenclature like the terminals drawn on the folios + //(see createElementNomenclatureView()). One column by information, + //like element_info. + QString spare_terminal_table(QStringLiteral( + "CREATE TABLE spare_terminal(uuid VARCHAR(50) PRIMARY KEY NOT NULL, " + "diagram_position INTEGER, title VARCHAR(100), folio VARCHAR(100), position INTEGER")); + for (const auto &key_ : QETInformation::elementInfoKeys()) { + spare_terminal_table += QStringLiteral(", ") + key_ + QStringLiteral(" VARCHAR(100)"); + } + spare_terminal_table += QStringLiteral(")"); + if (!query_.exec(spare_terminal_table)) { + qDebug() << " spare_terminal_table query : " << query_.lastError(); + } + createElementNomenclatureView(); createSummaryView(); createWiringListView(); @@ -2801,6 +2887,27 @@ void projectDataBase::createElementNomenclatureView() //See discussion #847. " AND e.type IN ('simple', 'terminal', 'master', 'slave', 'thumbnail')"); + //The spare terminals of the terminal strips (on no folio) are lines of + //the nomenclature too : the same columns, read in the spare_terminal + //table. They come after the folios (diagram_position), in the order + //of their strip (position). + { + const QString select_ = QStringLiteral(" AS SELECT "); + const auto begin_ = create_view.indexOf(select_) + select_.size(); + const auto end_ = create_view.indexOf(QStringLiteral(" FROM element_info ei")); + QString columns_ = create_view.mid(begin_, end_ - begin_); + columns_.replace(QStringLiteral("ei."), QStringLiteral("st.")); + columns_.replace(QStringLiteral("d.pos AS diagram_position"), QStringLiteral("st.diagram_position AS diagram_position")); + columns_.replace(QStringLiteral("e.type AS element_type"), QStringLiteral("'terminal' AS element_type")); + columns_.replace(QStringLiteral("e.sub_type AS element_sub_type"), QStringLiteral("NULL AS element_sub_type")); + columns_.replace(QStringLiteral("di.title AS title"), QStringLiteral("st.title AS title")); + columns_.replace(QStringLiteral("di.folio AS folio"), QStringLiteral("st.folio AS folio")); + columns_.replace(QStringLiteral("e.pos AS position"), QStringLiteral("st.position AS position")); + create_view += QStringLiteral(" UNION ALL SELECT ") + columns_ + + QStringLiteral(" FROM spare_terminal st" + " WHERE COALESCE(LOWER(TRIM(st.exclude_from_bom)), '') NOT IN ('true', '1', 'yes', 'on')"); + } + QSqlQuery query(m_data_base); if (!query.exec(create_view)) { qDebug() << query.lastError(); diff --git a/sources/dataBase/projectdatabase.h b/sources/dataBase/projectdatabase.h index a34d52536..02f351d07 100644 --- a/sources/dataBase/projectdatabase.h +++ b/sources/dataBase/projectdatabase.h @@ -234,6 +234,7 @@ class projectDataBase : public QObject void elementMoved(); public: + void spareTerminalsChanged(); signals: void dataBaseUpdated(); @@ -250,6 +251,7 @@ class projectDataBase : public QObject void populateElementTable(); void populateElementInfoTable(); void populateElementInfoTableFromFolios(); + void populateSpareTerminalTable(); void populateDiagramInfoTable(); void populateConductorTable(); void populateLinkTable(); diff --git a/sources/qetproject.cpp b/sources/qetproject.cpp index 9b5510f3c..c63d09602 100644 --- a/sources/qetproject.cpp +++ b/sources/qetproject.cpp @@ -4506,9 +4506,30 @@ TerminalStrip *QETProject::newTerminalStrip(QString installation, QString locati this); m_terminal_strip_vector.append(ts); + watchTerminalStrip(ts); return ts; } +/** + * @brief QETProject::watchTerminalStrip + * The spare terminals of @a strip (on no folio) are lines of the + * nomenclature : keep the database up to date with them. + * @param strip + * @param watch : false to stop watching @a strip + */ +void QETProject::watchTerminalStrip(TerminalStrip *strip, bool watch) +{ + if (!strip) { + return; + } + disconnect(strip, nullptr, &m_data_base, nullptr); + if (watch) { + connect(strip, &TerminalStrip::orderChanged, &m_data_base, &projectDataBase::spareTerminalsChanged); + connect(strip, &TerminalStrip::dataChanged, &m_data_base, &projectDataBase::spareTerminalsChanged); + } + m_data_base.spareTerminalsChanged(); +} + /** * @brief QETProject::addTerminalStrip * Add \p strip to the terminal strip list of the project. @@ -4525,6 +4546,7 @@ bool QETProject::addTerminalStrip(TerminalStrip *strip) return true; m_terminal_strip_vector.append(strip); + watchTerminalStrip(strip); return true; } @@ -4535,8 +4557,13 @@ bool QETProject::addTerminalStrip(TerminalStrip *strip) * @param strip * @return true if successfully removed. */ -bool QETProject::removeTerminalStrip(TerminalStrip *strip) { - return m_terminal_strip_vector.removeOne(strip); +bool QETProject::removeTerminalStrip(TerminalStrip *strip) +{ + const bool removed_ = m_terminal_strip_vector.removeOne(strip); + if (removed_) { + watchTerminalStrip(strip, false); + } + return removed_; } /** diff --git a/sources/qetproject.h b/sources/qetproject.h index 4b3dc7986..aeb87a1b5 100644 --- a/sources/qetproject.h +++ b/sources/qetproject.h @@ -443,6 +443,7 @@ class QETProject : public QObject } private: + void watchTerminalStrip(TerminalStrip *strip, bool watch = true); bool stampSaved(); void readProjectXml(QDomDocument &xml_project); void readDiagramsXml(QDomDocument &xml_project);