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:
Nyall Dawson 2016-01-25 13:05:36 +11:00
parent cf3c55bdfc
commit 39e1f68ccc
23 changed files with 278 additions and 14 deletions

View File

@ -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 );
};

View File

@ -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/ );

View File

@ -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 & );

View File

@ -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

View File

@ -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();

View File

@ -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.

View File

@ -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;
}
}

View File

@ -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 )

View File

@ -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;

View File

@ -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();

View File

@ -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

View File

@ -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 );

View File

@ -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

View File

@ -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() );

View File

@ -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
*

View File

@ -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" )

View File

@ -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; }

View File

@ -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" )

View File

@ -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.

View File

@ -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++ )
{

View File

@ -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