Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgslayoutatlas.h 3 : : ---------------- 4 : : begin : December 2017 5 : : copyright : (C) 2017 by Nyall Dawson 6 : : email : nyall dot dawson at gmail dot com 7 : : ***************************************************************************/ 8 : : /*************************************************************************** 9 : : * * 10 : : * This program is free software; you can redistribute it and/or modify * 11 : : * it under the terms of the GNU General Public License as published by * 12 : : * the Free Software Foundation; either version 2 of the License, or * 13 : : * (at your option) any later version. * 14 : : * * 15 : : ***************************************************************************/ 16 : : #ifndef QGSLAYOUTATLAS_H 17 : : #define QGSLAYOUTATLAS_H 18 : : 19 : : #include "qgis_core.h" 20 : : #include "qgsvectorlayerref.h" 21 : : #include "qgslayoutserializableobject.h" 22 : : #include "qgsabstractlayoutiterator.h" 23 : : #include "qgsexpressioncontextgenerator.h" 24 : : #include <QObject> 25 : : 26 : : class QgsLayout; 27 : : 28 : : /** 29 : : * \ingroup core 30 : : * \brief Class used to render QgsLayout as an atlas, by iterating over the features from an associated vector layer. 31 : : * 32 : : * QgsLayoutAtlas implement the QgsAbstractLayoutIterator interface, allowing them to be used 33 : : * directly with QgsLayoutExporter to automatically output all pages from the atlas. 34 : : * 35 : : * For QgsPrintLayout layouts, it is not necessary to manually construct a 36 : : * QgsLayoutAtlas object. Instead, the atlas attached to the print layout 37 : : * should be used. This can be retrieved by calling QgsPrintLayout::atlas(). 38 : : * 39 : : * \since QGIS 3.0 40 : : */ 41 : : class CORE_EXPORT QgsLayoutAtlas : public QObject, public QgsAbstractLayoutIterator, public QgsLayoutSerializableObject, public QgsExpressionContextGenerator 42 : : { 43 : 0 : Q_OBJECT 44 : : public: 45 : : 46 : : /** 47 : : * Constructor for new QgsLayoutAtlas. 48 : : */ 49 : : QgsLayoutAtlas( QgsLayout *layout SIP_TRANSFERTHIS ); 50 : : 51 : : QString stringType() const override; 52 : : QgsLayout *layout() override; 53 : : 54 : : /** 55 : : * Returns the atlas' layout. 56 : : * \note Not available in Python bindings. 57 : : */ 58 : : const QgsLayout *layout() const SIP_SKIP; 59 : : 60 : : bool writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context ) const override; 61 : : bool readXml( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context ) override; 62 : : 63 : : /** 64 : : * Returns whether the atlas generation is enabled 65 : : * \see setEnabled() 66 : : */ 67 : 0 : bool enabled() const { return mEnabled; } 68 : : 69 : : /** 70 : : * Sets whether the atlas is \a enabled. 71 : : * \see enabled() 72 : : */ 73 : : void setEnabled( bool enabled ); 74 : : 75 : : /** 76 : : * Returns TRUE if the atlas is set to hide the coverage layer. 77 : : * \see setHideCoverage() 78 : : */ 79 : : bool hideCoverage() const { return mHideCoverage; } 80 : : 81 : : /** 82 : : * Sets whether the coverage layer should be hidden in map items in the layouts. 83 : : * \see hideCoverage() 84 : : */ 85 : : void setHideCoverage( bool hide ); 86 : : 87 : : /** 88 : : * Returns the filename expression used for generating output filenames for each 89 : : * atlas page. 90 : : * \see setFilenameExpression() 91 : : * \see currentFilename() 92 : : */ 93 : : QString filenameExpression() const { return mFilenameExpressionString; } 94 : : 95 : : /** 96 : : * Sets the filename \a expression used for generating output filenames for each 97 : : * atlas page. 98 : : * If an invalid expression is passed, FALSE will be returned and \a errorString 99 : : * will be set to the expression error. 100 : : * \see filenameExpression() 101 : : * \see currentFilename() 102 : : */ 103 : : bool setFilenameExpression( const QString &expression, QString &errorString SIP_OUT ); 104 : : 105 : : /** 106 : : * Returns the current feature filename. 107 : : * \see filenameExpression() 108 : : * \see setFilenameExpression() 109 : : */ 110 : : QString currentFilename() const; 111 : : 112 : : /** 113 : : * Returns the coverage layer used for the atlas features. 114 : : * \see setCoverageLayer() 115 : : */ 116 : 0 : QgsVectorLayer *coverageLayer() const { return mCoverageLayer.get(); } 117 : : 118 : : /** 119 : : * Sets the coverage \a layer to use for the atlas features. 120 : : * \see coverageLayer() 121 : : */ 122 : : void setCoverageLayer( QgsVectorLayer *layer ); 123 : : 124 : : /** 125 : : * Returns the expression (or field name) used for calculating the page name. 126 : : * \see setPageNameExpression() 127 : : * \see nameForPage() 128 : : */ 129 : : QString pageNameExpression() const { return mPageNameExpression; } 130 : : 131 : : /** 132 : : * Sets the \a expression (or field name) used for calculating the page name. 133 : : * \see pageNameExpression() 134 : : */ 135 : : void setPageNameExpression( const QString &expression ); 136 : : 137 : : /** 138 : : * Returns the calculated name for a specified atlas \a page number. Page numbers start at 0. 139 : : * \see pageNameExpression() 140 : : */ 141 : : QString nameForPage( int page ) const; 142 : : 143 : : /** 144 : : * Returns TRUE if features should be sorted in the atlas. 145 : : * \see setSortFeatures() 146 : : * \see sortAscending() 147 : : * \see sortExpression() 148 : : */ 149 : 0 : bool sortFeatures() const { return mSortFeatures; } 150 : : 151 : : /** 152 : : * Sets whether features should be sorted in the atlas. 153 : : * \see sortFeatures() 154 : : * \see setSortAscending() 155 : : * \see setSortExpression() 156 : : */ 157 : : void setSortFeatures( bool enabled ); 158 : : 159 : : /** 160 : : * Returns TRUE if features should be sorted in an ascending order. 161 : : * 162 : : * This property has no effect is sortFeatures() is FALSE. 163 : : * 164 : : * \see sortFeatures() 165 : : * \see setSortAscending() 166 : : * \see sortExpression() 167 : : */ 168 : : bool sortAscending() const { return mSortAscending; } 169 : : 170 : : /** 171 : : * Sets whether features should be sorted in an ascending order. 172 : : * 173 : : * This property has no effect is sortFeatures() is FALSE. 174 : : * 175 : : * \see setSortFeatures() 176 : : * \see sortAscending() 177 : : * \see setSortExpression() 178 : : */ 179 : : void setSortAscending( bool ascending ); 180 : : 181 : : /** 182 : : * Returns the expression (or field name) to use for sorting features. 183 : : * 184 : : * This property has no effect is sortFeatures() is FALSE. 185 : : * 186 : : * \see sortFeatures() 187 : : * \see sortAscending() 188 : : * \see setSortExpression() 189 : : */ 190 : : QString sortExpression() const { return mSortExpression; } 191 : : 192 : : /** 193 : : * Sets the \a expression (or field name) to use for sorting features. 194 : : * 195 : : * This property has no effect is sortFeatures() is FALSE. 196 : : * 197 : : * \see setSortFeatures() 198 : : * \see setSortAscending() 199 : : * \see sortExpression() 200 : : */ 201 : : void setSortExpression( const QString &expression ); 202 : : 203 : : /** 204 : : * Returns TRUE if features should be filtered in the coverage layer. 205 : : * \see filterExpression() 206 : : * \see setFilterExpression() 207 : : */ 208 : 0 : bool filterFeatures() const { return mFilterFeatures; } 209 : : 210 : : /** 211 : : * Sets whether features should be \a filtered in the coverage layer. 212 : : * \see filterFeatures() 213 : : * \see setFilterExpression() 214 : : */ 215 : : void setFilterFeatures( bool filtered ); 216 : : 217 : : /** 218 : : * Returns the expression used for filtering features in the coverage layer. 219 : : * 220 : : * This property has no effect is filterFeatures() is FALSE. 221 : : * 222 : : * \see setFilterExpression() 223 : : * \see filterFeatures() 224 : : */ 225 : : QString filterExpression() const { return mFilterExpression; } 226 : : 227 : : /** 228 : : * Sets the \a expression used for filtering features in the coverage layer. 229 : : * 230 : : * This property has no effect is filterFeatures() is FALSE. 231 : : * 232 : : * If an invalid expression is passed, FALSE will be returned and \a errorString 233 : : * will be set to the expression error. 234 : : * 235 : : * \see filterExpression() 236 : : * \see setFilterFeatures() 237 : : */ 238 : : bool setFilterExpression( const QString &expression, QString &errorString SIP_OUT ); 239 : : 240 : : /** 241 : : * Requeries the current atlas coverage layer and applies filtering and sorting. Returns 242 : : * number of matching features. 243 : : */ 244 : : int updateFeatures(); 245 : : 246 : : bool beginRender() override; 247 : : bool endRender() override; 248 : : int count() const override; 249 : : QString filePath( const QString &baseFilePath, const QString &extension ) override; 250 : : 251 : : /** 252 : : * Returns the current feature number, where a value of 0 corresponds to the first feature. 253 : : */ 254 : 0 : int currentFeatureNumber() const { return mCurrentFeatureNo; } 255 : : 256 : : QgsExpressionContext createExpressionContext() const override; 257 : : 258 : : public slots: 259 : : 260 : : bool next() override; 261 : : 262 : : /** 263 : : * Iterates to the previous feature, returning FALSE if no previous feature exists. 264 : : * \see next() 265 : : * \see last() 266 : : * \see first() 267 : : * \see seekTo() 268 : : */ 269 : : bool previous(); 270 : : 271 : : /** 272 : : * Seeks to the last feature, returning FALSE if no feature was found. 273 : : * \see next() 274 : : * \see previous() 275 : : * \see first() 276 : : * \see seekTo() 277 : : */ 278 : : bool last(); 279 : : 280 : : /** 281 : : * Seeks to the first feature, returning FALSE if no feature was found. 282 : : * \see next() 283 : : * \see previous() 284 : : * \see last() 285 : : * \see seekTo() 286 : : */ 287 : : bool first(); 288 : : 289 : : /** 290 : : * Seeks to the specified \a feature number. 291 : : * \see first() 292 : : * \see previous() 293 : : * \see next() 294 : : * \see last() 295 : : */ 296 : : bool seekTo( int feature ); 297 : : 298 : : /** 299 : : * Seeks to the specified \a feature. 300 : : * \see first() 301 : : * \see previous() 302 : : * \see next() 303 : : * \see last() 304 : : */ 305 : : bool seekTo( const QgsFeature &feature ); 306 : : 307 : : /** 308 : : * Refreshes the current atlas feature, by refetching its attributes from the vector layer provider 309 : : */ 310 : : void refreshCurrentFeature(); 311 : : 312 : : signals: 313 : : 314 : : //! Emitted when one of the atlas parameters changes. 315 : : void changed(); 316 : : 317 : : //! Emitted when atlas is enabled or disabled. 318 : : void toggled( bool ); 319 : : 320 : : //! Emitted when the coverage layer for the atlas changes. 321 : : void coverageLayerChanged( QgsVectorLayer *layer ); 322 : : 323 : : //! Emitted when the atlas has an updated status bar \a message. 324 : : void messagePushed( const QString &message ); 325 : : 326 : : /** 327 : : * Emitted when the number of features for the atlas changes. 328 : : */ 329 : : void numberFeaturesChanged( int numFeatures ); 330 : : 331 : : //! Emitted when the current atlas \a feature changes. 332 : : void featureChanged( const QgsFeature &feature ); 333 : : 334 : : //! Emitted when atlas rendering has begun. 335 : : void renderBegun(); 336 : : 337 : : //! Emitted when atlas rendering has ended. 338 : : void renderEnded(); 339 : : 340 : : private slots: 341 : : void removeLayers( const QStringList &layers ); 342 : : 343 : : private: 344 : : 345 : : /** 346 : : * Updates the filename expression. 347 : : * \returns TRUE if expression was successfully parsed, FALSE if expression is invalid 348 : : */ 349 : : bool updateFilenameExpression( QString &error ); 350 : : 351 : : /** 352 : : * Evaluates filename for current feature 353 : : * \returns TRUE if feature filename was successfully evaluated 354 : : */ 355 : : bool evalFeatureFilename( const QgsExpressionContext &context ); 356 : : 357 : : /** 358 : : * Prepare the atlas for the given feature. Sets the extent and context variables 359 : : * \param i feature number 360 : : * \returns TRUE if feature was successfully prepared 361 : : */ 362 : : bool prepareForFeature( int i ); 363 : : 364 : : QPointer< QgsLayout > mLayout; 365 : : 366 : : bool mEnabled = false; 367 : : bool mHideCoverage = false; 368 : : QString mFilenameExpressionString; 369 : : QString mFilenameExpressionError; 370 : : 371 : : QgsVectorLayerRef mCoverageLayer; 372 : : 373 : : QString mCurrentFilename; 374 : : bool mSortFeatures = false; 375 : : bool mSortAscending = true; 376 : : 377 : : typedef QMap< QgsFeatureId, QVariant > SorterKeys; 378 : : // value of field that is used for ordering of features 379 : : SorterKeys mFeatureKeys; 380 : : 381 : : QString mSortExpression; 382 : : 383 : : QString mPageNameExpression; 384 : : 385 : : bool mFilterFeatures = false; 386 : : QString mFilterExpression; 387 : : 388 : : QString mFilterParserError; 389 : : 390 : : // id of each iterated feature (after filtering and sorting) paired with atlas page name 391 : : QVector< QPair<QgsFeatureId, QString> > mFeatureIds; 392 : : // current atlas feature number 393 : : int mCurrentFeatureNo = -1; 394 : : QgsFeature mCurrentFeature; 395 : : 396 : : 397 : : friend class AtlasFeatureSorter; 398 : : }; 399 : : 400 : : #endif //QGSLAYOUTATLAS_H 401 : : 402 : : 403 : :