use composite keys in relation reference widget

This commit is contained in:
Denis Rouzaud 2019-08-26 08:27:09 +02:00
parent 19231331ba
commit c8f16fc955
3 changed files with 112 additions and 43 deletions

View File

@ -51,9 +51,19 @@ class QgsRelationReferenceWidget : QWidget
this sets the related feature using from the foreign key this sets the related feature using from the foreign key
%End %End
QVariant foreignKey() const; QVariant foreignKey() const /Deprecated/;
%Docstring %Docstring
returns the related feature foreign key 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 %End
void setEditorContext( const QgsAttributeEditorContext &context, QgsMapCanvas *canvas, QgsMessageBar *messageBar ); void setEditorContext( const QgsAttributeEditorContext &context, QgsMapCanvas *canvas, QgsMessageBar *messageBar );
@ -160,7 +170,20 @@ unset the currently related feature
void init(); void init();
signals: 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
}; };

View File

@ -203,19 +203,18 @@ void QgsRelationReferenceWidget::setRelation( const QgsRelation &relation, bool
mReferencingLayer = relation.referencingLayer(); mReferencingLayer = relation.referencingLayer();
mRelationName = relation.name(); mRelationName = relation.name();
mReferencedLayer = relation.referencedLayer(); mReferencedLayer = relation.referencedLayer();
mReferencedField = relation.fieldPairs().at( 0 ).second; const QList<QgsRelation::FieldPair> fieldPairs = relation.fieldPairs();
for ( const QgsRelation::FieldPair &fieldPair : fieldPairs )
{
mReferencedFields << fieldPair.referencedField();
}
if ( mComboBox ) if ( mComboBox )
{ {
mComboBox->setSourceLayer( mReferencedLayer ); mComboBox->setSourceLayer( mReferencedLayer );
Q_NOWARN_DEPRECATED_PUSH mComboBox->setIdentifierFields( mReferencedFields );
mComboBox->setIdentifierField( mReferencedField );
Q_NOWARN_DEPRECATED_PUSH
} }
mReferencedFieldIdx = mReferencedLayer->fields().lookupField( relation.fieldPairs().at( 0 ).second );
mAttributeEditorFrame->setObjectName( QStringLiteral( "referencing/" ) + relation.name() ); mAttributeEditorFrame->setObjectName( QStringLiteral( "referencing/" ) + relation.name() );
if ( mEmbedForm ) if ( mEmbedForm )
{ {
QgsAttributeEditorContext context( mEditorContext, relation, QgsAttributeEditorContext::Single, QgsAttributeEditorContext::Embed ); QgsAttributeEditorContext context( mEditorContext, relation, QgsAttributeEditorContext::Single, QgsAttributeEditorContext::Embed );
@ -283,7 +282,9 @@ void QgsRelationReferenceWidget::setForeignKey( const QVariant &value )
return; return;
} }
mForeignKey = mFeature.attribute( mReferencedFieldIdx ); mForeignKeys.clear();
for ( const QString &fieldName : mReferencedFields )
mForeignKeys << mFeature.attribute( fieldName );
QgsExpression expr( mReferencedLayer->displayExpression() ); QgsExpression expr( mReferencedLayer->displayExpression() );
QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( mReferencedLayer ) ); QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( mReferencedLayer ) );
@ -291,7 +292,10 @@ void QgsRelationReferenceWidget::setForeignKey( const QVariant &value )
QString title = expr.evaluate( &context ).toString(); QString title = expr.evaluate( &context ).toString();
if ( expr.hasEvalError() ) 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 ); mLineEdit->setText( title );
} }
@ -323,7 +327,7 @@ void QgsRelationReferenceWidget::setForeignKey( const QVariant &value )
highlightFeature( mFeature ); // TODO : make this async highlightFeature( mFeature ); // TODO : make this async
updateAttributeEditorFrame( mFeature ); updateAttributeEditorFrame( mFeature );
emitForeignKeyChanged( foreignKey() ); emitForeignKeysChanged( foreignKeys() );
} }
void QgsRelationReferenceWidget::deleteForeignKey() void QgsRelationReferenceWidget::deleteForeignKey()
@ -346,7 +350,13 @@ void QgsRelationReferenceWidget::deleteForeignKey()
nullText = tr( "%1 (no selection)" ).arg( nullValue ); nullText = tr( "%1 (no selection)" ).arg( nullValue );
} }
mLineEdit->setText( nullText ); 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 ); mFeature.setValid( false );
} }
else else
@ -355,7 +365,8 @@ void QgsRelationReferenceWidget::deleteForeignKey()
} }
mRemoveFKButton->setEnabled( false ); mRemoveFKButton->setEnabled( false );
updateAttributeEditorFrame( QgsFeature() ); updateAttributeEditorFrame( QgsFeature() );
emitForeignKeyChanged( QVariant( QVariant::Int ) );
emitForeignKeysChanged( foreignKeys(), true );
} }
QgsFeature QgsRelationReferenceWidget::referencedFeature() const QgsFeature QgsRelationReferenceWidget::referencedFeature() const
@ -392,16 +403,23 @@ void QgsRelationReferenceWidget::showIndeterminateState()
} }
QVariant QgsRelationReferenceWidget::foreignKey() const QVariant QgsRelationReferenceWidget::foreignKey() const
{
QVariantList fkeys;
if ( fkeys.isEmpty() )
return QVariant( QVariant::Int );
else
return fkeys.at( 0 );
}
QVariantList QgsRelationReferenceWidget::foreignKeys() const
{ {
if ( mReadOnlySelector ) if ( mReadOnlySelector )
{ {
return mForeignKey; return mForeignKeys;
} }
else else
{ {
Q_NOWARN_DEPRECATED_PUSH return mComboBox->identifierValues();
return mComboBox->identifierValue();
Q_NOWARN_DEPRECATED_POP
} }
} }
@ -549,9 +567,7 @@ void QgsRelationReferenceWidget::init()
mComboBox->setSourceLayer( mReferencedLayer ); mComboBox->setSourceLayer( mReferencedLayer );
mComboBox->setDisplayExpression( mReferencedLayer->displayExpression() ); mComboBox->setDisplayExpression( mReferencedLayer->displayExpression() );
mComboBox->setAllowNull( mAllowNull ); mComboBox->setAllowNull( mAllowNull );
Q_NOWARN_DEPRECATED_PUSH mComboBox->setIdentifierFields( mReferencedFields );
mComboBox->setIdentifierField( mReferencedField );
Q_NOWARN_DEPRECATED_POP
QVariant nullValue = QgsApplication::nullRepresentation(); QVariant nullValue = QgsApplication::nullRepresentation();
@ -706,9 +722,7 @@ void QgsRelationReferenceWidget::comboReferenceChanged( int index )
highlightFeature( mFeature ); highlightFeature( mFeature );
updateAttributeEditorFrame( mFeature ); updateAttributeEditorFrame( mFeature );
Q_NOWARN_DEPRECATED_PUSH emitForeignKeysChanged( mComboBox->identifierValues() );
emitForeignKeyChanged( mComboBox->identifierValue() );
Q_NOWARN_DEPRECATED_POP
} }
void QgsRelationReferenceWidget::updateAttributeEditorFrame( const QgsFeature &feature ) void QgsRelationReferenceWidget::updateAttributeEditorFrame( const QgsFeature &feature )
@ -742,22 +756,27 @@ void QgsRelationReferenceWidget::featureIdentified( const QgsFeature &feature )
QString title = expr.evaluate( &context ).toString(); QString title = expr.evaluate( &context ).toString();
if ( expr.hasEvalError() ) 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 ); mLineEdit->setText( title );
mForeignKey = feature.attribute( mReferencedFieldIdx ); mForeignKeys.clear();
for ( const QString &fieldName : mReferencedFields )
mForeignKeys << mFeature.attribute( fieldName );
mFeature = feature; mFeature = feature;
} }
else else
{ {
mComboBox->setCurrentIndex( mComboBox->findData( feature.attribute( mReferencedFieldIdx ), QgsFeatureFilterModel::Role::IdentifierValueRole ) ); mComboBox->setCurrentFeature( feature );
mFeature = feature; mFeature = feature;
} }
mRemoveFKButton->setEnabled( mIsEditable ); mRemoveFKButton->setEnabled( mIsEditable );
highlightFeature( feature ); highlightFeature( feature );
updateAttributeEditorFrame( feature ); updateAttributeEditorFrame( feature );
emit foreignKeyChanged( foreignKey() ); emitForeignKeysChanged( foreignKeys(), true );
unsetMapTool(); unsetMapTool();
} }
@ -909,9 +928,12 @@ void QgsRelationReferenceWidget::addEntry()
if ( mEditorContext.vectorLayerTools()->addFeature( mReferencedLayer, attributes, QgsGeometry(), &f ) ) if ( mEditorContext.vectorLayerTools()->addFeature( mReferencedLayer, attributes, QgsGeometry(), &f ) )
{ {
Q_NOWARN_DEPRECATED_PUSH QVariantList attrs;
mComboBox->setIdentifierValue( f.attribute( mReferencedFieldIdx ) ); for ( const QString &fieldName : mReferencedFields )
Q_NOWARN_DEPRECATED_POP attrs << mFeature.attribute( fieldName );
mComboBox->setIdentifierValues( attrs );
mAddEntryButton->setEnabled( false ); 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() ) if ( foreignKeys == mForeignKeys && force == false )
{ return;
mForeignKey = foreignKey;
emit foreignKeyChanged( foreignKey ); mForeignKeys = foreignKeys;
} Q_NOWARN_DEPRECATED_PUSH
emit foreignKeyChanged( foreignKeys.at( 0 ) );
Q_NOWARN_DEPRECATED_POP
emit foreignKeysChanged( foreignKeys );
} }

