Skip to content

Commit

Permalink
Add embeddedSymbol getter and setter to QgsFeature
Browse files Browse the repository at this point in the history
Allows for storing per-feature symbology, e.g. for symbols which
are an innate part of features from a dataset which supports
feature level symbology.
  • Loading branch information
nyalldawson committed Mar 6, 2021
1 parent ef14759 commit b8b5528
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 4 deletions.
17 changes: 16 additions & 1 deletion python/core/auto_generated/qgsfeature.sip.in
Expand Up @@ -12,7 +12,6 @@




class QgsFeature
{
%Docstring
Expand Down Expand Up @@ -579,6 +578,22 @@ before this method can be used.
}
%End

const QgsSymbol *embeddedSymbol() const;
%Docstring
Returns the feature's embedded symbology, or ``None`` if the feature has no embedded symbol.

.. versionadded:: 3.20
%End

void setEmbeddedSymbol( QgsSymbol *symbol /Transfer/ );
%Docstring
Sets the feature's embedded ``symbol``.

Ownership of ``symbol`` is transferred to the feature.

.. versionadded:: 3.20
%End

int fieldNameIndex( const QString &fieldName ) const;
%Docstring
Utility method to get attribute index from name. Field map must be associated using :py:func:`~QgsFeature.setFields`
Expand Down
17 changes: 16 additions & 1 deletion src/core/qgsfeature.cpp
Expand Up @@ -68,7 +68,8 @@ bool QgsFeature::operator ==( const QgsFeature &other ) const
&& d->valid == other.d->valid
&& d->fields == other.d->fields
&& d->attributes == other.d->attributes
&& d->geometry.equals( other.d->geometry ) )
&& d->geometry.equals( other.d->geometry )
&& d->symbol == other.d->symbol )
return true;

return false;
Expand Down Expand Up @@ -284,6 +285,20 @@ QVariant QgsFeature::attribute( int fieldIdx ) const
return d->attributes.at( fieldIdx );
}

const QgsSymbol *QgsFeature::embeddedSymbol() const
{
return d->symbol.get();
}

void QgsFeature::setEmbeddedSymbol( QgsSymbol *symbol )
{
if ( symbol == d->symbol.get() )
return;

d.detach();
d->symbol.reset( symbol );
}

