QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 
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 }
void setDirty(bool b=true)
Flag the project as dirty (modified).
Definition: qgsproject.cpp:473
The class is used as a container of context for various read/write operations on other objects...
void removeItems()
Removes all items from the group (but does not delete them).
void setSelectedItem(QgsLayoutItem *item)
Clears any selected items and sets item as the current selection.
Definition: qgslayout.cpp:158
bool raiseItem(QgsLayoutItem *item, bool deferUpdate=false)
Raises an item up the z-order.
Definition: qgslayout.cpp:185
QgsLayoutGuideCollection & guides()
Returns a reference to the layout&#39;s guide collection, which manages page snap guides.
Definition: qgslayout.cpp:384
QgsLayoutItem * itemById(const QString &id) const
Returns a layout item given its id.
Definition: qgslayout.cpp:265
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
QgsLayout * clone() const
Creates a clone of the layout.
Definition: qgslayout.cpp:82
void backgroundTaskCountChanged(int total)
Emitted whenever the total number of background tasks running in items from the layout changes...
Base class for graphical items within a QgsLayout.
#define SIP_TRANSFERTHIS
Definition: qgis_sip.h:53
int type() const override
Returns a unique graphics item type identifier.
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
Base class for commands to undo/redo layout and layout object changes.
QgsLayoutUndoStack * undoStack()
Returns a pointer to the layout&#39;s undo stack, which manages undo/redo states for the layout and it&#39;s ...
Definition: qgslayout.cpp:685
friend class QgsLayoutModel
Definition: qgslayout.h:762
QVariant customProperty(const QString &key, const QVariant &defaultValue=QVariant()) const
Read a custom property from the layout.
Definition: qgslayout.cpp:414
QgsLayoutMeasurement convert(QgsLayoutMeasurement measurement, QgsUnitTypes::LayoutUnit targetUnits) const
Converts a measurement from one unit to another.
Stores information relating to the current reporting context for a layout.
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
virtual bool readXml(const QDomElement &layoutElement, const QDomDocument &document, const QgsReadWriteContext &context)
Sets the collection&#39;s state from a DOM element.
Definition: qgslayout.cpp:948
An undo stack for QgsLayouts.
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
void loadFromSettings()
Loads grid settings from the application layout settings.
A container for grouping several QgsLayoutItems.
static QDomDocument convertCompositionTemplate(const QDomDocument &document, QgsProject *project)
Convert a composition template document to a layout template.
virtual void setSelected(bool selected)
Sets whether the item should be selected.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Returns value for the given key. If the key is not stored, default value will be used.
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
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project.
void setUnits(QgsUnitTypes::LayoutUnit units)
Sets the native measurement units for the layout.
Definition: qgslayout.h:321
Stores metadata about one layout item class.
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
An interface for classes which can visit style entity (e.g.
void updateBounds()
Updates the scene bounds of the layout.
Definition: qgslayout.cpp:1100
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout&#39;s render context, which stores information relating to the current ...
Definition: qgslayout.cpp:358
void remove(const QString &key)
Remove a key (entry) from the store.
QList< QgsLayoutMultiFrame *> multiFrames() const
Returns a list of multi frames contained in the layout.
Definition: qgslayout.cpp:585
Abstract base class for layout items with the ability to distribute the content to several frames (Qg...
This class provides a method of storing points, consisting of an x and y coordinate, for use in QGIS layouts.
void layoutItems(QList< T *> &itemList) const
Returns a list of layout items of a specific type.
Definition: qgslayout.h:121
void removeCustomProperty(const QString &key)
Remove a custom property from the layout.
Definition: qgslayout.cpp:419
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
void deselectAll()
Clears any selected items in the layout.
Definition: qgslayout.cpp:168
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
QgsVectorLayer * layer() const
Returns the vector layer associated with the layout&#39;s context.
static QgsLayoutItemRegistry * layoutItemRegistry()
Returns the application&#39;s layout item registry, used for layout item types.
Layout graphical items for displaying a map.
void backgroundTaskCountChanged(int count)
Emitted whenever the number of background tasks an item is executing changes.
void setValue(const QString &key, const QVariant &value)
Add an entry to the store. If the entry with the keys exists already, it will be overwritten.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
void variablesChanged()
Emitted whenever the expression variables stored in the layout have been changed. ...
This class provides a method of storing measurements for use in QGIS layouts using a variety of diffe...
static bool isCompositionTemplate(const QDomDocument &document)
Check if the given document is a composition template.
static Q_INVOKABLE QgsUnitTypes::LayoutUnit decodeLayoutUnit(const QString &string, bool *ok=nullptr)
Decodes a layout unit from a string.
void refresh()
Forces the layout, and all items contained within it, to refresh.
Definition: qgslayout.cpp:803
QStringList customProperties() const
Returns list of keys stored in custom properties for the layout.
Definition: qgslayout.cpp:424
QList< QgsLayoutItem * > items() const
Returns a list of items contained by the group.
QgsLayoutPageCollection * pageCollection()
Returns a pointer to the layout&#39;s page collection, which stores and manages page items in the layout...
Definition: qgslayout.cpp:458
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QList< QgsLayoutItem * > selectedLayoutItems(bool includeLockedItems=true)
Returns list of selected layout items.
Definition: qgslayout.cpp:141
QList< QgsLayoutItem *> loadFromTemplate(const QDomDocument &document, const QgsReadWriteContext &context, bool clearExisting=true, bool *ok=nullptr)
Load a layout template document.
Definition: qgslayout.cpp:608
void selectedItemChanged(QgsLayoutItem *selected)
Emitted whenever the selected item changes.
virtual void cleanup()
Called just before a batch of items are deleted, allowing them to run cleanup tasks.
void removeMultiFrame(QgsLayoutMultiFrame *multiFrame)
Removes a multiFrame from the layout (but does not delete it).
Definition: qgslayout.cpp:580
Stores and manages the snap guides used by a layout.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc.
Definition: qgsproject.h:89
int page() const
Returns the page the item is currently on, with the first page returning 0.
QString id() const
Returns the item&#39;s ID name.
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:49
QStringList keys() const
Returns list of stored keys.
A manager for a collection of pages in a layout.
QRectF pageItemBounds(int page, bool visibleOnly=false) const
Returns the bounding box of the items contained on a specified page.
Definition: qgslayout.cpp:513
bool lowerItem(QgsLayoutItem *item, bool deferUpdate=false)
Lowers an item down the z-order.
Definition: qgslayout.cpp:198
static Q_INVOKABLE QString encodeUnit(QgsUnitTypes::DistanceUnit unit)
Encodes a distance unit to a string.
QgsLayoutModel * itemsModel()
Returns the items model attached to the layout.
Definition: qgslayout.cpp:136
friend class QgsLayoutItemAddItemCommand
Definition: qgslayout.h:757
virtual void finalizeRestoreFromXml()
Called after all pending items have been restored from XML.
QgsLayoutReportContext & reportContext()
Returns a reference to the layout&#39;s report context, which stores information relating to the current ...
Definition: qgslayout.cpp:368
friend class QgsLayoutUndoCommand
Definition: qgslayout.h:760
QgsExpressionContext createExpressionContext() const override
Creates an expression context relating to the layout&#39;s current state.
Definition: qgslayout.cpp:394
bool moveItemToBottom(QgsLayoutItem *item, bool deferUpdate=false)
Lowers an item down to the bottom of the z-order.
Definition: qgslayout.cpp:224
void clear()
Clears the layout.
Definition: qgslayout.cpp:110
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
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:227
double length() const
Returns the length of the measurement.
bool saveAsTemplate(const QString &path, const QgsReadWriteContext &context) const
Saves the layout as a template at the given file path.
Definition: qgslayout.cpp:590
const QgsLayoutMeasurementConverter & measurementConverter() const
Returns the layout measurement converter to be used in the layout.
void removeLayoutItem(QgsLayoutItem *item)
Removes an item from the layout.
Definition: qgslayout.cpp:555
static QgsExpressionContextScope * layoutScope(const QgsLayout *layout)
Creates a new scope which contains variables and functions relating to a QgsLayout layout...
void refreshed()
Emitted when the layout has been refreshed and items should also be refreshed and updated...
friend class QgsLayoutItemGroupUndoCommand
Definition: qgslayout.h:761
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
virtual QString uuid() const
Returns the item identification string.
void addLayoutItem(QgsLayoutItem *item)
Adds an item to the layout.
Definition: qgslayout.cpp:539
QgsLayoutMeasurement convertFromLayoutUnits(double length, QgsUnitTypes::LayoutUnit unit) const
Converts a length measurement from the layout&#39;s native units to a specified target unit...
Definition: qgslayout.cpp:343
Stores information relating to the current rendering settings for a layout.
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
An interface for layout objects which can be stored and read from DOM elements.
~QgsLayout() override
Definition: qgslayout.cpp:49
void initializeDefaults()
Initializes an empty layout, e.g.
Definition: qgslayout.cpp:101
QgsProject * project() const
The project associated with the layout.
Definition: qgslayout.cpp:131
void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for the layout.
Definition: qgslayout.cpp:406
LayoutUnit
Layout measurement units.
Definition: qgsunittypes.h:159
virtual QDomElement writeXml(QDomDocument &document, const QgsReadWriteContext &context) const
Returns the layout&#39;s state encapsulated in a DOM element.
Definition: qgslayout.cpp:822
bool isLocked() const
Returns true if the item is locked, and cannot be interacted with using the mouse.
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
void setPageSize(const QgsLayoutSize &size)
Sets the size of the page.
double convertToLayoutUnits(QgsLayoutMeasurement measurement) const
Converts a measurement into the layout&#39;s native units.
Definition: qgslayout.cpp:328
A model for items attached to a layout.
Manages snapping grids and preset snap lines in a layout, and handles snapping points to the nearest ...
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
This class provides a method of storing sizes, consisting of a width and height, for use in QGIS layo...
Definition: qgslayoutsize.h:40
void changed()
Emitted when properties of the layout change.
QgsLayoutItem * layoutItemAt(QPointF position, bool ignoreLocked=false) const
Returns the topmost layout item at a specified position.
Definition: qgslayout.cpp:292
bool moveItemToTop(QgsLayoutItem *item, bool deferUpdate=false)
Raises an item up to the top of the z-order.
Definition: qgslayout.cpp:211
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
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
void reloadSettings()
Refreshes the layout when global layout related options change.
Definition: qgslayout.cpp:378
void addMultiFrame(QgsLayoutMultiFrame *multiFrame)
Adds a multiFrame to the layout.
Definition: qgslayout.cpp:571
QgsLayout(QgsProject *project)
Construct a new layout linked to the specified project.
Definition: qgslayout.cpp:35
static QgsLayoutPoint decodePoint(const QString &string)
Decodes a point from a string.
Item representing the paper in a layout.
friend class QgsLayoutItemDeleteUndoCommand
Definition: qgslayout.h:758