From c19aecb06d6ead12a2c004c9dabf442c3d9d63fd Mon Sep 17 00:00:00 2001 From: nicogodet Date: Thu, 13 Feb 2025 14:54:17 +0100 Subject: [PATCH 1/2] [gui] Insure modified attribute form properties are stored when switching from one field to another (fixes qgis#60181) Co-authored-by: Mathieu Pellerin --- .../vector/qgsattributesformproperties.cpp | 9 +- src/gui/vector/qgsattributesformproperties.h | 2 + tests/src/gui/CMakeLists.txt | 1 + .../gui/testqgsattributesformproperties.cpp | 90 +++++++++++++++++++ 4 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 tests/src/gui/testqgsattributesformproperties.cpp diff --git a/src/gui/vector/qgsattributesformproperties.cpp b/src/gui/vector/qgsattributesformproperties.cpp index 8a82ab6b7ad1..8c7a27fb2985 100644 --- a/src/gui/vector/qgsattributesformproperties.cpp +++ b/src/gui/vector/qgsattributesformproperties.cpp @@ -618,8 +618,13 @@ void QgsAttributesFormProperties::loadAttributeSpecificEditor( QgsAttributesDnDT const Qgis::AttributeFormLayout layout = mEditorLayoutComboBox->currentData().value(); if ( layout == Qgis::AttributeFormLayout::DragAndDrop ) + { storeAttributeWidgetEdit(); - + } + if ( mAttributeTypeDialog ) + { + storeAttributeTypeDialog(); + } clearAttributeTypeFrame(); if ( emitter->selectedItems().count() != 1 ) @@ -648,7 +653,9 @@ void QgsAttributesFormProperties::loadAttributeSpecificEditor( QgsAttributesDnDT { receiver->selectFirstMatchingItem( itemData ); if ( layout == Qgis::AttributeFormLayout::DragAndDrop ) + { loadAttributeWidgetEdit(); + } loadAttributeTypeDialog(); break; } diff --git a/src/gui/vector/qgsattributesformproperties.h b/src/gui/vector/qgsattributesformproperties.h index 7d3f1170d39e..8be86664a0fb 100644 --- a/src/gui/vector/qgsattributesformproperties.h +++ b/src/gui/vector/qgsattributesformproperties.h @@ -422,6 +422,8 @@ class GUI_EXPORT QgsAttributesFormProperties : public QWidget, public QgsExpress QString mInitFilePath; QString mInitCode; int mBlockUpdates = 0; + + friend class TestQgsAttributesFormProperties; }; diff --git a/tests/src/gui/CMakeLists.txt b/tests/src/gui/CMakeLists.txt index e59701de7af8..8fb6cdf80bf6 100644 --- a/tests/src/gui/CMakeLists.txt +++ b/tests/src/gui/CMakeLists.txt @@ -34,6 +34,7 @@ set(TESTS testqgsdoublespinbox.cpp testqgsdualview.cpp testqgsattributeform.cpp + testqgsattributesformproperties.cpp testqgsdatetimeedit.cpp testqgsdockwidget.cpp testqgsfieldexpressionwidget.cpp diff --git a/tests/src/gui/testqgsattributesformproperties.cpp b/tests/src/gui/testqgsattributesformproperties.cpp new file mode 100644 index 000000000000..f412065141e1 --- /dev/null +++ b/tests/src/gui/testqgsattributesformproperties.cpp @@ -0,0 +1,90 @@ +/*************************************************************************** + testqgsattributesformproperties.cpp + -------------------------------------- + Date : 2025-01-21 + Copyright : (C) 2025 Mathieu Pellerin + Email : paul dot blottiere at oslandia dot com + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + + #include "qgstest.h" + + #include "qgsattributesformproperties.h" + #include "qgsattributetypedialog.h" + #include "qgsvectorlayer.h" + #include "qgsvectordataprovider.h" + #include "qgsgui.h" + + class TestQgsAttributesFormProperties : public QObject + { + Q_OBJECT + public: + TestQgsAttributesFormProperties() = default; + + private slots: + void initTestCase(); // will be called before the first testfunction is executed. + void cleanupTestCase(); // will be called after the last testfunction was executed. + void init(); // will be called before each testfunction is executed. + void cleanup(); // will be called after every testfunction. + + void testConfigStored(); + }; + + void TestQgsAttributesFormProperties::initTestCase() + { + QgsApplication::init(); + QgsApplication::initQgis(); + } + + void TestQgsAttributesFormProperties::cleanupTestCase() + { + QgsApplication::exitQgis(); + } + + void TestQgsAttributesFormProperties::init() + { + } + + void TestQgsAttributesFormProperties::cleanup() + { + } + + void TestQgsAttributesFormProperties::testConfigStored() + { + QgsVectorLayer *layer = new QgsVectorLayer( QStringLiteral( "Point?field=col0:integer&field=col1:integer" ), QStringLiteral( "test" ), QStringLiteral( "memory" ) ); + QgsAttributesFormProperties attributeFormProperties( layer ); + attributeFormProperties.init(); + + // Get the fields + QVERIFY( attributeFormProperties.mAvailableWidgetsTree ); + QTreeWidgetItem *fieldsItem = attributeFormProperties.mAvailableWidgetsTree->topLevelItem( 0 ); + QVERIFY( fieldsItem ); + QCOMPARE( fieldsItem->text( 0 ), QStringLiteral( "Fields" ) ); + QCOMPARE( fieldsItem->childCount(), 2 ); + + // Insure that the configuration was stored when switching from one available widgets tree item to another + attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 0 ) ); + QVERIFY( attributeFormProperties.mAttributeTypeDialog ); + attributeFormProperties.mAttributeTypeDialog->setAlias( QStringLiteral( "alias0" ) ); + attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 1 ) ); + QVERIFY( attributeFormProperties.mAttributeTypeDialog ); + attributeFormProperties.mAttributeTypeDialog->setAlias( QStringLiteral( "alias1" ) ); + + attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 0 ) ); + QVERIFY( attributeFormProperties.mAttributeTypeDialog ); + QCOMPARE( attributeFormProperties.mAttributeTypeDialog->alias(), QStringLiteral( "alias0" ) ); + attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 1 ) ); + QVERIFY( attributeFormProperties.mAttributeTypeDialog ); + QCOMPARE( attributeFormProperties.mAttributeTypeDialog->alias(), QStringLiteral( "alias1" ) ); + } + + QGSTEST_MAIN( TestQgsAttributesFormProperties ) + #include "testqgsattributesformproperties.moc" + \ No newline at end of file From aba51500f7d9ae3890783ab6554682e2027d6ee5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 13 Feb 2025 13:59:27 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../gui/testqgsattributesformproperties.cpp | 145 +++++++++--------- 1 file changed, 72 insertions(+), 73 deletions(-) diff --git a/tests/src/gui/testqgsattributesformproperties.cpp b/tests/src/gui/testqgsattributesformproperties.cpp index f412065141e1..03f70dca01de 100644 --- a/tests/src/gui/testqgsattributesformproperties.cpp +++ b/tests/src/gui/testqgsattributesformproperties.cpp @@ -14,77 +14,76 @@ ***************************************************************************/ - #include "qgstest.h" +#include "qgstest.h" - #include "qgsattributesformproperties.h" - #include "qgsattributetypedialog.h" - #include "qgsvectorlayer.h" - #include "qgsvectordataprovider.h" - #include "qgsgui.h" - - class TestQgsAttributesFormProperties : public QObject - { - Q_OBJECT - public: - TestQgsAttributesFormProperties() = default; - - private slots: - void initTestCase(); // will be called before the first testfunction is executed. - void cleanupTestCase(); // will be called after the last testfunction was executed. - void init(); // will be called before each testfunction is executed. - void cleanup(); // will be called after every testfunction. - - void testConfigStored(); - }; - - void TestQgsAttributesFormProperties::initTestCase() - { - QgsApplication::init(); - QgsApplication::initQgis(); - } - - void TestQgsAttributesFormProperties::cleanupTestCase() - { - QgsApplication::exitQgis(); - } - - void TestQgsAttributesFormProperties::init() - { - } - - void TestQgsAttributesFormProperties::cleanup() - { - } - - void TestQgsAttributesFormProperties::testConfigStored() - { - QgsVectorLayer *layer = new QgsVectorLayer( QStringLiteral( "Point?field=col0:integer&field=col1:integer" ), QStringLiteral( "test" ), QStringLiteral( "memory" ) ); - QgsAttributesFormProperties attributeFormProperties( layer ); - attributeFormProperties.init(); - - // Get the fields - QVERIFY( attributeFormProperties.mAvailableWidgetsTree ); - QTreeWidgetItem *fieldsItem = attributeFormProperties.mAvailableWidgetsTree->topLevelItem( 0 ); - QVERIFY( fieldsItem ); - QCOMPARE( fieldsItem->text( 0 ), QStringLiteral( "Fields" ) ); - QCOMPARE( fieldsItem->childCount(), 2 ); - - // Insure that the configuration was stored when switching from one available widgets tree item to another - attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 0 ) ); - QVERIFY( attributeFormProperties.mAttributeTypeDialog ); - attributeFormProperties.mAttributeTypeDialog->setAlias( QStringLiteral( "alias0" ) ); - attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 1 ) ); - QVERIFY( attributeFormProperties.mAttributeTypeDialog ); - attributeFormProperties.mAttributeTypeDialog->setAlias( QStringLiteral( "alias1" ) ); - - attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 0 ) ); - QVERIFY( attributeFormProperties.mAttributeTypeDialog ); - QCOMPARE( attributeFormProperties.mAttributeTypeDialog->alias(), QStringLiteral( "alias0" ) ); - attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 1 ) ); - QVERIFY( attributeFormProperties.mAttributeTypeDialog ); - QCOMPARE( attributeFormProperties.mAttributeTypeDialog->alias(), QStringLiteral( "alias1" ) ); - } - - QGSTEST_MAIN( TestQgsAttributesFormProperties ) - #include "testqgsattributesformproperties.moc" - \ No newline at end of file +#include "qgsattributesformproperties.h" +#include "qgsattributetypedialog.h" +#include "qgsvectorlayer.h" +#include "qgsvectordataprovider.h" +#include "qgsgui.h" + +class TestQgsAttributesFormProperties : public QObject +{ + Q_OBJECT + public: + TestQgsAttributesFormProperties() = default; + + private slots: + void initTestCase(); // will be called before the first testfunction is executed. + void cleanupTestCase(); // will be called after the last testfunction was executed. + void init(); // will be called before each testfunction is executed. + void cleanup(); // will be called after every testfunction. + + void testConfigStored(); +}; + +void TestQgsAttributesFormProperties::initTestCase() +{ + QgsApplication::init(); + QgsApplication::initQgis(); +} + +void TestQgsAttributesFormProperties::cleanupTestCase() +{ + QgsApplication::exitQgis(); +} + +void TestQgsAttributesFormProperties::init() +{ +} + +void TestQgsAttributesFormProperties::cleanup() +{ +} + +void TestQgsAttributesFormProperties::testConfigStored() +{ + QgsVectorLayer *layer = new QgsVectorLayer( QStringLiteral( "Point?field=col0:integer&field=col1:integer" ), QStringLiteral( "test" ), QStringLiteral( "memory" ) ); + QgsAttributesFormProperties attributeFormProperties( layer ); + attributeFormProperties.init(); + + // Get the fields + QVERIFY( attributeFormProperties.mAvailableWidgetsTree ); + QTreeWidgetItem *fieldsItem = attributeFormProperties.mAvailableWidgetsTree->topLevelItem( 0 ); + QVERIFY( fieldsItem ); + QCOMPARE( fieldsItem->text( 0 ), QStringLiteral( "Fields" ) ); + QCOMPARE( fieldsItem->childCount(), 2 ); + + // Insure that the configuration was stored when switching from one available widgets tree item to another + attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 0 ) ); + QVERIFY( attributeFormProperties.mAttributeTypeDialog ); + attributeFormProperties.mAttributeTypeDialog->setAlias( QStringLiteral( "alias0" ) ); + attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 1 ) ); + QVERIFY( attributeFormProperties.mAttributeTypeDialog ); + attributeFormProperties.mAttributeTypeDialog->setAlias( QStringLiteral( "alias1" ) ); + + attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 0 ) ); + QVERIFY( attributeFormProperties.mAttributeTypeDialog ); + QCOMPARE( attributeFormProperties.mAttributeTypeDialog->alias(), QStringLiteral( "alias0" ) ); + attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 1 ) ); + QVERIFY( attributeFormProperties.mAttributeTypeDialog ); + QCOMPARE( attributeFormProperties.mAttributeTypeDialog->alias(), QStringLiteral( "alias1" ) ); +} + +QGSTEST_MAIN( TestQgsAttributesFormProperties ) +#include "testqgsattributesformproperties.moc"