QVariant QgsFeature::attribute( const QString &name ) const
{
int fieldIdx = fieldNameIndex( name );
Expand Down
18 changes: 17 additions & 1 deletion src/core/qgsfeature.h
Expand Up @@ -37,7 +37,7 @@ class QgsField;
class QgsGeometry;
class QgsRectangle;
class QgsAbstractGeometry;

class QgsSymbol;

/***************************************************************************
* This class is considered CRITICAL and any change MUST be accompanied with
Expand Down Expand Up @@ -562,6 +562,22 @@ class CORE_EXPORT QgsFeature
% End
#endif

/**
* Returns the feature's embedded symbology, or NULLPTR if the feature has no embedded symbol.
*
* \since QGIS 3.20
*/
const QgsSymbol *embeddedSymbol() const;

/**
* Sets the feature's embedded \a symbol.
*
* Ownership of \a symbol is transferred to the feature.
*
* \since QGIS 3.20
*/
void setEmbeddedSymbol( QgsSymbol *symbol SIP_TRANSFER );

/**
* Utility method to get attribute index from name. Field map must be associated using setFields()
* before this method can be used.
Expand Down
4 changes: 4 additions & 0 deletions src/core/qgsfeature_p.h
Expand Up @@ -36,6 +36,7 @@ email : nyall dot dawson at gmail dot com
#include "qgsfields.h"

#include "qgsgeometry.h"
#include "qgssymbol.h"

class QgsFeaturePrivate : public QSharedData
{
Expand All @@ -54,6 +55,7 @@ class QgsFeaturePrivate : public QSharedData
, geometry( other.geometry )
, valid( other.valid )
, fields( other.fields )
, symbol( other.symbol ? other.symbol->clone() : nullptr )
{
}

Expand All @@ -76,6 +78,8 @@ class QgsFeaturePrivate : public QSharedData
//! Optional field map for name-based attribute lookups
QgsFields fields;

std::unique_ptr< QgsSymbol > symbol;

private:
QgsFeaturePrivate &operator=( const QgsFeaturePrivate & ) = delete;

Expand Down
32 changes: 31 additions & 1 deletion tests/src/core/testqgsfeature.cpp
Expand Up @@ -21,6 +21,7 @@
#include "qgsfeature.h"
#include "qgsfield.h"
#include "qgsgeometry.h"
#include "qgssymbol.h"

class TestQgsFeature: public QObject
{
Expand Down Expand Up @@ -189,29 +190,46 @@ void TestQgsFeature::copy()
{
QgsFeature original( 1000LL );
original.setAttributes( mAttrs );
original.setEmbeddedSymbol( QgsLineSymbol::createSimple( QVariantMap() ) );

QgsFeature copy( original );
QVERIFY( copy.id() == original.id() );
QCOMPARE( copy.attributes(), original.attributes() );
QVERIFY( copy.embeddedSymbol() );
// should be shallow copy
QCOMPARE( copy.embeddedSymbol(), original.embeddedSymbol() );

copy.setId( 1001LL );
QCOMPARE( original.id(), 1000LL );
QVERIFY( copy.id() != original.id() );

// symbol should be cloned on detach
QVERIFY( copy.embeddedSymbol() );
QVERIFY( copy.embeddedSymbol() != original.embeddedSymbol() );
}

void TestQgsFeature::assignment()
{
QgsFeature original( 1000LL );
original.setAttributes( mAttrs );
original.setEmbeddedSymbol( QgsLineSymbol::createSimple( QVariantMap() ) );

QgsFeature copy;
copy = original;
QCOMPARE( copy.id(), original.id() );
QCOMPARE( copy.attributes(), original.attributes() );
QVERIFY( copy.embeddedSymbol() );
// should be shallow copy
QCOMPARE( copy.embeddedSymbol(), original.embeddedSymbol() );

copy.setId( 1001LL );
QCOMPARE( original.id(), 1000LL );
QVERIFY( copy.id() != original.id() );
QCOMPARE( copy.attributes(), original.attributes() );

// symbol should be cloned on detach
QVERIFY( copy.embeddedSymbol() );
QVERIFY( copy.embeddedSymbol() != original.embeddedSymbol() );
}

void TestQgsFeature::gettersSetters()
Expand All @@ -223,6 +241,9 @@ void TestQgsFeature::gettersSetters()
feature.setValid( true );
QCOMPARE( feature.isValid(), true );

QVERIFY( !feature.embeddedSymbol() );
feature.setEmbeddedSymbol( QgsLineSymbol::createSimple( QVariantMap() ) );
QVERIFY( feature.embeddedSymbol() );
}

void TestQgsFeature::attributes()
Expand Down Expand Up @@ -417,7 +438,6 @@ void TestQgsFeature::fields()

void TestQgsFeature::equality()
{

QgsFeature feature;
feature.setFields( mFields, true );
feature.setAttribute( 0, QStringLiteral( "attr1" ) );
Expand All @@ -435,6 +455,16 @@ void TestQgsFeature::equality()

feature2.setAttribute( 1, 1 );
QVERIFY( feature != feature2 );
feature2.setAttribute( 1, QStringLiteral( "attr2" ) );
QVERIFY( feature == feature2 );
feature2.setEmbeddedSymbol( QgsLineSymbol::createSimple( QVariantMap() ) );
QVERIFY( feature != feature2 );
feature.setEmbeddedSymbol( QgsLineSymbol::createSimple( QVariantMap() ) );
QVERIFY( feature != feature2 );
feature2.setEmbeddedSymbol( nullptr );
QVERIFY( feature != feature2 );
feature.setEmbeddedSymbol( nullptr );
QVERIFY( feature == feature2 );

QgsFeature feature3;
feature3.setFields( mFields, true );
Expand Down

0 comments on commit b8b5528

Please sign in to comment.