18 #include <QtAlgorithms> 34 : mComposition( composition )
36 , mHideCoverage( false )
37 , mFilenamePattern(
"'output_'||@atlas_featurenumber" )
38 , mSingleFile( false )
39 , mSortFeatures( false )
40 , mSortAscending( true )
41 , mCurrentFeatureNo( 0 )
42 , mFilterFeatures( false )
55 if ( enabled == mEnabled )
66 void QgsAtlasComposition::removeLayers(
const QStringList& layers )
68 if ( !mCoverageLayer )
73 Q_FOREACH (
const QString& layerId, layers )
75 if ( layerId == mCoverageLayer.
layerId )
87 if ( layer == mCoverageLayer.
get() )
98 if ( pageNumber < 0 || pageNumber >= mFeatureIds.
count() )
101 return mFeatureIds.
at( pageNumber ).second;
138 if ( !mCoverageLayer )
147 if ( mCoverageLayer )
150 if ( idx >= 0 && idx < fields.
count() )
152 mSortKeyAttributeName = fields.
at( idx ).
name();
156 mSortKeyAttributeName =
"";
165 , mAscending( ascending )
170 return mAscending ?
qgsVariantLessThan( mKeys.value( id1.first ), mKeys.value( id2.first ) )
185 if ( !mCoverageLayer )
192 updateFilenameExpression();
198 if ( mFilterFeatures && !mFeatureFilter.isEmpty() )
201 if ( filterExpression->hasParserError() )
203 mFilterParserError = filterExpression->parserErrorString();
210 mFilterParserError =
QString();
215 if ( !mPageNameExpression.isEmpty() )
218 if ( nameExpression->hasParserError() )
220 nameExpression.
reset(
nullptr );
224 nameExpression->prepare( &expressionContext );
232 mFeatureKeys.clear();
233 int sortIdx = mCoverageLayer->
fieldNameIndex( mSortKeyAttributeName );
240 if ( !nameExpression.
isNull() )
242 QVariant result = nameExpression->evaluate( &expressionContext );
243 if ( nameExpression->hasEvalError() )
250 mFeatureIds.
push_back( qMakePair( feat.
id(), pageName ) );
252 if ( mSortFeatures && sortIdx != -1 )
254 mFeatureKeys.insert( feat.
id(), feat.
attributes().
at( sortIdx ) );
259 if ( !mFeatureKeys.isEmpty() )
261 FieldSorter sorter( mFeatureKeys, mSortAscending );
262 qSort( mFeatureIds.begin(), mFeatureIds.end(), sorter );
274 return mFeatureIds.size();
284 if ( !mCoverageLayer )
292 if ( !featuresUpdated )
303 if ( !mCoverageLayer )
315 void QgsAtlasComposition::updateAtlasMaps()
319 mComposition->composerItems( maps );
334 return mFeatureIds.size();
339 int newFeatureNo = mCurrentFeatureNo + 1;
340 if ( newFeatureNo >= mFeatureIds.size() )
342 newFeatureNo = mFeatureIds.size() - 1;
350 int newFeatureNo = mCurrentFeatureNo - 1;
351 if ( newFeatureNo < 0 )
374 for ( ; it != mFeatureIds.
constEnd(); ++it, ++currentIdx )
376 if (( *it ).first == feat->
id() )
378 featureI = currentIdx;
399 if ( !mCoverageLayer )
404 if ( mFeatureIds.isEmpty() )
410 if ( featureI >= mFeatureIds.size() )
415 mCurrentFeatureNo = featureI;
418 mCoverageLayer->getFeatures(
QgsFeatureRequest().setFilterFid( mFeatureIds[ featureI ].first ) ).nextFeature( mCurrentFeature );
423 if ( !evalFeatureFilename( expressionContext ) )
429 mGeometryCache.clear();
433 if ( !mCurrentFeature.isValid() )
450 mComposition->composerItems( maps );
462 atlasMaps << currentMap;
473 computeExtent( atlasMaps[0] );
478 if (( *mit )->atlasDriven() )
509 if ( mTransformedFeatureBounds.isEmpty() )
513 computeExtent( map );
516 double xa1 = mTransformedFeatureBounds.xMinimum();
517 double xa2 = mTransformedFeatureBounds.xMaximum();
518 double ya1 = mTransformedFeatureBounds.yMinimum();
519 double ya2 = mTransformedFeatureBounds.yMaximum();
524 bool isPointLayer =
false;
525 switch ( mCoverageLayer->wkbType() )
534 isPointLayer =
false;
544 double geomCenterX = ( xa1 + xa2 ) / 2.0;
545 double geomCenterY = ( ya1 + ya2 ) / 2.0;
550 double xMin = geomCenterX - mOrigExtent.width() / 2.0;
551 double yMin = geomCenterY - mOrigExtent.height() / 2.0;
554 xMin + mOrigExtent.width(),
555 yMin + mOrigExtent.height() );
560 newExtent.
scale( originalScale / newScale );
565 double newWidth = mOrigExtent.width();
566 double newHeight = mOrigExtent.height();
568 for (
int i = 0; i < scales.
size(); i++ )
570 double ratio = scales[i] / originalScale;
571 newWidth = mOrigExtent.width() * ratio;
572 newHeight = mOrigExtent.height() * ratio;
575 double xMin = geomCenterX - newWidth / 2.0;
576 double yMin = geomCenterY - newHeight / 2.0;
585 newExtent.
scale( scales[i] / newScale );
587 if (( newExtent.
width() >= mTransformedFeatureBounds.width() ) && ( newExtent.
height() >= mTransformedFeatureBounds.height() ) )
599 double geomRatio = mTransformedFeatureBounds.width() / mTransformedFeatureBounds.height();
600 double mapRatio = mOrigExtent.width() / mOrigExtent.height();
603 if ( geomRatio < mapRatio )
606 double adjWidth = ( mapRatio * mTransformedFeatureBounds.height() - mTransformedFeatureBounds.width() ) / 2.0;
611 else if ( geomRatio > mapRatio )
614 double adjHeight = ( mTransformedFeatureBounds.width() / mapRatio - mTransformedFeatureBounds.height() ) / 2.0;
632 return mCurrentFilename;
638 atlasElem.
setAttribute(
"enabled", mEnabled ?
"true" :
"false" );
644 if ( mCoverageLayer )
646 atlasElem.
setAttribute(
"coverageLayer", mCoverageLayer.layerId );
647 atlasElem.
setAttribute(
"coverageLayerName", mCoverageLayer.name );
648 atlasElem.
setAttribute(
"coverageLayerSource", mCoverageLayer.source );
649 atlasElem.
setAttribute(
"coverageLayerProvider", mCoverageLayer.provider );
656 atlasElem.
setAttribute(
"hideCoverage", mHideCoverage ?
"true" :
"false" );
657 atlasElem.
setAttribute(
"singleFile", mSingleFile ?
"true" :
"false" );
658 atlasElem.
setAttribute(
"filenamePattern", mFilenamePattern );
659 atlasElem.
setAttribute(
"pageNameExpression", mPageNameExpression );
661 atlasElem.
setAttribute(
"sortFeatures", mSortFeatures ?
"true" :
"false" );
664 atlasElem.
setAttribute(
"sortKey", mSortKeyAttributeName );
665 atlasElem.
setAttribute(
"sortAscending", mSortAscending ?
"true" :
"false" );
667 atlasElem.
setAttribute(
"filterFeatures", mFilterFeatures ?
"true" :
"false" );
668 if ( mFilterFeatures )
670 atlasElem.
setAttribute(
"featureFilter", mFeatureFilter );
678 mEnabled = atlasElem.
attribute(
"enabled",
"false" ) ==
"true" ? true :
false;
692 mCoverageLayer =
QgsVectorLayerRef( layerId, layerName, layerSource, layerProvider );
693 mCoverageLayer.resolveWeakly();
695 mPageNameExpression = atlasElem.
attribute(
"pageNameExpression",
QString() );
696 mSingleFile = atlasElem.
attribute(
"singleFile",
"false" ) ==
"true" ? true :
false;
697 mFilenamePattern = atlasElem.
attribute(
"filenamePattern",
"" );
699 mSortFeatures = atlasElem.
attribute(
"sortFeatures",
"false" ) ==
"true" ? true :
false;
702 mSortKeyAttributeName = atlasElem.
attribute(
"sortKey",
"" );
707 int idx = mSortKeyAttributeName.
toInt( &isIndex );
708 if ( isIndex && mCoverageLayer )
710 QgsFields fields = mCoverageLayer->fields();
711 if ( idx >= 0 && idx < fields.
count() )
713 mSortKeyAttributeName = fields.
at( idx ).
name();
716 mSortAscending = atlasElem.
attribute(
"sortAscending",
"true" ) ==
"true" ? true :
false;
718 mFilterFeatures = atlasElem.
attribute(
"filterFeatures",
"false" ) ==
"true" ? true :
false;
719 if ( mFilterFeatures )
721 mFeatureFilter = atlasElem.
attribute(
"featureFilter",
"" );
724 mHideCoverage = atlasElem.
attribute(
"hideCoverage",
"false" ) ==
"true" ? true :
false;
733 int composerMapNo = elem.
attribute(
"composerMap",
"-1" ).
toInt();
735 if ( composerMapNo != -1 )
738 mComposition->composerItems( maps );
741 if (( *it )->id() == composerMapNo )
743 composerMap = ( *it );
757 if ( composerMap && fixedScale )
765 mHideCoverage = hide;
771 mComposition->update();
778 mFilenamePattern = pattern;
779 return updateFilenameExpression();
791 if ( mCoverageLayer )
796 return expressionContext;
799 bool QgsAtlasComposition::updateFilenameExpression()
801 if ( !mCoverageLayer )
808 if ( !mFilenamePattern.isEmpty() )
810 mFilenameExpr.reset(
new QgsExpression( mFilenamePattern ) );
813 if ( mFilenameExpr->hasParserError() )
815 mFilenameParserError = mFilenameExpr->parserErrorString();
820 mFilenameExpr->prepare( &expressionContext );
826 evalFeatureFilename( expressionContext );
834 if ( !mFilenamePattern.isEmpty() && !mFilenameExpr.isNull() )
836 QVariant filenameRes = mFilenameExpr->evaluate( &context );
837 if ( mFilenameExpr->hasEvalError() )
843 mCurrentFilename = filenameRes.
toString();
850 mPredefinedScales = scales;
852 qSort( mPredefinedScales.begin(), mPredefinedScales.end() );
906 if ( !mCoverageLayer || !mCurrentFeature.isValid() || !mCurrentFeature.constGeometry() )
914 return *mCurrentFeature.constGeometry();
918 if ( it != mGeometryCache.
constEnd() )
924 if ( mCoverageLayer->crs() == crs )
926 return *mCurrentFeature.constGeometry();
929 QgsGeometry transformed = *mCurrentFeature.constGeometry();
931 mGeometryCache[crs.
srsid()] = transformed;
bool prepareForFeature(const int i, const bool updateMaps=true)
Prepare the atlas map for the given 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.
bool atlasDriven() const
Returns whether the map extent is set to follow the current atlas feature.
A rectangle specified with double values.
QgsAttributes attributes() const
Returns the feature's attributes.
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.
void composerItems(QList< T *> &itemList)
Return composer items of a specific type.
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.
QgsRectangle extent() const
void cache()
Create cache image.
const_iterator constEnd() const
QString currentPageName() const
Returns the name of the page for the current atlas feature.
void scale(double scaleFactor, const QgsPoint *c=nullptr)
Scale the rectangle around its center point.
QString nameForPage(int pageNumber) const
Returns the calculated name for a specified atlas page number.
#define Q_NOWARN_DEPRECATED_PUSH
void setDpi(double dpi)
Set the dpi to be used in scale calculations.
QgsComposition * composition()
QString currentFilename() const
Returns the current filename.
Container of fields for a vector layer.
A geometry is the spatial representation of a feature.
int numFeatures() const
Returns the number of features in the coverage layer.
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...
bool qgsVariantGreaterThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is greater than the second.
double toDouble(bool *ok) const
int count() const
Return number of items.
QString tr(const char *sourceText, const char *disambiguation, int n)
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
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.
QgsFields fields() const
Returns the list of fields of this layer.
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.
QString layerId
Original layer ID.
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.
void setAttribute(const QString &name, const QString &value)
void refreshFeature()
Refreshes the current atlas feature, by refetching its attributes from the vector layer provider...
double width() const
Width of the rectangle.
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)
Q_DECL_DEPRECATED bool atlasFixedScale() const
Returns true if the map uses a fixed scale when in atlas mode.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
void setEnabled(bool enabled)
Sets whether the atlas is enabled.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the scope.
void setLayer(TYPE *l)
Sets the reference to point to a specified layer.
int updateFeatures()
Requeries the current atlas coverage layer and applies filtering and sorting.
Graphics scene for map printing.
const QgsMapSettings & mapSettings() const
Return setting of QGIS map canvas.
Object representing map window.
int currentFeatureNumber() const
Returns the current feature number, where a value of 0 corresponds to the first feature.
QgsFeatureId id() const
Get the feature ID for this feature.
void featureChanged(QgsFeature *feature)
Is emitted when the current atlas feature changes.
Q_DECL_DEPRECATED bool fixedScale() const
Returns whether the atlas map uses a fixed scale.
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
int fieldNameIndex(const QString &fieldName) const
Utility method to get attribute index from name.
const T & at(int i) const
const_iterator constBegin() const
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 renderBegun()
Is emitted when atlas rendering has begun.
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
const QgsComposition * composition() const
Returns the composition the item is attached to.
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.
AtlasScalingMode atlasScalingMode() const
Returns the current atlas scaling mode.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
_LayerRef< QgsVectorLayer > QgsVectorLayerRef
Class for storing a coordinate reference system (CRS)
int count(const T &value) const
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.
Q_DECL_DEPRECATED QgsComposerMap * composerMap() const
Returns the map used by the atlas.
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
Q_DECL_DEPRECATED int sortKeyAttributeIndex() const
void setAtlasDriven(bool enabled)
Sets whether the map extent will follow the current atlas feature.
Q_DECL_DEPRECATED float margin() const
Returns the margin for the atlas map.
QDomElement createElement(const QString &tagName)
bool nextFeature(QgsFeature &f)
long srsid() const
Returns the SrsId, if available.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void writeXML(QDomElement &elem, QDomDocument &doc) const
Represents a vector layer which manages a vector based data sets.
TYPE * get() const
Returns a pointer to the layer, or nullptr if the reference has not yet been matched to a layer...
void statusMsgChanged(const QString &message)
Is emitted when the atlas has an updated status bar message for the composer window.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
QString authid() const
Returns the authority identifier for the CRS, which includes both the authority (eg EPSG) and the CRS...
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
bool enabled() const
Returns whether the atlas generation is enabled.
void setPredefinedScales(const QVector< qreal > &scales)
Sets the list of predefined scales for the atlas.
double height() const
Height of the rectangle.
const T value(const Key &key) const
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
static QgsExpressionContextScope * compositionScope(const QgsComposition *composition)
Creates a new scope which contains variables and functions relating to a QgsComposition.