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