mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-09-30 23:04:13 +02:00
Keep terminal uuids when a whole category is replaced; never duplicate one
Review of the previous commit: - keep() could give an old uuid to a new terminal while another terminal of the new definition already carried it (a moved terminal), leaving two terminals with one uuid. A terminal carrying any old uuid is now left alone, and an old uuid already in use is never handed out. - copyDirectory() replaced a whole category of the embedded collection (drag a folder onto the project's folder of the same name) without carrying terminal uuids over. keepInDirectory() walks both trees by name and calls keep() on each symbol. - The "wire(s) not loaded" log line repeated the folio's list on every paste; it is now written only when a folio is loaded. tst_terminaluuids: 3 new cases, each red on the previous keep(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <QDomElement>
|
||||
#include <QHash>
|
||||
#include <QSet>
|
||||
#include <QStringList>
|
||||
|
||||
namespace {
|
||||
@@ -64,26 +65,82 @@ QString terminalPlace(const QDomElement &terminal)
|
||||
one saved by a different version of the collection -- every wire on
|
||||
those symbols was lost the next time the project was opened.
|
||||
|
||||
Terminals that moved, and new ones, keep their own uuid. Where the old
|
||||
definition has two terminals at one place, they are matched in order.
|
||||
A terminal of the new definition that already carries one of the old
|
||||
uuids is that same terminal, perhaps moved: it keeps it, and that uuid
|
||||
is not given to anything else. Other terminals that moved, and new
|
||||
ones, keep their own. No uuid is ever given to two terminals. Where the
|
||||
old definition has two terminals at one place, they are matched in
|
||||
order.
|
||||
*/
|
||||
void TerminalUuids::keep(const QDomElement &old_element, QDomElement &new_element)
|
||||
{
|
||||
QHash<QString, QStringList> old_uuids;
|
||||
QSet<QString> all_old_uuids;
|
||||
for (const QDomElement &t : terminalsOf(old_element)) {
|
||||
const QString uuid = t.attribute(QStringLiteral("uuid"));
|
||||
if (!uuid.isEmpty()) {
|
||||
old_uuids[terminalPlace(t)] << uuid;
|
||||
all_old_uuids << uuid;
|
||||
}
|
||||
}
|
||||
if (old_uuids.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (QDomElement t : terminalsOf(new_element)) {
|
||||
const QList<QDomElement> new_terminals = terminalsOf(new_element);
|
||||
QSet<QString> taken;
|
||||
for (const QDomElement &t : new_terminals) {
|
||||
taken << t.attribute(QStringLiteral("uuid"));
|
||||
}
|
||||
|
||||
for (QDomElement t : new_terminals) {
|
||||
const QString own = t.attribute(QStringLiteral("uuid"));
|
||||
if (all_old_uuids.contains(own)) {
|
||||
continue;
|
||||
}
|
||||
QStringList &uuids = old_uuids[terminalPlace(t)];
|
||||
while (!uuids.isEmpty() && taken.contains(uuids.first())) {
|
||||
uuids.removeFirst();
|
||||
}
|
||||
if (!uuids.isEmpty()) {
|
||||
t.setAttribute(QStringLiteral("uuid"), uuids.takeFirst());
|
||||
const QString uuid = uuids.takeFirst();
|
||||
taken.remove(own);
|
||||
taken << uuid;
|
||||
t.setAttribute(QStringLiteral("uuid"), uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@brief TerminalUuids::keepInDirectory
|
||||
keep() for every symbol of @p new_directory that has a counterpart of
|
||||
the same name at the same place under @p old_directory. Both are
|
||||
<category> of an embedded collection; used when a whole category of
|
||||
the project is replaced.
|
||||
*/
|
||||
void TerminalUuids::keepInDirectory(const QDomElement &old_directory,
|
||||
QDomElement &new_directory)
|
||||
{
|
||||
for (QDomElement child = new_directory.firstChildElement();
|
||||
!child.isNull();
|
||||
child = child.nextSiblingElement()) {
|
||||
if (child.tagName() != QLatin1String("category")
|
||||
&& child.tagName() != QLatin1String("element")) {
|
||||
continue;
|
||||
}
|
||||
const QString name = child.attribute(QStringLiteral("name"));
|
||||
QDomElement old_child = old_directory.firstChildElement(child.tagName());
|
||||
while (!old_child.isNull()
|
||||
&& old_child.attribute(QStringLiteral("name")) != name) {
|
||||
old_child = old_child.nextSiblingElement(child.tagName());
|
||||
}
|
||||
if (old_child.isNull()) {
|
||||
continue;
|
||||
}
|
||||
if (child.tagName() == QLatin1String("category")) {
|
||||
keepInDirectory(old_child, child);
|
||||
} else {
|
||||
keep(old_child, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user