This commit is contained in:
Kellermorph
2026-08-01 14:26:39 +02:00
parent 4c1f82f814
commit e91bab14fe
6 changed files with 162 additions and 98 deletions
+6
View File
@@ -390,6 +390,12 @@ void projectDataBase::createElementNomenclatureView()
"ei.unity_auxiliary4 AS unity_auxiliary4," "ei.unity_auxiliary4 AS unity_auxiliary4,"
"ei.exclude_from_bom AS exclude_from_bom," "ei.exclude_from_bom AS exclude_from_bom,"
"ei.plc_type AS plc_type,"
"ei.plc_address AS plc_address,"
"ei.plc_function AS plc_function,"
"ei.plc_comment AS plc_comment,"
"ei.plc_crossref AS plc_crossref,"
"d.pos AS diagram_position," "d.pos AS diagram_position,"
"e.type AS element_type," "e.type AS element_type,"
"e.sub_type AS element_sub_type," "e.sub_type AS element_sub_type,"
+13 -3
View File
@@ -47,6 +47,7 @@ ElementQueryWidget::ElementQueryWidget(QWidget *parent) :
m_button_group.addButton(ui->m_coil_cb, 4); m_button_group.addButton(ui->m_coil_cb, 4);
m_button_group.addButton(ui->m_protection_cb, 5); m_button_group.addButton(ui->m_protection_cb, 5);
m_button_group.addButton(ui->m_thumbnail_cb, 6); m_button_group.addButton(ui->m_thumbnail_cb, 6);
m_button_group.addButton(ui->m_plc_cb, 7);
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) // ### Qt 6: remove #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) // ### Qt 6: remove
connect(&m_button_group, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), [this](int id) connect(&m_button_group, static_cast<void (QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked), [this](int id)
#else #else
@@ -76,7 +77,7 @@ ElementQueryWidget::ElementQueryWidget(QWidget *parent) :
else else
{ {
int checked = 0; int checked = 0;
for (int i=1 ; i<7 ; ++i) { for (int i=1 ; i<8 ; ++i) {
if (m_button_group.button(i)->isChecked()) {++checked;} if (m_button_group.button(i)->isChecked()) {++checked;}
} }
@@ -85,7 +86,7 @@ ElementQueryWidget::ElementQueryWidget(QWidget *parent) :
case 0 : case 0 :
check_box->setCheckState(Qt::Unchecked); check_box->setCheckState(Qt::Unchecked);
break; break;
case 6: case 7:
check_box->setCheckState(Qt::Checked); check_box->setCheckState(Qt::Checked);
break; break;
default: default:
@@ -191,8 +192,12 @@ void ElementQueryWidget::setQuery(const QString &query)
if (ui->m_thumbnail_cb->isChecked()) { if (ui->m_thumbnail_cb->isChecked()) {
++c; ++c;
} }
ui->m_plc_cb->setChecked (str_type.contains(ElementData::masterTypeToString(ElementData::PLC)) ? true : false);
if (ui->m_plc_cb->isChecked()) {
++c;
}
if (c == 6) { if (c == 7) {
ui->m_all_cb->setCheckState(Qt::Checked); ui->m_all_cb->setCheckState(Qt::Checked);
} else if (c > 0) { } else if (c > 0) {
ui->m_all_cb->setCheckState(Qt::PartiallyChecked); ui->m_all_cb->setCheckState(Qt::PartiallyChecked);
@@ -366,6 +371,11 @@ QString ElementQueryWidget::queryStr() const
if (ui->m_protection_cb->isChecked()) { if (ui->m_protection_cb->isChecked()) {
if (b) where +=" OR"; if (b) where +=" OR";
where += QStringLiteral(" element_sub_type = '") += ElementData::masterTypeToString(ElementData::Protection) += "'"; where += QStringLiteral(" element_sub_type = '") += ElementData::masterTypeToString(ElementData::Protection) += "'";
b = true;
}
if (ui->m_plc_cb->isChecked()) {
if (b) where +=" OR";
where += QStringLiteral(" element_sub_type = '") += ElementData::masterTypeToString(ElementData::PLC) += "'";
} }
where.append(")"); where.append(")");
+38 -28
View File
@@ -242,26 +242,6 @@
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property> </property>
<layout class="QGridLayout" name="gridLayout_4"> <layout class="QGridLayout" name="gridLayout_4">
<item row="5" column="0">
<widget class="QCheckBox" name="m_simple_cb">
<property name="text">
<string>Simples</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QCheckBox" name="m_protection_cb">
<property name="text">
<string>Organes de protection</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QCheckBox" name="m_all_cb"> <widget class="QCheckBox" name="m_all_cb">
<property name="text"> <property name="text">
@@ -272,17 +252,17 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="0" column="1">
<widget class="QCheckBox" name="m_button_cb"> <widget class="QCheckBox" name="m_simple_cb">
<property name="text"> <property name="text">
<string>Boutons et commutateurs</string> <string>Simples</string>
</property> </property>
<property name="checked"> <property name="checked">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="1" column="0">
<widget class="QCheckBox" name="m_terminal_cb"> <widget class="QCheckBox" name="m_terminal_cb">
<property name="text"> <property name="text">
<string>Borniers</string> <string>Borniers</string>
@@ -292,7 +272,27 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="1" column="1">
<widget class="QCheckBox" name="m_protection_cb">
<property name="text">
<string>Organes de protection</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="m_coil_cb">
<property name="text">
<string>Contacteurs et relais</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="m_thumbnail_cb"> <widget class="QCheckBox" name="m_thumbnail_cb">
<property name="text"> <property name="text">
<string>Vignettes</string> <string>Vignettes</string>
@@ -302,10 +302,20 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="3" column="0">
<widget class="QCheckBox" name="m_coil_cb"> <widget class="QCheckBox" name="m_button_cb">
<property name="text"> <property name="text">
<string>Contacteurs et relais</string> <string>Boutons et commutateurs</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="m_plc_cb">
<property name="text">
<string>Automates (MAE/SPS)</string>
</property> </property>
<property name="checked"> <property name="checked">
<bool>true</bool> <bool>true</bool>
@@ -683,7 +683,7 @@ void ElementPropertiesEditorWidget::createPlcConfigWidgets()
m_plc_table->horizontalHeader()->resizeSection(2, 150); m_plc_table->horizontalHeader()->resizeSection(2, 150);
m_plc_table->horizontalHeader()->resizeSection(3, 150); m_plc_table->horizontalHeader()->resizeSection(3, 150);
m_plc_table->horizontalHeader()->resizeSection(4, 100); m_plc_table->horizontalHeader()->resizeSection(4, 100);
m_plc_table->setSelectionBehavior(QAbstractItemView::SelectRows); m_plc_table->setSelectionBehavior(QAbstractItemView::SelectItems);
m_plc_table->setSelectionMode(QAbstractItemView::ExtendedSelection); m_plc_table->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_plc_table->setMinimumHeight(200); m_plc_table->setMinimumHeight(200);
tables_splitter->addWidget(m_plc_table); tables_splitter->addWidget(m_plc_table);
@@ -697,7 +697,7 @@ void ElementPropertiesEditorWidget::createPlcConfigWidgets()
m_plc_terminal_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); m_plc_terminal_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
m_plc_terminal_table->horizontalHeader()->resizeSection(0, 50); m_plc_terminal_table->horizontalHeader()->resizeSection(0, 50);
m_plc_terminal_table->horizontalHeader()->resizeSection(1, 80); m_plc_terminal_table->horizontalHeader()->resizeSection(1, 80);
m_plc_terminal_table->setSelectionBehavior(QAbstractItemView::SelectRows); m_plc_terminal_table->setSelectionBehavior(QAbstractItemView::SelectItems);
m_plc_terminal_table->setSelectionMode(QAbstractItemView::ExtendedSelection); m_plc_terminal_table->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_plc_terminal_table->setMinimumHeight(200); m_plc_terminal_table->setMinimumHeight(200);
tables_splitter->addWidget(m_plc_terminal_table); tables_splitter->addWidget(m_plc_terminal_table);
+11 -3
View File
@@ -1397,16 +1397,20 @@ void Element::setElementInformations(DiagramContext dc)
} }
emit elementInfoChange(old_info, m_data.m_informations); emit elementInfoChange(old_info, m_data.m_informations);
// Propagate label change to linked PLC slaves // Propagate label change to linked PLC slaves (label is changed via
// setElementInformations through the undo stack, not via setElementData)
if (m_data.m_type == ElementData::Master && m_data.m_master_type == ElementData::PLC) if (m_data.m_type == ElementData::Master && m_data.m_master_type == ElementData::PLC)
{ {
if (!m_group_index_map.isEmpty()) { if (!m_group_index_map.isEmpty())
{
const QString new_label = actualLabel(); const QString new_label = actualLabel();
for (auto it = m_group_index_map.constBegin(); it != m_group_index_map.constEnd(); ++it) for (auto it = m_group_index_map.constBegin(); it != m_group_index_map.constEnd(); ++it)
{ {
Element *slave = it.key(); Element *slave = it.key();
if (!slave) if (!slave)
continue; continue;
if (slave->elementInformations().value(QETInformation::ELMT_LABEL).toString() == new_label)
continue;
DiagramContext ctx = slave->elementInformations(); DiagramContext ctx = slave->elementInformations();
ctx.addValue(QETInformation::ELMT_LABEL, new_label); ctx.addValue(QETInformation::ELMT_LABEL, new_label);
slave->setElementInformations(ctx); slave->setElementInformations(ctx);
@@ -1480,6 +1484,7 @@ void Element::setElementData(ElementData data)
return autonum::AssignVariables::formulaToLabel( return autonum::AssignVariables::formulaToLabel(
xrp.slaveLabel(), seq, diagram(), this); xrp.slaveLabel(), seq, diagram(), this);
}()); }());
ctx.addValue(QETInformation::ELMT_LABEL, actualLabel());
ctx.addValue(QETInformation::ELMT_PLC_TC, ctx.addValue(QETInformation::ELMT_PLC_TC,
QString::number(io.terminalCount)); QString::number(io.terminalCount));
for (int t = 0; t < io.terminalCount && t < 4; ++t) for (int t = 0; t < io.terminalCount && t < 4; ++t)
@@ -1511,7 +1516,7 @@ void Element::setElementData(ElementData data)
} }
} }
} }
else if (label_changed) if (label_changed)
{ {
// Only label changed, update the label on the slave // Only label changed, update the label on the slave
DiagramContext ctx = slave->elementInformations(); DiagramContext ctx = slave->elementInformations();
@@ -1958,7 +1963,10 @@ void Element::drawPlcTable(QPainter *painter)
} }
QRectF text_rect = cr.adjusted(1, 0, -1, 0); QRectF text_rect = cr.adjusted(1, 0, -1, 0);
painter->save();
painter->setClipRect(text_rect, Qt::IntersectClip);
painter->drawText(text_rect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextWordWrap, cell_text); painter->drawText(text_rect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextWordWrap, cell_text);
painter->restore();
cx += col_widths[col]; cx += col_widths[col];
} }
+33 -3
View File
@@ -216,6 +216,16 @@ void MasterPropertiesWidget::reset()
*/ */
QUndoCommand* MasterPropertiesWidget::associatedUndo() const QUndoCommand* MasterPropertiesWidget::associatedUndo() const
{ {
// PLC masters manage their slave links via the IO table (setElementData),
// not via the link tree widget. The link tree is always empty for PLC
// masters, so we must not create an unlinkAll command.
if (m_element &&
m_element->elementData().m_type == ElementData::Master &&
m_element->elementData().m_master_type == ElementData::PLC)
{
return nullptr;
}
QList <Element *> to_link; QList <Element *> to_link;
QList <Element *> linked_ = m_element->linkedElements(); QList <Element *> linked_ = m_element->linkedElements();
@@ -880,6 +890,8 @@ void MasterPropertiesWidget::plcRemoveRow()
if (selected.isEmpty()) if (selected.isEmpty())
return; return;
m_plc_updating = true;
// Remove from bottom to top to preserve indices // Remove from bottom to top to preserve indices
std::sort(selected.begin(), selected.end(), std::sort(selected.begin(), selected.end(),
[](const QModelIndex &a, const QModelIndex &b) { return a.row() > b.row(); }); [](const QModelIndex &a, const QModelIndex &b) { return a.row() > b.row(); });
@@ -887,6 +899,9 @@ void MasterPropertiesWidget::plcRemoveRow()
for (const QModelIndex &idx : selected) { for (const QModelIndex &idx : selected) {
m_plc_table->removeRow(idx.row()); m_plc_table->removeRow(idx.row());
} }
m_plc_updating = false;
plcUpdateDisplaySettings();
} }
/** /**
@@ -902,6 +917,8 @@ void MasterPropertiesWidget::plcMoveRowUp()
if (row <= 0) if (row <= 0)
return; return;
m_plc_updating = true;
// Swap with row above // Swap with row above
for (int col = 0; col < m_plc_table->columnCount(); ++col) { for (int col = 0; col < m_plc_table->columnCount(); ++col) {
QWidget *w1 = m_plc_table->cellWidget(row, col); QWidget *w1 = m_plc_table->cellWidget(row, col);
@@ -916,6 +933,8 @@ void MasterPropertiesWidget::plcMoveRowUp()
} }
m_plc_table->setCurrentCell(row - 1, m_plc_table->currentColumn()); m_plc_table->setCurrentCell(row - 1, m_plc_table->currentColumn());
m_plc_updating = false;
plcUpdateDisplaySettings();
} }
/** /**
@@ -931,6 +950,8 @@ void MasterPropertiesWidget::plcMoveRowDown()
if (row < 0 || row >= m_plc_table->rowCount() - 1) if (row < 0 || row >= m_plc_table->rowCount() - 1)
return; return;
m_plc_updating = true;
// Swap with row below // Swap with row below
for (int col = 0; col < m_plc_table->columnCount(); ++col) { for (int col = 0; col < m_plc_table->columnCount(); ++col) {
QWidget *w1 = m_plc_table->cellWidget(row, col); QWidget *w1 = m_plc_table->cellWidget(row, col);
@@ -945,6 +966,8 @@ void MasterPropertiesWidget::plcMoveRowDown()
} }
m_plc_table->setCurrentCell(row + 1, m_plc_table->currentColumn()); m_plc_table->setCurrentCell(row + 1, m_plc_table->currentColumn());
m_plc_updating = false;
plcUpdateDisplaySettings();
} }
/** /**
@@ -978,6 +1001,13 @@ void MasterPropertiesWidget::plcUpdateDisplaySettings()
ElementData::PlcMasterData plc_data = ed.plcMasterData(); ElementData::PlcMasterData plc_data = ed.plcMasterData();
plc_data.ios.clear(); 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
for (int row = 0; row < m_plc_table->rowCount(); ++row) { for (int row = 0; row < m_plc_table->rowCount(); ++row) {
ElementData::PlcIO io; ElementData::PlcIO io;
@@ -1002,9 +1032,9 @@ void MasterPropertiesWidget::plcUpdateDisplaySettings()
if (crossref_item) if (crossref_item)
io.crossRef = crossref_item->text(); io.crossRef = crossref_item->text();
// Preserve terminal data from the original IO // Preserve terminal data by looking up original IO via address
if (row < ed.plcMasterData().ios.size()) { if (addr_to_orig_idx.contains(io.address)) {
const auto &orig_io = ed.plcMasterData().ios.at(row); const auto &orig_io = ed.plcMasterData().ios.at(addr_to_orig_idx.value(io.address));
io.terminalCount = orig_io.terminalCount; io.terminalCount = orig_io.terminalCount;
io.terminals = orig_io.terminals; io.terminals = orig_io.terminals;
} }