From cb0d8c8f637e4609bb5fd4757f797a5b2b788bd0 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Sun, 13 Sep 2026 00:06:31 +1200 Subject: [PATCH] Write embedded title block templates in a stable order Fifth site of the hash-ordering defect fixed in #844. TitleBlockTemplatesProjectCollection::templates() returns titleblock_templates_xml_.keys(), a QHash, and QETProject::toXml() iterated it directly. A project embedding more than one template therefore wrote the children in a different order on every save. examples/affuteuse_250h.qet embeds three -- A4_1, DIN_A4 and DIN_A4_copy -- and two saves of it produced "DIN_A4 A4_1 DIN_A4_copy" and "DIN_A4_copy A4_1 DIN_A4". It was the last of the two projects #844 could not make reproducible. Worth recording because the first reading of that diff was wrong: seeing name="DIN_A4" on one side and name="DIN_A4_copy" on the other looked like the save path renaming a template, which would have been far more serious -- a diagram referring to it by name would have been left dangling. The file simply contains both, and they had swapped places. Co-Authored-By: Claude Opus 5 --- sources/qetproject.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sources/qetproject.cpp b/sources/qetproject.cpp index 0147b3f97..a86670dc2 100644 --- a/sources/qetproject.cpp +++ b/sources/qetproject.cpp @@ -1043,7 +1043,14 @@ QDomDocument QETProject::toXml() // titleblock templates, if any if (m_titleblocks_collection.templates().count()) { QDomElement titleblocktemplates_elmt = xml_doc.createElement("titleblocktemplates"); - foreach (QString template_name, m_titleblocks_collection.templates()) { + //Sorted, because templates() returns QHash::keys() and Qt + //randomises hash order per process. Writing them unsorted put the + // children in a different order on every save, + //which is what made a project holding more than one template save + //irreproducibly. + QStringList template_names = m_titleblocks_collection.templates(); + template_names.sort(); + for (const QString &template_name : std::as_const(template_names)) { QDomElement e = m_titleblocks_collection.getTemplateXmlDescription(template_name); titleblocktemplates_elmt.appendChild(xml_doc.importNode(e, true)); }