diff --git a/sources/diagramcontext.cpp b/sources/diagramcontext.cpp index 4e4f0d205..5137a7bf5 100644 --- a/sources/diagramcontext.cpp +++ b/sources/diagramcontext.cpp @@ -151,8 +151,8 @@ bool DiagramContext::operator!=(const DiagramContext &dc) const void DiagramContext::toXml(QDomElement &e, const QString &tag_name) const { foreach (QString key, keys()) { - if ((tag_name == "elementInformation") && - (m_content[key].toString().trimmed().isEmpty())) { + const QString raw = m_content[key].toString(); + if ((tag_name == "elementInformation") && raw.trimmed().isEmpty()) { continue; } QDomElement property = e.ownerDocument().createElement(tag_name); @@ -161,7 +161,15 @@ void DiagramContext::toXml(QDomElement &e, const QString &tag_name) const property.removeAttribute("name"); property.setAttribute("show", m_content_show[key]); property.setAttribute("name", key); - QDomText value = e.ownerDocument().createTextNode(m_content[key].toString().trimmed()); + // Trim stray leading/trailing whitespace around real content, but + // not a value that IS whitespace: unconditionally trimming an + // all-whitespace string collapses it to "", which is silently + // indistinguishable from a value that was never set. A title-block + // custom variable set to a single space -- a workaround for #973, + // where an unset variable renders as its own literal placeholder -- + // would otherwise vanish on the very next save. + const QString stored = raw.trimmed().isEmpty() ? raw : raw.trimmed(); + QDomText value = e.ownerDocument().createTextNode(stored); property.appendChild(value); e.appendChild(property); } diff --git a/sources/qetproject.cpp b/sources/qetproject.cpp index 49b4a6520..af0f00b25 100644 --- a/sources/qetproject.cpp +++ b/sources/qetproject.cpp @@ -334,7 +334,18 @@ QETProject::ProjectState QETProject::openFile(QFile *file) //file without a persisted uuid derives its uuid from them. const QByteArray content = file->readAll(); QDomDocument xml_project; - if (!xml_project.setContent(content)) + // PreserveSpacingOnlyNodes: without it, a text node that is entirely + // whitespace -- e.g. a title-block custom variable deliberately set to + // a single space, the only way to give it a value other than blank + // (bugtracker #973) -- is silently dropped by Qt's default parsing, + // and QDomElement::text() then returns "" for it exactly as if it had + // never been set. Confirmed in isolation: parses to text()=="", + // this option makes it text()==" ". Every place in this codebase that + // walks a QDomNode's children already filters on isElement() (see + // QET::findInDomElement()), so the extra whitespace-only text nodes + // this keeps around are inert everywhere but the two elements that + // call .text() on themselves -- which is exactly where the bug was. + if (!xml_project.setContent(content, QDomDocument::ParseOption::PreserveSpacingOnlyNodes)) { if(opened_here) { file->close();