mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-25 07:24:21 +01:00
Show a folio without building its partners' folios (stage D5b)
Showing a folio built it and every folio holding a partner of its symbols. Now a partner is built alone, as a symbol, into its folio's scene (Diagram::buildSymbols()), and reused when that folio is built. - A linked folio report built alone had no wires when it was linked, so its texts showing a wire's properties stayed empty: after any build, linked reports on the built folios and their partners look at their wires again, as opening does. Unlinked reports keep their texts, as opening leaves them. - A report whose partner was built alone builds the partner's folio when its potential is followed. - tableChainFolios() parsed every unbuilt folio's file. The index now lists the drawn tables and the table each continues (folio_table), and a .qetz opened from it uses that list. An index without it falls back to the folio files. - A .qetz's project.sqlite is opened once per project (QetContainerDb::FolioReader), not once per folio built. nuri (136 folios), opened fresh, one folio shown: median 1104 -> 184 ms, each show builds one folio; industrial 234 -> 87 ms. tst_lazyfolios: a folio whose table continues another is shown first from a .qetz (fails when the index's chains are ignored). ctest 96/96 eager and lazy; 342-project corpus: master, lazy, .qetz lazy and .qetz kept all the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+97
-7
@@ -32,6 +32,7 @@
|
||||
#include "diagram.h"
|
||||
#include "qetgraphicsitem/element.h"
|
||||
#include "qetgraphicsitem/conductor.h"
|
||||
#include "qetgraphicsitem/dynamicelementtextitem.h"
|
||||
#include "qetgraphicsitem/ViewItem/qetgraphicstableitem.h"
|
||||
#include "qetgraphicsitem/ViewItem/projectdbmodel.h"
|
||||
#include "qetapp.h"
|
||||
@@ -487,7 +488,7 @@ QETProject::ProjectState QETProject::openFile(QFile *file)
|
||||
if (!index.isEmpty() && index.contains("folio_header")
|
||||
&& QetContainer::join(entries, &document, &why, &folio_files))
|
||||
{
|
||||
if (m_data_base.fillFromIndex(index, &m_folio_headers, &why)
|
||||
if (m_data_base.fillFromIndex(index, &m_folio_headers, &why, &m_index_tables)
|
||||
&& m_folio_headers.size() == folio_files.size()) {
|
||||
xml_project = document;
|
||||
m_container_files = files;
|
||||
@@ -496,6 +497,7 @@ QETProject::ProjectState QETProject::openFile(QFile *file)
|
||||
} else {
|
||||
m_data_base.discardFill();
|
||||
m_folio_headers.clear();
|
||||
m_index_tables.reset();
|
||||
qInfo().noquote() << "Not opened from the index of" << fi.fileName() << ":" << why;
|
||||
}
|
||||
}
|
||||
@@ -728,6 +730,21 @@ void QETProject::buildFolios(const QList<Diagram *> &folios) const
|
||||
for (Element *elmt : d->elements())
|
||||
if (elmt->keepsSavedLinks())
|
||||
elmt->initLink(self);
|
||||
//A linked folio report's texts show a wire's properties: the
|
||||
//report's own wire, else its partner's. A report built alone
|
||||
//first, as a partner (buildPartnerSymbols()), linked before it had
|
||||
//wires, and a report elsewhere may watch that partner: both look
|
||||
//again now, as opening has them do once every wire exists (an
|
||||
//unlinked report keeps its texts, as opening leaves them)
|
||||
for (Diagram *d : std::as_const(built))
|
||||
for (Element *elmt : d->elements())
|
||||
if ((elmt->linkType() & Element::AllReport) && !elmt->linkedElements().isEmpty())
|
||||
{
|
||||
emit elmt->linkedElementChanged();
|
||||
for (Element *partner : elmt->linkedElements())
|
||||
if (!built.contains(partner->diagram()))
|
||||
emit partner->linkedElementChanged();
|
||||
}
|
||||
//Likewise a table whose previous table was on a folio not built
|
||||
for (Diagram *d : builtFolios())
|
||||
for (QGraphicsItem *item : d->items())
|
||||
@@ -913,6 +930,16 @@ QSet<Diagram *> QETProject::tableChainFolios(Diagram *folio) const
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//Opened from an index: its tables, not the folio's part
|
||||
if (m_index_tables) {
|
||||
for (const projectDataBase::FolioTable &table : std::as_const(*m_index_tables)) {
|
||||
if (table.folio == d->uuid()) {
|
||||
folio_of.insert(table.table, d);
|
||||
previous_of.insert(table.table, table.previous);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const QDomNodeList tables = d->deferredXml().elementsByTagName(
|
||||
QetGraphicsTableItem::xmlTagName());
|
||||
@@ -983,11 +1010,43 @@ void QETProject::buildFolioToShow(Diagram *folio)
|
||||
return;
|
||||
}
|
||||
if (qEnvironmentVariableIntValue("QET_LAZY_FOLIOS_TRACE") == 1) {
|
||||
qWarning().noquote() << "lazy folios:" << to_build.size()
|
||||
<< "folios built for the partners of folio"
|
||||
<< folio->folioIndex() + 1;
|
||||
qWarning().noquote() << "lazy folios: the partners of folio" << folio->folioIndex() + 1
|
||||
<< "built alone, on" << to_build.size() << "folios";
|
||||
}
|
||||
buildFolios(to_build);
|
||||
//The partners alone, not their folios (stage D5b)
|
||||
buildPartnerSymbols(to_build, partners);
|
||||
}
|
||||
|
||||
/**
|
||||
@brief QETProject::buildPartnerSymbols
|
||||
Build on the folios @p folios, not built, the symbols @p partners alone
|
||||
(Diagram::buildSymbols()), as opening builds them: linked to the symbols
|
||||
built already, their texts refreshed, in the state opening has.
|
||||
*/
|
||||
void QETProject::buildPartnerSymbols(const QList<Diagram *> &folios, const QSet<QUuid> &partners)
|
||||
{
|
||||
const ProjectState state = m_state;
|
||||
m_state = ProjectParsingRunning;
|
||||
QList<Element *> built;
|
||||
for (Diagram *d : folios) {
|
||||
const QList<Element *> symbols = d->buildSymbols(partners);
|
||||
if (!symbols.isEmpty()) {
|
||||
built += symbols;
|
||||
linkElementsToElementAutoNums(d);
|
||||
}
|
||||
}
|
||||
for (Element *element : std::as_const(built)) {
|
||||
element->initLink(this);
|
||||
for (auto &text : element->dynamicTextItems())
|
||||
text->refreshLabelConnection();
|
||||
}
|
||||
//A built symbol linked to one of them puts its partners back in
|
||||
//their saved order
|
||||
for (Diagram *d : builtFolios())
|
||||
for (Element *element : d->elements())
|
||||
if (element->keepsSavedLinks())
|
||||
element->initLink(this);
|
||||
m_state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2316,6 +2375,11 @@ QDomDocument QETProject::toXml(QHash<int, QByteArray> *kept_folios, QStringList
|
||||
const bool keep = unloadedFolioCount() && !m_kept_folios_stale
|
||||
&& ((kept_folios && m_kept_folios_trusted) || (kept_parts && m_kept_parts_trusted));
|
||||
if (keep) {
|
||||
//Partners built alone and linked or unlinked since: their folio
|
||||
//is not what was read
|
||||
for (Diagram *diagram : std::as_const(m_diagrams_list))
|
||||
if (!diagram->isLoaded() && diagram->partialChanged())
|
||||
buildFolios({diagram});
|
||||
for (Diagram *diagram : std::as_const(m_diagrams_list))
|
||||
if (diagram->headerChanged())
|
||||
buildFolioToShow(diagram);
|
||||
@@ -2588,10 +2652,27 @@ QByteArray QETProject::containerIndex()
|
||||
seen.insert(uuid);
|
||||
return true;
|
||||
};
|
||||
//The drawn tables and the tables they continue: which folios a
|
||||
//folio's tables are built with (tableChainFolios())
|
||||
QList<projectDataBase::FolioTable> tables;
|
||||
for (Diagram *diagram : std::as_const(m_diagrams_list)) {
|
||||
if (!unique(diagram->uuid())) return QByteArray();
|
||||
if (!diagram->isLoaded()) {
|
||||
headers.append({diagram->uuid(), diagram->headerXml()});
|
||||
if (m_index_tables) {
|
||||
for (const projectDataBase::FolioTable &table : std::as_const(*m_index_tables))
|
||||
if (table.folio == diagram->uuid())
|
||||
tables.append(table);
|
||||
continue;
|
||||
}
|
||||
const QDomNodeList items = diagram->deferredXml().elementsByTagName(
|
||||
QetGraphicsTableItem::xmlTagName());
|
||||
for (int i = 0 ; i < items.size() ; ++i) {
|
||||
const QDomElement table = items.at(i).toElement();
|
||||
tables.append({QUuid(table.attribute(QStringLiteral("uuid"))), diagram->uuid(),
|
||||
QUuid(table.firstChildElement(QStringLiteral("previous_table"))
|
||||
.attribute(QStringLiteral("uuid")))});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
for (Element *element : diagram->elements())
|
||||
@@ -2599,8 +2680,14 @@ QByteArray QETProject::containerIndex()
|
||||
for (Conductor *conductor : diagram->conductors())
|
||||
if (!unique(conductor->uuid())) return QByteArray();
|
||||
headers.append({diagram->uuid(), diagram->headerXml()});
|
||||
for (QGraphicsItem *item : diagram->items()) {
|
||||
if (item->type() == QetGraphicsTableItem::Type) {
|
||||
auto table = static_cast<QetGraphicsTableItem *>(item);
|
||||
tables.append({table->uuid(), diagram->uuid(), table->previousTableUuid()});
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_data_base.indexFile(headers);
|
||||
return m_data_base.indexFile(headers, tables);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3323,7 +3410,10 @@ QDomElement QETProject::readFolioPart(const QString &file)
|
||||
{
|
||||
QDomDocument folio;
|
||||
QString error;
|
||||
if (!QetContainer::readFolio(m_container_files, file, &folio, &error)) {
|
||||
if (!m_folio_reader)
|
||||
m_folio_reader = std::make_unique<QetContainerDb::FolioReader>(
|
||||
m_container_files.value(QStringLiteral("project.sqlite")));
|
||||
if (!QetContainer::readFolio(m_container_files, file, &folio, &error, m_folio_reader.get())) {
|
||||
qWarning().noquote() << "Unable to read the folio" << file << ":" << error;
|
||||
return QDomElement();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user