From c8f16fc955c04d6fd03d8912961b39c28bdffa86 Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Mon, 26 Aug 2019 08:27:09 +0200 Subject: [PATCH] use composite keys in relation reference widget --- .../qgsrelationreferencewidget.sip.in | 27 +++++- .../qgsrelationreferencewidget.cpp | 95 ++++++++++++------- .../qgsrelationreferencewidget.h | 33 +++++-- 3 files changed, 112 insertions(+), 43 deletions(-) diff --git a/python/gui/auto_generated/editorwidgets/qgsrelationreferencewidget.sip.in b/python/gui/auto_generated/editorwidgets/qgsrelationreferencewidget.sip.in index cd692f9744c..44e5c41f19c 100644 --- a/python/gui/auto_generated/editorwidgets/qgsrelationreferencewidget.sip.in +++ b/python/gui/auto_generated/editorwidgets/qgsrelationreferencewidget.sip.in @@ -51,9 +51,19 @@ class QgsRelationReferenceWidget : QWidget this sets the related feature using from the foreign key %End - QVariant foreignKey() const; + QVariant foreignKey() const /Deprecated/; %Docstring returns the related feature foreign key + +.. deprecated:: since QGIS 3.10 +%End + + + QVariantList foreignKeys() const; +%Docstring +Returns the related feature foreign keys + +.. versionadded:: 3.10 %End void setEditorContext( const QgsAttributeEditorContext &context, QgsMapCanvas *canvas, QgsMessageBar *messageBar ); @@ -160,7 +170,20 @@ unset the currently related feature void init(); signals: - void foreignKeyChanged( const QVariant & ); + + void foreignKeyChanged( const QVariant & ) /Deprecated/; +%Docstring +Emitted when the foreign key changed + +.. deprecated:: since QGIS 3.10 +%End + + void foreignKeysChanged( const QVariantList & ); +%Docstring +Emitted when the foreign keys changed + +.. versionadded:: 3.10 +%End }; diff --git a/src/gui/editorwidgets/qgsrelationreferencewidget.cpp b/src/gui/editorwidgets/qgsrelationreferencewidget.cpp index 94c4619f39a..6aff8913899 100644 --- a/src/gui/editorwidgets/qgsrelationreferencewidget.cpp +++ b/src/gui/editorwidgets/qgsrelationreferencewidget.cpp @@ -203,19 +203,18 @@ void QgsRelationReferenceWidget::setRelation( const QgsRelation &relation, bool mReferencingLayer = relation.referencingLayer(); mRelationName = relation.name(); mReferencedLayer = relation.referencedLayer(); - mReferencedField = relation.fieldPairs().at( 0 ).second; + const QList fieldPairs = relation.fieldPairs(); + for ( const QgsRelation::FieldPair &fieldPair : fieldPairs ) + { + mReferencedFields << fieldPair.referencedField(); + } if ( mComboBox ) { mComboBox->setSourceLayer( mReferencedLayer ); - Q_NOWARN_DEPRECATED_PUSH - mComboBox->setIdentifierField( mReferencedField ); - Q_NOWARN_DEPRECATED_PUSH + mComboBox->setIdentifierFields( mReferencedFields ); } - - mReferencedFieldIdx = mReferencedLayer->fields().lookupField( relation.fieldPairs().at( 0 ).second ); mAttributeEditorFrame->setObjectName( QStringLiteral( "referencing/" ) + relation.name() ); - if ( mEmbedForm ) { QgsAttributeEditorContext context( mEditorContext, relation, QgsAttributeEditorContext::Single, QgsAttributeEditorContext::Embed ); @@ -283,7 +282,9 @@ void QgsRelationReferenceWidget::setForeignKey( const QVariant &value ) return; } - mForeignKey = mFeature.attribute( mReferencedFieldIdx ); + mForeignKeys.clear(); + for ( const QString &fieldName : mReferencedFields ) + mForeignKeys << mFeature.attribute( fieldName ); QgsExpression expr( mReferencedLayer->displayExpression() ); QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( mReferencedLayer ) ); @@ -291,7 +292,10 @@ void QgsRelationReferenceWidget::setForeignKey( const QVariant &value ) QString title = expr.evaluate( &context ).toString(); if ( expr.hasEvalError() ) { - title = mFeature.attribute( mReferencedFieldIdx ).toString(); + QStringList titleFields; + for ( const QString &fieldName : mReferencedFields ) + titleFields << mFeature.attribute( fieldName ).toString(); + title = titleFields.join( QStringLiteral( " " ) ); } mLineEdit->setText( title ); } @@ -323,7 +327,7 @@ void QgsRelationReferenceWidget::setForeignKey( const QVariant &value ) highlightFeature( mFeature ); // TODO : make this async updateAttributeEditorFrame( mFeature ); - emitForeignKeyChanged( foreignKey() ); + emitForeignKeysChanged( foreignKeys() ); } void QgsRelationReferenceWidget::deleteForeignKey() @@ -346,7 +350,13 @@ void QgsRelationReferenceWidget::deleteForeignKey() nullText = tr( "%1 (no selection)" ).arg( nullValue ); } mLineEdit->setText( nullText ); - mForeignKey = QVariant( QVariant::Int ); + QVariantList nullAttributes; + for ( const QString &fieldName : mReferencedFields ) + { + Q_UNUSED( fieldName ); + nullAttributes << QVariant( QVariant::Int ); + } + mForeignKeys = nullAttributes; mFeature.setValid( false ); } else @@ -355,7 +365,8 @@ void QgsRelationReferenceWidget::deleteForeignKey() } mRemoveFKButton->setEnabled( false ); updateAttributeEditorFrame( QgsFeature() ); - emitForeignKeyChanged( QVariant( QVariant::Int ) ); + + emitForeignKeysChanged( foreignKeys(), true ); } QgsFeature QgsRelationReferenceWidget::referencedFeature() const @@ -392,16 +403,23 @@ void QgsRelationReferenceWidget::showIndeterminateState() } QVariant QgsRelationReferenceWidget::foreignKey() const +{ + QVariantList fkeys; + if ( fkeys.isEmpty() ) + return QVariant( QVariant::Int ); + else + return fkeys.at( 0 ); +} + +QVariantList QgsRelationReferenceWidget::foreignKeys() const { if ( mReadOnlySelector ) { - return mForeignKey; + return mForeignKeys; } else { - Q_NOWARN_DEPRECATED_PUSH - return mComboBox->identifierValue(); - Q_NOWARN_DEPRECATED_POP + return mComboBox->identifierValues(); } } @@ -549,9 +567,7 @@ void QgsRelationReferenceWidget::init() mComboBox->setSourceLayer( mReferencedLayer ); mComboBox->setDisplayExpression( mReferencedLayer->displayExpression() ); mComboBox->setAllowNull( mAllowNull ); - Q_NOWARN_DEPRECATED_PUSH - mComboBox->setIdentifierField( mReferencedField ); - Q_NOWARN_DEPRECATED_POP + mComboBox->setIdentifierFields( mReferencedFields ); QVariant nullValue = QgsApplication::nullRepresentation(); @@ -706,9 +722,7 @@ void QgsRelationReferenceWidget::comboReferenceChanged( int index ) highlightFeature( mFeature ); updateAttributeEditorFrame( mFeature ); - Q_NOWARN_DEPRECATED_PUSH - emitForeignKeyChanged( mComboBox->identifierValue() ); - Q_NOWARN_DEPRECATED_POP + emitForeignKeysChanged( mComboBox->identifierValues() ); } void QgsRelationReferenceWidget::updateAttributeEditorFrame( const QgsFeature &feature ) @@ -742,22 +756,27 @@ void QgsRelationReferenceWidget::featureIdentified( const QgsFeature &feature ) QString title = expr.evaluate( &context ).toString(); if ( expr.hasEvalError() ) { - title = feature.attribute( mReferencedFieldIdx ).toString(); + QStringList titleFields; + for ( const QString &fieldName : mReferencedFields ) + titleFields << mFeature.attribute( fieldName ).toString(); + title = titleFields.join( QStringLiteral( " " ) ); } mLineEdit->setText( title ); - mForeignKey = feature.attribute( mReferencedFieldIdx ); + mForeignKeys.clear(); + for ( const QString &fieldName : mReferencedFields ) + mForeignKeys << mFeature.attribute( fieldName ); mFeature = feature; } else { - mComboBox->setCurrentIndex( mComboBox->findData( feature.attribute( mReferencedFieldIdx ), QgsFeatureFilterModel::Role::IdentifierValueRole ) ); + mComboBox->setCurrentFeature( feature ); mFeature = feature; } mRemoveFKButton->setEnabled( mIsEditable ); highlightFeature( feature ); updateAttributeEditorFrame( feature ); - emit foreignKeyChanged( foreignKey() ); + emitForeignKeysChanged( foreignKeys(), true ); unsetMapTool(); } @@ -909,9 +928,12 @@ void QgsRelationReferenceWidget::addEntry() if ( mEditorContext.vectorLayerTools()->addFeature( mReferencedLayer, attributes, QgsGeometry(), &f ) ) { - Q_NOWARN_DEPRECATED_PUSH - mComboBox->setIdentifierValue( f.attribute( mReferencedFieldIdx ) ); - Q_NOWARN_DEPRECATED_POP + QVariantList attrs; + for ( const QString &fieldName : mReferencedFields ) + attrs << mFeature.attribute( fieldName ); + + mComboBox->setIdentifierValues( attrs ); + mAddEntryButton->setEnabled( false ); } } @@ -948,11 +970,14 @@ void QgsRelationReferenceWidget::disableChainedComboBoxes( const QComboBox *scb } } -void QgsRelationReferenceWidget::emitForeignKeyChanged( const QVariant &foreignKey ) +void QgsRelationReferenceWidget::emitForeignKeysChanged( const QVariantList &foreignKeys, bool force ) { - if ( foreignKey != mForeignKey || foreignKey.isNull() != mForeignKey.isNull() ) - { - mForeignKey = foreignKey; - emit foreignKeyChanged( foreignKey ); - } + if ( foreignKeys == mForeignKeys && force == false ) + return; + + mForeignKeys = foreignKeys; + Q_NOWARN_DEPRECATED_PUSH + emit foreignKeyChanged( foreignKeys.at( 0 ) ); + Q_NOWARN_DEPRECATED_POP + emit foreignKeysChanged( foreignKeys ); } diff --git a/src/gui/editorwidgets/qgsrelationreferencewidget.h b/src/gui/editorwidgets/qgsrelationreferencewidget.h index 1f194cfb138..dd91a9b6232 100644 --- a/src/gui/editorwidgets/qgsrelationreferencewidget.h +++ b/src/gui/editorwidgets/qgsrelationreferencewidget.h @@ -86,8 +86,19 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget //! this sets the related feature using from the foreign key void setForeignKey( const QVariant &value ); + /** + * returns the related feature foreign key + * \deprecated since QGIS 3.10 + */ + Q_DECL_DEPRECATED QVariant foreignKey() const SIP_DEPRECATED; + //! returns the related feature foreign key - QVariant foreignKey() const; + + /** + * Returns the related feature foreign keys + * \since QGIS 3.10 + */ + QVariantList foreignKeys() const; void setEditorContext( const QgsAttributeEditorContext &context, QgsMapCanvas *canvas, QgsMessageBar *messageBar ); @@ -171,7 +182,18 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget void init(); signals: - void foreignKeyChanged( const QVariant & ); + + /** + * Emitted when the foreign key changed + * \deprecated since QGIS 3.10 + */ + Q_DECL_DEPRECATED void foreignKeyChanged( const QVariant & ) SIP_DEPRECATED; + + /** + * Emitted when the foreign keys changed + * \since QGIS 3.10 + */ + void foreignKeysChanged( const QVariantList & ); private slots: void highlightActionTriggered( QAction *action ); @@ -194,17 +216,16 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget void highlightFeature( QgsFeature f = QgsFeature(), CanvasExtent canvasExtent = Fixed ); void updateAttributeEditorFrame( const QgsFeature &feature ); void disableChainedComboBoxes( const QComboBox *cb ); - void emitForeignKeyChanged( const QVariant &foreignKey ); + void emitForeignKeysChanged( const QVariantList &foreignKeys, bool force = false ); // initialized QgsAttributeEditorContext mEditorContext; QgsMapCanvas *mCanvas = nullptr; QgsMessageBar *mMessageBar = nullptr; - QVariant mForeignKey; + QVariantList mForeignKeys; QgsFeature mFeature; // Index of the referenced layer key - int mReferencedFieldIdx = -1; - QString mReferencedField; + QStringList mReferencedFields; bool mAllowNull = true; QgsHighlight *mHighlight = nullptr; QgsMapToolIdentifyFeature *mMapTool = nullptr;