mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Fix filtering legend content by map when renderer contains
duplicate symbols (fix #14131) Now, we don't test for map content using the symbols but instead use the legend key during the hit test
This commit is contained in:
parent
cf3c55bdfc
commit
39e1f68ccc
@ -29,9 +29,18 @@ class QgsMapHitTest
|
||||
* @param symbol symbol to find
|
||||
* @param layer vector layer
|
||||
* @note added in QGIS 2.12
|
||||
* @see legendKeyVisible()
|
||||
*/
|
||||
bool symbolVisible( QgsSymbolV2* symbol, QgsVectorLayer* layer ) const;
|
||||
|
||||
/** Tests whether a given legend key is visible for a specified layer.
|
||||
* @param ruleKey legend rule key
|
||||
* @param layer vector layer
|
||||
* @note added in QGIS 2.14
|
||||
* @see symbolVisible()
|
||||
*/
|
||||
bool legendKeyVisible( const QString& ruleKey, QgsVectorLayer* layer ) const;
|
||||
|
||||
protected:
|
||||
|
||||
//! @note not available in Python bindings
|
||||
@ -43,11 +52,12 @@ class QgsMapHitTest
|
||||
/** Runs test for visible symbols within a layer
|
||||
* @param vl vector layer
|
||||
* @param usedSymbols set for storage of visible symbols
|
||||
* @param usedSymbolsRuleKey set of storage of visible legend rule keys
|
||||
* @param context render context
|
||||
* @note added in QGIS 2.12
|
||||
* @note not available in Python bindings
|
||||
*/
|
||||
//void runHitTestLayer( QgsVectorLayer* vl, SymbolV2Set& usedSymbols, QgsRenderContext& context );
|
||||
//void runHitTestLayer( QgsVectorLayer* vl, SymbolV2Set& usedSymbols, SymbolV2Set& usedSymbolsRuleKey, QgsRenderContext& context );
|
||||
|
||||
|
||||
};
|
||||
|
@ -121,6 +121,8 @@ class QgsCategorizedSymbolRendererV2 : QgsFeatureRendererV2
|
||||
//! @note added in 2.10
|
||||
QgsLegendSymbolListV2 legendSymbolItemsV2() const;
|
||||
|
||||
virtual QSet< QString > legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context );
|
||||
|
||||
QgsSymbolV2* sourceSymbol();
|
||||
void setSourceSymbol( QgsSymbolV2* sym /Transfer/ );
|
||||
|
||||
|
@ -224,6 +224,8 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
|
||||
//! @note added in 2.10
|
||||
QgsLegendSymbolListV2 legendSymbolItemsV2() const;
|
||||
|
||||
virtual QSet< QString > legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context );
|
||||
|
||||
QgsSymbolV2* sourceSymbol();
|
||||
void setSourceSymbol( QgsSymbolV2* sym /Transfer/ );
|
||||
|
||||
@ -306,6 +308,11 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2
|
||||
protected:
|
||||
QgsSymbolV2* symbolForValue( double value );
|
||||
|
||||
/** Returns the matching legend key for a value.
|
||||
*/
|
||||
QString legendKeyForValue( double value ) const;
|
||||
|
||||
|
||||
private:
|
||||
QgsGraduatedSymbolRendererV2( const QgsGraduatedSymbolRendererV2 & );
|
||||
QgsGraduatedSymbolRendererV2 & operator=( const QgsGraduatedSymbolRendererV2 & );
|
||||
|
@ -98,6 +98,12 @@ class QgsFeatureRendererV2
|
||||
//TODO - QGIS 3.0 change PyName to originalSymbolForFeature when deprecated method is removed
|
||||
virtual QgsSymbolV2* originalSymbolForFeature( QgsFeature& feature, QgsRenderContext& context ) /PyName=originalSymbolForFeature2/;
|
||||
|
||||
/**
|
||||
* Return legend keys matching a specified feature.
|
||||
* @note added in 2.14
|
||||
*/
|
||||
virtual QSet< QString > legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context );
|
||||
|
||||
virtual void startRender( QgsRenderContext& context, const QgsFields& fields ) = 0;
|
||||
|
||||
//! @deprecated since 2.4 - not using QgsVectorLayer directly anymore
|
||||
|
@ -220,6 +220,11 @@ class QgsRuleBasedRendererV2 : QgsFeatureRendererV2
|
||||
//! tell which symbols will be used to render the feature
|
||||
QgsSymbolV2List symbolsForFeature( QgsFeature& feat, QgsRenderContext* context = 0 );
|
||||
|
||||
/** Returns which legend keys match the feature
|
||||
* @note added in QGIS 2.14
|
||||
*/
|
||||
QSet< QString > legendKeysForFeature( QgsFeature& feat, QgsRenderContext* context = nullptr );
|
||||
|
||||
//! tell which rules will be used to render the feature
|
||||
QList<QgsRuleBasedRendererV2::Rule*> rulesForFeature( QgsFeature& feat, QgsRenderContext* context = 0 );
|
||||
|
||||
@ -388,6 +393,8 @@ class QgsRuleBasedRendererV2 : QgsFeatureRendererV2
|
||||
|
||||
virtual QgsSymbolV2List originalSymbolsForFeature( QgsFeature& feat, QgsRenderContext &context );
|
||||
|
||||
virtual QSet<QString> legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context );
|
||||
|
||||
//! returns bitwise OR-ed capabilities of the renderer
|
||||
virtual int capabilities();
|
||||
|
||||
|
@ -63,6 +63,8 @@ class QgsSingleSymbolRendererV2 : QgsFeatureRendererV2
|
||||
//! @note added in 2.6
|
||||
virtual QgsLegendSymbolListV2 legendSymbolItemsV2() const;
|
||||
|
||||
virtual QSet< QString > legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context );
|
||||
|
||||
//! creates a QgsSingleSymbolRendererV2 from an existing renderer.
|
||||
//! @note added in 2.5
|
||||
//! @returns a new renderer if the conversion was possible, otherwise 0.
|
||||
|
@ -1058,12 +1058,13 @@ QList<QgsLayerTreeModelLegendNode*> QgsLayerTreeModel::filterLegendNodes( const
|
||||
{
|
||||
Q_FOREACH ( QgsLayerTreeModelLegendNode* node, nodes )
|
||||
{
|
||||
QgsSymbolV2* ruleKey = reinterpret_cast< QgsSymbolV2* >( node->data( QgsSymbolV2LegendNode::SymbolV2LegacyRuleKeyRole ).value<void*>() );
|
||||
if ( ruleKey )
|
||||
QgsSymbolV2* symbolKey = reinterpret_cast< QgsSymbolV2* >( node->data( QgsSymbolV2LegendNode::SymbolV2LegacyRuleKeyRole ).value<void*>() );
|
||||
if ( symbolKey )
|
||||
{
|
||||
QString ruleKey = node->data( QgsSymbolV2LegendNode::RuleKeyRole ).toString();
|
||||
if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( node->layerNode()->layer() ) )
|
||||
{
|
||||
if ( mLegendFilterHitTest->symbolVisible( ruleKey, vl ) )
|
||||
if ( mLegendFilterHitTest->legendKeyVisible( ruleKey, vl ) )
|
||||
filtered << node;
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ void QgsMapHitTest::run()
|
||||
if ( vl->hasScaleBasedVisibility() && ( mSettings.scale() < vl->minimumScale() || mSettings.scale() > vl->maximumScale() ) )
|
||||
{
|
||||
mHitTest[vl] = SymbolV2Set(); // no symbols -> will not be shown
|
||||
mHitTestRuleKey[vl] = SymbolV2Set();
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -74,7 +75,8 @@ void QgsMapHitTest::run()
|
||||
|
||||
context.expressionContext() << QgsExpressionContextUtils::layerScope( vl );
|
||||
SymbolV2Set& usedSymbols = mHitTest[vl];
|
||||
runHitTestLayer( vl, usedSymbols, context );
|
||||
SymbolV2Set& usedSymbolsRuleKey = mHitTestRuleKey[vl];
|
||||
runHitTestLayer( vl, usedSymbols, usedSymbolsRuleKey, context );
|
||||
}
|
||||
|
||||
painter.end();
|
||||
@ -88,7 +90,15 @@ bool QgsMapHitTest::symbolVisible( QgsSymbolV2* symbol, QgsVectorLayer* layer )
|
||||
return mHitTest.value( layer ).contains( QgsSymbolLayerV2Utils::symbolProperties( symbol ) );
|
||||
}
|
||||
|
||||
void QgsMapHitTest::runHitTestLayer( QgsVectorLayer* vl, SymbolV2Set& usedSymbols, QgsRenderContext& context )
|
||||
bool QgsMapHitTest::legendKeyVisible( const QString& ruleKey, QgsVectorLayer* layer ) const
|
||||
{
|
||||
if ( !layer || !mHitTestRuleKey.contains( layer ) )
|
||||
return false;
|
||||
|
||||
return mHitTestRuleKey.value( layer ).contains( ruleKey );
|
||||
}
|
||||
|
||||
void QgsMapHitTest::runHitTestLayer( QgsVectorLayer* vl, SymbolV2Set& usedSymbols, SymbolV2Set& usedSymbolsRuleKey, QgsRenderContext& context )
|
||||
{
|
||||
bool hasStyleOverride = mSettings.layerStyleOverrides().contains( vl->id() );
|
||||
if ( hasStyleOverride )
|
||||
@ -125,6 +135,7 @@ void QgsMapHitTest::runHitTestLayer( QgsVectorLayer* vl, SymbolV2Set& usedSymbol
|
||||
QgsFeatureIterator fi = vl->getFeatures( request );
|
||||
|
||||
SymbolV2Set lUsedSymbols;
|
||||
SymbolV2Set lUsedSymbolsRuleKey;
|
||||
bool allExpressionFalse = false;
|
||||
bool hasExpression = mLayerFilterExpression.contains( vl->id() );
|
||||
QScopedPointer<QgsExpression> expr;
|
||||
@ -156,6 +167,11 @@ void QgsMapHitTest::runHitTestLayer( QgsVectorLayer* vl, SymbolV2Set& usedSymbol
|
||||
|
||||
//make sure we store string representation of symbol, not pointer
|
||||
//otherwise layer style override changes will delete original symbols and leave hanging pointers
|
||||
Q_FOREACH ( const QString& legendKey, r->legendKeysForFeature( f, context ) )
|
||||
{
|
||||
lUsedSymbolsRuleKey.insert( legendKey );
|
||||
}
|
||||
|
||||
if ( moreSymbolsPerFeature )
|
||||
{
|
||||
Q_FOREACH ( QgsSymbolV2* s, r->originalSymbolsForFeature( f, context ) )
|
||||
@ -177,6 +193,7 @@ void QgsMapHitTest::runHitTestLayer( QgsVectorLayer* vl, SymbolV2Set& usedSymbol
|
||||
{
|
||||
// QSet is implicitly shared => constant time
|
||||
usedSymbols = lUsedSymbols;
|
||||
usedSymbolsRuleKey = lUsedSymbolsRuleKey;
|
||||
}
|
||||
|
||||
if ( hasStyleOverride )
|
||||
|
@ -52,9 +52,18 @@ class CORE_EXPORT QgsMapHitTest
|
||||
* @param symbol symbol to find
|
||||
* @param layer vector layer
|
||||
* @note added in QGIS 2.12
|
||||
* @see legendKeyVisible()
|
||||
*/
|
||||
bool symbolVisible( QgsSymbolV2* symbol, QgsVectorLayer* layer ) const;
|
||||
|
||||
/** Tests whether a given legend key is visible for a specified layer.
|
||||
* @param ruleKey legend rule key
|
||||
* @param layer vector layer
|
||||
* @note added in QGIS 2.14
|
||||
* @see symbolVisible()
|
||||
*/
|
||||
bool legendKeyVisible( const QString& ruleKey, QgsVectorLayer* layer ) const;
|
||||
|
||||
protected:
|
||||
|
||||
//! @note not available in Python bindings
|
||||
@ -66,11 +75,12 @@ class CORE_EXPORT QgsMapHitTest
|
||||
/** Runs test for visible symbols within a layer
|
||||
* @param vl vector layer
|
||||
* @param usedSymbols set for storage of visible symbols
|
||||
* @param usedSymbolsRuleKey set of storage of visible legend rule keys
|
||||
* @param context render context
|
||||
* @note added in QGIS 2.12
|
||||
* @note not available in Python bindings
|
||||
*/
|
||||
void runHitTestLayer( QgsVectorLayer* vl, SymbolV2Set& usedSymbols, QgsRenderContext& context );
|
||||
void runHitTestLayer( QgsVectorLayer* vl, SymbolV2Set& usedSymbols, SymbolV2Set& usedSymbolsRuleKey, QgsRenderContext& context );
|
||||
|
||||
//! The initial map settings
|
||||
QgsMapSettings mSettings;
|
||||
@ -78,6 +88,9 @@ class CORE_EXPORT QgsMapHitTest
|
||||
//! The hit test
|
||||
HitTest mHitTest;
|
||||
|
||||
//! The hit test, using legend rule keys
|
||||
HitTest mHitTestRuleKey;
|
||||
|
||||
//! List of expression filter for each layer
|
||||
LayerFilterExpression mLayerFilterExpression;
|
||||
|
||||
|
@ -245,9 +245,8 @@ QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForFeature( QgsFeature& featu
|
||||
}
|
||||
|
||||
|
||||
QgsSymbolV2* QgsCategorizedSymbolRendererV2::originalSymbolForFeature( QgsFeature& feature, QgsRenderContext &context )
|
||||
QVariant QgsCategorizedSymbolRendererV2::valueForFeature( QgsFeature& feature, QgsRenderContext &context ) const
|
||||
{
|
||||
Q_UNUSED( context );
|
||||
QgsAttributes attrs = feature.attributes();
|
||||
QVariant value;
|
||||
if ( mAttrNum == -1 )
|
||||
@ -261,6 +260,13 @@ QgsSymbolV2* QgsCategorizedSymbolRendererV2::originalSymbolForFeature( QgsFeatur
|
||||
value = attrs.value( mAttrNum );
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
QgsSymbolV2* QgsCategorizedSymbolRendererV2::originalSymbolForFeature( QgsFeature& feature, QgsRenderContext &context )
|
||||
{
|
||||
QVariant value = valueForFeature( feature, context );
|
||||
|
||||
// find the right symbol for the category
|
||||
QgsSymbolV2 *symbol = symbolForValue( value );
|
||||
if ( symbol == skipRender() )
|
||||
@ -859,6 +865,26 @@ QgsLegendSymbolListV2 QgsCategorizedSymbolRendererV2::legendSymbolItemsV2() cons
|
||||
return QgsFeatureRendererV2::legendSymbolItemsV2();
|
||||
}
|
||||
|
||||
QSet<QString> QgsCategorizedSymbolRendererV2::legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context )
|
||||
{
|
||||
QString value = valueForFeature( feature, context ).toString();
|
||||
int i = 0;
|
||||
|
||||
Q_FOREACH ( const QgsRendererCategoryV2& cat, mCategories )
|
||||
{
|
||||
if ( value == cat.value() )
|
||||
{
|
||||
if ( cat.renderState() )
|
||||
return QSet< QString >() << QString::number( i );
|
||||
else
|
||||
return QSet< QString >();
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return QSet< QString >();
|
||||
}
|
||||
|
||||
QgsSymbolV2* QgsCategorizedSymbolRendererV2::sourceSymbol()
|
||||
{
|
||||
return mSourceSymbol.data();
|
||||
|
@ -150,6 +150,8 @@ class CORE_EXPORT QgsCategorizedSymbolRendererV2 : public QgsFeatureRendererV2
|
||||
//! @note added in 2.10
|
||||
QgsLegendSymbolListV2 legendSymbolItemsV2() const override;
|
||||
|
||||
virtual QSet< QString > legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context ) override;
|
||||
|
||||
QgsSymbolV2* sourceSymbol();
|
||||
void setSourceSymbol( QgsSymbolV2* sym );
|
||||
|
||||
@ -229,6 +231,12 @@ class CORE_EXPORT QgsCategorizedSymbolRendererV2 : public QgsFeatureRendererV2
|
||||
QgsSymbolV2* skipRender();
|
||||
|
||||
QgsSymbolV2* symbolForValue( const QVariant& value );
|
||||
|
||||
private:
|
||||
|
||||
/** Returns calculated classification value for a feature */
|
||||
QVariant valueForFeature( QgsFeature& feature, QgsRenderContext &context ) const;
|
||||
|
||||
};
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
|
||||
|
@ -325,6 +325,24 @@ QgsSymbolV2* QgsGraduatedSymbolRendererV2::symbolForValue( double value )
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QString QgsGraduatedSymbolRendererV2::legendKeyForValue( double value ) const
|
||||
{
|
||||
int i = 0;
|
||||
Q_FOREACH ( const QgsRendererRangeV2& range, mRanges )
|
||||
{
|
||||
if ( range.lowerValue() <= value && range.upperValue() >= value )
|
||||
{
|
||||
if ( range.renderState() || mCounting )
|
||||
return QString::number( i );
|
||||
else
|
||||
return QString::null;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// the value is out of the range: return NULL
|
||||
return QString::null;
|
||||
}
|
||||
|
||||
QgsSymbolV2* QgsGraduatedSymbolRendererV2::symbolForFeature( QgsFeature& feature, QgsRenderContext &context )
|
||||
{
|
||||
QgsSymbolV2* symbol = originalSymbolForFeature( feature, context );
|
||||
@ -357,9 +375,8 @@ QgsSymbolV2* QgsGraduatedSymbolRendererV2::symbolForFeature( QgsFeature& feature
|
||||
return tempSymbol;
|
||||
}
|
||||
|
||||
QgsSymbolV2* QgsGraduatedSymbolRendererV2::originalSymbolForFeature( QgsFeature& feature, QgsRenderContext &context )
|
||||
QVariant QgsGraduatedSymbolRendererV2::valueForFeature( QgsFeature& feature, QgsRenderContext &context ) const
|
||||
{
|
||||
Q_UNUSED( context );
|
||||
QgsAttributes attrs = feature.attributes();
|
||||
QVariant value;
|
||||
if ( mAttrNum < 0 || mAttrNum >= attrs.count() )
|
||||
@ -371,6 +388,13 @@ QgsSymbolV2* QgsGraduatedSymbolRendererV2::originalSymbolForFeature( QgsFeature&
|
||||
value = attrs.at( mAttrNum );
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
QgsSymbolV2* QgsGraduatedSymbolRendererV2::originalSymbolForFeature( QgsFeature& feature, QgsRenderContext &context )
|
||||
{
|
||||
QVariant value = valueForFeature( feature, context );
|
||||
|
||||
// Null values should not be categorized
|
||||
if ( value.isNull() )
|
||||
return nullptr;
|
||||
@ -1245,6 +1269,22 @@ QgsLegendSymbolListV2 QgsGraduatedSymbolRendererV2::legendSymbolItemsV2() const
|
||||
return QgsFeatureRendererV2::legendSymbolItemsV2();
|
||||
}
|
||||
|
||||
QSet< QString > QgsGraduatedSymbolRendererV2::legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context )
|
||||
{
|
||||
QVariant value = valueForFeature( feature, context );
|
||||
|
||||
// Null values should not be categorized
|
||||
if ( value.isNull() )
|
||||
return QSet< QString >();
|
||||
|
||||
// find the right category
|
||||
QString key = legendKeyForValue( value.toDouble() );
|
||||
if ( !key.isNull() )
|
||||
return QSet< QString >() << key;
|
||||
else
|
||||
return QSet< QString >();
|
||||
}
|
||||
|
||||
QgsLegendSymbolList QgsGraduatedSymbolRendererV2::legendSymbolItems( double scaleDenominator, const QString& rule )
|
||||
{
|
||||
Q_UNUSED( scaleDenominator );
|
||||
|
@ -257,6 +257,7 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
|
||||
//! @note added in 2.10
|
||||
QgsLegendSymbolListV2 legendSymbolItemsV2() const override;
|
||||
|
||||
virtual QSet< QString > legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context ) override;
|
||||
|
||||
QgsSymbolV2* sourceSymbol();
|
||||
void setSourceSymbol( QgsSymbolV2* sym );
|
||||
@ -360,9 +361,19 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
|
||||
|
||||
QgsSymbolV2* symbolForValue( double value );
|
||||
|
||||
/** Returns the matching legend key for a value.
|
||||
*/
|
||||
QString legendKeyForValue( double value ) const;
|
||||
|
||||
//! @note not available in Python bindings
|
||||
static const char * graduatedMethodStr( GraduatedMethod method );
|
||||
|
||||
private:
|
||||
|
||||
/** Returns calculated value used for classifying a feature.
|
||||
*/
|
||||
QVariant valueForFeature( QgsFeature& feature, QgsRenderContext &context ) const;
|
||||
|
||||
};
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
|
||||
|
@ -271,6 +271,13 @@ QgsSymbolV2 *QgsFeatureRendererV2::originalSymbolForFeature( QgsFeature &feature
|
||||
return symbolForFeature( feature, context );
|
||||
}
|
||||
|
||||
QSet< QString > QgsFeatureRendererV2::legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context )
|
||||
{
|
||||
Q_UNUSED( feature );
|
||||
Q_UNUSED( context );
|
||||
return QSet< QString >();
|
||||
}
|
||||
|
||||
void QgsFeatureRendererV2::startRender( QgsRenderContext& context, const QgsVectorLayer* vlayer )
|
||||
{
|
||||
startRender( context, vlayer->fields() );
|
||||
|
@ -119,6 +119,12 @@ class CORE_EXPORT QgsFeatureRendererV2
|
||||
//TODO - QGIS 3.0 change PyName to originalSymbolForFeature when deprecated method is removed
|
||||
virtual QgsSymbolV2* originalSymbolForFeature( QgsFeature& feature, QgsRenderContext& context );
|
||||
|
||||
/**
|
||||
* Return legend keys matching a specified feature.
|
||||
* @note added in 2.14
|
||||
*/
|
||||
virtual QSet< QString > legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context );
|
||||
|
||||
/**
|
||||
* Needs to be called when a new render cycle is started
|
||||
*
|
||||
|
@ -612,6 +612,20 @@ QgsSymbolV2List QgsRuleBasedRendererV2::Rule::symbolsForFeature( QgsFeature& fea
|
||||
return lst;
|
||||
}
|
||||
|
||||
QSet<QString> QgsRuleBasedRendererV2::Rule::legendKeysForFeature( QgsFeature& feat, QgsRenderContext* context )
|
||||
{
|
||||
QSet< QString> lst;
|
||||
if ( !isFilterOK( feat, context ) )
|
||||
return lst;
|
||||
lst.insert( mRuleKey );
|
||||
|
||||
Q_FOREACH ( Rule* rule, mActiveChildren )
|
||||
{
|
||||
lst.unite( rule->legendKeysForFeature( feat, context ) );
|
||||
}
|
||||
return lst;
|
||||
}
|
||||
|
||||
QgsRuleBasedRendererV2::RuleList QgsRuleBasedRendererV2::Rule::rulesForFeature( QgsFeature& feat, QgsRenderContext* context )
|
||||
{
|
||||
RuleList lst;
|
||||
@ -1193,6 +1207,11 @@ QgsSymbolV2List QgsRuleBasedRendererV2::originalSymbolsForFeature( QgsFeature& f
|
||||
return mRootRule->symbolsForFeature( feat, &context );
|
||||
}
|
||||
|
||||
QSet< QString > QgsRuleBasedRendererV2::legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context )
|
||||
{
|
||||
return mRootRule->legendKeysForFeature( feature, &context );
|
||||
}
|
||||
|
||||
QgsRuleBasedRendererV2* QgsRuleBasedRendererV2::convertFromRenderer( const QgsFeatureRendererV2* renderer )
|
||||
{
|
||||
if ( renderer->type() == "RuleRenderer" )
|
||||
|
@ -263,6 +263,11 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
|
||||
//! tell which symbols will be used to render the feature
|
||||
QgsSymbolV2List symbolsForFeature( QgsFeature& feat, QgsRenderContext* context = nullptr );
|
||||
|
||||
/** Returns which legend keys match the feature
|
||||
* @note added in QGIS 2.14
|
||||
*/
|
||||
QSet< QString > legendKeysForFeature( QgsFeature& feat, QgsRenderContext* context = nullptr );
|
||||
|
||||
//! tell which rules will be used to render the feature
|
||||
RuleList rulesForFeature( QgsFeature& feat, QgsRenderContext* context = nullptr );
|
||||
|
||||
@ -448,6 +453,8 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
|
||||
|
||||
virtual QgsSymbolV2List originalSymbolsForFeature( QgsFeature& feat, QgsRenderContext& context ) override;
|
||||
|
||||
virtual QSet<QString> legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context ) override;
|
||||
|
||||
//! returns bitwise OR-ed capabilities of the renderer
|
||||
virtual int capabilities() override { return MoreSymbolsPerFeature | Filter | ScaleDependent; }
|
||||
|
||||
|
@ -441,6 +441,13 @@ QgsLegendSymbolListV2 QgsSingleSymbolRendererV2::legendSymbolItemsV2() const
|
||||
return lst;
|
||||
}
|
||||
|
||||
QSet< QString > QgsSingleSymbolRendererV2::legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context )
|
||||
{
|
||||
Q_UNUSED( feature );
|
||||
Q_UNUSED( context );
|
||||
return QSet< QString >() << QString();
|
||||
}
|
||||
|
||||
QgsSingleSymbolRendererV2* QgsSingleSymbolRendererV2::convertFromRenderer( const QgsFeatureRendererV2 *renderer )
|
||||
{
|
||||
if ( renderer->type() == "singleSymbol" )
|
||||
|
@ -84,6 +84,8 @@ class CORE_EXPORT QgsSingleSymbolRendererV2 : public QgsFeatureRendererV2
|
||||
//! @note added in 2.6
|
||||
virtual QgsLegendSymbolListV2 legendSymbolItemsV2() const override;
|
||||
|
||||
virtual QSet< QString > legendKeysForFeature( QgsFeature& feature, QgsRenderContext& context ) override;
|
||||
|
||||
//! creates a QgsSingleSymbolRendererV2 from an existing renderer.
|
||||
//! @note added in 2.5
|
||||
//! @returns a new renderer if the conversion was possible, otherwise 0.
|
||||
|
@ -1077,7 +1077,7 @@ QDomElement QgsSymbolLayerV2Utils::saveSymbol( const QString& name, QgsSymbolV2*
|
||||
symEl.setAttribute( "name", name );
|
||||
symEl.setAttribute( "alpha", QString::number( symbol->alpha() ) );
|
||||
symEl.setAttribute( "clip_to_extent", symbol->clipFeaturesToExtent() ? "1" : "0" );
|
||||
QgsDebugMsg( "num layers " + QString::number( symbol->symbolLayerCount() ) );
|
||||
//QgsDebugMsg( "num layers " + QString::number( symbol->symbolLayerCount() ) );
|
||||
|
||||
for ( int i = 0; i < symbol->symbolLayerCount(); i++ )
|
||||
{
|
||||
|
@ -42,7 +42,7 @@ static QString _fileNameForTest( const QString& testName )
|
||||
return QDir::tempPath() + '/' + testName + ".png";
|
||||
}
|
||||
|
||||
static void _setStandardTestFont( QgsLegendSettings& settings )
|
||||
static void _setStandardTestFont( QgsLegendSettings& settings, QString style = "Roman" )
|
||||
{
|
||||
QList< QgsComposerLegendStyle::Style> styles;
|
||||
styles << QgsComposerLegendStyle::Title
|
||||
@ -51,7 +51,7 @@ static void _setStandardTestFont( QgsLegendSettings& settings )
|
||||
<< QgsComposerLegendStyle::SymbolLabel;
|
||||
Q_FOREACH ( QgsComposerLegendStyle::Style st, styles )
|
||||
{
|
||||
QFont font( QgsFontUtils::getStandardTestFont() );
|
||||
QFont font( QgsFontUtils::getStandardTestFont( style ) );
|
||||
font.setPointSizeF( settings.style( st ).font().pointSizeF() );
|
||||
settings.rstyle( st ).setFont( font );
|
||||
}
|
||||
@ -113,6 +113,7 @@ class TestQgsLegendRenderer : public QObject
|
||||
void testLongSymbolText();
|
||||
void testThreeColumns();
|
||||
void testFilterByMap();
|
||||
void testFilterByMapSameSymbol();
|
||||
void testRasterBorder();
|
||||
void testFilterByPolygon();
|
||||
void testFilterByExpression();
|
||||
@ -345,6 +346,71 @@ void TestQgsLegendRenderer::testFilterByMap()
|
||||
QVERIFY( _verifyImage( testName, mReport ) );
|
||||
}
|
||||
|
||||
void TestQgsLegendRenderer::testFilterByMapSameSymbol()
|
||||
{
|
||||
QgsVectorLayer* vl4 = new QgsVectorLayer( "Point", "Point Layer", "memory" );
|
||||
{
|
||||
QgsVectorDataProvider* pr = vl4->dataProvider();
|
||||
QList<QgsField> attrs;
|
||||
attrs << QgsField( "test_attr", QVariant::Int );
|
||||
pr->addAttributes( attrs );
|
||||
|
||||
QgsFields fields;
|
||||
fields.append( attrs.back() );
|
||||
|
||||
QList<QgsFeature> features;
|
||||
QgsFeature f1( fields, 1 );
|
||||
f1.setAttribute( 0, 1 );
|
||||
f1.setGeometry( QgsGeometry::fromPoint( QgsPoint( 1.0, 1.0 ) ) );
|
||||
QgsFeature f2( fields, 2 );
|
||||
f2.setAttribute( 0, 2 );
|
||||
f2.setGeometry( QgsGeometry::fromPoint( QgsPoint( 9.0, 1.0 ) ) );
|
||||
QgsFeature f3( fields, 3 );
|
||||
f3.setAttribute( 0, 3 );
|
||||
f3.setGeometry( QgsGeometry::fromPoint( QgsPoint( 5.0, 5.0 ) ) );
|
||||
features << f1 << f2 << f3;
|
||||
pr->addFeatures( features );
|
||||
vl4->updateFields();
|
||||
}
|
||||
QgsMapLayerRegistry::instance()->addMapLayer( vl4 );
|
||||
|
||||
//setup categorized renderer with duplicate symbols
|
||||
QgsCategoryList cats;
|
||||
QgsMarkerSymbolV2* sym4_1 = new QgsMarkerSymbolV2();
|
||||
sym4_1->setColor( Qt::red );
|
||||
cats << QgsRendererCategoryV2( 1, sym4_1, "Red1" );
|
||||
QgsMarkerSymbolV2* sym4_2 = new QgsMarkerSymbolV2();
|
||||
sym4_2->setColor( Qt::red );
|
||||
cats << QgsRendererCategoryV2( 2, sym4_2, "Red2" );
|
||||
QgsMarkerSymbolV2* sym4_3 = new QgsMarkerSymbolV2();
|
||||
sym4_3->setColor( Qt::red );
|
||||
cats << QgsRendererCategoryV2( 3, sym4_3, "Red3" );
|
||||
QgsCategorizedSymbolRendererV2* r4 = new QgsCategorizedSymbolRendererV2( "test_attr", cats );
|
||||
vl4->setRendererV2( r4 );
|
||||
|
||||
QString testName = "legend_filter_by_map_dupe";
|
||||
|
||||
QgsLayerTreeGroup* root = new QgsLayerTreeGroup();
|
||||
root->addLayer( vl4 );
|
||||
QgsLayerTreeModel legendModel( root );
|
||||
|
||||
QgsMapSettings mapSettings;
|
||||
// extent and size to include only the red and green points
|
||||
mapSettings.setExtent( QgsRectangle( 0, 0, 10.0, 4.0 ) );
|
||||
mapSettings.setOutputSize( QSize( 400, 100 ) );
|
||||
mapSettings.setOutputDpi( 96 );
|
||||
mapSettings.setLayers( QStringList() << vl4->id() );
|
||||
|
||||
legendModel.setLegendFilterByMap( &mapSettings );
|
||||
|
||||
QgsLegendSettings settings;
|
||||
_setStandardTestFont( settings, "Bold" );
|
||||
_renderLegend( testName, &legendModel, settings );
|
||||
QVERIFY( _verifyImage( testName, mReport ) );
|
||||
|
||||
QgsMapLayerRegistry::instance()->removeMapLayer( vl4 );
|
||||
}
|
||||
|
||||
void TestQgsLegendRenderer::testRasterBorder()
|
||||
{
|
||||
QString testName = "legend_raster_border";
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
Loading…
x
Reference in New Issue
Block a user