Skip to content
Permalink
Browse files

Clean atlas interface - avoid storage of pointer to atlas feature

  • Loading branch information
nyalldawson committed Aug 12, 2015
1 parent d32f334 commit 19a833c23d3dc0889b4442d03088d08da688645b
@@ -176,7 +176,7 @@ public:
*/
bool prepareForFeature( const QgsFeature * feat );

/** Returns the current filename. Must be called after prepareForFeature( i ) */
/** Returns the current filename. Must be called after prepareForFeature() */
const QString& currentFilename() const;

void writeXML( QDomElement& elem, QDomDocument& doc ) const;
@@ -201,13 +201,20 @@ public:
QgsComposition* composition();

/** Requeries the current atlas coverage layer and applies filtering and sorting. Returns
number of matching features. Must be called after prepareForFeature( i ) */
number of matching features. Must be called before prepareForFeature() */
int updateFeatures();

/** Returns the current atlas feature. Must be called after prepareForFeature( i ). */
QgsFeature* currentFeature();
/** Returns the current atlas feature. Must be called after prepareForFeature().
* @note added in QGIS 2.12
*/
QgsFeature feature() const;

/** Returns the name of the page for the current atlas feature. Must be called after prepareForFeature().
* @note added in QGIS 2.12
*/
QString currentPageName() const;

/** Returns the current feature number.
/** Returns the current feature number, where a value of 0 corresponds to the first feature.
* @note added in QGIS 2.12
*/
int currentFeatureNumber() const;
@@ -250,6 +257,9 @@ public:
int sortKeyAttributeIndex() const /Deprecated/;
void setSortKeyAttributeIndex( int idx ) /Deprecated/;

/** Returns the current atlas feature. Must be called after prepareForFeature(). */
QgsFeature* currentFeature() /Deprecated/;

public slots:

/** Refreshes the current atlas feature, by refetching its attributes from the vector layer provider
@@ -299,6 +299,10 @@ int QgsAtlasComposition::updateFeatures()
return mFeatureIds.size();
}

QString QgsAtlasComposition::currentPageName() const
{
return nameForPage( currentFeatureNumber() );
}

bool QgsAtlasComposition::beginRender()
{
@@ -205,7 +205,7 @@ class CORE_EXPORT QgsAtlasComposition : public QObject
*/
bool prepareForFeature( const QgsFeature *feat );

/** Returns the current filename. Must be called after prepareForFeature( i ) */
/** Returns the current filename. Must be called after prepareForFeature() */
const QString& currentFilename() const;

void writeXML( QDomElement& elem, QDomDocument& doc ) const;
@@ -230,13 +230,20 @@ class CORE_EXPORT QgsAtlasComposition : public QObject
QgsComposition* composition() { return mComposition; }

/** Requeries the current atlas coverage layer and applies filtering and sorting. Returns
number of matching features. Must be called after prepareForFeature( i ) */
number of matching features. Must be called after prepareForFeature() */
int updateFeatures();

/** Returns the current atlas feature. Must be called after prepareForFeature( i ). */
QgsFeature* currentFeature() { return &mCurrentFeature; }
/** Returns the current atlas feature. Must be called after prepareForFeature().
* @note added in QGIS 2.12
*/
QgsFeature feature() const { return mCurrentFeature; }

/** Returns the name of the page for the current atlas feature. Must be called after prepareForFeature().
* @note added in QGIS 2.12
*/
QString currentPageName() const;

/** Returns the current feature number.
/** Returns the current feature number, where a value of 0 corresponds to the first feature.
* @note added in QGIS 2.12
*/
int currentFeatureNumber() const { return mCurrentFeatureNo; }
@@ -280,6 +287,9 @@ class CORE_EXPORT QgsAtlasComposition : public QObject
Q_DECL_DEPRECATED int sortKeyAttributeIndex() const;
Q_DECL_DEPRECATED void setSortKeyAttributeIndex( int idx );

/** Returns the current atlas feature. Must be called after prepareForFeature( i ). */
Q_DECL_DEPRECATED QgsFeature* currentFeature() { return &mCurrentFeature; }

public slots:

