diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp index 2d672f9c4..e11ede4a3 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp @@ -18,6 +18,8 @@ #include "terminalstriplayoutpattern.h" #include "../../../utils/qetutils.h" +#include + TerminalStripLayoutPattern::TerminalStripLayoutPattern() { m_font.setPixelSize(15); @@ -116,3 +118,176 @@ void TerminalStripLayoutPattern::updateTerminalsTextOption() m_xref_text_option.setAlignment(m_xref_text_alignment); m_xref_text_option.setWrapMode(QTextOption::WordWrap); } + +namespace +{ + void rectToXml(QDomElement &element, const QString &name, const QRectF &rect) + { + element.setAttribute(name + QStringLiteral("_x"), rect.x()); + element.setAttribute(name + QStringLiteral("_y"), rect.y()); + element.setAttribute(name + QStringLiteral("_w"), rect.width()); + element.setAttribute(name + QStringLiteral("_h"), rect.height()); + } + + QRectF rectFromXml(const QDomElement &element, const QString &name, const QRectF &default_rect) + { + auto value = [&element, &name](const QString &suffix, qreal default_value) + { + bool ok = false; + const auto v = element.attribute(name + suffix).toDouble(&ok); + return ok ? v : default_value; + }; + + return QRectF(value(QStringLiteral("_x"), default_rect.x()), + value(QStringLiteral("_y"), default_rect.y()), + value(QStringLiteral("_w"), default_rect.width()), + value(QStringLiteral("_h"), default_rect.height())); + } + + qreal realFromXml(const QDomElement &element, const QString &name, qreal default_value) + { + bool ok = false; + const auto v = element.attribute(name).toDouble(&ok); + return ok ? v : default_value; + } + + QString orientationToString(Qt::Orientation orientation) { + return orientation == Qt::Horizontal ? QStringLiteral("horizontal") : QStringLiteral("vertical"); + } + + Qt::Orientation orientationFromXml(const QDomElement &element, const QString &name, Qt::Orientation default_value) + { + const auto v = element.attribute(name); + if (v == QLatin1String("horizontal")) return Qt::Horizontal; + if (v == QLatin1String("vertical")) return Qt::Vertical; + return default_value; + } + + Qt::Alignment alignmentFromXml(const QDomElement &element, const QString &name, Qt::Alignment default_value) + { + bool ok = false; + const auto v = element.attribute(name).toInt(&ok); + return ok && v ? Qt::Alignment(static_cast(v)) : default_value; + } +} + +/** + * @brief TerminalStripLayoutPattern::xmlTagName + * @return the tag name of the xml element used by toXml / fromXml + */ +QString TerminalStripLayoutPattern::xmlTagName() { + return QStringLiteral("terminal_strip_layout"); +} + +/** + * @brief TerminalStripLayoutPattern::toXml + * Save all the values of this layout, including the font. + * The font is saved by hand (family, pixel size, bold, italic) and not with + * QFont::toString() because the format of this string is different between Qt5 and Qt6. + * @param document + * @return the xml element + */ +QDomElement TerminalStripLayoutPattern::toXml(QDomDocument &document) const +{ + auto element = document.createElement(xmlTagName()); + + rectToXml(element, QStringLiteral("header"), m_header_rect); + element.setAttribute(QStringLiteral("header_text_orientation"), orientationToString(m_header_text_orientation)); + element.setAttribute(QStringLiteral("header_text_alignment"), static_cast(m_header_text_alignment)); + + rectToXml(element, QStringLiteral("spacer"), m_spacer_rect); + + element.setAttribute(QStringLiteral("font_family"), m_font.family()); + element.setAttribute(QStringLiteral("font_pixel_size"), m_font.pixelSize()); + element.setAttribute(QStringLiteral("font_bold"), m_font.bold() ? 1 : 0); + element.setAttribute(QStringLiteral("font_italic"), m_font.italic() ? 1 : 0); + + for (auto i = 0; i < m_terminal_rect.size(); ++i) { + rectToXml(element, QStringLiteral("terminal_%1").arg(i), m_terminal_rect.at(i)); + } + + element.setAttribute(QStringLiteral("terminals_text_height"), m_terminals_text_height); + element.setAttribute(QStringLiteral("terminals_text_y"), m_terminals_text_y); + element.setAttribute(QStringLiteral("terminals_text_orientation"), orientationToString(m_terminals_text_orientation)); + element.setAttribute(QStringLiteral("terminals_text_alignment"), static_cast(m_terminals_text_alignment)); + + element.setAttribute(QStringLiteral("xref_text_height"), m_xref_text_height); + element.setAttribute(QStringLiteral("xref_text_y"), m_xref_text_y); + element.setAttribute(QStringLiteral("xref_text_orientation"), orientationToString(m_xref_text_orientation)); + element.setAttribute(QStringLiteral("xref_text_alignment"), static_cast(m_xref_text_alignment)); + + element.setAttribute(QStringLiteral("type_symbol_y"), m_type_symbol_y); + element.setAttribute(QStringLiteral("type_symbol_height"), m_type_symbol_height); + element.setAttribute(QStringLiteral("connection_length"), m_connection_length); + element.setAttribute(QStringLiteral("cable_wire_length"), m_cable_wire_length); + element.setAttribute(QStringLiteral("cable_length"), m_cable_length); + element.setAttribute(QStringLiteral("cable_end_length"), m_cable_end_length); + + element.setAttribute(QStringLiteral("bridge_point_d"), m_bridge_point_d); + for (auto i = 0; i < m_bridge_point_y_offset.size(); ++i) { + element.setAttribute(QStringLiteral("bridge_point_y_offset_%1").arg(i), m_bridge_point_y_offset.at(i)); + } + + return element; +} + +/** + * @brief TerminalStripLayoutPattern::fromXml + * Load the values saved by toXml. A value missing in @a layout_element + * (project saved with an older version) keep the current value of this layout. + * @param layout_element + */ +void TerminalStripLayoutPattern::fromXml(const QDomElement &layout_element) +{ + if (layout_element.isNull()) { + return; + } + + m_header_rect = rectFromXml(layout_element, QStringLiteral("header"), m_header_rect); + m_header_text_orientation = orientationFromXml(layout_element, QStringLiteral("header_text_orientation"), m_header_text_orientation); + setHeaderTextAlignment(alignmentFromXml(layout_element, QStringLiteral("header_text_alignment"), m_header_text_alignment)); + + m_spacer_rect = rectFromXml(layout_element, QStringLiteral("spacer"), m_spacer_rect); + + auto font_ = m_font; + if (layout_element.hasAttribute(QStringLiteral("font_family"))) { + font_.setFamily(layout_element.attribute(QStringLiteral("font_family"))); + } + const auto pixel_size = layout_element.attribute(QStringLiteral("font_pixel_size")).toInt(); + if (pixel_size > 0) { + font_.setPixelSize(pixel_size); + } + if (layout_element.hasAttribute(QStringLiteral("font_bold"))) { + font_.setBold(layout_element.attribute(QStringLiteral("font_bold")).toInt() != 0); + } + if (layout_element.hasAttribute(QStringLiteral("font_italic"))) { + font_.setItalic(layout_element.attribute(QStringLiteral("font_italic")).toInt() != 0); + } + setFont(font_); + + for (auto i = 0; i < m_terminal_rect.size(); ++i) { + m_terminal_rect[i] = rectFromXml(layout_element, QStringLiteral("terminal_%1").arg(i), m_terminal_rect.at(i)); + } + + m_terminals_text_height = realFromXml(layout_element, QStringLiteral("terminals_text_height"), m_terminals_text_height); + m_terminals_text_y = realFromXml(layout_element, QStringLiteral("terminals_text_y"), m_terminals_text_y); + m_terminals_text_orientation = orientationFromXml(layout_element, QStringLiteral("terminals_text_orientation"), m_terminals_text_orientation); + setTerminalsTextAlignment(alignmentFromXml(layout_element, QStringLiteral("terminals_text_alignment"), m_terminals_text_alignment)); + + m_xref_text_height = realFromXml(layout_element, QStringLiteral("xref_text_height"), m_xref_text_height); + m_xref_text_y = realFromXml(layout_element, QStringLiteral("xref_text_y"), m_xref_text_y); + m_xref_text_orientation = orientationFromXml(layout_element, QStringLiteral("xref_text_orientation"), m_xref_text_orientation); + setXrefTextAlignment(alignmentFromXml(layout_element, QStringLiteral("xref_text_alignment"), m_xref_text_alignment)); + + m_type_symbol_y = realFromXml(layout_element, QStringLiteral("type_symbol_y"), m_type_symbol_y); + m_type_symbol_height = realFromXml(layout_element, QStringLiteral("type_symbol_height"), m_type_symbol_height); + m_connection_length = realFromXml(layout_element, QStringLiteral("connection_length"), m_connection_length); + m_cable_wire_length = realFromXml(layout_element, QStringLiteral("cable_wire_length"), m_cable_wire_length); + m_cable_length = realFromXml(layout_element, QStringLiteral("cable_length"), m_cable_length); + m_cable_end_length = realFromXml(layout_element, QStringLiteral("cable_end_length"), m_cable_end_length); + + m_bridge_point_d = realFromXml(layout_element, QStringLiteral("bridge_point_d"), m_bridge_point_d); + for (auto i = 0; i < m_bridge_point_y_offset.size(); ++i) { + m_bridge_point_y_offset[i] = realFromXml(layout_element, QStringLiteral("bridge_point_y_offset_%1").arg(i), m_bridge_point_y_offset.at(i)); + } +} diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h index ee5e4e8ee..b432783b2 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 @@ -103,6 +104,11 @@ class TerminalStripLayoutPattern QUuid m_uuid{QUuid::createUuid()}; QString m_name; + //Save / load of the layout in the project xml + QDomElement toXml(QDomDocument &document) const; + void fromXml(const QDomElement &layout_element); + static QString xmlTagName(); + private: void updateHeaderTextOption(); void updateTerminalsTextOption(); diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutshandler.cpp b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutshandler.cpp index 66a0bc92f..1dc905d73 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutshandler.cpp +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutshandler.cpp @@ -17,6 +17,7 @@ */ #include "terminalstriplayoutshandler.h" +#include #include TerminalStripLayoutsHandler::TerminalStripLayoutsHandler() @@ -30,3 +31,27 @@ QSharedPointer TerminalStripLayoutsHandler::defaultL { return m_default_layout; } + +/** + * @brief TerminalStripLayoutsHandler::toXml + * Append the default layout (font included) as a child of @a parent_element + * @param parent_element + */ +void TerminalStripLayoutsHandler::toXml(QDomElement &parent_element) const +{ + auto document = parent_element.ownerDocument(); + parent_element.appendChild(m_default_layout->toXml(document)); +} + +/** + * @brief TerminalStripLayoutsHandler::fromXml + * Load the default layout from the child of @a parent_element, if any. + * The existing layout object is modified in place because the terminal + * strip items share it. + * @param parent_element + */ +void TerminalStripLayoutsHandler::fromXml(const QDomElement &parent_element) +{ + m_default_layout->fromXml( + parent_element.firstChildElement(TerminalStripLayoutPattern::xmlTagName())); +} diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutshandler.h b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutshandler.h index cddb842f2..d9275c4da 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutshandler.h +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutshandler.h @@ -18,6 +18,7 @@ #ifndef TERMINALSTRIPLAYOUTSHANDLER_H #define TERMINALSTRIPLAYOUTSHANDLER_H +#include #include #include @@ -33,6 +34,9 @@ class TerminalStripLayoutsHandler TerminalStripLayoutsHandler(); QSharedPointer defaultLayout(); + void toXml(QDomElement &parent_element) const; + void fromXml(const QDomElement &parent_element); + private: QSet> m_layout_set; QSharedPointer m_default_layout; diff --git a/sources/qetproject.cpp b/sources/qetproject.cpp index d6b070f49..829ffd3b6 100644 --- a/sources/qetproject.cpp +++ b/sources/qetproject.cpp @@ -1587,6 +1587,8 @@ QDomDocument QETProject::toXml() //Write terminal strip to xml if (m_terminal_strip_vector.count()) { + m_project_properties_handler.terminalStripLayoutHandler().toXml(project_root); + auto xml_strip = xml_doc.createElement(QStringLiteral("terminal_strips")); for (auto &strip : m_terminal_strip_vector) { xml_strip.appendChild(strip->toXml(xml_doc)); @@ -2092,6 +2094,10 @@ void QETProject::readProjectXml(QDomDocument &xml_project) readElementsCollectionXml(xml_project); const qint64 elements_ms = phase_timer.restart(); + //Load the layout of the terminal strip (font, size of cells...), + //before the diagrams because the terminal strip items use it + m_project_properties_handler.terminalStripLayoutHandler().fromXml(xml_project.documentElement()); + //Load the diagrams readDiagramsXml(xml_project); const qint64 diagrams_ms = phase_timer.restart();