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 =
"";
169 return mAscending ?
qgsVariantLessThan( mKeys.value( id1.first ), mKeys.value( id2.first ) )
182 if ( !mCoverageLayer )
189 updateFilenameExpression();
195 if ( mFilterFeatures && !mFeatureFilter.isEmpty() )
198 if ( filterExpression->hasParserError() )
200 mFilterParserError = filterExpression->parserErrorString();
207 mFilterParserError =
QString();
212 if ( !mPageNameExpression.isEmpty() )
215 if ( nameExpression->hasParserError() )
217 nameExpression.
reset(
nullptr );
221 nameExpression->prepare( &expressionContext );
229 mFeatureKeys.clear();
230 int sortIdx = mCoverageLayer->
fieldNameIndex( mSortKeyAttributeName );
237 if ( !nameExpression.
isNull() )
239 QVariant result = nameExpression->evaluate( &expressionContext );
240 if ( nameExpression->hasEvalError() )
247 mFeatureIds.
push_back( qMakePair( feat.
id(), pageName ) );
249 if ( mSortFeatures && sortIdx != -1 )
251 mFeatureKeys.insert( feat.
id(), feat.
attributes().
at( sortIdx ) );
256 if ( !mFeatureKeys.isEmpty() )
258 FieldSorter sorter( mFeatureKeys, mSortAscending );
259 qSort( mFeatureIds.begin(), mFeatureIds.end(), sorter );
271 return mFeatureIds.size();
281 if ( !mCoverageLayer )
289 if ( !featuresUpdated )
300 if ( !mCoverageLayer )
312 void QgsAtlasComposition::updateAtlasMaps()
316 mComposition->composerItems( maps );
331 return mFeatureIds.size();
336 int newFeatureNo = mCurrentFeatureNo + 1;
337 if ( newFeatureNo >= mFeatureIds.size() )
339 newFeatureNo = mFeatureIds.size() - 1;
347 int newFeatureNo = mCurrentFeatureNo - 1;
348 if ( newFeatureNo < 0 )
371 for ( ; it != mFeatureIds.
constEnd(); ++it, ++currentIdx )
373 if (( *it ).first == feat->
id() )
375 featureI = currentIdx;
396 if ( !mCoverageLayer )
401 if ( mFeatureIds.isEmpty() )
407 if ( featureI >= mFeatureIds.size() )
412 mCurrentFeatureNo = featureI;
415 mCoverageLayer->getFeatures(
QgsFeatureRequest().setFilterFid( mFeatureIds[ featureI ].first ) ).nextFeature( mCurrentFeature );
420 if ( !evalFeatureFilename( expressionContext ) )
426 mGeometryCache.clear();
430 if ( !mCurrentFeature.isValid() )
447 mComposition->composerItems( maps );
459 atlasMaps << currentMap;
470 computeExtent( atlasMaps[0] );
475 if (( *mit )->atlasDriven() )
506 if ( mTransformedFeatureBounds.isEmpty() )
510 computeExtent( map );
513 double xa1 = mTransformedFeatureBounds.xMinimum();
514 double xa2 = mTransformedFeatureBounds.xMaximum();
515 double ya1 = mTransformedFeatureBounds.yMinimum();
516 double ya2 = mTransformedFeatureBounds.yMaximum();
521 bool isPointLayer =
false;
522 switch ( mCoverageLayer->wkbType() )
531 isPointLayer =
false;
541 double geomCenterX = ( xa1 + xa2 ) / 2.0;
542 double geomCenterY = ( ya1 + ya2 ) / 2.0;
547 double xMin = geomCenterX - mOrigExtent.width() / 2.0;
548 double yMin = geomCenterY - mOrigExtent.height() / 2.0;
551 xMin + mOrigExtent.width(),
552 yMin + mOrigExtent.height() );
557 newExtent.
scale( originalScale / newScale );
562 double newWidth = mOrigExtent.width();
563 double newHeight = mOrigExtent.height();
565 for (
int i = 0; i < scales.
size(); i++ )
567 double ratio = scales[i] / originalScale;
568 newWidth = mOrigExtent.width() * ratio;
569 newHeight = mOrigExtent.height() * ratio;
572 double xMin = geomCenterX - newWidth / 2.0;
573 double yMin = geomCenterY - newHeight / 2.0;
582 newExtent.
scale( scales[i] / newScale );
584 if (( newExtent.
width() >= mTransformedFeatureBounds.width() ) && ( newExtent.
height() >= mTransformedFeatureBounds.height() ) )
596 double geomRatio = mTransformedFeatureBounds.width() / mTransformedFeatureBounds.height();
597 double mapRatio = mOrigExtent.width() / mOrigExtent.height();
600 if ( geomRatio < mapRatio )
603 double adjWidth = ( mapRatio * mTransformedFeatureBounds.height() - mTransformedFeatureBounds.width() ) / 2.0;
608 else if ( geomRatio > mapRatio )
611 double adjHeight = ( mTransformedFeatureBounds.width() / mapRatio - mTransformedFeatureBounds.height() ) / 2.0;
629 return mCurrentFilename;
635 atlasElem.
setAttribute(
"enabled", mEnabled ?
"true" :
"false" );
641 if ( mCoverageLayer )
643 atlasElem.
setAttribute(
"coverageLayer", mCoverageLayer->id() );
650 atlasElem.
setAttribute(
"hideCoverage", mHideCoverage ?
"true" :
"false" );
651 atlasElem.
setAttribute(
"singleFile", mSingleFile ?
"true" :
"false" );
652 atlasElem.
setAttribute(
"filenamePattern", mFilenamePattern );
653 atlasElem.
setAttribute(
"pageNameExpression", mPageNameExpression );
655 atlasElem.
setAttribute(
"sortFeatures", mSortFeatures ?
"true" :
"false" );
658 atlasElem.
setAttribute(
"sortKey", mSortKeyAttributeName );
659 atlasElem.
setAttribute(
"sortAscending", mSortAscending ?
"true" :
"false" );
661 atlasElem.
setAttribute(
"filterFeatures", mFilterFeatures ?
"true" :
"false" );
662 if ( mFilterFeatures )
664 atlasElem.
setAttribute(
"featureFilter", mFeatureFilter );
672 mEnabled = atlasElem.
attribute(
"enabled",
"false" ) ==
"true" ? true :
false;
681 mCoverageLayer =
nullptr;
685 if ( it.key() == atlasElem.
attribute(
"coverageLayer" ) )
692 mPageNameExpression = atlasElem.
attribute(
"pageNameExpression",
QString() );
693 mSingleFile = atlasElem.
attribute(
"singleFile",
"false" ) ==
"true" ? true :
false;
694 mFilenamePattern = atlasElem.
attribute(
"filenamePattern",
"" );
696 mSortFeatures = atlasElem.
attribute(
"sortFeatures",
"false" ) ==
"true" ? true :
false;
699 mSortKeyAttributeName = atlasElem.
attribute(
"sortKey",
"" );
704 int idx = mSortKeyAttributeName.
toInt( &isIndex );
705 if ( isIndex && mCoverageLayer )
707 const QgsFields fields = mCoverageLayer->fields();
708 if ( idx >= 0 && idx < fields.
count() )
710 mSortKeyAttributeName = fields[idx].name();
713 mSortAscending = atlasElem.
attribute(
"sortAscending",
"true" ) ==
"true" ? true :
false;
715 mFilterFeatures = atlasElem.
attribute(
"filterFeatures",
"false" ) ==
"true" ? true :
false;
716 if ( mFilterFeatures )
718 mFeatureFilter = atlasElem.
attribute(
"featureFilter",
"" );
721 mHideCoverage = atlasElem.
attribute(
"hideCoverage",
"false" ) ==
"true" ? true :
false;
730 int composerMapNo = elem.
attribute(
"composerMap",
"-1" ).
toInt();
732 if ( composerMapNo != -1 )
735 mComposition->composerItems( maps );
738 if (( *it )->id() == composerMapNo )
740 composerMap = ( *it );
754 if ( composerMap && fixedScale )
762 mHideCoverage = hide;
768 mComposition->update();
775 mFilenamePattern = pattern;
776 return updateFilenameExpression();
788 if ( mCoverageLayer )
793 return expressionContext;
796 bool QgsAtlasComposition::updateFilenameExpression()
798 if ( !mCoverageLayer )
805 if ( !mFilenamePattern.isEmpty() )
807 mFilenameExpr.reset(
new QgsExpression( mFilenamePattern ) );
810 if ( mFilenameExpr->hasParserError() )
812 mFilenameParserError = mFilenameExpr->parserErrorString();
817 mFilenameExpr->prepare( &expressionContext );
823 evalFeatureFilename( expressionContext );
831 if ( !mFilenamePattern.isEmpty() && !mFilenameExpr.isNull() )
833 QVariant filenameRes = mFilenameExpr->evaluate( &context );
834 if ( mFilenameExpr->hasEvalError() )
840 mCurrentFilename = filenameRes.
toString();
847 mPredefinedScales = scales;
849 qSort( mPredefinedScales.begin(), mPredefinedScales.end() );
903 if ( !mCoverageLayer || !mCurrentFeature.isValid() || !mCurrentFeature.constGeometry() )
911 return *mCurrentFeature.constGeometry();
915 if ( it != mGeometryCache.
constEnd() )
921 if ( mCoverageLayer->crs() == crs )
923 return *mCurrentFeature.constGeometry();
926 QgsGeometry transformed = *mCurrentFeature.constGeometry();
928 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)
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
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.
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.
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
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.
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.
FieldSorter(QgsAtlasComposition::SorterKeys &keys, bool ascending=true)
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.
Class for storing a coordinate reference system (CRS)
int count(const T &value) const
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.
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.
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.
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
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.