mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-25 07:24:21 +01:00
Keep the symbols and wires a folio cannot load, and save them back
Opening a project dropped, with only a debug line, a symbol whose definition could not be found (missing from the project's collection and from the library) and every wire on it; and a wire whose terminal could not be matched, after the symbol's definition was redrawn. The next save wrote the project without them. One save of a forum upload whose collection was incomplete kept 1 of 219 symbols and none of its 299 wires. A folio now keeps what it could not load as it was read (Diagram::m_kept_symbols, m_kept_wires) and writes it back when it is saved whole (Diagram::writeKept()): - a symbol, its terminals given ids after those of the folio's symbols; - a wire, an end found written from its terminal as Conductor::toXml() does, an end not found as the symbol and terminal uuids it names; for a wire saved by legacy ids, the terminal's uuid derived from where it was saved (Element::savedTerminalUuid(), out of matchMovedTerminals()), so it joins again once the definition has it there. A wire whose ends cannot be read, or an end naming no terminal of the file, is kept so that it joins nothing. A symbol kept counts as waiting (projectDataBase::waitingSymbols()), so a partner keeps its link to it. The open warning now lists the symbols not loaded too, and says both are kept. Once the definition is back, the symbol and its wires are built again: 741.qet with one transistor definition removed (8 symbols, 33 wires on them) saves all 67 wires, and with the definition put back opens with all 65 symbols and 67 wires, the same folio as before. tst_resaveunchanged::unloadableItemsKept: fixtures/coil_contact_wired.qet (coil, linked contact, two wires; built with the script API) with the coil's definition removed, or the contact's terminals moved and given new uuids: both symbols, wires and links saved, a second save the same, and the coil's definition put back gives the undamaged project's symbols and wires. Fails on master (1 symbol; 0 wires). FINDINGS F127, F128. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -975,6 +975,41 @@ bool Element::valideXml(QDomElement &e)
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Element::savedTerminalUuid
|
||||
@return the uuid TerminalUuids derives for the terminal saved as
|
||||
@p records [@p index] (a symbol's saved terminals, in file order) at the
|
||||
place it was saved: its docking point less the stub Terminal::init()
|
||||
adds, and its rank among the records at that place, as the project
|
||||
counted it when it gave the terminals their uuids
|
||||
*/
|
||||
QUuid Element::savedTerminalUuid(const QList<QDomElement> &records, int index)
|
||||
{
|
||||
const auto dock_of = [](const QDomElement &r) {
|
||||
return QPointF(r.attribute(QStringLiteral("x")).toDouble(),
|
||||
r.attribute(QStringLiteral("y")).toDouble());
|
||||
};
|
||||
const QDomElement &record = records.at(index);
|
||||
const int orientation = record.attribute(QStringLiteral("orientation")).toInt();
|
||||
const QPointF dock = dock_of(record);
|
||||
QPointF old_pos = dock;
|
||||
switch (orientation) {
|
||||
case Qet::North: old_pos -= QPointF(0, Terminal::terminalSize); break;
|
||||
case Qet::East : old_pos -= QPointF(-Terminal::terminalSize, 0); break;
|
||||
case Qet::West : old_pos -= QPointF(Terminal::terminalSize, 0); break;
|
||||
case Qet::South: old_pos -= QPointF(0, -Terminal::terminalSize); break;
|
||||
}
|
||||
int rank = 0;
|
||||
for (int j = 0; j < index; ++j) {
|
||||
const QPointF other = dock_of(records.at(j));
|
||||
if (records.at(j).attribute(QStringLiteral("orientation")).toInt() == orientation
|
||||
&& qAbs(other.x() - dock.x()) < 1e-6
|
||||
&& qAbs(other.y() - dock.y()) < 1e-6)
|
||||
++rank;
|
||||
}
|
||||
return TerminalUuids::derived(old_pos.x(), old_pos.y(), orientation, rank);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Element::matchMovedTerminals
|
||||
Pair the saved terminals that no live terminal matched exactly with the
|
||||
@@ -1033,32 +1068,8 @@ void Element::matchMovedTerminals(const QList<QDomElement> &records,
|
||||
//Pair a record with a live terminal: register its legacy id, and the
|
||||
//uuid derived for the terminal at its old place
|
||||
const auto pair_up = [&](int index, Terminal *t) {
|
||||
const QDomElement &record = records.at(index);
|
||||
const QPointF dock = dock_of(record);
|
||||
|
||||
//The old place of the terminal: its docking point less the
|
||||
//stub that Terminal::init() added
|
||||
QPointF old_pos = dock;
|
||||
switch (orientation_of(record)) {
|
||||
case Qet::North: old_pos -= QPointF(0, Terminal::terminalSize); break;
|
||||
case Qet::East : old_pos -= QPointF(-Terminal::terminalSize, 0); break;
|
||||
case Qet::West : old_pos -= QPointF(Terminal::terminalSize, 0); break;
|
||||
case Qet::South: old_pos -= QPointF(0, -Terminal::terminalSize); break;
|
||||
}
|
||||
//The rank among the records at the same place, as the project
|
||||
//counted it when it gave the terminals their uuids
|
||||
int rank = 0;
|
||||
for (int j = 0; j < index; ++j) {
|
||||
const QPointF other = dock_of(records.at(j));
|
||||
if (orientation_of(records.at(j)) == orientation_of(record)
|
||||
&& qAbs(other.x() - dock.x()) < 1e-6
|
||||
&& qAbs(other.y() - dock.y()) < 1e-6)
|
||||
++rank;
|
||||
}
|
||||
|
||||
id_adr.insert(record.attribute(QStringLiteral("id")).toInt(), t);
|
||||
m_old_place_terminals.insert(TerminalUuids::derived(old_pos.x(), old_pos.y(),
|
||||
orientation_of(record), rank), t);
|
||||
id_adr.insert(records.at(index).attribute(QStringLiteral("id")).toInt(), t);
|
||||
m_old_place_terminals.insert(savedTerminalUuid(records, index), t);
|
||||
m_moved_terminals << t;
|
||||
};
|
||||
const auto same_place = [](const QPointF &a, const QPointF &b) {
|
||||
|
||||
Reference in New Issue
Block a user