From b87caa795d4dae8426785fd83a0e21645637161c Mon Sep 17 00:00:00 2001 From: Mathieu Pellerin Date: Sat, 14 Sep 2024 16:32:59 +0700 Subject: [PATCH 1/2] Optimize feature form loading by avoiding cost of loading unavailable editor widget types --- src/core/attributeformmodelbase.cpp | 83 +++++++++++++++++++---------- 1 file changed, 55 insertions(+), 28 deletions(-) diff --git a/src/core/attributeformmodelbase.cpp b/src/core/attributeformmodelbase.cpp index cdb69660f0..ad5fa55167 100644 --- a/src/core/attributeformmodelbase.cpp +++ b/src/core/attributeformmodelbase.cpp @@ -17,6 +17,7 @@ #include "attributeformmodel.h" #include "attributeformmodelbase.h" +#include #include #include #include @@ -34,13 +35,31 @@ #include #include +Q_GLOBAL_STATIC( QStringList, sSupportedEditorWidgets ); AttributeFormModelBase::AttributeFormModelBase( QObject *parent ) : QStandardItemModel( 0, 1, parent ) { connect( QgsProject::instance(), &QgsProject::mapThemeCollectionChanged, this, &AttributeFormModelBase::onMapThemeCollectionChanged ); if ( QgsProject::instance()->mapThemeCollection() ) + { onMapThemeCollectionChanged(); + } + + if ( sSupportedEditorWidgets->isEmpty() ) + { + QDirIterator it( ":qml/editorwidgets" ); + while ( it.hasNext() ) + { + it.next(); + const QFileInfo fileInfo = it.fileInfo(); + if ( fileInfo.isFile() ) + { + sSupportedEditorWidgets->append( fileInfo.baseName() ); + } + } + sSupportedEditorWidgets->append( QStringLiteral( "RelationEditor" ) ); + } } void AttributeFormModelBase::onMapThemeCollectionChanged() @@ -964,60 +983,68 @@ void AttributeFormModelBase::setConstraintsSoftValid( bool constraintsSoftValid QgsEditorWidgetSetup AttributeFormModelBase::findBest( const int fieldIndex ) { QgsFields fields = mLayer->fields(); - - //make the default one - QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( QStringLiteral( "TextEdit" ), QVariantMap() ); - if ( fieldIndex >= 0 && fieldIndex < fields.count() ) { //when field has a configured setup, take it - setup = mLayer->editorWidgetSetup( fieldIndex ); - if ( !setup.isNull() ) - return setup; + QgsEditorWidgetSetup configuredSetup = mLayer->editorWidgetSetup( fieldIndex ); + if ( !configuredSetup.isNull() ) + { + if ( !sSupportedEditorWidgets->contains( configuredSetup.type() ) ) + { + return QgsEditorWidgetSetup( QStringLiteral( "TextEdit" ), QVariantMap() ); + } + return configuredSetup; + } - //when it's a provider field with default value clause, take Textedit + //when it's a provider field with default value clause, take Textedit #if _QGIS_VERSION_INT >= 33800 if ( fields.fieldOrigin( fieldIndex ) == Qgis::FieldOrigin::Provider ) #else if ( fields.fieldOrigin( fieldIndex ) == QgsFields::OriginProvider ) #endif { - int providerOrigin = fields.fieldOriginIndex( fieldIndex ); + const int providerOrigin = fields.fieldOriginIndex( fieldIndex ); if ( !mLayer->dataProvider()->defaultValueClause( providerOrigin ).isEmpty() ) - return setup; + { + return QgsEditorWidgetSetup( QStringLiteral( "TextEdit" ), QVariantMap() ); + } } - //find the best one + if ( !mLayer->referencingRelations( fieldIndex ).isEmpty() ) + { + QgsRelation relation = mLayer->referencingRelations( fieldIndex )[0]; + QVariantMap config; + config.insert( QStringLiteral( "Relation" ), relation.id() ); + config.insert( QStringLiteral( "AllowAddFeatures" ), false ); + config.insert( QStringLiteral( "ShowOpenFormButton" ), true ); + return QgsEditorWidgetSetup( QStringLiteral( "RelationReference" ), config ); + } + + // Find the best one based on field type const QgsField field = fields.at( fieldIndex ); - //on a boolean type take "CheckBox" if ( field.type() == QMetaType::Bool ) - setup = QgsEditorWidgetSetup( QStringLiteral( "CheckBox" ), QVariantMap() ); - //on a date or time type take "DateTime" - if ( field.isDateOrTime() ) { + // on a boolean type, take "CheckBox" + return QgsEditorWidgetSetup( QStringLiteral( "CheckBox" ), QVariantMap() ); + } + else if ( field.isDateOrTime() ) + { + // on a time types, take "DateTime" QVariantMap config; config.insert( QStringLiteral( "field_format" ), QgsDateTimeFieldFormatter::defaultFormat( field.type() ) ); config.insert( QStringLiteral( "display_format" ), QgsDateTimeFieldFormatter::defaultFormat( field.type() ) ); config.insert( QStringLiteral( "calendar_popup" ), true ); config.insert( QStringLiteral( "allow_null" ), true ); - setup = QgsEditorWidgetSetup( QStringLiteral( "DateTime" ), config ); + return QgsEditorWidgetSetup( QStringLiteral( "DateTime" ), config ); } - //on numeric types take "Range" - if ( field.type() == QMetaType::Int || field.type() == QMetaType::Double || field.isNumeric() ) - setup = QgsEditorWidgetSetup( QStringLiteral( "Range" ), QVariantMap() ); - //if it's a foreign key configured in a relation take "RelationReference" - if ( !mLayer->referencingRelations( fieldIndex ).isEmpty() ) + else if ( field.type() == QMetaType::Int || field.type() == QMetaType::Double || field.isNumeric() ) { - QgsRelation relation = mLayer->referencingRelations( fieldIndex )[0]; - QVariantMap config; - config.insert( QStringLiteral( "Relation" ), relation.id() ); - config.insert( QStringLiteral( "AllowAddFeatures" ), false ); - config.insert( QStringLiteral( "ShowOpenFormButton" ), true ); - setup = QgsEditorWidgetSetup( QStringLiteral( "RelationReference" ), config ); + // on numeric types, take "Range" + return QgsEditorWidgetSetup( QStringLiteral( "Range" ), QVariantMap() ); } } - return setup; + return QgsEditorWidgetSetup( QStringLiteral( "TextEdit" ), QVariantMap() ); } bool AttributeFormModelBase::hasTabs() const From 3e7220e54ae861390531cb31aed6d38c29ed142c Mon Sep 17 00:00:00 2001 From: Mathieu Pellerin Date: Sat, 14 Sep 2024 18:08:23 +0700 Subject: [PATCH 2/2] Micro optimization: insure the height of feature form containers non-zero when the item is loaded --- src/qml/FeatureForm.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qml/FeatureForm.qml b/src/qml/FeatureForm.qml index 1a1d4c54cb..87caaaf9fe 100644 --- a/src/qml/FeatureForm.qml +++ b/src/qml/FeatureForm.qml @@ -453,7 +453,7 @@ Page { property string itemType: Type active: (Type === 'container' && GroupIndex !== undefined && GroupIndex.valid) || ((Type === 'text' || Type === 'html' || Type === 'qml') && form.model.featureModel.modelMode != FeatureModel.MultiFeatureModel) - height: active ? item.childrenRect.height : 0 + height: status == Loader.Ready ? item.childrenRect.height : 0 anchors { left: parent.left right: parent.right