/** Refreshes the current atlas feature, by refetching its attributes from the vector layer provider
@@ -488,16 +488,8 @@ bool QgsComposerAttributeTableV2::getTableContents( QgsComposerTableContents &co
if ( mSource == QgsComposerAttributeTableV2::RelationChildren )
{
QgsRelation relation = QgsProject::instance()->relationManager()->relation( mRelationId );
QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature();
if ( atlasFeature )
{
req = relation.getRelatedFeaturesRequest( *atlasFeature );
}
else
{
//no atlas feature, so empty table
return true;
}
QgsFeature atlasFeature = mComposition->atlasComposition().feature();
req = relation.getRelatedFeaturesRequest( atlasFeature );
}

if ( !selectionRect.isEmpty() )
@@ -509,16 +501,8 @@ bool QgsComposerAttributeTableV2::getTableContents( QgsComposerTableContents &co
&& mComposition->atlasComposition().enabled() )
{
//source mode is current atlas feature
QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature();
if ( atlasFeature )
{
req.setFilterFid( atlasFeature->id() );
}
else
{
//no atlas feature, so empty table
return true;
}
QgsFeature atlasFeature = mComposition->atlasComposition().feature();
req.setFilterFid( atlasFeature.id() );
}

QgsFeature f;
@@ -544,9 +528,9 @@ bool QgsComposerAttributeTableV2::getTableContents( QgsComposerTableContents &co
{
continue;
}
QgsFeature* atlasFeature = mComposition->atlasComposition().currentFeature();
if ( !atlasFeature || !atlasFeature->constGeometry() ||
!f.constGeometry()->intersects( atlasFeature->constGeometry() ) )
QgsFeature atlasFeature = mComposition->atlasComposition().feature();
if ( !atlasFeature.constGeometry() ||
!f.constGeometry()->intersects( atlasFeature.constGeometry() ) )
{
//feature falls outside current atlas feature
continue;
@@ -44,7 +44,6 @@ QgsComposerHtml::QgsComposerHtml( QgsComposition* c, bool createUndoCommands )
, mEvaluateExpressions( true )
, mUseSmartBreaks( true )
, mMaxBreakDistance( 10 )
, mExpressionFeature( 0 )
, mExpressionLayer( 0 )
, mDistanceArea( 0 )
, mEnableUserStylesheet( false )
@@ -75,7 +74,7 @@ QgsComposerHtml::QgsComposerHtml( QgsComposition* c, bool createUndoCommands )
{
//a html item added while atlas preview is enabled needs to have the expression context set,
//otherwise fields in the html aren't correctly evaluated until atlas preview feature changes (#9457)
setExpressionContext( mComposition->atlasComposition().currentFeature(), mComposition->atlasComposition().coverageLayer() );
setExpressionContext( mComposition->atlasComposition().feature(), mComposition->atlasComposition().coverageLayer() );
}

//connect to atlas feature changes
@@ -169,7 +168,7 @@ void QgsComposerHtml::loadHtml( const bool useCache )
//evaluate expressions
if ( mEvaluateExpressions )
{
loadedHtml = QgsExpression::replaceExpressionText( loadedHtml, mExpressionFeature, mExpressionLayer, 0, mDistanceArea );
loadedHtml = QgsExpression::replaceExpressionText( loadedHtml, &mExpressionFeature, mExpressionLayer, 0, mDistanceArea );
}

mLoaded = false;
@@ -513,7 +512,7 @@ bool QgsComposerHtml::readXML( const QDomElement& itemElem, const QDomDocument&
return true;
}

void QgsComposerHtml::setExpressionContext( QgsFeature* feature, QgsVectorLayer* layer )
void QgsComposerHtml::setExpressionContext( const QgsFeature &feature, QgsVectorLayer* layer )
{
mExpressionFeature = feature;
mExpressionLayer = layer;
@@ -538,15 +537,15 @@ void QgsComposerHtml::setExpressionContext( QgsFeature* feature, QgsVectorLayer*
void QgsComposerHtml::refreshExpressionContext()
{
QgsVectorLayer * vl = 0;
QgsFeature* feature = 0;
QgsFeature feature;

if ( mComposition->atlasComposition().enabled() )
{
vl = mComposition->atlasComposition().coverageLayer();
}
if ( mComposition->atlasMode() != QgsComposition::AtlasOff )
{
feature = mComposition->atlasComposition().currentFeature();
feature = mComposition->atlasComposition().feature();
}

setExpressionContext( feature, vl );
@@ -17,11 +17,11 @@
#define QGSCOMPOSERHTML_H

#include "qgscomposermultiframe.h"
#include "qgsfeature.h"
#include <QUrl>

class QWebPage;
class QImage;
class QgsFeature;
class QgsVectorLayer;
class QgsNetworkContentFetcher;
class QgsDistanceArea;
@@ -240,7 +240,7 @@ class CORE_EXPORT QgsComposerHtml: public QgsComposerMultiFrame
bool mUseSmartBreaks;
double mMaxBreakDistance;

QgsFeature* mExpressionFeature;
QgsFeature mExpressionFeature;
QgsVectorLayer* mExpressionLayer;
QgsDistanceArea* mDistanceArea;

@@ -258,7 +258,7 @@ class CORE_EXPORT QgsComposerHtml: public QgsComposerMultiFrame
QString fetchHtml( QUrl url );

/** Sets the current feature, the current layer and a list of local variable substitutions for evaluating expressions */
void setExpressionContext( QgsFeature* feature, QgsVectorLayer* layer );
void setExpressionContext( const QgsFeature& feature, QgsVectorLayer* layer );

