From 44c96a4c95f33c4f4043c18ab2eda39ebc11ff9d Mon Sep 17 00:00:00 2001 From: ispyisail Date: Fri, 23 Oct 2026 07:26:45 +1300 Subject: [PATCH] Move a folio's number and total through the project database QETZ-DB-FIRST 2d-1: the first sub-stage of 2d (QETZ-DB-FIRST-2D-SCOPE.md). A folio's 1-based position among the project's folios, and the project's folio count, were purely computed on the fly from QETProject's live m_diagrams_list (QETProject::folioIndex(), updateDiagramsFolioData()) and cached only as BorderTitleBlock's own folio_index_/folio_total_ members -- never in projectDataBase, so nothing could query a folio's number without walking the live project. Add a folio_number table (diagram_uuid, folio_index, folio_total), written through from two places: BorderTitleBlock::setFolioData() (every live folio add/remove/reorder, same point that already sets the members), and projectDataBase::populateFromDocument() (straight from the document for a folio not yet built, same habit as folio_titleblock/folio_border). Added BorderTitleBlock::folioIndex() as a public getter alongside the existing folioTotal(), both now reading the store first like the other title-block and border accessors added in stage 2c. Co-Authored-By: Claude Sonnet 5 --- sources/bordertitleblock.cpp | 29 +++++++++++ sources/bordertitleblock.h | 10 +++- sources/dataBase/projectdatabase.cpp | 72 ++++++++++++++++++++++++++++ sources/dataBase/projectdatabase.h | 8 ++++ 4 files changed, 117 insertions(+), 2 deletions(-) diff --git a/sources/bordertitleblock.cpp b/sources/bordertitleblock.cpp index 380b034e8..fcc221161 100644 --- a/sources/bordertitleblock.cpp +++ b/sources/bordertitleblock.cpp @@ -357,6 +357,19 @@ const BorderProperties *BorderTitleBlock::storedBorder() const return nullptr; } +/** + @brief BorderTitleBlock::storedFolioNumber + @param index set to the stored folio index, when found + @param total set to the stored folio total, when found + @return whether the project's store holds a number for this folio +*/ +bool BorderTitleBlock::storedFolioNumber(int *index, int *total) const +{ + if (projectDataBase *store = placedStore()) + return store->storedFolioNumber(m_owner_folio->uuid(), index, total); + return false; +} + /** @brief BorderTitleBlock::setOwnerFolio @param folio : the folio this border and title block belongs to @@ -401,6 +414,21 @@ void BorderTitleBlock::storeBorder() store->storeFolioBorder(m_owner_folio->uuid(), exportBorder()); } +/** + @brief BorderTitleBlock::storeFolioNumber + Write this folio's index and total to its project's store, once its + folio is placed: every change of them comes through here. +*/ +void BorderTitleBlock::storeFolioNumber() +{ + //Read the members directly, not the getters: the getters check the + //store first, which this call is about to update -- going through + //them here would echo back the old stored value instead of the new + //one, the same trap storeBorder() avoids with exportBorder(). + if (projectDataBase *store = placedStore()) + store->storeFolioNumber(m_owner_folio->uuid(), folio_index_, folio_total_); +} + /** @brief BorderTitleBlock::importTitleBlock @param ip the new properties of titleblock @@ -1178,6 +1206,7 @@ void BorderTitleBlock::setFolioData( } btb_final_folio_.replace("%id", QString::number(folio_index_)); btb_final_folio_.replace("%total", QString::number(folio_total_)); + storeFolioNumber(); updateDiagramContextForTitleBlock(project_properties); } diff --git a/sources/bordertitleblock.h b/sources/bordertitleblock.h index e25a77ed1..2c3b9fbe1 100644 --- a/sources/bordertitleblock.h +++ b/sources/bordertitleblock.h @@ -141,8 +141,12 @@ class BorderTitleBlock : public QObject /// The title of the folio numbering this folio follows, nothing else changes void setAutoPageNum(const QString &title); /// @return the value of the total number of folios - int folioTotal() const { return(folio_total_);} - + int folioTotal() const { + int index, total; return(storedFolioNumber(&index, &total) ? total : folio_total_);} + /// @return this folio's 1-based position among the project's folios + int folioIndex() const { + int index, total; return(storedFolioNumber(&index, &total) ? index : folio_index_);} + // methods to get display options /// @return true si le cartouche est affiche, false sinon bool titleBlockIsDisplayed() const { @@ -300,8 +304,10 @@ class BorderTitleBlock : public QObject TitleBlockProperties current() const; const TitleBlockProperties *stored() const; const BorderProperties *storedBorder() const; + bool storedFolioNumber(int *index, int *total) const; projectDataBase *placedStore() const; void storeTitleBlock(); void storeBorder(); + void storeFolioNumber(); }; #endif diff --git a/sources/dataBase/projectdatabase.cpp b/sources/dataBase/projectdatabase.cpp index 8457febca..827b0df06 100644 --- a/sources/dataBase/projectdatabase.cpp +++ b/sources/dataBase/projectdatabase.cpp @@ -519,6 +519,11 @@ bool projectDataBase::populateFromDocument(const QDomDocument &document, QString return refuse(QStringLiteral("a folio number uses %autonum")); } border->setFolioData(i + 1, int(diagram_nodes.size()), QString(), project_wide); + //setFolioData() only writes through the store for a placed + //folio (reader isn't one); store it here too, straight from + //the document (habit 4), so a folio not yet built still has + //its number queryable. + storeFolioNumber(diagram_uuid, i + 1, int(diagram_nodes.size())); //What a formula on this folio is worked out from, as //AssignVariables::formulaToLabel() reads it off a built folio. @@ -2684,6 +2689,19 @@ bool projectDataBase::createDataBase() qDebug() << " folio_border_table query : " << query_.lastError(); } + //Create the folio_number table: a folio's 1-based position among + //the project's folios and the project's folio count, recomputed + //whenever a folio is added, removed or reordered + //(QETProject::updateDiagramsFolioData()), the store each folio's + //number is written through (storeFolioNumber()). One row per folio. + if (!query_.exec(QStringLiteral( + "CREATE TABLE folio_number (" + "diagram_uuid VARCHAR(50) PRIMARY KEY NOT NULL, " + "folio_index INTEGER NOT NULL, " + "folio_total INTEGER NOT NULL)"))) { + qDebug() << " folio_number_table query : " << query_.lastError(); + } + //Create the conductor_properties table: the properties of every //wire placed in the project, as the attributes a saved wire carries, //the store wires write through (storeConductorProperties()). @@ -3647,6 +3665,53 @@ void projectDataBase::storeFolioBorder(const QUuid &folio, const BorderPropertie } } +/** + @brief projectDataBase::storedFolioNumber + @param index set to the stored folio index, when found + @param total set to the stored folio total, when found + @return whether the folio @p folio has a stored number +*/ +bool projectDataBase::storedFolioNumber(const QUuid &folio, int *index, int *total) const +{ + auto it = m_folio_numbers.constFind(folio); + if (it == m_folio_numbers.constEnd()) return false; + if (index) *index = it.value().first; + if (total) *total = it.value().second; + return true; +} + +/** + @brief projectDataBase::storeFolioNumber + Store @p index and @p total as the number of the folio @p folio, in + the folio_number table and the cache in front of it. +*/ +void projectDataBase::storeFolioNumber(const QUuid &folio, int index, int total) +{ + if (folio.isNull()) return; + const QPair value(index, total); + auto known = m_folio_numbers.find(folio); + if (known != m_folio_numbers.end() && *known == value) return; + m_folio_numbers.insert(folio, value); + + const QString uuid = folio.toString(); + QSqlQuery remove(m_data_base); + remove.prepare(QStringLiteral("DELETE FROM folio_number WHERE diagram_uuid = :uuid")); + remove.bindValue(QStringLiteral(":uuid"), uuid); + if (!remove.exec()) { + qDebug() << "projectDataBase::storeFolioNumber remove error : " << remove.lastError(); + } + QSqlQuery insert(m_data_base); + insert.prepare(QStringLiteral( + "INSERT INTO folio_number (diagram_uuid, folio_index, folio_total) " + "VALUES (:uuid, :idx, :tot)")); + insert.bindValue(QStringLiteral(":uuid"), uuid); + insert.bindValue(QStringLiteral(":idx"), index); + insert.bindValue(QStringLiteral(":tot"), total); + if (!insert.exec()) { + qDebug() << "projectDataBase::storeFolioNumber insert error : " << insert.lastError(); + } +} + /** @brief projectDataBase::placeFolio @p folio is now a folio of the project: its title block and border are @@ -3682,6 +3747,13 @@ void projectDataBase::unplaceFolio(Diagram *folio, const QUuid &uuid) if (!remove_border.exec()) { qDebug() << "projectDataBase::unplaceFolio border error : " << remove_border.lastError(); } + m_folio_numbers.remove(uuid); + QSqlQuery remove_number(m_data_base); + remove_number.prepare(QStringLiteral("DELETE FROM folio_number WHERE diagram_uuid = :uuid")); + remove_number.bindValue(QStringLiteral(":uuid"), uuid.toString()); + if (!remove_number.exec()) { + qDebug() << "projectDataBase::unplaceFolio number error : " << remove_number.lastError(); + } } /** diff --git a/sources/dataBase/projectdatabase.h b/sources/dataBase/projectdatabase.h index 8408ca351..5ec7cace0 100644 --- a/sources/dataBase/projectdatabase.h +++ b/sources/dataBase/projectdatabase.h @@ -154,6 +154,13 @@ class projectDataBase : public QObject const BorderProperties *storedFolioBorder(const QUuid &folio) const; void storeFolioBorder(const QUuid &folio, const BorderProperties &properties); + //The folio number and total folio count of every folio of the + //project, by folio uuid: recomputed whenever a folio is added, + //removed or reordered (QETProject::updateDiagramsFolioData()), + //the store each folio's number is written through. + bool storedFolioNumber(const QUuid &folio, int *index, int *total) const; + void storeFolioNumber(const QUuid &folio, int index, int total); + //The properties of every wire placed in the project, by wire //uuid: the store each wire's properties are written through //A wire not placed keeps its own. @@ -430,6 +437,7 @@ class projectDataBase : public QObject QHash m_unbuilt_wire_edits; QHash m_folio_titleblocks; QHash m_folio_borders; + QHash> m_folio_numbers; // index, total QHash> m_placed_folios; QHash m_conductor_properties; //The rows of conductor_properties, to write only what changes