QGIS API Documentation 3.99.0-Master (d270888f95f)
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
19#include "qgsfillsymbol.h"
20#include "qgslayout.h"
21#include "qgslayoutframe.h"
22#include "qgslayoutundostack.h"
23#include "qgsmargins.h"
24#include "qgsreadwritecontext.h"
25#include "qgssymbollayerutils.h"
26
27#include <QString>
28
29#include "moc_qgslayoutpagecollection.cpp"
30
31using namespace Qt::StringLiterals;
32
34 : QObject( layout )
35 , mLayout( layout )
36 , mGuideCollection( new QgsLayoutGuideCollection( layout, this ) )
37{
38 createDefaultPageStyleSymbol();
39}
40
42{
43 const auto constMPages = mPages;
44 for ( QgsLayoutItemPage *page : constMPages )
45 {
46 mLayout->removeItem( page );
47 page->deleteLater();
48 }
49}
50
52{
53 if ( !symbol )
54 return;
55
56 mPageStyleSymbol.reset( static_cast<QgsFillSymbol *>( symbol->clone() ) );
57
58 for ( QgsLayoutItemPage *page : std::as_const( mPages ) )
59 {
60 page->setPageStyleSymbol( symbol->clone() );
61 page->update();
62 }
63}
64
66{
67 return mPageStyleSymbol.get();
68}
69
71{
72 mPreviousItemPositions.clear();
73 QList< QgsLayoutItem * > items;
74 mLayout->layoutItems( items );
75
76 for ( QgsLayoutItem *item : std::as_const( items ) )
77 {
78 if ( item->type() == QgsLayoutItemRegistry::LayoutPage )
79 continue;
80
81 mPreviousItemPositions.insert( item->uuid(), qMakePair( item->page(), item->pagePositionWithUnits() ) );
82 }
83}
84
86{
87 for ( auto it = mPreviousItemPositions.constBegin(); it != mPreviousItemPositions.constEnd(); ++it )
88 {
89 const QString key { it.key() };
90 if ( QgsLayoutItem *item = mLayout->itemByUuid( key ) )
91 {
92 if ( !mBlockUndoCommands )
93 item->beginCommand( QString() );
94
95 item->attemptMove( it.value().second, true, false, it.value().first );
96
97 // Item might have been deleted
98 if ( mLayout->itemByUuid( key ) )
99 {
100 if ( !mBlockUndoCommands )
101 item->endCommand();
102 }
103 else
104 {
105 item->cancelCommand();
106 }
107 }
108 }
109 mPreviousItemPositions.clear();
110}
111
113{
114 double currentY = 0;
115 QgsLayoutPoint p( 0, 0, mLayout->units() );
116 const auto constMPages = mPages;
117 for ( QgsLayoutItemPage *page : constMPages )
118 {
119 page->attemptMove( p );
120 currentY += mLayout->convertToLayoutUnits( page->pageSize() ).height() + spaceBetweenPages();
121 p.setY( currentY );
122 }
123 mLayout->guides().update();
124 mLayout->updateBounds();
125 emit changed();
126}
127
129{
130 double maxWidth = 0;
131 for ( QgsLayoutItemPage *page : mPages )
132 {
133 maxWidth = std::max( maxWidth, mLayout->convertToLayoutUnits( page->pageSize() ).width() );
134 }
135 return maxWidth;
136}
137
139{
140 double maxArea = 0;
141 QSizeF maxSize;
142 for ( QgsLayoutItemPage *page : mPages )
143 {
144 QSizeF pageSize = mLayout->convertToLayoutUnits( page->pageSize() );
145 double area = pageSize.width() * pageSize.height();
146 if ( area > maxArea )
147 {
148 maxArea = area;
149 maxSize = pageSize;
150 }
151 }
152 return maxSize;
153}
154
156{
157 QSizeF size;
158 for ( QgsLayoutItemPage *page : mPages )
159 {
160 QSizeF pageSize = mLayout->convertToLayoutUnits( page->pageSize() );
161 if ( !size.isValid() )
162 size = pageSize;
163 else
164 {
165 if ( !qgsDoubleNear( pageSize.width(), size.width(), 0.01 )
166 || !qgsDoubleNear( pageSize.height(), size.height(), 0.01 ) )
167 return false;
168 }
169 }
170 return true;
171}
172
174{
175 int pageNumber = 0;
176 double startNextPageY = 0;
177 const auto constMPages = mPages;
178 for ( QgsLayoutItemPage *page : constMPages )
179 {
180 startNextPageY += page->rect().height() + spaceBetweenPages();
181 if ( startNextPageY > point.y() )
182 break;
183 pageNumber++;
184 }
185
186 if ( pageNumber > mPages.count() - 1 )
187 pageNumber = mPages.count() - 1;
188 return pageNumber;
189}
190
192{
193 if ( mPages.empty() )
194 return 0;
195
196 int pageNumber = 0;
197 double startNextPageY = 0;
198 const auto constMPages = mPages;
199 for ( QgsLayoutItemPage *page : constMPages )
200 {
201 startNextPageY += page->rect().height() + spaceBetweenPages();
202 if ( startNextPageY >= point.y() )
203 break;
204 pageNumber++;
205 }
206
207 if ( startNextPageY >= point.y() )
208 {
209 // found an existing page
210 return pageNumber;
211 }
212
213 double lastPageHeight = mPages.last()->rect().height();
214 while ( startNextPageY < point.y() )
215 {
216 startNextPageY += lastPageHeight + spaceBetweenPages();
217 if ( startNextPageY >= point.y() )
218 break;
219 pageNumber++;
220 }
221
222 return pageNumber;
223}
224
226{
227 const QList< QGraphicsItem * > items = mLayout->items( point );
228 for ( QGraphicsItem *item : items )
229 {
230 if ( item->type() == QgsLayoutItemRegistry::LayoutPage )
231 {
232 QgsLayoutItemPage *page = static_cast< QgsLayoutItemPage * >( item );
233 if ( page->mapToScene( page->rect() ).boundingRect().contains( point ) )
234 return page;
235 }
236 }
237 return nullptr;
238}
239
241{
242 QPointF layoutUnitsPos = mLayout->convertToLayoutUnits( position );
243 if ( page > 0 && page < mPages.count() )
244 {
245 layoutUnitsPos.ry() += mPages.at( page )->pos().y();
246 }
247 return layoutUnitsPos;
248}
249
251{
252 double vDelta = 0.0;
253 if ( page > 0 && page < mPages.count() )
254 {
255 vDelta = mLayout->convertFromLayoutUnits( mPages.at( page )->pos().y(), position.units() ).length();
256 }
257
258 return QgsLayoutPoint( position.x(), position.y() + vDelta, position.units() );
259}
260
261QPointF QgsLayoutPageCollection::positionOnPage( QPointF position ) const
262{
263 double startCurrentPageY = 0;
264 double startNextPageY = 0;
265 int pageNumber = 0;
266 const auto constMPages = mPages;
267 for ( QgsLayoutItemPage *page : constMPages )
268 {
269 startCurrentPageY = startNextPageY;
270 startNextPageY += page->rect().height() + spaceBetweenPages();
271 if ( startNextPageY > position.y() )
272 break;
273 pageNumber++;
274 }
275
276 double y;
277 if ( pageNumber == mPages.size() )
278 {
279 //y coordinate is greater then the end of the last page, so return distance between
280 //top of last page and y coordinate
281 y = position.y() - ( startNextPageY - spaceBetweenPages() );
282 }
283 else
284 {
285 //y coordinate is less then the end of the last page
286 y = position.y() - startCurrentPageY;
287 }
288 return QPointF( position.x(), y );
289}
290
292{
293 return mLayout->convertToLayoutUnits( QgsLayoutMeasurement( 10 ) );
294}
295
297{
298 return spaceBetweenPages() / 2;
299}
300
302{
303 //calculate current bounds
304 QRectF bounds = mLayout->layoutBounds( true, 0.0 );
305 if ( bounds.isEmpty() )
306 return;
307
308 if ( !mBlockUndoCommands )
309 mLayout->undoStack()->beginCommand( this, tr( "Resize to Contents" ) );
310
311 for ( int page = mPages.count() - 1; page > 0; page-- )
312 {
313 deletePage( page );
314 }
315
316 if ( mPages.empty() )
317 {
318 auto page = std::make_unique< QgsLayoutItemPage >( mLayout );
319 addPage( page.release() );
320 }
321
322 QgsLayoutItemPage *page = mPages.at( 0 );
323
324 double marginLeft = mLayout->convertToLayoutUnits( QgsLayoutMeasurement( margins.left(), marginUnits ) );
325 double marginTop = mLayout->convertToLayoutUnits( QgsLayoutMeasurement( margins.top(), marginUnits ) );
326 double marginBottom = mLayout->convertToLayoutUnits( QgsLayoutMeasurement( margins.bottom(), marginUnits ) );
327 double marginRight = mLayout->convertToLayoutUnits( QgsLayoutMeasurement( margins.right(), marginUnits ) );
328
329 bounds.setWidth( bounds.width() + marginLeft + marginRight );
330 bounds.setHeight( bounds.height() + marginTop + marginBottom );
331
332 QgsLayoutSize newPageSize = mLayout->convertFromLayoutUnits( bounds.size(), mLayout->units() );
333 page->setPageSize( newPageSize );
334
335 reflow();
336
337 //also move all items so that top-left of bounds is at marginLeft, marginTop
338 double diffX = marginLeft - bounds.left();
339 double diffY = marginTop - bounds.top();
340
341 const QList<QGraphicsItem *> itemList = mLayout->items();
342 for ( QGraphicsItem *item : itemList )
343 {
344 if ( QgsLayoutItem *layoutItem = dynamic_cast<QgsLayoutItem *>( item ) )
345 {
346 QgsLayoutItemPage *pageItem = dynamic_cast<QgsLayoutItemPage *>( layoutItem );
347 if ( !pageItem )
348 {
349 layoutItem->beginCommand( tr( "Move Item" ) );
350 layoutItem->attemptMoveBy( diffX, diffY );
351 layoutItem->endCommand();
352 }
353 }
354 }
355
356 //also move guides
357 mLayout->undoStack()->beginCommand( &mLayout->guides(), tr( "Move Guides" ) );
358 const QList< QgsLayoutGuide * > verticalGuides = mLayout->guides().guides( Qt::Vertical );
359 for ( QgsLayoutGuide *guide : verticalGuides )
360 {
361 guide->setLayoutPosition( guide->layoutPosition() + diffX );
362 }
363 const QList< QgsLayoutGuide * > horizontalGuides = mLayout->guides().guides( Qt::Horizontal );
364 for ( QgsLayoutGuide *guide : horizontalGuides )
365 {
366 guide->setLayoutPosition( guide->layoutPosition() + diffY );
367 }
368 mLayout->undoStack()->endCommand();
369
370 if ( !mBlockUndoCommands )
371 mLayout->undoStack()->endCommand();
372}
373
374bool QgsLayoutPageCollection::writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context ) const
375{
376 QDomElement element = document.createElement( u"PageCollection"_s );
377
378 QDomElement pageStyleElem = QgsSymbolLayerUtils::saveSymbol( QString(), mPageStyleSymbol.get(), document, context );
379 element.appendChild( pageStyleElem );
380
381 for ( const QgsLayoutItemPage *page : mPages )
382 {
383 page->writeXml( element, document, context );
384 }
385
386 mGuideCollection->writeXml( element, document, context );
387
388 parentElement.appendChild( element );
389 return true;
390}
391
392bool QgsLayoutPageCollection::readXml( const QDomElement &e, const QDomDocument &document, const QgsReadWriteContext &context )
393{
394 QDomElement element = e;
395 if ( element.nodeName() != "PageCollection"_L1 )
396 {
397 element = element.firstChildElement( u"PageCollection"_s );
398 }
399
400 if ( element.nodeName() != "PageCollection"_L1 )
401 {
402 return false;
403 }
404
405 mBlockUndoCommands = true;
406
407 int i = 0;
408 for ( QgsLayoutItemPage *page : std::as_const( mPages ) )
409 {
410 emit pageAboutToBeRemoved( i );
411 mLayout->removeItem( page );
412 page->deleteLater();
413 ++i;
414 }
415 mPages.clear();
416
417 QDomElement pageStyleSymbolElem = element.firstChildElement( u"symbol"_s );
418 if ( !pageStyleSymbolElem.isNull() )
419 {
420 mPageStyleSymbol = QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( pageStyleSymbolElem, context );
421 }
422
423 QDomNodeList pageList = element.elementsByTagName( u"LayoutItem"_s );
424 for ( int i = 0; i < pageList.size(); ++i )
425 {
426 QDomElement pageElement = pageList.at( i ).toElement();
427 auto page = std::make_unique<QgsLayoutItemPage>( mLayout );
428 if ( mPageStyleSymbol )
429 page->setPageStyleSymbol( mPageStyleSymbol->clone() );
430 page->readXml( pageElement, document, context );
431 page->finalizeRestoreFromXml();
432 mPages.append( page.get() );
433 mLayout->addItem( page.release() );
434 }
435
436 reflow();
437
438 mGuideCollection->readXml( element, document, context );
439
440 mBlockUndoCommands = false;
441 return true;
442}
443
445{
446 return *mGuideCollection;
447}
448
450{
451 return *mGuideCollection;
452}
453
455{
456 QgsLayoutItemPage *referencePage = page( sourcePage );
457 if ( !referencePage )
458 {
459 return;
460 }
461
462 mLayout->undoStack()->beginCommand( this, tr( "Apply page properties" ) );
463 mBlockUndoCommands = true;
464
465 for ( QgsLayoutItemPage *page : mPages )
466 {
467 if ( page == referencePage )
468 {
469 continue;
470 }
471 page->setPageSize( referencePage->pageSize() );
472 page->setPageStyleSymbol( referencePage->pageStyleSymbol()->clone() );
473 }
474
475 mLayout->undoStack()->endCommand();
476 mBlockUndoCommands = false;
477 mLayout->refresh();
478}
479
481{
482 const auto constMPages = mPages;
483 for ( QgsLayoutItemPage *page : constMPages )
484 {
485 page->redraw();
486 }
487}
488
490{
491 return mLayout;
492}
493
494QList<QgsLayoutItemPage *> QgsLayoutPageCollection::pages()
495{
496 return mPages;
497}
498
500{
501 return mPages.count();
502}
503
505{
506 return mPages.value( pageNumber );
507}
508
510{
511 return mPages.value( pageNumber );
512}
513
515{
516 return mPages.indexOf( page );
517}
518
519QList<QgsLayoutItemPage *> QgsLayoutPageCollection::visiblePages( const QRectF &region ) const
520{
521 QList<QgsLayoutItemPage *> pages;
522 const auto constMPages = mPages;
523 for ( QgsLayoutItemPage *page : constMPages )
524 {
525 if ( page->mapToScene( page->rect() ).boundingRect().intersects( region ) )
526 pages << page;
527 }
528 return pages;
529}
530
531QList<int> QgsLayoutPageCollection::visiblePageNumbers( const QRectF &region ) const
532{
533 QList< int > pages;
534 int p = 0;
535 const auto constMPages = mPages;
536 for ( QgsLayoutItemPage *page : constMPages )
537 {
538 if ( page->mapToScene( page->rect() ).boundingRect().intersects( region ) )
539 pages << p;
540 p++;
541 }
542 return pages;
543}
544
546{
547 //get all items on page
548 const QList<QgsLayoutItem *> items = mLayout->pageCollection()->itemsOnPage( page );
549
550 //loop through and check for non-paper items
551 for ( QgsLayoutItem *item : items )
552 {
553 //is item a paper item?
554 if ( item->type() != QgsLayoutItemRegistry::LayoutPage )
555 {
556 //item is not a paper item, so we have other items on the page
557 return false;
558 }
559 }
560 //no non-paper items
561 return true;
562}
563
564QList<QgsLayoutItem *> QgsLayoutPageCollection::itemsOnPage( int page ) const
565{
566 QList<QgsLayoutItem *> itemList;
567 const QList<QGraphicsItem *> graphicsItemList = mLayout->items();
568 itemList.reserve( graphicsItemList.size() );
569 for ( QGraphicsItem *graphicsItem : graphicsItemList )
570 {
571 QgsLayoutItem *item = dynamic_cast<QgsLayoutItem *>( graphicsItem );
572 if ( item && item->page() == page )
573 {
574 itemList.push_back( item );
575 }
576 }
577 return itemList;
578}
579
581{
582 if ( page >= mPages.count() || page < 0 )
583 {
584 //page number out of range, of course we shouldn't export it - stop smoking crack!
585 return false;
586 }
587
588 QgsLayoutItemPage *pageItem = mPages.at( page );
589 if ( !pageItem->shouldDrawItem() )
590 return false;
591
592 //check all frame items on page
593 QList<QgsLayoutFrame *> frames;
594 itemsOnPage( frames, page );
595 for ( QgsLayoutFrame *frame : std::as_const( frames ) )
596 {
597 if ( frame->hidePageIfEmpty() && frame->isEmpty() )
598 {
599 //frame is set to hide page if empty, and frame is empty, so we don't want to export this page
600 return false;
601 }
602 }
603 return true;
604}
605
607{
608 if ( !mBlockUndoCommands )
609 mLayout->undoStack()->beginCommand( this, tr( "Add Page" ) );
610 mPages.append( page );
611 mLayout->addItem( page );
612 reflow();
613 if ( !mBlockUndoCommands )
614 mLayout->undoStack()->endCommand();
615}
616
618{
619 if ( mPages.empty() )
620 return nullptr;
621
622 QgsLayoutItemPage *lastPage = mPages.at( mPages.count() - 1 );
623 auto newPage = std::make_unique< QgsLayoutItemPage >( mLayout );
624 newPage->attemptResize( lastPage->sizeWithUnits() );
625 addPage( newPage.release() );
626 return mPages.at( mPages.count() - 1 );
627}
628
630{
631 if ( !mBlockUndoCommands )
632 {
633 mLayout->undoStack()->beginMacro( tr( "Add Page" ) );
634 mLayout->undoStack()->beginCommand( this, tr( "Add Page" ) );
635 }
636
637 if ( beforePage < 0 )
638 beforePage = 0;
639
641 if ( beforePage >= mPages.count() )
642 {
643 mPages.append( page );
644 }
645 else
646 {
647 mPages.insert( beforePage, page );
648 }
649 mLayout->addItem( page );
650 reflow();
651
652 // bump up stored page numbers to account
653 for ( auto it = mPreviousItemPositions.begin(); it != mPreviousItemPositions.end(); ++it ) // clazy:exclude=detaching-member
654 {
655 if ( it.value().first < beforePage )
656 continue;
657
658 it.value().first = it.value().first + 1;
659 }
660
662 if ( ! mBlockUndoCommands )
663 {
664 mLayout->undoStack()->endCommand();
665 mLayout->undoStack()->endMacro();
666 }
667}
668
670{
671 if ( pageNumber < 0 || pageNumber >= mPages.count() )
672 return;
673
674 if ( !mBlockUndoCommands )
675 {
676 mLayout->undoStack()->beginMacro( tr( "Remove Page" ) );
677 mLayout->undoStack()->beginCommand( this, tr( "Remove Page" ) );
678 }
681 QgsLayoutItemPage *page = mPages.takeAt( pageNumber );
682 mLayout->removeItem( page );
683 page->deleteLater();
684 reflow();
685
686 // bump stored page numbers to account
687 for ( auto it = mPreviousItemPositions.begin(); it != mPreviousItemPositions.end(); ++it ) // clazy:exclude=detaching-member
688 {
689 if ( it.value().first <= pageNumber )
690 continue;
691
692 it.value().first = it.value().first - 1;
693 }
694
696 if ( ! mBlockUndoCommands )
697 {
698 mLayout->undoStack()->endCommand();
699 mLayout->undoStack()->endMacro();
700 }
701}
702
704{
705 if ( !mPages.contains( page ) )
706 return;
707
708 if ( !mBlockUndoCommands )
709 {
710 mLayout->undoStack()->beginMacro( tr( "Remove Page" ) );
711 mLayout->undoStack()->beginCommand( this, tr( "Remove Page" ) );
712 }
713 int pageIndex = mPages.indexOf( page );
714 emit pageAboutToBeRemoved( pageIndex );
716 mPages.removeAll( page );
717 page->deleteLater();
718 // remove immediately from scene -- otherwise immediately calculation of layout bounds (such as is done
719 // in reflow) will still consider the page, at least until it's actually deleted at the next event loop
720 mLayout->removeItem( page );
721 reflow();
722
723 // bump stored page numbers to account
724 for ( auto it = mPreviousItemPositions.begin(); it != mPreviousItemPositions.end(); ++it ) // clazy:exclude=detaching-member
725 {
726 if ( it.value().first <= pageIndex )
727 continue;
728
729 it.value().first = it.value().first - 1;
730 }
731
733 if ( !mBlockUndoCommands )
734 {
735 mLayout->undoStack()->endCommand();
736 mLayout->undoStack()->endMacro();
737 }
738}
739
741{
742 if ( !mBlockUndoCommands )
743 {
744 mLayout->undoStack()->beginMacro( tr( "Remove Pages" ) );
745 mLayout->undoStack()->beginCommand( this, tr( "Remove Pages" ) );
746 }
747 for ( int i = mPages.count() - 1; i >= 0; --i )
748 {
749 emit pageAboutToBeRemoved( i );
750 mPages.takeAt( i )->deleteLater();
751 }
752 reflow();
753 if ( !mBlockUndoCommands )
754 {
755 mLayout->undoStack()->endCommand();
756 mLayout->undoStack()->endMacro();
757 }
758}
759
761{
762 mPages.removeAll( page );
763 return page;
764}
765
766void QgsLayoutPageCollection::createDefaultPageStyleSymbol()
767{
768 QVariantMap properties;
769 properties.insert( u"color"_s, u"white"_s );
770 properties.insert( u"style"_s, u"solid"_s );
771 properties.insert( u"style_border"_s, u"no"_s );
772 properties.insert( u"joinstyle"_s, u"miter"_s );
773 mPageStyleSymbol = QgsFillSymbol::createSimple( properties );
774}
775
LayoutUnit
Layout measurement units.
Definition qgis.h:5275
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static std::unique_ptr< 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.
Contains the configuration for a single snap guide used by a layout.
Item representing the paper in a layout.
QgsLayoutSize pageSize() const
Returns the size of the page.
const QgsFillSymbol * pageStyleSymbol() const
Returns the symbol to use for drawing the page background.
Base class for graphical items within a QgsLayout.
QgsLayoutSize sizeWithUnits() const
Returns the item's current size, including units.
int page() const
Returns the page the item is currently on, with the first page returning 0.
bool shouldDrawItem() const
Returns whether the item should be drawn in the current context.
Provides a method of storing measurements for use in QGIS layouts using a variety of different measur...
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.
void applyPropertiesToAllOtherPages(int sourcePage)
Apply the source page properties (size & background color) to all other pages.
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.
Provides a method of storing points, consisting of an x and y coordinate, for use in QGIS layouts.
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.
Provides a method of storing sizes, consisting of a width and height, for use in QGIS layouts.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition qgslayout.h:50
Defines the four margins of a rectangle.
Definition qgsmargins.h:40
double top() const
Returns the top margin.
Definition qgsmargins.h:80
double right() const
Returns the right margin.
Definition qgsmargins.h:86
double bottom() const
Returns the bottom margin.
Definition qgsmargins.h:92
double left() const
Returns the left margin.
Definition qgsmargins.h:74
A container for the context for various read/write operations on objects.
static std::unique_ptr< QgsSymbol > loadSymbol(const QDomElement &element, const QgsReadWriteContext &context)
Attempts to load a symbol from a DOM element.
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:6900