Move a folio's border dimensions into the project database

Adds a folio_border table and wires BorderTitleBlock's column/row
grid (counts, widths, header sizes, display flags) through it, the
same way folio_titleblock already covers the title block itself.
Closes the one gap DB-ACCESSORS 4.6 found still living only in the
folio's own XML.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-10-22 22:55:34 +13:00
parent b98193dbe2
commit 489676b155
4 changed files with 151 additions and 25 deletions
+49 -10
View File
@@ -345,6 +345,18 @@ const TitleBlockProperties *BorderTitleBlock::stored() const
return nullptr;
}
/**
@brief BorderTitleBlock::storedBorder
@return the properties the project's store holds for this folio's
border, or nullptr if it is not placed.
*/
const BorderProperties *BorderTitleBlock::storedBorder() const
{
if (projectDataBase *store = placedStore())
return store->storedFolioBorder(m_owner_folio->uuid());
return nullptr;
}
/**
@brief BorderTitleBlock::setOwnerFolio
@param folio : the folio this border and title block belongs to
@@ -378,6 +390,17 @@ void BorderTitleBlock::storeTitleBlock()
store->storeFolioTitleBlock(m_owner_folio->uuid(), localTitleBlock());
}
/**
@brief BorderTitleBlock::storeBorder
Write this folio's border properties to its project's store, once its
folio is placed: every change of them comes through here.
*/
void BorderTitleBlock::storeBorder()
{
if (projectDataBase *store = placedStore())
store->storeFolioBorder(m_owner_folio->uuid(), exportBorder());
}
/**
@brief BorderTitleBlock::importTitleBlock
@param ip the new properties of titleblock
@@ -418,15 +441,19 @@ void BorderTitleBlock::importTitleBlock(const TitleBlockProperties &ip)
*/
BorderProperties BorderTitleBlock::exportBorder()
{
//Read the members directly, not the getters: a folio placed in a
//project reads those back from the store, which storeBorder() is
//about to update from this very value -- going through them here
//would echo back the old stored value instead of the new one.
BorderProperties bp;
bp.columns_count = columnsCount();
bp.columns_width = columnsWidth();
bp.columns_header_height = columnsHeaderHeight();
bp.display_columns = columnsAreDisplayed();
bp.rows_count = rowsCount();
bp.rows_height = rowsHeight();
bp.rows_header_width = rowsHeaderWidth();
bp.display_rows = rowsAreDisplayed();
bp.columns_count = columns_count_;
bp.columns_width = columns_width_;
bp.columns_header_height = columns_header_height_;
bp.display_columns = display_columns_;
bp.rows_count = rows_count_;
bp.rows_height = rows_height_;
bp.rows_header_width = rows_header_width_;
bp.display_rows = display_rows_;
return(bp);
}
@@ -530,7 +557,10 @@ void BorderTitleBlock::displayTitleBlock(bool di) {
void BorderTitleBlock::displayColumns(bool dc) {
bool change = (dc != display_columns_);
display_columns_ = dc;
if (change) emit(displayChanged());
if (change) {
storeBorder();
emit(displayChanged());
}
}
/**
@@ -541,7 +571,10 @@ void BorderTitleBlock::displayColumns(bool dc) {
void BorderTitleBlock::displayRows(bool dr) {
bool change = (dr != display_rows_);
display_rows_ = dr;
if (change) emit(displayChanged());
if (change) {
storeBorder();
emit(displayChanged());
}
}
/**
@@ -831,6 +864,7 @@ void BorderTitleBlock::setColumnsCount(int nb_c) {
if (nb_c == columnsCount()) return;
columns_count_ = qMax(MIN_COLUMN_COUNT , nb_c);
updateRectangles();
storeBorder();
}
/**
@@ -850,6 +884,7 @@ void BorderTitleBlock::setColumnsWidth(const qreal &new_cw) {
if (new_cw == columnsWidth()) return;
columns_width_ = qMax(MIN_COLUMN_WIDTH , new_cw);
updateRectangles();
storeBorder();
}
/**
@@ -865,6 +900,7 @@ void BorderTitleBlock::setColumnsWidth(const qreal &new_cw) {
void BorderTitleBlock::setColumnsHeaderHeight(const qreal &new_chh) {
columns_header_height_ = qBound(qreal(5.0), new_chh, qreal(50.0));
updateRectangles();
storeBorder();
}
/**
@@ -884,6 +920,7 @@ void BorderTitleBlock::setRowsCount(int nb_r) {
if (nb_r == rowsCount()) return;
rows_count_ = qMax(MIN_ROW_COUNT, nb_r);
updateRectangles();
storeBorder();
}
/**
@@ -903,6 +940,7 @@ void BorderTitleBlock::setRowsHeight(const qreal &new_rh) {
if (new_rh == rowsHeight()) return;
rows_height_ = qMax(MIN_ROW_HEIGHT, new_rh);
updateRectangles();
storeBorder();
}
/**
@@ -918,6 +956,7 @@ void BorderTitleBlock::setRowsHeight(const qreal &new_rh) {
void BorderTitleBlock::setRowsHeaderWidth(const qreal &new_rhw) {
rows_header_width_ = qBound(qreal(5.0), new_rhw, qreal(50.0));
updateRectangles();
storeBorder();
}
/**
+15 -12
View File
@@ -52,29 +52,30 @@ class BorderTitleBlock : public QObject
void draw(QPainter *painter);
void drawDxf(QString &, int);
//METHODS TO GET DIMENSION
//METHODS TO GET DIMENSION. A folio placed in a project reads them
//from the project's store, any other from its own copy.
//COLUMNS
/// @return the number of columns
int columnsCount() const { return(columns_count_); }
int columnsCount() const { const BorderProperties *s = storedBorder(); return(s ? s->columns_count : columns_count_); }
/// @return the columns width, in pixels
qreal columnsWidth() const { return(columns_width_); }
qreal columnsWidth() const { const BorderProperties *s = storedBorder(); return(s ? s->columns_width : columns_width_); }
/// @return the total width of all columns, headers excluded
qreal columnsTotalWidth() const {
return(columns_count_ * columns_width_); }
return(columnsCount() * columnsWidth()); }
/// @return the column headers height, in pixels
qreal columnsHeaderHeight() const {
return(columns_header_height_); }
const BorderProperties *s = storedBorder(); return(s ? s->columns_header_height : columns_header_height_); }
//ROWS
/// @return the number of rows
int rowsCount() const { return(rows_count_); }
int rowsCount() const { const BorderProperties *s = storedBorder(); return(s ? s->rows_count : rows_count_); }
/// @return the rows height, in pixels
qreal rowsHeight() const { return(rows_height_); }
qreal rowsHeight() const { const BorderProperties *s = storedBorder(); return(s ? s->rows_height : rows_height_); }
/// @return the total height of all rows, headers excluded
qreal rowsTotalHeight() const {
return(rows_count_ * rows_height_); }
return(rowsCount() * rowsHeight()); }
/// @return la rows header width, in pixels
qreal rowsHeaderWidth() const { return(rows_header_width_); }
qreal rowsHeaderWidth() const { const BorderProperties *s = storedBorder(); return(s ? s->rows_header_width : rows_header_width_); }
/// @return the edge where title block is docked
Qt::Edge titleBlockEdge() const { return(m_edge); }
@@ -148,10 +149,10 @@ class BorderTitleBlock : public QObject
return(display_titleblock_); }
/// @return true si les entetes des colonnes sont affiches,
/// false sinon
bool columnsAreDisplayed() const { return(display_columns_); }
bool columnsAreDisplayed() const { const BorderProperties *s = storedBorder(); return(s ? s->display_columns : display_columns_); }
/// @return true si les entetes des lignes sont affiches,
/// false sinon
bool rowsAreDisplayed() const { return(display_rows_); }
bool rowsAreDisplayed() const { const BorderProperties *s = storedBorder(); return(s ? s->display_rows : display_rows_); }
/// @return true si la bordure est affichee, false sinon
bool borderIsDisplayed() const { return(display_border_); }
@@ -298,7 +299,9 @@ class BorderTitleBlock : public QObject
Diagram *m_owner_folio = nullptr;
TitleBlockProperties current() const;
const TitleBlockProperties *stored() const;
const BorderProperties *storedBorder() const;
projectDataBase *placedStore() const;
void storeTitleBlock();
void storeBorder();
};
#endif
+79 -3
View File
@@ -2666,6 +2666,24 @@ bool projectDataBase::createDataBase()
qDebug() << " folio_titleblock_table query : " << query_.lastError();
}
//Create the folio_border table: the border/grid dimensions of
//every folio (the column/row reference grid, e.g. "A1", "B2"), the
//store each folio's border is written through
//(storeFolioBorder()). One row per folio.
if (!query_.exec(QStringLiteral(
"CREATE TABLE folio_border ("
"diagram_uuid VARCHAR(50) PRIMARY KEY NOT NULL, "
"columns_count INTEGER NOT NULL, "
"columns_width REAL NOT NULL, "
"columns_header_height REAL NOT NULL, "
"display_columns INTEGER NOT NULL, "
"rows_count INTEGER NOT NULL, "
"rows_height REAL NOT NULL, "
"rows_header_width REAL NOT NULL, "
"display_rows INTEGER NOT NULL)"))) {
qDebug() << " folio_border_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()).
@@ -3579,33 +3597,91 @@ void projectDataBase::storeFolioTitleBlock(const QUuid &folio, const TitleBlockP
}
}
/**
@brief projectDataBase::storedFolioBorder
@return the stored border properties of the folio @p folio, or nullptr;
valid until the store next changes
*/
const BorderProperties *projectDataBase::storedFolioBorder(const QUuid &folio) const
{
auto it = m_folio_borders.constFind(folio);
return it == m_folio_borders.constEnd() ? nullptr : &it.value();
}
/**
@brief projectDataBase::storeFolioBorder
Store @p properties as the border of the folio @p folio, in the
folio_border table and the cache in front of it.
*/
void projectDataBase::storeFolioBorder(const QUuid &folio, const BorderProperties &properties)
{
if (folio.isNull()) return;
auto known = m_folio_borders.find(folio);
if (known != m_folio_borders.end() && *known == properties) return;
m_folio_borders.insert(folio, properties);
const QString uuid = folio.toString();
QSqlQuery remove(m_data_base);
remove.prepare(QStringLiteral("DELETE FROM folio_border WHERE diagram_uuid = :uuid"));
remove.bindValue(QStringLiteral(":uuid"), uuid);
if (!remove.exec()) {
qDebug() << "projectDataBase::storeFolioBorder remove error : " << remove.lastError();
}
QSqlQuery insert(m_data_base);
insert.prepare(QStringLiteral(
"INSERT INTO folio_border (diagram_uuid, columns_count, columns_width, "
"columns_header_height, display_columns, rows_count, rows_height, "
"rows_header_width, display_rows) VALUES (:uuid, :cc, :cw, :chh, :dc, "
":rc, :rh, :rhw, :dr)"));
insert.bindValue(QStringLiteral(":uuid"), uuid);
insert.bindValue(QStringLiteral(":cc"), properties.columns_count);
insert.bindValue(QStringLiteral(":cw"), properties.columns_width);
insert.bindValue(QStringLiteral(":chh"), properties.columns_header_height);
insert.bindValue(QStringLiteral(":dc"), properties.display_columns ? 1 : 0);
insert.bindValue(QStringLiteral(":rc"), properties.rows_count);
insert.bindValue(QStringLiteral(":rh"), properties.rows_height);
insert.bindValue(QStringLiteral(":rhw"), properties.rows_header_width);
insert.bindValue(QStringLiteral(":dr"), properties.display_rows ? 1 : 0);
if (!insert.exec()) {
qDebug() << "projectDataBase::storeFolioBorder insert error : " << insert.lastError();
}
}
/**
@brief projectDataBase::placeFolio
@p folio is now a folio of the project: its title block is stored under
its uuid.
@p folio is now a folio of the project: its title block and border are
stored under its uuid.
*/
void projectDataBase::placeFolio(Diagram *folio)
{
m_placed_folios.insert(folio->uuid(), folio);
storeFolioTitleBlock(folio->uuid(), folio->border_and_titleblock.localTitleBlock());
storeFolioBorder(folio->uuid(), folio->border_and_titleblock.exportBorder());
}
/**
@brief projectDataBase::unplaceFolio
@p folio no longer holds @p uuid (it was removed, or its uuid changed):
the title block stored under it goes.
the title block and border stored under it go.
*/
void projectDataBase::unplaceFolio(Diagram *folio, const QUuid &uuid)
{
if (m_placed_folios.value(uuid) != folio) return;
m_placed_folios.remove(uuid);
m_folio_titleblocks.remove(uuid);
m_folio_borders.remove(uuid);
QSqlQuery remove(m_data_base);
remove.prepare(QStringLiteral("DELETE FROM folio_titleblock WHERE diagram_uuid = :uuid"));
remove.bindValue(QStringLiteral(":uuid"), uuid.toString());
if (!remove.exec()) {
qDebug() << "projectDataBase::unplaceFolio error : " << remove.lastError();
}
QSqlQuery remove_border(m_data_base);
remove_border.prepare(QStringLiteral("DELETE FROM folio_border WHERE diagram_uuid = :uuid"));
remove_border.bindValue(QStringLiteral(":uuid"), uuid.toString());
if (!remove_border.exec()) {
qDebug() << "projectDataBase::unplaceFolio border error : " << remove_border.lastError();
}
}
/**
+8
View File
@@ -34,6 +34,7 @@
#include "../diagramcontext.h"
#include "../titleblockproperties.h"
#include "../borderproperties.h"
#include "../conductorproperties.h"
#include "../autoNum/assignvariables.h"
#include "../autoNum/numerotationcontext.h"
@@ -147,6 +148,12 @@ class projectDataBase : public QObject
void folioUuidChanged(Diagram *folio, const QUuid &old_uuid);
QStringList folioTitleBlockMismatches() const;
//The border properties of every folio of the project, by folio
//uuid: the store each folio's border is written through. A
//folio not in a project keeps its own.
const BorderProperties *storedFolioBorder(const QUuid &folio) const;
void storeFolioBorder(const QUuid &folio, const BorderProperties &properties);
//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.
@@ -422,6 +429,7 @@ class projectDataBase : public QObject
struct UnbuiltWireEdit { ConductorProperties properties; QUuid folio; };
QHash<QUuid, UnbuiltWireEdit> m_unbuilt_wire_edits;
QHash<QUuid, TitleBlockProperties> m_folio_titleblocks;
QHash<QUuid, BorderProperties> m_folio_borders;
QHash<QUuid, QPointer<Diagram>> m_placed_folios;
QHash<QUuid, ConductorProperties> m_conductor_properties;
//The rows of conductor_properties, to write only what changes