Files
qelectrotech-source-mirror/sources/properties/xrefproperties.cpp
T
Kellermorph a2880ad79e Write the cable XML only where it has something to carry
Two pieces of cable XML went into every file the program saved, whether
the project had cables or not (non-blocking review comment by
ispyisail). Resaving one of the example projects added both of them.

- <cable_autonums> is now written only when it holds something: a named
  rule, an axis other than the default, the numbering question answered
  with no, or a rule of its own. When it is missing, the reader falls
  back to exactly the defaults a project which never touched cable
  numbering has, so nothing changes for those files.

  That is deliberately not "only when the project has cables", which
  would cost data: a rule configured before the first cable is drawn and
  an axis chosen before it are answers only this element can carry, and
  the question answered with no has to survive even if the cable which
  prompted it was cancelled again.

- the font attribute of <xref> is now written only when there is one.
  Only the cable cross-reference has a font of its own; writing it
  unconditionally put font="" on every cross-reference type of every
  project, and an absent attribute reads back as no font, which is what
  all the others are.

Verified by resaving examples/741.qet, examples/Projet_vierge.qet and
examples/affuteuse_250h.qet: before, cable_autonums=1 and font="" on
each; after, none of them. A cable project of the reviewer's own keeps
<cable_autonums axis_priority="y" current_autonum="Cable"> with its rule
and its real fonts, and only loses the four empty font attributes.
ctest 92/93, the one failure being the pre-existing headless
tst_menubarkeyboard.
2026-10-10 09:42:54 +02:00

275 lines
9.6 KiB
C++

