Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgslayoutitemlegend.h 3 : : --------------------- 4 : : begin : October 2017 5 : : copyright : (C) 2017 by Nyall Dawson 6 : : email : nyall dot dawson at gmail dot com 7 : : ***************************************************************************/ 8 : : 9 : : /*************************************************************************** 10 : : * * 11 : : * This program is free software; you can redistribute it and/or modify * 12 : : * it under the terms of the GNU General Public License as published by * 13 : : * the Free Software Foundation; either version 2 of the License, or * 14 : : * (at your option) any later version. * 15 : : * * 16 : : ***************************************************************************/ 17 : : 18 : : #ifndef QGSLAYOUTITEMLEGEND_H 19 : : #define QGSLAYOUTITEMLEGEND_H 20 : : 21 : : #include "qgis_core.h" 22 : : #include "qgis_sip.h" 23 : : #include "qgslayoutitem.h" 24 : : #include "qgslayertreemodel.h" 25 : : #include "qgslegendsettings.h" 26 : : #include "qgslayertreegroup.h" 27 : : #include "qgsexpressioncontext.h" 28 : : 29 : : class QgsLayerTreeModel; 30 : : class QgsSymbol; 31 : : class QgsLayoutItemMap; 32 : : class QgsLegendRenderer; 33 : : class QgsLayoutItemLegend; 34 : : 35 : : /** 36 : : * \ingroup core 37 : : * \brief Item model implementation based on layer tree model for layout legend. 38 : : * 39 : : * Overrides some functionality of QgsLayerTreeModel to better fit the needs of layout legends. 40 : : * 41 : : * \since QGIS 2.6 42 : : */ 43 : : class CORE_EXPORT QgsLegendModel : public QgsLayerTreeModel 44 : : { 45 : : Q_OBJECT 46 : : 47 : : public: 48 : : //! Construct the model based on the given layer tree 49 : : QgsLegendModel( QgsLayerTree *rootNode, QObject *parent SIP_TRANSFERTHIS = nullptr, QgsLayoutItemLegend *layout = nullptr ); 50 : : 51 : : //! Alternative constructor. 52 : : QgsLegendModel( QgsLayerTree *rootNode, QgsLayoutItemLegend *layout ); 53 : : 54 : : QVariant data( const QModelIndex &index, int role ) const override; 55 : : 56 : : Qt::ItemFlags flags( const QModelIndex &index ) const override; 57 : : 58 : : /** 59 : : * Returns filtered list of active legend nodes attached to a particular layer node 60 : : * (by default it returns also legend node embedded in parent layer node (if any) unless skipNodeEmbeddedInParent is TRUE) 61 : : * \note Parameter skipNodeEmbeddedInParent added in QGIS 2.18 62 : : * \note Not available in Python bindings 63 : : * \see layerOriginalLegendNodes() 64 : : * \since QGIS 3.10 65 : : */ 66 : : QList<QgsLayerTreeModelLegendNode *> layerLegendNodes( QgsLayerTreeLayer *nodeLayer, bool skipNodeEmbeddedInParent = false ) const SIP_SKIP; 67 : : 68 : : /** 69 : : * Clears any previously cached data for the specified \a node. 70 : : * \since QGIS 3.14 71 : : */ 72 : : void clearCachedData( QgsLayerTreeNode *node ) const; 73 : : 74 : : signals: 75 : : 76 : : /** 77 : : * Emitted to refresh the legend. 78 : : * \since QGIS 3.10 79 : : */ 80 : : void refreshLegend(); 81 : : 82 : : private slots: 83 : : 84 : : /** 85 : : * Handle incoming signal to refresh the legend. 86 : : * \since QGIS 3.10 87 : : */ 88 : : void forceRefresh(); 89 : : 90 : : private: 91 : : 92 : : /** 93 : : * Pointer to the QgsLayoutItemLegend class that made the model. 94 : : * \since QGIS 3.10 95 : : */ 96 : : QgsLayoutItemLegend *mLayoutLegend = nullptr; 97 : : 98 : : /** 99 : : * Evaluate the expression or symbol expressions of a given layer node. 100 : : * \since QGIS 3.14 101 : : */ 102 : : QString evaluateLayerExpressions( QgsLayerTreeLayer *nodeLayer ) const; 103 : : 104 : : }; 105 : : 106 : : 107 : : 108 : : /** 109 : : * \ingroup core 110 : : * \brief A layout item subclass for map legends. 111 : : * \since QGIS 3.0 112 : : */ 113 : : class CORE_EXPORT QgsLayoutItemLegend : public QgsLayoutItem 114 : : { 115 : 0 : Q_OBJECT 116 : : 117 : : public: 118 : : 119 : : /** 120 : : * Constructor for QgsLayoutItemLegend, with the specified parent \a layout. 121 : : */ 122 : : QgsLayoutItemLegend( QgsLayout *layout ); 123 : : 124 : : /** 125 : : * Returns a new legend item for the specified \a layout. 126 : : * 127 : : * The caller takes responsibility for deleting the returned object. 128 : : */ 129 : : static QgsLayoutItemLegend *create( QgsLayout *layout ) SIP_FACTORY; 130 : : 131 : : int type() const override; 132 : : QIcon icon() const override; 133 : : QgsLayoutItem::Flags itemFlags() const override; 134 : : //Overridden to show legend title 135 : : QString displayName() const override; 136 : : 137 : : /** 138 : : * Sets the legend's item bounds to fit the whole legend content. 139 : : */ 140 : : void adjustBoxSize(); 141 : : 142 : : /** 143 : : * Sets whether the legend should automatically resize to fit its contents. 144 : : * \param enabled set to FALSE to disable automatic resizing. The legend frame will not 145 : : * be expanded to fit legend items, and items may be cropped from display. 146 : : * \see resizeToContents() 147 : : */ 148 : : void setResizeToContents( bool enabled ); 149 : : 150 : : /** 151 : : * Returns whether the legend should automatically resize to fit its contents. 152 : : * \see setResizeToContents() 153 : : */ 154 : : bool resizeToContents() const; 155 : : 156 : : /** 157 : : * Returns the legend model. 158 : : */ 159 : : QgsLegendModel *model() { return mLegendModel.get(); } 160 : : 161 : : /** 162 : : * Sets whether the legend content should auto update to reflect changes in the project's 163 : : * layer tree. 164 : : * \see autoUpdateModel() 165 : : */ 166 : : void setAutoUpdateModel( bool autoUpdate ); 167 : : 168 : : /** 169 : : * Returns whether the legend content should auto update to reflect changes in the project's 170 : : * layer tree. 171 : : * \see setAutoUpdateModel() 172 : : */ 173 : : bool autoUpdateModel() const; 174 : : 175 : : /** 176 : : * Set whether legend items should be filtered to show just the ones visible in the associated map. 177 : : * \see legendFilterByMapEnabled() 178 : : */ 179 : : void setLegendFilterByMapEnabled( bool enabled ); 180 : : 181 : : /** 182 : : * Find out whether legend items are filtered to show just the ones visible in the associated map 183 : : * \see setLegendFilterByMapEnabled() 184 : : */ 185 : 0 : bool legendFilterByMapEnabled() const { return mLegendFilterByMap; } 186 : : 187 : : /** 188 : : * When set to TRUE, during an atlas rendering, it will filter out legend elements 189 : : * where features are outside the current atlas feature. 190 : : * \see legendFilterOutAtlas() 191 : : */ 192 : : void setLegendFilterOutAtlas( bool doFilter ); 193 : : 194 : : /** 195 : : * Returns whether to filter out legend elements outside of the current atlas feature. 196 : : * \see setLegendFilterOutAtlas() 197 : : */ 198 : : bool legendFilterOutAtlas() const; 199 : : 200 : : /** 201 : : * Sets the legend \a title. 202 : : * \see title() 203 : : */ 204 : : void setTitle( const QString &title ); 205 : : 206 : : /** 207 : : * Returns the legend title. 208 : : * \see setTitle() 209 : : */ 210 : : QString title() const; 211 : : 212 : : /** 213 : : * Returns the alignment of the legend title. 214 : : * \see setTitleAlignment() 215 : : */ 216 : : Qt::AlignmentFlag titleAlignment() const; 217 : : 218 : : /** 219 : : * Sets the \a alignment of the legend title. 220 : : * \see titleAlignment() 221 : : */ 222 : : void setTitleAlignment( Qt::AlignmentFlag alignment ); 223 : : 224 : : /** 225 : : * Returns reference to modifiable legend style. 226 : : */ 227 : : QgsLegendStyle &rstyle( QgsLegendStyle::Style s ); 228 : : 229 : : /** 230 : : * Returns legend style. 231 : : */ 232 : : QgsLegendStyle style( QgsLegendStyle::Style s ) const; 233 : : 234 : : /** 235 : : * Sets the style of \a component to \a style for the legend. 236 : : */ 237 : : void setStyle( QgsLegendStyle::Style component, const QgsLegendStyle &style ); 238 : : 239 : : /** 240 : : * Returns the font settings for a legend \a component. 241 : : * \see setStyleFont() 242 : : */ 243 : : QFont styleFont( QgsLegendStyle::Style component ) const; 244 : : 245 : : /** 246 : : * Sets the style \a font for a legend \a component. 247 : : * \see styleFont() 248 : : */ 249 : : void setStyleFont( QgsLegendStyle::Style component, const QFont &font ); 250 : : 251 : : /** 252 : : * Set the \a margin for a legend \a component. 253 : : */ 254 : : void setStyleMargin( QgsLegendStyle::Style component, double margin ); 255 : : 256 : : /** 257 : : * Set the \a margin for a particular \a side of a legend \a component. 258 : : */ 259 : : void setStyleMargin( QgsLegendStyle::Style component, QgsLegendStyle::Side side, double margin ); 260 : : 261 : : /** 262 : : * Returns the spacing in-between lines in layout units. 263 : : * \see setLineSpacing() 264 : : */ 265 : : double lineSpacing() const; 266 : : 267 : : /** 268 : : * Sets the \a spacing in-between multiple lines. 269 : : * \see lineSpacing() 270 : : */ 271 : : void setLineSpacing( double spacing ); 272 : : 273 : : /** 274 : : * Returns the legend box space. 275 : : * \see setBoxSpace() 276 : : */ 277 : : double boxSpace() const; 278 : : 279 : : /** 280 : : * Sets the legend box \a space. 281 : : * \see boxSpace() 282 : : */ 283 : : void setBoxSpace( double space ); 284 : : 285 : : /** 286 : : * Returns the legend column spacing. 287 : : * \see setColumnSpace() 288 : : */ 289 : : double columnSpace() const; 290 : : 291 : : /** 292 : : * Sets the legend column \a spacing. 293 : : * \see columnSpace() 294 : : */ 295 : : void setColumnSpace( double spacing ); 296 : : 297 : : /** 298 : : * Returns the legend font color. 299 : : * \see setFontColor() 300 : : */ 301 : : QColor fontColor() const; 302 : : 303 : : /** 304 : : * Sets the legend font \a color. 305 : : * \see fontColor() 306 : : */ 307 : : void setFontColor( const QColor &color ); 308 : : 309 : : /** 310 : : * Returns the legend symbol width. 311 : : * \see setSymbolWidth() 312 : : */ 313 : : double symbolWidth() const; 314 : : 315 : : /** 316 : : * Sets the legend symbol \a width. 317 : : * \see symbolWidth() 318 : : */ 319 : : void setSymbolWidth( double width ); 320 : : 321 : : /** 322 : : * Returns the maximum symbol size (in mm). 0.0 means there is no maximum set. 323 : : * 324 : : * \see setMaximumSymbolSize() 325 : : * \since QGIS 3.16 326 : : */ 327 : : double maximumSymbolSize() const; 328 : : 329 : : /** 330 : : * Set the maximum symbol \a size for symbol (in millimeters). 331 : : * 332 : : * A symbol size of 0.0 indicates no maximum is set. 333 : : * 334 : : * \see maximumSymbolSize() 335 : : * \since QGIS 3.16 336 : : */ 337 : : void setMaximumSymbolSize( double size ); 338 : : 339 : : /** 340 : : * Returns the minimum symbol size (in mm). A value 0.0 means there is no minimum set. 341 : : * 342 : : * \see setMinimumSymbolSize 343 : : * \since QGIS 3.16 344 : : */ 345 : : double minimumSymbolSize() const; 346 : : 347 : : /** 348 : : * Set the minimum symbol \a size for symbol (in millimeters). 349 : : * 350 : : * A symbol size of 0.0 indicates no minimum is set. 351 : : * 352 : : * \see minimumSymbolSize() 353 : : * \since QGIS 3.16 354 : : */ 355 : : void setMinimumSymbolSize( double size ); 356 : : 357 : : /** 358 : : * Sets the \a alignment for placement of legend symbols. 359 : : * 360 : : * Only Qt::AlignLeft or Qt::AlignRight are supported values. 361 : : * 362 : : * \see symbolAlignment() 363 : : * \since QGIS 3.10 364 : : */ 365 : : void setSymbolAlignment( Qt::AlignmentFlag alignment ); 366 : : 367 : : /** 368 : : * Returns the alignment for placement of legend symbols. 369 : : * 370 : : * Only Qt::AlignLeft or Qt::AlignRight are supported values. 371 : : * 372 : : * \see setSymbolAlignment() 373 : : * \since QGIS 3.10 374 : : */ 375 : : Qt::AlignmentFlag symbolAlignment() const; 376 : : 377 : : /** 378 : : * Returns the legend symbol height. 379 : : * \see setSymbolHeight() 380 : : */ 381 : : double symbolHeight() const; 382 : : 383 : : /** 384 : : * Sets the legend symbol \a height. 385 : : * \see symbolHeight() 386 : : */ 387 : : void setSymbolHeight( double height ); 388 : : 389 : : /** 390 : : * Returns the WMS legend width. 391 : : * \see setWmsLegendWidth() 392 : : */ 393 : : double wmsLegendWidth() const; 394 : : 395 : : /** 396 : : * Sets the WMS legend \a width. 397 : : * \see wmsLegendWidth() 398 : : */ 399 : : void setWmsLegendWidth( double width ); 400 : : 401 : : /** 402 : : * Returns the WMS legend height. 403 : : * \see setWmsLegendHeight() 404 : : */ 405 : : double wmsLegendHeight() const; 406 : : 407 : : /** 408 : : * Sets the WMS legend \a height. 409 : : * \see wmsLegendHeight() 410 : : */ 411 : : void setWmsLegendHeight( double height ); 412 : : 413 : : /** 414 : : * Sets the legend text wrapping \a string. 415 : : * \see wrapString() 416 : : */ 417 : : void setWrapString( const QString &string ); 418 : : 419 : : /** 420 : : * Returns the legend text wrapping string. 421 : : * \see setWrapString() 422 : : */ 423 : : QString wrapString() const; 424 : : 425 : : /** 426 : : * Returns the legend column count. 427 : : * \see setColumnCount() 428 : : */ 429 : : int columnCount() const; 430 : : 431 : : /** 432 : : * Sets the legend column \a count. 433 : : * \see columnCount() 434 : : */ 435 : : void setColumnCount( int count ); 436 : : 437 : : /** 438 : : * Returns whether the legend items from a single layer can be split 439 : : * over multiple columns. 440 : : * \see setSplitLayer() 441 : : */ 442 : : bool splitLayer() const; 443 : : 444 : : /** 445 : : * Sets whether the legend items from a single layer can be split 446 : : * over multiple columns. 447 : : * \see splitLayer() 448 : : */ 449 : : void setSplitLayer( bool enabled ); 450 : : 451 : : /** 452 : : * Returns whether column widths should be equalized. 453 : : * \see setEqualColumnWidth() 454 : : */ 455 : : bool equalColumnWidth() const; 456 : : 457 : : /** 458 : : * Sets whether column widths should be equalized. 459 : : * \see equalColumnWidth() 460 : : */ 461 : : void setEqualColumnWidth( bool equalize ); 462 : : 463 : : /** 464 : : * Returns whether a stroke will be drawn around raster symbol items. 465 : : * \see setDrawRasterStroke() 466 : : * \see rasterStrokeColor() 467 : : * \see rasterStrokeWidth() 468 : : */ 469 : : bool drawRasterStroke() const; 470 : : 471 : : /** 472 : : * Sets whether a stroke will be drawn around raster symbol items. 473 : : * \param enabled set to TRUE to draw borders 474 : : * \see drawRasterStroke() 475 : : * \see setRasterStrokeColor() 476 : : * \see setRasterStrokeWidth() 477 : : */ 478 : : void setDrawRasterStroke( bool enabled ); 479 : : 480 : : /** 481 : : * Returns the stroke color for the stroke drawn around raster symbol items. The stroke is 482 : : * only drawn if drawRasterStroke() is TRUE. 483 : : * \see setRasterStrokeColor() 484 : : * \see drawRasterStroke() 485 : : * \see rasterStrokeWidth() 486 : : */ 487 : : QColor rasterStrokeColor() const; 488 : : 489 : : /** 490 : : * Sets the stroke \a color for the stroke drawn around raster symbol items. The stroke is 491 : : * only drawn if drawRasterStroke() is TRUE. 492 : : * \see rasterStrokeColor() 493 : : * \see setDrawRasterStroke() 494 : : * \see setRasterStrokeWidth() 495 : : */ 496 : : void setRasterStrokeColor( const QColor &color ); 497 : : 498 : : /** 499 : : * Returns the stroke width (in layout units) for the stroke drawn around raster symbol items. The stroke is 500 : : * only drawn if drawRasterStroke() is TRUE. 501 : : * \see setRasterStrokeWidth() 502 : : * \see drawRasterStroke() 503 : : * \see rasterStrokeColor() 504 : : */ 505 : : double rasterStrokeWidth() const; 506 : : 507 : : /** 508 : : * Sets the stroke width for the stroke drawn around raster symbol items. The stroke is 509 : : * only drawn if drawRasterStroke() is TRUE. 510 : : * \see rasterStrokeWidth() 511 : : * \see setDrawRasterStroke() 512 : : * \see setRasterStrokeColor() 513 : : */ 514 : : void setRasterStrokeWidth( double width ); 515 : : 516 : : /** 517 : : * Sets the \a map to associate with the legend. 518 : : * \see linkedMap() 519 : : */ 520 : : void setLinkedMap( QgsLayoutItemMap *map ); 521 : : 522 : : /** 523 : : * Returns the associated map. 524 : : * \see setLinkedMap() 525 : : */ 526 : : QgsLayoutItemMap *linkedMap() const { return mMap; } 527 : : 528 : : /** 529 : : * Returns the name of the theme currently linked to the legend. 530 : : * 531 : : * This usually equates to the theme rendered in the linkedMap(). 532 : : * 533 : : * \since QGIS 3.14 534 : : */ 535 : : QString themeName() const; 536 : : 537 : : /** 538 : : * Updates the model and all legend entries. 539 : : */ 540 : : void updateLegend(); 541 : : 542 : : /** 543 : : * Updates the legend content when filtered by map. 544 : : */ 545 : : void updateFilterByMap( bool redraw = true ); 546 : : 547 : : /** 548 : : * Returns the legend's renderer settings object. 549 : : */ 550 : : const QgsLegendSettings &legendSettings() const { return mSettings; } 551 : : 552 : : void paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget ) override; 553 : : 554 : : void finalizeRestoreFromXml() override; 555 : : 556 : : QgsExpressionContext createExpressionContext() const override; 557 : : ExportLayerBehavior exportLayerBehavior() const override; 558 : : bool accept( QgsStyleEntityVisitorInterface *visitor ) const override; 559 : : 560 : : public slots: 561 : : 562 : : void refresh() override; 563 : : void refreshDataDefinedProperty( QgsLayoutObject::DataDefinedProperty property = QgsLayoutObject::AllProperties ) override; 564 : : 565 : : protected: 566 : : void draw( QgsLayoutItemRenderContext &context ) override; 567 : : bool writePropertiesToElement( QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context ) const override; 568 : : bool readPropertiesFromElement( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context ) override; 569 : : 570 : : private slots: 571 : : 572 : : //! Removes the associated map if the map is deleted. 573 : : void invalidateCurrentMap(); 574 : : 575 : : void updateFilterByMapAndRedraw(); 576 : : 577 : : 578 : : //! update legend in case style of associated map has changed 579 : : void mapLayerStyleOverridesChanged(); 580 : : //! update legend in case theme of associated map has changed 581 : : void mapThemeChanged( const QString &theme ); 582 : : 583 : : //! react to atlas 584 : : void onAtlasEnded(); 585 : : void onAtlasFeature(); 586 : : 587 : : void nodeCustomPropertyChanged( QgsLayerTreeNode *node, const QString &key ); 588 : : 589 : : //! Clears any data cached for the legend model 590 : : void clearLegendCachedData(); 591 : : 592 : : private: 593 : : QgsLayoutItemLegend() = delete; 594 : : 595 : : //! use new custom layer tree and update model. if new root is NULLPTR, will use project's tree 596 : : void setCustomLayerTree( QgsLayerTree *rootGroup ); 597 : : 598 : : void setupMapConnections( QgsLayoutItemMap *map, bool connect = true ); 599 : : 600 : : void setModelStyleOverrides( const QMap<QString, QString> &overrides ); 601 : : 602 : : std::unique_ptr< QgsLegendModel > mLegendModel; 603 : : std::unique_ptr< QgsLayerTreeGroup > mCustomLayerTree; 604 : : 605 : : QgsLegendSettings mSettings; 606 : : 607 : : QString mTitle; 608 : : int mColumnCount = 1; 609 : : 610 : : QString mMapUuid; 611 : : QgsLayoutItemMap *mMap = nullptr; 612 : : 613 : : bool mLegendFilterByMap = false; 614 : : bool mLegendFilterByExpression = false; 615 : : 616 : : //! whether to filter out legend elements outside of the atlas feature 617 : : bool mFilterOutAtlas = false; 618 : : 619 : : //! tag for update request 620 : : bool mFilterAskedForUpdate = false; 621 : : //! actual filter update 622 : : void doUpdateFilterByMap(); 623 : : 624 : : bool mInAtlas = false; 625 : : 626 : : //! Will be FALSE until the associated map scale and DPI have been calculated 627 : : bool mInitialMapScaleCalculated = false; 628 : : 629 : : //! Will be TRUE if the legend size should be totally reset at next paint 630 : : bool mForceResize = false; 631 : : 632 : : //! Will be TRUE if the legend should be resized automatically to fit contents 633 : : bool mSizeToContents = true; 634 : : 635 : : //! Name of theme for legend -- usually the theme associated with the linked map. 636 : : QString mThemeName; 637 : : 638 : : friend class QgsCompositionConverter; 639 : : 640 : : }; 641 : : 642 : : #endif // QGSLAYOUTITEMLEGEND_H 643 : :