Add, move or remove a folio without building the others (stage D5)

Adding, moving or removing a folio rewrote every folio's position in
the project database through diagrams(), which builds every folio: 3 s
on a 50-folio project opened lazily. A folio not built has its position
and title block already, so folios() is enough. The list of tables a
table can continue builds only the folios holding a table (from the
index of a .qetz), and the wiring list's count of wires left out looks
at built folios only: reading a wire drops it unless both its ends are
found.

tst_lazyfolios: a folio added, moved and removed builds no other, with
the folios' rows as when every folio is built (fails with diagrams():
47 built); the tables listed as when built, building the 12 folios that
hold one (fails when every folio is built). ctest 96/96 eager and lazy;
342 corpus projects save the same in all four arms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-10-12 08:46:31 +13:00
parent 8ae937007c
commit e7fd820db6
5 changed files with 91 additions and 4 deletions
+6 -3
View File
@@ -1536,8 +1536,10 @@ int projectDataBase::excludedConductorCount() const
return 0;
}
//A folio not built (QET_LAZY_FOLIOS) has none: reading a wire
//drops it unless both its ends are found (Conductor::fromXml())
int count = 0;
for (auto *diagram : m_project->diagrams())
for (auto *diagram : m_project->builtFolios())
{
const auto conductor_list = diagram->conductors();
for (auto *conductor : conductor_list)
@@ -1722,11 +1724,12 @@ void projectDataBase::flushElementPositions()
/**
@brief projectDataBase::updateFolioPositions
Write every folio's position and folio number again, after a folio was
added, removed or moved.
added, removed or moved. A folio not built yet (QET_LAZY_FOLIOS) has
its position and title block already: it is not built for this.
*/
void projectDataBase::updateFolioPositions()
{
for (auto diagram : m_project->diagrams())
for (auto diagram : m_project->folios())
{
m_diagram_order_changed.bindValue(":pos", m_project->folioIndex(diagram)+1);
m_diagram_order_changed.bindValue(":uuid", diagram->uuid().toString());
+8 -1
View File
@@ -199,7 +199,14 @@ QVector<QetGraphicsTableItem *> ElementProvider::table(
}
}
for (auto d : allFolios()) {
//Only the folios holding a table are built for it
QList<Diagram *> folios = m_diagram_list;
if (m_project) {
m_project->buildFoliosHoldingTables();
folios = m_project->builtFolios();
folios.removeOne(m_excluded);
}
for (auto d : std::as_const(folios)) {
for (auto item_ : d->items())
{
if(item_->type() == QetGraphicsTableItem::Type)
+21
View File
@@ -2978,6 +2978,27 @@ bool QETProject::usesElement(const ElementsLocation &location) const
return(unbuiltFolioElements().contains(location));
}
/**
@brief QETProject::buildFoliosHoldingTables
Build the folios not built yet (QET_LAZY_FOLIOS) that hold a drawn
table, found from the index the project was opened from when it has
one: what a list of the project's tables needs, and no more
*/
void QETProject::buildFoliosHoldingTables()
{
QList<Diagram *> to_build;
for (Diagram *d : std::as_const(m_diagrams_list))
if (!d->isLoaded() && unbuiltFolioHasTables(d))
to_build << d;
if (to_build.isEmpty()) {
return;
}
if (qEnvironmentVariableIntValue("QET_LAZY_FOLIOS_TRACE") == 1) {
qWarning().noquote() << "lazy folios:" << to_build.size() << "folios built for their tables";
}
buildFolios(to_build);
}
/**
@brief QETProject::unbuiltFolioHasTables
@return true if @p folio, not built yet (QET_LAZY_FOLIOS), has a drawn
+1
View File
@@ -135,6 +135,7 @@ class QETProject : public QObject
void buildPartnerSymbols(const QList<Diagram *> &folios, const QSet<QUuid> &partners);
void buildFoliosHolding(ElementData::Types kinds, bool free_only);
void buildFoliosHoldingSymbols(const QSet<QUuid> &symbols);
void buildFoliosHoldingTables();
QSet<QUuid> symbolsOnUnbuiltFolios() const;
/// While saving: the symbols on folios not built a built symbol
/// may be saved linked to (Element::toXml())
+55
View File
@@ -725,6 +725,61 @@ int main(int argc, char **argv)
check(asked.folioPartsRead() == built, "asking a .qetz reads no file of a folio not built");
}
//A folio added, moved and removed: no other folio built, the
//folios' rows as when every folio is built (D5)
{
auto shuffle = [](QETProject &project) {
Diagram *added = project.addNewDiagram();
project.diagramOrderChanged(1, 0);
project.removeDiagram(added);
};
auto folioRows = [](QETProject &project) {
QStringList rows;
for (const QString &row : tables(project))
if (row.startsWith("diagram")) rows << row;
return rows;
};
QETProject shuffled(zipped);
const int unbuilt = shuffled.unloadedFolioCount();
shuffle(shuffled);
std::printf(".qetz folio added, moved, removed: %d folios built\n",
unbuilt - shuffled.unloadedFolioCount());
check(shuffled.unloadedFolioCount() == unbuilt, "adding, moving and removing a folio builds no other");
qunsetenv("QET_LAZY_FOLIOS");
QETProject usual_shuffled(zipped);
qputenv("QET_LAZY_FOLIOS", "1");
shuffle(usual_shuffled);
check(folioRows(shuffled) == folioRows(usual_shuffled), "folios' rows after a move as when built");
}
//The tables a table can continue (its properties editor) and
//the wiring list's count of wires left out: only the folios
//holding a table built (D5)
{
QETProject listed(zipped);
const int unbuilt = listed.unloadedFolioCount();
auto tableUuids = [](const QVector<QetGraphicsTableItem *> &list) {
QStringList uuids;
for (QetGraphicsTableItem *table : list) uuids << table->uuid().toString();
uuids.sort();
return uuids;
};
const QStringList lazy_tables = tableUuids(ElementProvider(&listed).table(nullptr, nullptr));
check(!lazy_tables.isEmpty(), "the project has tables");
check(lazy_tables == tableUuids(ElementProvider(&eager).table(nullptr, nullptr)),
"the project's tables listed as when built");
check(listed.dataBase()->excludedConductorCount() == eager.dataBase()->excludedConductorCount(),
"wires left out of the wiring list counted as when built");
int with_tables = 0;
for (Diagram *folio : folios) {
for (QGraphicsItem *item : folio->items())
if (item->type() == QetGraphicsTableItem::Type) { ++with_tables; break; }
}
std::printf(".qetz tables listed: %d folios built, %d hold a table\n",
unbuilt - listed.unloadedFolioCount(), with_tables);
check(listed.unloadedFolioCount() > 0, "listing the tables does not build every folio");
}
//Saved as a .qetz without building the folios not touched
//(D4): their parts and rows copied as they were
QETProject untouched(zipped);