Merge pull request #669 from Kellermorph/fix-plc-editor

PLC Fix scroll sync, data persistence, font defaults, copy/paste, and layout fixes
This commit is contained in:
Laurent Trinques
2026-08-06 08:03:22 +02:00
committed by GitHub
8 changed files with 452 additions and 87 deletions
+3 -2
View File
@@ -18,6 +18,7 @@
#include "partplctable.h"
#include "../../QPropertyUndoCommand/qpropertyundocommand.h"
#include "../../qetapp.h"
#include "../../QetGraphicsItemModeler/qetgraphicshandleritem.h"
#include "../../QetGraphicsItemModeler/qetgraphicshandlerutility.h"
#include "../../properties/elementdata.h"
@@ -302,7 +303,7 @@ void PartPlcTable::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
// Draw column headers
QFont header_font = plc_data.headerFont.family().isEmpty()
? painter->font() : plc_data.headerFont;
? QETApp::diagramTextsFont() : plc_data.headerFont;
header_font.setBold(true);
painter->setFont(header_font);
@@ -318,7 +319,7 @@ void PartPlcTable::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
// Draw IO rows
QFont cell_font = plc_data.cellFont.family().isEmpty()
? painter->font() : plc_data.cellFont;
? QETApp::diagramTextsFont() : plc_data.cellFont;
painter->setFont(cell_font);
int start_idx = block_starts.at(block);
int end_idx = (block + 1 < block_starts.size())
@@ -28,6 +28,8 @@
#include <QSignalBlocker>
#include <QTableWidgetItem>
#include <QHeaderView>
#include <QScrollBar>
#include <QWheelEvent>
#include <QTableWidget>
#include <QCheckBox>
#include <QGroupBox>
@@ -41,6 +43,8 @@
#include <QFont>
#include <QLineEdit>
#include <QSplitter>
#include <QShortcut>
#include <QMenu>
/**
@brief The EditorDelegate class
@@ -666,10 +670,15 @@ void ElementPropertiesEditorWidget::createPlcConfigWidgets()
plc_layout->addLayout(toolbar);
// Tables side by side: IO table (left) + Terminal table (right)
auto *tables_splitter = new QSplitter(Qt::Horizontal, m_plc_gb);
// Both share a single vertical scrollbar on the right
auto *tables_container = new QWidget(m_plc_gb);
auto *tables_layout = new QHBoxLayout(tables_container);
tables_layout->setContentsMargins(0, 0, 0, 0);
auto *splitter = new QSplitter(Qt::Horizontal, tables_container);
// IO Table
m_plc_table = new QTableWidget(tables_splitter);
m_plc_table = new QTableWidget(splitter);
m_plc_table->setColumnCount(5);
m_plc_table->setHorizontalHeaderLabels({
tr("Type"), tr("Adresse"), tr("Fonction"),
@@ -686,10 +695,10 @@ void ElementPropertiesEditorWidget::createPlcConfigWidgets()
m_plc_table->setSelectionBehavior(QAbstractItemView::SelectItems);
m_plc_table->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_plc_table->setMinimumHeight(200);
tables_splitter->addWidget(m_plc_table);
m_plc_table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// Terminal table (per IO: Nb + T1-T4)
m_plc_terminal_table = new QTableWidget(tables_splitter);
m_plc_terminal_table = new QTableWidget(splitter);
m_plc_terminal_table->setColumnCount(2);
m_plc_terminal_table->setHorizontalHeaderLabels({
tr("Nb."), tr("T1")
@@ -700,13 +709,61 @@ void ElementPropertiesEditorWidget::createPlcConfigWidgets()
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);
m_plc_terminal_table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
tables_splitter->setStretchFactor(0, 3);
tables_splitter->setStretchFactor(1, 1);
tables_splitter->setSizes({500, 150});
// Shared vertical scrollbar
m_plc_shared_scrollbar = new QScrollBar(Qt::Vertical, tables_container);
m_plc_shared_scrollbar->setMinimum(0);
plc_layout->addWidget(tables_splitter);
splitter->addWidget(m_plc_table);
splitter->addWidget(m_plc_terminal_table);
splitter->setStretchFactor(0, 3);
splitter->setStretchFactor(1, 1);
tables_layout->addWidget(splitter);
tables_layout->addWidget(m_plc_shared_scrollbar);
// Bidirectional sync between tables and shared scrollbar
// Use flag to prevent infinite loops
connect(m_plc_shared_scrollbar, &QScrollBar::valueChanged,
this, [this](int value) {
if (m_plc_scroll_sync) return;
m_plc_scroll_sync = true;
m_plc_table->verticalScrollBar()->setValue(value);
m_plc_terminal_table->verticalScrollBar()->setValue(value);
m_plc_scroll_sync = false;
});
connect(m_plc_table->verticalScrollBar(), &QScrollBar::valueChanged,
this, [this](int value) {
if (m_plc_scroll_sync) return;
m_plc_scroll_sync = true;
m_plc_shared_scrollbar->setValue(value);
m_plc_terminal_table->verticalScrollBar()->setValue(value);
m_plc_scroll_sync = false;
});
connect(m_plc_terminal_table->verticalScrollBar(), &QScrollBar::valueChanged,
this, [this](int value) {
if (m_plc_scroll_sync) return;
m_plc_scroll_sync = true;
m_plc_shared_scrollbar->setValue(value);
m_plc_table->verticalScrollBar()->setValue(value);
m_plc_scroll_sync = false;
});
// Update shared scrollbar range from both tables
auto syncRange = [this]() {
int max = qMax(m_plc_table->verticalScrollBar()->maximum(),
m_plc_terminal_table->verticalScrollBar()->maximum());
m_plc_shared_scrollbar->blockSignals(true);
m_plc_shared_scrollbar->setMaximum(max);
m_plc_shared_scrollbar->blockSignals(false);
};
connect(m_plc_table->verticalScrollBar(), &QScrollBar::rangeChanged,
this, syncRange);
connect(m_plc_terminal_table->verticalScrollBar(), &QScrollBar::rangeChanged,
this, syncRange);
plc_layout->addWidget(tables_container);
// Font settings
auto *font_layout = new QHBoxLayout();
@@ -790,12 +847,25 @@ void ElementPropertiesEditorWidget::createPlcConfigWidgets()
}
plc_layout->addLayout(col_layout);
// Add to master group box
ui->m_master_gb->layout()->addWidget(m_plc_gb);
// Add to master group box - row 4, full width
auto *gl = qobject_cast<QGridLayout*>(ui->m_master_gb->layout());
gl->addWidget(m_plc_gb, 4, 0, 1, 2);
// Connect signals
connect(add_btn, &QPushButton::clicked, this, &ElementPropertiesEditorWidget::plcAddRow);
connect(remove_btn, &QPushButton::clicked, this, &ElementPropertiesEditorWidget::plcRemoveRow);
// Ctrl+V shortcut for paste
auto *paste_shortcut = new QShortcut(QKeySequence::Paste, m_plc_table);
connect(paste_shortcut, &QShortcut::activated, this, &ElementPropertiesEditorWidget::plcPasteFromClipboard);
// Context menu for the PLC table
m_plc_table->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_plc_table, &QTableWidget::customContextMenuRequested, this, [this](const QPoint &pos) {
QMenu menu;
menu.addAction(tr("Coller depuis le presse-papiers"), this, &ElementPropertiesEditorWidget::plcPasteFromClipboard);
menu.exec(m_plc_table->mapToGlobal(pos));
});
}
/**
@@ -877,12 +947,12 @@ void ElementPropertiesEditorWidget::populatePlcTable()
m_plc_header_font = plc_data.headerFont;
m_plc_cell_font = plc_data.cellFont;
if (m_plc_header_font.family().isEmpty()) {
m_plc_header_font = QFont(m_plc_table->font());
m_plc_header_font = QETApp::diagramTextsFont();
m_plc_header_font.setBold(true);
m_plc_header_font.setPointSize(8);
}
if (m_plc_cell_font.family().isEmpty()) {
m_plc_cell_font = QFont(m_plc_table->font());
m_plc_cell_font = QETApp::diagramTextsFont();
m_plc_cell_font.setPointSize(8);
}
m_plc_header_font_btn->setText(tr("Police des en-têtes: %1 %2pt")
@@ -920,6 +990,21 @@ void ElementPropertiesEditorWidget::populatePlcTable()
hdr->moveSection(hdr->visualIndex(logical), visual);
}
}
// Ensure scrollbars stay hidden and sync shared scrollbar range
if (m_plc_table) {
m_plc_table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_plc_table->verticalScrollBar()->setVisible(false);
}
if (m_plc_terminal_table) {
m_plc_terminal_table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_plc_terminal_table->verticalScrollBar()->setVisible(false);
}
if (m_plc_shared_scrollbar && m_plc_table) {
int max = qMax(m_plc_table->verticalScrollBar()->maximum(),
m_plc_terminal_table->verticalScrollBar()->maximum());
m_plc_shared_scrollbar->setMaximum(max);
}
}
/**
@@ -1158,53 +1243,80 @@ void ElementPropertiesEditorWidget::plcPasteFromClipboard()
return;
QStringList lines = clipboard_text.split('\n', Qt::SkipEmptyParts);
if (lines.isEmpty())
return;
int start_row = m_plc_table->rowCount();
m_plc_table->setRowCount(start_row + lines.size());
for (int i = 0; i < lines.size(); ++i) {
QStringList cells = lines.at(i).split('\t');
int row = start_row + i;
// Type combo
auto *type_cb = new QComboBox(m_plc_table);
QStringList plc_types = ElementData::plcIOTypeList();
for (int t = 0; t < plc_types.size(); ++t) {
type_cb->addItem(plc_types.at(t), t);
}
// Try to match type from clipboard
if (!cells.isEmpty()) {
QString type_str = cells.at(0).trimmed();
int type_idx = -1;
for (int t = 0; t < plc_types.size(); ++t) {
if (plc_types.at(t).compare(type_str, Qt::CaseInsensitive) == 0) {
type_idx = t;
bool has_tabs = false;
for (const QString &line : lines) {
if (line.contains('\t')) {
has_tabs = true;
break;
}
}
if (type_idx >= 0)
type_cb->setCurrentIndex(type_idx);
if (!has_tabs) {
// Vertical paste: values go down the same column
int target_col = m_plc_table->currentColumn();
if (target_col < 0) target_col = 0;
int target_row = m_plc_table->currentRow();
if (target_row < 0) target_row = 0;
int max_rows = m_plc_table->rowCount();
for (int i = 0; i < lines.size(); ++i) {
int row = target_row + i;
if (row >= max_rows) break;
plcSetCellFromValue(row, target_col, lines.at(i).trimmed());
}
m_plc_table->setCellWidget(row, 0, type_cb);
} else {
// Horizontal paste: each line is a separate IO row
int target_row = m_plc_table->currentRow();
if (target_row < 0) target_row = 0;
int max_rows = m_plc_table->rowCount();
// Address
m_plc_table->setItem(row, 1, new QTableWidgetItem(
cells.size() > 1 ? cells.at(1).trimmed() : QString()));
for (int i = 0; i < lines.size(); ++i) {
int row = target_row + i;
if (row >= max_rows) break;
QStringList cells = lines.at(i).split('\t');
for (int c = 0; c < cells.size(); ++c) {
if (c > 4) break;
plcSetCellFromValue(row, c, cells.at(c).trimmed());
}
}
}
}
// Function text
m_plc_table->setItem(row, 2, new QTableWidgetItem(
cells.size() > 2 ? cells.at(2).trimmed() : QString()));
/**
* @brief ElementPropertiesEditorWidget::plcSetCellFromValue
* Set a single table cell value, respecting the column widget type.
*/
void ElementPropertiesEditorWidget::plcSetCellFromValue(int row, int col, const QString &val)
{
if (!m_plc_table || row < 0 || col < 0 || col > 4)
return;
// Comment
m_plc_table->setItem(row, 3, new QTableWidgetItem(
cells.size() > 3 ? cells.at(3).trimmed() : QString()));
// CrossRef (read-only)
auto *crossref_item = new QTableWidgetItem(
cells.size() > 4 ? cells.at(4).trimmed() : QString());
crossref_item->setFlags(crossref_item->flags() & ~Qt::ItemIsEditable);
m_plc_table->setItem(row, 4, crossref_item);
if (col == 0) {
auto *type_cb = qobject_cast<QComboBox*>(m_plc_table->cellWidget(row, col));
if (!type_cb)
return;
if (!val.isEmpty()) {
QStringList plc_types = ElementData::plcIOTypeList();
for (int t = 0; t < plc_types.size(); ++t) {
if (plc_types.at(t).compare(val, Qt::CaseInsensitive) == 0) {
type_cb->setCurrentIndex(t);
return;
}
}
}
}
else if (col == 4) {
// CrossRef - read-only
auto *item = new QTableWidgetItem(val);
item->setFlags(item->flags() & ~Qt::ItemIsEditable);
m_plc_table->setItem(row, col, item);
}
else {
// Text columns: Address, Function, Comment
m_plc_table->setItem(row, col, new QTableWidgetItem(val));
}
}
@@ -30,6 +30,7 @@ class QCheckBox;
class QGroupBox;
class QPushButton;
class QLineEdit;
class QScrollBar;
namespace Ui {
class ElementPropertiesEditorWidget;
@@ -74,6 +75,7 @@ class ElementPropertiesEditorWidget : public QDialog
void plcTerminalCountChanged(int row, int count);
void plcSelectHeaderFont();
void plcSelectCellFont();
void plcSetCellFromValue(int row, int col, const QString &val);
//ATTRIBUTES
private:
@@ -95,6 +97,8 @@ class ElementPropertiesEditorWidget : public QDialog
QList<QCheckBox *> m_plc_col_visibility_checkboxes;
QList<QSpinBox *> m_plc_col_width_spinboxes;
QList<QLineEdit *> m_plc_col_name_edits;
QScrollBar *m_plc_shared_scrollbar = nullptr;
bool m_plc_scroll_sync = false;
};
#endif // ELEMENTPROPERTIESEDITORWIDGET_H
@@ -39,6 +39,19 @@
<item>
<widget class="QComboBox" name="m_base_type_cb"/>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
@@ -94,16 +107,33 @@
<string>Élément maître</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<item row="0" column="0" colspan="2">
<layout class="QHBoxLayout" name="type_concret_layout">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>Type concret</string>
</property>
</widget>
</item>
<item row="0" column="1">
<item>
<spacer name="type_concret_spacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QComboBox" name="m_master_type_cb"/>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="max_slaves_checkbox">
<property name="text">
@@ -202,19 +232,6 @@
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="Informations">
+205
View File
@@ -267,6 +267,211 @@ QDomElement ElementData::kindInfoToXml(QDomDocument &document)
return returned_elmt;
}
/**
* @brief ElementData::plcMasterDataToXml
* Serialize PLC master data to XML (used by Element::toXml for diagram instances)
*/
QDomElement ElementData::plcMasterDataToXml(QDomDocument &document) const
{
auto xml_plc = document.createElement(QStringLiteral("plcMasterData"));
xml_plc.setAttribute(QStringLiteral("rowHeight"),
QString::number(m_plc_master_data.rowHeight, 'f', 2));
// Save break positions
{
auto xml_breaks = document.createElement(QStringLiteral("breakPositions"));
for (int bp : m_plc_master_data.breakPositions) {
auto xml_bp = document.createElement(QStringLiteral("break"));
xml_bp.appendChild(document.createTextNode(QString::number(bp)));
xml_breaks.appendChild(xml_bp);
}
xml_plc.appendChild(xml_breaks);
}
// Save column widths
auto xml_col_widths = document.createElement(QStringLiteral("columnWidths"));
for (auto it = m_plc_master_data.colWidths.constBegin();
it != m_plc_master_data.colWidths.constEnd(); ++it) {
auto xml_col = document.createElement(QStringLiteral("column"));
xml_col.setAttribute(QStringLiteral("index"), it.key());
xml_col.setAttribute(QStringLiteral("width"), QString::number(it.value(), 'f', 2));
xml_col_widths.appendChild(xml_col);
}
xml_plc.appendChild(xml_col_widths);
// Save column visibility
auto xml_col_vis = document.createElement(QStringLiteral("columnVisibility"));
for (auto it = m_plc_master_data.colVisible.constBegin();
it != m_plc_master_data.colVisible.constEnd(); ++it) {
auto xml_col = document.createElement(QStringLiteral("column"));
xml_col.setAttribute(QStringLiteral("index"), it.key());
xml_col.setAttribute(QStringLiteral("visible"), it.value() ? "true" : "false");
xml_col_vis.appendChild(xml_col);
}
xml_plc.appendChild(xml_col_vis);
// Save fonts
if (!m_plc_master_data.headerFont.family().isEmpty()) {
auto xml_hfont = document.createElement(QStringLiteral("headerFont"));
xml_hfont.setAttribute(QStringLiteral("family"), m_plc_master_data.headerFont.family());
xml_hfont.setAttribute(QStringLiteral("size"), m_plc_master_data.headerFont.pointSize());
xml_hfont.setAttribute(QStringLiteral("bold"), m_plc_master_data.headerFont.bold() ? "true" : "false");
xml_plc.appendChild(xml_hfont);
}
if (!m_plc_master_data.cellFont.family().isEmpty()) {
auto xml_cfont = document.createElement(QStringLiteral("cellFont"));
xml_cfont.setAttribute(QStringLiteral("family"), m_plc_master_data.cellFont.family());
xml_cfont.setAttribute(QStringLiteral("size"), m_plc_master_data.cellFont.pointSize());
xml_cfont.setAttribute(QStringLiteral("bold"), m_plc_master_data.cellFont.bold() ? "true" : "false");
xml_plc.appendChild(xml_cfont);
}
// Save custom column names
if (!m_plc_master_data.columnNames.isEmpty()) {
auto xml_names = document.createElement(QStringLiteral("columnNames"));
for (int i = 0; i < m_plc_master_data.columnNames.size(); ++i) {
auto xml_name = document.createElement(QStringLiteral("column"));
xml_name.setAttribute(QStringLiteral("index"), i);
xml_name.appendChild(document.createTextNode(m_plc_master_data.columnNames.at(i)));
xml_names.appendChild(xml_name);
}
xml_plc.appendChild(xml_names);
}
// Save column order
if (!m_plc_master_data.columnOrder.isEmpty()) {
auto xml_order = document.createElement(QStringLiteral("columnOrder"));
QString order_str;
for (int i = 0; i < m_plc_master_data.columnOrder.size(); ++i) {
if (i > 0) order_str += QStringLiteral(",");
order_str += QString::number(m_plc_master_data.columnOrder.at(i));
}
xml_order.appendChild(document.createTextNode(order_str));
xml_plc.appendChild(xml_order);
}
// Save showHeaders
{
auto xml_sh = document.createElement(QStringLiteral("showHeaders"));
xml_sh.appendChild(document.createTextNode(
m_plc_master_data.showHeaders ? QStringLiteral("1") : QStringLiteral("0")));
xml_plc.appendChild(xml_sh);
}
// Save IO entries
auto xml_ios = document.createElement(QStringLiteral("plcIOs"));
for (const auto &io : m_plc_master_data.ios) {
auto xml_io = document.createElement(QStringLiteral("plcIO"));
xml_io.setAttribute(QStringLiteral("type"), plcIOTypeToString(io.type));
xml_io.setAttribute(QStringLiteral("address"), io.address);
xml_io.setAttribute(QStringLiteral("functionText"), io.functionText);
xml_io.setAttribute(QStringLiteral("comment"), io.comment);
xml_io.setAttribute(QStringLiteral("crossRef"), io.crossRef);
xml_io.setAttribute(QStringLiteral("terminalCount"), io.terminalCount);
for (const auto &t : io.terminals) {
auto xml_term = document.createElement(QStringLiteral("terminal"));
xml_term.appendChild(document.createTextNode(t));
xml_io.appendChild(xml_term);
}
xml_ios.appendChild(xml_io);
}
xml_plc.appendChild(xml_ios);
return xml_plc;
}
/**
* @brief ElementData::plcMasterDataFromXml
* Deserialize PLC master data from XML
*/
void ElementData::plcMasterDataFromXml(const QDomElement &xml_plc)
{
if (xml_plc.isNull())
return;
// Reset PLC data before loading to avoid appending to existing data
m_plc_master_data = PlcMasterData();
m_plc_master_data.rowHeight = xml_plc.attribute(
QStringLiteral("rowHeight"), QStringLiteral("8.0")).toDouble();
// Load break positions
auto xml_breaks = xml_plc.firstChildElement(QStringLiteral("breakPositions"));
for (const auto &xml_bp : QETXML::findInDomElement(xml_breaks, QStringLiteral("break"))) {
m_plc_master_data.breakPositions.append(xml_bp.text().toInt());
}
// Load column widths
auto xml_col_widths = xml_plc.firstChildElement(QStringLiteral("columnWidths"));
for (const auto &xml_col : QETXML::findInDomElement(xml_col_widths, QStringLiteral("column"))) {
int idx = xml_col.attribute(QStringLiteral("index")).toInt();
qreal w = xml_col.attribute(QStringLiteral("width")).toDouble();
m_plc_master_data.colWidths.insert(idx, w);
}
// Load column visibility
auto xml_col_vis = xml_plc.firstChildElement(QStringLiteral("columnVisibility"));
for (const auto &xml_col : QETXML::findInDomElement(xml_col_vis, QStringLiteral("column"))) {
int idx = xml_col.attribute(QStringLiteral("index")).toInt();
bool vis = xml_col.attribute(QStringLiteral("visible")) == QLatin1String("true");
m_plc_master_data.colVisible.insert(idx, vis);
}
// Load fonts
auto xml_hfont = xml_plc.firstChildElement(QStringLiteral("headerFont"));
if (!xml_hfont.isNull()) {
m_plc_master_data.headerFont.setFamily(xml_hfont.attribute(QStringLiteral("family")));
m_plc_master_data.headerFont.setPointSize(xml_hfont.attribute(QStringLiteral("size")).toInt());
m_plc_master_data.headerFont.setBold(xml_hfont.attribute(QStringLiteral("bold")) == QLatin1String("true"));
}
auto xml_cfont = xml_plc.firstChildElement(QStringLiteral("cellFont"));
if (!xml_cfont.isNull()) {
m_plc_master_data.cellFont.setFamily(xml_cfont.attribute(QStringLiteral("family")));
m_plc_master_data.cellFont.setPointSize(xml_cfont.attribute(QStringLiteral("size")).toInt());
m_plc_master_data.cellFont.setBold(xml_cfont.attribute(QStringLiteral("bold")) == QLatin1String("true"));
}
// Load custom column names
auto xml_names = xml_plc.firstChildElement(QStringLiteral("columnNames"));
for (const auto &xml_col : QETXML::findInDomElement(xml_names, QStringLiteral("column"))) {
int idx = xml_col.attribute(QStringLiteral("index")).toInt();
while (m_plc_master_data.columnNames.size() <= idx)
m_plc_master_data.columnNames.append(QString());
m_plc_master_data.columnNames.replace(idx, xml_col.text());
}
// Load column order
auto xml_order = xml_plc.firstChildElement(QStringLiteral("columnOrder"));
if (!xml_order.isNull()) {
QStringList order_str_list = xml_order.text().split(',');
for (const auto &s : order_str_list) {
m_plc_master_data.columnOrder.append(s.trimmed().toInt());
}
}
// Load showHeaders
auto xml_sh = xml_plc.firstChildElement(QStringLiteral("showHeaders"));
if (!xml_sh.isNull()) {
m_plc_master_data.showHeaders = xml_sh.text() == QLatin1String("1");
}
// Load IO entries
auto xml_ios = xml_plc.firstChildElement(QStringLiteral("plcIOs"));
for (const auto &xml_io : QETXML::findInDomElement(xml_ios, QStringLiteral("plcIO"))) {
PlcIO io;
io.type = plcIOTypeFromString(xml_io.attribute(QStringLiteral("type")));
io.address = xml_io.attribute(QStringLiteral("address"));
io.functionText = xml_io.attribute(QStringLiteral("functionText"));
io.comment = xml_io.attribute(QStringLiteral("comment"));
io.crossRef = xml_io.attribute(QStringLiteral("crossRef"));
io.terminalCount = xml_io.attribute(QStringLiteral("terminalCount")).toInt();
for (const auto &xml_term : QETXML::findInDomElement(xml_io, QStringLiteral("terminal"))) {
io.terminals.append(xml_term.text());
}
m_plc_master_data.ios.append(io);
}
}
/**
* @brief ElementData::setTerminalType
* Override the terminal type by \p t_type
+7
View File
@@ -130,6 +130,11 @@ class ElementData : public PropertiesInterface
QList<int> columnOrder; ///< Column display order (logical indices)
bool showHeaders = true; ///< Show column headers on sheet
PlcMasterData() {
headerFont.setFamily(QString());
cellFont.setFamily(QString());
}
bool operator==(const PlcMasterData &other) const {
return ios == other.ios
&& breakPositions == other.breakPositions
@@ -201,6 +206,8 @@ class ElementData : public PropertiesInterface
QDomElement toXml(QDomDocument &xml_element) const override;
bool fromXml(const QDomElement &xml_element) override;
QDomElement kindInfoToXml(QDomDocument &document);
QDomElement plcMasterDataToXml(QDomDocument &document) const;
void plcMasterDataFromXml(const QDomElement &xml_plc);
void setTerminalType(ElementData::TerminalType t_type);
ElementData::TerminalType terminalType() const;
+21 -2
View File
@@ -16,6 +16,7 @@
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
*/
#include "element.h"
#include "../qetapp.h"
#include "../qetproject.h"
#include "../PropertiesEditor/propertieseditordialog.h"
#include "../autoNum/assignvariables.h"
@@ -860,6 +861,15 @@ bool Element::fromXml(QDomElement &e,
}
}
//Load PLC master data override from diagram XML
if (m_data.m_type == ElementData::Master &&
m_data.m_master_type == ElementData::PLC)
{
auto xml_plc = e.firstChildElement(QStringLiteral("plcMasterData"));
if (!xml_plc.isNull())
m_data.plcMasterDataFromXml(xml_plc);
}
//We must block the update of the alignment when loading the information
//otherwise the pos of the text will not be the same as it was at save time.
for(DynamicElementTextItem *deti : m_dynamic_text_list)
@@ -993,6 +1003,15 @@ QDomElement Element::toXml(
element.appendChild(properties);
}
//Save PLC master data override for elements on diagram
if (m_data.m_type == ElementData::Master &&
m_data.m_master_type == ElementData::PLC)
{
auto xml_plc = m_data.plcMasterDataToXml(document);
if (!xml_plc.isNull())
element.appendChild(xml_plc);
}
//Dynamic texts
QDomElement dyn_text = document.createElement(QStringLiteral("dynamic_texts"));
for (DynamicElementTextItem *deti : m_dynamic_text_list)
@@ -1876,12 +1895,12 @@ void Element::drawPlcTable(QPainter *painter)
// Fonts
QFont header_font = plc_data.headerFont;
if (header_font.family().isEmpty()) {
header_font = painter->font();
header_font = QETApp::diagramTextsFont();
header_font.setBold(true);
}
QFont cell_font = plc_data.cellFont;
if (cell_font.family().isEmpty()) {
cell_font = painter->font();
cell_font = QETApp::diagramTextsFont();
}
for (const QPointF &pos : positions) {
+1 -1
View File
@@ -535,7 +535,7 @@ void MasterPropertiesWidget::updateUi()
tr("Commentaire"), tr("Réf. croisée")
});
m_plc_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
m_plc_table->setSelectionBehavior(QAbstractItemView::SelectRows);
m_plc_table->setSelectionBehavior(QAbstractItemView::SelectItems);
m_plc_table->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_plc_table->setMinimumHeight(200);