mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-05 02:24:13 +02:00
fix
This commit is contained in:
@@ -99,6 +99,19 @@ class ElementData : public PropertiesInterface
|
||||
int terminalCount = 1; ///< Number of terminals for this IO (1-4)
|
||||
QStringList terminals; ///< Terminal values T1, T2, ... (size = terminalCount)
|
||||
|
||||
/**
|
||||
* @brief Return terminal labels, generating defaults (T1, T2...) if empty
|
||||
*/
|
||||
QStringList effectiveTerminals() const {
|
||||
if (!terminals.isEmpty())
|
||||
return terminals;
|
||||
int count = qMax(terminalCount, 1);
|
||||
QStringList defaults;
|
||||
for (int i = 0; i < count && i < 4; ++i)
|
||||
defaults << QStringLiteral("T%1").arg(i + 1);
|
||||
return defaults;
|
||||
}
|
||||
|
||||
bool operator==(const PlcIO &other) const {
|
||||
return type == other.type
|
||||
&& address == other.address
|
||||
|
||||
@@ -38,6 +38,15 @@
|
||||
#include "dynamicelementtextitem.h"
|
||||
#include "elementtextitemgroup.h"
|
||||
#include "iostream"
|
||||
|
||||
#include <QCollator>
|
||||
|
||||
static const QString plcTerminalKeys[] = {
|
||||
QETInformation::ELMT_PLC_T1,
|
||||
QETInformation::ELMT_PLC_T2,
|
||||
QETInformation::ELMT_PLC_T3,
|
||||
QETInformation::ELMT_PLC_T4
|
||||
};
|
||||
#include "../qetxml.h"
|
||||
#include "../qetversion.h"
|
||||
#include "qgraphicsitemutility.h"
|
||||
@@ -1511,13 +1520,7 @@ void Element::setElementData(ElementData data)
|
||||
{
|
||||
QString val = (t < io.terminals.size())
|
||||
? io.terminals.at(t) : QString();
|
||||
ctx.addValue(
|
||||
QStringList({
|
||||
QETInformation::ELMT_PLC_T1,
|
||||
QETInformation::ELMT_PLC_T2,
|
||||
QETInformation::ELMT_PLC_T3,
|
||||
QETInformation::ELMT_PLC_T4
|
||||
}).at(t), val);
|
||||
ctx.addValue(plcTerminalKeys[t], val);
|
||||
}
|
||||
slave->setElementInformations(ctx);
|
||||
|
||||
|
||||
@@ -823,17 +823,15 @@ QUuid Terminal::uuid() const
|
||||
QString Terminal::name() const
|
||||
{
|
||||
if (d->m_use_master_label && parent_element_) {
|
||||
// Find the master element in the slave's linked elements
|
||||
for (Element *elmt : parent_element_->linkedElements()) {
|
||||
if (elmt->linkType() == Element::Master) {
|
||||
int group_idx = elmt->groupIndexForElement(parent_element_);
|
||||
if (group_idx >= 0) {
|
||||
// For PLC masters, use io.terminals as labels
|
||||
if (elmt->elementData().m_master_type == ElementData::PLC) {
|
||||
const auto &plc_data = elmt->elementData().plcMasterData();
|
||||
if (group_idx < plc_data.ios.size()) {
|
||||
int label_idx = d->m_master_label_index;
|
||||
const QStringList &labels = plc_data.ios.at(group_idx).terminals;
|
||||
const QStringList labels = plc_data.ios.at(group_idx).effectiveTerminals();
|
||||
if (label_idx >= 0 && label_idx < labels.size()) {
|
||||
return labels.at(label_idx);
|
||||
}
|
||||
|
||||
@@ -979,14 +979,7 @@ void MasterPropertiesWidget::plcUpdateDisplaySettings()
|
||||
ElementData::PlcMasterData plc_data = ed.plcMasterData();
|
||||
plc_data.ios.clear();
|
||||
|
||||
// Build address -> original IO lookup to correctly reattach terminal data
|
||||
// after row reorder (move up/down) or row removal
|
||||
QHash<QString, int> addr_to_orig_idx;
|
||||
for (int i = 0; i < ed.plcMasterData().ios.size(); ++i) {
|
||||
addr_to_orig_idx[ed.plcMasterData().ios.at(i).address] = i;
|
||||
}
|
||||
|
||||
// Read IOs from table, preserving terminal data from original IOs
|
||||
// Read IOs from table, preserving terminal data from original IOs by row index
|
||||
for (int row = 0; row < m_plc_table->rowCount(); ++row) {
|
||||
ElementData::PlcIO io;
|
||||
|
||||
@@ -1010,9 +1003,12 @@ void MasterPropertiesWidget::plcUpdateDisplaySettings()
|
||||
if (crossref_item)
|
||||
io.crossRef = crossref_item->text();
|
||||
|
||||
// Preserve terminal data by looking up original IO via address
|
||||
if (addr_to_orig_idx.contains(io.address)) {
|
||||
const auto orig_io = ed.plcMasterData().ios.at(addr_to_orig_idx.value(io.address));
|
||||
// Preserve terminal data by matching row index directly.
|
||||
// This avoids address-based lookup which fails when all addresses
|
||||
// are empty (common in PLC masters) — a hash collision would cause
|
||||
// only the last IO's terminals to be used for all rows.
|
||||
if (row < ed.plcMasterData().ios.size()) {
|
||||
const auto &orig_io = ed.plcMasterData().ios.at(row);
|
||||
io.terminalCount = orig_io.terminalCount;
|
||||
io.terminals = orig_io.terminals;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,16 @@
|
||||
#include "../autoNum/assignvariables.h"
|
||||
#include "../autoNum/numerotationcontextcommands.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <QCollator>
|
||||
|
||||
static const QString plcTerminalKeys[] = {
|
||||
QETInformation::ELMT_PLC_T1,
|
||||
QETInformation::ELMT_PLC_T2,
|
||||
QETInformation::ELMT_PLC_T3,
|
||||
QETInformation::ELMT_PLC_T4
|
||||
};
|
||||
|
||||
/**
|
||||
@brief Get the cross-ref text for a slave element using XRefProperties formula
|
||||
@param master the PLC master element
|
||||
@@ -408,15 +418,16 @@ void LinkElementCommand::makeLink(const QList<Element *> &element_list)
|
||||
// Set master labels on slave terminals
|
||||
if (elmt->elementData().m_master_type == ElementData::PLC)
|
||||
{
|
||||
// For PLC masters, use io.terminals as labels
|
||||
const auto &plc_data = elmt->elementData().plcMasterData();
|
||||
if (group_idx < plc_data.ios.size())
|
||||
{
|
||||
const QStringList &labels = plc_data.ios.at(group_idx).terminals;
|
||||
const QStringList labels = plc_data.ios.at(group_idx).effectiveTerminals();
|
||||
QList<Terminal *> slave_terms = m_element->terminals();
|
||||
QCollator collator;
|
||||
collator.setNumericMode(true);
|
||||
std::sort(slave_terms.begin(), slave_terms.end(),
|
||||
[](Terminal *a, Terminal *b) {
|
||||
return a->baseName() < b->baseName();
|
||||
[&collator](Terminal *a, Terminal *b) {
|
||||
return collator.compare(a->baseName(), b->baseName()) < 0;
|
||||
});
|
||||
for (int i = 0; i < slave_terms.size(); ++i)
|
||||
{
|
||||
@@ -426,6 +437,29 @@ void LinkElementCommand::makeLink(const QList<Element *> &element_list)
|
||||
slave_terms.at(i)->setMasterLabelIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Populate PLC variables on the slave
|
||||
const auto &io = plc_data.ios.at(group_idx);
|
||||
DiagramContext ctx = m_element->elementInformations();
|
||||
ctx.addValue(QETInformation::ELMT_PLC_TYPE,
|
||||
ElementData::translatedPlcIOType(io.type));
|
||||
ctx.addValue(QETInformation::ELMT_PLC_ADDRESS, io.address);
|
||||
ctx.addValue(QETInformation::ELMT_PLC_FUNCTION, io.functionText);
|
||||
ctx.addValue(QETInformation::ELMT_PLC_COMMENT, io.comment);
|
||||
ctx.addValue(QETInformation::ELMT_PLC_CROSSREF,
|
||||
plcCrossRefText(elmt, m_element));
|
||||
ctx.addValue(QETInformation::ELMT_LABEL,
|
||||
elmt->actualLabel());
|
||||
ctx.addValue(QETInformation::ELMT_PLC_TC,
|
||||
QString::number(io.terminalCount));
|
||||
const QStringList eff_terms = io.effectiveTerminals();
|
||||
for (int t = 0; t < io.terminalCount && t < 4; ++t)
|
||||
{
|
||||
QString val = (t < eff_terms.size())
|
||||
? eff_terms.at(t) : QString();
|
||||
ctx.addValue(plcTerminalKeys[t], val);
|
||||
}
|
||||
m_element->setElementInformations(ctx);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -435,9 +469,11 @@ void LinkElementCommand::makeLink(const QList<Element *> &element_list)
|
||||
{
|
||||
const QStringList &labels = groups.at(group_idx).labels;
|
||||
QList<Terminal *> slave_terms = m_element->terminals();
|
||||
QCollator collator;
|
||||
collator.setNumericMode(true);
|
||||
std::sort(slave_terms.begin(), slave_terms.end(),
|
||||
[](Terminal *a, Terminal *b) {
|
||||
return a->baseName() < b->baseName();
|
||||
[&collator](Terminal *a, Terminal *b) {
|
||||
return collator.compare(a->baseName(), b->baseName()) < 0;
|
||||
});
|
||||
for (int i = 0; i < slave_terms.size(); ++i)
|
||||
{
|
||||
@@ -450,41 +486,6 @@ void LinkElementCommand::makeLink(const QList<Element *> &element_list)
|
||||
}
|
||||
}
|
||||
|
||||
// Populate PLC variables on the slave if master is PLC type
|
||||
if (elmt->elementData().m_master_type == ElementData::PLC)
|
||||
{
|
||||
const auto &plc_data = elmt->elementData().plcMasterData();
|
||||
if (group_idx < plc_data.ios.size())
|
||||
{
|
||||
const auto &io = plc_data.ios.at(group_idx);
|
||||
DiagramContext ctx = m_element->elementInformations();
|
||||
ctx.addValue(QETInformation::ELMT_PLC_TYPE,
|
||||
ElementData::translatedPlcIOType(io.type));
|
||||
ctx.addValue(QETInformation::ELMT_PLC_ADDRESS, io.address);
|
||||
ctx.addValue(QETInformation::ELMT_PLC_FUNCTION, io.functionText);
|
||||
ctx.addValue(QETInformation::ELMT_PLC_COMMENT, io.comment);
|
||||
ctx.addValue(QETInformation::ELMT_PLC_CROSSREF,
|
||||
plcCrossRefText(elmt, m_element));
|
||||
ctx.addValue(QETInformation::ELMT_LABEL,
|
||||
elmt->actualLabel());
|
||||
ctx.addValue(QETInformation::ELMT_PLC_TC,
|
||||
QString::number(io.terminalCount));
|
||||
for (int t = 0; t < io.terminalCount && t < 4; ++t)
|
||||
{
|
||||
QString val = (t < io.terminals.size())
|
||||
? io.terminals.at(t) : QString();
|
||||
ctx.addValue(
|
||||
QStringList({
|
||||
QETInformation::ELMT_PLC_T1,
|
||||
QETInformation::ELMT_PLC_T2,
|
||||
QETInformation::ELMT_PLC_T3,
|
||||
QETInformation::ELMT_PLC_T4
|
||||
}).at(t), val);
|
||||
}
|
||||
m_element->setElementInformations(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -507,11 +508,13 @@ void LinkElementCommand::makeLink(const QList<Element *> &element_list)
|
||||
const auto &plc_data = m_element->elementData().plcMasterData();
|
||||
if (group_idx < plc_data.ios.size())
|
||||
{
|
||||
const QStringList &labels = plc_data.ios.at(group_idx).terminals;
|
||||
const QStringList labels = plc_data.ios.at(group_idx).effectiveTerminals();
|
||||
QList<Terminal *> slave_terms = slave->terminals();
|
||||
QCollator collator;
|
||||
collator.setNumericMode(true);
|
||||
std::sort(slave_terms.begin(), slave_terms.end(),
|
||||
[](Terminal *a, Terminal *b) {
|
||||
return a->baseName() < b->baseName();
|
||||
[&collator](Terminal *a, Terminal *b) {
|
||||
return collator.compare(a->baseName(), b->baseName()) < 0;
|
||||
});
|
||||
for (int i = 0; i < slave_terms.size(); ++i)
|
||||
{
|
||||
@@ -530,9 +533,11 @@ void LinkElementCommand::makeLink(const QList<Element *> &element_list)
|
||||
{
|
||||
const QStringList &labels = groups.at(group_idx).labels;
|
||||
QList<Terminal *> slave_terms = slave->terminals();
|
||||
QCollator collator;
|
||||
collator.setNumericMode(true);
|
||||
std::sort(slave_terms.begin(), slave_terms.end(),
|
||||
[](Terminal *a, Terminal *b) {
|
||||
return a->name() < b->name();
|
||||
[&collator](Terminal *a, Terminal *b) {
|
||||
return collator.compare(a->baseName(), b->baseName()) < 0;
|
||||
});
|
||||
for (int i = 0; i < slave_terms.size(); ++i)
|
||||
{
|
||||
@@ -564,17 +569,12 @@ void LinkElementCommand::makeLink(const QList<Element *> &element_list)
|
||||
m_element->actualLabel());
|
||||
ctx.addValue(QETInformation::ELMT_PLC_TC,
|
||||
QString::number(io.terminalCount));
|
||||
const QStringList eff_terms = io.effectiveTerminals();
|
||||
for (int t = 0; t < io.terminalCount && t < 4; ++t)
|
||||
{
|
||||
QString val = (t < io.terminals.size())
|
||||
? io.terminals.at(t) : QString();
|
||||
ctx.addValue(
|
||||
QStringList({
|
||||
QETInformation::ELMT_PLC_T1,
|
||||
QETInformation::ELMT_PLC_T2,
|
||||
QETInformation::ELMT_PLC_T3,
|
||||
QETInformation::ELMT_PLC_T4
|
||||
}).at(t), val);
|
||||
QString val = (t < eff_terms.size())
|
||||
? eff_terms.at(t) : QString();
|
||||
ctx.addValue(plcTerminalKeys[t], val);
|
||||
}
|
||||
slave->setElementInformations(ctx);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user