/*
Copyright 2006-2026 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 <http://www.gnu.org/licenses/>.
*/
#include "xrefproperties.h"
#include "../qetapp.h"
#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
*/
XRefProperties::XRefProperties()
{
m_show_power_ctc = true;
m_show_terminal_name = true;
m_show_all_configured_slaves = false;
m_stack_overlapping = true;
m_display = Cross;
m_snap_to = Bottom;
m_prefix_keys << "power" << "delay" << "switch";
m_master_label = "%f-%l%c";
m_slave_label = "(%f-%l%c)";
m_font = QString();
m_offset = 0;
m_slave_offset = 0;
m_xref_pos = Qt::AlignBottom;
}
/**
@brief XRefProperties::toSettings
Save to settings
@param settings: QSettings to use
@param prefix: prefix before properties name
*/
void XRefProperties::toSettings(QSettings &settings,
const QString prefix) const
{
settings.setValue(prefix % "showpowerctc", m_show_power_ctc);
settings.setValue(prefix % "showterminalname", m_show_terminal_name);
settings.setValue(prefix % "showallconfiguredslaves", m_show_all_configured_slaves);
settings.setValue(prefix % "stackoverlapping", m_stack_overlapping);
QString display = m_display == Cross? "cross" : "contacts";
settings.setValue(prefix % "displayhas", display);
QString snap = m_snap_to == Bottom? "bottom" : "label";
settings.setValue(prefix % "snapto", snap);
int offset = m_offset;
settings.setValue(prefix % "offset", offset);
int slave_offset = m_slave_offset;
settings.setValue(prefix % "slave_offset", slave_offset);
QString master_label = m_master_label;
settings.setValue(prefix % "master_label", master_label);
QString slave_label = m_slave_label;
settings.setValue(prefix % "slave_label", slave_label);
settings.setValue(prefix % "font", m_font);
QMetaEnum var = QMetaEnum::fromType<Qt::Alignment>();
settings.setValue(prefix % "xrefpos", var.valueToKey(m_xref_pos));
foreach (QString key, m_prefix.keys()) {
settings.setValue(prefix % key % "prefix", m_prefix.value(key));
}
}
/**
@brief XRefProperties::fromSettings
load from settings
@param settings: QSettings to use
@param prefix: prefix before properties name
*/
void XRefProperties::fromSettings(const QSettings &settings,
const QString prefix)
{
m_show_power_ctc = settings.value(prefix % "showpowerctc", true).toBool();
m_show_terminal_name = settings.value(prefix % "showterminalname", true).toBool();
m_show_all_configured_slaves = settings.value(prefix % "showallconfiguredslaves", false).toBool();
m_stack_overlapping = settings.value(prefix % "stackoverlapping", true).toBool();
QString display = settings.value(prefix % "displayhas", "cross").toString();
display == "cross"? m_display = Cross : m_display = Contacts;
QString snap = settings.value(prefix % "snapto", "label").toString();
snap == "bottom"? m_snap_to = Bottom : m_snap_to = Label;
m_offset = settings.value(prefix % "offset", "0").toInt();
m_slave_offset = settings.value(prefix % "slave_offset", "0").toInt();
m_master_label = settings.value(prefix % "master_label", "%f-%l%c").toString();
m_slave_label = settings.value(prefix % "slave_label", "(%f-%l%c)").toString();
m_font = settings.value(prefix % "font").toString();
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());
}
}
/**
@brief XRefProperties::toXml
Save to xml
@param xml_document : QDomElement to use for saving
@return QDomElement
*/
QDomElement XRefProperties::toXml(QDomDocument &xml_document) const
{
QDomElement xml_element = xml_document.createElement("xref");
xml_element.setAttribute("type", m_key);
xml_element.setAttribute("showpowerctc", m_show_power_ctc? "true" : "false");
xml_element.setAttribute("showterminalname", m_show_terminal_name? "true" : "false");
xml_element.setAttribute("showallconfiguredslaves", m_show_all_configured_slaves? "true" : "false");
xml_element.setAttribute("stackoverlapping", m_stack_overlapping? "true" : "false");
QString display = m_display == Cross? "cross" : "contacts";
xml_element.setAttribute("displayhas", display);
QString snap = m_snap_to == Bottom? "bottom" : "label";
xml_element.setAttribute("snapto", snap);
QString xrefpos;
QMetaEnum var = QMetaEnum::fromType<Qt::Alignment>();
xml_element.setAttribute("xrefpos", var.valueToKey(m_xref_pos));
int offset = m_offset;
xml_element.setAttribute("offset", QString::number(offset));
xml_element.setAttribute("slave_offset", QString::number(m_slave_offset));
QString master_label = m_master_label;
xml_element.setAttribute("master_label", master_label);
QString slave_label = m_slave_label;
xml_element.setAttribute("slave_label", slave_label);
//Only the cable cross-reference has a font of its own, and only
//it ever sets one. Writing the attribute unconditionally put
//font="" on every cross-reference type of every project the
//program saved; a file which does not hold the attribute reads
//back as no font, which is what all of them are.
if (!m_font.isEmpty()) {
xml_element.setAttribute("font", m_font);
}
foreach (QString key, m_prefix.keys()) {
xml_element.setAttribute(key % "prefix", m_prefix.value(key));
}
return xml_element;
}
/**
@brief XRefProperties::fromXml
Load from xml
@param xml_element: QDomElement to use for load
*/
bool XRefProperties::fromXml(const QDomElement &xml_element) {
m_show_power_ctc = xml_element.attribute("showpowerctc") == "true";
m_show_terminal_name = xml_element.attribute("showterminalname", "true") == "true";
m_show_all_configured_slaves = xml_element.attribute("showallconfiguredslaves", "false") == "true";
m_stack_overlapping = xml_element.attribute("stackoverlapping", "true") == "true";
QString display = xml_element.attribute("displayhas", "cross");
display == "cross"? m_display = Cross : m_display = Contacts;
QString snap = xml_element.attribute("snapto", "label");
snap == "bottom"? m_snap_to = Bottom : m_snap_to = Label;
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();
m_master_label = xml_element.attribute("master_label", "%f-%l%c");
m_slave_label = xml_element.attribute("slave_label","(%f-%l%c)");
m_font = xml_element.attribute("font");
foreach (QString key, m_prefix_keys) {
m_prefix.insert(key, xml_element.attribute(key % "prefix"));
}
return true;
}
/**
@brief XRefProperties::defaultProperties
@return the default properties stored in the setting file
One entry per kind of element which shows a cross reference, stored
under its own key: "coil", "protection", "commutator", "plc" -- and
"cable", which is not an element at all: it is the reference a cable
writes in the label of each of its sections when the cable runs on
several folios.
*/
QHash<QString, XRefProperties> XRefProperties::defaultProperties()
{
QHash <QString, XRefProperties> hash;
QStringList keys;
keys << "coil" << "protection" << "commutator" << "plc" << "cable";
QSettings settings;
foreach (QString key, keys)
{
XRefProperties properties;
QString str("diagrameditor/defaultxref");
properties.fromSettings(settings, str += key);
//A cable takes the very same default text as a relay master
//and the other types, "%f-%l%c": what it names is then the
//other section of the cable -- the folio it stands on and
//the place it stands at there, which is what an element
//points at as well. No default of its own, so that setting
//the five of them apart needs no thought at all.
hash.insert(key, properties);
}
return hash;
}
bool XRefProperties::operator ==(const XRefProperties &xrp) const{
return (m_show_power_ctc == xrp.m_show_power_ctc
&& m_show_terminal_name == xrp.m_show_terminal_name
&& m_show_all_configured_slaves == xrp.m_show_all_configured_slaves
&& m_stack_overlapping == xrp.m_stack_overlapping
&& m_display == xrp.m_display
&& m_snap_to == xrp.m_snap_to
&& m_prefix == xrp.m_prefix
&& m_master_label== xrp.m_master_label
&& m_offset == xrp.m_offset
&& m_slave_offset== xrp.m_slave_offset
&& m_xref_pos == xrp.m_xref_pos
&& m_slave_label == xrp.m_slave_label
&& m_font == xrp.m_font);
}
bool XRefProperties::operator !=(const XRefProperties &xrp) const
{
return (! (*this == xrp));
}