Fix #1238: cross-reference drawn over the label in older projects

XRefProperties read the stored cross-reference position with
QMetaEnum::keyToValue() and cast the result straight to
Qt::AlignmentFlag. An empty value gives -1. Earlier versions saved
xrefpos="" into projects and the settings file (18 of the 29 shipped
examples that carry cross-reference settings have it), and -1 matches
no branch of DynamicElementTextItem::setXref_item(), so the
cross-reference stayed at (0,0): the top-left corner of the label,
on top of it.

fromXml() fell back to AlignBottom only when the attribute was
missing, and fromSettings() only when the key was missing (#296), so
an empty value kept producing the bad position and was saved back
empty on every save.

Both now go through one helper that returns AlignBottom for an empty,
unknown, or not-offered value. The next save writes "AlignBottom", so
affected projects heal once resaved.

tst_xrefpos covers fromXml(), fromSettings() and the rewrite on save;
it fails 5 of 14 cases without this change. Exporting
examples/2612_ats_singlephase.qet to SVG before and after shows every
slave cross-reference moving from over its label to below it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ELKpbGxqJd7EFiTUypBtVe
This commit is contained in:
ispyisail
2026-10-03 10:18:06 +13:00
parent 04b7659180
commit 9749985089
3 changed files with 138 additions and 10 deletions
+32 -10
View File
@@ -22,6 +22,36 @@
#include <QHash>
#include <QMetaEnum>
namespace {
/**
@brief xrefPosFromKey
@param key : stored name of the position, e.g. "AlignBottom"
@return the position, or Qt::AlignBottom if key is empty or not one of
the positions the cross-reference settings offer. Older versions saved
an empty "xrefpos", which drew the cross-reference over the label.
*/
Qt::AlignmentFlag xrefPosFromKey(const QString &key)
{
bool ok = false;
const int value = QMetaEnum::fromType<Qt::Alignment>()
.keyToValue(key.toStdString().data(), &ok);
if (!ok)
return Qt::AlignBottom;
switch (value) {
case Qt::AlignBottom:
case Qt::AlignTop:
case Qt::AlignLeft:
case Qt::AlignRight:
case Qt::AlignBaseline:
case Qt::AlignHCenter:
return Qt::AlignmentFlag(value);
default:
return Qt::AlignBottom;
}
}
}
/**
@brief XRefProperties::XRefProperties
Default Constructor
@@ -96,8 +126,7 @@ void XRefProperties::fromSettings(const QSettings &settings,
m_master_label = settings.value(prefix % "master_label", "%f-%l%c").toString();
m_slave_label = settings.value(prefix % "slave_label", "(%f-%l%c)").toString();
QMetaEnum var = QMetaEnum::fromType<Qt::Alignment>();
m_xref_pos = Qt::AlignmentFlag(var.keyToValue((settings.value(prefix % "xrefpos", "AlignBottom").toString()).toStdString().data()));
m_xref_pos = xrefPosFromKey(settings.value(prefix % "xrefpos").toString());
for (QString key : m_prefix_keys) {
m_prefix.insert(key, settings.value(prefix + key % "prefix").toString());
@@ -157,14 +186,7 @@ bool XRefProperties::fromXml(const QDomElement &xml_element) {
QString snap = xml_element.attribute("snapto", "label");
snap == "bottom"? m_snap_to = Bottom : m_snap_to = Label;
QString xrefpos = xml_element.attribute("xrefpos","Left");
QMetaEnum var = QMetaEnum::fromType<Qt::Alignment>();
if(xml_element.hasAttribute("xrefpos"))
m_xref_pos = Qt::AlignmentFlag(var.keyToValue(xml_element.attribute("xrefpos").toStdString().data()));
else
m_xref_pos = Qt::AlignBottom;
m_xref_pos = xrefPosFromKey(xml_element.attribute("xrefpos"));
m_offset = xml_element.attribute("offset", "0").toInt();
m_slave_offset = xml_element.attribute("slave_offset", "0").toInt();