Skip to content
Permalink
Browse files
Relation editor widget support for multiple features
  • Loading branch information
domi4484 committed Nov 8, 2021
1 parent 9c02b8c commit 3499d9a03349468b8e191b3fc04f5c088d0f3daf
@@ -246,6 +246,15 @@ Forward the signal to the embedded form
virtual void setFeature( const QgsFeature &feature );


void setMultiEditFeatureIds( const QgsFeatureIds &fids );
%Docstring
Set multiple feature to edit simultaneously.

:param fids: Multiple Id of features to edit

.. versionadded:: 3.22
%End

void setVisible( bool visible );
%Docstring
Sets the visibility of the wrapper's widget.
@@ -74,6 +74,15 @@ Returns the nm relation
void setFeature( const QgsFeature &feature, bool update = true );
%Docstring
Sets the ``feature`` being edited and updates the UI unless ``update`` is set to ``False``
%End

void setMultiEditFeatureIds( const QgsFeatureIds &fids );
%Docstring
Set multiple feature to edit simultaneously.

:param fids: Multiple Id of features to edit

.. versionadded:: 3.22
%End

virtual void setEditorContext( const QgsAttributeEditorContext &context );
@@ -34,6 +34,15 @@ Constructor
virtual QString currentFilterExpression() const;


void setMultiEditFeatureIds( const QgsFeatureIds &fids );
%Docstring
Set multiple feature to edit simultaneously.

:param fids: Multiple Id of features to edit

.. versionadded:: 3.22
%End

};

/************************************************************************
@@ -1,5 +1,5 @@
/***************************************************************************
qgsrelationreferenceconfigdlgbase.h
qgsrelationreferenceconfigdlg.h
--------------------------------------
Date : 21.4.2013
Copyright : (C) 2013 Matthias Kuhn
@@ -59,6 +59,12 @@ void QgsRelationWidgetWrapper::setFeature( const QgsFeature &feature )
mWidget->setFeature( feature );
}

void QgsRelationWidgetWrapper::setMultiEditFeatureIds( const QgsFeatureIds &fids )
{
if ( mWidget && mRelation.isValid() )
mWidget->setMultiEditFeatureIds( fids );
}

void QgsRelationWidgetWrapper::setVisible( bool visible )
{
if ( mWidget )
@@ -213,6 +213,13 @@ class GUI_EXPORT QgsRelationWidgetWrapper : public QgsWidgetWrapper
public slots:
void setFeature( const QgsFeature &feature ) override;

/**
* Set multiple feature to edit simultaneously.
* \param fids Multiple Id of features to edit
* \since QGIS 3.22
*/
void setMultiEditFeatureIds( const QgsFeatureIds &fids );

