mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-20 13:24:24 +02:00
Keep in a .qetz what QElectroTech cannot compute for a symbol it cannot build
The .qetz leaves out of its folios what QElectroTech computes when it builds them (format 4): a symbol's terminal list and information texts, a wire's description of its ends. A symbol whose definition the project does not hold is never built, so none of it came back: through a .qetz, the symbols and wires kept by the previous commit lost their terminal lists, texts and end labels. QetContainer::dropComputed() now leaves a symbol whose definition is not in the project's collection (embeddedDefinitions()), and the wires ending on it, as they are. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
#include "qetcontainerdb.h"
|
#include "qetcontainerdb.h"
|
||||||
|
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
|
#include <functional>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
@@ -242,6 +243,28 @@ bool QetContainer::ownUuids(const QDomElement &project)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief QetContainer::embeddedDefinitions
|
||||||
|
@return the paths of the symbol definitions the project @p project
|
||||||
|
holds in its collection, as a symbol's type names them after embed://
|
||||||
|
*/
|
||||||
|
QSet<QString> QetContainer::embeddedDefinitions(const QDomElement &project)
|
||||||
|
{
|
||||||
|
QSet<QString> paths;
|
||||||
|
std::function<void(const QDomElement &, const QString &)> walk =
|
||||||
|
[&](const QDomElement &category, const QString &path) {
|
||||||
|
for (QDomElement child = category.firstChildElement() ; !child.isNull() ;
|
||||||
|
child = child.nextSiblingElement()) {
|
||||||
|
const QString name = path + child.attribute(QStringLiteral("name"));
|
||||||
|
if (child.tagName() == QLatin1String("category")) walk(child, name + QLatin1Char('/'));
|
||||||
|
else if (child.tagName() == QLatin1String("element")) paths.insert(name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for (const QDomElement &collection : childElements(project, QStringLiteral("collection")))
|
||||||
|
walk(collection, QString());
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief QetContainer::dropComputed
|
@brief QetContainer::dropComputed
|
||||||
Take out of the folio @p diagram what QElectroTech computes when it
|
Take out of the folio @p diagram what QElectroTech computes when it
|
||||||
@@ -253,19 +276,39 @@ bool QetContainer::ownUuids(const QDomElement &project)
|
|||||||
list of its terminals. Checked on 342 projects: opened and saved, each
|
list of its terminals. Checked on 342 projects: opened and saved, each
|
||||||
comes back as it was, but the terminal lists of a file whose symbols
|
comes back as it was, but the terminal lists of a file whose symbols
|
||||||
share a uuid (F100), where wires find their ends by them.
|
share a uuid (F100), where wires find their ends by them.
|
||||||
|
Nothing is taken from a symbol whose definition is not among
|
||||||
|
@p defined (embeddedDefinitions()), nor from a wire ending on one:
|
||||||
|
QElectroTech cannot build that symbol, keeps it as read and saves it
|
||||||
|
back (F127), so nothing of it would be computed again.
|
||||||
*/
|
*/
|
||||||
void QetContainer::dropComputed(QDomElement diagram, bool terminal_lists)
|
void QetContainer::dropComputed(QDomElement diagram, bool terminal_lists,
|
||||||
|
const QSet<QString> &defined)
|
||||||
{
|
{
|
||||||
|
QSet<QString> undefined;
|
||||||
|
for (const QDomElement &list : childElements(diagram, QStringLiteral("elements")))
|
||||||
|
for (const QDomElement &element : childElements(list, QStringLiteral("element"))) {
|
||||||
|
const QString type = element.attribute(QStringLiteral("type"));
|
||||||
|
if (!type.startsWith(QLatin1String("embed://"))
|
||||||
|
|| !defined.contains(type.mid(int(qstrlen("embed://")))))
|
||||||
|
undefined.insert(element.attribute(QStringLiteral("uuid")));
|
||||||
|
}
|
||||||
for (QDomElement list : childElements(diagram, QStringLiteral("conductors")))
|
for (QDomElement list : childElements(diagram, QStringLiteral("conductors")))
|
||||||
for (QDomElement wire : childElements(list, QStringLiteral("conductor")))
|
for (QDomElement wire : childElements(list, QStringLiteral("conductor")))
|
||||||
|
{
|
||||||
|
if (undefined.contains(wire.attribute(QStringLiteral("element1")))
|
||||||
|
|| undefined.contains(wire.attribute(QStringLiteral("element2"))))
|
||||||
|
continue;
|
||||||
for (const char *end : {"1", "2"})
|
for (const char *end : {"1", "2"})
|
||||||
for (const char *name : {"element%1_label", "element%1_name", "element%1_linked",
|
for (const char *name : {"element%1_label", "element%1_name", "element%1_linked",
|
||||||
"terminalname%1"})
|
"terminalname%1"})
|
||||||
wire.removeAttribute(QString::fromLatin1(name).arg(QLatin1String(end)));
|
wire.removeAttribute(QString::fromLatin1(name).arg(QLatin1String(end)));
|
||||||
|
}
|
||||||
for (QDomElement list : childElements(diagram, QStringLiteral("elements")))
|
for (QDomElement list : childElements(diagram, QStringLiteral("elements")))
|
||||||
{
|
{
|
||||||
for (QDomElement element : childElements(list, QStringLiteral("element")))
|
for (QDomElement element : childElements(list, QStringLiteral("element")))
|
||||||
{
|
{
|
||||||
|
if (undefined.contains(element.attribute(QStringLiteral("uuid"))))
|
||||||
|
continue;
|
||||||
if (terminal_lists)
|
if (terminal_lists)
|
||||||
for (QDomElement terminals : childElements(element, QStringLiteral("terminals")))
|
for (QDomElement terminals : childElements(element, QStringLiteral("terminals")))
|
||||||
removeElement(terminals);
|
removeElement(terminals);
|
||||||
@@ -341,8 +384,9 @@ QList<QetZip::Entry> QetContainer::split(const QDomDocument &project, const QStr
|
|||||||
int folio = 0;
|
int folio = 0;
|
||||||
//Nothing QElectroTech computes is kept (format 4)
|
//Nothing QElectroTech computes is kept (format 4)
|
||||||
const bool own_uuids = ownUuids(root);
|
const bool own_uuids = ownUuids(root);
|
||||||
|
const QSet<QString> defined = embeddedDefinitions(root);
|
||||||
for (QDomElement diagram : childElements(root, QStringLiteral("diagram")))
|
for (QDomElement diagram : childElements(root, QStringLiteral("diagram")))
|
||||||
dropComputed(diagram, own_uuids);
|
dropComputed(diagram, own_uuids, defined);
|
||||||
|
|
||||||
//The parts of the folios kept as they were, and their pictures
|
//The parts of the folios kept as they were, and their pictures
|
||||||
QMap<QString, QByteArray> pictures; //name -> png, once each
|
QMap<QString, QByteArray> pictures; //name -> png, once each
|
||||||
|
|||||||
@@ -89,7 +89,9 @@ namespace QetContainer
|
|||||||
void inlinePicture(QDomElement image, const QByteArray &bytes);
|
void inlinePicture(QDomElement image, const QByteArray &bytes);
|
||||||
|
|
||||||
/// Take what QElectroTech computes out of a folio (format 4)
|
/// Take what QElectroTech computes out of a folio (format 4)
|
||||||
void dropComputed(QDomElement diagram, bool terminal_lists);
|
void dropComputed(QDomElement diagram, bool terminal_lists, const QSet<QString> &defined);
|
||||||
|
/// The symbol definitions a project holds, by path after embed://
|
||||||
|
QSet<QString> embeddedDefinitions(const QDomElement &project);
|
||||||
/// true if every folio, symbol and wire has a uuid of its own
|
/// true if every folio, symbol and wire has a uuid of its own
|
||||||
bool ownUuids(const QDomElement &project);
|
bool ownUuids(const QDomElement &project);
|
||||||
/// Parse @p xml as a .qet is read (QETProject::openFile)
|
/// Parse @p xml as a .qet is read (QETProject::openFile)
|
||||||
|
|||||||
@@ -77,9 +77,10 @@ class tst_qetcontainer : public QObject
|
|||||||
{
|
{
|
||||||
QDomDocument copy = document.cloneNode(true).toDocument();
|
QDomDocument copy = document.cloneNode(true).toDocument();
|
||||||
const bool own_uuids = QetContainer::ownUuids(copy.documentElement());
|
const bool own_uuids = QetContainer::ownUuids(copy.documentElement());
|
||||||
|
const QSet<QString> defined = QetContainer::embeddedDefinitions(copy.documentElement());
|
||||||
for (QDomElement diagram = copy.documentElement().firstChildElement(QStringLiteral("diagram"));
|
for (QDomElement diagram = copy.documentElement().firstChildElement(QStringLiteral("diagram"));
|
||||||
!diagram.isNull() ; diagram = diagram.nextSiblingElement(QStringLiteral("diagram")))
|
!diagram.isNull() ; diagram = diagram.nextSiblingElement(QStringLiteral("diagram")))
|
||||||
QetContainer::dropComputed(diagram, own_uuids);
|
QetContainer::dropComputed(diagram, own_uuids, defined);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user