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