@@ -74,6 +74,9 @@ QgsAtlasRendering::QgsAtlasRendering( QgsComposition* composition )
74
74
75
75
void QgsAtlasRendering::begin ( const QString& filenamePattern )
76
76
{
77
+ if ( !impl->composition || !impl->composition ->atlasMap () || !impl->composition ->atlasMap ()->atlasCoverageLayer () )
78
+ return ;
79
+
77
80
impl->filenamePattern = filenamePattern;
78
81
79
82
QgsVectorLayer* coverage = impl->composition ->atlasMap ()->atlasCoverageLayer ();
@@ -103,12 +106,7 @@ void QgsAtlasRendering::begin( const QString& filenamePattern )
103
106
}
104
107
105
108
// select all features with all attributes
106
- QgsAttributeList selectedAttributes;
107
- for ( QgsFieldMap::const_iterator fit = fieldmap.begin (); fit != fieldmap.end (); ++fit )
108
- {
109
- selectedAttributes.push_back ( fit.key () );
110
- }
111
- provider->select ( selectedAttributes );
109
+ provider->select ( provider->attributeIndexes () );
112
110
113
111
// features must be stored in a list, since modifying the layer's extent rewinds nextFeature()
114
112
QgsFeature feature;
@@ -134,101 +132,104 @@ void QgsAtlasRendering::begin( const QString& filenamePattern )
134
132
135
133
// special columns for expressions
136
134
QgsExpression::setSpecialColumn ( " $numfeatures" , QVariant ( (int )impl->nFeatures ) );
137
- QgsExpression::setSpecialColumn ( " $numpages" , QVariant ( (int )impl->composition ->numPages () ) );
138
135
}
139
136
140
137
void QgsAtlasRendering::prepareForFeature ( size_t featureI )
141
138
{
142
- QgsFeature* fit = &impl->features [featureI];
139
+ if ( !impl->composition || !impl->composition ->atlasMap () || !impl->composition ->atlasMap ()->atlasCoverageLayer () )
140
+ return ;
143
141
144
- if ( impl->filenamePattern .size () > 0 )
142
+ QgsFeature* fit = &impl->features [featureI];
143
+
144
+ if ( impl->filenamePattern .size () > 0 )
145
+ {
146
+ QgsExpression::setSpecialColumn ( " $feature" , QVariant ( (int )featureI + 1 ) );
147
+ QVariant filenameRes = impl->filenameExpr ->evaluate ( &*fit );
148
+ if ( impl->filenameExpr ->hasEvalError () )
145
149
{
146
- QgsExpression::setSpecialColumn ( " $feature" , QVariant ( (int )featureI + 1 ) );
147
- QVariant filenameRes = impl->filenameExpr ->evaluate ( &*fit );
148
- if ( impl->filenameExpr ->hasEvalError () )
149
- {
150
- throw std::runtime_error ( " Filename eval error: " + impl->filenameExpr ->evalErrorString ().toStdString () );
151
- }
152
-
153
- impl->currentFilename = filenameRes.toString ();
150
+ throw std::runtime_error ( " Filename eval error: " + impl->filenameExpr ->evalErrorString ().toStdString () );
154
151
}
155
-
156
- //
157
- // compute the new extent
158
- // keep the original aspect ratio
159
- // and apply a margin
160
-
161
- // QgsGeometry::boundingBox is expressed in the geometry"s native CRS
162
- // They have to be transformed to the MapRenderer's one
163
- QgsRectangle geom_rect = impl->transform .transform ( fit->geometry ()->boundingBox () );
164
- double xa1 = geom_rect.xMinimum ();
165
- double xa2 = geom_rect.xMaximum ();
166
- double ya1 = geom_rect.yMinimum ();
167
- double ya2 = geom_rect.yMaximum ();
168
- QgsRectangle new_extent = geom_rect;
169
-
170
- // restore the original extent
171
- // (successive calls to setNewExtent tend to deform the original rectangle)
172
- impl->composition ->atlasMap ()->setNewExtent ( impl->origExtent );
173
-
174
- if ( impl->composition ->atlasMap ()->atlasFixedScale () )
152
+
153
+ impl->currentFilename = filenameRes.toString ();
154
+ }
155
+
156
+ //
157
+ // compute the new extent
158
+ // keep the original aspect ratio
159
+ // and apply a margin
160
+
161
+ // QgsGeometry::boundingBox is expressed in the geometry"s native CRS
162
+ // We have to transform the grometry to the destination CRS and ask for the bounding box
163
+ // Note: we cannot directly take the transformation of the bounding box, since transformations are not linear
164
+
165
+ QgsGeometry tgeom ( *fit->geometry () );
166
+ tgeom.transform ( impl->transform );
167
+ QgsRectangle geom_rect = tgeom.boundingBox ();
168
+
169
+ double xa1 = geom_rect.xMinimum ();
170
+ double xa2 = geom_rect.xMaximum ();
171
+ double ya1 = geom_rect.yMinimum ();
172
+ double ya2 = geom_rect.yMaximum ();
173
+ QgsRectangle new_extent = geom_rect;
174
+
175
+ // restore the original extent
176
+ // (successive calls to setNewExtent tend to deform the original rectangle)
177
+ impl->composition ->atlasMap ()->setNewExtent ( impl->origExtent );
178
+
179
+ if ( impl->composition ->atlasMap ()->atlasFixedScale () )
180
+ {
181
+ // only translate, keep the original scale (i.e. width x height)
182
+
183
+ double geom_center_x = (xa1 + xa2) / 2.0 ;
184
+ double geom_center_y = (ya1 + ya2) / 2.0 ;
185
+ double xx = geom_center_x - impl->origExtent .width () / 2.0 ;
186
+ double yy = geom_center_y - impl->origExtent .height () / 2.0 ;
187
+ new_extent = QgsRectangle ( xx,
188
+ yy,
189
+ xx + impl->origExtent .width (),
190
+ yy + impl->origExtent .height () );
191
+ }
192
+ else
193
+ {
194
+ // auto scale
195
+
196
+ double geom_ratio = geom_rect.width () / geom_rect.height ();
197
+ double map_ratio = impl->origExtent .width () / impl->origExtent .height ();
198
+
199
+ // geometry height is too big
200
+ if ( geom_ratio < map_ratio )
175
201
{
176
- // only translate, keep the original scale (i.e. width x height)
177
-
178
- double geom_center_x = (xa1 + xa2) / 2.0 ;
179
- double geom_center_y = (ya1 + ya2) / 2.0 ;
180
- double xx = geom_center_x - impl->origExtent .width () / 2.0 ;
181
- double yy = geom_center_y - impl->origExtent .height () / 2.0 ;
182
- new_extent = QgsRectangle ( xx,
183
- yy,
184
- xx + impl->origExtent .width (),
185
- yy + impl->origExtent .height () );
202
+ new_extent = QgsRectangle ( (xa1 + xa2 + map_ratio * (ya1 - ya2)) / 2.0 ,
203
+ ya1,
204
+ xa1 + map_ratio * (ya2 - ya1),
205
+ ya2);
186
206
}
187
- else
207
+ // geometry width is too big
208
+ else if ( geom_ratio > map_ratio )
188
209
{
189
- // auto scale
190
-
191
- double geom_ratio = geom_rect.width () / geom_rect.height ();
192
- double map_ratio = impl->origExtent .width () / impl->origExtent .height ();
193
-
194
- // geometry height is too big
195
- if ( geom_ratio < map_ratio )
196
- {
197
- new_extent = QgsRectangle ( (xa1 + xa2 + map_ratio * (ya1 - ya2)) / 2.0 ,
198
- ya1,
199
- xa1 + map_ratio * (ya2 - ya1),
200
- ya2);
201
- }
202
- // geometry width is too big
203
- else if ( geom_ratio > map_ratio )
204
- {
205
- new_extent = QgsRectangle ( xa1,
206
- (ya1 + ya2 + (xa1 - xa2) / map_ratio) / 2.0 ,
207
- xa2,
208
- ya1 + (xa2 - xa1) / map_ratio);
209
- }
210
- if ( impl->composition ->atlasMap ()->atlasMargin () > 0.0 )
211
- {
212
- new_extent.scale ( 1 + impl->composition ->atlasMap ()->atlasMargin () );
213
- }
210
+ new_extent = QgsRectangle ( xa1,
211
+ (ya1 + ya2 + (xa1 - xa2) / map_ratio) / 2.0 ,
212
+ xa2,
213
+ ya1 + (xa2 - xa1) / map_ratio);
214
214
}
215
-
216
- // evaluate label expressions
217
- QList<QgsComposerLabel*> labels;
218
- impl->composition ->composerItems ( labels );
219
- QgsExpression::setSpecialColumn ( " $feature" , QVariant ( (int )featureI + 1 ) );
220
-
221
- for ( QList<QgsComposerLabel*>::iterator lit = labels.begin (); lit != labels.end (); ++lit )
215
+ if ( impl->composition ->atlasMap ()->atlasMargin () > 0.0 )
222
216
{
223
- // build a local substitution map
224
- QMap<QString, QVariant> pageMap;
225
- pageMap.insert ( " $page" , QVariant ( (int )impl->composition ->itemPageNumber ( *lit ) + 1 ) );
226
- (*lit)->setExpressionContext ( fit, impl->composition ->atlasMap ()->atlasCoverageLayer (), pageMap );
217
+ new_extent.scale ( 1 + impl->composition ->atlasMap ()->atlasMargin () );
227
218
}
228
-
229
-
230
- // set the new extent (and render)
231
- impl->composition ->atlasMap ()->setNewExtent ( new_extent );
219
+ }
220
+
221
+ // evaluate label expressions
222
+ QList<QgsComposerLabel*> labels;
223
+ impl->composition ->composerItems ( labels );
224
+ QgsExpression::setSpecialColumn ( " $feature" , QVariant ( (int )featureI + 1 ) );
225
+
226
+ for ( QList<QgsComposerLabel*>::iterator lit = labels.begin (); lit != labels.end (); ++lit )
227
+ {
228
+ (*lit)->setExpressionContext ( fit, impl->composition ->atlasMap ()->atlasCoverageLayer () );
229
+ }
230
+
231
+ // set the new extent (and render)
232
+ impl->composition ->atlasMap ()->setNewExtent ( new_extent );
232
233
}
233
234
234
235
size_t QgsAtlasRendering::numFeatures () const
@@ -243,6 +244,9 @@ const QString& QgsAtlasRendering::currentFilename() const
243
244
244
245
void QgsAtlasRendering::end ()
245
246
{
247
+ if ( !impl->composition || !impl->composition ->atlasMap () || !impl->composition ->atlasMap ()->atlasCoverageLayer () )
248
+ return ;
249
+
246
250
// reset label expression contexts
247
251
QList<QgsComposerLabel*> labels;
248
252
impl->composition ->composerItems ( labels );
@@ -350,6 +354,10 @@ void QgsComposition::setNumPages( int pages )
350
354
mPages .removeLast ();
351
355
}
352
356
}
357
+
358
+ // update the corresponding variable
359
+ QgsExpression::setSpecialColumn ( " $numpages" , QVariant ((int )numPages ()) );
360
+
353
361
emit nPagesChanged ();
354
362
}
355
363
@@ -1700,6 +1708,8 @@ void QgsComposition::addPaperItem()
1700
1708
addItem ( paperItem );
1701
1709
paperItem->setZValue ( 0 );
1702
1710
mPages .push_back ( paperItem );
1711
+
1712
+ QgsExpression::setSpecialColumn ( " $numpages" , QVariant ((int )mPages .size ()) );
1703
1713
}
1704
1714
1705
1715
void QgsComposition::removePaperItems ()
@@ -1709,6 +1719,7 @@ void QgsComposition::removePaperItems()
1709
1719
delete mPages .at ( i );
1710
1720
}
1711
1721
mPages .clear ();
1722
+ QgsExpression::setSpecialColumn ( " $numpages" , QVariant ((int )0 ) );
1712
1723
}
1713
1724
1714
1725
void QgsComposition::deleteAndRemoveMultiFrames ()
@@ -1836,3 +1847,32 @@ void QgsComposition::renderPage( QPainter* p, int page )
1836
1847
1837
1848
mPlotStyle = savedPlotStyle;
1838
1849
}
1850
+
1851
+ void QgsComposition::setAtlasMap ( QgsComposerMap* map )
1852
+ {
1853
+ mAtlasMap = map;
1854
+ if ( map != 0 )
1855
+ {
1856
+ QObject::connect ( map, SIGNAL ( atlasCoverageLayerChanged ( QgsVectorLayer* )), this , SLOT ( onAtlasCoverageChanged ( QgsVectorLayer* ) ) );
1857
+ }
1858
+ else
1859
+ {
1860
+ QObject::disconnect ( map, SIGNAL ( atlasCoverageLayerChanged ( QgsVectorLayer* )), this , SLOT ( onAtlasCoverageChanged ( QgsVectorLayer* ) ) );
1861
+ }
1862
+ }
1863
+
1864
+ void QgsComposition::onAtlasCoverageChanged ( QgsVectorLayer* )
1865
+ {
1866
+ // update variables
1867
+ if ( mAtlasMap != 0 && mAtlasMap ->atlasCoverageLayer () != 0 )
1868
+ {
1869
+ QgsVectorDataProvider* provider = mAtlasMap ->atlasCoverageLayer ()->dataProvider ();
1870
+ QgsExpression::setSpecialColumn ( " $numfeatures" , QVariant ( (int )provider->featureCount () ) );
1871
+ }
1872
+ else
1873
+ {
1874
+ QgsExpression::setSpecialColumn ( " $numfeatures" , QVariant ( (int )0 ) );
1875
+ }
1876
+ //
1877
+ QgsExpression::setSpecialColumn ( " $numpages" , QVariant ( (int )numPages () ) );
1878
+ }
0 commit comments