mirror of
https://github.com/qgis/QGIS.git
synced 2025-06-19 00:02:48 -04:00
Sort attribute table by representation value where useful
Fix #15096 And aligns some edge-cases of sort behavior
This commit is contained in:
parent
31fc2b0c12
commit
56a0af5bd8
@ -123,6 +123,21 @@ class QgsEditorWidgetFactory
|
||||
*/
|
||||
virtual QString representValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const;
|
||||
|
||||
/**
|
||||
* If the default sort order should be overwritten for this widget, you can transform the value in here.
|
||||
*
|
||||
* @param vl The vector layer.
|
||||
* @param fieldIdx The index of the field.
|
||||
* @param config The editor widget config.
|
||||
* @param cache The editor widget cache.
|
||||
* @param value The value to represent.
|
||||
*
|
||||
* @return By default the value is returned unmodified.
|
||||
*
|
||||
* @note Added in 2.16
|
||||
*/
|
||||
virtual QVariant sortValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const;
|
||||
|
||||
/**
|
||||
* Return the alignment for a particular field. By default this will consider the field type but can be overwritten if mapped
|
||||
* values are represented.
|
||||
|
@ -69,19 +69,24 @@ class QgsRelationReferenceWidget : QWidget
|
||||
|
||||
//! return the related feature (from the referenced layer)
|
||||
//! if no feature is related, it returns an invalid feature
|
||||
QgsFeature referencedFeature();
|
||||
QgsFeature referencedFeature() const;
|
||||
|
||||
/** Sets the widget to display in an indeterminate "mixed value" state.
|
||||
* @note added in QGIS 2.16
|
||||
*/
|
||||
void showIndeterminateState();
|
||||
|
||||
/**
|
||||
* Determines if a button for adding new features should be shown.
|
||||
*
|
||||
* @note added in QGIS 2.16
|
||||
*/
|
||||
bool allowAddFeatures() const;
|
||||
|
||||
/**
|
||||
* Determines if a button for adding new features should be shown.
|
||||
*
|
||||
* @note added in QGIS 2.16
|
||||
*/
|
||||
void setAllowAddFeatures( bool allowAddFeatures );
|
||||
|
||||
|
@ -40,6 +40,7 @@ QgsAttributeTableModel::QgsAttributeTableModel( QgsVectorLayerCache *layerCache,
|
||||
, mLayerCache( layerCache )
|
||||
, mFieldCount( 0 )
|
||||
, mSortCacheExpression( "" )
|
||||
, mSortFieldIndex( -1 )
|
||||
, mExtraColumns( 0 )
|
||||
{
|
||||
mExpressionContext << QgsExpressionContextUtils::globalScope()
|
||||
@ -206,8 +207,19 @@ void QgsAttributeTableModel::featureAdded( QgsFeatureId fid )
|
||||
|
||||
if ( featOk && mFeatureRequest.acceptFeature( mFeat ) )
|
||||
{
|
||||
mExpressionContext.setFeature( mFeat );
|
||||
mSortCache[fid] = mSortCacheExpression.evaluate();
|
||||
if ( mSortFieldIndex == -1 )
|
||||
{
|
||||
mExpressionContext.setFeature( mFeat );
|
||||
mSortCache[mFeat.id()] = mSortCacheExpression.evaluate( &mExpressionContext );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsEditorWidgetFactory* widgetFactory = mWidgetFactories.at( mSortFieldIndex );
|
||||
const QVariant& widgetCache = mAttributeWidgetCaches.at( mSortFieldIndex );
|
||||
const QgsEditorWidgetConfig& widgetConfig = mWidgetConfigs.at( mSortFieldIndex );
|
||||
QVariant sortValue = widgetFactory->representValue( layer(), mSortFieldIndex, widgetConfig, widgetCache, mFeat.attribute( mSortFieldIndex ) );
|
||||
mSortCache.insert( mFeat.id(), sortValue );
|
||||
}
|
||||
|
||||
int n = mRowIdMap.size();
|
||||
beginInsertRows( QModelIndex(), n, n );
|
||||
@ -257,10 +269,20 @@ void QgsAttributeTableModel::attributeValueChanged( QgsFeatureId fid, int idx, c
|
||||
|
||||
if ( mSortCacheAttributes.contains( idx ) )
|
||||
{
|
||||
// if the expression used multiple fields, this will not work but this way we don't have
|
||||
// to run the expensive query in the 80% cases where we just have a simple column for sorting
|
||||
// or it's the first used column, this works just fine
|
||||
mSortCache[fid] = value;
|
||||
if ( mSortFieldIndex == -1 )
|
||||
{
|
||||
loadFeatureAtId( fid );
|
||||
mExpressionContext.setFeature( mFeat );
|
||||
mSortCache[fid] = mSortCacheExpression.evaluate( &mExpressionContext );
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsEditorWidgetFactory* widgetFactory = mWidgetFactories.at( mSortFieldIndex );
|
||||
const QVariant& widgetCache = mAttributeWidgetCaches.at( mSortFieldIndex );
|
||||
const QgsEditorWidgetConfig& widgetConfig = mWidgetConfigs.at( mSortFieldIndex );
|
||||
QVariant sortValue = widgetFactory->representValue( layer(), mSortFieldIndex, widgetConfig, widgetCache, value );
|
||||
mSortCache.insert( fid, sortValue );
|
||||
}
|
||||
}
|
||||
// No filter request: skip all possibly heavy checks
|
||||
if ( mFeatureRequest.filterType() == QgsFeatureRequest::FilterNone )
|
||||
@ -341,6 +363,9 @@ void QgsAttributeTableModel::loadAttributes()
|
||||
mFieldCount = attributes.size();
|
||||
mAttributes = attributes;
|
||||
|
||||
if ( mSortFieldIndex >= mAttributes.count() )
|
||||
mSortFieldIndex = -1;
|
||||
|
||||
if ( ins )
|
||||
{
|
||||
endInsertColumns();
|
||||
@ -373,8 +398,7 @@ void QgsAttributeTableModel::loadLayer()
|
||||
QTime t;
|
||||
t.start();
|
||||
|
||||
QgsFeature feat;
|
||||
while ( features.nextFeature( feat ) )
|
||||
while ( features.nextFeature( mFeat ) )
|
||||
{
|
||||
++i;
|
||||
|
||||
@ -387,8 +411,7 @@ void QgsAttributeTableModel::loadLayer()
|
||||
|
||||
t.restart();
|
||||
}
|
||||
mFeat = feat;
|
||||
featureAdded( feat.id() );
|
||||
featureAdded( mFeat.id() );
|
||||
}
|
||||
|
||||
emit finished();
|
||||
@ -758,14 +781,35 @@ void QgsAttributeTableModel::prefetchSortData( const QString& expressionString )
|
||||
{
|
||||
mSortCache.clear();
|
||||
mSortCacheAttributes.clear();
|
||||
|
||||
mSortFieldIndex = -1;
|
||||
mSortCacheExpression = QgsExpression( expressionString );
|
||||
|
||||
mSortCacheExpression.prepare( &mExpressionContext );
|
||||
QgsEditorWidgetFactory* widgetFactory = nullptr;
|
||||
QVariant widgetCache;
|
||||
QgsEditorWidgetConfig widgetConfig;
|
||||
|
||||
Q_FOREACH ( const QString& col, mSortCacheExpression.referencedColumns() )
|
||||
if ( mSortCacheExpression.isField() )
|
||||
{
|
||||
mSortCacheAttributes.append( mLayerCache->layer()->fieldNameIndex( col ) );
|
||||
QString fieldName = dynamic_cast<const QgsExpression::NodeColumnRef*>( mSortCacheExpression.rootNode() )->name();
|
||||
mSortFieldIndex = mLayerCache->layer()->fieldNameIndex( fieldName );
|
||||
}
|
||||
|
||||
if ( mSortFieldIndex == -1 )
|
||||
{
|
||||
mSortCacheExpression.prepare( &mExpressionContext );
|
||||
|
||||
Q_FOREACH ( const QString& col, mSortCacheExpression.referencedColumns() )
|
||||
{
|
||||
mSortCacheAttributes.append( mLayerCache->layer()->fieldNameIndex( col ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mSortCacheAttributes.append( mSortFieldIndex );
|
||||
|
||||
widgetFactory = mWidgetFactories.at( mSortFieldIndex );
|
||||
widgetCache = mAttributeWidgetCaches.at( mSortFieldIndex );
|
||||
widgetConfig = mWidgetConfigs.at( mSortFieldIndex );
|
||||
}
|
||||
|
||||
QgsFeatureRequest request = QgsFeatureRequest( mFeatureRequest )
|
||||
@ -776,8 +820,16 @@ void QgsAttributeTableModel::prefetchSortData( const QString& expressionString )
|
||||
QgsFeature f;
|
||||
while ( it.nextFeature( f ) )
|
||||
{
|
||||
mExpressionContext.setFeature( f );
|
||||
mSortCache.insert( f.id(), mSortCacheExpression.evaluate( &mExpressionContext ) );
|
||||
if ( mSortFieldIndex == -1 )
|
||||
{
|
||||
mExpressionContext.setFeature( f );
|
||||
mSortCache.insert( f.id(), mSortCacheExpression.evaluate( &mExpressionContext ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
QVariant sortValue = widgetFactory->representValue( layer(), mSortFieldIndex, widgetConfig, widgetCache, f.attribute( mSortFieldIndex ) );
|
||||
mSortCache.insert( f.id(), sortValue );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,6 +218,7 @@ class GUI_EXPORT QgsAttributeTableModel: public QAbstractTableModel
|
||||
/**
|
||||
* Get the the feature request
|
||||
*/
|
||||
// TODO QGIS 3: return copy instead of reference
|
||||
const QgsFeatureRequest& request() const;
|
||||
|
||||
/**
|
||||
@ -350,6 +351,8 @@ class GUI_EXPORT QgsAttributeTableModel: public QAbstractTableModel
|
||||
/** The currently cached column */
|
||||
QgsExpression mSortCacheExpression;
|
||||
QgsAttributeList mSortCacheAttributes;
|
||||
/** If it is set, a simple field is used for sorting, if it's -1 it's the mSortCacheExpression*/
|
||||
int mSortFieldIndex;
|
||||
/** Allows caching of one value per column (used for sorting) */
|
||||
QHash<QgsFeatureId, QVariant> mSortCache;
|
||||
|
||||
|
@ -75,6 +75,15 @@ QString QgsEditorWidgetFactory::representValue( QgsVectorLayer* vl, int fieldIdx
|
||||
return value == defVal ? defVal : vl->fields().at( fieldIdx ).displayString( value );
|
||||
}
|
||||
|
||||
QVariant QgsEditorWidgetFactory::sortValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const
|
||||
{
|
||||
Q_UNUSED( vl )
|
||||
Q_UNUSED( fieldIdx )
|
||||
Q_UNUSED( config )
|
||||
Q_UNUSED( cache )
|
||||
return value;
|
||||
}
|
||||
|
||||
Qt::AlignmentFlag QgsEditorWidgetFactory::alignmentFlag( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config ) const
|
||||
{
|
||||
Q_UNUSED( config );
|
||||
|
@ -138,6 +138,21 @@ class GUI_EXPORT QgsEditorWidgetFactory
|
||||
*/
|
||||
virtual QString representValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const;
|
||||
|
||||
/**
|
||||
* If the default sort order should be overwritten for this widget, you can transform the value in here.
|
||||
*
|
||||
* @param vl The vector layer.
|
||||
* @param fieldIdx The index of the field.
|
||||
* @param config The editor widget config.
|
||||
* @param cache The editor widget cache.
|
||||
* @param value The value to represent.
|
||||
*
|
||||
* @return By default the value is returned unmodified.
|
||||
*
|
||||
* @note Added in 2.16
|
||||
*/
|
||||
virtual QVariant sortValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const;
|
||||
|
||||
/**
|
||||
* Return the alignment for a particular field. By default this will consider the field type but can be overwritten if mapped
|
||||
* values are represented.
|
||||
|
@ -171,3 +171,8 @@ QString QgsRelationReferenceFactory::representValue( QgsVectorLayer* vl, int fie
|
||||
}
|
||||
return title;
|
||||
}
|
||||
|
||||
QVariant QgsRelationReferenceFactory::sortValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const
|
||||
{
|
||||
return representValue( vl, fieldIdx, config, cache, value );
|
||||
}
|
||||
|
@ -82,7 +82,9 @@ class GUI_EXPORT QgsRelationReferenceFactory : public QgsEditorWidgetFactory
|
||||
*/
|
||||
virtual void writeConfig( const QgsEditorWidgetConfig& config, QDomElement& configElement, QDomDocument& doc, const QgsVectorLayer* layer, int fieldIdx ) override;
|
||||
|
||||
QString representValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const override;
|
||||
virtual QString representValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const override;
|
||||
|
||||
virtual QVariant sortValue( QgsVectorLayer *vl, int fieldIdx, const QgsEditorWidgetConfig &config, const QVariant &cache, const QVariant &value ) const override;
|
||||
|
||||
virtual QMap<const char*, int> supportedWidgetTypes() override;
|
||||
|
||||
|
@ -89,6 +89,11 @@ QString QgsValueMapWidgetFactory::representValue( QgsVectorLayer* vl, int fieldI
|
||||
return config.key( value, QVariant( QString( "(%1)" ).arg( value.toString() ) ).toString() );
|
||||
}
|
||||
|
||||
QVariant QgsValueMapWidgetFactory::sortValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const
|
||||
{
|
||||
return representValue( vl, fieldIdx, config, cache, value );
|
||||
}
|
||||
|
||||
Qt::AlignmentFlag QgsValueMapWidgetFactory::alignmentFlag( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config ) const
|
||||
{
|
||||
Q_UNUSED( vl );
|
||||
|
@ -36,6 +36,7 @@ class GUI_EXPORT QgsValueMapWidgetFactory : public QgsEditorWidgetFactory
|
||||
QgsEditorWidgetConfig readConfig( const QDomElement& configElement, QgsVectorLayer* layer, int fieldIdx ) override;
|
||||
void writeConfig( const QgsEditorWidgetConfig& config, QDomElement& configElement, QDomDocument& doc, const QgsVectorLayer* layer, int fieldIdx ) override;
|
||||
QString representValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const override;
|
||||
QVariant sortValue( QgsVectorLayer *vl, int fieldIdx, const QgsEditorWidgetConfig &config, const QVariant &cache, const QVariant &value ) const override;
|
||||
Qt::AlignmentFlag alignmentFlag( QgsVectorLayer *vl, int fieldIdx, const QgsEditorWidgetConfig &config ) const override;
|
||||
virtual QMap<const char*, int> supportedWidgetTypes() override;
|
||||
};
|
||||
|
@ -130,6 +130,11 @@ QString QgsValueRelationWidgetFactory::representValue( QgsVectorLayer* vl, int f
|
||||
return QString( "(%1)" ).arg( value.toString() );
|
||||
}
|
||||
|
||||
QVariant QgsValueRelationWidgetFactory::sortValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const
|
||||
{
|
||||
return representValue( vl, fieldIdx, config, cache, value );
|
||||
}
|
||||
|
||||
Qt::AlignmentFlag QgsValueRelationWidgetFactory::alignmentFlag( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config ) const
|
||||
{
|
||||
Q_UNUSED( vl );
|
||||
|
@ -39,6 +39,7 @@ class GUI_EXPORT QgsValueRelationWidgetFactory : public QgsEditorWidgetFactory
|
||||
QgsEditorWidgetConfig readConfig( const QDomElement& configElement, QgsVectorLayer* layer, int fieldIdx ) override;
|
||||
void writeConfig( const QgsEditorWidgetConfig& config, QDomElement& configElement, QDomDocument& doc, const QgsVectorLayer* layer, int fieldIdx ) override;
|
||||
QString representValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const override;
|
||||
QVariant sortValue( QgsVectorLayer *vl, int fieldIdx, const QgsEditorWidgetConfig &config, const QVariant &cache, const QVariant &value ) const override;
|
||||
Qt::AlignmentFlag alignmentFlag( QgsVectorLayer *vl, int fieldIdx, const QgsEditorWidgetConfig &config ) const override;
|
||||
QVariant createCache( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config ) override;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user