Answer scripts from the folio asked for, without building every folio (stage D5)

The scripting API (scripts and the assistant's live mode) reached a folio
through diagrams(), which builds every folio, for every call. A folio's
own data -- count, title, uuid, title block, border, wire defaults --
now comes from folios(), built or not; a call reading or changing a
folio's items builds that folio, as showing it does (built()); selecting
a symbol by uuid builds the folio the project database places it on.
Search and replace and the continuity check still build every folio.

DiagramContent worked out one wire of each potential when made, which
follows potentials through folio reports and built the folios at the
other end, for every caller; it is now worked out when first asked
(Search and replace asks; a merge asks both sides, as before).

tst_lazyfolios: on a .qetz, a script reads every folio's title, uuid and
border building none (fails with diagrams()), and the symbols and wires
of the folio with the most links to other folios as when built, building
that folio only (27 before potentials were lazy). ctest 96/96 but
modal_quit_regression in both modes: a race in that test (gdb interrupts
the main thread inside malloc while the folio view repaints during the
dialog, master too), 2 of 23 runs here, 0 of 10 on master, passing alone.
342 corpus projects save the same in all four arms, and export the same
wiring list and wire numbers lazily.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-10-12 14:20:17 +13:00
parent 65b10b01d9
commit 9078e4e321
6 changed files with 164 additions and 86 deletions
+29 -10
View File
@@ -79,13 +79,7 @@ DiagramContent::DiagramContent(Diagram *diagram, bool selected) :
m_other_conductors << c;
}
if (m_potential_conductors.isEmpty()) {
m_potential_conductors << c;
} else {
if (!potentialIsManaged(c->relatedPotentialConductors(true).values())) {
m_potential_conductors << c;
}
}
m_potential_candidates << c;
break;
}
case DiagramImageItem::Type: { m_images << qgraphicsitem_cast<DiagramImageItem *>(item); break;}
@@ -379,12 +373,14 @@ DiagramContent &DiagramContent::operator+=(const DiagramContent &other)
if(!m_selected_items.contains(qgi))
m_selected_items << qgi;
for (Conductor *c : other.m_potential_conductors)
QList<Conductor *> potentials = potentialConductors();
for (Conductor *c : other.potentialConductors())
{
QList<Conductor *> c_list = c->relatedPotentialConductors(true).values();
c_list << c;
if (!potentialIsManaged(c_list)) {
m_potential_conductors << c;
potentials << c;
m_potential_conductors = potentials;
}
}
@@ -402,17 +398,40 @@ DiagramContent &DiagramContent::operator+=(const DiagramContent &other)
*/
bool DiagramContent::potentialIsManaged(QList<Conductor *> conductors)
{
const QList<Conductor *> potentials = potentialConductors();
bool b = false;
for (Conductor *c : conductors)
{
if (m_potential_conductors.contains(c))
if (potentials.contains(c))
b = true;
}
return b;
}
/**
@brief DiagramContent::potentialConductors
@return one wire of each potential of the wires of this content, worked
out the first time it is asked (see m_potential_conductors)
*/
QList<Conductor *> DiagramContent::potentialConductors() const
{
if (!m_potential_conductors) {
QList<Conductor *> potentials;
for (Conductor *c : m_potential_candidates) {
bool managed = false;
if (!potentials.isEmpty())
for (Conductor *related : c->relatedPotentialConductors(true))
if (potentials.contains(related)) { managed = true; break; }
if (!managed)
potentials << c;
}
m_potential_conductors = potentials;
}
return *m_potential_conductors;
}
/**
@brief DiagramContent::hasTextEditing
@return true if handle a text currently in editing interaction