View File

@ -86,8 +86,19 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget
//! this sets the related feature using from the foreign key //! this sets the related feature using from the foreign key
void setForeignKey( const QVariant &value ); 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 //! 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 ); void setEditorContext( const QgsAttributeEditorContext &context, QgsMapCanvas *canvas, QgsMessageBar *messageBar );
@ -171,7 +182,18 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget
void init(); void init();
signals: 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: private slots:
void highlightActionTriggered( QAction *action ); void highlightActionTriggered( QAction *action );
@ -194,17 +216,16 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget
void highlightFeature( QgsFeature f = QgsFeature(), CanvasExtent canvasExtent = Fixed ); void highlightFeature( QgsFeature f = QgsFeature(), CanvasExtent canvasExtent = Fixed );
void updateAttributeEditorFrame( const QgsFeature &feature ); void updateAttributeEditorFrame( const QgsFeature &feature );
void disableChainedComboBoxes( const QComboBox *cb ); void disableChainedComboBoxes( const QComboBox *cb );
void emitForeignKeyChanged( const QVariant &foreignKey ); void emitForeignKeysChanged( const QVariantList &foreignKeys, bool force = false );
// initialized // initialized
QgsAttributeEditorContext mEditorContext; QgsAttributeEditorContext mEditorContext;
QgsMapCanvas *mCanvas = nullptr; QgsMapCanvas *mCanvas = nullptr;
QgsMessageBar *mMessageBar = nullptr; QgsMessageBar *mMessageBar = nullptr;
QVariant mForeignKey; QVariantList mForeignKeys;
QgsFeature mFeature; QgsFeature mFeature;
// Index of the referenced layer key // Index of the referenced layer key
int mReferencedFieldIdx = -1; QStringList mReferencedFields;
QString mReferencedField;
bool mAllowNull = true; bool mAllowNull = true;
QgsHighlight *mHighlight = nullptr; QgsHighlight *mHighlight = nullptr;
QgsMapToolIdentifyFeature *mMapTool = nullptr; QgsMapToolIdentifyFeature *mMapTool = nullptr;