From 4ca0bbf6822a7dd8b5399b8edac3af1f571bbc58 Mon Sep 17 00:00:00 2001 From: joshua Date: Thu, 7 Nov 2024 18:48:53 +0100 Subject: [PATCH 01/15] Minor Add more help line for the preview of terminal strip configurator --- .../GraphicsItem/terminalstripdrawer.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp index fcb2e78a4..57db4b70f 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp @@ -64,6 +64,8 @@ void TerminalStripDrawer::paint(QPainter *painter) painter->save(); painter->setPen(Qt::blue); painter->drawRect(boundingRect()); + painter->drawLine(QPointF{boundingRect().left(), boundingRect().center().y()}, + QPointF{boundingRect().right(), boundingRect().center().y()}); painter->restore(); } @@ -145,6 +147,15 @@ void TerminalStripDrawer::paint(QPainter *painter) painter->restore(); } + if(m_preview_draw) + { + painter->save(); + painter->setPen(Qt::yellow); + painter->drawLine(QPoint{terminal_rect.x(), terminal_rect.y() + terminal_rect.height()/2}, + QPoint{terminal_rect.width(), terminal_rect.y() + terminal_rect.height()/2}); + painter->restore(); + } + //Draw text painter->save(); if (terminals_text_orientation[index_] == Qt::Horizontal) From ae5e1888660f42a9a3e5f5141b3f8cdf3068db06 Mon Sep 17 00:00:00 2001 From: joshua Date: Wed, 12 Mar 2025 19:14:45 +0100 Subject: [PATCH 02/15] Add converter for dpi to pixel font size Add a little function used to convert if needed the size of a font set in dpi to pixel. Because the conversion from pdi to pixel can't be exactly identical, the text size in the diagram can be a little different, in the other side the switch between screens with different dpi is no more a problem. --- sources/utils/qetutils.cpp | 18 ++++++++++++++++++ sources/utils/qetutils.h | 1 + 2 files changed, 19 insertions(+) diff --git a/sources/utils/qetutils.cpp b/sources/utils/qetutils.cpp index 6d8ce1d68..5fbe9a730 100644 --- a/sources/utils/qetutils.cpp +++ b/sources/utils/qetutils.cpp @@ -132,3 +132,21 @@ bool QETUtils::sortBeginIntString(const QString &str_a, const QString &str_b) return str_a -1) { + return; + } + + auto px = font.pointSizeF()/72 * QFontMetrics{font}.fontDpi(); + font.setPixelSize(qRound(px)); +} diff --git a/sources/utils/qetutils.h b/sources/utils/qetutils.h index 61864c56f..60cbe0f45 100644 --- a/sources/utils/qetutils.h +++ b/sources/utils/qetutils.h @@ -31,6 +31,7 @@ namespace QETUtils QString marginsToString(const QMargins &margins); QMargins marginsFromString(const QString &string); qreal graphicsHandlerSize(QGraphicsItem *item); + void pixelSizedFont (QFont &font); bool sortBeginIntString(const QString &str_a, const QString &str_b); From 7747223dfae7c54c956bacdd0fa4337101925fb8 Mon Sep 17 00:00:00 2001 From: joshua Date: Wed, 12 Mar 2025 19:22:30 +0100 Subject: [PATCH 03/15] Terminal strip item font is editable The font used in the terminal strip item can be edited trough the terminal strip layout editor widget --- .../properties/terminalstriplayoutpattern.cpp | 11 + .../properties/terminalstriplayoutpattern.h | 8 +- .../GraphicsItem/terminalstripdrawer.cpp | 2 + .../ui/terminalstriplayouteditor.cpp | 14 +- .../ui/terminalstriplayouteditor.h | 1 - .../ui/terminalstriplayouteditor.ui | 541 ++++++++++-------- 6 files changed, 345 insertions(+), 232 deletions(-) diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp index f0b8801c9..19f0bfc4c 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp @@ -16,10 +16,12 @@ along with QElectroTech. If not, see . */ #include "terminalstriplayoutpattern.h" +#include "../../../utils/qetutils.h" #include TerminalStripLayoutPattern::TerminalStripLayoutPattern() { + m_font.setPixelSize(15); updateHeaderTextOption(); updateTerminalsTextOption(); } @@ -39,6 +41,15 @@ QTextOption TerminalStripLayoutPattern::headerTextOption() const { return m_header_text_option; } +QFont TerminalStripLayoutPattern::font() const { + return m_font; +} + +void TerminalStripLayoutPattern::setFont(const QFont &font) { + m_font = font; + QETUtils::pixelSizedFont(m_font); +} + void TerminalStripLayoutPattern::setTerminalsTextAlignment(const QVector &alignment) { m_terminals_text_alignment = alignment; diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h index ac8aac7e1..96ebaeb14 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h @@ -18,6 +18,7 @@ #ifndef TERMINALSTRIPLAYOUTPATTERN_H #define TERMINALSTRIPLAYOUTPATTERN_H +#include #include #include #include @@ -52,6 +53,10 @@ class TerminalStripLayoutPattern //Spacer between the header and the terminals QRect m_spacer_rect{0, 50, 10, 90}; + //Font + QFont font() const; + void setFont (const QFont &font); + //Terminals QVector m_terminal_rect { @@ -90,7 +95,8 @@ class TerminalStripLayoutPattern void updateHeaderTextOption(); void updateTerminalsTextOption(); - private: + private: + QFont m_font; Qt::Alignment m_header_text_alignment{Qt::AlignCenter}; QTextOption m_header_text_option; diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp index 57db4b70f..b0f16493f 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp @@ -56,6 +56,8 @@ void TerminalStripDrawer::paint(QPainter *painter) auto brush_ = painter->brush(); brush_.setColor(Qt::white); + painter->setFont(m_pattern->font()); + painter->setPen(pen_); painter->setBrush(brush_); diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp b/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp index 11e0b239f..630d672fc 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp @@ -15,9 +15,12 @@ You should have received a copy of the GNU General Public License along with QElectroTech. If not, see . */ +#include + #include "terminalstriplayouteditor.h" #include "ui_terminalstriplayouteditor.h" #include "../GraphicsItem/properties/terminalstriplayoutpattern.h" +#include "../../utils/qetutils.h" TerminalStripLayoutEditor::TerminalStripLayoutEditor(QSharedPointer layout, QWidget *parent) : @@ -54,8 +57,6 @@ void TerminalStripLayoutEditor::valueEdited() return; } - //auto *data_ = m_layout.data(); - m_layout.data()->m_header_rect.setRect(0, ui->m_y_header_sb->value(), ui->m_width_header_sb->value(), @@ -91,6 +92,10 @@ void TerminalStripLayoutEditor::valueEdited() m_layout.data()->m_bridge_point_y_offset[2] = ui->m_bridge_point_2_sb->value(); m_layout.data()->m_bridge_point_y_offset[3] = ui->m_bridge_point_3_sb->value(); + auto font_ = ui->m_font_cb->currentFont(); + font_.setPixelSize(ui->m_font_size_sb->value()); + m_layout->setFont(font_); + m_layout.data()->m_header_text_orientation = ui->m_header_text_orientation_cb->currentIndex() == 0 ? Qt::Horizontal : Qt::Vertical; @@ -180,6 +185,10 @@ void TerminalStripLayoutEditor::updateUi() ui->m_bridge_point_2_sb->setValue(bridge_point[2]); ui->m_bridge_point_3_sb->setValue(bridge_point[3]); + const auto font = m_layout->font(); + ui->m_font_size_sb->setValue(font.pixelSize()); + ui->m_font_cb->setCurrentFont(font); + if (data->m_header_text_orientation == Qt::Horizontal) { ui->m_header_text_orientation_cb->setCurrentIndex(0); } else { @@ -225,4 +234,3 @@ void TerminalStripLayoutEditor::on_m_display_preview_help_clicked(bool checked) m_preview_strip_item.m_drawer.setPreviewDraw(checked); m_preview_strip_item.update(); } - diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.h b/sources/TerminalStrip/ui/terminalstriplayouteditor.h index d4daea579..ec048ca23 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.h +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.h @@ -76,7 +76,6 @@ class TerminalStripLayoutEditor : public QWidget private slots: void valueEdited(); - void on_m_display_preview_help_clicked(bool checked); private: diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.ui b/sources/TerminalStrip/ui/terminalstriplayouteditor.ui index eca92386e..1d5b73ba6 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.ui +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.ui @@ -6,8 +6,8 @@ 0 0 - 767 - 544 + 892 + 555 @@ -15,57 +15,26 @@ - QLayout::SetMaximumSize + QLayout::SizeConstraint::SetMaximumSize - - - - Borne niveau 0 : + + + + 1000 - - - - En tête : + + + + 1000 - Qt::Horizontal - - - - - - - - - - Point de pont - - - - - - - 1000 - - - - - - - Qt::Horizontal - - - - - - - 1000 + Qt::Orientation::Horizontal @@ -76,15 +45,43 @@ - - - - Afficher l'aide + + + + 1000 - - + + + + 1000 + + + + + + + Borne niveau 0 : + + + + + + + 1000 + + + + + + + 1000 + + + + + 1000 @@ -97,22 +94,39 @@ - - + + + + + 1000 - - + + - Largeur + Borne niveau 3 : - - + + + + Borne niveau 2 : + + + + + + + 1000 + + + + + 1000 @@ -125,17 +139,45 @@ - - + + - Hauteur + Afficher l'aide - - + + - Prévisualisation : + Largeur + + + + + + + 1000 + + + + + + + Espace : + + + + + + + Qt::Orientation::Horizontal + + + + + + + 1000 @@ -146,35 +188,14 @@ - - - - 1000 + + + + Borne niveau 1 : - - - - 1000 - - - - - - - 1000 - - - - - - - 1000 - - - - + @@ -189,26 +210,56 @@ 0 - - + + - Gauche + Horizontal - Centre - - - - - Droite + Vertical - + + + + Orientation du texte d'en tête : + + + + + + + + Horizontal + + + + + Vertical + + + + + + + + Alignement du texte d'en tête : + + + + + + + Orientation du texte de borne : + + + + @@ -227,65 +278,111 @@ - - - - Alignement du texte d'en tête : - + + + + + Gauche + + + + + Centre + + + + + Droite + + - + Alignement du texte de borne : - - - - - Horizontal + + + + + 0 - - - - Vertical + + 0 - - - - - - - - Horizontal + + 0 - - - - Vertical + + 0 - - - - - - - Orientation du texte de borne : - - - - - - - Orientation du texte d'en tête : - + + + + Police : + + + + + + + + + + Taille : + + + + + + + 1 + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + + 1000 + + + + + + + 1000 + + + + + + + En tête : + + + @@ -293,34 +390,6 @@ - - - - Borne niveau 2 : - - - - - - - 1000 - - - - - - - Espace : - - - - - - - 1000 - - - @@ -328,66 +397,52 @@ - - - - 1000 - - - - - - - 1000 - - - - - - - 1000 - - - - - - - 1000 - - - - - - - 1000 - - - - - - - Borne niveau 3 : - - - - - - - 1000 - - - - - - - Borne niveau 1 : - - - - - + + - Qt::Horizontal + Qt::Orientation::Horizontal + + + + + + + 1000 + + + + + + + 1000 + + + + + + + Hauteur + + + + + + + Point de pont + + + + + + + 1000 + + + + + + + Prévisualisation : @@ -811,6 +866,38 @@ + + m_font_cb + currentFontChanged(QFont) + TerminalStripLayoutEditor + valueEdited() + + + 245 + 276 + + + 445 + 277 + + + + + m_font_size_sb + valueChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 507 + 277 + + + 445 + 277 + + + valueEdited() From 2d89d70682cb82b99513579f4663700d560d32d5 Mon Sep 17 00:00:00 2001 From: joshua Date: Wed, 12 Mar 2025 21:10:16 +0100 Subject: [PATCH 04/15] Add possibility to adjust terminal text position The bounding rectangle used to define the position of the terminal text can be edited. The y position and height can now be edited. The width is not editable because is always the width of the rectangle of the of the terminal. --- .../properties/terminalstriplayoutpattern.h | 11 +- .../GraphicsItem/terminalstripdrawer.cpp | 15 +- .../ui/terminalstriplayouteditor.cpp | 7 +- .../ui/terminalstriplayouteditor.ui | 164 ++++++++++++------ 4 files changed, 128 insertions(+), 69 deletions(-) diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h index 96ebaeb14..bba900d09 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h @@ -68,15 +68,10 @@ class TerminalStripLayoutPattern void setTerminalsTextAlignment(const QVector &alignment); QVector terminalsTextAlignment() const; - QVector terminalsTextOption() const; + QVector terminalsTextOption() const; + int m_terminals_text_height{50}; + int m_terminals_text_y{35}; - QVector m_terminals_text_rect - { - QRect{0,35,20,50}, - QRect{0,35,20,50}, - QRect{0,35,20,50}, - QRect{0,35,20,50} - }; QVector m_terminals_text_orientation { Qt::Vertical, diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp index b0f16493f..522073437 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp @@ -105,9 +105,10 @@ void TerminalStripDrawer::paint(QPainter *painter) //Draw terminals - const auto terminals_text_rect{m_pattern->m_terminals_text_rect}; const auto terminals_text_orientation{m_pattern->m_terminals_text_orientation}; const auto terminals_text_option{m_pattern->terminalsTextOption()}; + const auto terminals_text_height{m_pattern->m_terminals_text_height}; + const auto terminals_text_y{m_pattern->m_terminals_text_y}; QRect terminal_rect; QHash> bridges_anchor_points; @@ -160,16 +161,12 @@ void TerminalStripDrawer::paint(QPainter *painter) //Draw text painter->save(); - if (terminals_text_orientation[index_] == Qt::Horizontal) + text_rect.setRect(0, terminals_text_y, terminal_rect.width(), terminals_text_height); + if (terminals_text_orientation[index_] == Qt::Vertical) { - text_rect = terminals_text_rect[index_]; - } - else - { - const auto rect_{terminals_text_rect[index_]}; - painter->translate(rect_.bottomLeft()); + painter->translate(text_rect.bottomLeft()); painter->rotate(270); - text_rect.setRect(0, 0, rect_.height(), terminal_rect.width()); + text_rect.setRect(0, 0, text_rect.height(), text_rect.width()); } const auto shared_real_terminal{real_terminal_vector[i]}; diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp b/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp index 630d672fc..c630ed500 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp @@ -20,7 +20,6 @@ #include "terminalstriplayouteditor.h" #include "ui_terminalstriplayouteditor.h" #include "../GraphicsItem/properties/terminalstriplayoutpattern.h" -#include "../../utils/qetutils.h" TerminalStripLayoutEditor::TerminalStripLayoutEditor(QSharedPointer layout, QWidget *parent) : @@ -137,6 +136,9 @@ void TerminalStripLayoutEditor::valueEdited() break; } + m_layout.data()->m_terminals_text_y = ui->m_terminal_text_y_sb->value(); + m_layout.data()->m_terminals_text_height = ui->m_terminal_text_height_sb->value(); + updateUi(); m_preview_strip_item.update(); } @@ -219,6 +221,9 @@ void TerminalStripLayoutEditor::updateUi() ui->m_terminal_text_alignment_cb->setCurrentIndex(2); } + ui->m_terminal_text_y_sb->setValue(data->m_terminals_text_y); + ui->m_terminal_text_height_sb->setValue(data->m_terminals_text_height); + m_ui_updating = false; updatePreview(); } diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.ui b/sources/TerminalStrip/ui/terminalstriplayouteditor.ui index 1d5b73ba6..f8f74789a 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.ui +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.ui @@ -6,8 +6,8 @@ 0 0 - 892 - 555 + 683 + 589 @@ -144,6 +144,9 @@ Afficher l'aide + + false + @@ -210,7 +213,14 @@ 0 - + + + + Longueur maximal du texte de borne + + + + @@ -224,42 +234,7 @@ - - - - Orientation du texte d'en tête : - - - - - - - - Horizontal - - - - - Vertical - - - - - - - - Alignement du texte d'en tête : - - - - - - - Orientation du texte de borne : - - - - + @@ -278,29 +253,38 @@ - - + + - Gauche + Horizontal - Centre - - - - - Droite + Vertical - - + + - Alignement du texte de borne : + Orientation du texte d'en tête : + + + + + + + Alignement du texte d'en tête : + + + + + + + Origine vertical du texte de borne : @@ -359,6 +343,52 @@ + + + + + Gauche + + + + + Centre + + + + + Droite + + + + + + + + 30 + + + 1000 + + + + + + + Orientation du texte de borne : + + + + + + + + + + Alignement du texte de borne : + + + @@ -898,6 +928,38 @@ + + m_terminal_text_y_sb + valueChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 207 + 383 + + + 445 + 277 + + + + + m_terminal_text_height_sb + valueChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 430 + 383 + + + 445 + 277 + + + valueEdited() From 2c1b840f9c54eadf2cdb3f478e31c8cfe5bd998f Mon Sep 17 00:00:00 2001 From: joshua Date: Wed, 12 Mar 2025 21:48:18 +0100 Subject: [PATCH 05/15] Use same properties for every terminal level Initially it was planned to have separate text configuration for every terminal level. It's not useful, use same properties for every level is sufficient and visually more consistent. By consequent every QVector related to these properties was replaced by a single value. --- .../properties/terminalstriplayoutpattern.cpp | 20 +++--------- .../properties/terminalstriplayoutpattern.h | 32 ++++--------------- .../GraphicsItem/terminalstripdrawer.cpp | 4 +-- .../ui/terminalstriplayouteditor.cpp | 28 +++++----------- 4 files changed, 22 insertions(+), 62 deletions(-) diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp index 19f0bfc4c..b6fba13e8 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp @@ -50,18 +50,18 @@ void TerminalStripLayoutPattern::setFont(const QFont &font) { QETUtils::pixelSizedFont(m_font); } -void TerminalStripLayoutPattern::setTerminalsTextAlignment(const QVector &alignment) +void TerminalStripLayoutPattern::setTerminalsTextAlignment(const Qt::Alignment &alignment) { m_terminals_text_alignment = alignment; updateTerminalsTextOption(); } -QVector TerminalStripLayoutPattern::terminalsTextAlignment() const +Qt::Alignment TerminalStripLayoutPattern::terminalsTextAlignment() const { return m_terminals_text_alignment; } -QVector TerminalStripLayoutPattern::terminalsTextOption() const +QTextOption TerminalStripLayoutPattern::terminalsTextOption() const { return m_terminals_text_option; } @@ -74,16 +74,6 @@ void TerminalStripLayoutPattern::updateHeaderTextOption() void TerminalStripLayoutPattern::updateTerminalsTextOption() { - if (m_terminals_text_option.size() == - m_terminals_text_alignment.size()) - { - for (auto i = 0 ; i &alignment); - QVector terminalsTextAlignment() const; - QVector terminalsTextOption() const; + //Terminal text + void setTerminalsTextAlignment(const Qt::Alignment &alignment); + Qt::Alignment terminalsTextAlignment() const; + QTextOption terminalsTextOption() const; int m_terminals_text_height{50}; int m_terminals_text_y{35}; - - QVector m_terminals_text_orientation - { - Qt::Vertical, - Qt::Vertical, - Qt::Vertical, - Qt::Vertical - }; + Qt::Orientation m_terminals_text_orientation {Qt::Vertical}; int m_bridge_point_d{5}; QVector m_bridge_point_y_offset{50,70,90,110}; @@ -95,20 +89,8 @@ class TerminalStripLayoutPattern Qt::Alignment m_header_text_alignment{Qt::AlignCenter}; QTextOption m_header_text_option; - QVector m_terminals_text_alignment - { - Qt::AlignRight | Qt::AlignVCenter, - Qt::AlignRight | Qt::AlignVCenter, - Qt::AlignRight | Qt::AlignVCenter, - Qt::AlignRight | Qt::AlignVCenter - }; - QVector m_terminals_text_option - { - QTextOption(), - QTextOption(), - QTextOption(), - QTextOption() - }; + Qt::Alignment m_terminals_text_alignment {Qt::AlignRight | Qt::AlignVCenter}; + QTextOption m_terminals_text_option{QTextOption()}; }; #endif // TERMINALSTRIPLAYOUTPATTERN_H diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp index 522073437..256665305 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp @@ -162,7 +162,7 @@ void TerminalStripDrawer::paint(QPainter *painter) //Draw text painter->save(); text_rect.setRect(0, terminals_text_y, terminal_rect.width(), terminals_text_height); - if (terminals_text_orientation[index_] == Qt::Vertical) + if (terminals_text_orientation == Qt::Vertical) { painter->translate(text_rect.bottomLeft()); painter->rotate(270); @@ -172,7 +172,7 @@ void TerminalStripDrawer::paint(QPainter *painter) const auto shared_real_terminal{real_terminal_vector[i]}; painter->drawText(text_rect, shared_real_terminal ? shared_real_terminal->label() : QLatin1String(), - terminals_text_option[index_]); + terminals_text_option); if (m_preview_draw) { diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp b/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp index c630ed500..b54164f94 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp @@ -108,31 +108,19 @@ void TerminalStripLayoutEditor::valueEdited() m_layout.data()->setHeaderTextAlignment(Qt::AlignRight | Qt::AlignVCenter); break; } - m_layout.data()->m_terminals_text_orientation[0] = ui->m_terminal_text_orientation_cb->currentIndex() == 0 ? - Qt::Horizontal : - Qt::Vertical; + m_layout.data()->m_terminals_text_orientation = ui->m_terminal_text_orientation_cb->currentIndex() == 0 ? + Qt::Horizontal : + Qt::Vertical; switch (ui->m_terminal_text_alignment_cb->currentIndex()) { case 0: - m_layout.data()->setTerminalsTextAlignment( - QVector { Qt::AlignLeft | Qt::AlignVCenter, - Qt::AlignLeft | Qt::AlignVCenter, - Qt::AlignLeft | Qt::AlignVCenter, - Qt::AlignLeft | Qt::AlignVCenter }); + m_layout.data()->setTerminalsTextAlignment(Qt::Alignment {Qt::AlignLeft | Qt::AlignVCenter}); break; case 1: - m_layout.data()->setTerminalsTextAlignment( - QVector { Qt::AlignHCenter | Qt::AlignVCenter, - Qt::AlignHCenter | Qt::AlignVCenter, - Qt::AlignHCenter | Qt::AlignVCenter, - Qt::AlignHCenter | Qt::AlignVCenter }); + m_layout.data()->setTerminalsTextAlignment(Qt::Alignment { Qt::AlignHCenter | Qt::AlignVCenter}); break; default: - m_layout.data()->setTerminalsTextAlignment( - QVector { Qt::AlignRight | Qt::AlignVCenter, - Qt::AlignRight | Qt::AlignVCenter, - Qt::AlignRight | Qt::AlignVCenter, - Qt::AlignRight | Qt::AlignVCenter }); + m_layout.data()->setTerminalsTextAlignment(Qt::Alignment { Qt::AlignRight | Qt::AlignVCenter}); break; } @@ -197,7 +185,7 @@ void TerminalStripLayoutEditor::updateUi() ui->m_header_text_orientation_cb->setCurrentIndex(1); } - if (data->m_terminals_text_orientation[0] == Qt::Horizontal) { + if (data->m_terminals_text_orientation == Qt::Horizontal) { ui->m_terminal_text_orientation_cb->setCurrentIndex(0); } else { ui->m_terminal_text_orientation_cb->setCurrentIndex(1); @@ -212,7 +200,7 @@ void TerminalStripLayoutEditor::updateUi() ui->m_header_text_alignment_cb->setCurrentIndex(2); } - const auto terminal_alignment = data->terminalsTextAlignment().at(0); + const auto terminal_alignment = data->terminalsTextAlignment(); if (terminal_alignment &Qt::AlignLeft) { ui->m_terminal_text_alignment_cb->setCurrentIndex(0); } else if (terminal_alignment &Qt::AlignHCenter) { From 95e401a2661da14581f76027a2cf78d7f2096c52 Mon Sep 17 00:00:00 2001 From: joshua Date: Thu, 5 Jun 2025 23:04:56 +0200 Subject: [PATCH 06/15] Class TerminalStripLayoutPattern can be save/load from xml Add a new class TerminalStripLayoutPatternXml used to save / load a TerminalStripLayoutPattern class into a xml. Also create the namespace QETSVG used to read/write some svg element / attribute to xml. This class is used by the class TerminalStripLayoutPatternXml. --- qelectrotech.pro | 6 +- .../properties/terminalstriplayoutpattern.cpp | 14 ++ sources/qetxml.cpp | 89 ++++++++ sources/qetxml.h | 6 + sources/svg/qetsvg.cpp | 151 ++++++++++++++ sources/svg/qetsvg.h | 51 +++++ sources/xml/terminalstriplayoutpatternxml.cpp | 191 ++++++++++++++++++ sources/xml/terminalstriplayoutpatternxml.h | 41 ++++ 8 files changed, 547 insertions(+), 2 deletions(-) create mode 100644 sources/svg/qetsvg.cpp create mode 100644 sources/svg/qetsvg.h create mode 100644 sources/xml/terminalstriplayoutpatternxml.cpp create mode 100644 sources/xml/terminalstriplayoutpatternxml.h diff --git a/qelectrotech.pro b/qelectrotech.pro index 5729674e9..badb86bdb 100644 --- a/qelectrotech.pro +++ b/qelectrotech.pro @@ -166,7 +166,8 @@ HEADERS += $$files(sources/*.h) \ $$files(sources/TerminalStrip/GraphicsItem/*.h) \ $$files(sources/TerminalStrip/GraphicsItem/properties/*.h) \ $$files(sources/xml/*.h) \ - $$files(sources/dxf/*.h) + $$files(sources/dxf/*.h) \ + $$files(sources/svg/*.h) SOURCES += $$files(sources/*.cpp) \ $$files(sources/editor/*.cpp) \ @@ -208,7 +209,8 @@ SOURCES += $$files(sources/*.cpp) \ $$files(sources/TerminalStrip/GraphicsItem/*.cpp) \ $$files(sources/TerminalStrip/GraphicsItem/properties/*.cpp) \ $$files(sources/xml/*.cpp) \ - $$files(sources/dxf/*.cpp) + $$files(sources/dxf/*.cpp) \ + $$files(sources/svg/*.cpp) # Needed for use promote QTreeWidget in terminalstripeditor.ui INCLUDEPATH += sources/TerminalStrip/ui diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp index b6fba13e8..84baeb591 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp @@ -26,8 +26,15 @@ TerminalStripLayoutPattern::TerminalStripLayoutPattern() updateTerminalsTextOption(); } +/** + * @brief TerminalStripLayoutPattern::setHeaderTextAlignment + * Set text alignment to @param alignment. If alignment have no + * flag this function do nothing + * @param alignment + */ void TerminalStripLayoutPattern::setHeaderTextAlignment(const Qt::Alignment &alignment) { + if (!alignment) return; m_header_text_alignment = alignment; updateHeaderTextOption(); } @@ -50,8 +57,15 @@ void TerminalStripLayoutPattern::setFont(const QFont &font) { QETUtils::pixelSizedFont(m_font); } +/** + * @brief TerminalStripLayoutPattern::setTerminalsTextAlignment + * Set text alignment to @param alignment. If alignment have no + * flag this function do nothing + * @param alignment + */ void TerminalStripLayoutPattern::setTerminalsTextAlignment(const Qt::Alignment &alignment) { + if (!alignment) return; m_terminals_text_alignment = alignment; updateTerminalsTextOption(); } diff --git a/sources/qetxml.cpp b/sources/qetxml.cpp index b22a5581c..dc35ce30a 100644 --- a/sources/qetxml.cpp +++ b/sources/qetxml.cpp @@ -953,4 +953,93 @@ bool qGraphicsItemPosFromXml(QGraphicsItem *item, const QDomElement &xml_elmt) return false; } +/** + * @brief orientationToAttribute + * Write the Qt::orientation has an attribute of @param element. + * Attribute name is 'orientation' value is 'horizontal' or 'vertical' + * @param orientation + * @param element + */ +void orientationToAttribute(const Qt::Orientation &orientation, QDomElement &element) +{ + element.setAttribute(QStringLiteral("orientation"), + orientation == Qt::Horizontal ? QStringLiteral("Horizontal") : + QStringLiteral("Vertical")); +} + +/** + * @brief orientationFromAttribute + * @param element + * @param def_value + * @return the Qt::Orientation read in @param element. If an error occur + * the returned orientation is @param def_value. + */ +Qt::Orientation orientationFromAttribute(const QDomElement &element, Qt::Orientation def_value) +{ + if (element.hasAttribute(QStringLiteral("orientation"))) { + const auto str {element.attribute(QStringLiteral("orientation"))}; + if (str == QLatin1String("Horizontal")) + return Qt::Horizontal; + else if (str == QLatin1String("Vertical")) + return Qt::Vertical; + } + //Error occur during reading, we return the default value + return def_value; +} + +void alignmentToAttribute(const Qt::Alignment &alignment, QDomElement &element) +{ + QStringList al; + if (alignment &Qt::AlignLeft) + al.append(QStringLiteral("Left")); + if (alignment &Qt::AlignRight) + al.append(QStringLiteral("Right")); + if (alignment &Qt::AlignHCenter) + al.append(QStringLiteral("HCenter")); + if (alignment &Qt::AlignJustify) + al.append(QStringLiteral("Justify")); + if (alignment &Qt::AlignTop) + al.append(QStringLiteral("Top")); + if (alignment &Qt::AlignBottom) + al.append(QStringLiteral("Bottom")); + if (alignment &Qt::AlignBottom) + al.append(QStringLiteral("VCenter")); + if (alignment &Qt::AlignBaseline) + al.append(QStringLiteral("Baseline")); + + element.setAttribute(QStringLiteral("alignment"),al.join(QStringLiteral(" "))); +} + +/** + * @brief alignmentFromAttribute + * @param element + * @return The alignment read in @param element. If an error + * occured the return Qt::alignment contain no set flag. + */ +Qt::Alignment alignmentFromAttribute(const QDomElement &element) +{ + Qt::Alignment al; + if (element.hasAttribute(QStringLiteral("alignment"))) { + const auto alignment {element.attribute(QStringLiteral("alignment"))}; + if(alignment.contains(QStringLiteral("Left"))) + al = al | Qt::AlignLeft; + if(alignment.contains(QStringLiteral("Right"))) + al = al | Qt::AlignRight; + if(alignment.contains(QStringLiteral("HCenter"))) + al = al | Qt::AlignHCenter; + if(alignment.contains(QStringLiteral("Justify"))) + al = al | Qt::AlignJustify; + if(alignment.contains(QStringLiteral("Top"))) + al = al | Qt::AlignTop; + if(alignment.contains(QStringLiteral("Bottom"))) + al = al | Qt::AlignBottom; + if(alignment.contains(QStringLiteral("VCenter"))) + al = al | Qt::AlignVCenter; + if(alignment.contains(QStringLiteral("Baseline"))) + al = al | Qt::AlignBaseline; + } + + return al; +} + } diff --git a/sources/qetxml.h b/sources/qetxml.h index 9d57d2240..c5670d857 100644 --- a/sources/qetxml.h +++ b/sources/qetxml.h @@ -94,6 +94,12 @@ namespace QETXML QDomElement qGraphicsItemPosToXml(QGraphicsItem *item, QDomDocument &document); bool qGraphicsItemPosFromXml(QGraphicsItem *item, const QDomElement &xml_elmt); + void orientationToAttribute(const Qt::Orientation &orientation, QDomElement &element); + Qt::Orientation orientationFromAttribute(const QDomElement &element, Qt::Orientation def_value = Qt::Vertical); + + void alignmentToAttribute(const Qt::Alignment &alignment, QDomElement &element); + Qt::Alignment alignmentFromAttribute (const QDomElement &element); + QString boolToString(bool value); bool boolFromString(const QString &value, bool default_value = true, diff --git a/sources/svg/qetsvg.cpp b/sources/svg/qetsvg.cpp new file mode 100644 index 000000000..ba5ac7d99 --- /dev/null +++ b/sources/svg/qetsvg.cpp @@ -0,0 +1,151 @@ +/* + Copyright 2006-2025 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ + +#include "qetsvg.h" + +#include +#include +#include <../qet.h> + +/** + * @brief QETSVG::rectToElmt + * Write a QRect as a svg rect element. + * @param rect + * @param parent_document + * @return + */ +QDomElement QETSVG::rectToElmt(const QRect &rect, QDomDocument &parent_document) +{ + auto dom_element = parent_document.createElement(QStringLiteral("rect")); + if (!rect.isNull()) { + dom_element.setAttribute(QStringLiteral("x"), rect.x()); + yToAttribute(rect.y(), dom_element); + dom_element.setAttribute(QStringLiteral("width"), rect.width()); + heightToAttribute(rect.height(), dom_element); + } + return dom_element; +} + +/** + * @brief QETSVG::rectFromElmt + * @param xml_element : xml_element of an svg rect. + * The tag name must be 'rect' if not, the returned QRect is null. + * @return a svg rect to QRect + */ +QRect QETSVG::rectFromElmt(const QDomElement &xml_element) +{ + QRect rect; + if (xml_element.tagName() == QLatin1String("rect")) { + rect.setRect(xml_element.attribute(QStringLiteral("x"), QStringLiteral("0")).toInt(), + static_cast (yFromAttribute(xml_element, 0)), + xml_element.attribute(QStringLiteral("width"), QStringLiteral("10")).toInt(), + static_cast (heightFromAttribute(xml_element, 10))); + } + return rect; +} + +/** + * @brief QETSVG::yToAttribute + * @param y + * @param xml_element + */ +void QETSVG::yToAttribute(const qreal &y, QDomElement &xml_element) { + xml_element.setAttribute(QStringLiteral("y"), QString::number(y)); +} + +/** + * @brief QETSVG::yFromAttribute + * @param xml_element + * @param def_value + * @return + */ +qreal QETSVG::yFromAttribute(const QDomElement &xml_element, const qreal &def_value) { + qreal value; + if (QET::attributeIsAReal(xml_element, QStringLiteral("y"), &value)) { + return value; + } + return def_value; +} + +/** + * @brief QETSVG::heightToAttribute + * @param height + * @param xml_element + */ +void QETSVG::heightToAttribute(const qreal &height, QDomElement &xml_element) { + xml_element.setAttribute(QStringLiteral("height"), QString::number(height)); +} + +qreal QETSVG::heightFromAttribute(const QDomElement &xml_element, const qreal &def_value) { + qreal value; + if (QET::attributeIsAReal(xml_element, QStringLiteral("height"), &value)) { + return value; + } + return def_value; +} + +void QETSVG::rToAttribute(const qreal &r, QDomElement &xml_element) { + xml_element.setAttribute(QStringLiteral("r"), QString::number(r)); +} + +qreal QETSVG::rFromAttribute(const QDomElement &xml_element, const qreal &def_value) { + qreal value; + if (QET::attributeIsAReal(xml_element, QStringLiteral("r"), &value)) { + return value; + } + return def_value; + +} + +void QETSVG::pointsToAttribute(const QVector &points, QDomElement &xml_element) +{ + QStringList strl; + for (const auto &point : points) { + strl.append(QString::number(point.x()) + + QString(",") + + QString::number(point.y())); + } + + xml_element.setAttribute(QStringLiteral("points"), strl.join(" ")); +} + +/** + * @brief QETSVG::pointsFromAttribute + * @param xml_element + * @return a vector of points stored in attribute 'points' of @xml_element. + * The returned vector can be empty. + */ +QVector QETSVG::pointsFromAttribute(const QDomElement &xml_element) +{ + QVector vector; + if (const auto string_points = xml_element.attribute(QStringLiteral("points")).split(QStringLiteral(" ")) ; + !string_points.isEmpty()) { + bool x_ok, y_ok; for (const auto &point : string_points) { + const auto string_x_y = point.split(QStringLiteral(",")); + if (string_x_y.size() == 2) { + const auto x = string_x_y[0].toDouble(&x_ok); + const auto y = string_x_y[1].toDouble(&y_ok); + if (x_ok && y_ok) { + vector.append(QPointF{x,y}); + } + } + } + } + + return vector; +} diff --git a/sources/svg/qetsvg.h b/sources/svg/qetsvg.h new file mode 100644 index 000000000..037d33c7c --- /dev/null +++ b/sources/svg/qetsvg.h @@ -0,0 +1,51 @@ +/* + Copyright 2006-2025 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#ifndef QETSVG_H +#define QETSVG_H + +#include + +class QDomDocument; +class QPointF; +class QRect; + +/** + * @namespace QETSVG + * @brief the QETSVG namespace provide function read and write svg. + * Some function work on xml element (ex rect) and some other + * work on attribute of an element (ex x) + */ +namespace QETSVG +{ + QDomElement rectToElmt(const QRect &rect, QDomDocument &parent_document); + QRect rectFromElmt(const QDomElement &xml_element); + + void yToAttribute(const qreal &y, QDomElement &xml_element); + qreal yFromAttribute(const QDomElement &xml_element, const qreal &def_value=0); + + void heightToAttribute(const qreal &height, QDomElement &xml_element); + qreal heightFromAttribute(const QDomElement &xml_element, const qreal &def_value=10); + + void rToAttribute(const qreal &r, QDomElement &xml_element); + qreal rFromAttribute(const QDomElement &xml_element, const qreal &def_value=1); + + void pointsToAttribute(const QVector &points, QDomElement &xml_element); + QVector pointsFromAttribute (const QDomElement &xml_element); +} + +#endif // QETSVG_H diff --git a/sources/xml/terminalstriplayoutpatternxml.cpp b/sources/xml/terminalstriplayoutpatternxml.cpp new file mode 100644 index 000000000..9ae8a0dbb --- /dev/null +++ b/sources/xml/terminalstriplayoutpatternxml.cpp @@ -0,0 +1,191 @@ +/* + Copyright 2006-2025 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#include "terminalstriplayoutpatternxml.h" + +#include "../TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h" +#include "../qetxml.h" +#include "../svg/qetsvg.h" + +const QString LAYOUT_PATTERN_TAG_NAME { QStringLiteral("terminal_strip_layout_pattern") }; +const QString LAYOUTS_PATTERN_TAG_NAME { QStringLiteral("terminal_strip_layouts_pattern") }; + +/** + * @brief TerminalStripLayoutPatternXml::toXml + * Save a vector of @class TerminalStripLayoutPattern into main xml element + * with tagg name 'terminal_strip_layouts_pattern' who itself embedded each single @class TerminalStripLayoutPattern + * into a xml element with tag name 'terminal_strip_layout_pattern' (layout without 'S' at the end) + * @param patterns + * @param document + * @return + */ +QDomElement TerminalStripLayoutPatternXml::toXml(const QVector > &patterns, + QDomDocument &document) +{ + auto dom_element = document.createElement(LAYOUTS_PATTERN_TAG_NAME); + for (const auto &pattern : patterns) + { + const auto child_ = toXml(pattern, document); + if (!child_.isNull()) { + dom_element.appendChild(child_); + } + } + + return dom_element; +} + +/** + * @brief TerminalStripLayoutPatternXml::fromXml + * Load a vector of @class TerminalStripLayoutPattern from a main xml element + * with tagg name 'terminal_strip_layouts_pattern' who itself have several child + * with tag name 'terminal_strip_layout_pattern' (layout without 'S' at the end) for every + * @class TerminalStripLayoutPattern to load + * @param element + * @return + */ +QVector > TerminalStripLayoutPatternXml::fromXml(const QDomElement &element) +{ + QVector > returned_vector; + + for (const auto &dom_elmt : QETXML::subChild(element, + LAYOUTS_PATTERN_TAG_NAME, + LAYOUT_PATTERN_TAG_NAME)) + { + auto layout_pattern = QSharedPointer::create(); + fromXml(layout_pattern, dom_elmt); + + returned_vector << layout_pattern; + } + + return returned_vector; +} + +/** + * @brief TerminalStripLayoutPatternXml::toXml + * Save a @class TerminalStripLayoutPattern to a xml element with tag name terminal_strip_layout_pattern + * @param pattern + * @param document + * @return + */ +QDomElement TerminalStripLayoutPatternXml::toXml(const QSharedPointer &pattern, QDomDocument &document) +{ + auto pattern_xml = document.createElement(LAYOUT_PATTERN_TAG_NAME); + if (!pattern.isNull()) { + //Write strip pattern attributes + pattern_xml.setAttribute(QStringLiteral("name"), pattern->m_name); + pattern_xml.setAttribute(QStringLiteral("uuid"), pattern->m_uuid.toString()); + + //Write header properties + auto header_xml = document.createElement(QStringLiteral("header")); + header_xml.appendChild(QETSVG::rectToElmt(pattern->m_header_rect, document)); + + auto header_text_xml = document.createElement(QStringLiteral("text")); + QETXML::orientationToAttribute(pattern->m_header_text_orientation, header_text_xml); + QETXML::alignmentToAttribute(pattern->headerTextAlignment(),header_text_xml); + + //Write spacer properties + auto spacer_xml = document.createElement(QStringLiteral("spacer")); + spacer_xml.appendChild(QETSVG::rectToElmt(pattern->m_spacer_rect, document)); + + pattern_xml.appendChild(header_xml).appendChild(header_text_xml); + pattern_xml.appendChild(spacer_xml); + + //Write terminals properties + auto terminals_xml = document.createElement(QStringLiteral("terminals")); + for (const auto &rect : pattern->m_terminal_rect) { + terminals_xml.appendChild(QETSVG::rectToElmt(rect, document)); + } + + auto terminals_text_xml = document.createElement(QStringLiteral("text")); + QETXML::orientationToAttribute(pattern->m_terminals_text_orientation, terminals_text_xml); + QETXML::alignmentToAttribute(pattern->terminalsTextAlignment(),terminals_text_xml); + QETSVG::yToAttribute(pattern->m_terminals_text_y, terminals_text_xml); + QETSVG::heightToAttribute(pattern->m_terminals_text_height, terminals_text_xml); + terminals_xml.appendChild(terminals_text_xml); + + auto bridge_xml = document.createElement(QStringLiteral("bridges")); + QETSVG::rToAttribute(static_cast(pattern->m_bridge_point_d)/2, bridge_xml); + QETSVG::pointsToAttribute(QVector{QPointF{0, static_cast (pattern->m_bridge_point_y_offset.at(0))}, + QPointF{0, static_cast (pattern->m_bridge_point_y_offset.at(1))}, + QPointF{0, static_cast (pattern->m_bridge_point_y_offset.at(2))}, + QPointF{0, static_cast (pattern->m_bridge_point_y_offset.at(3))}}, + bridge_xml); + terminals_xml.appendChild(bridge_xml); + + pattern_xml.appendChild(terminals_xml); + } + + return pattern_xml; +} + +/** + * @brief TerminalStripLayoutPatternXml::fromXml + * LOad a @class TerminalStripLayoutPattern from a xml element with tag name terminal_strip_layout_pattern + * @param layout + * @param element + */ +void TerminalStripLayoutPatternXml::fromXml(QSharedPointer &layout, const QDomElement &element) +{ + if (element.tagName() != LAYOUT_PATTERN_TAG_NAME) return; + layout->m_name = element.attribute(QStringLiteral("name"), layout->m_name); + layout->m_uuid.fromString(element.attribute(QStringLiteral("uuid"), layout->m_uuid.toString())); + + const auto header_xml = element.firstChildElement(QStringLiteral("header")); + if (!header_xml.isNull() && header_xml.hasAttribute(QStringLiteral("rect"))) { + layout->m_header_rect = QETSVG::rectFromElmt(header_xml); + } + + if (const auto header_text_xml = header_xml.firstChildElement(QStringLiteral("text")); + !header_text_xml.isNull()) { + layout->m_header_text_orientation = QETXML::orientationFromAttribute(header_text_xml, layout->m_header_text_orientation); + layout->setHeaderTextAlignment(QETXML::alignmentFromAttribute(header_text_xml)); + } + + const auto spacer_xml = element.firstChildElement(QStringLiteral("spacer")); + if (const auto rect = QETSVG::rectFromElmt(spacer_xml); + !rect.isNull()) { + layout->m_spacer_rect = rect; + } + + if (const auto terminals_xml = element.firstChildElement(QStringLiteral("terminals")); + !terminals_xml.isNull()) { + layout->m_terminal_rect.clear(); + for (const auto &terminal_rect_xml : QETXML::directChild(terminals_xml, QStringLiteral("rect"))) { + layout->m_terminal_rect.append(QETSVG::rectFromElmt(terminal_rect_xml)) ; + } + + if (const auto terminals_text_xml = terminals_xml.firstChildElement(QStringLiteral("text")); + !terminals_text_xml.isNull()) { + layout->m_terminals_text_orientation = QETXML::orientationFromAttribute(terminals_text_xml, layout->m_terminals_text_orientation); + layout->setTerminalsTextAlignment(QETXML::alignmentFromAttribute(terminals_text_xml)); + layout->m_terminals_text_y = QETSVG::yFromAttribute(terminals_text_xml); + layout->m_terminals_text_height = QETSVG::heightFromAttribute(terminals_text_xml); + } + + if (const auto bridge_xml = terminals_xml.firstChildElement(QStringLiteral("bridges")); + !bridge_xml.isNull()) { + layout->m_bridge_point_d = QETSVG::rFromAttribute(bridge_xml, 2.5)*2; + if (const auto points = QETSVG::pointsFromAttribute(bridge_xml); + points.size() == 4) { + layout->m_bridge_point_y_offset[0]= static_cast(points[0].y()); + layout->m_bridge_point_y_offset[1]= static_cast(points[1].y()); + layout->m_bridge_point_y_offset[2]= static_cast(points[2].y()); + layout->m_bridge_point_y_offset[3]= static_cast(points[3].y()); + } + } + } +} diff --git a/sources/xml/terminalstriplayoutpatternxml.h b/sources/xml/terminalstriplayoutpatternxml.h new file mode 100644 index 000000000..644d7ff12 --- /dev/null +++ b/sources/xml/terminalstriplayoutpatternxml.h @@ -0,0 +1,41 @@ +/* + Copyright 2006-2025 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#ifndef TERMINALSTRIPLAYOUTPATTERNXML_H +#define TERMINALSTRIPLAYOUTPATTERNXML_H + +#include +#include + +class TerminalStripLayoutPattern; + +/** + * @brief The TerminalStripLayoutPatternXml class + * A class used to save/restor a @class TerminalStripLayoutPattern to + * xml + */ +class TerminalStripLayoutPatternXml +{ + public: + static QDomElement toXml(const QVector> &patterns, QDomDocument &document); + static QVector> fromXml(const QDomElement &element); + + static QDomElement toXml (const QSharedPointer &pattern, QDomDocument &document); + static void fromXml(QSharedPointer &layout, const QDomElement &element); +}; + +#endif // TERMINALSTRIPLAYOUTPATTERNXML_H From d699faf5017b721ec9beeea4a20bc137af8aa47f Mon Sep 17 00:00:00 2001 From: joshua Date: Sun, 8 Jun 2025 21:40:32 +0200 Subject: [PATCH 07/15] Change some int to qreal Made this change to be more compliant with svg --- .../properties/terminalstriplayoutpattern.h | 22 ++++----- .../GraphicsItem/terminalstripdrawer.cpp | 18 ++++---- .../GraphicsItem/terminalstripdrawer.h | 4 +- sources/svg/qetsvg.cpp | 46 +++++++++---------- sources/svg/qetsvg.h | 6 +-- sources/xml/terminalstriplayoutpatternxml.cpp | 20 ++++---- sources/xml/terminalstriplayoutpatternxml.h | 4 +- 7 files changed, 60 insertions(+), 60 deletions(-) diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h index 03bbf21ec..1b5f0c40a 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h @@ -44,38 +44,38 @@ class TerminalStripLayoutPattern TerminalStripLayoutPattern(); //Header of terminal strip - QRect m_header_rect{0,30,50,130}; + QRectF m_header_rect{0,30,50,130}; Qt::Orientation m_header_text_orientation{Qt::Horizontal}; void setHeaderTextAlignment(const Qt::Alignment &alignment); Qt::Alignment headerTextAlignment() const; QTextOption headerTextOption() const; //Spacer between the header and the terminals - QRect m_spacer_rect{0, 50, 10, 90}; + QRectF m_spacer_rect{0, 50, 10, 90}; //Font QFont font() const; void setFont (const QFont &font); //Terminals - QVector m_terminal_rect + QVector m_terminal_rect { - QRect{0, 0, 20, 190}, - QRect{0, 10, 20, 170}, - QRect{0, 20, 20, 150}, - QRect{0, 30, 20, 130} + QRectF{0, 0, 20, 190}, + QRectF{0, 10, 20, 170}, + QRectF{0, 20, 20, 150}, + QRectF{0, 30, 20, 130} }; //Terminal text void setTerminalsTextAlignment(const Qt::Alignment &alignment); Qt::Alignment terminalsTextAlignment() const; QTextOption terminalsTextOption() const; - int m_terminals_text_height{50}; - int m_terminals_text_y{35}; + qreal m_terminals_text_height{50}; + qreal m_terminals_text_y{35}; Qt::Orientation m_terminals_text_orientation {Qt::Vertical}; - int m_bridge_point_d{5}; - QVector m_bridge_point_y_offset{50,70,90,110}; + qreal m_bridge_point_d{5}; + QVector m_bridge_point_y_offset{50,70,90,110}; QUuid m_uuid{QUuid::createUuid()}; QString m_name; diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp index 256665305..4b94b9284 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp @@ -95,7 +95,7 @@ void TerminalStripDrawer::paint(QPainter *painter) //Move painter pos to next drawing painter->translate(m_pattern->m_header_rect.width(),0); - int x_offset{m_pattern->m_header_rect.width()}; + qreal x_offset{m_pattern->m_header_rect.width()}; //Draw spacer painter->drawRect(m_pattern->m_spacer_rect); @@ -109,7 +109,7 @@ void TerminalStripDrawer::paint(QPainter *painter) const auto terminals_text_option{m_pattern->terminalsTextOption()}; const auto terminals_text_height{m_pattern->m_terminals_text_height}; const auto terminals_text_y{m_pattern->m_terminals_text_y}; - QRect terminal_rect; + QRectF terminal_rect; QHash> bridges_anchor_points; @@ -145,7 +145,7 @@ void TerminalStripDrawer::paint(QPainter *painter) //We can't use terminal_rect.bottomLeft for p2 because //the returned value deviate from the true value //(see Qt documentation about QRect) - const QPoint p2 { p1.x(), p1.y() + terminal_rect.height() }; + const QPointF p2 { p1.x(), p1.y() + terminal_rect.height() }; painter->drawLine(p1, p2); painter->restore(); } @@ -154,8 +154,8 @@ void TerminalStripDrawer::paint(QPainter *painter) { painter->save(); painter->setPen(Qt::yellow); - painter->drawLine(QPoint{terminal_rect.x(), terminal_rect.y() + terminal_rect.height()/2}, - QPoint{terminal_rect.width(), terminal_rect.y() + terminal_rect.height()/2}); + painter->drawLine(QPointF{terminal_rect.x(), terminal_rect.y() + terminal_rect.height()/2}, + QPointF{terminal_rect.width(), terminal_rect.y() + terminal_rect.height()/2}); painter->restore(); } @@ -226,7 +226,7 @@ void TerminalStripDrawer::paint(QPainter *painter) QRectF TerminalStripDrawer::boundingRect() const { - return QRect{0, 0, width(), height()};; + return QRectF{0, 0, width(), height()};; } void TerminalStripDrawer::setLayout(QSharedPointer layout) @@ -243,7 +243,7 @@ void TerminalStripDrawer::setPreviewDraw(bool draw) { m_preview_draw = draw; } -int TerminalStripDrawer::height() const +qreal TerminalStripDrawer::height() const { if (m_pattern) { @@ -261,11 +261,11 @@ int TerminalStripDrawer::height() const return 0; } -int TerminalStripDrawer::width() const +qreal TerminalStripDrawer::width() const { if (m_pattern) { - int width_{m_pattern->m_header_rect.width() + m_pattern->m_spacer_rect.width()}; + qreal width_{m_pattern->m_header_rect.width() + m_pattern->m_spacer_rect.width()}; if (m_strip) { diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h index 20f41478c..72286c41d 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h @@ -80,8 +80,8 @@ namespace TerminalStripDrawer void setPreviewDraw(bool draw = true); private: - int height() const; - int width() const; + qreal height() const; + qreal width() const; private: QSharedPointer m_strip; diff --git a/sources/svg/qetsvg.cpp b/sources/svg/qetsvg.cpp index ba5ac7d99..c1fa1bdca 100644 --- a/sources/svg/qetsvg.cpp +++ b/sources/svg/qetsvg.cpp @@ -29,7 +29,7 @@ * @param parent_document * @return */ -QDomElement QETSVG::rectToElmt(const QRect &rect, QDomDocument &parent_document) +QDomElement QETSVG::rectToElmt(const QRectF &rect, QDomDocument &parent_document) { auto dom_element = parent_document.createElement(QStringLiteral("rect")); if (!rect.isNull()) { @@ -47,16 +47,16 @@ QDomElement QETSVG::rectToElmt(const QRect &rect, QDomDocument &parent_document) * The tag name must be 'rect' if not, the returned QRect is null. * @return a svg rect to QRect */ -QRect QETSVG::rectFromElmt(const QDomElement &xml_element) +QRectF QETSVG::rectFromElmt(const QDomElement &xml_element) { - QRect rect; + QRectF rect_; if (xml_element.tagName() == QLatin1String("rect")) { - rect.setRect(xml_element.attribute(QStringLiteral("x"), QStringLiteral("0")).toInt(), - static_cast (yFromAttribute(xml_element, 0)), - xml_element.attribute(QStringLiteral("width"), QStringLiteral("10")).toInt(), - static_cast (heightFromAttribute(xml_element, 10))); + rect_.setRect(xml_element.attribute(QStringLiteral("x"), QStringLiteral("0")).toDouble(), + yFromAttribute(xml_element, 0), + xml_element.attribute(QStringLiteral("width"), QStringLiteral("10")).toDouble(), + heightFromAttribute(xml_element, 10)); } - return rect; + return rect_; } /** @@ -75,9 +75,9 @@ void QETSVG::yToAttribute(const qreal &y, QDomElement &xml_element) { * @return */ qreal QETSVG::yFromAttribute(const QDomElement &xml_element, const qreal &def_value) { - qreal value; - if (QET::attributeIsAReal(xml_element, QStringLiteral("y"), &value)) { - return value; + qreal value_; + if (QET::attributeIsAReal(xml_element, QStringLiteral("y"), &value_)) { + return value_; } return def_value; } @@ -92,9 +92,9 @@ void QETSVG::heightToAttribute(const qreal &height, QDomElement &xml_element) { } qreal QETSVG::heightFromAttribute(const QDomElement &xml_element, const qreal &def_value) { - qreal value; - if (QET::attributeIsAReal(xml_element, QStringLiteral("height"), &value)) { - return value; + qreal value_; + if (QET::attributeIsAReal(xml_element, QStringLiteral("height"), &value_)) { + return value_; } return def_value; } @@ -104,9 +104,9 @@ void QETSVG::rToAttribute(const qreal &r, QDomElement &xml_element) { } qreal QETSVG::rFromAttribute(const QDomElement &xml_element, const qreal &def_value) { - qreal value; - if (QET::attributeIsAReal(xml_element, QStringLiteral("r"), &value)) { - return value; + qreal value_; + if (QET::attributeIsAReal(xml_element, QStringLiteral("r"), &value_)) { + return value_; } return def_value; @@ -114,14 +114,14 @@ qreal QETSVG::rFromAttribute(const QDomElement &xml_element, const qreal &def_va void QETSVG::pointsToAttribute(const QVector &points, QDomElement &xml_element) { - QStringList strl; + QStringList strl_; for (const auto &point : points) { - strl.append(QString::number(point.x()) + + strl_.append(QString::number(point.x()) + QString(",") + QString::number(point.y())); } - xml_element.setAttribute(QStringLiteral("points"), strl.join(" ")); + xml_element.setAttribute(QStringLiteral("points"), strl_.join(" ")); } /** @@ -132,7 +132,7 @@ void QETSVG::pointsToAttribute(const QVector &points, QDomElement &xml_ */ QVector QETSVG::pointsFromAttribute(const QDomElement &xml_element) { - QVector vector; + QVector vector_; if (const auto string_points = xml_element.attribute(QStringLiteral("points")).split(QStringLiteral(" ")) ; !string_points.isEmpty()) { bool x_ok, y_ok; for (const auto &point : string_points) { @@ -141,11 +141,11 @@ QVector QETSVG::pointsFromAttribute(const QDomElement &xml_element) const auto x = string_x_y[0].toDouble(&x_ok); const auto y = string_x_y[1].toDouble(&y_ok); if (x_ok && y_ok) { - vector.append(QPointF{x,y}); + vector_.append(QPointF{x,y}); } } } } - return vector; + return vector_; } diff --git a/sources/svg/qetsvg.h b/sources/svg/qetsvg.h index 037d33c7c..0577236ea 100644 --- a/sources/svg/qetsvg.h +++ b/sources/svg/qetsvg.h @@ -22,7 +22,7 @@ class QDomDocument; class QPointF; -class QRect; +class QRectF; /** * @namespace QETSVG @@ -32,8 +32,8 @@ class QRect; */ namespace QETSVG { - QDomElement rectToElmt(const QRect &rect, QDomDocument &parent_document); - QRect rectFromElmt(const QDomElement &xml_element); + QDomElement rectToElmt(const QRectF &rect, QDomDocument &parent_document); + QRectF rectFromElmt(const QDomElement &xml_element); void yToAttribute(const qreal &y, QDomElement &xml_element); qreal yFromAttribute(const QDomElement &xml_element, const qreal &def_value=0); diff --git a/sources/xml/terminalstriplayoutpatternxml.cpp b/sources/xml/terminalstriplayoutpatternxml.cpp index 9ae8a0dbb..5ea20a1cb 100644 --- a/sources/xml/terminalstriplayoutpatternxml.cpp +++ b/sources/xml/terminalstriplayoutpatternxml.cpp @@ -118,12 +118,12 @@ QDomElement TerminalStripLayoutPatternXml::toXml(const QSharedPointer(pattern->m_bridge_point_d)/2, bridge_xml); - QETSVG::pointsToAttribute(QVector{QPointF{0, static_cast (pattern->m_bridge_point_y_offset.at(0))}, - QPointF{0, static_cast (pattern->m_bridge_point_y_offset.at(1))}, - QPointF{0, static_cast (pattern->m_bridge_point_y_offset.at(2))}, - QPointF{0, static_cast (pattern->m_bridge_point_y_offset.at(3))}}, - bridge_xml); + QETSVG::rToAttribute(pattern->m_bridge_point_d/2, bridge_xml); + QVector points_vector; + for (const auto &y : pattern->m_bridge_point_y_offset) { + points_vector.append(QPointF{0,y}); + } + QETSVG::pointsToAttribute(points_vector, bridge_xml); terminals_xml.appendChild(bridge_xml); pattern_xml.appendChild(terminals_xml); @@ -181,10 +181,10 @@ void TerminalStripLayoutPatternXml::fromXml(QSharedPointerm_bridge_point_d = QETSVG::rFromAttribute(bridge_xml, 2.5)*2; if (const auto points = QETSVG::pointsFromAttribute(bridge_xml); points.size() == 4) { - layout->m_bridge_point_y_offset[0]= static_cast(points[0].y()); - layout->m_bridge_point_y_offset[1]= static_cast(points[1].y()); - layout->m_bridge_point_y_offset[2]= static_cast(points[2].y()); - layout->m_bridge_point_y_offset[3]= static_cast(points[3].y()); + layout->m_bridge_point_y_offset[0]= points[0].y(); + layout->m_bridge_point_y_offset[1]= points[1].y(); + layout->m_bridge_point_y_offset[2]= points[2].y(); + layout->m_bridge_point_y_offset[3]= points[3].y(); } } } diff --git a/sources/xml/terminalstriplayoutpatternxml.h b/sources/xml/terminalstriplayoutpatternxml.h index 644d7ff12..df6dba87b 100644 --- a/sources/xml/terminalstriplayoutpatternxml.h +++ b/sources/xml/terminalstriplayoutpatternxml.h @@ -25,8 +25,8 @@ class TerminalStripLayoutPattern; /** * @brief The TerminalStripLayoutPatternXml class - * A class used to save/restor a @class TerminalStripLayoutPattern to - * xml + * A class with static function used to save/restor a + * @class TerminalStripLayoutPattern to xml */ class TerminalStripLayoutPatternXml { From 3a6b4807dbe1a0fb6bb28f918d25c1d01bbfac05 Mon Sep 17 00:00:00 2001 From: joshua Date: Mon, 9 Jun 2025 21:35:00 +0200 Subject: [PATCH 08/15] Fix crash. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix crash when : 1°-Open a project with terminal strip and open the terminal strip editor 2°-Close the terminal strip editor and the project (keep qelectrotech open). 3°-redo step 1 and click on an item in the tree at left of the window, qet crash. Qet don't crash anymore but the terminal strip editor continue to work with the terminal strip of the first opening (exactly the pointer of the terminal strip) who don't exist anymore. Need more work. --- sources/TerminalStrip/ui/terminalstriptreedockwidget.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sources/TerminalStrip/ui/terminalstriptreedockwidget.h b/sources/TerminalStrip/ui/terminalstriptreedockwidget.h index 31ed57b32..6fdbb1ee1 100644 --- a/sources/TerminalStrip/ui/terminalstriptreedockwidget.h +++ b/sources/TerminalStrip/ui/terminalstriptreedockwidget.h @@ -74,7 +74,7 @@ class TerminalStripTreeDockWidget : public QDockWidget QPointer m_project; QPointer m_current_strip; - QHash m_item_strip_H; + QHash> m_item_strip_H; QHash> m_uuid_terminal_H; QHash> m_uuid_strip_H; QVector m_strip_changed_connection; From d711d8fb4abc4586c1b33343b2540cac30483e43 Mon Sep 17 00:00:00 2001 From: joshua Date: Wed, 11 Jun 2025 22:43:41 +0200 Subject: [PATCH 09/15] Terminal strip editor can now edit multiple project. Before this this commit the terminal strip editor couldn't only work on the first project opened into this editor, all other project opened after couldn't be edited. This is now past, terminal strip editor can now edit every project open in QElectroTech. --- .../TerminalStrip/ui/freeterminaleditor.cpp | 35 +++++++++++-- sources/TerminalStrip/ui/freeterminaleditor.h | 8 +-- .../TerminalStrip/ui/freeterminalmodel.cpp | 52 +++++++++++++------ sources/TerminalStrip/ui/freeterminalmodel.h | 1 + .../TerminalStrip/ui/terminalstripeditor.cpp | 43 +++++++++------ .../TerminalStrip/ui/terminalstripeditor.h | 8 +-- .../ui/terminalstripeditorwindow.cpp | 17 ++++-- .../ui/terminalstripeditorwindow.h | 5 +- .../ui/terminalstriptreedockwidget.cpp | 34 ++++++++++-- .../ui/terminalstriptreedockwidget.h | 4 +- 10 files changed, 159 insertions(+), 48 deletions(-) diff --git a/sources/TerminalStrip/ui/freeterminaleditor.cpp b/sources/TerminalStrip/ui/freeterminaleditor.cpp index 2f41c6a24..7f5393fb7 100644 --- a/sources/TerminalStrip/ui/freeterminaleditor.cpp +++ b/sources/TerminalStrip/ui/freeterminaleditor.cpp @@ -32,16 +32,20 @@ */ FreeTerminalEditor::FreeTerminalEditor(QETProject *project, QWidget *parent) : QWidget(parent), - ui(new Ui::FreeTerminalEditor), - m_project(project) + ui(new Ui::FreeTerminalEditor), + m_project(project) { ui->setupUi(this); ui->m_table_view->setItemDelegate(new FreeTerminalModelDelegate(ui->m_table_view)); - m_model = new FreeTerminalModel(m_project, this); + m_model = new FreeTerminalModel(m_project, this); ui->m_table_view->setModel(m_model); ui->m_table_view->setCurrentIndex(m_model->index(0,0)); + if (m_project) { + connect(m_project, &QObject::destroyed, this, &FreeTerminalEditor::reload); + } + //Disabled the move if the table is currently edited (yellow cell) connect(m_model, &FreeTerminalModel::dataChanged, this, [=] { this->setDisabledMove(); @@ -135,6 +139,31 @@ void FreeTerminalEditor::apply() reload(); } +/** + * @brief FreeTerminalEditor::setProject + * Set @project as project handled by this editor. + * If a previous project was setted, everything is clear. + * This function track the destruction of the project, + * that mean if the project pointer is deleted + * no need to call this function with a nullptr, + * everything is made inside this class. + * @param project + */ +void FreeTerminalEditor::setProject(QETProject *project) +{ + if(m_project) { + disconnect(m_project, &QObject::destroyed, this, &FreeTerminalEditor::reload); + } + m_project = project; + if (m_model) { + m_model->setProject(project); + } + if (m_project) { + connect(m_project, &QObject::destroyed, this, &FreeTerminalEditor::reload); + } + reload(); +} + void FreeTerminalEditor::on_m_type_cb_activated(int index) { if (m_model) diff --git a/sources/TerminalStrip/ui/freeterminaleditor.h b/sources/TerminalStrip/ui/freeterminaleditor.h index a185a109e..6c1455d03 100644 --- a/sources/TerminalStrip/ui/freeterminaleditor.h +++ b/sources/TerminalStrip/ui/freeterminaleditor.h @@ -19,8 +19,8 @@ #define FREETERMINALEDITOR_H #include +#include "../../qetproject.h" -class QETProject; class RealTerminal; class FreeTerminalModel; class QTableView; @@ -40,6 +40,8 @@ class FreeTerminalEditor : public QWidget void reload(); void apply(); + void setProject(QETProject *project); + private slots: void on_m_type_cb_activated(int index); void on_m_function_cb_activated(int index); @@ -52,7 +54,7 @@ class FreeTerminalEditor : public QWidget private: Ui::FreeTerminalEditor *ui; - QETProject *m_project = nullptr; - FreeTerminalModel *m_model = nullptr; + QPointer m_project; + FreeTerminalModel *m_model {nullptr}; }; #endif // FREETERMINALEDITOR_H diff --git a/sources/TerminalStrip/ui/freeterminalmodel.cpp b/sources/TerminalStrip/ui/freeterminalmodel.cpp index 426b60e07..d3b59ef05 100644 --- a/sources/TerminalStrip/ui/freeterminalmodel.cpp +++ b/sources/TerminalStrip/ui/freeterminalmodel.cpp @@ -56,10 +56,30 @@ FreeTerminalModel::Column FreeTerminalModel::columnTypeForIndex(const QModelInde * @param parent */ FreeTerminalModel::FreeTerminalModel(QETProject *project, QObject *parent) : - QAbstractTableModel(parent), - m_project(project) + QAbstractTableModel(parent) { + setProject(project); +} + +/** + * @brief FreeTerminalModel::setProject + * Set @project as project handled by this model. + * If a previous project was setted, everything is clear. + * This function track the destruction of the project, + * that mean if the project pointer is deleted + * no need to call this function with a nullptr, + * everything is made inside this class. + * @param project + */ +void FreeTerminalModel::setProject(QETProject *project) { - fillTerminalVector(); + if(m_project) { + disconnect(m_project, &QObject::destroyed, this, &FreeTerminalModel::clear); + } + m_project = project; + if (m_project) { + connect(m_project, &QObject::destroyed, this, &FreeTerminalModel::clear); + } + clear(); } /** @@ -305,20 +325,22 @@ QVector > FreeTerminalModel::realTerminalForIndex(c */ void FreeTerminalModel::fillTerminalVector() { - ElementProvider provider_(m_project); - auto free_terminal_vector = provider_.freeTerminal(); + if (m_project) { + ElementProvider provider_(m_project); + auto free_terminal_vector = provider_.freeTerminal(); - std::sort(free_terminal_vector.begin(), free_terminal_vector.end(), - [](TerminalElement *a, TerminalElement *b) - { - return QETUtils::sortBeginIntString(a->elementData().m_informations.value(QETInformation::ELMT_LABEL).toString(), - b->elementData().m_informations.value(QETInformation::ELMT_LABEL).toString()); - }); + std::sort(free_terminal_vector.begin(), free_terminal_vector.end(), + [](TerminalElement *a, TerminalElement *b) + { + return QETUtils::sortBeginIntString(a->elementData().m_informations.value(QETInformation::ELMT_LABEL).toString(), + b->elementData().m_informations.value(QETInformation::ELMT_LABEL).toString()); + }); - for (const auto &terminal_ : free_terminal_vector) { - m_terminal_vector.append(terminal_->realTerminal()); - m_real_t_data.append(modelRealTerminalData::data(terminal_->realTerminal())); - } + for (const auto &terminal_ : free_terminal_vector) { + m_terminal_vector.append(terminal_->realTerminal()); + m_real_t_data.append(modelRealTerminalData::data(terminal_->realTerminal())); + } + } } /**************************************************************** diff --git a/sources/TerminalStrip/ui/freeterminalmodel.h b/sources/TerminalStrip/ui/freeterminalmodel.h index 5d13cafc4..bc64dd0dd 100644 --- a/sources/TerminalStrip/ui/freeterminalmodel.h +++ b/sources/TerminalStrip/ui/freeterminalmodel.h @@ -47,6 +47,7 @@ class FreeTerminalModel : public QAbstractTableModel public: explicit FreeTerminalModel(QETProject *project, QObject *parent = nullptr); + void setProject(QETProject *project); int rowCount(const QModelIndex &parent) const override; int columnCount(const QModelIndex &parent) const override; diff --git a/sources/TerminalStrip/ui/terminalstripeditor.cpp b/sources/TerminalStrip/ui/terminalstripeditor.cpp index a2ff47b99..d65d1c128 100644 --- a/sources/TerminalStrip/ui/terminalstripeditor.cpp +++ b/sources/TerminalStrip/ui/terminalstripeditor.cpp @@ -84,6 +84,12 @@ TerminalStripEditor::~TerminalStripEditor() { delete ui; } +void TerminalStripEditor::setProject(QETProject *project) +{ + m_project = project; + setCurrentStrip(nullptr); +} + /** * @brief TerminalStripEditor::setCurrentStrip * Set the current terminal strip edited to \p strip_ @@ -98,27 +104,15 @@ void TerminalStripEditor::setCurrentStrip(TerminalStrip *strip_) if (m_current_strip) { disconnect(m_current_strip, &TerminalStrip::orderChanged, this, &TerminalStripEditor::reload); disconnect(m_current_strip, &TerminalStrip::bridgeChanged, this, &TerminalStripEditor::reload); + disconnect(m_current_strip, &QObject::destroyed, this, &TerminalStripEditor::clear); } ui->m_move_to_cb->clear(); - if (!strip_) - { - ui->m_installation_le ->clear(); - ui->m_location_le ->clear(); - ui->m_name_le ->clear(); - ui->m_comment_le ->clear(); - ui->m_description_te ->clear(); - m_current_strip = nullptr; - - ui->m_table_widget->setModel(nullptr); - if (m_model) { - m_model->deleteLater(); - m_model = nullptr; - } + if (!strip_) { + clear(); } - else - { + else { ui->m_installation_le ->setText(strip_->installation()); ui->m_location_le ->setText(strip_->location()); ui->m_name_le ->setText(strip_->name()); @@ -159,6 +153,7 @@ void TerminalStripEditor::setCurrentStrip(TerminalStrip *strip_) connect(m_current_strip, &TerminalStrip::orderChanged, this, &TerminalStripEditor::reload); connect(m_current_strip, &TerminalStrip::bridgeChanged, this, &TerminalStripEditor::reload); + connect(m_current_strip, &QObject::destroyed, this, &TerminalStripEditor::clear); } } @@ -230,6 +225,22 @@ void TerminalStripEditor::apply() reload(); } +void TerminalStripEditor::clear() +{ + ui->m_installation_le ->clear(); + ui->m_location_le ->clear(); + ui->m_name_le ->clear(); + ui->m_comment_le ->clear(); + ui->m_description_te ->clear(); + m_current_strip.clear(); + + ui->m_table_widget->setModel(nullptr); + if (m_model) { + m_model->deleteLater(); + m_model = nullptr; + } +} + /** * @brief TerminalStripEditor::spanMultiLevelTerminals * Span row of m_table_widget for multi-level terminal diff --git a/sources/TerminalStrip/ui/terminalstripeditor.h b/sources/TerminalStrip/ui/terminalstripeditor.h index 5ca482892..f7f839957 100644 --- a/sources/TerminalStrip/ui/terminalstripeditor.h +++ b/sources/TerminalStrip/ui/terminalstripeditor.h @@ -41,11 +41,13 @@ class TerminalStripEditor : public QWidget public: explicit TerminalStripEditor(QETProject *project, QWidget *parent = nullptr); ~TerminalStripEditor() override; + void setProject(QETProject *project); void setCurrentStrip(TerminalStrip *strip_); void reload(); void apply(); private: + void clear(); void spanMultiLevelTerminals(); void selectionChanged(); QSize setUpBridgeCellWidth(); @@ -67,9 +69,9 @@ class TerminalStripEditor : public QWidget private: Ui::TerminalStripEditor *ui; - QETProject *m_project {nullptr}; - TerminalStrip *m_current_strip {nullptr}; - TerminalStripModel *m_model {nullptr}; + QPointer m_project; + QPointer m_current_strip; + TerminalStripModel *m_model {nullptr}; }; #endif // TERMINALSTRIPEDITOR_H diff --git a/sources/TerminalStrip/ui/terminalstripeditorwindow.cpp b/sources/TerminalStrip/ui/terminalstripeditorwindow.cpp index 24a826ea7..7ec4d3c41 100644 --- a/sources/TerminalStrip/ui/terminalstripeditorwindow.cpp +++ b/sources/TerminalStrip/ui/terminalstripeditorwindow.cpp @@ -51,8 +51,8 @@ void TerminalStripEditorWindow::edit(TerminalStrip *strip) TerminalStripEditorWindow::TerminalStripEditorWindow(QETProject *project, QWidget *parent) : QMainWindow(parent), - ui(new Ui::TerminalStripEditorWindow), - m_project(project) + ui(new Ui::TerminalStripEditorWindow), + m_project(project) { ui->setupUi(this); ui->m_remove_terminal->setDisabled(true); @@ -76,6 +76,18 @@ TerminalStripEditorWindow::~TerminalStripEditorWindow() delete ui; } +/** + * @brief TerminalStripEditorWindow::setProject + * @param project + */ +void TerminalStripEditorWindow::setProject(QETProject *project) +{ + m_project = project; + m_tree_dock->setProject(project); + m_free_terminal_editor->setProject(project); + m_terminal_strip_editor->setProject(project); +} + void TerminalStripEditorWindow::setCurrentStrip(TerminalStrip *strip) { m_tree_dock->setSelectedStrip(strip); } @@ -200,4 +212,3 @@ void TerminalStripEditorWindow::on_m_button_box_clicked(QAbstractButton *button) void TerminalStripEditorWindow::on_m_stacked_widget_currentChanged(int arg1) { ui->m_button_box->setHidden(arg1 == EMPTY_PAGE); } - diff --git a/sources/TerminalStrip/ui/terminalstripeditorwindow.h b/sources/TerminalStrip/ui/terminalstripeditorwindow.h index b303d5c35..5ae4a8288 100644 --- a/sources/TerminalStrip/ui/terminalstripeditorwindow.h +++ b/sources/TerminalStrip/ui/terminalstripeditorwindow.h @@ -51,6 +51,8 @@ class TerminalStripEditorWindow : public QMainWindow if (!window_) window_ = new TerminalStripEditorWindow{project, parent}; mutex_.unlock(); + } else { + window_->setProject(project); } return window_; } @@ -71,6 +73,7 @@ class TerminalStripEditorWindow : public QMainWindow explicit TerminalStripEditorWindow(QETProject *project, QWidget *parent = nullptr); ~TerminalStripEditorWindow(); + void setProject(QETProject *project); void setCurrentStrip(TerminalStrip *strip); private slots: @@ -87,7 +90,7 @@ class TerminalStripEditorWindow : public QMainWindow private: Ui::TerminalStripEditorWindow *ui{nullptr}; - QETProject *m_project {nullptr}; + QPointer m_project; TerminalStripTreeDockWidget *m_tree_dock{nullptr}; FreeTerminalEditor *m_free_terminal_editor {nullptr}; TerminalStripEditor *m_terminal_strip_editor {nullptr}; diff --git a/sources/TerminalStrip/ui/terminalstriptreedockwidget.cpp b/sources/TerminalStrip/ui/terminalstriptreedockwidget.cpp index 360d4190d..2e5a5922f 100644 --- a/sources/TerminalStrip/ui/terminalstriptreedockwidget.cpp +++ b/sources/TerminalStrip/ui/terminalstriptreedockwidget.cpp @@ -30,11 +30,10 @@ TerminalStripTreeDockWidget::TerminalStripTreeDockWidget(QETProject *project, QWidget *parent) : QDockWidget(parent), - ui(new Ui::TerminalStripTreeDockWidget), - m_project(project) + ui(new Ui::TerminalStripTreeDockWidget) { ui->setupUi(this); - buildTree(); + setProject(project); #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) ui->m_tree_view->expandRecursively(ui->m_tree_view->rootIndex()); @@ -48,6 +47,32 @@ TerminalStripTreeDockWidget::~TerminalStripTreeDockWidget() delete ui; } +/** + * @brief TerminalStripTreeDockWidget::setProject + * Set @project as project handled by this tree dock. + * If a previous project was setted, everything is clear. + * This function track the destruction of the project, + * that mean if the project pointer is deleted + * no need to call this function with a nullptr, + * everything is made inside this class. + * @param project + */ +void TerminalStripTreeDockWidget::setProject(QETProject *project) +{ + if(m_project && m_project_destroy_connection) { + disconnect(m_project_destroy_connection); + } + m_project = project; + if (m_project) { + m_project_destroy_connection = connect(m_project, &QObject::destroyed, [this](){ + this->m_current_strip.clear(); + this->reload(); + }); + } + m_current_strip.clear(); + reload(); +} + /** * @brief TerminalStripTreeDockWidget::reload */ @@ -205,6 +230,9 @@ void TerminalStripTreeDockWidget::on_m_tree_view_currentItemChanged(QTreeWidgetI */ void TerminalStripTreeDockWidget::buildTree() { + if(!m_project) { + return; + } auto title_ = m_project->title(); if (title_.isEmpty()) { diff --git a/sources/TerminalStrip/ui/terminalstriptreedockwidget.h b/sources/TerminalStrip/ui/terminalstriptreedockwidget.h index 6fdbb1ee1..327bca079 100644 --- a/sources/TerminalStrip/ui/terminalstriptreedockwidget.h +++ b/sources/TerminalStrip/ui/terminalstriptreedockwidget.h @@ -49,6 +49,7 @@ class TerminalStripTreeDockWidget : public QDockWidget explicit TerminalStripTreeDockWidget(QETProject *project, QWidget *parent = nullptr); ~TerminalStripTreeDockWidget(); + void setProject(QETProject *project = nullptr); void reload(); bool currentIsStrip() const; TerminalStrip* currentStrip() const; @@ -78,7 +79,8 @@ class TerminalStripTreeDockWidget : public QDockWidget QHash> m_uuid_terminal_H; QHash> m_uuid_strip_H; QVector m_strip_changed_connection; - bool m_current_is_free_terminal{false}; + bool m_current_is_free_terminal{false}; + QMetaObject::Connection m_project_destroy_connection; }; #endif // TERMINALSTRIPTREEDOCKWIDGET_H From a2ae8255aca9759df407e2db637522b0e5d230ba Mon Sep 17 00:00:00 2001 From: joshua Date: Tue, 1 Jul 2025 22:46:18 +0200 Subject: [PATCH 10/15] Minor fix During the development, we saved some terminal strip with "phantom" terminal (terminal added to the strip and after the terminal was removed from the project but keep in the terminal strip data) and this mistake was saved in the xml. When we open this project the phantom terminal don't appear in the layout but the empty physical terminal is still here in the terminal strip data because the position of the terminals in the strip is wrong (sometime bigger than the size of the strip, sometime with a gap, sometime don't start at 0). This commit fix this mistake when we open a project. --- sources/TerminalStrip/terminalstrip.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sources/TerminalStrip/terminalstrip.cpp b/sources/TerminalStrip/terminalstrip.cpp index 839a5493e..8d469cc3b 100644 --- a/sources/TerminalStrip/terminalstrip.cpp +++ b/sources/TerminalStrip/terminalstrip.cpp @@ -1037,8 +1037,10 @@ bool TerminalStrip::fromXml(QDomElement &xml_element) } } - auto raw_ptr = new PhysicalTerminal(this, real_t_vector); - m_physical_terminals.append(raw_ptr->sharedRef()); + if (!real_t_vector.isEmpty()) { + auto raw_ptr = new PhysicalTerminal(this, real_t_vector); + m_physical_terminals.append(raw_ptr->sharedRef()); + } } } From a121fbe53073583f78ccd072215855fe1018b997 Mon Sep 17 00:00:00 2001 From: joshua Date: Tue, 1 Jul 2025 23:37:16 +0200 Subject: [PATCH 11/15] Add undo / redo command The undo/redo command of diagram editor is shared to the terminal strip editor. --- sources/TerminalStrip/ui/terminalstripeditorwindow.cpp | 5 +++++ sources/TerminalStrip/ui/terminalstripeditorwindow.ui | 4 ++-- sources/qetdiagrameditor.h | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/sources/TerminalStrip/ui/terminalstripeditorwindow.cpp b/sources/TerminalStrip/ui/terminalstripeditorwindow.cpp index 7ec4d3c41..923f1372f 100644 --- a/sources/TerminalStrip/ui/terminalstripeditorwindow.cpp +++ b/sources/TerminalStrip/ui/terminalstripeditorwindow.cpp @@ -55,6 +55,11 @@ TerminalStripEditorWindow::TerminalStripEditorWindow(QETProject *project, QWidge m_project(project) { ui->setupUi(this); + if (auto diagram_editor = QETApp::diagramEditor(project)) { + ui->m_tool_bar->addSeparator(); + ui->m_tool_bar->addAction(diagram_editor->undo); + ui->m_tool_bar->addAction(diagram_editor->redo); + } ui->m_remove_terminal->setDisabled(true); addTreeDockWidget(); diff --git a/sources/TerminalStrip/ui/terminalstripeditorwindow.ui b/sources/TerminalStrip/ui/terminalstripeditorwindow.ui index 43cb3eaa7..f390f33cf 100644 --- a/sources/TerminalStrip/ui/terminalstripeditorwindow.ui +++ b/sources/TerminalStrip/ui/terminalstripeditorwindow.ui @@ -33,12 +33,12 @@ 0 0 1364 - 21 + 23 - + toolBar diff --git a/sources/qetdiagrameditor.h b/sources/qetdiagrameditor.h index 2257d6688..72ac24d8a 100644 --- a/sources/qetdiagrameditor.h +++ b/sources/qetdiagrameditor.h @@ -54,6 +54,8 @@ class KAutoSaveFile; class QETDiagramEditor : public QETMainWindow { Q_OBJECT + + friend class TerminalStripEditorWindow; public: QETDiagramEditor( From 74b55f3bf50571f69992eff5e490e9eb46080710 Mon Sep 17 00:00:00 2001 From: joshua Date: Thu, 24 Jul 2025 22:24:15 +0200 Subject: [PATCH 12/15] Disable deletion if a terminal can't be deleted. In case of user try to delete a terminal element who is bridged or belong to a physical terminal with more than one level, the deletion is aborted to avoid mistake in the terminal strip parent of the terminal element. A dialog is opened when the deletion can't be to explain to user what to do for enable the deletion. --- sources/diagramcontent.cpp | 10 +++++- sources/diagramcontent.h | 3 ++ sources/qetdiagrameditor.cpp | 21 ++++++++---- .../deleteqgraphicsitemcommand.cpp | 32 +++++++++++++++++++ .../undocommand/deleteqgraphicsitemcommand.h | 2 +- 5 files changed, 60 insertions(+), 8 deletions(-) diff --git a/sources/diagramcontent.cpp b/sources/diagramcontent.cpp index 398013c83..3ea10715a 100644 --- a/sources/diagramcontent.cpp +++ b/sources/diagramcontent.cpp @@ -59,7 +59,15 @@ DiagramContent::DiagramContent(Diagram *diagram, bool selected) : { switch (item->type()) { - case Element::Type: { m_elements << qgraphicsitem_cast(item); break;} + case Element::Type: + { + auto element = qgraphicsitem_cast(item); + m_elements << element; + if (element->elementData().m_type == ElementData::Terminale) { + m_terminal_elements << static_cast(element); + } + break; + } case IndependentTextItem::Type: { m_text_fields << qgraphicsitem_cast(item); break;} case Conductor::Type: { diff --git a/sources/diagramcontent.h b/sources/diagramcontent.h index 1525fbedc..1eff2ed55 100644 --- a/sources/diagramcontent.h +++ b/sources/diagramcontent.h @@ -21,6 +21,8 @@ #include #include +#include "../qetgraphicsitem/terminalelement.h" + class QGraphicsItem; class Conductor; class Element; @@ -81,6 +83,7 @@ class DiagramContent QList m_selected_items; QVector m_tables; QVector m_terminal_strip; + QVector> m_terminal_elements; QList selectedTexts() const; diff --git a/sources/qetdiagrameditor.cpp b/sources/qetdiagrameditor.cpp index 5e7c3982a..c94e92c91 100644 --- a/sources/qetdiagrameditor.cpp +++ b/sources/qetdiagrameditor.cpp @@ -1468,12 +1468,21 @@ void QETDiagramEditor::selectionGroupTriggered(QAction *action) if (!dv || value.isEmpty()) return; - if (value == "delete_selection") - { - diagram->clearSelection(); - diagram->undoStack().push(new DeleteQGraphicsItemCommand(diagram, dc)); - dv->adjustSceneRect(); - } + if (value == "delete_selection") + { + if (DeleteQGraphicsItemCommand::hasNonDeletableTerminal(dc)) { + QET::QetMessageBox::information(this, + tr("Suppression de borne impossible"), + tr("La suppression ne peut être effectué car la selection " + "possède une ou plusieurs bornes ponté et/ou appartenant à une borne à niveau multiple.\n" + "Déponter et/ou supprimer les niveaux des bornes concerné " + "afin de pouvoir les supprimer")); + } else { + diagram->clearSelection(); + diagram->undoStack().push(new DeleteQGraphicsItemCommand(diagram, dc)); + dv->adjustSceneRect(); + } + } else if (value == "rotate_selection") { RotateSelectionCommand *c = new RotateSelectionCommand(diagram); diff --git a/sources/undocommand/deleteqgraphicsitemcommand.cpp b/sources/undocommand/deleteqgraphicsitemcommand.cpp index 24e407b17..074a04607 100644 --- a/sources/undocommand/deleteqgraphicsitemcommand.cpp +++ b/sources/undocommand/deleteqgraphicsitemcommand.cpp @@ -28,6 +28,8 @@ #include "../qetgraphicsitem/elementtextitemgroup.h" #include "../qetgraphicsitem/terminal.h" #include "addelementtextcommand.h" +#include "../TerminalStrip/realterminal.h" +#include "../TerminalStrip/physicalterminal.h" /** @brief DeleteQGraphicsItemCommand::DeleteQGraphicsItemCommand @@ -115,6 +117,36 @@ DeleteQGraphicsItemCommand::~DeleteQGraphicsItemCommand() m_diagram->qgiManager().release(m_removed_contents.items(DiagramContent::All)); } +/** + * @brief DeleteQGraphicsItemCommand::hasNonDeletableTerminal + * Return true if @content have terminal element which can't be deleted. + * The reason why a terminal can't be deleted is because they have bridge + * or belong to a physical terminal with more than one level. + * @param diagram + * @param content + * @param dialog + * @return + */ +bool DeleteQGraphicsItemCommand::hasNonDeletableTerminal(const DiagramContent &content) +{ + if (!content.m_terminal_elements.isEmpty()) + { + for (const auto &terminal : content.m_terminal_elements) + { + if (!terminal.isNull()) + { + if (terminal->parentTerminalStrip() + && (terminal->realTerminal()->isBridged() + || terminal->realTerminal()->physicalTerminal()->levelCount() != 1)) { + return true; + } + } + } + } + + return false; +} + /** @brief DeleteQGraphicsItemCommand::setPotentialsOfRemovedElements This function creates new conductors (if needed) for conserve the electrical potentials diff --git a/sources/undocommand/deleteqgraphicsitemcommand.h b/sources/undocommand/deleteqgraphicsitemcommand.h index 370d1565c..53bb4d091 100644 --- a/sources/undocommand/deleteqgraphicsitemcommand.h +++ b/sources/undocommand/deleteqgraphicsitemcommand.h @@ -34,10 +34,10 @@ class DeleteQGraphicsItemCommand : public QUndoCommand public: DeleteQGraphicsItemCommand(Diagram *diagram, const DiagramContent &content, QUndoCommand * parent = nullptr); ~DeleteQGraphicsItemCommand() override; + static bool hasNonDeletableTerminal(const DiagramContent &content); private: DeleteQGraphicsItemCommand(const DeleteQGraphicsItemCommand &); - void setPotentialsOfRemovedElements(); Terminal *terminalInSamePotential(Terminal *terminal, Conductor *conductor_to_exclude); From f6ba47277dd5f5e42c5aaa11276e06cf671ff504 Mon Sep 17 00:00:00 2001 From: joshua Date: Thu, 2 Oct 2025 21:52:40 +0200 Subject: [PATCH 13/15] Minor : revamp Use QGIUtility::drawBoundingRectSelection for draw the selection rect of element instead of a method of the element itself. Less code. --- sources/qetgraphicsitem/element.cpp | 31 ++--------------------------- sources/qetgraphicsitem/element.h | 3 --- 2 files changed, 2 insertions(+), 32 deletions(-) diff --git a/sources/qetgraphicsitem/element.cpp b/sources/qetgraphicsitem/element.cpp index 5f5315444..0817155ec 100644 --- a/sources/qetgraphicsitem/element.cpp +++ b/sources/qetgraphicsitem/element.cpp @@ -34,6 +34,7 @@ #include "elementtextitemgroup.h" #include "iostream" #include "../qetxml.h" +#include "qgraphicsitemutility.h" #include #include @@ -242,7 +243,7 @@ void Element::paint( //Draw the selection rectangle if ( isSelected() || m_mouse_over ) { - drawSelection(painter, options); + QGIUtility::drawBoundingRectSelection(this, painter); } } @@ -340,34 +341,6 @@ void Element::drawAxes( /*** Methodes privees ***/ -/** - Dessine le cadre de selection de l'element de maniere systematiquement non antialiasee. - @param painter Le QPainter a utiliser pour dessiner les bornes. - @param options Les options de style a prendre en compte -*/ -void Element::drawSelection( - QPainter *painter, - const QStyleOptionGraphicsItem *options) -{ - Q_UNUSED(options) - painter -> save(); - // Annulation des renderhints - painter -> setRenderHint(QPainter::Antialiasing, false); - painter -> setRenderHint(QPainter::TextAntialiasing, false); - painter -> setRenderHint(QPainter::SmoothPixmapTransform, false); - // Dessin du cadre de selection en gris - QPen t; - t.setColor(Qt::gray); - t.setStyle(Qt::DashDotLine); - t.setCosmetic(true); - painter -> setPen(t); - // Le dessin se fait a partir du rectangle delimitant - painter -> drawRoundedRect(boundingRect().adjusted(1, 1, -1, -1), - 10, - 10); - painter -> restore(); -} - /** Dessine le cadre de selection de l'element de maniere systematiquement non antialiasee. @param painter Le QPainter a utiliser pour dessiner les bornes. diff --git a/sources/qetgraphicsitem/element.h b/sources/qetgraphicsitem/element.h index 96ba46205..0565ffc01 100644 --- a/sources/qetgraphicsitem/element.h +++ b/sources/qetgraphicsitem/element.h @@ -197,9 +197,6 @@ class Element : public QetGraphicsItem void setSize(int, int); private: - void drawSelection( - QPainter *, - const QStyleOptionGraphicsItem *); void drawHighlight( QPainter *, const QStyleOptionGraphicsItem *); From f0ec416a91233193f3e2f6582c5c0ad869f855de Mon Sep 17 00:00:00 2001 From: joshua Date: Fri, 3 Oct 2025 21:49:21 +0200 Subject: [PATCH 14/15] Terminal strip graphic item can display Xref of terminal --- .../GraphicsItem/demoterminalstrip.cpp | 110 ++++---- .../properties/terminalstriplayoutpattern.cpp | 27 +- .../properties/terminalstriplayoutpattern.h | 16 +- .../GraphicsItem/terminalstripdrawer.cpp | 32 ++- .../GraphicsItem/terminalstripdrawer.h | 1 + .../GraphicsItem/trueterminalstrip.cpp | 10 + .../GraphicsItem/trueterminalstrip.h | 1 + .../ui/terminalstriplayouteditor.cpp | 41 +++ .../ui/terminalstriplayouteditor.ui | 244 ++++++++++++++---- sources/xml/terminalstriplayoutpatternxml.cpp | 15 ++ 10 files changed, 390 insertions(+), 107 deletions(-) diff --git a/sources/TerminalStrip/GraphicsItem/demoterminalstrip.cpp b/sources/TerminalStrip/GraphicsItem/demoterminalstrip.cpp index bea467656..91edb3092 100644 --- a/sources/TerminalStrip/GraphicsItem/demoterminalstrip.cpp +++ b/sources/TerminalStrip/GraphicsItem/demoterminalstrip.cpp @@ -38,9 +38,10 @@ namespace TerminalStripDrawer class DemoRealTerminal : public AbstractRealTerminalInterface { public: - DemoRealTerminal(const QString &label, const QUuid &bridge) : - m_label { label }, - m_bridge { bridge } + DemoRealTerminal(const QString &label, const QString &xref, const QUuid &bridge) : + m_label { label }, + m_xref{ xref }, + m_bridge { bridge } {} QString label() const override { @@ -55,8 +56,12 @@ namespace TerminalStripDrawer return new DemoBridge { m_bridge }; } + QString xref() const override { + return m_xref; + } + private: - QString m_label; + QString m_label, m_xref; QUuid m_bridge; }; @@ -101,52 +106,65 @@ namespace TerminalStripDrawer QVector > real_terminals_vector; - real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("24vdc"), - lvl_1)}; - real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("0vdc"), - lvl_2)}; - real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("signal"), - lvl_3)}; - real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("teach"), - lvl_4)}; - m_physical_terminal << QSharedPointer { - new DemoPhysicalTerminal {real_terminals_vector}}; + real_terminals_vector << QSharedPointer { + new DemoRealTerminal( QStringLiteral("24vdc"), + QStringLiteral("1_A1"), + lvl_1)}; + real_terminals_vector << QSharedPointer { + new DemoRealTerminal( QStringLiteral("0vdc"), + QStringLiteral("1_A2"), + lvl_2)}; + real_terminals_vector << QSharedPointer { + new DemoRealTerminal( QStringLiteral("signal"), + QStringLiteral("1_A3"), + lvl_3)}; + real_terminals_vector << QSharedPointer { + new DemoRealTerminal( QStringLiteral("teach"), + QStringLiteral("1_A4"), + lvl_4)}; + m_physical_terminal << QSharedPointer { + new DemoPhysicalTerminal {real_terminals_vector}}; real_terminals_vector.clear(); - real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("24vdc"), - lvl_1)}; - real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("0vdc"), - lvl_2)}; - real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("signal"), - lvl_3)}; - real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("teach"), - lvl_4)}; - m_physical_terminal << QSharedPointer { - new DemoPhysicalTerminal {real_terminals_vector}}; + real_terminals_vector << QSharedPointer { + new DemoRealTerminal( QStringLiteral("24vdc"), + QStringLiteral("2_A1"), + lvl_1)}; + real_terminals_vector << QSharedPointer { + new DemoRealTerminal( QStringLiteral("0vdc"), + QStringLiteral("2_A2"), + lvl_2)}; + real_terminals_vector << QSharedPointer { + new DemoRealTerminal( QStringLiteral("signal"), + QStringLiteral("2_A3"), + lvl_3)}; + real_terminals_vector << QSharedPointer { + new DemoRealTerminal( QStringLiteral("teach"), + QStringLiteral("2_A4"), + lvl_4)}; + m_physical_terminal << QSharedPointer { + new DemoPhysicalTerminal {real_terminals_vector}}; + real_terminals_vector.clear(); - real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("24vdc"), - lvl_1)}; - real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("0vdc"), - lvl_2)}; - real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("signal"), - lvl_3)}; - real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("teach"), - lvl_4)}; - m_physical_terminal << QSharedPointer { - new DemoPhysicalTerminal {real_terminals_vector}}; + real_terminals_vector << QSharedPointer { + new DemoRealTerminal( QStringLiteral("24vdc"), + QStringLiteral("3_A1"), + lvl_1)}; + real_terminals_vector << QSharedPointer { + new DemoRealTerminal( QStringLiteral("0vdc"), + QStringLiteral("3_A2"), + lvl_2)}; + real_terminals_vector << QSharedPointer { + new DemoRealTerminal( QStringLiteral("signal"), + QStringLiteral("3_A3"), + lvl_3)}; + real_terminals_vector << QSharedPointer { + new DemoRealTerminal( QStringLiteral("teach"), + QStringLiteral("3_A4"), + lvl_4)}; + m_physical_terminal << QSharedPointer { + new DemoPhysicalTerminal {real_terminals_vector}}; } } diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp index 84baeb591..82fba3498 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp @@ -17,7 +17,6 @@ */ #include "terminalstriplayoutpattern.h" #include "../../../utils/qetutils.h" -#include TerminalStripLayoutPattern::TerminalStripLayoutPattern() { @@ -80,6 +79,29 @@ QTextOption TerminalStripLayoutPattern::terminalsTextOption() const return m_terminals_text_option; } +/** + * @brief TerminalStripLayoutPattern::setXrefTextAlignment + * Set text alignment to @param alignment. If alignment have no + * flag this function do nothing + * @param alignment + */ +void TerminalStripLayoutPattern::setXrefTextAlignment(const Qt::Alignment &alignment) +{ + if (!alignment) return; + m_xref_text_alignment = alignment; + updateTerminalsTextOption(); +} + +Qt::Alignment TerminalStripLayoutPattern::xrefTextAlignment() const +{ + return m_xref_text_alignment; +} + +QTextOption TerminalStripLayoutPattern::xrefTextOption() const +{ + return m_xref_text_option; +} + void TerminalStripLayoutPattern::updateHeaderTextOption() { m_header_text_option.setAlignment(m_header_text_alignment); @@ -90,4 +112,7 @@ void TerminalStripLayoutPattern::updateTerminalsTextOption() { m_terminals_text_option.setAlignment(m_terminals_text_alignment); m_terminals_text_option.setWrapMode(QTextOption::WordWrap); + + m_xref_text_option.setAlignment(m_xref_text_alignment); + m_xref_text_option.setWrapMode(QTextOption::WordWrap); } diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h index 1b5f0c40a..6dbc0da82 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h @@ -74,6 +74,14 @@ class TerminalStripLayoutPattern qreal m_terminals_text_y{35}; Qt::Orientation m_terminals_text_orientation {Qt::Vertical}; + //Xref text + void setXrefTextAlignment(const Qt::Alignment &alignment); + Qt::Alignment xrefTextAlignment() const; + QTextOption xrefTextOption() const; + qreal m_xref_text_height{60}; + qreal m_xref_text_y{95}; + Qt::Orientation m_xref_text_orientation {Qt::Vertical}; + qreal m_bridge_point_d{5}; QVector m_bridge_point_y_offset{50,70,90,110}; @@ -89,8 +97,12 @@ class TerminalStripLayoutPattern Qt::Alignment m_header_text_alignment{Qt::AlignCenter}; QTextOption m_header_text_option; - Qt::Alignment m_terminals_text_alignment {Qt::AlignRight | Qt::AlignVCenter}; - QTextOption m_terminals_text_option{QTextOption()}; + Qt::Alignment + m_terminals_text_alignment {Qt::AlignRight | Qt::AlignVCenter}, + m_xref_text_alignment {Qt::AlignLeft | Qt::AlignVCenter}; + QTextOption + m_terminals_text_option{QTextOption()}, + m_xref_text_option{QTextOption()}; }; #endif // TERMINALSTRIPLAYOUTPATTERN_H diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp index 4b94b9284..f71542c3d 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp @@ -16,6 +16,7 @@ along with QElectroTech. If not, see . */ #include "terminalstripdrawer.h" + #include namespace TerminalStripDrawer { @@ -111,6 +112,12 @@ void TerminalStripDrawer::paint(QPainter *painter) const auto terminals_text_y{m_pattern->m_terminals_text_y}; QRectF terminal_rect; + const auto xref_text_orientation{m_pattern->m_xref_text_orientation}; + const auto xref_text_option{m_pattern->xrefTextOption()}; + const auto xref_text_height{m_pattern->m_xref_text_height}; + const auto xref_text_y{m_pattern->m_xref_text_y}; + QRectF xref_rect; + QHash> bridges_anchor_points; //Loop over physical terminals @@ -170,9 +177,9 @@ void TerminalStripDrawer::paint(QPainter *painter) } const auto shared_real_terminal{real_terminal_vector[i]}; - painter->drawText(text_rect, - shared_real_terminal ? shared_real_terminal->label() : QLatin1String(), - terminals_text_option); + painter->drawText(text_rect, + shared_real_terminal ? shared_real_terminal->label() : QLatin1String(), + terminals_text_option); if (m_preview_draw) { @@ -182,6 +189,25 @@ void TerminalStripDrawer::paint(QPainter *painter) painter->restore(); + //Draw xref + auto xref_string = shared_real_terminal->xref(); + painter->save(); + xref_rect.setRect(0, xref_text_y, terminal_rect.width(), xref_text_height); + if (xref_text_orientation == Qt::Vertical) + { + painter->translate(xref_rect.bottomLeft()); + painter->rotate(270); + xref_rect.setRect(0, 0, xref_rect.height(), xref_rect.width()); + } + painter->drawText(xref_rect, xref_string, xref_text_option); + + if (m_preview_draw) + { + painter->setPen(Qt::blue); + painter->drawRect(xref_rect); + } + painter->restore(); + //Add bridge anchor if (shared_real_terminal->isBridged()) { diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h index 72286c41d..8fa5fd8e1 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h @@ -43,6 +43,7 @@ namespace TerminalStripDrawer virtual QString label() const = 0; virtual bool isBridged() const = 0; virtual AbstractBridgeInterface* bridge() const = 0; + virtual QString xref() const = 0; }; class AbstractPhysicalTerminalInterface diff --git a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp index 15273e4c1..29e1ad0ef 100644 --- a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp +++ b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp @@ -20,6 +20,7 @@ #include "../realterminal.h" #include "../terminalstrip.h" #include "../terminalstripbridge.h" +#include "../../autoNum/assignvariables.h" #include "terminalstripdrawer.h" @@ -118,6 +119,15 @@ namespace TerminalStripDrawer return new TrueBridge(m_real->bridge()); } + QString TrueRealTerminal::xref() const + { + if (m_real && m_real->isElement()) { + return autonum::AssignVariables::genericXref(m_real->element()); + } else { + return QString{}; + } + } + TrueBridge::TrueBridge(QSharedPointer bridge) : m_bridge { bridge } {} diff --git a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h index 10b3775fa..d94827553 100644 --- a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h +++ b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h @@ -58,6 +58,7 @@ namespace TerminalStripDrawer QString label() const override; bool isBridged() const override; AbstractBridgeInterface* bridge() const override; + QString xref() const override; private: QSharedPointer m_real; diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp b/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp index b54164f94..85744e00e 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp @@ -108,6 +108,7 @@ void TerminalStripLayoutEditor::valueEdited() m_layout.data()->setHeaderTextAlignment(Qt::AlignRight | Qt::AlignVCenter); break; } + //Terminal text m_layout.data()->m_terminals_text_orientation = ui->m_terminal_text_orientation_cb->currentIndex() == 0 ? Qt::Horizontal : Qt::Vertical; @@ -127,6 +128,26 @@ void TerminalStripLayoutEditor::valueEdited() m_layout.data()->m_terminals_text_y = ui->m_terminal_text_y_sb->value(); m_layout.data()->m_terminals_text_height = ui->m_terminal_text_height_sb->value(); + //Xref text + m_layout.data()->m_xref_text_orientation = ui->m_xref_orientation_cb->currentIndex() == 0 ? + Qt::Horizontal : + Qt::Vertical; + + switch (ui->m_xref_alignment_cb->currentIndex()) { + case 0: + m_layout.data()->setXrefTextAlignment(Qt::Alignment {Qt::AlignLeft | Qt::AlignVCenter}); + break; + case 1: + m_layout.data()->setXrefTextAlignment(Qt::Alignment { Qt::AlignHCenter | Qt::AlignVCenter}); + break; + default: + m_layout.data()->setXrefTextAlignment(Qt::Alignment { Qt::AlignRight | Qt::AlignVCenter}); + break; + } + + m_layout.data()->m_xref_text_y = ui->m_xref_y_sb->value(); + m_layout.data()->m_xref_text_height = ui->m_xref_height_sb->value(); + updateUi(); m_preview_strip_item.update(); } @@ -200,6 +221,7 @@ void TerminalStripLayoutEditor::updateUi() ui->m_header_text_alignment_cb->setCurrentIndex(2); } + //Terminal text const auto terminal_alignment = data->terminalsTextAlignment(); if (terminal_alignment &Qt::AlignLeft) { ui->m_terminal_text_alignment_cb->setCurrentIndex(0); @@ -212,6 +234,25 @@ void TerminalStripLayoutEditor::updateUi() ui->m_terminal_text_y_sb->setValue(data->m_terminals_text_y); ui->m_terminal_text_height_sb->setValue(data->m_terminals_text_height); + //Xref text + if (data->m_xref_text_orientation == Qt::Horizontal) { + ui->m_xref_orientation_cb->setCurrentIndex(0); + } else { + ui->m_xref_orientation_cb->setCurrentIndex(1); + } + + const auto xref_alignment = data->xrefTextAlignment(); + if (xref_alignment &Qt::AlignLeft) { + ui->m_xref_alignment_cb->setCurrentIndex(0); + } else if (xref_alignment &Qt::AlignHCenter) { + ui->m_xref_alignment_cb->setCurrentIndex(1); + } else if (xref_alignment &Qt::AlignRight) { + ui->m_xref_alignment_cb->setCurrentIndex(2); + } + + ui->m_xref_y_sb->setValue(data->m_xref_text_y); + ui->m_xref_height_sb->setValue(data->m_xref_text_height); + m_ui_updating = false; updatePreview(); } diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.ui b/sources/TerminalStrip/ui/terminalstriplayouteditor.ui index f8f74789a..c9a762252 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.ui +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.ui @@ -6,8 +6,8 @@ 0 0 - 683 - 589 + 961 + 624 @@ -15,7 +15,7 @@ - QLayout::SizeConstraint::SetMaximumSize + QLayout::SetMaximumSize @@ -34,7 +34,7 @@ - Qt::Orientation::Horizontal + Qt::Horizontal @@ -173,7 +173,7 @@ - Qt::Orientation::Horizontal + Qt::Horizontal @@ -213,13 +213,6 @@ 0 - - - - Longueur maximal du texte de borne - - - @@ -253,38 +246,17 @@ - - - - - Horizontal - - - - - Vertical - - - - - Orientation du texte d'en tête : + Orientation - Alignement du texte d'en tête : - - - - - - - Origine vertical du texte de borne : + Alignement @@ -330,7 +302,7 @@ - Qt::Orientation::Horizontal + Qt::Horizontal @@ -343,7 +315,48 @@ - + + + + Texte d'en tête + + + Qt::AlignCenter + + + + + + + Origine vertical + + + + + + + Longueur maximal + + + + + + + 1000 + + + + + + + 30 + + + 1000 + + + + @@ -362,30 +375,87 @@ - - - - 30 + + + + + Horizontal + + + + + Vertical + + + + + + + + Texte borne + + Qt::AlignCenter + + + + + + + Référence croisée + + + Qt::AlignCenter + + + + + + + + Horizontal + + + + + Vertical + + + + + + + + + Gauche + + + + + Centre + + + + + Droite + + + + + + 1000 - - - - Orientation du texte de borne : + + + + 30 - - - - - - - - - Alignement du texte de borne : + + 1000 @@ -430,7 +500,7 @@ - Qt::Orientation::Horizontal + Qt::Horizontal @@ -960,6 +1030,70 @@ + + m_xref_alignment_cb + currentIndexChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 836 + 365 + + + 480 + 311 + + + + + m_xref_height_sb + valueChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 836 + 431 + + + 480 + 311 + + + + + m_xref_orientation_cb + currentIndexChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 836 + 333 + + + 480 + 311 + + + + + m_xref_y_sb + valueChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 836 + 398 + + + 480 + 311 + + + valueEdited() diff --git a/sources/xml/terminalstriplayoutpatternxml.cpp b/sources/xml/terminalstriplayoutpatternxml.cpp index 5ea20a1cb..687dd5b53 100644 --- a/sources/xml/terminalstriplayoutpatternxml.cpp +++ b/sources/xml/terminalstriplayoutpatternxml.cpp @@ -117,6 +117,13 @@ QDomElement TerminalStripLayoutPatternXml::toXml(const QSharedPointerm_terminals_text_height, terminals_text_xml); terminals_xml.appendChild(terminals_text_xml); + auto xref_text_xml = document.createElement(QStringLiteral("xref")); + QETXML::orientationToAttribute(pattern->m_xref_text_orientation, xref_text_xml); + QETXML::alignmentToAttribute(pattern->xrefTextAlignment(),xref_text_xml); + QETSVG::yToAttribute(pattern->m_xref_text_y, xref_text_xml); + QETSVG::heightToAttribute(pattern->m_xref_text_height, xref_text_xml); + terminals_xml.appendChild(xref_text_xml); + auto bridge_xml = document.createElement(QStringLiteral("bridges")); QETSVG::rToAttribute(pattern->m_bridge_point_d/2, bridge_xml); QVector points_vector; @@ -176,6 +183,14 @@ void TerminalStripLayoutPatternXml::fromXml(QSharedPointerm_terminals_text_height = QETSVG::heightFromAttribute(terminals_text_xml); } + if (const auto xref_text_xml = terminals_xml.firstChildElement(QStringLiteral("xref")); + !xref_text_xml.isNull()) { + layout->m_xref_text_orientation = QETXML::orientationFromAttribute(xref_text_xml, layout->m_xref_text_orientation); + layout->setXrefTextAlignment(QETXML::alignmentFromAttribute(xref_text_xml)); + layout->m_xref_text_y = QETSVG::yFromAttribute(xref_text_xml); + layout->m_xref_text_height = QETSVG::heightFromAttribute(xref_text_xml); + } + if (const auto bridge_xml = terminals_xml.firstChildElement(QStringLiteral("bridges")); !bridge_xml.isNull()) { layout->m_bridge_point_d = QETSVG::rFromAttribute(bridge_xml, 2.5)*2; From 7e5d41b4743f24d20a13287f2da892fe0b475f4e Mon Sep 17 00:00:00 2001 From: joshua Date: Tue, 14 Oct 2025 22:12:38 +0200 Subject: [PATCH 15/15] Terminal strip Xref is clickable When user hover the Xref string of a terminal, the string color change to blue to advise user the xref is clickable. Double click on the blue Xref go the folio of the terminal and zoom the view to the terminal. --- .../GraphicsItem/terminalstripdrawer.cpp | 71 +++++++++++++++++-- .../GraphicsItem/terminalstripdrawer.h | 20 ++++++ .../GraphicsItem/terminalstripitem.cpp | 48 ++++++++++++- .../GraphicsItem/terminalstripitem.h | 3 +- sources/TerminalStrip/physicalterminal.cpp | 14 ++++ sources/TerminalStrip/physicalterminal.h | 1 + sources/qetgraphicsitem/qetgraphicsitem.cpp | 32 ++++++++- sources/qetgraphicsitem/qetgraphicsitem.h | 6 ++ 8 files changed, 186 insertions(+), 9 deletions(-) diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp index f71542c3d..f805ef7c1 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp @@ -45,6 +45,7 @@ void TerminalStripDrawer::paint(QPainter *painter) { if (m_strip && m_pattern) { + m_united_xref_text_rect = QRectF(); //To draw text, QPainter need a Qrect. Instead of create an instance //for each text, we re-use the same instance of QRect. QRect text_rect; @@ -91,11 +92,10 @@ void TerminalStripDrawer::paint(QPainter *painter) const auto text_{m_strip->installation() + " " + m_strip->location() + " " + m_strip->name()}; painter->drawText(text_rect, text_, m_pattern->headerTextOption()); - painter->restore(); + painter->restore(); //Move painter pos to next drawing painter->translate(m_pattern->m_header_rect.width(),0); - qreal x_offset{m_pattern->m_header_rect.width()}; //Draw spacer @@ -120,6 +120,8 @@ void TerminalStripDrawer::paint(QPainter *painter) QHash> bridges_anchor_points; + m_hovered_xref = hoverTerminal{}; + int physical_index = 0; //Loop over physical terminals for (const auto &physical_t : m_strip->physicalTerminal()) { @@ -190,15 +192,40 @@ void TerminalStripDrawer::paint(QPainter *painter) painter->restore(); //Draw xref - auto xref_string = shared_real_terminal->xref(); - painter->save(); xref_rect.setRect(0, xref_text_y, terminal_rect.width(), xref_text_height); + painter->save(); if (xref_text_orientation == Qt::Vertical) { painter->translate(xref_rect.bottomLeft()); painter->rotate(270); xref_rect.setRect(0, 0, xref_rect.height(), xref_rect.width()); } + + QTransform transform; + transform.translate(x_offset, 0); + + if (xref_text_orientation == Qt::Vertical) + { + transform.translate(0, xref_text_y + xref_text_height); + transform.rotate(270); + } + + auto xref_string = shared_real_terminal->xref(); + + const auto mapped_xref_text_rect = transform.mapRect(painter->boundingRect(xref_rect, xref_string, xref_text_option)); + if (m_united_xref_text_rect.isNull()) { + m_united_xref_text_rect = mapped_xref_text_rect; + } else { + m_united_xref_text_rect = m_united_xref_text_rect.united(mapped_xref_text_rect); + } + + //if mouse hover the xref text, draw it in blue to advise user the xref is clickable. + if (!m_mouse_hover_pos.isNull() && mapped_xref_text_rect.contains(m_mouse_hover_pos)) { + painter->setPen(Qt::blue); + m_hovered_xref.physical = physical_index; + m_hovered_xref.real = i; + } + painter->drawText(xref_rect, xref_string, xref_text_option); if (m_preview_draw) @@ -234,6 +261,7 @@ void TerminalStripDrawer::paint(QPainter *painter) painter->translate(terminal_rect.width(),0); x_offset += terminal_rect.width(); } + physical_index++; } painter->restore(); @@ -269,6 +297,41 @@ void TerminalStripDrawer::setPreviewDraw(bool draw) { m_preview_draw = draw; } +void TerminalStripDrawer::setMouseHoverPos(const QPointF &pos) +{ + m_last_mouse_pos_in_xrefs_rect = m_united_xref_text_rect.contains(m_mouse_hover_pos); + m_mouse_hover_pos = pos; +} + +/** + * @brief TerminalStripDrawer::mouseHoverXref + * @return True if the mouse position (given through the function setMouseHoverPos) + * hover the rect of a xref. + */ +bool TerminalStripDrawer::mouseHoverXref() const { + return m_united_xref_text_rect.contains(m_mouse_hover_pos); +} + +bool TerminalStripDrawer::needUpdate() +{ + if (mouseHoverXref()) { + return true; + } else if (m_last_mouse_pos_in_xrefs_rect) { + return true; + } + return false; +} + +/** + * @brief TerminalStripDrawer::hoveredXref + * @return the current terminal hovered by the mouse + * in the xref bounding rectangle + */ +hoverTerminal TerminalStripDrawer::hoveredXref() const +{ + return m_hovered_xref; +} + qreal TerminalStripDrawer::height() const { if (m_pattern) diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h index 8fa5fd8e1..363bc2cdf 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h @@ -27,6 +27,17 @@ class TerminalStrip; namespace TerminalStripDrawer { + /** + * @brief The hoverTerminal struct + * Just a little struct use to know what is the physical and real terminal + * when the mouse hover the Xref string of a terminal. + * If mouse don't hover a Xref the value is set to -1; + */ + struct hoverTerminal{ + int physical{-1}; + int real{-1}; + }; + class AbstractBridgeInterface { public: @@ -80,6 +91,11 @@ namespace TerminalStripDrawer void setPreviewDraw(bool draw = true); + void setMouseHoverPos(const QPointF &pos); + bool mouseHoverXref() const; + bool needUpdate(); + hoverTerminal hoveredXref() const; + private: qreal height() const; qreal width() const; @@ -88,6 +104,10 @@ namespace TerminalStripDrawer QSharedPointer m_strip; QSharedPointer m_pattern; bool m_preview_draw { false }; + QPointF m_mouse_hover_pos; + QRectF m_united_xref_text_rect; + bool m_last_mouse_pos_in_xrefs_rect{false}; + hoverTerminal m_hovered_xref; }; } diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp index 77f28adee..ad9634b4d 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp @@ -22,6 +22,8 @@ #include "../../project/projectpropertieshandler.h" #include "../../qetgraphicsitem/qgraphicsitemutility.h" #include "../terminalstrip.h" +#include "../physicalterminal.h" +#include "../realterminal.h" #include "../ui/terminalstripeditorwindow.h" #include "trueterminalstrip.h" @@ -94,13 +96,53 @@ QString TerminalStripItem::name() const { return tr("plan de bornes"); } +void TerminalStripItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + QetGraphicsItem::hoverMoveEvent(event); + m_drawer.setMouseHoverPos(hoverMousePos()); + if (m_drawer.needUpdate()) { + update(); + } +} + +void TerminalStripItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + QetGraphicsItem::hoverLeaveEvent(event); + m_drawer.setMouseHoverPos(QPointF{}); +} + void TerminalStripItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { Q_UNUSED (event); - if (m_strip) { - TerminalStripEditorWindow::edit(m_strip); - } + const auto hovered = m_drawer.hoveredXref(); + + if (m_strip) { + if (hovered.physical >= 0 && + hovered.real >= 0) + { + if (const auto physical_terminal = m_strip->physicalTerminal(hovered.physical); + !physical_terminal.isNull()) + { + if (const auto real_terminal = physical_terminal->realTerminal(hovered.real); + !real_terminal.isNull() && + real_terminal->isElement()) + { + if (QPointer element = real_terminal->element(); + !element.isNull()) + { + //Unselect and ungrab mouse to prevent unwanted + //move when element is in the same scene of this. + setSelected(false); + ungrabMouse(); + QetGraphicsItem::showItem(element); + } + } + } + } else { + TerminalStripEditorWindow::edit(m_strip); + } + } } void TerminalStripItem::refreshPending() diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripitem.h b/sources/TerminalStrip/GraphicsItem/terminalstripitem.h index b26a6dd8b..f69e8595b 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripitem.h +++ b/sources/TerminalStrip/GraphicsItem/terminalstripitem.h @@ -46,6 +46,8 @@ class TerminalStripItem : public QetGraphicsItem QRectF boundingRect() const override; QString name() const override; + void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override; + void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override; void refreshPending(); void setLayout(QSharedPointer layout); @@ -57,7 +59,6 @@ class TerminalStripItem : public QetGraphicsItem QPointer m_strip; TerminalStripDrawer::TerminalStripDrawer m_drawer; QUuid m_pending_strip_uuid; - }; #endif // TERMINALSTRIPITEM_H diff --git a/sources/TerminalStrip/physicalterminal.cpp b/sources/TerminalStrip/physicalterminal.cpp index 99165a20f..86eefb945 100644 --- a/sources/TerminalStrip/physicalterminal.cpp +++ b/sources/TerminalStrip/physicalterminal.cpp @@ -189,6 +189,20 @@ QVector> PhysicalTerminal::realTerminals() const { return m_real_terminal; } +/** + * @brief PhysicalTerminal::realTerminal + * @param pos + * @return the real terminal at position pos. + * Note that the returned QSharedPointer can be null + */ +QSharedPointer PhysicalTerminal::realTerminal(int pos) const +{ + if (pos < m_real_terminal.size()) { + return m_real_terminal.at(pos); + } + else return QSharedPointer{}; +} + /** * @brief uuid * @return the uuid of this physical terminal diff --git a/sources/TerminalStrip/physicalterminal.h b/sources/TerminalStrip/physicalterminal.h index 7d90ff681..4cb78e059 100644 --- a/sources/TerminalStrip/physicalterminal.h +++ b/sources/TerminalStrip/physicalterminal.h @@ -86,6 +86,7 @@ class PhysicalTerminal int levelCount() const; int levelOf(const QSharedPointer &terminal) const; QVector> realTerminals() const; + QSharedPointer realTerminal(int pos) const; QUuid uuid() const; int pos() const; int realTerminalCount() const; diff --git a/sources/qetgraphicsitem/qetgraphicsitem.cpp b/sources/qetgraphicsitem/qetgraphicsitem.cpp index fc1acc385..873a79fba 100644 --- a/sources/qetgraphicsitem/qetgraphicsitem.cpp +++ b/sources/qetgraphicsitem/qetgraphicsitem.cpp @@ -24,12 +24,31 @@ Default constructor @param parent : Parent Item */ +void QetGraphicsItem::showItem(QetGraphicsItem *item) +{ + if (item && item->diagram()) + { + item->diagram()->showMe(); + item->setSelected(true); + + //Zoom to the item + for(QGraphicsView *view : item->scene()->views()) + { + QRectF fit = item->sceneBoundingRect(); + fit.adjust(-200, -200, 200, 200); + view->fitInView(fit, Qt::KeepAspectRatioByExpanding); + } + } +} + QetGraphicsItem::QetGraphicsItem(QGraphicsItem *parent): QGraphicsObject(parent), is_movable_(true), m_first_move(true), snap_to_grid_(true) -{} +{ + setAcceptHoverEvents(true); +} QetGraphicsItem::~QetGraphicsItem() {} @@ -68,6 +87,11 @@ bool QetGraphicsItem::isHovered() const { return m_hovered; } +QPointF QetGraphicsItem::hoverMousePos() const +{ + return m_mouse_hover_pos; +} + /** @brief QetGraphicsItem::state @return the current state of this item @@ -166,6 +190,12 @@ void QetGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) QGraphicsObject::hoverEnterEvent(event); } +void QetGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + QGraphicsObject::hoverMoveEvent(event); + m_mouse_hover_pos = event->pos(); +} + void QetGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { m_hovered = false; diff --git a/sources/qetgraphicsitem/qetgraphicsitem.h b/sources/qetgraphicsitem/qetgraphicsitem.h index e6459403b..11a967a35 100644 --- a/sources/qetgraphicsitem/qetgraphicsitem.h +++ b/sources/qetgraphicsitem/qetgraphicsitem.h @@ -28,6 +28,9 @@ class QetGraphicsItem : public QGraphicsObject { Q_OBJECT + public : + static void showItem (QetGraphicsItem *item); + public: //constructor destructor QetGraphicsItem(QGraphicsItem *parent = nullptr); @@ -43,6 +46,7 @@ class QetGraphicsItem : public QGraphicsObject virtual void setMovable (bool movable) { is_movable_ = movable;} bool isHovered() const; + QPointF hoverMousePos() const; virtual void editProperty () {} virtual QString name ()const @@ -57,6 +61,7 @@ class QetGraphicsItem : public QGraphicsObject void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; + void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override; void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; protected: @@ -68,6 +73,7 @@ class QetGraphicsItem : public QGraphicsObject private: bool m_hovered{false}; + QPointF m_mouse_hover_pos; };