18 #include <QtAlgorithms> 34 : mComposition( composition )
36 , mHideCoverage( false )
37 , mFilenamePattern(
"'output_'||@atlas_featurenumber" )
38 , mCoverageLayer( nullptr )
39 , mSingleFile( false )
40 , mSortFeatures( false )
41 , mSortAscending( true )
42 , mCurrentFeatureNo( 0 )
43 , mFilterFeatures( false )
56 if ( enabled == mEnabled )
67 void QgsAtlasComposition::removeLayers(
const QStringList& layers )
69 if ( !mCoverageLayer )
74 Q_FOREACH (
const QString& layerId, layers )
76 if ( layerId == mCoverageLayer->
id() )
79 mCoverageLayer =
nullptr;
88 if ( layer == mCoverageLayer )
93 mCoverageLayer = layer;
99 if ( pageNumber < 0 || pageNumber >= mFeatureIds.
count() )
102 return mFeatureIds.
at( pageNumber ).second;
139 if ( !mCoverageLayer )
148 if ( mCoverageLayer )
151 if ( idx >= 0 && idx < fields.
count() )
153 mSortKeyAttributeName = fields[idx].name();
157 mSortKeyAttributeName =
"";
171 if ( mKeys[ id1.first ].type() == QVariant::Int )
173 result = mKeys[ id1.first ].toInt() < mKeys[ id2.first ].toInt();
175 else if ( mKeys[ id1.first ].type() == QVariant::Double )
177 result = mKeys[ id1.first ].toDouble() < mKeys[ id2.first ].toDouble();
179 else if ( mKeys[ id1.first ].type() == QVariant::String )
184 return mAscending ? result : !result;
195 if ( !mCoverageLayer )
202 updateFilenameExpression();
208 if ( mFilterFeatures && !mFeatureFilter.isEmpty() )
211 if ( filterExpression->hasParserError() )
213 mFilterParserError = filterExpression->parserErrorString();
220 mFilterParserError =
QString();
225 if ( !mPageNameExpression.isEmpty() )
228 if ( nameExpression->hasParserError() )
230 nameExpression.
reset(
nullptr );
232 nameExpression->prepare( &expressionContext );
239 mFeatureKeys.clear();
240 int sortIdx = mCoverageLayer->
fieldNameIndex( mSortKeyAttributeName );
247 if ( !nameExpression.
isNull() )
249 QVariant result = nameExpression->evaluate( &expressionContext );
250 if ( nameExpression->hasEvalError() )
257 mFeatureIds.
push_back( qMakePair( feat.
id(), pageName ) );
259 if ( mSortFeatures && sortIdx != -1 )
261 mFeatureKeys.insert( feat.
id(), feat.
attributes().
at( sortIdx ) );
266 if ( !mFeatureKeys.isEmpty() )
268 FieldSorter sorter( mFeatureKeys, mSortAscending );
269 qSort( mFeatureIds.begin(), mFeatureIds.end(), sorter );
281 return mFeatureIds.size();
291 if ( !mCoverageLayer )
299 if ( !featuresUpdated )
310 if ( !mCoverageLayer )
322 void QgsAtlasComposition::updateAtlasMaps()
326 mComposition->composerItems( maps );
341 return mFeatureIds.size();
346 int newFeatureNo = mCurrentFeatureNo + 1;
347 if ( newFeatureNo >= mFeatureIds.size() )
349 newFeatureNo = mFeatureIds.size() - 1;
357 int newFeatureNo = mCurrentFeatureNo - 1;
358 if ( newFeatureNo < 0 )
381 for ( ; it != mFeatureIds.
constEnd(); ++it, ++currentIdx )
383 if (( *it ).first == feat->
id() )
385 featureI = currentIdx;
406 if ( !mCoverageLayer )
411 if ( mFeatureIds.isEmpty() )
417 if ( featureI >= mFeatureIds.size() )
422 mCurrentFeatureNo = featureI;
425 mCoverageLayer->getFeatures(
QgsFeatureRequest().setFilterFid( mFeatureIds[ featureI ].first ) ).nextFeature( mCurrentFeature );
430 if ( !evalFeatureFilename( expressionContext ) )
436 mGeometryCache.clear();
440 if ( !mCurrentFeature.isValid() )
457 mComposition->composerItems( maps );
469 atlasMaps << currentMap;
480 computeExtent( atlasMaps[0] );
485 if (( *mit )->atlasDriven() )
516 if ( mTransformedFeatureBounds.isEmpty() )
520 computeExtent( map );
523 double xa1 = mTransformedFeatureBounds.xMinimum();
524 double xa2 = mTransformedFeatureBounds.xMaximum();
525 double ya1 = mTransformedFeatureBounds.yMinimum();
526 double ya2 = mTransformedFeatureBounds.yMaximum();
531 bool isPointLayer =
false;
532 switch ( mCoverageLayer->wkbType() )
541 isPointLayer =
false;
551 double geomCenterX = ( xa1 + xa2 ) / 2.0;
552 double geomCenterY = ( ya1 + ya2 ) / 2.0;
557 double xMin = geomCenterX - mOrigExtent.width() / 2.0;
558 double yMin = geomCenterY - mOrigExtent.height() / 2.0;
561 xMin + mOrigExtent.width(),
562 yMin + mOrigExtent.height() );
567 newExtent.
scale( originalScale / newScale );
572 double newWidth = mOrigExtent.width();
573 double newHeight = mOrigExtent.height();
575 for (
int i = 0; i < scales.
size(); i++ )
577 double ratio = scales[i] / originalScale;
578 newWidth = mOrigExtent.width() * ratio;
579 newHeight = mOrigExtent.height() * ratio;
582 double xMin = geomCenterX - newWidth / 2.0;
583 double yMin = geomCenterY - newHeight / 2.0;
592 newExtent.
scale( scales[i] / newScale );
594 if (( newExtent.
width() >= mTransformedFeatureBounds.width() ) && ( newExtent.
height() >= mTransformedFeatureBounds.height() ) )
606 double geomRatio = mTransformedFeatureBounds.width() / mTransformedFeatureBounds.height();
607 double mapRatio = mOrigExtent.width() / mOrigExtent.height();
610 if ( geomRatio < mapRatio )
613 double adjWidth = ( mapRatio * mTransformedFeatureBounds.height() - mTransformedFeatureBounds.width() ) / 2.0;
618 else if ( geomRatio > mapRatio )
621 double adjHeight = ( mTransformedFeatureBounds.width() / mapRatio - mTransformedFeatureBounds.height() ) / 2.0;
639 return mCurrentFilename;
645 atlasElem.
setAttribute(
"enabled", mEnabled ?
"true" :
"false" );
651 if ( mCoverageLayer )
653 atlasElem.
setAttribute(
"coverageLayer", mCoverageLayer->id() );
660 atlasElem.
setAttribute(
"hideCoverage", mHideCoverage ?
"true" :
"false" );
661 atlasElem.
setAttribute(
"singleFile", mSingleFile ?
"true" :
"false" );
662 atlasElem.
setAttribute(
"filenamePattern", mFilenamePattern );
663 atlasElem.
setAttribute(
"pageNameExpression", mPageNameExpression );
665 atlasElem.
setAttribute(
"sortFeatures", mSortFeatures ?
"true" :
"false" );
668 atlasElem.
setAttribute(
"sortKey", mSortKeyAttributeName );
669 atlasElem.
setAttribute(
"sortAscending", mSortAscending ?
"true" :
"false" );
671 atlasElem.
setAttribute(
"filterFeatures", mFilterFeatures ?
"true" :
"false" );
672 if ( mFilterFeatures )
674 atlasElem.
setAttribute(
"featureFilter", mFeatureFilter );
682 mEnabled = atlasElem.
attribute(
"enabled",
"false" ) ==
"true" ?
true :
false;
691 mCoverageLayer =
nullptr;
695 if ( it.key() == atlasElem.
attribute(
"coverageLayer" ) )
702 mPageNameExpression = atlasElem.
attribute(
"pageNameExpression",
QString() );
703 mSingleFile = atlasElem.
attribute(
"singleFile",
"false" ) ==
"true" ?
true :
false;
704 mFilenamePattern = atlasElem.
attribute(
"filenamePattern",
"" );
706 mSortFeatures = atlasElem.
attribute(
"sortFeatures",
"false" ) ==
"true" ?
true :
false;
709 mSortKeyAttributeName = atlasElem.
attribute(
"sortKey",
"" );
714 int idx = mSortKeyAttributeName.
toInt( &isIndex );
715 if ( isIndex && mCoverageLayer )
717 const QgsFields fields = mCoverageLayer->fields();
718 if ( idx >= 0 && idx < fields.
count() )
720 mSortKeyAttributeName = fields[idx].name();
723 mSortAscending = atlasElem.
attribute(
"sortAscending",
"true" ) ==
"true" ?
true :
false;
725 mFilterFeatures = atlasElem.
attribute(
"filterFeatures",
"false" ) ==
"true" ?
true :
false;
726 if ( mFilterFeatures )
728 mFeatureFilter = atlasElem.
attribute(
"featureFilter",
"" );
731 mHideCoverage = atlasElem.
attribute(
"hideCoverage",
"false" ) ==
"true" ?
true :
false;
740 int composerMapNo = elem.
attribute(
"composerMap",
"-1" ).
toInt();
742 if ( composerMapNo != -1 )
745 mComposition->composerItems( maps );
748 if (( *it )->id() == composerMapNo )
750 composerMap = ( *it );
764 if ( composerMap && fixedScale )
772 mHideCoverage = hide;
778 mComposition->update();
785 mFilenamePattern = pattern;
786 return updateFilenameExpression();
798 if ( mCoverageLayer )
803 return expressionContext;
806 bool QgsAtlasComposition::updateFilenameExpression()
808 if ( !mCoverageLayer )
815 if ( !mFilenamePattern.isEmpty() )
817 mFilenameExpr.reset(
new QgsExpression( mFilenamePattern ) );
820 if ( mFilenameExpr->hasParserError() )
822 mFilenameParserError = mFilenameExpr->parserErrorString();
827 mFilenameExpr->prepare( &expressionContext );
833 evalFeatureFilename( expressionContext );
841 if ( !mFilenamePattern.isEmpty() && !mFilenameExpr.isNull() )
843 QVariant filenameRes = mFilenameExpr->evaluate( &context );
844 if ( mFilenameExpr->hasEvalError() )
850 mCurrentFilename = filenameRes.
toString();
857 mPredefinedScales = scales;
859 qSort( mPredefinedScales.begin(), mPredefinedScales.end() );
913 if ( !mCoverageLayer || !mCurrentFeature.isValid() || !mCurrentFeature.constGeometry() )
921 return *mCurrentFeature.constGeometry();
925 if ( it != mGeometryCache.
constEnd() )
931 if ( mCoverageLayer->crs() == crs )
933 return *mCurrentFeature.constGeometry();
936 QgsGeometry transformed = *mCurrentFeature.constGeometry();
938 mGeometryCache[crs.
srsid()] = transformed;
bool prepareForFeature(const int i, const bool updateMaps=true)
Prepare the atlas map for the given feature.
QgsFeatureId id() const
Get the feature ID for this feature.
Class for parsing and evaluation of expressions (formerly called "search strings").
void setMapUnits(QGis::UnitType mapUnits)
Set the map units.
Wrapper for iterator of features from vector data provider or vector layer.
A rectangle specified with double values.
void renderEnded()
Is emitted when atlas rendering has ended.
double atlasMargin(const QgsComposerObject::PropertyValueType valueType=QgsComposerObject::EvaluatedValue)
Returns the margin size (percentage) used when the map is in atlas mode.
Q_DECL_DEPRECATED int sortKeyAttributeIndex() const
int localeAwareCompare(const QString &other) const
int fieldNameIndex(const QString &fieldName) const
Utility method to get attribute index from name.
QDomNode appendChild(const QDomNode &newChild)
static QgsExpressionContextScope * atlasScope(const QgsAtlasComposition *atlas)
Creates a new scope which contains variables and functions relating to a QgsAtlasComposition.
void setNewAtlasFeatureExtent(const QgsRectangle &extent)
Sets new Extent for the current atlas preview and changes width, height (and implicitely also scale)...
QgsAtlasComposition(QgsComposition *composition)
QString attribute(const QString &name, const QString &defValue) const
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QgsFields fields() const
Returns the list of fields of this layer.
long srsid() const
Returns the SrsId, if available.
Q_DECL_DEPRECATED bool fixedScale() const
Returns whether the atlas map uses a fixed scale.
const QgsMapSettings & mapSettings() const
Return setting of QGIS map canvas.
QString nameForPage(int pageNumber) const
Returns the calculated name for a specified atlas page number.
void cache()
Create cache image.
const_iterator constEnd() const
void scale(double scaleFactor, const QgsPoint *c=nullptr)
Scale the rectangle around its center point.
#define Q_NOWARN_DEPRECATED_PUSH
void setDpi(double dpi)
Set the dpi to be used in scale calculations.
QgsComposition * composition()
bool enabled() const
Returns whether the atlas generation is enabled.
Container of fields for a vector layer.
A geometry is the spatial representation of a feature.
const_iterator constFind(const Key &key) const
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the scope.
void toggled(bool)
Emitted when atlas is enabled or disabled.
void setHideCoverage(bool hide)
Sets whether the coverage layer should be hidden in map items in the composition. ...
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
QString currentPageName() const
Returns the name of the page for the current atlas feature.
double toDouble(bool *ok) const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
void endRender()
Ends the rendering.
void readXML(const QDomElement &elem, const QDomDocument &doc)
Reads general atlas settings from xml.
Q_DECL_DEPRECATED void setFixedScale(bool fixed)
Sets whether the atlas map should use a fixed scale.
Q_DECL_DEPRECATED float margin() const
Returns the margin for the atlas map.
void setAtlasMargin(double margin)
Sets the margin size (percentage) used when the map is in atlas mode.
bool setFilenamePattern(const QString &pattern)
Sets the filename expression used for generating output filenames for each atlas page.
Q_DECL_DEPRECATED void setSortKeyAttributeIndex(int idx)
void setCoverageLayer(QgsVectorLayer *layer)
Sets the coverage layer to use for the atlas features.
void setAtlasScalingMode(AtlasScalingMode mode)
Sets the current atlas scaling mode.
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
bool beginRender()
Begins the rendering.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
Q_DECL_DEPRECATED void setComposerMap(QgsComposerMap *map)
Sets the map used by the atlas.
double calculate(const QgsRectangle &mapExtent, int canvasWidth)
Calculate the scale denominator.
void prepareMap(QgsComposerMap *map)
Recalculates the bounds of an atlas driven map.
QgsAttributes attributes() const
Returns the feature's attributes.
void setAttribute(const QString &name, const QString &value)
void refreshFeature()
Refreshes the current atlas feature, by refetching its attributes from the vector layer provider...
const QgsComposition * composition() const
Returns the composition the item is attached to.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
int toInt(bool *ok, int base) const
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
const_iterator constEnd() const
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
This class wraps a request for features to a vector layer (or directly its vector data provider)...
int numFeatures() const
Returns the number of features in the coverage layer.
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
int count() const
Return number of items.
Q_DECL_DEPRECATED bool atlasFixedScale() const
Returns true if the map uses a fixed scale when in atlas mode.
void setEnabled(bool enabled)
Sets whether the atlas is enabled.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the scope.
int updateFeatures()
Requeries the current atlas coverage layer and applies filtering and sorting.
void writeXML(QDomElement &elem, QDomDocument &doc) const
Graphics scene for map printing.
QString currentFilename() const
Returns the current filename.
Object representing map window.
QgsGeometry currentGeometry(const QgsCoordinateReferenceSystem &projectedTo=QgsCoordinateReferenceSystem()) const
Returns the current atlas geometry in the given projection system (default to the coverage layer's CR...
void featureChanged(QgsFeature *feature)
Is emitted when the current atlas feature changes.
void coverageLayerChanged(QgsVectorLayer *layer)
Is emitted when the coverage layer for an atlas changes.
Calculates scale for a given combination of canvas size, map extent, and monitor dpi.
bool setAtlasMode(const QgsComposition::AtlasMode mode)
Sets the current atlas mode of the composition.
#define Q_NOWARN_DEPRECATED_POP
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
const T & at(int i) const
const_iterator constBegin() const
void renderBegun()
Is emitted when atlas rendering has begun.
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QgsRectangle extent() const
FieldSorter(QgsAtlasComposition::SorterKeys &keys, bool ascending=true)
Q_DECL_DEPRECATED QgsComposerMap * composerMap() const
Returns the map used by the atlas.
void readXMLMapSettings(const QDomElement &elem, const QDomDocument &doc)
Reads old (pre 2.2) map related atlas settings from xml.
Q_DECL_DEPRECATED void setMargin(float margin)
Sets the margin for the atlas map.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
AtlasScalingMode atlasScalingMode() const
Returns the current atlas scaling mode.
Class for storing a coordinate reference system (CRS)
int count(const T &value) const
QString authid() const
Returns the authority identifier for the CRS, which includes both the authority (eg EPSG) and the CRS...
const QMap< QString, QgsMapLayer * > & mapLayers()
Retrieve the mapLayers collection (mainly intended for use by projection)
void parameterChanged()
Emitted when one of the parameters changes.
int transform(const QgsCoordinateTransform &ct)
Transform this geometry as described by CoordinateTransform ct.
void numberFeaturesChanged(int numFeatures)
Is emitted when the number of features for the atlas changes.
bool atlasDriven() const
Returns whether the map extent is set to follow the current atlas feature.
int currentFeatureNumber() const
Returns the current feature number, where a value of 0 corresponds to the first feature.
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
void setAtlasDriven(bool enabled)
Sets whether the map extent will follow the current atlas feature.
QDomElement createElement(const QString &tagName)
bool nextFeature(QgsFeature &f)
void composerItems(QList< T * > &itemList)
Return composer items of a specific type.
double width() const
Width of the rectangle.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Represents a vector layer which manages a vector based data sets.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
void statusMsgChanged(const QString &message)
Is emitted when the atlas has an updated status bar message for the composer window.
void setPredefinedScales(const QVector< qreal > &scales)
Sets the list of predefined scales for the atlas.
bool operator()(const QPair< QgsFeatureId, QString > &id1, const QPair< QgsFeatureId, QString > &id2)
double height() const
Height of the rectangle.
const T value(const Key &key) const
static QgsExpressionContextScope * compositionScope(const QgsComposition *composition)
Creates a new scope which contains variables and functions relating to a QgsComposition.