QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgslayoutpagecollection.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutpagecollection.cpp
3  ----------------------------
4  begin : July 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 
18 #include "qgslayout.h"
19 #include "qgsreadwritecontext.h"
20 #include "qgsproject.h"
22 #include "qgssymbollayerutils.h"
23 #include "qgslayoutframe.h"
24 #include "qgslayoutundostack.h"
25 
27  : QObject( layout )
28  , mLayout( layout )
29  , mGuideCollection( new QgsLayoutGuideCollection( layout, this ) )
30 {
31  createDefaultPageStyleSymbol();
32 }
33 
35 {
36  Q_FOREACH ( QgsLayoutItemPage *page, mPages )
37  {
38  mLayout->removeItem( page );
39  page->deleteLater();
40  }
41 }
42 
44 {
45  if ( !symbol )
46  return;
47 
48  mPageStyleSymbol.reset( static_cast<QgsFillSymbol *>( symbol->clone() ) );
49 
50  for ( QgsLayoutItemPage *page : qgis::as_const( mPages ) )
51  {
52  page->update();
53  }
54 
55 }
56 
58 {
59  mPreviousItemPositions.clear();
60  QList< QgsLayoutItem * > items;
61  mLayout->layoutItems( items );
62 
63  for ( QgsLayoutItem *item : qgis::as_const( items ) )
64  {
65  if ( item->type() == QgsLayoutItemRegistry::LayoutPage )
66  continue;
67 
68  mPreviousItemPositions.insert( item->uuid(), qMakePair( item->page(), item->pagePositionWithUnits() ) );
69  }
70 }
71 
73 {
74  for ( auto it = mPreviousItemPositions.constBegin(); it != mPreviousItemPositions.constEnd(); ++it )
75  {
76  if ( QgsLayoutItem *item = mLayout->itemByUuid( it.key() ) )
77  {
78  if ( !mBlockUndoCommands )
79  item->beginCommand( QString() );
80  item->attemptMove( it.value().second, true, false, it.value().first );
81  if ( !mBlockUndoCommands )
82  item->endCommand();
83  }
84  }
85  mPreviousItemPositions.clear();
86 }
87 
89 {
90  double currentY = 0;
91  QgsLayoutPoint p( 0, 0, mLayout->units() );
92  Q_FOREACH ( QgsLayoutItemPage *page, mPages )
93  {
94  page->attemptMove( p );
95  currentY += mLayout->convertToLayoutUnits( page->pageSize() ).height() + spaceBetweenPages();
96  p.setY( currentY );
97  }
98  mLayout->guides().update();
99  mLayout->updateBounds();
100  emit changed();
101 }
102 
104 {
105  double maxWidth = 0;
106  for ( QgsLayoutItemPage *page : mPages )
107  {
108  maxWidth = std::max( maxWidth, mLayout->convertToLayoutUnits( page->pageSize() ).width() );
109  }
110  return maxWidth;
111 }
112 
114 {
115  double maxArea = 0;
116  QSizeF maxSize;
117  for ( QgsLayoutItemPage *page : mPages )
118  {
119  QSizeF pageSize = mLayout->convertToLayoutUnits( page->pageSize() );
120  double area = pageSize.width() * pageSize.height();
121  if ( area > maxArea )
122  {
123  maxArea = area;
124  maxSize = pageSize;
125  }
126  }
127  return maxSize;
128 }
129 
131 {
132  QSizeF size;
133  for ( QgsLayoutItemPage *page : mPages )
134  {
135  QSizeF pageSize = mLayout->convertToLayoutUnits( page->pageSize() );
136  if ( !size.isValid() )
137  size = pageSize;
138  else
139  {
140  if ( !qgsDoubleNear( pageSize.width(), size.width(), 0.01 )
141  || !qgsDoubleNear( pageSize.height(), size.height(), 0.01 ) )
142  return false;
143  }
144  }
145  return true;
146 }
147 
149 {
150  int pageNumber = 0;
151  double startNextPageY = 0;
152  Q_FOREACH ( QgsLayoutItemPage *page, mPages )
153  {
154  startNextPageY += page->rect().height() + spaceBetweenPages();
155  if ( startNextPageY > point.y() )
156  break;
157  pageNumber++;
158  }
159 
160  if ( pageNumber > mPages.count() - 1 )
161  pageNumber = mPages.count() - 1;
162  return pageNumber;
163 }
164 
166 {
167  if ( mPages.empty() )
168  return 0;
169 
170  int pageNumber = 0;
171  double startNextPageY = 0;
172  Q_FOREACH ( QgsLayoutItemPage *page, mPages )
173  {
174  startNextPageY += page->rect().height() + spaceBetweenPages();
175  if ( startNextPageY >= point.y() )
176  break;
177  pageNumber++;
178  }
179 
180  if ( startNextPageY >= point.y() )
181  {
182  // found an existing page
183  return pageNumber;
184  }
185 
186  double lastPageHeight = mPages.last()->rect().height();
187  while ( startNextPageY < point.y() )
188  {
189  startNextPageY += lastPageHeight + spaceBetweenPages();
190  if ( startNextPageY >= point.y() )
191  break;
192  pageNumber++;
193  }
194 
195  return pageNumber;
196 }
197 
199 {
200  const QList< QGraphicsItem * > items = mLayout->items( point );
201  for ( QGraphicsItem *item : items )
202  {
203  if ( item->type() == QgsLayoutItemRegistry::LayoutPage )
204  {
205  QgsLayoutItemPage *page = static_cast< QgsLayoutItemPage * >( item );
206  if ( page->mapToScene( page->rect() ).boundingRect().contains( point ) )
207  return page;
208  }
209  }
210  return nullptr;
211 }
212 
214 {
215  QPointF layoutUnitsPos = mLayout->convertToLayoutUnits( position );
216  if ( page > 0 && page < mPages.count() )
217  {
218  layoutUnitsPos.ry() += mPages.at( page )->pos().y();
219  }
220  return layoutUnitsPos;
221 }
222 
224 {
225  double vDelta = 0.0;
226  if ( page > 0 && page < mPages.count() )
227  {
228  vDelta = mLayout->convertFromLayoutUnits( mPages.at( page )->pos().y(), position.units() ).length();
229  }
230 
231  return QgsLayoutPoint( position.x(), position.y() + vDelta, position.units() );
232 }
233 
234 QPointF QgsLayoutPageCollection::positionOnPage( QPointF position ) const
235 {
236  double startCurrentPageY = 0;
237  double startNextPageY = 0;
238  int pageNumber = 0;
239  Q_FOREACH ( QgsLayoutItemPage *page, mPages )
240  {
241  startCurrentPageY = startNextPageY;
242  startNextPageY += page->rect().height() + spaceBetweenPages();
243  if ( startNextPageY > position.y() )
244  break;
245  pageNumber++;
246  }
247 
248  double y;
249  if ( pageNumber == mPages.size() )
250  {
251  //y coordinate is greater then the end of the last page, so return distance between
252  //top of last page and y coordinate
253  y = position.y() - ( startNextPageY - spaceBetweenPages() );
254  }
255  else
256  {
257  //y coordinate is less then the end of the last page
258  y = position.y() - startCurrentPageY;
259  }
260  return QPointF( position.x(), y );
261 }
262 
264 {
265  return mLayout->convertToLayoutUnits( QgsLayoutMeasurement( 10 ) );
266 }
267 
269 {
270  return spaceBetweenPages() / 2;
271 }
272 
274 {
275  if ( !mBlockUndoCommands )
276  mLayout->undoStack()->beginCommand( this, tr( "Resize to Contents" ) );
277 
278  //calculate current bounds
279  QRectF bounds = mLayout->layoutBounds( true, 0.0 );
280 
281  for ( int page = mPages.count() - 1; page > 0; page-- )
282  {
283  deletePage( page );
284  }
285 
286  if ( mPages.empty() )
287  {
288  std::unique_ptr< QgsLayoutItemPage > page = qgis::make_unique< QgsLayoutItemPage >( mLayout );
289  addPage( page.release() );
290  }
291 
292  QgsLayoutItemPage *page = mPages.at( 0 );
293 
294  double marginLeft = mLayout->convertToLayoutUnits( QgsLayoutMeasurement( margins.left(), marginUnits ) );
295  double marginTop = mLayout->convertToLayoutUnits( QgsLayoutMeasurement( margins.top(), marginUnits ) );
296  double marginBottom = mLayout->convertToLayoutUnits( QgsLayoutMeasurement( margins.bottom(), marginUnits ) );
297  double marginRight = mLayout->convertToLayoutUnits( QgsLayoutMeasurement( margins.right(), marginUnits ) );
298 
299  bounds.setWidth( bounds.width() + marginLeft + marginRight );
300  bounds.setHeight( bounds.height() + marginTop + marginBottom );
301 
302  QgsLayoutSize newPageSize = mLayout->convertFromLayoutUnits( bounds.size(), mLayout->units() );
303  page->setPageSize( newPageSize );
304 
305  reflow();
306 
307  //also move all items so that top-left of bounds is at marginLeft, marginTop
308  double diffX = marginLeft - bounds.left();
309  double diffY = marginTop - bounds.top();
310 
311  const QList<QGraphicsItem *> itemList = mLayout->items();
312  for ( QGraphicsItem *item : itemList )
313  {
314  if ( QgsLayoutItem *layoutItem = dynamic_cast<QgsLayoutItem *>( item ) )
315  {
316  QgsLayoutItemPage *pageItem = dynamic_cast<QgsLayoutItemPage *>( layoutItem );
317  if ( !pageItem )
318  {
319  layoutItem->beginCommand( tr( "Move Item" ) );
320  layoutItem->attemptMoveBy( diffX, diffY );
321  layoutItem->endCommand();
322  }
323  }
324  }
325 
326  //also move guides
327  mLayout->undoStack()->beginCommand( &mLayout->guides(), tr( "Move Guides" ) );
328  const QList< QgsLayoutGuide * > verticalGuides = mLayout->guides().guides( Qt::Vertical );
329  for ( QgsLayoutGuide *guide : verticalGuides )
330  {
331  guide->setLayoutPosition( guide->layoutPosition() + diffX );
332  }
333  const QList< QgsLayoutGuide * > horizontalGuides = mLayout->guides().guides( Qt::Horizontal );
334  for ( QgsLayoutGuide *guide : horizontalGuides )
335  {
336  guide->setLayoutPosition( guide->layoutPosition() + diffY );
337  }
338  mLayout->undoStack()->endCommand();
339 
340  if ( !mBlockUndoCommands )
341  mLayout->undoStack()->endCommand();
342 }
343 
344 bool QgsLayoutPageCollection::writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context ) const
345 {
346  QDomElement element = document.createElement( QStringLiteral( "PageCollection" ) );
347 
348  QDomElement pageStyleElem = QgsSymbolLayerUtils::saveSymbol( QString(), mPageStyleSymbol.get(), document, context );
349  element.appendChild( pageStyleElem );
350 
351  for ( const QgsLayoutItemPage *page : mPages )
352  {
353  page->writeXml( element, document, context );
354  }
355 
356  mGuideCollection->writeXml( element, document, context );
357 
358  parentElement.appendChild( element );
359  return true;
360 }
361 
362 bool QgsLayoutPageCollection::readXml( const QDomElement &e, const QDomDocument &document, const QgsReadWriteContext &context )
363 {
364  QDomElement element = e;
365  if ( element.nodeName() != QStringLiteral( "PageCollection" ) )
366  {
367  element = element.firstChildElement( QStringLiteral( "PageCollection" ) );
368  }
369 
370  if ( element.nodeName() != QStringLiteral( "PageCollection" ) )
371  {
372  return false;
373  }
374 
375  mBlockUndoCommands = true;
376 
377  int i = 0;
378  for ( QgsLayoutItemPage *page : qgis::as_const( mPages ) )
379  {
380  emit pageAboutToBeRemoved( i );
381  mLayout->removeItem( page );
382  page->deleteLater();
383  ++i;
384  }
385  mPages.clear();
386 
387  QDomElement pageStyleSymbolElem = element.firstChildElement( QStringLiteral( "symbol" ) );
388  if ( !pageStyleSymbolElem.isNull() )
389  {
390  mPageStyleSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( pageStyleSymbolElem, context ) );
391  }
392 
393  QDomNodeList pageList = element.elementsByTagName( QStringLiteral( "LayoutItem" ) );
394  for ( int i = 0; i < pageList.size(); ++i )
395  {
396  QDomElement pageElement = pageList.at( i ).toElement();
397  std::unique_ptr< QgsLayoutItemPage > page( new QgsLayoutItemPage( mLayout ) );
398  page->readXml( pageElement, document, context );
399  page->finalizeRestoreFromXml();
400  mPages.append( page.get() );
401  mLayout->addItem( page.release() );
402  }
403 
404  reflow();
405 
406  mGuideCollection->readXml( element, document, context );
407 
408  mBlockUndoCommands = false;
409  return true;
410 }
411 
413 {
414  return *mGuideCollection;
415 }
416 
418 {
419  return *mGuideCollection;
420 }
421 
423 {
424  Q_FOREACH ( QgsLayoutItemPage *page, mPages )
425  {
426  page->redraw();
427  }
428 }
429 
431 {
432  return mLayout;
433 }
434 
435 QList<QgsLayoutItemPage *> QgsLayoutPageCollection::pages()
436 {
437  return mPages;
438 }
439 
441 {
442  return mPages.count();
443 }
444 
446 {
447  return mPages.value( pageNumber );
448 }
449 
451 {
452  return mPages.value( pageNumber );
453 }
454 
456 {
457  return mPages.indexOf( page );
458 }
459 
460 QList<QgsLayoutItemPage *> QgsLayoutPageCollection::visiblePages( const QRectF &region ) const
461 {
462  QList<QgsLayoutItemPage *> pages;
463  Q_FOREACH ( QgsLayoutItemPage *page, mPages )
464  {
465  if ( page->mapToScene( page->rect() ).boundingRect().intersects( region ) )
466  pages << page;
467  }
468  return pages;
469 }
470 
471 QList<int> QgsLayoutPageCollection::visiblePageNumbers( const QRectF &region ) const
472 {
473  QList< int > pages;
474  int p = 0;
475  Q_FOREACH ( QgsLayoutItemPage *page, mPages )
476  {
477  if ( page->mapToScene( page->rect() ).boundingRect().intersects( region ) )
478  pages << p;
479  p++;
480  }
481  return pages;
482 }
483 
485 {
486  //get all items on page
487  const QList<QgsLayoutItem *> items = mLayout->pageCollection()->itemsOnPage( page );
488 
489  //loop through and check for non-paper items
490  for ( QgsLayoutItem *item : items )
491  {
492  //is item a paper item?
493  if ( item->type() != QgsLayoutItemRegistry::LayoutPage )
494  {
495  //item is not a paper item, so we have other items on the page
496  return false;
497  }
498  }
499  //no non-paper items
500  return true;
501 }
502 
503 QList<QgsLayoutItem *> QgsLayoutPageCollection::itemsOnPage( int page ) const
504 {
505  QList<QgsLayoutItem *> itemList;
506  const QList<QGraphicsItem *> graphicsItemList = mLayout->items();
507  itemList.reserve( graphicsItemList.size() );
508  for ( QGraphicsItem *graphicsItem : graphicsItemList )
509  {
510  QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
511  if ( item && item->page() == page )
512  {
513  itemList.push_back( item );
514  }
515  }
516  return itemList;
517 }
518 
520 {
521  if ( page >= mPages.count() || page < 0 )
522  {
523  //page number out of range, of course we shouldn't export it - stop smoking crack!
524  return false;
525  }
526 
527  QgsLayoutItemPage *pageItem = mPages.at( page );
528  if ( !pageItem->shouldDrawItem() )
529  return false;
530 
531  //check all frame items on page
532  QList<QgsLayoutFrame *> frames;
533  itemsOnPage( frames, page );
534  for ( QgsLayoutFrame *frame : qgis::as_const( frames ) )
535  {
536  if ( frame->hidePageIfEmpty() && frame->isEmpty() )
537  {
538  //frame is set to hide page if empty, and frame is empty, so we don't want to export this page
539  return false;
540  }
541  }
542  return true;
543 }
544 
546 {
547  if ( !mBlockUndoCommands )
548  mLayout->undoStack()->beginCommand( this, tr( "Add Page" ) );
549  mPages.append( page );
550  mLayout->addItem( page );
551  reflow();
552  if ( !mBlockUndoCommands )
553  mLayout->undoStack()->endCommand();
554 }
555 
557 {
558  if ( mPages.empty() )
559  return nullptr;
560 
561  QgsLayoutItemPage *lastPage = mPages.at( mPages.count() - 1 );
562  std::unique_ptr< QgsLayoutItemPage > newPage = qgis::make_unique< QgsLayoutItemPage >( mLayout );
563  newPage->attemptResize( lastPage->sizeWithUnits() );
564  addPage( newPage.release() );
565  return mPages.at( mPages.count() - 1 );
566 }
567 
569 {
570  if ( !mBlockUndoCommands )
571  {
572  mLayout->undoStack()->beginMacro( tr( "Add Page" ) );
573  mLayout->undoStack()->beginCommand( this, tr( "Add Page" ) );
574  }
575 
576  if ( beforePage < 0 )
577  beforePage = 0;
578 
580  if ( beforePage >= mPages.count() )
581  {
582  mPages.append( page );
583  }
584  else
585  {
586  mPages.insert( beforePage, page );
587  }
588  mLayout->addItem( page );
589  reflow();
590 
591  // bump up stored page numbers to account
592  for ( auto it = mPreviousItemPositions.begin(); it != mPreviousItemPositions.end(); ++it ) // clazy:exclude=detaching-member
593  {
594  if ( it.value().first < beforePage )
595  continue;
596 
597  it.value().first = it.value().first + 1;
598  }
599 
601  if ( ! mBlockUndoCommands )
602  {
603  mLayout->undoStack()->endCommand();
604  mLayout->undoStack()->endMacro();
605  }
606 }
607 
609 {
610  if ( pageNumber < 0 || pageNumber >= mPages.count() )
611  return;
612 
613  if ( !mBlockUndoCommands )
614  {
615  mLayout->undoStack()->beginMacro( tr( "Remove Page" ) );
616  mLayout->undoStack()->beginCommand( this, tr( "Remove Page" ) );
617  }
618  emit pageAboutToBeRemoved( pageNumber );
620  QgsLayoutItemPage *page = mPages.takeAt( pageNumber );
621  mLayout->removeItem( page );
622  page->deleteLater();
623  reflow();
624 
625  // bump stored page numbers to account
626  for ( auto it = mPreviousItemPositions.begin(); it != mPreviousItemPositions.end(); ++it ) // clazy:exclude=detaching-member
627  {
628  if ( it.value().first <= pageNumber )
629  continue;
630 
631  it.value().first = it.value().first - 1;
632  }
633 
635  if ( ! mBlockUndoCommands )
636  {
637  mLayout->undoStack()->endCommand();
638  mLayout->undoStack()->endMacro();
639  }
640 }
641 
643 {
644  if ( !mPages.contains( page ) )
645  return;
646 
647  if ( !mBlockUndoCommands )
648  {
649  mLayout->undoStack()->beginMacro( tr( "Remove Page" ) );
650  mLayout->undoStack()->beginCommand( this, tr( "Remove Page" ) );
651  }
652  int pageIndex = mPages.indexOf( page );
653  emit pageAboutToBeRemoved( pageIndex );
655  mPages.removeAll( page );
656  page->deleteLater();
657  reflow();
658 
659  // bump stored page numbers to account
660  for ( auto it = mPreviousItemPositions.begin(); it != mPreviousItemPositions.end(); ++it ) // clazy:exclude=detaching-member
661  {
662  if ( it.value().first <= pageIndex )
663  continue;
664 
665  it.value().first = it.value().first - 1;
666  }
667 
669  if ( !mBlockUndoCommands )
670  {
671  mLayout->undoStack()->endCommand();
672  mLayout->undoStack()->endMacro();
673  }
674 }
675 
677 {
678  if ( !mBlockUndoCommands )
679  {
680  mLayout->undoStack()->beginMacro( tr( "Remove Pages" ) );
681  mLayout->undoStack()->beginCommand( this, tr( "Remove Pages" ) );
682  }
683  for ( int i = mPages.count() - 1; i >= 0; --i )
684  {
685  emit pageAboutToBeRemoved( i );
686  mPages.takeAt( i )->deleteLater();
687  }
688  reflow();
689  if ( !mBlockUndoCommands )
690  {
691  mLayout->undoStack()->endCommand();
692  mLayout->undoStack()->endMacro();
693  }
694 }
695 
697 {
698  mPages.removeAll( page );
699  return page;
700 }
701 
702 void QgsLayoutPageCollection::createDefaultPageStyleSymbol()
703 {
704  QgsStringMap properties;
705  properties.insert( QStringLiteral( "color" ), QStringLiteral( "white" ) );
706  properties.insert( QStringLiteral( "style" ), QStringLiteral( "solid" ) );
707  properties.insert( QStringLiteral( "style_border" ), QStringLiteral( "no" ) );
708  properties.insert( QStringLiteral( "joinstyle" ), QStringLiteral( "miter" ) );
709  mPageStyleSymbol.reset( QgsFillSymbol::createSimple( properties ) );
710 }
711 
712 
int pageCount() const
Returns the number of pages in the collection.
The class is used as a container of context for various read/write operations on other objects...
bool writeXml(QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores the collection&#39;s state in a DOM element.
void pageAboutToBeRemoved(int pageNumber)
Emitted just before a page is removed from the collection.
void beginCommand(const QString &commandText, UndoCommand command=UndoNone)
Starts new undo command for this item.
QgsLayoutGuideCollection & guides()
Returns a reference to the layout&#39;s guide collection, which manages page snap guides.
Definition: qgslayout.cpp:382
Base class for graphical items within a QgsLayout.
bool pageIsEmpty(int page) const
Returns whether a given page index is empty, ie, it contains no items except for the background paper...
QgsLayoutItemPage * extendByNewPage()
Adds a new page to the end of the collection.
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:682
Contains the configuration for a single snap guide used by a layout.
QgsLayoutSize pageSize() const
Returns the size of the page.
QList< int > visiblePageNumbers(const QRectF &region) const
Returns a list of the page numbers which are visible within the specified region (in layout coordinat...
QgsLayoutItemPage * takePage(QgsLayoutItemPage *page)
Takes a page from the collection, returning ownership of the page to the caller.
void resizeToContents(const QgsMargins &margins, QgsUnitTypes::LayoutUnit marginUnits)
Resizes the layout to a single page which fits the current contents of the layout.
QRectF layoutBounds(bool ignorePages=false, double margin=0.0) const
Calculates the bounds of all non-gui items in the layout.
Definition: qgslayout.cpp:466
static QgsFillSymbol * createSimple(const QgsStringMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties. ...
Definition: qgssymbol.cpp:1150
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:278
double pageShadowWidth() const
Returns the size of the page shadow, in layout units.
void clear()
Removes all pages from the collection.
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:341
void setPageStyleSymbol(QgsFillSymbol *symbol)
Sets the symbol to use for drawing pages in the collection.
void redraw() override
QgsLayoutGuideCollection & guides()
Returns a reference to the collection&#39;s guide collection, which manages page snap guides...
double x() const
Returns x coordinate of point.
QList< QgsLayoutItemPage * > pages()
Returns a list of pages in the collection.
void changed()
Emitted when pages are added or removed from the collection.
bool writeXml(QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context) const
Stores the item state in a DOM element.
double left() const
Returns the left margin.
Definition: qgsmargins.h:72
void updateBounds()
Updates the scene bounds of the layout.
Definition: qgslayout.cpp:1081
QMap< QString, QString > QgsStringMap
Definition: qgis.h:577
QgsLayoutSize sizeWithUnits() const
Returns the item&#39;s current size, including units.
QPointF pagePositionToLayoutPosition(int page, const QgsLayoutPoint &position) const
Converts a position on a page to an absolute position in layout coordinates.
void layoutItems(QList< T * > &itemList) const
Returns a list of layout items of a specific type.
Definition: qgslayout.h:121
QgsLayoutItem * itemByUuid(const QString &uuid, bool includeTemplateUuids=false) const
Returns the layout item with matching uuid unique identifier, or a nullptr if a matching item could n...
Definition: qgslayout.cpp:235
void beginPageSizeChange()
Should be called before changing any page item sizes, and followed by a call to endPageSizeChange().
This class provides a method of storing points, consisting of an x and y coordinate, for use in QGIS layouts.
void endCommand()
Saves final state of an object and pushes the active command to the undo history. ...
QgsLayoutItemPage * page(int pageNumber)
Returns a specific page (by pageNumber) from the collection.
This class provides a method of storing measurements for use in QGIS layouts using a variety of diffe...
QgsFillSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:1952
QgsLayoutPageCollection * pageCollection()
Returns a pointer to the layout&#39;s page collection, which stores and manages page items in the layout...
Definition: qgslayout.cpp:456
double maximumPageWidth() const
Returns the maximum width of pages in the collection.
QgsLayoutItemPage * pageAtPoint(QPointF point) const
Returns the page at a specified point (in layout coordinates).
Stores and manages the snap guides used by a layout.
bool readXml(const QDomElement &collectionElement, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets the collection&#39;s state from a DOM element.
void redraw()
Triggers a redraw for all pages.
QSizeF maximumPageSize() const
Returns the maximum size of any page in the collection, by area.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:49
QPointF positionOnPage(QPointF point) const
Returns the position within a page of a point in the layout (in layout units).
void beginMacro(const QString &commandText)
Starts a macro command, with the given descriptive commandText.
int pageNumberForPoint(QPointF point) const
Returns the page number corresponding to a point in the layout (in layout units). ...
void beginCommand(QgsLayoutUndoObjectInterface *object, const QString &commandText, int id=0)
Begins a new undo command for the specified object.
QList< QgsLayoutItem * > itemsOnPage(int page) const
Returns a list of layout items on the specified page index.
QList< QgsLayoutGuide * > guides()
Returns a list of all guides contained in the collection.
bool shouldExportPage(int page) const
Returns whether the specified page number should be included in exports of the layouts.
int page() const
Returns the page the item is currently on, with the first page returning 0.
QgsLayoutPoint pagePositionToAbsolute(int page, const QgsLayoutPoint &position) const
Converts a position on a page to an absolute position in (maintaining the units from the input positi...
double right() const
Returns the right margin.
Definition: qgsmargins.h:84
bool shouldDrawItem() const
Returns whether the item should be drawn in the current context.
double bottom() const
Returns the bottom margin.
Definition: qgsmargins.h:90
double top() const
Returns the top margin.
Definition: qgsmargins.h:78
void insertPage(QgsLayoutItemPage *page, int beforePage)
Inserts a page into a specific position in the collection.
virtual void attemptMove(const QgsLayoutPoint &point, bool useReferencePoint=true, bool includesFrame=false, int page=-1)
Attempts to move the item to a specified point.
int pageNumber(QgsLayoutItemPage *page) const
Returns the page number for the specified page, or -1 if the page is not contained in the collection...
void update()
Updates the position (and visibility) of all guide line items.
QList< QgsLayoutItemPage * > visiblePages(const QRectF &region) const
Returns a list of the pages which are visible within the specified region (in layout coordinates)...
static QDomElement saveSymbol(const QString &symbolName, QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
LayoutUnit
Layout measurement units.
Definition: qgsunittypes.h:124
QgsUnitTypes::LayoutUnit units() const
Returns the native units for the layout.
Definition: qgslayout.h:328
void addPage(QgsLayoutItemPage *page)
Adds a page to the collection.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgssymbol.h:1003
int predictPageNumberForPoint(QPointF point) const
Returns the theoretical page number corresponding to a point in the layout (in layout units)...
void deletePage(int pageNumber)
Deletes a page from the collection.
void endPageSizeChange()
Should be called after changing any page item sizes, and preceded by a call to beginPageSizeChange()...
double spaceBetweenPages() const
Returns the space between pages, in layout units.
void endMacro()
Ends a macro command.
QgsLayoutPageCollection(QgsLayout *layout)
Constructor for QgsLayoutItemPage, with the specified parent layout.
void reflow()
Forces the page collection to reflow the arrangement of pages, e.g.
This class provides a method of storing sizes, consisting of a width and height, for use in QGIS layo...
Definition: qgslayoutsize.h:40
Base class for frame items, which form a layout multiframe item.
bool hasUniformPageSizes() const
Returns true if the layout has uniform page sizes, e.g.
QgsLayout * layout() override
Returns the layout the object belongs to.
QgsUnitTypes::LayoutUnit units() const
Returns the units for the point.
double y() const
Returns y coordinate of point.
The QgsMargins class defines the four margins of a rectangle.
Definition: qgsmargins.h:37
double convertToLayoutUnits(QgsLayoutMeasurement measurement) const
Converts a measurement into the layout&#39;s native units.
Definition: qgslayout.cpp:326
Item representing the paper in a layout.