QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgslayout.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayout.cpp
3  -------------------
4  begin : June 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 
17 #include "qgslayout.h"
18 #include "qgslayoutitem.h"
19 #include "qgslayoutmodel.h"
22 #include "qgsreadwritecontext.h"
23 #include "qgsproject.h"
25 #include "qgslayoutitemgroup.h"
27 #include "qgslayoutmultiframe.h"
28 #include "qgslayoutitemmap.h"
29 #include "qgslayoutundostack.h"
31 #include "qgsvectorlayer.h"
33 #include "qgsstyleentityvisitor.h"
34 #include "qgsruntimeprofiler.h"
35 
37  : mProject( project )
38  , mRenderContext( new QgsLayoutRenderContext( this ) )
39  , mReportContext( new QgsLayoutReportContext( this ) )
40  , mSnapper( QgsLayoutSnapper( this ) )
41  , mGridSettings( this )
42  , mPageCollection( new QgsLayoutPageCollection( this ) )
43  , mUndoStack( new QgsLayoutUndoStack( this ) )
44 {
45  // just to make sure - this should be the default, but maybe it'll change in some future Qt version...
46  setBackgroundBrush( Qt::NoBrush );
47  mItemsModel.reset( new QgsLayoutModel( this ) );
48 }
49 
51 {
52  // no need for undo commands when we're destroying the layout
53  mUndoStack->blockCommands( true );
54 
55  deleteAndRemoveMultiFrames();
56 
57  // make sure that all layout items are removed before
58  // this class is deconstructed - to avoid segfaults
59  // when layout items access in destructor layout that isn't valid anymore
60 
61  // since deletion of some item types (e.g. groups) trigger deletion
62  // of other items, we have to do this careful, one at a time...
63  QList<QGraphicsItem *> itemList = items();
64  bool deleted = true;
65  while ( deleted )
66  {
67  deleted = false;
68  for ( QGraphicsItem *item : std::as_const( itemList ) )
69  {
70  if ( dynamic_cast< QgsLayoutItem * >( item ) && !dynamic_cast< QgsLayoutItemPage *>( item ) )
71  {
72  delete item;
73  deleted = true;
74  break;
75  }
76  }
77  itemList = items();
78  }
79 
80  mItemsModel.reset(); // manually delete, so we can control order of destruction
81 }
82 
84 {
85  QDomDocument currentDoc;
86 
87  QgsReadWriteContext context;
88  QDomElement elem = writeXml( currentDoc, context );
89  currentDoc.appendChild( elem );
90 
91  std::unique_ptr< QgsLayout > newLayout = std::make_unique< QgsLayout >( mProject );
92  bool ok = false;
93  newLayout->loadFromTemplate( currentDoc, context, true, &ok );
94  if ( !ok )
95  {
96  return nullptr;
97  }
98 
99  return newLayout.release();
100 }
101 
103 {
104  // default to a A4 landscape page
105  QgsLayoutItemPage *page = new QgsLayoutItemPage( this );
107  mPageCollection->addPage( page );
108  mUndoStack->stack()->clear();
109 }
110 
112 {
113  deleteAndRemoveMultiFrames();
114 
115  //delete all non paper items
116  const QList<QGraphicsItem *> itemList = items();
117  for ( QGraphicsItem *item : itemList )
118  {
119  QgsLayoutItem *cItem = dynamic_cast<QgsLayoutItem *>( item );
120  QgsLayoutItemPage *pItem = dynamic_cast<QgsLayoutItemPage *>( item );
121  if ( cItem && !pItem )
122  {
123  removeLayoutItemPrivate( cItem );
124  }
125  }
126  mItemsModel->clear();
127 
128  mPageCollection->clear();
129  mUndoStack->stack()->clear();
130 }
131 
133 {
134  return mProject;
135 }
136 
138 {
139  return mItemsModel.get();
140 }
141 
142 QList<QgsLayoutItem *> QgsLayout::selectedLayoutItems( const bool includeLockedItems )
143 {
144  QList<QgsLayoutItem *> layoutItemList;
145 
146  const QList<QGraphicsItem *> graphicsItemList = selectedItems();
147  for ( QGraphicsItem *item : graphicsItemList )
148  {
149  QgsLayoutItem *layoutItem = dynamic_cast<QgsLayoutItem *>( item );
150  if ( layoutItem && ( includeLockedItems || !layoutItem->isLocked() ) )
151  {
152  layoutItemList.push_back( layoutItem );
153  }
154  }
155 
156  return layoutItemList;
157 }
158 
160 {
161  whileBlocking( this )->deselectAll();
162  if ( item )
163  {
164  item->setSelected( true );
165  }
166  emit selectedItemChanged( item );
167 }
168 
170 {
171  //we can't use QGraphicsScene::clearSelection, as that emits no signals
172  //and we don't know which items are being deselected
173  //accordingly, we can't inform the layout model of selection changes
174  //instead, do the clear selection manually...
175  const QList<QGraphicsItem *> selectedItemList = selectedItems();
176  for ( QGraphicsItem *item : selectedItemList )
177  {
178  if ( QgsLayoutItem *layoutItem = dynamic_cast<QgsLayoutItem *>( item ) )
179  {
180  layoutItem->setSelected( false );
181  }
182  }
183  emit selectedItemChanged( nullptr );
184 }
185 
186 bool QgsLayout::raiseItem( QgsLayoutItem *item, bool deferUpdate )
187 {
188  //model handles reordering items
189  bool result = mItemsModel->reorderItemUp( item );
190  if ( result && !deferUpdate )
191  {
192  //update all positions
193  updateZValues();
194  update();
195  }
196  return result;
197 }
198 
199 bool QgsLayout::lowerItem( QgsLayoutItem *item, bool deferUpdate )
200 {
201  //model handles reordering items
202  bool result = mItemsModel->reorderItemDown( item );
203  if ( result && !deferUpdate )
204  {
205  //update all positions
206  updateZValues();
207  update();
208  }
209  return result;
210 }
211 
212 bool QgsLayout::moveItemToTop( QgsLayoutItem *item, bool deferUpdate )
213 {
214  //model handles reordering items
215  bool result = mItemsModel->reorderItemToTop( item );
216  if ( result && !deferUpdate )
217  {
218  //update all positions
219  updateZValues();
220  update();
221  }
222  return result;
223 }
224 
225 bool QgsLayout::moveItemToBottom( QgsLayoutItem *item, bool deferUpdate )
226 {
227  //model handles reordering items
228  bool result = mItemsModel->reorderItemToBottom( item );
229  if ( result && !deferUpdate )
230  {
231  //update all positions
232  updateZValues();
233  update();
234  }
235  return result;
236 }
237 
238 QgsLayoutItem *QgsLayout::itemByUuid( const QString &uuid, bool includeTemplateUuids ) const
239 {
240  QList<QgsLayoutItem *> itemList;
241  layoutItems( itemList );
242  for ( QgsLayoutItem *item : std::as_const( itemList ) )
243  {
244  if ( item->uuid() == uuid )
245  return item;
246  else if ( includeTemplateUuids && item->mTemplateUuid == uuid )
247  return item;
248  }
249 
250  return nullptr;
251 }
252 
253 QgsLayoutItem *QgsLayout::itemByTemplateUuid( const QString &uuid ) const
254 {
255  QList<QgsLayoutItem *> itemList;
256  layoutItems( itemList );
257  for ( QgsLayoutItem *item : std::as_const( itemList ) )
258  {
259  if ( item->mTemplateUuid == uuid )
260  return item;
261  }
262 
263  return nullptr;
264 }
265 
266 QgsLayoutItem *QgsLayout::itemById( const QString &id ) const
267 {
268  const QList<QGraphicsItem *> itemList = items();
269  for ( QGraphicsItem *item : itemList )
270  {
271  QgsLayoutItem *layoutItem = dynamic_cast<QgsLayoutItem *>( item );
272  if ( layoutItem && layoutItem->id() == id )
273  {
274  return layoutItem;
275  }
276  }
277  return nullptr;
278 }
279 
280 QgsLayoutMultiFrame *QgsLayout::multiFrameByUuid( const QString &uuid, bool includeTemplateUuids ) const
281 {
282  for ( QgsLayoutMultiFrame *mf : mMultiFrames )
283  {
284  if ( mf->uuid() == uuid )
285  return mf;
286  else if ( includeTemplateUuids && mf->mTemplateUuid == uuid )
287  return mf;
288  }
289 
290  return nullptr;
291 }
292 
293 QgsLayoutItem *QgsLayout::layoutItemAt( QPointF position, const bool ignoreLocked ) const
294 {
295  return layoutItemAt( position, nullptr, ignoreLocked );
296 }
297 
298 QgsLayoutItem *QgsLayout::layoutItemAt( QPointF position, const QgsLayoutItem *belowItem, const bool ignoreLocked ) const
299 {
300  //get a list of items which intersect the specified position, in descending z order
301  const QList<QGraphicsItem *> itemList = items( position, Qt::IntersectsItemShape, Qt::DescendingOrder );
302 
303  bool foundBelowItem = false;
304  for ( QGraphicsItem *graphicsItem : itemList )
305  {
306  QgsLayoutItem *layoutItem = dynamic_cast<QgsLayoutItem *>( graphicsItem );
307  QgsLayoutItemPage *paperItem = dynamic_cast<QgsLayoutItemPage *>( layoutItem );
308  if ( layoutItem && !paperItem )
309  {
310  // If we are not checking for a an item below a specified item, or if we've
311  // already found that item, then we've found our target
312  if ( ( ! belowItem || foundBelowItem ) && ( !ignoreLocked || !layoutItem->isLocked() ) )
313  {
314  return layoutItem;
315  }
316  else
317  {
318  if ( layoutItem == belowItem )
319  {
320  //Target item is next in list
321  foundBelowItem = true;
322  }
323  }
324  }
325  }
326  return nullptr;
327 }
328 
330 {
331  return mRenderContext->measurementConverter().convert( measurement, mUnits ).length();
332 }
333 
335 {
336  return mRenderContext->measurementConverter().convert( size, mUnits ).toQSizeF();
337 }
338 
339 QPointF QgsLayout::convertToLayoutUnits( const QgsLayoutPoint &point ) const
340 {
341  return mRenderContext->measurementConverter().convert( point, mUnits ).toQPointF();
342 }
343 
345 {
346  return mRenderContext->measurementConverter().convert( QgsLayoutMeasurement( length, mUnits ), unit );
347 }
348 
350 {
351  return mRenderContext->measurementConverter().convert( QgsLayoutSize( size.width(), size.height(), mUnits ), unit );
352 }
353 
355 {
356  return mRenderContext->measurementConverter().convert( QgsLayoutPoint( point.x(), point.y(), mUnits ), unit );
357 }
358 
360 {
361  return *mRenderContext;
362 }
363 
365 {
366  return *mRenderContext;
367 }
368 
370 {
371  return *mReportContext;
372 }
373 
375 {
376  return *mReportContext;
377 }
378 
380 {
381  mGridSettings.loadFromSettings();
382  mPageCollection->redraw();
383 }
384 
386 {
387  return mPageCollection->guides();
388 }
389 
391 {
392  return mPageCollection->guides();
393 }
394 
396 {
400  if ( mReportContext->layer() )
401  context.appendScope( QgsExpressionContextUtils::layerScope( mReportContext->layer() ) );
402 
404  return context;
405 }
406 
407 void QgsLayout::setCustomProperty( const QString &key, const QVariant &value )
408 {
409  mCustomProperties.setValue( key, value );
410 
411  if ( key.startsWith( QLatin1String( "variable" ) ) )
412  emit variablesChanged();
413 }
414 
415 QVariant QgsLayout::customProperty( const QString &key, const QVariant &defaultValue ) const
416 {
417  return mCustomProperties.value( key, defaultValue );
418 }
419 
420 void QgsLayout::removeCustomProperty( const QString &key )
421 {
422  mCustomProperties.remove( key );
423 }
424 
425 QStringList QgsLayout::customProperties() const
426 {
427  return mCustomProperties.keys();
428 }
429 
431 {
432  // prefer explicitly set reference map
433  if ( QgsLayoutItemMap *map = qobject_cast< QgsLayoutItemMap * >( itemByUuid( mWorldFileMapId ) ) )
434  return map;
435 
436  // else try to find largest map
437  QList< QgsLayoutItemMap * > maps;
438  layoutItems( maps );
439  QgsLayoutItemMap *largestMap = nullptr;
440  double largestMapArea = 0;
441  for ( QgsLayoutItemMap *map : std::as_const( maps ) )
442  {
443  double area = map->rect().width() * map->rect().height();
444  if ( area > largestMapArea )
445  {
446  largestMapArea = area;
447  largestMap = map;
448  }
449  }
450  return largestMap;
451 }
452 
454 {
455  mWorldFileMapId = map ? map->uuid() : QString();
456  mProject->setDirty( true );
457 }
458 
460 {
461  return mPageCollection.get();
462 }
463 
465 {
466  return mPageCollection.get();
467 }
468 
469 QRectF QgsLayout::layoutBounds( bool ignorePages, double margin ) const
470 {
471  //start with an empty rectangle
472  QRectF bounds;
473 
474  //add all layout items and pages which are in the layout
475  const auto constItems = items();
476  for ( const QGraphicsItem *item : constItems )
477  {
478  const QgsLayoutItem *layoutItem = dynamic_cast<const QgsLayoutItem *>( item );
479  if ( !layoutItem )
480  continue;
481 
482  bool isPage = layoutItem->type() == QgsLayoutItemRegistry::LayoutPage;
483  if ( !isPage || !ignorePages )
484  {
485  //expand bounds with current item's bounds
486  QRectF itemBounds;
487  if ( isPage )
488  {
489  // for pages we only consider the item's rect - not the bounding rect
490  // as the bounding rect contains extra padding
491  itemBounds = layoutItem->mapToScene( layoutItem->rect() ).boundingRect();
492  }
493  else
494  itemBounds = item->sceneBoundingRect();
495 
496  if ( bounds.isValid() )
497  bounds = bounds.united( itemBounds );
498  else
499  bounds = itemBounds;
500  }
501  }
502 
503  if ( bounds.isValid() && margin > 0.0 )
504  {
505  //finally, expand bounds out by specified margin of page size
506  double maxWidth = mPageCollection->maximumPageWidth();
507  bounds.adjust( -maxWidth * margin, -maxWidth * margin, maxWidth * margin, maxWidth * margin );
508  }
509 
510  return bounds;
511 
512 }
513 
514 QRectF QgsLayout::pageItemBounds( int page, bool visibleOnly ) const
515 {
516  //start with an empty rectangle
517  QRectF bounds;
518 
519  //add all QgsLayoutItems on page
520  const QList<QGraphicsItem *> itemList = items();
521  for ( QGraphicsItem *item : itemList )
522  {
523  const QgsLayoutItem *layoutItem = dynamic_cast<const QgsLayoutItem *>( item );
524  if ( layoutItem && layoutItem->type() != QgsLayoutItemRegistry::LayoutPage && layoutItem->page() == page )
525  {
526  if ( visibleOnly && !layoutItem->isVisible() )
527  continue;
528 
529  //expand bounds with current item's bounds
530  if ( bounds.isValid() )
531  bounds = bounds.united( item->sceneBoundingRect() );
532  else
533  bounds = item->sceneBoundingRect();
534  }
535  }
536 
537  return bounds;
538 }
539 
541 {
542  addLayoutItemPrivate( item );
543  QString undoText;
544  if ( QgsLayoutItemAbstractMetadata *metadata = QgsApplication::layoutItemRegistry()->itemMetadata( item->type() ) )
545  {
546  undoText = tr( "Create %1" ).arg( metadata->visibleName() );
547  }
548  else
549  {
550  undoText = tr( "Create Item" );
551  }
552  if ( !mUndoStack->isBlocked() )
553  mUndoStack->push( new QgsLayoutItemAddItemCommand( item, undoText ) );
554 }
555 
557 {
558  std::unique_ptr< QgsLayoutItemDeleteUndoCommand > deleteCommand;
559  if ( !mUndoStack->isBlocked() )
560  {
561  mUndoStack->beginMacro( tr( "Delete Items" ) );
562  deleteCommand.reset( new QgsLayoutItemDeleteUndoCommand( item, tr( "Delete Item" ) ) );
563  }
564  removeLayoutItemPrivate( item );
565  if ( deleteCommand )
566  {
567  mUndoStack->push( deleteCommand.release() );
568  mUndoStack->endMacro();
569  }
570 }
571 
573 {
574  if ( !multiFrame )
575  return;
576 
577  if ( !mMultiFrames.contains( multiFrame ) )
578  mMultiFrames << multiFrame;
579 }
580 
582 {
583  mMultiFrames.removeAll( multiFrame );
584 }
585 
586 QList<QgsLayoutMultiFrame *> QgsLayout::multiFrames() const
587 {
588  return mMultiFrames;
589 }
590 
591 bool QgsLayout::saveAsTemplate( const QString &path, const QgsReadWriteContext &context ) const
592 {
593  QFile templateFile( path );
594  if ( !templateFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
595  {
596  return false;
597  }
598 
599  QDomDocument saveDocument;
600  QDomElement elem = writeXml( saveDocument, context );
601  saveDocument.appendChild( elem );
602 
603  if ( templateFile.write( saveDocument.toByteArray() ) == -1 )
604  return false;
605 
606  return true;
607 }
608 
609 QList< QgsLayoutItem * > QgsLayout::loadFromTemplate( const QDomDocument &document, const QgsReadWriteContext &context, bool clearExisting, bool *ok )
610 {
611  if ( ok )
612  *ok = false;
613 
614  QList< QgsLayoutItem * > result;
615 
616  if ( clearExisting )
617  {
618  clear();
619  }
620 
621  QDomDocument doc;
622 
623  // If this is a 2.x composition template, convert it to a layout template
625  {
626  doc = QgsCompositionConverter::convertCompositionTemplate( document, mProject );
627  }
628  else
629  {
630  doc = document;
631  }
632 
633  // remove all uuid attributes since we don't want duplicates UUIDS
634  QDomNodeList itemsNodes = doc.elementsByTagName( QStringLiteral( "LayoutItem" ) );
635  for ( int i = 0; i < itemsNodes.count(); ++i )
636  {
637  QDomNode itemNode = itemsNodes.at( i );
638  if ( itemNode.isElement() )
639  {
640  itemNode.toElement().removeAttribute( QStringLiteral( "uuid" ) );
641  }
642  }
643  QDomNodeList multiFrameNodes = doc.elementsByTagName( QStringLiteral( "LayoutMultiFrame" ) );
644  for ( int i = 0; i < multiFrameNodes.count(); ++i )
645  {
646  QDomNode multiFrameNode = multiFrameNodes.at( i );
647  if ( multiFrameNode.isElement() )
648  {
649  multiFrameNode.toElement().removeAttribute( QStringLiteral( "uuid" ) );
650  QDomNodeList frameNodes = multiFrameNode.toElement().elementsByTagName( QStringLiteral( "childFrame" ) );
651  QDomNode itemNode = frameNodes.at( i );
652  if ( itemNode.isElement() )
653  {
654  itemNode.toElement().removeAttribute( QStringLiteral( "uuid" ) );
655  }
656  }
657  }
658 
659  //read general settings
660  if ( clearExisting )
661  {
662  QDomElement layoutElem = doc.documentElement();
663  if ( layoutElem.isNull() )
664  {
665  return result;
666  }
667 
668  bool loadOk = readXml( layoutElem, doc, context );
669  if ( !loadOk )
670  {
671  return result;
672  }
673  layoutItems( result );
674  }
675  else
676  {
677  result = addItemsFromXml( doc.documentElement(), doc, context );
678  }
679 
680  if ( ok )
681  *ok = true;
682 
683  return result;
684 }
685 
687 {
688  return mUndoStack.get();
689 }
690 
692 {
693  return mUndoStack.get();
694 }
695 
697 class QgsLayoutUndoCommand: public QgsAbstractLayoutUndoCommand
698 {
699  public:
700 
701  QgsLayoutUndoCommand( QgsLayout *layout, const QString &text, int id, QUndoCommand *parent SIP_TRANSFERTHIS = nullptr )
702  : QgsAbstractLayoutUndoCommand( text, id, parent )
703  , mLayout( layout )
704  {}
705 
706  protected:
707 
708  void saveState( QDomDocument &stateDoc ) const override
709  {
710  stateDoc.clear();
711  QDomElement documentElement = stateDoc.createElement( QStringLiteral( "UndoState" ) );
712  mLayout->writeXmlLayoutSettings( documentElement, stateDoc, QgsReadWriteContext() );
713  stateDoc.appendChild( documentElement );
714  }
715 
716  void restoreState( QDomDocument &stateDoc ) override
717  {
718  if ( !mLayout )
719  {
720  return;
721  }
722 
723  mLayout->readXmlLayoutSettings( stateDoc.documentElement(), stateDoc, QgsReadWriteContext() );
724  mLayout->project()->setDirty( true );
725  }
726 
727  private:
728 
729  QgsLayout *mLayout = nullptr;
730 };
732 
733 QgsAbstractLayoutUndoCommand *QgsLayout::createCommand( const QString &text, int id, QUndoCommand *parent )
734 {
735  return new QgsLayoutUndoCommand( this, text, id, parent );
736 }
737 
738 QgsLayoutItemGroup *QgsLayout::groupItems( const QList<QgsLayoutItem *> &items )
739 {
740  if ( items.size() < 2 )
741  {
742  //not enough items for a group
743  return nullptr;
744  }
745 
746  mUndoStack->beginMacro( tr( "Group Items" ) );
747  std::unique_ptr< QgsLayoutItemGroup > itemGroup( new QgsLayoutItemGroup( this ) );
748  for ( QgsLayoutItem *item : items )
749  {
750  itemGroup->addItem( item );
751  }
752  QgsLayoutItemGroup *returnGroup = itemGroup.get();
753  addLayoutItem( itemGroup.release() );
754 
755  std::unique_ptr< QgsLayoutItemGroupUndoCommand > c( new QgsLayoutItemGroupUndoCommand( QgsLayoutItemGroupUndoCommand::Grouped, returnGroup, this, tr( "Group Items" ) ) );
756  mUndoStack->push( c.release() );
757  mProject->setDirty( true );
758 
759  mUndoStack->endMacro();
760 
761  return returnGroup;
762 }
763 
764 QList<QgsLayoutItem *> QgsLayout::ungroupItems( QgsLayoutItemGroup *group )
765 {
766  QList<QgsLayoutItem *> ungroupedItems;
767  if ( !group )
768  {
769  return ungroupedItems;
770  }
771 
772  mUndoStack->beginMacro( tr( "Ungroup Items" ) );
773  // Call this before removing group items so it can keep note
774  // of contents
775  std::unique_ptr< QgsLayoutItemGroupUndoCommand > c( new QgsLayoutItemGroupUndoCommand( QgsLayoutItemGroupUndoCommand::Ungrouped, group, this, tr( "Ungroup Items" ) ) );
776  mUndoStack->push( c.release() );
777 
778  mProject->setDirty( true );
779 
780  ungroupedItems = group->items();
781  group->removeItems();
782 
783  removeLayoutItem( group );
784  mUndoStack->endMacro();
785 
786  return ungroupedItems;
787 }
788 
790 {
791  const QList< QGraphicsItem * > constItems = items();
792  for ( const QGraphicsItem *item : constItems )
793  {
794  const QgsLayoutItem *layoutItem = dynamic_cast<const QgsLayoutItem *>( item );
795  if ( !layoutItem )
796  continue;
797 
798  if ( !layoutItem->accept( visitor ) )
799  return false;
800  }
801  return true;
802 }
803 
805 {
806  mUndoStack->blockCommands( true );
807  mPageCollection->beginPageSizeChange();
808  emit refreshed();
809  mPageCollection->reflow();
810  mPageCollection->endPageSizeChange();
811  mUndoStack->blockCommands( false );
812  update();
813 }
814 
815 void QgsLayout::writeXmlLayoutSettings( QDomElement &element, QDomDocument &document, const QgsReadWriteContext & ) const
816 {
817  mCustomProperties.writeXml( element, document );
818  element.setAttribute( QStringLiteral( "units" ), QgsUnitTypes::encodeUnit( mUnits ) );
819  element.setAttribute( QStringLiteral( "worldFileMap" ), mWorldFileMapId );
820  element.setAttribute( QStringLiteral( "printResolution" ), mRenderContext->dpi() );
821 }
822 
823 QDomElement QgsLayout::writeXml( QDomDocument &document, const QgsReadWriteContext &context ) const
824 {
825  QDomElement element = document.createElement( QStringLiteral( "Layout" ) );
826  auto save = [&]( const QgsLayoutSerializableObject * object )->bool
827  {
828  return object->writeXml( element, document, context );
829  };
830  save( &mSnapper );
831  save( &mGridSettings );
832  save( mPageCollection.get() );
833 
834  //save items except paper items and frame items (they are saved with the corresponding multiframe)
835  const QList<QGraphicsItem *> itemList = items();
836  for ( const QGraphicsItem *graphicsItem : itemList )
837  {
838  if ( const QgsLayoutItem *item = dynamic_cast< const QgsLayoutItem *>( graphicsItem ) )
839  {
840  if ( item->type() == QgsLayoutItemRegistry::LayoutPage )
841  continue;
842 
843  item->writeXml( element, document, context );
844  }
845  }
846 
847  //save multiframes
848  for ( QgsLayoutMultiFrame *mf : mMultiFrames )
849  {
850  if ( mf->frameCount() > 0 )
851  mf->writeXml( element, document, context );
852  }
853 
854  writeXmlLayoutSettings( element, document, context );
855  return element;
856 }
857 
858 bool QgsLayout::readXmlLayoutSettings( const QDomElement &layoutElement, const QDomDocument &, const QgsReadWriteContext & )
859 {
860  mCustomProperties.readXml( layoutElement );
861  setUnits( QgsUnitTypes::decodeLayoutUnit( layoutElement.attribute( QStringLiteral( "units" ) ) ) );
862  mWorldFileMapId = layoutElement.attribute( QStringLiteral( "worldFileMap" ) );
863  mRenderContext->setDpi( layoutElement.attribute( QStringLiteral( "printResolution" ), QStringLiteral( "300" ) ).toDouble() );
864  emit changed();
865 
866  return true;
867 }
868 
869 void QgsLayout::addLayoutItemPrivate( QgsLayoutItem *item )
870 {
871  addItem( item );
872  updateBounds();
873  mItemsModel->rebuildZList();
874  connect( item, &QgsLayoutItem::backgroundTaskCountChanged, this, &QgsLayout::itemBackgroundTaskCountChanged );
875  emit itemAdded( item );
876 }
877 
878 void QgsLayout::removeLayoutItemPrivate( QgsLayoutItem *item )
879 {
880  mItemsModel->setItemRemoved( item );
881  // small chance that item is still in a scene - the model may have
882  // rejected the removal for some reason. This is probably not necessary,
883  // but can't hurt...
884  if ( item->scene() )
885  removeItem( item );
886 #if 0 //TODO
887  emit itemRemoved( item );
888 #endif
889  item->cleanup();
890  item->deleteLater();
891 }
892 
893 void QgsLayout::deleteAndRemoveMultiFrames()
894 {
895  qDeleteAll( mMultiFrames );
896  mMultiFrames.clear();
897 }
898 
899 QPointF QgsLayout::minPointFromXml( const QDomElement &elem ) const
900 {
901  double minX = std::numeric_limits<double>::max();
902  double minY = std::numeric_limits<double>::max();
903  const QDomNodeList itemList = elem.elementsByTagName( QStringLiteral( "LayoutItem" ) );
904  bool found = false;
905  for ( int i = 0; i < itemList.size(); ++i )
906  {
907  const QDomElement currentItemElem = itemList.at( i ).toElement();
908 
909  QgsLayoutPoint pos = QgsLayoutPoint::decodePoint( currentItemElem.attribute( QStringLiteral( "position" ) ) );
910  QPointF layoutPoint = convertToLayoutUnits( pos );
911 
912  minX = std::min( minX, layoutPoint.x() );
913  minY = std::min( minY, layoutPoint.y() );
914  found = true;
915  }
916  return found ? QPointF( minX, minY ) : QPointF( 0, 0 );
917 }
918 
919 void QgsLayout::updateZValues( const bool addUndoCommands )
920 {
921  int counter = mItemsModel->zOrderListSize();
922  const QList<QgsLayoutItem *> zOrderList = mItemsModel->zOrderList();
923 
924  if ( addUndoCommands )
925  {
926  mUndoStack->beginMacro( tr( "Change Item Stacking" ) );
927  }
928  for ( QgsLayoutItem *currentItem : zOrderList )
929  {
930  if ( currentItem )
931  {
932  if ( addUndoCommands )
933  {
934  mUndoStack->beginCommand( currentItem, QString() );
935  }
936  currentItem->setZValue( counter );
937  if ( addUndoCommands )
938  {
939  mUndoStack->endCommand();
940  }
941  }
942  --counter;
943  }
944  if ( addUndoCommands )
945  {
946  mUndoStack->endMacro();
947  }
948 }
949 
950 bool QgsLayout::readXml( const QDomElement &layoutElement, const QDomDocument &document, const QgsReadWriteContext &context )
951 {
952  if ( layoutElement.nodeName() != QLatin1String( "Layout" ) )
953  {
954  return false;
955  }
956 
957  auto restore = [&]( QgsLayoutSerializableObject * object )->bool
958  {
959  return object->readXml( layoutElement, document, context );
960  };
961 
962  std::unique_ptr< QgsScopedRuntimeProfile > profile;
963  if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) )
964  profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Read layout settings" ), QStringLiteral( "projectload" ) );
965 
966  blockSignals( true ); // defer changed signal to end
967  readXmlLayoutSettings( layoutElement, document, context );
968  blockSignals( false );
969 
970  if ( profile )
971  profile->switchTask( tr( "Load pages" ) );
972  restore( mPageCollection.get() );
973  if ( profile )
974  profile->switchTask( tr( "Load snapping settings" ) );
975  restore( &mSnapper );
976  if ( profile )
977  profile->switchTask( tr( "Load grid settings" ) );
978  restore( &mGridSettings );
979 
980  if ( profile )
981  profile->switchTask( tr( "Restore items" ) );
982  addItemsFromXml( layoutElement, document, context );
983 
984  emit changed();
985 
986  return true;
987 }
988 
989 QList< QgsLayoutItem * > QgsLayout::addItemsFromXml( const QDomElement &parentElement, const QDomDocument &document, const QgsReadWriteContext &context, QPointF *position, bool pasteInPlace )
990 {
991  QList< QgsLayoutItem * > newItems;
992  QList< QgsLayoutMultiFrame * > newMultiFrames;
993 
994  //if we are adding items to a layout which already contains items, we need to make sure
995  //these items are placed at the top of the layout and that zValues are not duplicated
996  //so, calculate an offset which needs to be added to the zValue of created items
997  int zOrderOffset = mItemsModel->zOrderListSize();
998 
999  QPointF pasteShiftPos;
1000  int pageNumber = -1;
1001  if ( position )
1002  {
1003  //If we are placing items relative to a certain point, then calculate how much we need
1004  //to shift the items by so that they are placed at this point
1005  //First, calculate the minimum position from the xml
1006  QPointF minItemPos = minPointFromXml( parentElement );
1007  //next, calculate how much each item needs to be shifted from its original position
1008  //so that it's placed at the correct relative position
1009  pasteShiftPos = *position - minItemPos;
1010  if ( pasteInPlace )
1011  {
1012  pageNumber = mPageCollection->pageNumberForPoint( *position );
1013  }
1014  }
1015 
1016  std::unique_ptr< QgsScopedRuntimeProfile > profile;
1017  if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) )
1018  profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Read items" ), QStringLiteral( "projectload" ) );
1019 
1020  // multiframes
1021 
1022  //TODO - fix this. pasting multiframe frame items has no effect
1023  const QDomNodeList multiFrameList = parentElement.elementsByTagName( QStringLiteral( "LayoutMultiFrame" ) );
1024  for ( int i = 0; i < multiFrameList.size(); ++i )
1025  {
1026  const QDomElement multiFrameElem = multiFrameList.at( i ).toElement();
1027  const int itemType = multiFrameElem.attribute( QStringLiteral( "type" ) ).toInt();
1028 
1029  if ( profile )
1030  {
1031  if ( QgsLayoutMultiFrameAbstractMetadata *metadata = QgsApplication::layoutItemRegistry()->multiFrameMetadata( itemType ) )
1032  {
1033  profile->switchTask( tr( "Load %1" ).arg( metadata->visibleName() ) );
1034  }
1035  }
1036 
1037  std::unique_ptr< QgsLayoutMultiFrame > mf( QgsApplication::layoutItemRegistry()->createMultiFrame( itemType, this ) );
1038  if ( !mf )
1039  {
1040  // e.g. plugin based item which is no longer available
1041  continue;
1042  }
1043  mf->readXml( multiFrameElem, document, context );
1044 
1045 #if 0 //TODO?
1046  mf->setCreateUndoCommands( true );
1047 #endif
1048 
1049  QgsLayoutMultiFrame *m = mf.get();
1050  this->addMultiFrame( mf.release() );
1051 
1052  //offset z values for frames
1053  //TODO - fix this after fixing multiframe item paste
1054  /*for ( int frameIdx = 0; frameIdx < mf->frameCount(); ++frameIdx )
1055  {
1056  QgsLayoutItemFrame * frame = mf->frame( frameIdx );
1057  frame->setZValue( frame->zValue() + zOrderOffset );
1058 
1059  // also need to shift frames according to position/pasteInPlacePt
1060  }*/
1061  newMultiFrames << m;
1062  }
1063 
1064  const QDomNodeList layoutItemList = parentElement.childNodes();
1065  for ( int i = 0; i < layoutItemList.size(); ++i )
1066  {
1067  const QDomElement currentItemElem = layoutItemList.at( i ).toElement();
1068  if ( currentItemElem.nodeName() != QLatin1String( "LayoutItem" ) )
1069  continue;
1070 
1071  const int itemType = currentItemElem.attribute( QStringLiteral( "type" ) ).toInt();
1072 
1073  if ( profile )
1074  {
1075  if ( QgsLayoutItemAbstractMetadata *metadata = QgsApplication::layoutItemRegistry()->itemMetadata( itemType ) )
1076  {
1077  profile->switchTask( tr( "Load %1" ).arg( metadata->visibleName() ) );
1078  }
1079  }
1080 
1081  std::unique_ptr< QgsLayoutItem > item( QgsApplication::layoutItemRegistry()->createItem( itemType, this ) );
1082  if ( !item )
1083  {
1084  // e.g. plugin based item which is no longer available
1085  continue;
1086  }
1087 
1088  item->readXml( currentItemElem, document, context );
1089  if ( position )
1090  {
1091  if ( pasteInPlace )
1092  {
1093  QgsLayoutPoint posOnPage = QgsLayoutPoint::decodePoint( currentItemElem.attribute( QStringLiteral( "positionOnPage" ) ) );
1094  item->attemptMove( posOnPage, true, false, pageNumber );
1095  }
1096  else
1097  {
1098  item->attemptMoveBy( pasteShiftPos.x(), pasteShiftPos.y() );
1099  }
1100  }
1101 
1102  QgsLayoutItem *layoutItem = item.get();
1103  addLayoutItem( item.release() );
1104  layoutItem->setZValue( layoutItem->zValue() + zOrderOffset );
1105  newItems << layoutItem;
1106  }
1107 
1108  // we now allow items to "post-process", e.g. if they need to setup connections
1109  // to other items in the layout, which may not have existed at the time the
1110  // item's state was restored. E.g. a scalebar may have been restored before the map
1111  // it is linked to
1112  std::unique_ptr< QgsScopedRuntimeProfile > itemProfile;
1113  if ( profile )
1114  {
1115  profile->switchTask( tr( "Finalize restore" ) );
1116  }
1117  for ( QgsLayoutItem *item : std::as_const( newItems ) )
1118  {
1119  if ( profile )
1120  itemProfile = std::make_unique< QgsScopedRuntimeProfile >( item->displayName(), QStringLiteral( "projectload" ) );
1121  item->finalizeRestoreFromXml();
1122  if ( itemProfile )
1123  itemProfile.reset();
1124  }
1125  for ( QgsLayoutMultiFrame *mf : std::as_const( newMultiFrames ) )
1126  {
1127  if ( profile )
1128  itemProfile = std::make_unique< QgsScopedRuntimeProfile >( mf->displayName(), QStringLiteral( "projectload" ) );
1129  mf->finalizeRestoreFromXml();
1130  if ( itemProfile )
1131  itemProfile.reset();
1132  }
1133 
1134  for ( QgsLayoutItem *item : std::as_const( newItems ) )
1135  {
1136  item->mTemplateUuid.clear();
1137  }
1138  for ( QgsLayoutMultiFrame *mf : std::as_const( newMultiFrames ) )
1139  {
1140  mf->mTemplateUuid.clear();
1141  }
1142 
1143  //Since this function adds items in an order which isn't the z-order, and each item is added to end of
1144  //z order list in turn, it will now be inconsistent with the actual order of items in the scene.
1145  //Make sure z order list matches the actual order of items in the scene.
1146 
1147  if ( profile )
1148  profile->switchTask( tr( "Update model" ) );
1149  mItemsModel->rebuildZList();
1150 
1151  return newItems;
1152 }
1153 
1155 {
1156  setSceneRect( layoutBounds( false, 0.05 ) );
1157 }
1158 
1159 void QgsLayout::itemBackgroundTaskCountChanged( int count )
1160 {
1161  QgsLayoutItem *item = qobject_cast<QgsLayoutItem *>( sender() );
1162  if ( !item )
1163  return;
1164 
1165  if ( count > 0 )
1166  mBackgroundTaskCount.insert( item, count );
1167  else
1168  mBackgroundTaskCount.remove( item );
1169 
1170  // sum up new count of background tasks
1171  int total = 0;
1172  for ( auto it = mBackgroundTaskCount.constBegin(); it != mBackgroundTaskCount.constEnd(); ++it )
1173  {
1174  total += it.value();
1175  }
1176 
1177  emit backgroundTaskCountChanged( total );
1178 }
QgsLayout::deselectAll
void deselectAll()
Clears any selected items in the layout.
Definition: qgslayout.cpp:169
QgsLayoutItem::cleanup
virtual void cleanup()
Called just before a batch of items are deleted, allowing them to run cleanup tasks.
Definition: qgslayoutitem.cpp:99
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:406
QgsLayout::changed
void changed()
Emitted when properties of the layout change.
QgsLayoutItem::id
QString id() const
Returns the item's ID name.
Definition: qgslayoutitem.h:359
qgslayoutitemgroup.h
qgsexpressioncontextutils.h
QgsLayout::multiFrameByUuid
QgsLayoutMultiFrame * multiFrameByUuid(const QString &uuid, bool includeTemplateUuids=false) const
Returns the layout multiframe with matching uuid unique identifier, or nullptr if a matching multifra...
Definition: qgslayout.cpp:280
QgsLayout::addLayoutItem
void addLayoutItem(QgsLayoutItem *item)
Adds an item to the layout.
Definition: qgslayout.cpp:540
QgsLayout::referenceMap
QgsLayoutItemMap * referenceMap() const
Returns the map item which will be used to generate corresponding world files when the layout is expo...
Definition: qgslayout.cpp:430
QgsLayoutRenderContext::measurementConverter
const QgsLayoutMeasurementConverter & measurementConverter() const
Returns the layout measurement converter to be used in the layout.
Definition: qgslayoutrendercontext.h:133
QgsLayout::removeCustomProperty
void removeCustomProperty(const QString &key)
Remove a custom property from the layout.
Definition: qgslayout.cpp:420
qgslayoutitemgroupundocommand.h
qgsruntimeprofiler.h
qgslayoutundostack.h
QgsAbstractLayoutUndoCommand::saveState
virtual void saveState(QDomDocument &stateDoc) const =0
Saves the state of the object to the specified stateDoc.
QgsLayoutItemPage
Item representing the paper in a layout.
Definition: qgslayoutitempage.h:58
QgsExpressionContextUtils::globalScope
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Definition: qgsexpressioncontextutils.cpp:40
QgsReadWriteContext
The class is used as a container of context for various read/write operations on other objects.
Definition: qgsreadwritecontext.h:34
QgsLayout::setSelectedItem
void setSelectedItem(QgsLayoutItem *item)
Clears any selected items and sets item as the current selection.
Definition: qgslayout.cpp:159
QgsLayout::selectedLayoutItems
QList< QgsLayoutItem * > selectedLayoutItems(bool includeLockedItems=true)
Returns list of selected layout items.
Definition: qgslayout.cpp:142
QgsLayout::itemByUuid
QgsLayoutItem * itemByUuid(const QString &uuid, bool includeTemplateUuids=false) const
Returns the layout item with matching uuid unique identifier, or nullptr if a matching item could not...
Definition: qgslayout.cpp:238
QgsLayout::layoutItems
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
Definition: qgslayout.h:122
QgsLayout::raiseItem
bool raiseItem(QgsLayoutItem *item, bool deferUpdate=false)
Raises an item up the z-order.
Definition: qgslayout.cpp:186
QgsLayout::itemById
QgsLayoutItem * itemById(const QString &id) const
Returns a layout item given its id.
Definition: qgslayout.cpp:266
QgsLayout::renderContext
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout's render context, which stores information relating to the current ...
Definition: qgslayout.cpp:359
QgsLayoutMeasurement::length
double length() const
Returns the length of the measurement.
Definition: qgslayoutmeasurement.h:48
qgsreadwritecontext.h
QgsCompositionConverter::convertCompositionTemplate
static QDomDocument convertCompositionTemplate(const QDomDocument &document, QgsProject *project)
Convert a composition template document to a layout template.
Definition: qgscompositionconverter.cpp:482
QgsLayout::QgsLayoutUndoCommand
friend class QgsLayoutUndoCommand
Definition: qgslayout.h:776
QgsLayoutItem::finalizeRestoreFromXml
virtual void finalizeRestoreFromXml()
Called after all pending items have been restored from XML.
Definition: qgslayoutitem.cpp:825
QgsExpressionContextUtils::layerScope
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Definition: qgsexpressioncontextutils.cpp:334
qgslayoutmultiframe.h
QgsLayout::ungroupItems
QList< QgsLayoutItem * > ungroupItems(QgsLayoutItemGroup *group)
Ungroups items by removing them from an item group and removing the group from the layout.
Definition: qgslayout.cpp:764
QgsLayout::QgsLayoutModel
friend class QgsLayoutModel
Definition: qgslayout.h:778
QgsUnitTypes::LayoutUnit
LayoutUnit
Layout measurement units.
Definition: qgsunittypes.h:181
QgsLayoutItemPage::setPageSize
void setPageSize(const QgsLayoutSize &size)
Sets the size of the page.
Definition: qgslayoutitempage.cpp:72
QgsLayoutRenderContext
Stores information relating to the current rendering settings for a layout.
Definition: qgslayoutrendercontext.h:36
QgsLayoutReportContext
Stores information relating to the current reporting context for a layout.
Definition: qgslayoutreportcontext.h:32
QgsStyleEntityVisitorInterface
An interface for classes which can visit style entity (e.g. symbol) nodes (using the visitor pattern)...
Definition: qgsstyleentityvisitor.h:33
QgsExpressionContextUtils::layoutScope
static QgsExpressionContextScope * layoutScope(const QgsLayout *layout)
Creates a new scope which contains variables and functions relating to a QgsLayout layout.
Definition: qgsexpressioncontextutils.cpp:556
QgsLayout::addMultiFrame
void addMultiFrame(QgsLayoutMultiFrame *multiFrame)
Adds a multiFrame to the layout.
Definition: qgslayout.cpp:572
QgsObjectCustomProperties::readXml
void readXml(const QDomNode &parentNode, const QString &keyStartsWith=QString())
Read store contents from an XML node.
Definition: qgsobjectcustomproperties.cpp:51
QgsLayout::QgsLayoutItemDeleteUndoCommand
friend class QgsLayoutItemDeleteUndoCommand
Definition: qgslayout.h:774
QgsLayout::refreshed
void refreshed()
Emitted when the layout has been refreshed and items should also be refreshed and updated.
QgsLayoutItem::page
int page() const
Returns the page the item is currently on, with the first page returning 0.
Definition: qgslayoutitem.cpp:542
QgsAbstractLayoutUndoCommand::restoreState
virtual void restoreState(QDomDocument &stateDoc)=0
Restores the state of the object from the specified stateDoc.
QgsLayoutMultiFrame
Abstract base class for layout items with the ability to distribute the content to several frames (Qg...
Definition: qgslayoutmultiframe.h:48
qgslayoutitemundocommand.h
QgsLayout::customProperties
QStringList customProperties() const
Returns list of keys stored in custom properties for the layout.
Definition: qgslayout.cpp:425
QgsLayout::pageCollection
QgsLayoutPageCollection * pageCollection()
Returns a pointer to the layout's page collection, which stores and manages page items in the layout.
Definition: qgslayout.cpp:459
QgsLayoutMeasurementConverter::convert
QgsLayoutMeasurement convert(QgsLayoutMeasurement measurement, QgsUnitTypes::LayoutUnit targetUnits) const
Converts a measurement from one unit to another.
Definition: qgslayoutmeasurementconverter.cpp:21
QgsLayoutItem::backgroundTaskCountChanged
void backgroundTaskCountChanged(int count)
Emitted whenever the number of background tasks an item is executing changes.
QgsLayout::createExpressionContext
QgsExpressionContext createExpressionContext() const override
Creates an expression context relating to the layout's current state.
Definition: qgslayout.cpp:395
QgsProject
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:103
QgsLayoutItem::setSelected
virtual void setSelected(bool selected)
Sets whether the item should be selected.
Definition: qgslayoutitem.cpp:160
QgsLayout::setUnits
void setUnits(QgsUnitTypes::LayoutUnit units)
Sets the native measurement units for the layout.
Definition: qgslayout.h:322
QgsLayout::clone
QgsLayout * clone() const
Creates a clone of the layout.
Definition: qgslayout.cpp:83
QgsLayoutItem::type
int type() const override
Returns a unique graphics item type identifier.
Definition: qgslayoutitem.cpp:124
QgsLayoutItemAbstractMetadata
Stores metadata about one layout item class.
Definition: qgslayoutitemregistry.h:45
QgsLayout::addItemsFromXml
QList< QgsLayoutItem * > addItemsFromXml(const QDomElement &parentElement, const QDomDocument &document, const QgsReadWriteContext &context, QPointF *position=nullptr, bool pasteInPlace=false)
Add items from an XML representation to the layout.
Definition: qgslayout.cpp:989
QgsLayout::layoutBounds
QRectF layoutBounds(bool ignorePages=false, double margin=0.0) const
Calculates the bounds of all non-gui items in the layout.
Definition: qgslayout.cpp:469
QgsLayoutMultiFrameAbstractMetadata
Stores metadata about one layout multiframe class.
Definition: qgslayoutitemregistry.h:189
QgsLayoutRenderContext::setDpi
void setDpi(double dpi)
Sets the dpi for outputting the layout.
Definition: qgslayoutrendercontext.cpp:80
QgsExpressionContextUtils::projectScope
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
Definition: qgsexpressioncontextutils.cpp:291
QgsLayout::layoutItemAt
QgsLayoutItem * layoutItemAt(QPointF position, bool ignoreLocked=false) const
Returns the topmost layout item at a specified position.
Definition: qgslayout.cpp:293
QgsLayout::moveItemToTop
bool moveItemToTop(QgsLayoutItem *item, bool deferUpdate=false)
Raises an item up to the top of the z-order.
Definition: qgslayout.cpp:212
QgsLayout::moveItemToBottom
bool moveItemToBottom(QgsLayoutItem *item, bool deferUpdate=false)
Lowers an item down to the bottom of the z-order.
Definition: qgslayout.cpp:225
QgsUnitTypes::encodeUnit
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
Definition: qgsunittypes.cpp:122
QgsLayoutUndoStack
An undo stack for QgsLayouts.
Definition: qgslayoutundostack.h:36
QgsLayoutModel
A model for items attached to a layout. The model also maintains the z-order for the layout,...
Definition: qgslayoutmodel.h:52
QgsLayout::QgsLayout
QgsLayout(QgsProject *project)
Construct a new layout linked to the specified project.
Definition: qgslayout.cpp:36
QgsLayout::customProperty
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from the layout.
Definition: qgslayout.cpp:415
qgslayoutitem.h
QgsLayout::~QgsLayout
~QgsLayout() override
Definition: qgslayout.cpp:50
whileBlocking
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:2191
QgsLayoutItem::accept
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
Definition: qgslayoutitem.cpp:1166
QgsLayout::pageItemBounds
QRectF pageItemBounds(int page, bool visibleOnly=false) const
Returns the bounding box of the items contained on a specified page.
Definition: qgslayout.cpp:514
QgsCompositionConverter::isCompositionTemplate
static bool isCompositionTemplate(const QDomDocument &document)
Check if the given document is a composition template.
Definition: qgscompositionconverter.cpp:477
QgsLayout::readXml
virtual bool readXml(const QDomElement &layoutElement, const QDomDocument &document, const QgsReadWriteContext &context)
Sets the collection's state from a DOM element.
Definition: qgslayout.cpp:950
QgsRuntimeProfiler::groupIsActive
bool groupIsActive(const QString &group) const
Returns true if the specified group is currently being logged, i.e.
Definition: qgsruntimeprofiler.cpp:294
QgsLayout::loadFromTemplate
QList< QgsLayoutItem * > loadFromTemplate(const QDomDocument &document, const QgsReadWriteContext &context, bool clearExisting=true, bool *ok=nullptr)
Load a layout template document.
Definition: qgslayout.cpp:609
QgsObjectCustomProperties::setValue
void setValue(const QString &key, const QVariant &value)
Add an entry to the store with the specified key.
Definition: qgsobjectcustomproperties.cpp:31
QgsLayout::reportContext
QgsLayoutReportContext & reportContext()
Returns a reference to the layout's report context, which stores information relating to the current ...
Definition: qgslayout.cpp:369
qgslayoutguidecollection.h
QgsApplication::profiler
static QgsRuntimeProfiler * profiler()
Returns the application runtime profiler.
Definition: qgsapplication.cpp:549
QgsLayout::variablesChanged
void variablesChanged()
Emitted whenever the expression variables stored in the layout have been changed.
QgsLayout::updateBounds
void updateBounds()
Updates the scene bounds of the layout.
Definition: qgslayout.cpp:1154
QgsProject::setDirty
void setDirty(bool b=true)
Flag the project as dirty (modified).
Definition: qgsproject.cpp:576
QgsLayout::removeMultiFrame
void removeMultiFrame(QgsLayoutMultiFrame *multiFrame)
Removes a multiFrame from the layout (but does not delete it).
Definition: qgslayout.cpp:581
QgsLayoutItemGroup::removeItems
void removeItems()
Removes all items from the group (but does not delete them).
Definition: qgslayoutitemgroup.cpp:87
QgsLayoutItem
Base class for graphical items within a QgsLayout.
Definition: qgslayoutitem.h:112
QgsLayout::QgsLayoutItemAddItemCommand
friend class QgsLayoutItemAddItemCommand
Definition: qgslayout.h:773
qgslayout.h
QgsLayoutItemGroup
A container for grouping several QgsLayoutItems.
Definition: qgslayoutitemgroup.h:28
QgsObjectCustomProperties::remove
void remove(const QString &key)
Removes a key (entry) from the store.
Definition: qgsobjectcustomproperties.cpp:41
QgsExpressionContext::appendScope
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Definition: qgsexpressioncontext.cpp:494
QgsLayoutSerializableObject
An interface for layout objects which can be stored and read from DOM elements.
Definition: qgslayoutserializableobject.h:35
QgsLayout::accept
bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
Definition: qgslayout.cpp:789
qgsvectorlayer.h
QgsLayoutItemMap
Layout graphical items for displaying a map.
Definition: qgslayoutitemmap.h:317
QgsLayout::groupItems
QgsLayoutItemGroup * groupItems(const QList< QgsLayoutItem * > &items)
Creates a new group from a list of layout items and adds the group to the layout.
Definition: qgslayout.cpp:738
QgsLayoutGuideCollection
Stores and manages the snap guides used by a layout.
Definition: qgslayoutguidecollection.h:168
QgsLayout::setReferenceMap
void setReferenceMap(QgsLayoutItemMap *map)
Sets the map item which will be used to generate corresponding world files when the layout is exporte...
Definition: qgslayout.cpp:453
QgsLayout::lowerItem
bool lowerItem(QgsLayoutItem *item, bool deferUpdate=false)
Lowers an item down the z-order.
Definition: qgslayout.cpp:199
QgsLayoutPageCollection
A manager for a collection of pages in a layout.
Definition: qgslayoutpagecollection.h:39
QgsLayoutGridSettings::loadFromSettings
void loadFromSettings()
Loads grid settings from the application layout settings.
Definition: qgslayoutgridsettings.cpp:53
QgsLayoutItem::uuid
virtual QString uuid() const
Returns the item identification string.
Definition: qgslayoutitem.h:345
QgsApplication::layoutItemRegistry
static QgsLayoutItemRegistry * layoutItemRegistry()
Returns the application's layout item registry, used for layout item types.
Definition: qgsapplication.cpp:2395
QgsLayout::writeXml
virtual QDomElement writeXml(QDomDocument &document, const QgsReadWriteContext &context) const
Returns the layout's state encapsulated in a DOM element.
Definition: qgslayout.cpp:823
QgsAbstractLayoutUndoCommand
Base class for commands to undo/redo layout and layout object changes.
Definition: qgslayoutundocommand.h:34
c
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Definition: porting_processing.dox:1
QgsLayout
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:50
qgscompositionconverter.h
QgsLayout::initializeDefaults
void initializeDefaults()
Initializes an empty layout, e.g.
Definition: qgslayout.cpp:102
QgsLayout::updateZValues
void updateZValues(bool addUndoCommands=true)
Resets the z-values of items based on their position in the internal z order list.
Definition: qgslayout.cpp:919
QgsLayout::selectedItemChanged
void selectedItemChanged(QgsLayoutItem *selected)
Emitted whenever the selected item changes.
QgsLayoutItem::displayName
virtual QString displayName() const
Gets item display name.
Definition: qgslayoutitem.cpp:107
QgsObjectCustomProperties::keys
QStringList keys() const
Returns a list of all stored keys.
Definition: qgsobjectcustomproperties.cpp:26
QgsObjectCustomProperties::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Returns the value for the given key.
Definition: qgsobjectcustomproperties.cpp:36
QgsLayout::clear
void clear()
Clears the layout.
Definition: qgslayout.cpp:111
QgsLayoutPoint::decodePoint
static QgsLayoutPoint decodePoint(const QString &string)
Decodes a point from a string.
Definition: qgslayoutpoint.cpp:60
QgsLayoutItemGroup::items
QList< QgsLayoutItem * > items() const
Returns a list of items contained by the group.
Definition: qgslayoutitemgroup.cpp:99
QgsLayoutSnapper
Manages snapping grids and preset snap lines in a layout, and handles snapping points to the nearest ...
Definition: qgslayoutsnapper.h:36
QgsLayout::multiFrames
QList< QgsLayoutMultiFrame * > multiFrames() const
Returns a list of multi frames contained in the layout.
Definition: qgslayout.cpp:586
QgsLayout::backgroundTaskCountChanged
void backgroundTaskCountChanged(int total)
Emitted whenever the total number of background tasks running in items from the layout changes.
QgsLayout::itemAdded
void itemAdded(QgsLayoutItem *item)
Emitted when an item was added to the layout.
qgslayoutpagecollection.h
QgsLayoutSize
This class provides a method of storing sizes, consisting of a width and height, for use in QGIS layo...
Definition: qgslayoutsize.h:40
QgsLayoutRenderContext::dpi
double dpi() const
Returns the dpi for outputting the layout.
Definition: qgslayoutrendercontext.cpp:89
QgsLayout::guides
QgsLayoutGuideCollection & guides()
Returns a reference to the layout's guide collection, which manages page snap guides.
Definition: qgslayout.cpp:385
QgsUnitTypes::LayoutMillimeters
@ LayoutMillimeters
Millimeters.
Definition: qgsunittypes.h:183
QgsLayout::itemByTemplateUuid
QgsLayoutItem * itemByTemplateUuid(const QString &uuid) const
Returns the layout item with matching template uuid unique identifier, or nullptr if a matching item ...
Definition: qgslayout.cpp:253
QgsLayout::saveAsTemplate
bool saveAsTemplate(const QString &path, const QgsReadWriteContext &context) const
Saves the layout as a template at the given file path.
Definition: qgslayout.cpp:591
QgsLayout::project
QgsProject * project() const
The project associated with the layout.
Definition: qgslayout.cpp:132
QgsLayout::setCustomProperty
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for the layout.
Definition: qgslayout.cpp:407
QgsLayout::removeLayoutItem
void removeLayoutItem(QgsLayoutItem *item)
Removes an item from the layout.
Definition: qgslayout.cpp:556
QgsLayoutPoint
This class provides a method of storing points, consisting of an x and y coordinate,...
Definition: qgslayoutpoint.h:39
QgsLayout::QgsLayoutItemGroupUndoCommand
friend class QgsLayoutItemGroupUndoCommand
Definition: qgslayout.h:777
QgsLayout::createCommand
QgsAbstractLayoutUndoCommand * createCommand(const QString &text, int id=0, QUndoCommand *parent=nullptr) override
Creates a new layout undo command with the specified text and parent.
Definition: qgslayout.cpp:733
QgsUnitTypes::decodeLayoutUnit
static Q_INVOKABLE QgsUnitTypes::LayoutUnit decodeLayoutUnit(const QString &string, bool *ok=nullptr)
Decodes a layout unit from a string.
Definition: qgsunittypes.cpp:3043
SIP_TRANSFERTHIS
#define SIP_TRANSFERTHIS
Definition: qgis_sip.h:53
QgsLayout::convertToLayoutUnits
double convertToLayoutUnits(QgsLayoutMeasurement measurement) const
Converts a measurement into the layout's native units.
Definition: qgslayout.cpp:329
qgslayoutmodel.h
qgsproject.h
QgsLayout::refresh
void refresh()
Forces the layout, and all items contained within it, to refresh.
Definition: qgslayout.cpp:804
QgsLayoutReportContext::layer
QgsVectorLayer * layer() const
Returns the vector layer associated with the layout's context.
Definition: qgslayoutreportcontext.cpp:66
QgsLayout::itemsModel
QgsLayoutModel * itemsModel()
Returns the items model attached to the layout.
Definition: qgslayout.cpp:137
QgsLayoutMeasurement
This class provides a method of storing measurements for use in QGIS layouts using a variety of diffe...
Definition: qgslayoutmeasurement.h:33
QgsLayoutItem::isLocked
bool isLocked() const
Returns true if the item is locked, and cannot be interacted with using the mouse.
Definition: qgslayoutitem.h:402
QgsLayout::convertFromLayoutUnits
QgsLayoutMeasurement convertFromLayoutUnits(double length, QgsUnitTypes::LayoutUnit unit) const
Converts a length measurement from the layout's native units to a specified target unit.
Definition: qgslayout.cpp:344
QgsObjectCustomProperties::writeXml
void writeXml(QDomNode &parentNode, QDomDocument &doc) const
Writes the store contents to an XML node.
Definition: qgsobjectcustomproperties.cpp:130
QgsLayoutItemRegistry::LayoutPage
@ LayoutPage
Page items.
Definition: qgslayoutitemregistry.h:346
qgsstyleentityvisitor.h
qgslayoutitemmap.h
QgsLayout::reloadSettings
void reloadSettings()
Refreshes the layout when global layout related options change.
Definition: qgslayout.cpp:379
QgsLayout::undoStack
QgsLayoutUndoStack * undoStack()
Returns a pointer to the layout's undo stack, which manages undo/redo states for the layout and it's ...
Definition: qgslayout.cpp:686