Skip to content

Commit

Permalink
Relation editor widget support for multiple features
Browse files Browse the repository at this point in the history
  • Loading branch information
domi4484 committed Nov 8, 2021
1 parent 9c02b8c commit 3499d9a
Show file tree
Hide file tree
Showing 14 changed files with 267 additions and 54 deletions.
Expand Up @@ -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.
Expand Down
Expand Up @@ -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 );
Expand Down
Expand Up @@ -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

};

/************************************************************************
Expand Down
2 changes: 1 addition & 1 deletion src/gui/editorwidgets/qgsrelationreferenceconfigdlg.h
@@ -1,5 +1,5 @@
/***************************************************************************
qgsrelationreferenceconfigdlgbase.h
qgsrelationreferenceconfigdlg.h
--------------------------------------
Date : 21.4.2013
Copyright : (C) 2013 Matthias Kuhn
Expand Down
6 changes: 6 additions & 0 deletions src/gui/editorwidgets/qgsrelationwidgetwrapper.cpp
Expand Up @@ -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 )
Expand Down
7 changes: 7 additions & 0 deletions src/gui/editorwidgets/qgsrelationwidgetwrapper.h
Expand Up @@ -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
Expand Down
75 changes: 62 additions & 13 deletions src/gui/qgsabstractrelationeditorwidget.cpp
Expand Up @@ -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() );

Expand Down Expand Up @@ -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() );
Expand Down Expand Up @@ -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 )
Expand Down Expand Up @@ -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 );

Expand All @@ -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();
Expand All @@ -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;
}

Expand Down Expand Up @@ -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() )
Expand All @@ -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 );
Expand All @@ -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
Expand Down Expand Up @@ -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 ) )
Expand Down Expand Up @@ -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 );
}

Expand Down Expand Up @@ -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
Expand All @@ -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()
Expand Down
9 changes: 8 additions & 1 deletion src/gui/qgsabstractrelationeditorwidget.h
Expand Up @@ -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
Expand Down Expand Up @@ -229,7 +236,7 @@ class GUI_EXPORT QgsAbstractRelationEditorWidget : public QWidget
QgsAttributeEditorContext mEditorContext;
QgsRelation mRelation;
QgsRelation mNmRelation;
QgsFeature mFeature;
QgsFeatureList mFeatureList;

bool mLayerInSameTransactionGroup = false;

Expand Down
17 changes: 16 additions & 1 deletion src/gui/qgsattributeform.cpp
Expand Up @@ -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 );
Expand Down Expand Up @@ -2512,6 +2512,9 @@ void QgsAttributeForm::setMultiEditFeatureIds( const QgsFeatureIds &fids )
}
}
}

setMultiEditFeatureIdsRelations( fids );

mIsSettingMultiEditFeatures = false;
}

Expand Down Expand Up @@ -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()] )
Expand Down
2 changes: 2 additions & 0 deletions src/gui/qgsattributeform.h
Expand Up @@ -379,6 +379,8 @@ class GUI_EXPORT QgsAttributeForm : public QWidget

void updateDefaultValueDependencies();

void setMultiEditFeatureIdsRelations( const QgsFeatureIds &fids );

struct WidgetInfo
{
QWidget *widget = nullptr;
Expand Down
5 changes: 5 additions & 0 deletions src/gui/qgsattributeformrelationeditorwidget.cpp
Expand Up @@ -45,3 +45,8 @@ QString QgsAttributeFormRelationEditorWidget::currentFilterExpression() const

return filterExpression;
}

void QgsAttributeFormRelationEditorWidget::setMultiEditFeatureIds( const QgsFeatureIds &fids )
{
mWrapper->setMultiEditFeatureIds( fids );
}
7 changes: 7 additions & 0 deletions src/gui/qgsattributeformrelationeditorwidget.h
Expand Up @@ -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;
Expand Down

0 comments on commit 3499d9a

Please sign in to comment.