Skip to content

Commit

Permalink
Add cache for relation reference field formatter
Browse files Browse the repository at this point in the history
this speeds up tables with relation reference fields massively
  • Loading branch information
m-kuhn committed Feb 20, 2019
1 parent eceaea8 commit 5fe225b
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 1 deletion.
Expand Up @@ -35,6 +35,9 @@ Default constructor of field formatter for a relation reference field.

virtual QVariant sortValue( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value ) const;


virtual QVariant createCache( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config ) const;

};

/************************************************************************
Expand Down
64 changes: 63 additions & 1 deletion src/core/fieldformatter/qgsrelationreferencefieldformatter.cpp
Expand Up @@ -30,7 +30,10 @@ QString QgsRelationReferenceFieldFormatter::id() const

QString QgsRelationReferenceFieldFormatter::representValue( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value ) const
{
Q_UNUSED( cache );
if ( cache.isValid() )
{
return cache.value<QMap<QVariant, QString>>().value( value );
}

// Some sanity checks
if ( !config.contains( QStringLiteral( "Relation" ) ) )
Expand Down Expand Up @@ -90,3 +93,62 @@ QVariant QgsRelationReferenceFieldFormatter::sortValue( QgsVectorLayer *layer, i
{
return representValue( layer, fieldIndex, config, cache, value );
}

QVariant QgsRelationReferenceFieldFormatter::createCache( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config ) const
{
Q_UNUSED( fieldIndex );
QMap<QVariant, QString> cache;

// Some sanity checks
if ( !config.contains( QStringLiteral( "Relation" ) ) )
{
QgsMessageLog::logMessage( QObject::tr( "Missing Relation in configuration" ) );
return QVariant();
}
QgsRelation relation = QgsProject::instance()->relationManager()->relation( config[QStringLiteral( "Relation" )].toString() );
if ( !relation.isValid() )
{
QgsMessageLog::logMessage( QObject::tr( "Invalid relation" ) );
return QVariant();
}
QgsVectorLayer *referencingLayer = relation.referencingLayer();
if ( layer != referencingLayer )
{
QgsMessageLog::logMessage( QObject::tr( "representValue() with inconsistent layer parameter w.r.t relation referencingLayer" ) );
return QVariant();
}
QgsVectorLayer *referencedLayer = relation.referencedLayer();
if ( !referencedLayer )
{
QgsMessageLog::logMessage( QObject::tr( "Cannot find referenced layer" ) );
return QVariant();
}
int referencedFieldIdx = referencedLayer->fields().lookupField( relation.fieldPairs().at( 0 ).second );
if ( referencedFieldIdx == -1 )
{
QgsMessageLog::logMessage( QObject::tr( "Invalid referenced field (%1) configured in relation %2" ).arg( relation.fieldPairs().at( 0 ).second, relation.name() ) );
return QVariant();
}

QgsFeature feature;
auto iterator = referencedLayer->getFeatures();

QgsExpression expr( referencedLayer->displayExpression() );
QgsExpressionContext context( QgsExpressionContextUtils::globalProjectLayerScopes( referencedLayer ) );

while ( iterator.nextFeature( feature ) )
{
context.setFeature( feature );
QString title = expr.evaluate( &context ).toString();

if ( expr.hasEvalError() )
{
int referencedFieldIdx = referencedLayer->fields().lookupField( relation.fieldPairs().at( 0 ).second );
title = feature.attribute( referencedFieldIdx ).toString();
}

cache.insert( feature.attribute( referencedFieldIdx ), title );
}

return QVariant::fromValue<QMap<QVariant, QString>>( cache );
}
2 changes: 2 additions & 0 deletions src/core/fieldformatter/qgsrelationreferencefieldformatter.h
Expand Up @@ -41,6 +41,8 @@ class CORE_EXPORT QgsRelationReferenceFieldFormatter : public QgsFieldFormatter
QString representValue( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value ) const override;

QVariant sortValue( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config, const QVariant &cache, const QVariant &value ) const override;

QVariant createCache( QgsVectorLayer *layer, int fieldIndex, const QVariantMap &config ) const override;
};

#endif // QGSRELATIONREFERENCEFIELDKIT_H

0 comments on commit 5fe225b

Please sign in to comment.