From e91bab14fe11f71698ad0163672becee1b8e5e7a Mon Sep 17 00:00:00 2001 From: Kellermorph Date: Sat, 1 Aug 2026 14:26:39 +0200 Subject: [PATCH] Update --- sources/dataBase/projectdatabase.cpp | 12 +- sources/dataBase/ui/elementquerywidget.cpp | 24 ++- sources/dataBase/ui/elementquerywidget.ui | 170 +++++++++--------- .../ui/elementpropertieseditorwidget.cpp | 4 +- sources/qetgraphicsitem/element.cpp | 14 +- sources/ui/masterpropertieswidget.cpp | 36 +++- 6 files changed, 162 insertions(+), 98 deletions(-) diff --git a/sources/dataBase/projectdatabase.cpp b/sources/dataBase/projectdatabase.cpp index b1cd048bb..eacbeb712 100644 --- a/sources/dataBase/projectdatabase.cpp +++ b/sources/dataBase/projectdatabase.cpp @@ -388,9 +388,15 @@ void projectDataBase::createElementNomenclatureView() "ei.supplier_auxiliary4 AS supplier_auxiliary4," "ei.quantity_auxiliary4 AS quantity_auxiliary4," "ei.unity_auxiliary4 AS unity_auxiliary4," - "ei.exclude_from_bom AS exclude_from_bom," - - "d.pos AS diagram_position," + "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," "e.type AS element_type," "e.sub_type AS element_sub_type," "di.title AS title," diff --git a/sources/dataBase/ui/elementquerywidget.cpp b/sources/dataBase/ui/elementquerywidget.cpp index f7eb0dd46..ccc59fb6d 100644 --- a/sources/dataBase/ui/elementquerywidget.cpp +++ b/sources/dataBase/ui/elementquerywidget.cpp @@ -47,6 +47,7 @@ ElementQueryWidget::ElementQueryWidget(QWidget *parent) : m_button_group.addButton(ui->m_coil_cb, 4); m_button_group.addButton(ui->m_protection_cb, 5); 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 connect(&m_button_group, static_cast(&QButtonGroup::buttonClicked), [this](int id) #else @@ -76,7 +77,7 @@ ElementQueryWidget::ElementQueryWidget(QWidget *parent) : else { 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;} } @@ -85,7 +86,7 @@ ElementQueryWidget::ElementQueryWidget(QWidget *parent) : case 0 : check_box->setCheckState(Qt::Unchecked); break; - case 6: + case 7: check_box->setCheckState(Qt::Checked); break; default: @@ -187,12 +188,16 @@ void ElementQueryWidget::setQuery(const QString &query) if (ui->m_protection_cb) { ++c; } - ui->m_thumbnail_cb->setChecked (str_type.contains(ElementData::typeToString(ElementData::Thumbnail)) ? true : false); - if (ui->m_thumbnail_cb->isChecked()) { - ++c; - } + ui->m_thumbnail_cb->setChecked (str_type.contains(ElementData::typeToString(ElementData::Thumbnail)) ? true : false); + if (ui->m_thumbnail_cb->isChecked()) { + ++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); } else if (c > 0) { ui->m_all_cb->setCheckState(Qt::PartiallyChecked); @@ -366,6 +371,11 @@ QString ElementQueryWidget::queryStr() const if (ui->m_protection_cb->isChecked()) { if (b) where +=" OR"; 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(")"); diff --git a/sources/dataBase/ui/elementquerywidget.ui b/sources/dataBase/ui/elementquerywidget.ui index d1b04f227..7f3ae30fb 100644 --- a/sources/dataBase/ui/elementquerywidget.ui +++ b/sources/dataBase/ui/elementquerywidget.ui @@ -234,86 +234,96 @@ 0 - - - Type d'éléments - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - Simples - - - true - - - - - - - Organes de protection - - - true - - - - - - - Tous - - - true - - - - - - - Boutons et commutateurs - - - true - - - - - - - Borniers - - - true - - - - - - - Vignettes - - - true - - - - - - - Contacteurs et relais - - - true - - - - - + + + Type d'éléments + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + Tous + + + true + + + + + + + Simples + + + true + + + + + + + Borniers + + + true + + + + + + + Organes de protection + + + true + + + + + + + Contacteurs et relais + + + true + + + + + + + Vignettes + + + true + + + + + + + Boutons et commutateurs + + + true + + + + + + + Automates (MAE/SPS) + + + true + + + + + diff --git a/sources/editor/ui/elementpropertieseditorwidget.cpp b/sources/editor/ui/elementpropertieseditorwidget.cpp index 9c0407d21..4500a1734 100644 --- a/sources/editor/ui/elementpropertieseditorwidget.cpp +++ b/sources/editor/ui/elementpropertieseditorwidget.cpp @@ -683,7 +683,7 @@ void ElementPropertiesEditorWidget::createPlcConfigWidgets() m_plc_table->horizontalHeader()->resizeSection(2, 150); m_plc_table->horizontalHeader()->resizeSection(3, 150); 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->setMinimumHeight(200); 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()->resizeSection(0, 50); 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->setMinimumHeight(200); tables_splitter->addWidget(m_plc_terminal_table); diff --git a/sources/qetgraphicsitem/element.cpp b/sources/qetgraphicsitem/element.cpp index 58d00dcd2..d6d12e312 100644 --- a/sources/qetgraphicsitem/element.cpp +++ b/sources/qetgraphicsitem/element.cpp @@ -1397,16 +1397,20 @@ void Element::setElementInformations(DiagramContext dc) } 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_group_index_map.isEmpty()) { + if (!m_group_index_map.isEmpty()) + { const QString new_label = actualLabel(); for (auto it = m_group_index_map.constBegin(); it != m_group_index_map.constEnd(); ++it) { Element *slave = it.key(); if (!slave) continue; + if (slave->elementInformations().value(QETInformation::ELMT_LABEL).toString() == new_label) + continue; DiagramContext ctx = slave->elementInformations(); ctx.addValue(QETInformation::ELMT_LABEL, new_label); slave->setElementInformations(ctx); @@ -1480,6 +1484,7 @@ void Element::setElementData(ElementData data) return autonum::AssignVariables::formulaToLabel( xrp.slaveLabel(), seq, diagram(), this); }()); + ctx.addValue(QETInformation::ELMT_LABEL, actualLabel()); ctx.addValue(QETInformation::ELMT_PLC_TC, QString::number(io.terminalCount)); 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 DiagramContext ctx = slave->elementInformations(); @@ -1958,7 +1963,10 @@ void Element::drawPlcTable(QPainter *painter) } 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->restore(); cx += col_widths[col]; } diff --git a/sources/ui/masterpropertieswidget.cpp b/sources/ui/masterpropertieswidget.cpp index d7f4d1182..e5952a5e5 100644 --- a/sources/ui/masterpropertieswidget.cpp +++ b/sources/ui/masterpropertieswidget.cpp @@ -216,6 +216,16 @@ void MasterPropertiesWidget::reset() */ 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 to_link; QList linked_ = m_element->linkedElements(); @@ -880,6 +890,8 @@ void MasterPropertiesWidget::plcRemoveRow() if (selected.isEmpty()) return; + m_plc_updating = true; + // Remove from bottom to top to preserve indices std::sort(selected.begin(), selected.end(), [](const QModelIndex &a, const QModelIndex &b) { return a.row() > b.row(); }); @@ -887,6 +899,9 @@ void MasterPropertiesWidget::plcRemoveRow() for (const QModelIndex &idx : selected) { m_plc_table->removeRow(idx.row()); } + + m_plc_updating = false; + plcUpdateDisplaySettings(); } /** @@ -902,6 +917,8 @@ void MasterPropertiesWidget::plcMoveRowUp() if (row <= 0) return; + m_plc_updating = true; + // Swap with row above for (int col = 0; col < m_plc_table->columnCount(); ++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_updating = false; + plcUpdateDisplaySettings(); } /** @@ -931,6 +950,8 @@ void MasterPropertiesWidget::plcMoveRowDown() if (row < 0 || row >= m_plc_table->rowCount() - 1) return; + m_plc_updating = true; + // Swap with row below for (int col = 0; col < m_plc_table->columnCount(); ++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_updating = false; + plcUpdateDisplaySettings(); } /** @@ -978,6 +1001,13 @@ 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 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 for (int row = 0; row < m_plc_table->rowCount(); ++row) { ElementData::PlcIO io; @@ -1002,9 +1032,9 @@ void MasterPropertiesWidget::plcUpdateDisplaySettings() if (crossref_item) io.crossRef = crossref_item->text(); - // Preserve terminal data from the original IO - if (row < ed.plcMasterData().ios.size()) { - const auto &orig_io = ed.plcMasterData().ios.at(row); + // 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)); io.terminalCount = orig_io.terminalCount; io.terminals = orig_io.terminals; }