/**
* Sets the visibility of the wrapper's widget.
* \param visible set to TRUE to show widget, FALSE to hide widget
@@ -43,7 +43,8 @@ void QgsAbstractRelationEditorWidget::setRelationFeature( const QgsRelation &rel
beforeSetRelationFeature( relation, feature );

mRelation = relation;
mFeature = feature;
mFeatureList.clear();
mFeatureList.append( feature );

setObjectName( QStringLiteral( "referenced/" ) + mRelation.name() );

@@ -103,14 +104,26 @@ QgsAttributeEditorContext QgsAbstractRelationEditorWidget::editorContext() const

void QgsAbstractRelationEditorWidget::setFeature( const QgsFeature &feature, bool update )
{
mFeature = feature;
mFeatureList.clear();
mFeatureList.append( feature );

// Is this OK???
mEditorContext.setFormFeature( feature );

if ( update )
updateUi();
}

void QgsAbstractRelationEditorWidget::setMultiEditFeatureIds( const QgsFeatureIds &fids )
{
mFeatureList.clear();

QgsFeatureIterator featureIterator = mRelation.referencedLayer()->getFeatures( QgsFeatureRequest().setFilterFids( fids ) );
QgsFeature feature;
while ( featureIterator.nextFeature( feature ) )
mFeatureList.append( feature );
}

void QgsAbstractRelationEditorWidget::setNmRelationId( const QVariant &nmRelationId )
{
const QgsRelation nmrelation = QgsProject::instance()->relationManager()->relation( nmRelationId.toString() );
@@ -161,7 +174,10 @@ void QgsAbstractRelationEditorWidget::updateTitle()

QgsFeature QgsAbstractRelationEditorWidget::feature() const
{
return mFeature;
if ( !mFeatureList.isEmpty() )
return mFeatureList.first();

return QgsFeature();
}

void QgsAbstractRelationEditorWidget::toggleEditing( bool state )
@@ -205,6 +221,12 @@ void QgsAbstractRelationEditorWidget::addFeature( const QgsGeometry &geometry )

if ( mNmRelation.isValid() )
{
if ( mFeatureList.size() > 1 )
{
QgsLogger::warning( tr( "Adding of feature not supported in multiple edit mode for n:m relations" ) );
return;
}

// only normal relations support m:n relation
Q_ASSERT( mNmRelation.type() == QgsRelation::Normal );

@@ -222,7 +244,7 @@ void QgsAbstractRelationEditorWidget::addFeature( const QgsGeometry &geometry )
for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
{
const int index = fields.indexOf( fieldPair.first );
linkAttributes.insert( index, mFeature.attribute( fieldPair.second ) );
linkAttributes.insert( index, mFeatureList.first().attribute( fieldPair.second ) );
}

const auto constNmFieldPairs = mNmRelation.fieldPairs();
@@ -237,13 +259,19 @@ void QgsAbstractRelationEditorWidget::addFeature( const QgsGeometry &geometry )
}
else
{
const auto constFieldPairs = mRelation.fieldPairs();
for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
int featureAdded = 0;
for ( const QgsFeature &feature : mFeatureList )
{
keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), mFeature.attribute( fieldPair.referencedField() ) );
}
const auto constFieldPairs = mRelation.fieldPairs();
for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
{
keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), feature.attribute( fieldPair.referencedField() ) );
}

if ( !vlTools->addFeature( mRelation.referencingLayer(), keyAttrs, geometry ) )
if ( vlTools->addFeature( mRelation.referencingLayer(), keyAttrs, geometry ) )
featureAdded++;
}
if ( featureAdded == 0 )
return;
}

@@ -374,6 +402,12 @@ void QgsAbstractRelationEditorWidget::deleteFeatures( const QgsFeatureIds &fids

void QgsAbstractRelationEditorWidget::linkFeature()
{
if ( mFeatureList.size() > 1 )
{
QgsLogger::warning( tr( "Linking of feature not supported in multiple edit mode" ) );
return;
}

QgsVectorLayer *layer = nullptr;

if ( mNmRelation.isValid() )
@@ -384,12 +418,14 @@ void QgsAbstractRelationEditorWidget::linkFeature()
layer = mNmRelation.referencedLayer();
}
else
{
layer = mRelation.referencingLayer();
}

QgsFeatureSelectionDlg *selectionDlg = new QgsFeatureSelectionDlg( layer, mEditorContext, this );
selectionDlg->setAttribute( Qt::WA_DeleteOnClose );

const QString displayString = QgsVectorLayerUtils::getFeatureDisplayString( mRelation.referencedLayer(), mFeature );
const QString displayString = QgsVectorLayerUtils::getFeatureDisplayString( mRelation.referencedLayer(), mFeatureList.first() );
selectionDlg->setWindowTitle( tr( "Link existing child features for parent %1 \"%2\"" ).arg( mRelation.referencedLayer()->name(), displayString ) );

connect( selectionDlg, &QDialog::accepted, this, &QgsAbstractRelationEditorWidget::onLinkFeatureDlgAccepted );
@@ -399,6 +435,13 @@ void QgsAbstractRelationEditorWidget::linkFeature()
void QgsAbstractRelationEditorWidget::onLinkFeatureDlgAccepted()
{
QgsFeatureSelectionDlg *selectionDlg = qobject_cast<QgsFeatureSelectionDlg *>( sender() );

if ( mFeatureList.size() > 1 )
{
QgsLogger::warning( tr( "Linking of feature not supported in multiple edit mode" ) );
return;
}

if ( mNmRelation.isValid() )
{
// only normal relations support m:n relation
@@ -434,7 +477,7 @@ void QgsAbstractRelationEditorWidget::onLinkFeatureDlgAccepted()
for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
{
const int index = fields.indexOf( fieldPair.first );
linkAttributes.insert( index, mFeature.attribute( fieldPair.second ) );
linkAttributes.insert( index, mFeatureList.first().attribute( fieldPair.second ) );
}

while ( it.nextFeature( relatedFeature ) )
@@ -464,7 +507,7 @@ void QgsAbstractRelationEditorWidget::onLinkFeatureDlgAccepted()
for ( const QgsRelation::FieldPair &fieldPair : constFieldPairs )
{
const int idx = mRelation.referencingLayer()->fields().lookupField( fieldPair.referencingField() );
const QVariant val = mFeature.attribute( fieldPair.referencedField() );
const QVariant val = mFeatureList.first().attribute( fieldPair.referencedField() );
keys.insert( idx, val );
}

@@ -502,6 +545,12 @@ void QgsAbstractRelationEditorWidget::unlinkFeature( const QgsFeatureId fid )

void QgsAbstractRelationEditorWidget::unlinkFeatures( const QgsFeatureIds &fids )
{
if ( mFeatureList.size() > 1 )
{
QgsLogger::warning( tr( "Unlinking of features not supported in multiple edit mode" ) );
return;
}

if ( mNmRelation.isValid() )
{
// only normal relations support m:n relation
@@ -522,7 +571,7 @@ void QgsAbstractRelationEditorWidget::unlinkFeatures( const QgsFeatureIds &fids
}

const QString filter = QStringLiteral( "(%1) AND (%2)" ).arg(
mRelation.getRelatedFeaturesRequest( mFeature ).filterExpression()->expression(),
mRelation.getRelatedFeaturesRequest( mFeatureList.first() ).filterExpression()->expression(),
filters.join( QLatin1String( " OR " ) ) );

QgsFeatureIterator linkedIterator = mRelation.referencingLayer()->getFeatures( QgsFeatureRequest()
@@ -97,6 +97,13 @@ class GUI_EXPORT QgsAbstractRelationEditorWidget : public QWidget
*/
void setFeature( const QgsFeature &feature, bool update = true );

