Skip to content

Commit

Permalink
Fix #50197 and reduce usage of signal/slots in attribute form
Browse files Browse the repository at this point in the history
  • Loading branch information
domi4484 authored and nyalldawson committed Nov 18, 2022
1 parent fde3b8f commit a65c16c
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 70 deletions.
130 changes: 63 additions & 67 deletions src/gui/qgsattributeform.cpp
Expand Up @@ -750,23 +750,25 @@ bool QgsAttributeForm::saveMultiEdits()
{
//find changed attributes
QgsAttributeMap newAttributeValues;
QMap< int, QgsAttributeFormEditorWidget * >::const_iterator wIt = mFormEditorWidgets.constBegin();
for ( ; wIt != mFormEditorWidgets.constEnd(); ++ wIt )
const QList<int> fieldIndexes = mFormEditorWidgets.uniqueKeys();
mFormEditorWidgets.constBegin();
for ( int fieldIndex : fieldIndexes )
{
QgsAttributeFormEditorWidget *w = wIt.value();
if ( !w->hasChanged() )
const QList<QgsAttributeFormEditorWidget *> widgets = mFormEditorWidgets.values( fieldIndex );
if ( !widgets.first()->hasChanged() )
continue;

if ( !w->currentValue().isValid() // if the widget returns invalid (== do not change)
|| !fieldIsEditable( wIt.key() ) ) // or the field cannot be edited ...
if ( !widgets.first()->currentValue().isValid() // if the widget returns invalid (== do not change)
|| !fieldIsEditable( fieldIndex ) ) // or the field cannot be edited ...
{
continue;
}

// let editor know we've accepted the changes
w->changesCommitted();
for ( QgsAttributeFormEditorWidget *widget : widgets )
widget->changesCommitted();

newAttributeValues.insert( wIt.key(), w->currentValue() );
newAttributeValues.insert( fieldIndex, widgets.first()->currentValue() );
}

if ( newAttributeValues.isEmpty() )
Expand Down Expand Up @@ -1043,6 +1045,15 @@ void QgsAttributeForm::onAttributeChanged( const QVariant &value, const QVariant
// Updates expression controlled labels
updateLabels();

// Update other widgets pointing to the same field
const QList<QgsAttributeFormEditorWidget *> formEditorWidgets = mFormEditorWidgets.values( eww->fieldIdx() );
for ( QgsAttributeFormEditorWidget *formEditorWidget : formEditorWidgets )
{
if ( formEditorWidget->editorWidget() == eww )
continue;
formEditorWidget->editorWidget()->setValue( value );
}

if ( !signalEmitted )
{
Q_NOWARN_DEPRECATED_PUSH
Expand Down Expand Up @@ -1355,9 +1366,9 @@ void QgsAttributeForm::onConstraintStatusChanged( const QString &constraint,
QgsEditorWidgetWrapper *eww = qobject_cast<QgsEditorWidgetWrapper *>( sender() );
Q_ASSERT( eww );

QgsAttributeFormEditorWidget *formEditorWidget = mFormEditorWidgets.value( eww->fieldIdx() );
const QList<QgsAttributeFormEditorWidget *> formEditorWidgets = mFormEditorWidgets.values( eww->fieldIdx() );

if ( formEditorWidget )
for ( QgsAttributeFormEditorWidget *formEditorWidget : formEditorWidgets )
formEditorWidget->setConstraintStatus( constraint, description, err, result );
}

Expand Down Expand Up @@ -1460,9 +1471,9 @@ void QgsAttributeForm::synchronizeState()
QgsEditorWidgetWrapper *eww = qobject_cast<QgsEditorWidgetWrapper *>( ww );
if ( eww )
{
QgsAttributeFormEditorWidget *formWidget = mFormEditorWidgets.value( eww->fieldIdx() );
const QList<QgsAttributeFormEditorWidget *> formWidgets = mFormEditorWidgets.values( eww->fieldIdx() );

if ( formWidget )
for ( QgsAttributeFormEditorWidget *formWidget : formWidgets )
formWidget->setConstraintResultVisible( isEditable );

eww->setConstraintResultVisible( isEditable );
Expand Down Expand Up @@ -1877,7 +1888,7 @@ void QgsAttributeForm::init()

if ( eww )
{
addWidgetWrapper( eww );
mWidgets.append( eww );
mIconMap[eww->widget()] = i;
}

Expand Down Expand Up @@ -2484,27 +2495,6 @@ QgsAttributeForm::WidgetInfo QgsAttributeForm::createWidgetFromDef( const QgsAtt
return newWidgetInfo;
}

void QgsAttributeForm::addWidgetWrapper( QgsEditorWidgetWrapper *eww )
{
for ( QgsWidgetWrapper *ww : std::as_const( mWidgets ) )
{
QgsEditorWidgetWrapper *meww = qobject_cast<QgsEditorWidgetWrapper *>( ww );
if ( meww )
{
// if another widget wrapper exists for the same field
// synchronise them
if ( meww->field() == eww->field() )
{
connect( meww, &QgsEditorWidgetWrapper::valuesChanged, eww, &QgsEditorWidgetWrapper::setValues );
connect( eww, &QgsEditorWidgetWrapper::valuesChanged, meww, &QgsEditorWidgetWrapper::setValues );
break;
}
}
}

mWidgets.append( eww );
}

void QgsAttributeForm::createWrappers()
{
QList<QWidget *> myWidgets = findChildren<QWidget *>();
Expand Down Expand Up @@ -2538,7 +2528,7 @@ void QgsAttributeForm::createWrappers()
int idx = mLayer->fields().lookupField( field.name() );

QgsEditorWidgetWrapper *eww = QgsGui::editorWidgetRegistry()->create( mLayer, idx, myWidget, this, mContext );
addWidgetWrapper( eww );
mWidgets.append( eww );
}
}
}
Expand Down Expand Up @@ -2685,49 +2675,55 @@ void QgsAttributeForm::setMultiEditFeatureIds( const QgsFeatureIds &fids )
const auto constMixedValueFields = mixedValueFields;
for ( int fieldIndex : std::as_const( mixedValueFields ) )
{
if ( QgsAttributeFormEditorWidget *w = mFormEditorWidgets.value( fieldIndex, nullptr ) )
{
const QStringList additionalFields = w->editorWidget()->additionalFields();
QVariantList additionalFieldValues;
for ( const QString &additionalField : additionalFields )
additionalFieldValues << firstFeature.attribute( additionalField );
const QList<QgsAttributeFormEditorWidget *> formEditorWidgets = mFormEditorWidgets.values( fieldIndex );
if ( formEditorWidgets.isEmpty() )
continue;

const QStringList additionalFields = formEditorWidgets.first()->editorWidget()->additionalFields();
QVariantList additionalFieldValues;
for ( const QString &additionalField : additionalFields )
additionalFieldValues << firstFeature.attribute( additionalField );

for ( QgsAttributeFormEditorWidget *w : formEditorWidgets )
w->initialize( firstFeature.attribute( fieldIndex ), true, additionalFieldValues );
}
}
QHash< int, QVariant >::const_iterator sharedValueIt = fieldSharedValues.constBegin();
for ( ; sharedValueIt != fieldSharedValues.constEnd(); ++sharedValueIt )
{
if ( QgsAttributeFormEditorWidget *w = mFormEditorWidgets.value( sharedValueIt.key(), nullptr ) )
const QList<QgsAttributeFormEditorWidget *> formEditorWidgets = mFormEditorWidgets.values( sharedValueIt.key() );
if ( formEditorWidgets.isEmpty() )
continue;

bool mixed = false;
const QStringList additionalFields = formEditorWidgets.first()->editorWidget()->additionalFields();
for ( const QString &additionalField : additionalFields )
{
bool mixed = false;
const QStringList additionalFields = w->editorWidget()->additionalFields();
for ( const QString &additionalField : additionalFields )
int index = mLayer->fields().indexFromName( additionalField );
if ( constMixedValueFields.contains( index ) )
{
int index = mLayer->fields().indexFromName( additionalField );
if ( constMixedValueFields.contains( index ) )
{
// if additional field are mixed, it is considered as mixed
mixed = true;
break;
}
// if additional field are mixed, it is considered as mixed
mixed = true;
break;
}
QVariantList additionalFieldValues;
if ( mixed )
{
for ( const QString &additionalField : additionalFields )
additionalFieldValues << firstFeature.attribute( additionalField );
}
QVariantList additionalFieldValues;
if ( mixed )
{
for ( const QString &additionalField : additionalFields )
additionalFieldValues << firstFeature.attribute( additionalField );
for ( QgsAttributeFormEditorWidget *w : formEditorWidgets )
w->initialize( firstFeature.attribute( sharedValueIt.key() ), true, additionalFieldValues );
}
else
}
else
{
for ( const QString &additionalField : additionalFields )
{
for ( const QString &additionalField : additionalFields )
{
int index = mLayer->fields().indexFromName( additionalField );
Q_ASSERT( fieldSharedValues.contains( index ) );
additionalFieldValues << fieldSharedValues.value( index );
}
w->initialize( sharedValueIt.value(), false, additionalFieldValues );
int index = mLayer->fields().indexFromName( additionalField );
Q_ASSERT( fieldSharedValues.contains( index ) );
additionalFieldValues << fieldSharedValues.value( index );
}
for ( QgsAttributeFormEditorWidget *w : formEditorWidgets )
w->initialize( sharedValueIt.value(), false, additionalFieldValues );
}
}

Expand Down
4 changes: 1 addition & 3 deletions src/gui/qgsattributeform.h
Expand Up @@ -408,8 +408,6 @@ class GUI_EXPORT QgsAttributeForm : public QWidget

WidgetInfo createWidgetFromDef( const QgsAttributeEditorElement *widgetDef, QWidget *parent, QgsVectorLayer *vl, QgsAttributeEditorContext &context );

void addWidgetWrapper( QgsEditorWidgetWrapper *eww );

/**
* Creates widget wrappers for all suitable widgets found.
* Called once maximally.
Expand Down Expand Up @@ -465,7 +463,7 @@ class GUI_EXPORT QgsAttributeForm : public QWidget
QDialogButtonBox *mButtonBox = nullptr;
QWidget *mSearchButtonBox = nullptr;
QList<QgsAttributeFormInterface *> mInterfaces;
QMap< int, QgsAttributeFormEditorWidget * > mFormEditorWidgets;
QMultiMap< int, QgsAttributeFormEditorWidget * > mFormEditorWidgets;
QList< QgsAttributeFormWidget *> mFormWidgets;
QMap<const QgsVectorLayerJoinInfo *, QgsFeature> mJoinedFeatures;
QMap<QLabel *, QgsProperty> mLabelDataDefinedProperties;
Expand Down

0 comments on commit a65c16c

Please sign in to comment.