From 82fc56c5e675d112d89c4aafdd250219715cad1a Mon Sep 17 00:00:00 2001 From: ispyisail Date: Fri, 2 Oct 2026 21:04:54 +1300 Subject: [PATCH] Fix Project properties > OK marking the project modified with no edit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pressing OK in Projet > Propriétés du projet without changing anything marked the project modified and rewrote its defaults for new folios. Besides the Page Num placeholder (fixed separately), four causes: - Title block custom fields: since #271 the dialog offers the template's variables for filling in; those left empty came back as part of the context. Drop the ones not in the stored context. - DiagramContext::remove() left the key's show flag behind, so a context with a key removed never equalled one without it. - Guides: applyConf() marked the project modified whether or not the guides changed. Compare them like every other setting. - Wire dash size and cross-reference offsets: the spin boxes cannot show the stored default (dash size 1 under a minimum of 2; offset 0 under a minimum of 40 shown as "Default"), so the clamped value came back. Keep the stored value unless the box shows something else, as #1204 did for the wire panel. Checked in the GUI (with the Page Num fix as well) on grafcet, schema_indus and Projet_vierge: OK with no edit then Ctrl+S saves the same file as Ctrl+S alone; master writes dash-size 1 -> 2, a cross-reference offset 0 -> 40, and on Projet_vierge 22 empty custom fields. New test for DiagramContext::remove() fails without the fix. Co-Authored-By: Claude Opus 5.5 (1M context) --- sources/diagramcontext.cpp | 1 + sources/ui/conductorpropertieswidget.cpp | 6 ++++++ sources/ui/configpage/configpages.cpp | 6 ++++-- sources/ui/titleblockpropertieswidget.cpp | 9 +++++++++ sources/ui/titleblockpropertieswidget.h | 2 ++ sources/ui/xrefpropertieswidget.cpp | 11 +++++++++-- tests/qttest/tst_diagramcontext.cpp | 18 ++++++++++++++++++ 7 files changed, 49 insertions(+), 4 deletions(-) diff --git a/sources/diagramcontext.cpp b/sources/diagramcontext.cpp index 94b8696a2..b6228e36e 100644 --- a/sources/diagramcontext.cpp +++ b/sources/diagramcontext.cpp @@ -42,6 +42,7 @@ void DiagramContext::add(DiagramContext other) */ void DiagramContext::remove(const QString &key) { m_content.remove(key); + m_content_show.remove(key); } /** diff --git a/sources/ui/conductorpropertieswidget.cpp b/sources/ui/conductorpropertieswidget.cpp index d8e3e57a6..d203880a1 100644 --- a/sources/ui/conductorpropertieswidget.cpp +++ b/sources/ui/conductorpropertieswidget.cpp @@ -126,6 +126,12 @@ ConductorProperties ConductorPropertiesWidget::properties() const properties_.m_bicolor = ui->m_color_2_gb->isChecked(); properties_.m_color_2 = ui->m_color_2_kpb->color(); properties_.m_dash_size = ui->m_dash_size_sb->value(); + //The box starts at 2, so the default size 1 shows as 2: keep the + //stored size unless the box shows something else. + if (properties_.m_dash_size == qBound(ui->m_dash_size_sb->minimum(), + m_properties.m_dash_size, + ui->m_dash_size_sb->maximum())) + properties_.m_dash_size = m_properties.m_dash_size; properties_.style = ui -> m_line_style_cb->itemData(ui->m_line_style_cb->currentIndex()).value().style(); properties_.m_formula = ui->m_formula_le->text(); properties_.text = ui -> m_text_le -> text(); diff --git a/sources/ui/configpage/configpages.cpp b/sources/ui/configpage/configpages.cpp index 7c2db969d..b9ac8562c 100644 --- a/sources/ui/configpage/configpages.cpp +++ b/sources/ui/configpage/configpages.cpp @@ -233,8 +233,10 @@ void NewDiagramPage::applyConf() pg.color = g.color; proj_guides.append(pg); } - m_project->setDefaultGuides(proj_guides); - modified_project = true; + if (m_project->defaultGuides() != proj_guides) { + m_project->setDefaultGuides(proj_guides); + modified_project = true; + } if (modified_project) { m_project -> setModified(modified_project); diff --git a/sources/ui/titleblockpropertieswidget.cpp b/sources/ui/titleblockpropertieswidget.cpp index 929b557c2..ac1d92bb2 100644 --- a/sources/ui/titleblockpropertieswidget.cpp +++ b/sources/ui/titleblockpropertieswidget.cpp @@ -166,6 +166,7 @@ void TitleBlockPropertiesWidget::setProperties( // Show the saved custom values, plus any of the template's custom variables // that aren't defined yet, so the user only fills in the missing ones (#271). DiagramContext context = properties.context; + m_context_keys = context.keys(); addTemplateVariables(context, index); m_dcw -> setContext(context); } @@ -215,6 +216,14 @@ TitleBlockProperties TitleBlockPropertiesWidget::properties() const } prop.context = m_dcw -> context(); + //The template's custom variables are only offered for filling in + //(#271): one left empty is not part of the properties. + const QList keys = prop.context.keys(); + for (const QString &key : keys) { + if (!m_context_keys.contains(key) + && prop.context.value(key).toString().isEmpty()) + prop.context.remove(key); + } prop.auto_page_num = ui->auto_page_cb->currentText(); diff --git a/sources/ui/titleblockpropertieswidget.h b/sources/ui/titleblockpropertieswidget.h index 0622da8a5..58ec00be7 100644 --- a/sources/ui/titleblockpropertieswidget.h +++ b/sources/ui/titleblockpropertieswidget.h @@ -100,6 +100,8 @@ class TitleBlockPropertiesWidget : public QWidget private: Ui::TitleBlockPropertiesWidget *ui; DiagramContextWidget *m_dcw; + /// keys of the context given to setProperties() + QStringList m_context_keys; QAction *m_tbt_edit, *m_tbt_duplicate; QMenu *m_tbt_menu; QList m_tbt_collection_list; diff --git a/sources/ui/xrefpropertieswidget.cpp b/sources/ui/xrefpropertieswidget.cpp index c113eda45..d08c8d5c7 100644 --- a/sources/ui/xrefpropertieswidget.cpp +++ b/sources/ui/xrefpropertieswidget.cpp @@ -151,8 +151,15 @@ void XRefPropertiesWidget::saveProperties(int index) { xrp.setPrefix("switch", ui->m_switch_prefix_le->text()); xrp.setMasterLabel(ui->m_master_le->text()); xrp.setSlaveLabel(ui->m_slave_le->text()); - xrp.setOffset(ui->m_offset_sb->value()); - xrp.setSlaveOffset(ui->m_slave_offset_sb->value()); + //The boxes cannot show a value below their minimum (the offset's + //minimum is its "Default" entry, standing for the stored 0): keep + //the stored value unless the box shows something else. + if (ui->m_offset_sb->value() != qBound(ui->m_offset_sb->minimum(), xrp.offset(), + ui->m_offset_sb->maximum())) + xrp.setOffset(ui->m_offset_sb->value()); + if (ui->m_slave_offset_sb->value() != qBound(ui->m_slave_offset_sb->minimum(), xrp.slaveOffset(), + ui->m_slave_offset_sb->maximum())) + xrp.setSlaveOffset(ui->m_slave_offset_sb->value()); m_properties.insert(type, xrp); } diff --git a/tests/qttest/tst_diagramcontext.cpp b/tests/qttest/tst_diagramcontext.cpp index f0e004b0d..640dee9e7 100644 --- a/tests/qttest/tst_diagramcontext.cpp +++ b/tests/qttest/tst_diagramcontext.cpp @@ -65,6 +65,24 @@ private slots: QCOMPARE(fromDom(xml(value)), expected); QCOMPARE(fromPugi(xml(value)), expected); } + + // remove() forgets the key entirely: a context with a key added + // then removed equals one that never had it. remove() used to keep + // the key's show flag, so the two never compared equal, and + // Project properties > OK saw a change where there was none. + void removeForgetsTheKey() + { + DiagramContext edited; + edited.addValue(QStringLiteral("author"), QStringLiteral("N.V.")); + edited.addValue(QStringLiteral("01-numprojet"), QString()); + edited.remove(QStringLiteral("01-numprojet")); + + DiagramContext stored; + stored.addValue(QStringLiteral("author"), QStringLiteral("N.V.")); + + QCOMPARE(edited.keys(), stored.keys()); + QVERIFY(edited == stored); + } }; QTEST_APPLESS_MAIN(tst_diagramcontext)