Skip to content
Permalink
Browse files
Change QgsVectorLayer::featureCount( QgsSymbol* symbol ) to instead
use a legend key string

Avoids crashes due to symbol pointer lifetime issues
  • Loading branch information
nyalldawson committed Dec 2, 2016
1 parent 42d3f4b commit 6d0203d61203bc5f2d034a8d7e6b12e6f4827308
Showing with 17 additions and 18 deletions.
  1. +1 −0 doc/api_break.dox
  2. +3 −4 python/core/qgsvectorlayer.sip
  3. +2 −2 src/core/layertree/qgslayertreemodellegendnode.cpp
  4. +6 −6 src/core/qgsvectorlayer.cpp
  5. +5 −6 src/core/qgsvectorlayer.h
@@ -1572,6 +1572,7 @@ displayExpression instead. For the map tip use mapTipTemplate() instead.
- getStyleFromDatabase(): msgError argument is correctly declared as output argument
- loadNamedStyle(): theResultFlag argument is correctly declared as output argument
- The duplicate selectionChanged() signal was removed. Use selectionChanged( const QgsFeatureIds&, const QgsFeatureIds&, const bool ) instead.
- featureCount() now requires a legend key string instead of a QgsSymbol pointer argument.

QgsVectorLayerEditBuffer {#qgis_api_break_3_0_QgsVectorLayerEditBuffer}
------------------------
@@ -732,12 +732,11 @@ class QgsVectorLayer : QgsMapLayer, QgsExpressionContextGenerator
bool readSld( const QDomNode& node, QString& errorMessage );

/**
* Number of features rendered with specified symbol. Features must be first
* Number of features rendered with specified legend key. Features must be first
* calculated by countSymbolFeatures()
* @param symbol the symbol
* @return number of features rendered by symbol or -1 if failed or counts are not available
*/
long featureCount( QgsSymbol* symbol ) const;
long featureCount( const QString& legendKey ) const;

/**
* Update the data source of the layer. The layer's renderer and legend will be preserved only
@@ -752,7 +751,7 @@ class QgsVectorLayer : QgsMapLayer, QgsExpressionContextGenerator
void setDataSource( const QString& dataSource, const QString& baseName, const QString& provider, bool loadDefaultStyleFlag = false );

/**
* Count features for symbols. Feature counts may be get by featureCount( QgsSymbol*).
* Count features for symbols. Feature counts may be get by featureCount().
* @param showProgress show progress dialog
* @return true if calculated, false if failed or was canceled by user
*/
@@ -468,8 +468,8 @@ void QgsSymbolLegendNode::updateLabel()
else
{
mLabel = mUserLabel.isEmpty() ? mItem.label() : mUserLabel;
if ( showFeatureCount && vl && mItem.legacyRuleKey() )
mLabel += QStringLiteral( " [%1]" ).arg( vl->featureCount( mItem.legacyRuleKey() ) );
if ( showFeatureCount && vl )
mLabel += QStringLiteral( " [%1]" ).arg( vl->featureCount( mItem.ruleKey() ) );
}
}

@@ -622,12 +622,12 @@ bool QgsVectorLayer::diagramsEnabled() const
return false;
}

long QgsVectorLayer::featureCount( QgsSymbol* symbol ) const
long QgsVectorLayer::featureCount( const QString& legendKey ) const
{
if ( !mSymbolFeatureCounted )
return -1;

return mSymbolFeatureCountMap.value( symbol );
return mSymbolFeatureCountMap.value( legendKey );
}

/** \ingroup core
@@ -697,7 +697,7 @@ bool QgsVectorLayer::countSymbolFeatures( bool showProgress )

for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
{
mSymbolFeatureCountMap.insert( symbolIt->second, 0 );
mSymbolFeatureCountMap.insert( symbolIt->first, 0 );
}

long nFeatures = featureCount();
@@ -749,10 +749,10 @@ bool QgsVectorLayer::countSymbolFeatures( bool showProgress )
while ( fit.nextFeature( f ) )
{
renderContext.expressionContext().setFeature( f );
QgsSymbolList featureSymbolList = mRenderer->originalSymbolsForFeature( f, renderContext );
for ( QgsSymbolList::iterator symbolIt = featureSymbolList.begin(); symbolIt != featureSymbolList.end(); ++symbolIt )
QSet<QString> featureKeyList = mRenderer->legendKeysForFeature( f, renderContext );
Q_FOREACH ( const QString& key, featureKeyList )
{
mSymbolFeatureCountMap[*symbolIt] += 1;
mSymbolFeatureCountMap[key] += 1;
}
++featuresCounted;

@@ -837,12 +837,11 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
bool readSld( const QDomNode& node, QString& errorMessage ) override;

/**
* Number of features rendered with specified symbol. Features must be first
* Number of features rendered with specified legend key. Features must be first
* calculated by countSymbolFeatures()
* @param symbol the symbol
* @return number of features rendered by symbol or -1 if failed or counts are not available
*/
long featureCount( QgsSymbol* symbol ) const;
long featureCount( const QString& legendKey ) const;

/**
* Update the data source of the layer. The layer's renderer and legend will be preserved only
@@ -857,7 +856,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
void setDataSource( const QString& dataSource, const QString& baseName, const QString& provider, bool loadDefaultStyleFlag = false );

/**
* Count features for symbols. Feature counts may be get by featureCount( QgsSymbol*).
* Count features for symbols. Feature counts may be get by featureCount().
* @param showProgress show progress dialog
* @return true if calculated, false if failed or was canceled by user
*/
@@ -2080,8 +2079,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
// Features in renderer classes counted
bool mSymbolFeatureCounted;

// Feature counts for each renderer symbol
QMap<QgsSymbol*, long> mSymbolFeatureCountMap;
// Feature counts for each renderer legend key
QHash<QString, long> mSymbolFeatureCountMap;

//! True while an undo command is active
bool mEditCommandActive;

0 comments on commit 6d0203d

Please sign in to comment.