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