| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744 |
- /***************************************************************************
- attributeformmodelbase.cpp - AttributeFormModelBase
- ---------------------
- begin : 16.8.2016
- copyright : (C) 2016 by Matthias Kuhn
- email : matthias@opengis.ch
- ***************************************************************************
- * *
- * 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 "attributeformmodel.h"
- #include "attributeformmodelbase.h"
- #include <QRegularExpression>
- #include <qgsattributeeditorcontainer.h>
- #include <qgsattributeeditorelement.h>
- #include <qgsattributeeditorfield.h>
- #include <qgsattributeeditorhtmlelement.h>
- #include <qgsattributeeditorqmlelement.h>
- #include <qgsattributeeditorrelation.h>
- #include <qgsdatetimefieldformatter.h>
- #include <qgseditorwidgetsetup.h>
- #include <qgsmapthemecollection.h>
- #include <qgsproject.h>
- #include <qgsrelationmanager.h>
- #include <qgsvectorlayer.h>
- #include <qgsvectorlayerutils.h>
- AttributeFormModelBase::AttributeFormModelBase( QObject *parent )
- : QStandardItemModel( 0, 1, parent )
- {
- connect( QgsProject::instance(), &QgsProject::mapThemeCollectionChanged, this, &AttributeFormModelBase::onMapThemeCollectionChanged );
- if ( QgsProject::instance()->mapThemeCollection() )
- onMapThemeCollectionChanged();
- }
- AttributeFormModelBase::~AttributeFormModelBase()
- {
- delete mTemporaryContainer;
- }
- void AttributeFormModelBase::onMapThemeCollectionChanged()
- {
- connect( QgsProject::instance()->mapThemeCollection(), &QgsMapThemeCollection::mapThemeChanged, this, [ = ] { resetModel(); applyFeatureModel(); } );
- }
- QHash<int, QByteArray> AttributeFormModelBase::roleNames() const
- {
- QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
- roles[AttributeFormModel::ElementType] = "Type";
- roles[AttributeFormModel::Name] = "Name";
- roles[AttributeFormModel::AttributeValue] = "AttributeValue";
- roles[AttributeFormModel::AttributeEditable] = "AttributeEditable";
- roles[AttributeFormModel::EditorWidget] = "EditorWidget";
- roles[AttributeFormModel::EditorWidgetConfig] = "EditorWidgetConfig";
- roles[AttributeFormModel::RelationEditorWidget] = "RelationEditorWidget";
- roles[AttributeFormModel::RelationEditorWidgetConfig] = "RelationEditorWidgetConfig";
- roles[AttributeFormModel::RememberValue] = "RememberValue";
- roles[AttributeFormModel::Field] = "Field";
- roles[AttributeFormModel::RelationId] = "RelationId";
- roles[AttributeFormModel::NmRelationId] = "NmRelationId";
- roles[AttributeFormModel::Group] = "Group";
- roles[AttributeFormModel::ConstraintHardValid] = "ConstraintHardValid";
- roles[AttributeFormModel::ConstraintSoftValid] = "ConstraintSoftValid";
- roles[AttributeFormModel::ConstraintDescription] = "ConstraintDescription";
- roles[AttributeFormModel::AttributeAllowEdit] = "AttributeAllowEdit";
- roles[AttributeFormModel::EditorWidgetCode] = "EditorWidgetCode";
- roles[AttributeFormModel::TabIndex] = "TabIndex";
- roles[AttributeFormModel::Color] = "Color";
- return roles;
- }
- bool AttributeFormModelBase::setData( const QModelIndex &index, const QVariant &value, int role )
- {
- if ( !qgsVariantEqual( data( index, role ), value ) )
- {
- switch ( role )
- {
- case AttributeFormModel::AttributeAllowEdit:
- {
- QStandardItem *item = itemFromIndex( index );
- int fieldIndex = item->data( AttributeFormModel::FieldIndex ).toInt();
- mFeatureModel->setData( mFeatureModel->index( fieldIndex ), value, FeatureModel::AttributeAllowEdit );
- item->setData( value, AttributeFormModel::AttributeAllowEdit );
- updateVisibilityAndConstraints( fieldIndex );
- break;
- }
- case AttributeFormModel::RememberValue:
- {
- QStandardItem *item = itemFromIndex( index );
- int fieldIndex = item->data( AttributeFormModel::FieldIndex ).toInt();
- mFeatureModel->setData( mFeatureModel->index( fieldIndex ), value, FeatureModel::RememberAttribute );
- item->setData( value, AttributeFormModel::RememberValue );
- break;
- }
- case AttributeFormModel::AttributeValue:
- {
- QStandardItem *item = itemFromIndex( index );
- int fieldIndex = item->data( AttributeFormModel::FieldIndex ).toInt();
- bool changed = mFeatureModel->setData( mFeatureModel->index( fieldIndex ), value, FeatureModel::AttributeValue );
- if ( changed )
- {
- item->setData( value, AttributeFormModel::AttributeValue );
- emit dataChanged( index, index, QVector<int>() << role );
- }
- updateDefaultValues( fieldIndex );
- updateVisibilityAndConstraints( fieldIndex );
- return changed;
- }
- }
- }
- return false;
- }
- FeatureModel *AttributeFormModelBase::featureModel() const
- {
- return mFeatureModel;
- }
- void AttributeFormModelBase::setFeatureModel( FeatureModel *featureModel )
- {
- if ( mFeatureModel == featureModel )
- return;
- if ( mFeatureModel )
- {
- disconnect( mFeatureModel, &FeatureModel::currentLayerChanged, this, &AttributeFormModelBase::resetModel );
- disconnect( mFeatureModel, &FeatureModel::modelReset, this, &AttributeFormModelBase::applyFeatureModel );
- disconnect( mFeatureModel, &FeatureModel::featureUpdated, this, &AttributeFormModelBase::applyFeatureModel );
- }
- mFeatureModel = featureModel;
- connect( mFeatureModel, &FeatureModel::currentLayerChanged, this, &AttributeFormModelBase::resetModel );
- connect( mFeatureModel, &FeatureModel::modelReset, this, &AttributeFormModelBase::applyFeatureModel );
- connect( mFeatureModel, &FeatureModel::featureUpdated, this, &AttributeFormModelBase::applyFeatureModel );
- emit featureModelChanged();
- }
- void AttributeFormModelBase::resetModel()
- {
- clear();
- mVisibilityExpressions.clear();
- mConstraints.clear();
- if ( !mFeatureModel )
- return;
- mLayer = mFeatureModel->layer();
- if ( mLayer )
- {
- QgsAttributeEditorContainer *root;
- delete mTemporaryContainer;
- mTemporaryContainer = nullptr;
- if ( mLayer->editFormConfig().layout() == QgsEditFormConfig::TabLayout )
- {
- root = mLayer->editFormConfig().invisibleRootContainer();
- }
- else
- {
- root = generateRootContainer();
- mTemporaryContainer = root;
- }
- setHasTabs( !root->children().isEmpty() && QgsAttributeEditorElement::AeTypeContainer == root->children().first()->type() );
- invisibleRootItem()->setColumnCount( 1 );
- if ( mHasTabs )
- {
- const QList<QgsAttributeEditorElement *> children { root->children() };
- int currentTab = 0;
- for ( QgsAttributeEditorElement *element : children )
- {
- if ( element->type() == QgsAttributeEditorElement::AeTypeContainer )
- {
- QgsAttributeEditorContainer *container = static_cast<QgsAttributeEditorContainer *>( element );
- QStandardItem *item = new QStandardItem();
- item->setData( element->name(), AttributeFormModel::Name );
- item->setData( "container", AttributeFormModel::ElementType );
- item->setData( true, AttributeFormModel::CurrentlyVisible );
- item->setData( true, AttributeFormModel::ConstraintHardValid );
- item->setData( true, AttributeFormModel::ConstraintSoftValid );
- invisibleRootItem()->appendRow( item );
- if ( container->visibilityExpression().enabled() )
- {
- mVisibilityExpressions.append( qMakePair( container->visibilityExpression().data(), QVector<QStandardItem *>() << item ) );
- }
- QVector<QStandardItem *> dummy;
- flatten( container, item, QString(), dummy, currentTab, container->backgroundColor() );
- currentTab++;
- }
- }
- }
- else
- {
- QVector<QStandardItem *> dummy;
- flatten( invisibleRootContainer(), invisibleRootItem(), QString(), dummy );
- }
- mExpressionContext = mLayer->createExpressionContext();
- }
- }
- void AttributeFormModelBase::applyFeatureModel()
- {
- for ( int i = 0; i < invisibleRootItem()->rowCount(); ++i )
- {
- updateAttributeValue( invisibleRootItem()->child( i ) );
- }
- updateVisibilityAndConstraints();
- }
- QgsAttributeEditorContainer *AttributeFormModelBase::generateRootContainer() const
- {
- QgsAttributeEditorContainer *root = new QgsAttributeEditorContainer( QString(), nullptr );
- //get fields
- QgsFields fields = mLayer->fields();
- for ( int i = 0; i < fields.size(); ++i )
- {
- if ( fields.at( i ).editorWidgetSetup().type() != QStringLiteral( "Hidden" ) )
- {
- QgsAttributeEditorField *field = new QgsAttributeEditorField( fields.at( i ).name(), i, root );
- root->addChildElement( field );
- }
- }
- //get relations
- const QList<QgsRelation> referencingRelations = QgsProject::instance()->relationManager()->referencedRelations( mLayer );
- for ( const QgsRelation &referencingRelation : referencingRelations )
- {
- QgsAttributeEditorRelation *relation = new QgsAttributeEditorRelation( referencingRelation, root );
- root->addChildElement( relation );
- }
- return root;
- }
- QgsAttributeEditorContainer *AttributeFormModelBase::invisibleRootContainer() const
- {
- return mTemporaryContainer ? mTemporaryContainer : mLayer->editFormConfig().invisibleRootContainer();
- }
- void AttributeFormModelBase::updateAttributeValue( QStandardItem *item )
- {
- if ( item->data( AttributeFormModel::ElementType ) == QStringLiteral( "field" ) )
- {
- int fieldIndex = item->data( AttributeFormModel::FieldIndex ).toInt();
- QVariant attributeValue = mFeatureModel->data( mFeatureModel->index( fieldIndex ), FeatureModel::AttributeValue );
- item->setData( attributeValue.isNull() ? QVariant() : attributeValue, AttributeFormModel::AttributeValue );
- item->setData( mFeatureModel->data( mFeatureModel->index( fieldIndex ), FeatureModel::AttributeAllowEdit ), AttributeFormModel::AttributeAllowEdit );
- //set item visibility to false in case it's a linked attribute
- item->setData( !mFeatureModel->data( mFeatureModel->index( fieldIndex ), FeatureModel::LinkedAttribute ).toBool(), AttributeFormModel::CurrentlyVisible );
- }
- else if ( item->data( AttributeFormModel::ElementType ) == QStringLiteral( "qml" ) || item->data( AttributeFormModel::ElementType ) == QStringLiteral( "html" ) )
- {
- QString code = mEditorWidgetCodes[item];
- QRegularExpression re( "expression\\.evaluate\\(\\s*\\\"(.*?[^\\\\])\\\"\\s*\\)" );
- QRegularExpressionMatch match = re.match( code );
- while ( match.hasMatch() )
- {
- QString expression = match.captured( 1 );
- expression = expression.replace( QStringLiteral( "\\\"" ), QStringLiteral( "\"" ) );
- QgsExpressionContext expressionContext = mLayer->createExpressionContext();
- expressionContext.setFeature( mFeatureModel->feature() );
- QgsExpression exp = QgsExpression( expression );
- exp.prepare( &expressionContext );
- QVariant result = exp.evaluate( &expressionContext );
- QString resultString;
- switch ( static_cast<QMetaType::Type>( result.type() ) )
- {
- case QMetaType::Int:
- case QMetaType::UInt:
- case QMetaType::Double:
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- resultString = result.toString();
- break;
- case QMetaType::Bool:
- resultString = result.toBool() ? QStringLiteral( "true" ) : QStringLiteral( "false" );
- break;
- default:
- resultString = QStringLiteral( "'%1'" ).arg( result.toString() );
- break;
- }
- code = code.mid( 0, match.capturedStart( 0 ) ) + resultString + code.mid( match.capturedEnd( 0 ) );
- match = re.match( code );
- }
- item->setData( code, AttributeFormModel::EditorWidgetCode );
- }
- else
- {
- for ( int i = 0; i < item->rowCount(); ++i )
- {
- updateAttributeValue( item->child( i ) );
- }
- }
- }
- void AttributeFormModelBase::flatten( QgsAttributeEditorContainer *container, QStandardItem *parent, const QString &parentVisibilityExpressions, QVector<QStandardItem *> &items, int currentTabIndex, const QColor &color )
- {
- const QList<QgsAttributeEditorElement *> children { container->children() };
- for ( QgsAttributeEditorElement *element : children )
- {
- switch ( element->type() )
- {
- case QgsAttributeEditorElement::AeTypeContainer:
- {
- QString visibilityExpression = parentVisibilityExpressions;
- QgsAttributeEditorContainer *innerContainer = static_cast<QgsAttributeEditorContainer *>( element );
- if ( innerContainer->visibilityExpression().enabled() )
- {
- if ( visibilityExpression.isNull() )
- visibilityExpression = innerContainer->visibilityExpression().data().expression();
- else
- visibilityExpression += " AND " + innerContainer->visibilityExpression().data().expression();
- }
- QVector<QStandardItem *> newItems;
- flatten( innerContainer, parent, visibilityExpression, newItems, 0, innerContainer->backgroundColor() );
- if ( !visibilityExpression.isEmpty() )
- mVisibilityExpressions.append( qMakePair( QgsExpression( visibilityExpression ), newItems ) );
- break;
- }
- case QgsAttributeEditorElement::AeTypeField:
- {
- QgsAttributeEditorField *editorField = static_cast<QgsAttributeEditorField *>( element );
- // editorField->idx() is not working on joined fields
- const QgsFields fields = mLayer->fields();
- int fieldIndex = fields.lookupField( editorField->name() );
- if ( fieldIndex < 0 || fieldIndex >= mLayer->fields().size() )
- continue;
- QgsField field = mLayer->fields().at( fieldIndex );
- QStandardItem *item = new QStandardItem();
- item->setData( currentTabIndex, AttributeFormModel::TabIndex );
- item->setData( mLayer->attributeDisplayName( fieldIndex ), AttributeFormModel::Name );
- item->setData( !mLayer->editFormConfig().readOnly( fieldIndex ) &&
- !( field.defaultValueDefinition().isValid() && field.defaultValueDefinition().applyOnUpdate() ), AttributeFormModel::AttributeEditable );
- const QgsEditorWidgetSetup setup = findBest( fieldIndex );
- item->setData( setup.type(), AttributeFormModel::EditorWidget );
- item->setData( setup.config(), AttributeFormModel::EditorWidgetConfig );
- item->setData( mFeatureModel->rememberedAttributes().at( fieldIndex ) ? Qt::Checked : Qt::Unchecked, AttributeFormModel::RememberValue );
- item->setData( QgsField( field ), AttributeFormModel::Field );
- item->setData( "field", AttributeFormModel::ElementType );
- item->setData( fieldIndex, AttributeFormModel::FieldIndex );
- item->setData( container->isGroupBox() ? container->name() : QString(), AttributeFormModel::Group );
- item->setData( true, AttributeFormModel::CurrentlyVisible );
- item->setData( true, AttributeFormModel::ConstraintHardValid );
- item->setData( true, AttributeFormModel::ConstraintSoftValid );
- item->setData( mFeatureModel->data( mFeatureModel->index( fieldIndex ), FeatureModel::AttributeAllowEdit ), AttributeFormModel::AttributeAllowEdit );
- if ( color.isValid() )
- item->setData( color, AttributeFormModel::Color );
- // create constraint description
- QStringList descriptions;
- if ( field.constraints().constraints() & QgsFieldConstraints::ConstraintExpression )
- {
- descriptions << ( !field.constraints().constraintDescription().isEmpty()
- ? field.constraints().constraintDescription()
- : tr( "Expression constraint" ) );
- }
- if ( field.constraints().constraints() & QgsFieldConstraints::ConstraintNotNull )
- {
- descriptions << tr( "Not NULL" );
- }
- if ( field.constraints().constraints() & QgsFieldConstraints::ConstraintUnique )
- {
- descriptions << tr( "Unique" );
- }
- item->setData( descriptions.join( ", " ), AttributeFormModel::ConstraintDescription );
- updateAttributeValue( item );
- mConstraints.insert( item, field.constraints() );
- items.append( item );
- parent->appendRow( item );
- break;
- }
- case QgsAttributeEditorElement::AeTypeRelation:
- {
- QgsAttributeEditorRelation *editorRelation = static_cast<QgsAttributeEditorRelation *>( element );
- QgsRelation relation = editorRelation->relation();
- QStandardItem *item = new QStandardItem();
- item->setData( currentTabIndex, AttributeFormModel::TabIndex );
- item->setData( relation.name(), AttributeFormModel::Name );
- item->setData( true, AttributeFormModel::AttributeEditable );
- item->setData( true, AttributeFormModel::CurrentlyVisible );
- item->setData( "relation", AttributeFormModel::ElementType );
- item->setData( "RelationEditor", AttributeFormModel::EditorWidget );
- item->setData( editorRelation->relationWidgetTypeId(), AttributeFormModel::RelationEditorWidget );
- item->setData( editorRelation->relationEditorConfiguration(), AttributeFormModel::RelationEditorWidgetConfig );
- item->setData( relation.id(), AttributeFormModel::RelationId );
- item->setData( mLayer->editFormConfig().widgetConfig( relation.id() )[QStringLiteral( "nm-rel" )].toString(), AttributeFormModel::NmRelationId );
- item->setData( container->isGroupBox() ? container->name() : QString(), AttributeFormModel::Group );
- item->setData( true, AttributeFormModel::CurrentlyVisible );
- item->setData( true, AttributeFormModel::ConstraintHardValid );
- item->setData( true, AttributeFormModel::ConstraintSoftValid );
- item->setData( true, AttributeFormModel::AttributeAllowEdit );
- items.append( item );
- parent->appendRow( item );
- break;
- }
- case QgsAttributeEditorElement::AeTypeQmlElement:
- {
- QgsAttributeEditorQmlElement *qmlElement = static_cast<QgsAttributeEditorQmlElement *>( element );
- QStandardItem *item = new QStandardItem();
- item->setData( currentTabIndex, AttributeFormModel::TabIndex );
- item->setData( "qml", AttributeFormModel::ElementType );
- item->setData( qmlElement->name(), AttributeFormModel::Name );
- item->setData( true, AttributeFormModel::CurrentlyVisible );
- item->setData( false, AttributeFormModel::AttributeEditable );
- item->setData( false, AttributeFormModel::AttributeAllowEdit );
- item->setData( container->isGroupBox() ? container->name() : QString(), AttributeFormModel::Group );
- mEditorWidgetCodes.insert( item, qmlElement->qmlCode() );
- updateAttributeValue( item );
- items.append( item );
- parent->appendRow( item );
- break;
- }
- case QgsAttributeEditorElement::AeTypeHtmlElement:
- {
- QgsAttributeEditorHtmlElement *htmlElement = static_cast<QgsAttributeEditorHtmlElement *>( element );
- QStandardItem *item = new QStandardItem();
- item->setData( currentTabIndex, AttributeFormModel::TabIndex );
- item->setData( "html", AttributeFormModel::ElementType );
- item->setData( htmlElement->name(), AttributeFormModel::Name );
- item->setData( true, AttributeFormModel::CurrentlyVisible );
- item->setData( false, AttributeFormModel::AttributeEditable );
- item->setData( false, AttributeFormModel::AttributeAllowEdit );
- item->setData( container->isGroupBox() ? container->name() : QString(), AttributeFormModel::Group );
- mEditorWidgetCodes.insert( item, htmlElement->htmlCode() );
- updateAttributeValue( item );
- items.append( item );
- parent->appendRow( item );
- break;
- }
- case QgsAttributeEditorElement::AeTypeInvalid:
- #if _QGIS_VERSION_INT >= 32100
- case QgsAttributeEditorElement::AeTypeAction:
- #endif
- // todo
- break;
- }
- }
- }
- void AttributeFormModelBase::updateDefaultValues( int fieldIndex )
- {
- const QgsFields fields = mFeatureModel->feature().fields();
- if ( fieldIndex < 0 || fieldIndex > fields.size() )
- return;
- const QString fieldName = fields.at( fieldIndex ).name();
- mExpressionContext.setFields( fields );
- mExpressionContext.setFeature( mFeatureModel->feature() );
- QMap<QStandardItem *, QgsFieldConstraints>::ConstIterator constraintIterator( mConstraints.constBegin() );
- for ( ; constraintIterator != mConstraints.constEnd(); ++constraintIterator )
- {
- QStandardItem *item = constraintIterator.key();
- int fidx = item->data( AttributeFormModel::FieldIndex ).toInt();
- if ( fidx == fieldIndex || !fields.at( fidx ).defaultValueDefinition().isValid() || !fields.at( fidx ).defaultValueDefinition().applyOnUpdate() )
- continue;
- QgsExpression exp( fields.at( fidx ).defaultValueDefinition().expression() );
- exp.prepare( &mExpressionContext );
- // avoid cost of value update if expression doesn't contain the field which triggered the default values update
- if ( !exp.referencedColumns().contains( fieldName ) )
- continue;
- QVariant defaultValue = exp.evaluate( &mExpressionContext );
- bool changed = mFeatureModel->setData( mFeatureModel->index( fidx ), defaultValue, FeatureModel::AttributeValue );
- if ( changed )
- {
- item->setData( defaultValue, AttributeFormModel::AttributeValue );
- updateDefaultValues( fidx );
- updateVisibilityAndConstraints( fidx );
- }
- }
- }
- void AttributeFormModelBase::updateVisibilityAndConstraints( int fieldIndex )
- {
- QgsFields fields = mFeatureModel->feature().fields();
- mExpressionContext.setFields( fields );
- mExpressionContext.setFeature( mFeatureModel->feature() );
- for ( const VisibilityExpression &it : std::as_const( mVisibilityExpressions ) )
- {
- if ( fieldIndex == -1 || it.first.referencedAttributeIndexes( fields ).contains( fieldIndex ) )
- {
- QgsExpression exp = it.first;
- exp.prepare( &mExpressionContext );
- bool visible = exp.evaluate( &mExpressionContext ).toInt();
- for ( QStandardItem *item : std::as_const( it.second ) )
- {
- if ( item->data( AttributeFormModel::CurrentlyVisible ).toBool() != visible )
- {
- item->setData( visible, AttributeFormModel::CurrentlyVisible );
- emit dataChanged( item->index(), item->index(), QVector<int>() << AttributeFormModel::CurrentlyVisible );
- }
- }
- }
- }
- // reset contrainsts status of containers
- if ( mHasTabs )
- {
- QStandardItem *root = invisibleRootItem();
- for ( int i = 0; i < root->rowCount(); i++ )
- {
- QStandardItem *item = root->child( i, 0 );
- item->setData( true, AttributeFormModel::ConstraintHardValid );
- item->setData( true, AttributeFormModel::ConstraintSoftValid );
- }
- }
- bool allConstraintsHardValid = true;
- bool allConstraintsSoftValid = true;
- QMap<QStandardItem *, QgsFieldConstraints>::ConstIterator constraintIterator( mConstraints.constBegin() );
- for ( ; constraintIterator != mConstraints.constEnd(); ++constraintIterator )
- {
- QStandardItem *item = constraintIterator.key();
- const bool isVisible = item->data( AttributeFormModel::CurrentlyVisible ).toBool();
- int fidx = item->data( AttributeFormModel::FieldIndex ).toInt();
- if ( isVisible && mFeatureModel->data( mFeatureModel->index( fidx ), FeatureModel::AttributeAllowEdit ) == true )
- {
- QStringList errors;
- QgsFeature feature = mFeatureModel->feature();
- QString defaultValueClause = mLayer->dataProvider()->defaultValueClause( fidx );
- QString attrValue = feature.attribute( fidx ).toString();
- // Providers will check for a literal "defaultValueClause" to autogenerate PKs.
- // For example, the gpkg provider will generate a fid if it is set to "Autogenerate".
- // On QField, if the user leaves the field empty, we will assume he wants to autogenerate it.
- // This makes sure, the NOT NULL constraint is skipped in this case.
- if ( attrValue.isEmpty() && !defaultValueClause.isEmpty() )
- {
- feature.setAttribute( fidx, defaultValueClause );
- }
- bool hardConstraintSatisfied = QgsVectorLayerUtils::validateAttribute( mLayer, feature, fidx, errors, QgsFieldConstraints::ConstraintStrengthHard );
- if ( hardConstraintSatisfied != item->data( AttributeFormModel::ConstraintHardValid ).toBool() )
- {
- item->setData( hardConstraintSatisfied, AttributeFormModel::ConstraintHardValid );
- }
- if ( !item->data( AttributeFormModel::ConstraintHardValid ).toBool() )
- {
- allConstraintsHardValid = false;
- if ( mHasTabs && item->parent() )
- item->parent()->setData( false, AttributeFormModel::ConstraintHardValid );
- }
- QStringList softErrors;
- bool softConstraintSatisfied = QgsVectorLayerUtils::validateAttribute( mLayer, mFeatureModel->feature(), fidx, softErrors, QgsFieldConstraints::ConstraintStrengthSoft );
- if ( softConstraintSatisfied != item->data( AttributeFormModel::ConstraintSoftValid ).toBool() )
- {
- item->setData( softConstraintSatisfied, AttributeFormModel::ConstraintSoftValid );
- }
- if ( !item->data( AttributeFormModel::ConstraintSoftValid ).toBool() )
- {
- allConstraintsSoftValid = false;
- if ( mHasTabs && item->parent() )
- item->parent()->setData( false, AttributeFormModel::ConstraintSoftValid );
- }
- }
- else
- {
- item->setData( true, AttributeFormModel::ConstraintHardValid );
- item->setData( true, AttributeFormModel::ConstraintSoftValid );
- }
- }
- setConstraintsHardValid( allConstraintsHardValid );
- setConstraintsSoftValid( allConstraintsSoftValid );
- }
- bool AttributeFormModelBase::constraintsHardValid() const
- {
- return mConstraintsHardValid;
- }
- bool AttributeFormModelBase::constraintsSoftValid() const
- {
- return mConstraintsSoftValid;
- }
- QVariant AttributeFormModelBase::attribute( const QString &name )
- {
- if ( !mLayer )
- return QVariant();
- int idx = mLayer->fields().indexOf( name );
- return mFeatureModel->data( mFeatureModel->index( idx ), FeatureModel::AttributeValue );
- }
- void AttributeFormModelBase::setConstraintsHardValid( bool constraintsHardValid )
- {
- if ( constraintsHardValid == mConstraintsHardValid )
- return;
- mConstraintsHardValid = constraintsHardValid;
- emit constraintsHardValidChanged();
- }
- void AttributeFormModelBase::setConstraintsSoftValid( bool constraintsSoftValid )
- {
- if ( constraintsSoftValid == mConstraintsSoftValid )
- return;
- mConstraintsSoftValid = constraintsSoftValid;
- emit constraintsSoftValidChanged();
- }
- 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;
- //when it's a provider field with default value clause, take Textedit
- if ( fields.fieldOrigin( fieldIndex ) == QgsFields::OriginProvider )
- {
- int providerOrigin = fields.fieldOriginIndex( fieldIndex );
- if ( !mLayer->dataProvider()->defaultValueClause( providerOrigin ).isEmpty() )
- return setup;
- }
- //find the best one
- const QgsField field = fields.at( fieldIndex );
- //on a boolean type take "CheckBox"
- if ( field.type() == QVariant::Bool )
- setup = QgsEditorWidgetSetup( QStringLiteral( "CheckBox" ), QVariantMap() );
- //on a date or time type take "DateTime"
- if ( field.isDateOrTime() )
- {
- 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 );
- }
- //on numeric types take "Range"
- if ( field.type() == QVariant::Int || field.type() == QVariant::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() )
- {
- 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 );
- }
- }
- return setup;
- }
- bool AttributeFormModelBase::hasTabs() const
- {
- return mHasTabs;
- }
- void AttributeFormModelBase::setHasTabs( bool hasTabs )
- {
- if ( hasTabs == mHasTabs )
- return;
- mHasTabs = hasTabs;
- emit hasTabsChanged();
- }
- bool AttributeFormModelBase::save()
- {
- return mFeatureModel->save();
- }
- bool AttributeFormModelBase::create()
- {
- return mFeatureModel->create();
- }
- bool AttributeFormModelBase::deleteFeature()
- {
- return mFeatureModel->deleteFeature();
- }
|