/**
* Set multiple feature to edit simultaneously.
* \param fids Multiple Id of features to edit
* \since QGIS 3.22
*/
void setMultiEditFeatureIds( const QgsFeatureIds &fids );

/**
* Sets the editor \a context
* \note if context cadDockWidget is null, it won't be possible to digitize
@@ -229,7 +236,7 @@ class GUI_EXPORT QgsAbstractRelationEditorWidget : public QWidget
QgsAttributeEditorContext mEditorContext;
QgsRelation mRelation;
QgsRelation mNmRelation;
QgsFeature mFeature;
QgsFeatureList mFeatureList;

bool mLayerInSameTransactionGroup = false;

@@ -212,7 +212,7 @@ void QgsAttributeForm::setMode( QgsAttributeEditorContext::Mode mode )
w->setContext( newContext );
}

bool relationWidgetsVisible = ( mMode != QgsAttributeEditorContext::MultiEditMode && mMode != QgsAttributeEditorContext::AggregateSearchMode );
bool relationWidgetsVisible = ( mMode != QgsAttributeEditorContext::AggregateSearchMode );
for ( QgsAttributeFormRelationEditorWidget *w : findChildren< QgsAttributeFormRelationEditorWidget * >() )
{
w->setVisible( relationWidgetsVisible );
@@ -2512,6 +2512,9 @@ void QgsAttributeForm::setMultiEditFeatureIds( const QgsFeatureIds &fids )
}
}
}

setMultiEditFeatureIdsRelations( fids );

mIsSettingMultiEditFeatures = false;
}

@@ -2665,6 +2668,18 @@ void QgsAttributeForm::updateDefaultValueDependencies()
}
}

void QgsAttributeForm::setMultiEditFeatureIdsRelations( const QgsFeatureIds &fids )
{
for ( QgsAttributeFormWidget *formWidget : mFormWidgets )
{
QgsAttributeFormRelationEditorWidget *relationEditorWidget = dynamic_cast<QgsAttributeFormRelationEditorWidget *>( formWidget );
if ( !relationEditorWidget )
continue;

relationEditorWidget->setMultiEditFeatureIds( fids );
}
}

void QgsAttributeForm::updateIcon( QgsEditorWidgetWrapper *eww )
{
if ( !eww->widget() || !mIconMap[eww->widget()] )
@@ -379,6 +379,8 @@ class GUI_EXPORT QgsAttributeForm : public QWidget

void updateDefaultValueDependencies();

void setMultiEditFeatureIdsRelations( const QgsFeatureIds &fids );

struct WidgetInfo
{
QWidget *widget = nullptr;
@@ -45,3 +45,8 @@ QString QgsAttributeFormRelationEditorWidget::currentFilterExpression() const

return filterExpression;
}

void QgsAttributeFormRelationEditorWidget::setMultiEditFeatureIds( const QgsFeatureIds &fids )
{
mWrapper->setMultiEditFeatureIds( fids );
}
@@ -44,6 +44,13 @@ class GUI_EXPORT QgsAttributeFormRelationEditorWidget : public QgsAttributeFormW
void createSearchWidgetWrappers( const QgsAttributeEditorContext &context = QgsAttributeEditorContext() ) override;
QString currentFilterExpression() const override;

/**
* Set multiple feature to edit simultaneously.
* \param fids Multiple Id of features to edit
* \since QGIS 3.22
*/
void setMultiEditFeatureIds( const QgsFeatureIds &fids );

private:
QgsRelationAggregateSearchWidgetWrapper *mSearchWidget = nullptr;
QgsRelationWidgetWrapper *mWrapper = nullptr;
Loading

0 comments on commit 3499d9a

Please sign in to comment.