Fix a table losing its query when a folio is removed with lazy folios

With lazy folios, removing a folio left the tables on folios not built
yet as the file had them. A table split over several folios keeps its
query in its first part; when the folio holding that part was removed,
the next part, built later from the file, named a part that was gone and
was saved with no query. A parts list that listed the removed folio's
symbols also kept its old size. With every folio built neither happens.

Removing a folio that holds a table or a symbol now builds the folios
holding tables first, while the removed folio is still in the project.
A folio with neither builds nothing, as tst_lazyfolios checks.

buildFolios() now holds the project database's update signal back and
sends it once at the end, as pasting does: without that every item built
made every table lay itself out again, and the save after a removal on a
50-folio project took about 270 s instead of 4.5 s. The rows are still
written as each item is built, so no full refill of the database is
needed (one per build made a 136-folio project's edit 20 % slower).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XCdg2Er2vYhB8Vwa5G7fSR
This commit is contained in:
ispyisail
2026-10-17 22:22:10 +13:00
parent 391ed4a252
commit bc6da100d3
3 changed files with 104 additions and 0 deletions
+44
View File
@@ -752,11 +752,24 @@ void QETProject::buildFolios(const QList<Diagram *> &folios) const
auto *self = const_cast<QETProject *>(this);
const ProjectState state = m_state;
self->m_state = ProjectParsingRunning;
//Batch the database's signals as a paste does
//(DiagramEventAddPaste): every symbol and wire built would emit
//dataBaseUpdated(), and every table already built would measure all
//its rows again each time -- minutes for a save building 40 folios
//with 10 parts-list folios built. The rows are still written as each
//item is built: only the signal waits, and is sent once at the end
//(updateDB() would fill the whole database again, every time).
const bool signals_were_blocked = self->m_data_base.signalsBlocked();
self->m_data_base.blockSignals(true);
QList<Diagram *> built;
for (Diagram *d : folios)
if (d->buildDeferred()) built << d;
for (Diagram *d : std::as_const(built))
self->folioLoaded(d);
self->m_data_base.blockSignals(signals_were_blocked);
if (!signals_were_blocked && !built.isEmpty()) {
emit self->m_data_base.dataBaseUpdated();
}
//A symbol built before still keeping the links it was saved with
//(a partner on a folio not built): its initLink() links those just
//built, puts its partners back in their saved order and drops what
@@ -3175,6 +3188,23 @@ void QETProject::buildFoliosHoldingTables()
buildFolios(to_build);
}
/**
@brief QETProject::folioHoldsTablesOrSymbols
@return true if @p folio, built or not, has a drawn table or a symbol
*/
bool QETProject::folioHoldsTablesOrSymbols(Diagram *folio) const
{
if (!folio->isLoaded()) {
const QDomElement xml = folio->deferredXml();
return !xml.elementsByTagName(QetGraphicsTableItem::xmlTagName()).isEmpty()
|| !xml.elementsByTagName(QStringLiteral("element")).isEmpty();
}
for (QGraphicsItem *item : folio->items())
if (item->type() == QetGraphicsTableItem::Type || item->type() == Element::Type)
return true;
return false;
}
/**
@brief QETProject::unbuiltFolioHasTables
@return true if @p folio, not built yet (lazy folios), has a drawn
@@ -4274,6 +4304,20 @@ void QETProject::detachDiagram(Diagram *diagram)
disconnect(diagram, &Diagram::usedTitleBlockTemplateChanged,
this, &QETProject::usedTitleBlockTemplateChanged);
//A folio that holds a table or a symbol is removed: tables on folios
//not built yet (lazy folios) are built while it is still in the
//project, as they are with every folio built (F121). A table split
//over several folios keeps its query in its first part, and the next
//part takes it over only if that part was built
//(QetGraphicsTableItem::toXml()); built later, from the file, it
//names a part that is gone and saves no query. A built table also
//follows the project's database, so a parts list that showed this
//folio's symbols is resized like every other. A folio with neither
//builds no other.
if (folioHoldsTablesOrSymbols(diagram)) {
buildFoliosHoldingTables();
}
m_diagrams_list.removeAll(diagram);
updateDiagramsFolioData();
emit diagramRemoved(this, diagram);