/** Calculates the max width of frames in the html multiframe*/
double maxFrameWidth() const;
@@ -48,7 +48,6 @@ QgsComposerLabel::QgsComposerLabel( QgsComposition *composition )
, mFontColor( QColor( 0, 0, 0 ) )
, mHAlignment( Qt::AlignLeft )
, mVAlignment( Qt::AlignTop )
, mExpressionFeature( 0 )
, mExpressionLayer( 0 )
, mDistanceArea( 0 )
{
@@ -73,7 +72,8 @@ QgsComposerLabel::QgsComposerLabel( QgsComposition *composition )
{
//a label added while atlas preview is enabled needs to have the expression context set,
//otherwise fields in the label aren't correctly evaluated until atlas preview feature changes (#9457)
setExpressionContext( mComposition->atlasComposition().currentFeature(), mComposition->atlasComposition().coverageLayer() );
QgsFeature atlasFeature = mComposition->atlasComposition().feature();
setExpressionContext( &atlasFeature, mComposition->atlasComposition().coverageLayer() );
}

if ( mComposition )
@@ -234,9 +234,9 @@ void QgsComposerLabel::setHtmlState( int state )
}
}

void QgsComposerLabel::setExpressionContext( QgsFeature* feature, QgsVectorLayer* layer, QMap<QString, QVariant> substitutions )
void QgsComposerLabel::setExpressionContext( QgsFeature *feature, QgsVectorLayer* layer, QMap<QString, QVariant> substitutions )
{
mExpressionFeature = feature;
mExpressionFeature = feature ? *feature : QgsFeature();
mExpressionLayer = layer;
mSubstitutions = substitutions;

@@ -263,18 +263,18 @@ void QgsComposerLabel::setExpressionContext( QgsFeature* feature, QgsVectorLayer
void QgsComposerLabel::refreshExpressionContext()
{
QgsVectorLayer * vl = 0;
QgsFeature* feature = 0;
QgsFeature feature;

if ( mComposition->atlasComposition().enabled() )
{
vl = mComposition->atlasComposition().coverageLayer();
}
if ( mComposition->atlasMode() != QgsComposition::AtlasOff )
{
feature = mComposition->atlasComposition().currentFeature();
feature = mComposition->atlasComposition().feature();
}

setExpressionContext( feature, vl );
setExpressionContext( &feature, vl );
}

QString QgsComposerLabel::displayText() const
@@ -283,7 +283,7 @@ QString QgsComposerLabel::displayText() const
replaceDateText( displayText );
QMap<QString, QVariant> subs = mSubstitutions;
subs[ "$page" ] = QVariant(( int )mComposition->itemPageNumber( this ) + 1 );
return QgsExpression::replaceExpressionText( displayText, mExpressionFeature, mExpressionLayer, &subs, mDistanceArea );
return QgsExpression::replaceExpressionText( displayText, &mExpressionFeature, mExpressionLayer, &subs, mDistanceArea );
}

void QgsComposerLabel::replaceDateText( QString& text ) const
@@ -197,7 +197,7 @@ class CORE_EXPORT QgsComposerLabel: public QgsComposerItem
/** Replaces replace '$CURRENT_DATE<(FORMAT)>' with the current date (e.g. $CURRENT_DATE(d 'June' yyyy)*/
void replaceDateText( QString& text ) const;

QgsFeature* mExpressionFeature;
QgsFeature mExpressionFeature;
QgsVectorLayer* mExpressionLayer;
QMap<QString, QVariant> mSubstitutions;
QgsDistanceArea* mDistanceArea;
@@ -238,7 +238,8 @@ void QgsComposerShape::drawShapeUsingSymbol( QPainter* p )
{
//using an atlas, so render using current atlas feature
//since there may be data defined symbols using atlas feature properties
mShapeStyleSymbol->renderPolygon( shapePolygon, &rings, mComposition->atlasComposition().currentFeature(), context );
QgsFeature atlasFeature = mComposition->atlasComposition().feature();
mShapeStyleSymbol->renderPolygon( shapePolygon, &rings, &atlasFeature, context );
}
else
{
@@ -3074,8 +3074,9 @@ bool QgsComposition::dataDefinedEvaluate( QgsComposerObject::DataDefinedProperty
expressionValue.clear();

//get fields and feature from atlas
const QgsFeature* currentFeature = 0;
QgsFeature currentFeature;
QgsFields layerFields;
bool useFeature = false;
if ( mAtlasComposition.enabled() )
{
QgsVectorLayer* atlasLayer = mAtlasComposition.coverageLayer();
@@ -3085,12 +3086,12 @@ bool QgsComposition::dataDefinedEvaluate( QgsComposerObject::DataDefinedProperty
}
if ( mAtlasMode != QgsComposition::AtlasOff )
{
currentFeature = mAtlasComposition.currentFeature();
currentFeature = mAtlasComposition.feature();
}
}

//evaluate data defined property using current atlas context
QVariant result = dataDefinedValue( property, currentFeature, layerFields, dataDefinedProperties );
QVariant result = dataDefinedValue( property, useFeature ? &currentFeature : 0, layerFields, dataDefinedProperties );

if ( result.isValid() )
{
@@ -199,7 +199,8 @@ void QgsPaperItem::paint( QPainter* painter, const QStyleOptionGraphicsItem* ite
{
//using an atlas, so render using current atlas feature
//since there may be data defined symbols using atlas feature properties
mComposition->pageStyleSymbol()->renderPolygon( pagePolygon, &rings, mComposition->atlasComposition().currentFeature(), context );
QgsFeature atlasFeature = mComposition->atlasComposition().feature();
mComposition->pageStyleSymbol()->renderPolygon( pagePolygon, &rings, &atlasFeature, context );
}
else
{
@@ -502,7 +502,7 @@ void TestQgsComposerTableV2::attributeTableRelationSource()
QVERIFY( mComposition->atlasComposition().beginRender() );
QVERIFY( mComposition->atlasComposition().prepareForFeature( 0 ) );

QCOMPARE( mComposition->atlasComposition().currentFeature()->attribute( "Class" ).toString(), QString( "Jet" ) );
QCOMPARE( mComposition->atlasComposition().feature().attribute( "Class" ).toString(), QString( "Jet" ) );
QCOMPARE( table->contents()->length(), 8 );

QgsComposerTableRow row = table->contents()->at( 0 );
@@ -531,7 +531,7 @@ void TestQgsComposerTableV2::attributeTableRelationSource()

//next atlas feature
QVERIFY( mComposition->atlasComposition().prepareForFeature( 1 ) );
QCOMPARE( mComposition->atlasComposition().currentFeature()->attribute( "Class" ).toString(), QString( "Biplane" ) );
QCOMPARE( mComposition->atlasComposition().feature().attribute( "Class" ).toString(), QString( "Biplane" ) );
QCOMPARE( table->contents()->length(), 5 );
row = table->contents()->at( 0 );
QCOMPARE( row.at( 0 ), QVariant( "Biplane" ) );

0 comments on commit 19a833c

Please sign in to comment.
You can’t perform that action at this time.