QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgslayoutmultiframe.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayoutmultiframe.cpp
3 -----------------------
4 begin : October 2017
5 copyright : (C) 2017 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgslayoutmultiframe.h"
18#include "qgslayoutframe.h"
19#include "qgslayout.h"
21#include "qgslayoutundostack.h"
23#include <QUuid>
24
26 : QgsLayoutObject( layout )
27 , mUuid( QUuid::createUuid().toString() )
28{
29 mLayout->addMultiFrame( this );
30
31 connect( mLayout->pageCollection(), &QgsLayoutPageCollection::changed, this, &QgsLayoutMultiFrame::handlePageChange );
32}
33
35{
37}
38
39QSizeF QgsLayoutMultiFrame::fixedFrameSize( const int frameIndex ) const
40{
41 Q_UNUSED( frameIndex )
42 return QSizeF( 0, 0 );
43}
44
45QSizeF QgsLayoutMultiFrame::minFrameSize( const int frameIndex ) const
46{
47 Q_UNUSED( frameIndex )
48 return QSizeF( 0, 0 );
49}
50
52{
53 return yPos;
54}
55
56void QgsLayoutMultiFrame::addFrame( QgsLayoutFrame *frame, bool recalcFrameSizes )
57{
58 if ( !frame || mFrameItems.contains( frame ) )
59 return;
60
61 mFrameItems.push_back( frame );
62 frame->mMultiFrame = this;
64 connect( frame, &QgsLayoutFrame::destroyed, this, [this, frame ]
65 {
66 handleFrameRemoval( frame );
67 } );
68 if ( mLayout && !frame->scene() )
69 {
70 mLayout->addLayoutItem( frame );
71 }
72
73 if ( recalcFrameSizes )
74 {
76 }
77}
78
80{
81 if ( mode != mResizeMode )
82 {
83 mLayout->undoStack()->beginMacro( tr( "Change Resize Mode" ) );
84 mResizeMode = mode;
86 mLayout->undoStack()->endMacro();
87 emit changed();
88 }
89}
90
91QList<QgsLayoutFrame *> QgsLayoutMultiFrame::frames() const
92{
93 return mFrameItems;
94}
95
97{
98 if ( mFrameItems.empty() )
99 {
100 return;
101 }
102
103 QSizeF size = totalSize();
104 double totalHeight = size.height();
105
106 if ( totalHeight < 1 )
107 {
108 return;
109 }
110
111 if ( mBlockUndoCommands )
112 mLayout->undoStack()->blockCommands( true );
113
114 double currentY = 0;
115 double currentHeight = 0;
116 QgsLayoutFrame *currentItem = nullptr;
117
118 for ( int i = 0; i < mFrameItems.size(); ++i )
119 {
120 if ( mResizeMode != RepeatOnEveryPage && currentY >= totalHeight )
121 {
122 if ( mResizeMode == RepeatUntilFinished || mResizeMode == ExtendToNextPage ) //remove unneeded frames in extent mode
123 {
124 bool removingPages = true;
125 for ( int j = mFrameItems.size(); j > i; --j )
126 {
127 int numPagesBefore = mLayout->pageCollection()->pageCount();
128 removeFrame( j - 1, removingPages );
129 //if removing the frame didn't also remove the page, then stop removing pages
130 removingPages = removingPages && ( mLayout->pageCollection()->pageCount() < numPagesBefore );
131 }
132 return;
133 }
134 }
135
136 currentItem = mFrameItems.value( i );
137 currentHeight = currentItem->rect().height();
139 {
140 currentItem->setContentSection( QRectF( 0, 0, currentItem->rect().width(), currentHeight ) );
141 }
142 else
143 {
144 currentHeight = findNearbyPageBreak( currentY + currentHeight ) - currentY;
145 currentItem->setContentSection( QRectF( 0, currentY, currentItem->rect().width(), currentHeight ) );
146 }
147 currentItem->update();
148 currentY += currentHeight;
149 }
150
151 //at end of frames but there is still content left. Add other pages if ResizeMode ==
152 if ( mLayout->pageCollection()->pageCount() > 0 && currentItem && mResizeMode != UseExistingFrames )
153 {
154 while ( ( mResizeMode == RepeatOnEveryPage ) || currentY < totalHeight )
155 {
156 //find out on which page the lower left point of the last frame is
157 int page = mLayout->pageCollection()->predictPageNumberForPoint( QPointF( 0, currentItem->pos().y() + currentItem->rect().height() ) ) + 1;
158
160 {
161 if ( page >= mLayout->pageCollection()->pageCount() )
162 {
163 break;
164 }
165 }
166 else
167 {
168 //add new pages if required
169 for ( int p = mLayout->pageCollection()->pageCount() - 1 ; p < page; ++p )
170 {
171 mLayout->pageCollection()->extendByNewPage();
172 }
173 }
174
175 double currentPageHeight = mLayout->pageCollection()->page( page )->rect().height();
176
177 double frameHeight = 0;
178 switch ( mResizeMode )
179 {
182 {
183 frameHeight = currentItem->rect().height();
184 break;
185 }
186 case ExtendToNextPage:
187 {
188 frameHeight = ( currentY + currentPageHeight ) > totalHeight ? totalHeight - currentY : currentPageHeight;
189 break;
190 }
191
193 break;
194 }
195
196 double newFrameY = mLayout->pageCollection()->page( page )->pos().y();
198 {
199 newFrameY += currentItem->pagePos().y();
200 }
201
202 //create new frame
203 QgsLayoutFrame *newFrame = createNewFrame( currentItem,
204 QPointF( currentItem->pos().x(), newFrameY ),
205 QSizeF( currentItem->rect().width(), frameHeight ) );
206
208 {
209 newFrame->setContentSection( QRectF( 0, 0, newFrame->rect().width(), newFrame->rect().height() ) );
210 currentY += frameHeight;
211 }
212 else
213 {
214 double contentHeight = findNearbyPageBreak( currentY + newFrame->rect().height() ) - currentY;
215 newFrame->setContentSection( QRectF( 0, currentY, newFrame->rect().width(), contentHeight ) );
216 currentY += contentHeight;
217 }
218
219 currentItem = newFrame;
220 }
221 }
222
223 if ( mBlockUndoCommands )
224 mLayout->undoStack()->blockCommands( false );
225}
226
228{
229 if ( mFrameItems.empty() )
230 {
231 //no frames, nothing to do
232 return;
233 }
234
235 const QList< QgsLayoutFrame * > frames = mFrameItems;
236 for ( QgsLayoutFrame *frame : frames )
237 {
239 }
240}
241
243{
244
245}
246
247QgsLayoutFrame *QgsLayoutMultiFrame::createNewFrame( QgsLayoutFrame *currentFrame, QPointF pos, QSizeF size )
248{
249 if ( !currentFrame )
250 {
251 return nullptr;
252 }
253
254 QgsLayoutFrame *newFrame = new QgsLayoutFrame( mLayout, this );
255 newFrame->attemptSetSceneRect( QRectF( pos.x(), pos.y(), size.width(), size.height() ) );
256
257 //copy some settings from the parent frame
258 newFrame->setBackgroundColor( currentFrame->backgroundColor() );
259 newFrame->setBackgroundEnabled( currentFrame->hasBackground() );
260 newFrame->setBlendMode( currentFrame->blendMode() );
261 newFrame->setFrameEnabled( currentFrame->frameEnabled() );
262 newFrame->setFrameStrokeColor( currentFrame->frameStrokeColor() );
263 newFrame->setFrameJoinStyle( currentFrame->frameJoinStyle() );
264 newFrame->setFrameStrokeWidth( currentFrame->frameStrokeWidth() );
265 newFrame->setItemOpacity( currentFrame->itemOpacity() );
266 newFrame->setHideBackgroundIfEmpty( currentFrame->hideBackgroundIfEmpty() );
267
268 addFrame( newFrame, false );
269
270 return newFrame;
271}
272
274{
275 return tr( "<Multiframe>" );
276}
277
278QgsAbstractLayoutUndoCommand *QgsLayoutMultiFrame::createCommand( const QString &text, int id, QUndoCommand *parent )
279{
280 return new QgsLayoutMultiFrameUndoCommand( this, text, id, parent );
281}
282
284{
287 return context;
288}
289
291{
292 if ( !mLayout )
293 return;
294
295 mLayout->undoStack()->beginCommand( this, commandText, command );
296}
297
299{
300 if ( mLayout )
301 mLayout->undoStack()->endCommand();
302}
303
305{
306 if ( mLayout )
307 mLayout->undoStack()->cancelCommand();
308}
309
311{
312 for ( int i = 0; i < mFrameUuids.count(); ++i )
313 {
314 QgsLayoutFrame *frame = nullptr;
315 const QString uuid = mFrameUuids.at( i );
316 if ( !uuid.isEmpty() )
317 {
318 QgsLayoutItem *item = mLayout->itemByUuid( uuid, true );
319 frame = qobject_cast< QgsLayoutFrame * >( item );
320 }
321 if ( !frame )
322 {
323 const QString templateUuid = mFrameTemplateUuids.at( i );
324 if ( !templateUuid.isEmpty() )
325 {
326 QgsLayoutItem *item = mLayout->itemByTemplateUuid( templateUuid );
327 frame = qobject_cast< QgsLayoutFrame * >( item );
328 }
329 }
330
331 if ( frame )
332 {
333 addFrame( frame );
334 }
335 }
336}
337
339{
342}
343
344void QgsLayoutMultiFrame::handleFrameRemoval( QgsLayoutFrame *frame )
345{
346 if ( mBlockUpdates )
347 return;
348
349 if ( !frame )
350 {
351 return;
352 }
353 int index = mFrameItems.indexOf( frame );
354 if ( index == -1 )
355 {
356 return;
357 }
358
359 mFrameItems.removeAt( index );
360 if ( !mFrameItems.isEmpty() )
361 {
362 if ( resizeMode() != QgsLayoutMultiFrame::RepeatOnEveryPage && !mIsRecalculatingSize )
363 {
364 //removing a frame forces the multi frame to UseExistingFrames resize mode
365 //otherwise the frame may not actually be removed, leading to confusing ui behavior
367 emit changed();
369 }
370 }
371}
372
373void QgsLayoutMultiFrame::handlePageChange()
374{
375 if ( mLayout->pageCollection()->pageCount() < 1 )
376 {
377 return;
378 }
379
381 {
382 return;
383 }
384
385 //remove items beginning on non-existing pages
386 for ( int i = mFrameItems.size() - 1; i >= 0; --i )
387 {
389 int page = mLayout->pageCollection()->predictPageNumberForPoint( frame->pos() );
390 if ( page >= mLayout->pageCollection()->pageCount() )
391 {
392 removeFrame( i );
393 }
394 }
395
396 if ( !mFrameItems.empty() )
397 {
398 //page number of the last item
399 QgsLayoutFrame *lastFrame = mFrameItems.last();
400 int lastItemPage = mLayout->pageCollection()->predictPageNumberForPoint( lastFrame->pos() );
401
402 for ( int i = lastItemPage + 1; i < mLayout->pageCollection()->pageCount(); ++i )
403 {
404 //copy last frame to current page
405 std::unique_ptr< QgsLayoutFrame > newFrame = std::make_unique< QgsLayoutFrame >( mLayout, this );
406
407 newFrame->attemptSetSceneRect( QRectF( lastFrame->pos().x(),
408 mLayout->pageCollection()->page( i )->pos().y() + lastFrame->pagePos().y(),
409 lastFrame->rect().width(), lastFrame->rect().height() ) );
410 lastFrame = newFrame.get();
411 addFrame( newFrame.release(), false );
412 }
413 }
414
416 update();
417}
418
419void QgsLayoutMultiFrame::removeFrame( int i, const bool removeEmptyPages )
420{
421 if ( i >= mFrameItems.count() )
422 {
423 return;
424 }
425
426 QgsLayoutFrame *frameItem = mFrameItems.at( i );
427 if ( mLayout )
428 {
429 mIsRecalculatingSize = true;
430 int pageNumber = frameItem->page();
431 //remove item, but don't create undo command
432 mLayout->undoStack()->blockCommands( true );
433 mLayout->removeLayoutItem( frameItem );
434 //if frame was the only item on the page, remove the page
435 if ( removeEmptyPages && mLayout->pageCollection()->pageIsEmpty( pageNumber ) )
436 {
437 mLayout->pageCollection()->deletePage( pageNumber );
438 }
439 mLayout->undoStack()->blockCommands( false );
440 mIsRecalculatingSize = false;
441 }
442
443 if ( i >= mFrameItems.count() )
444 {
445 return;
446 }
447
448 mFrameItems.removeAt( i );
449}
450
452{
453 for ( QgsLayoutFrame *frame : std::as_const( mFrameItems ) )
454 {
455 frame->update();
456 }
457}
458
460{
461 mBlockUpdates = true;
462 ResizeMode bkResizeMode = mResizeMode;
464 mLayout->undoStack()->blockCommands( true );
465 for ( QgsLayoutFrame *frame : std::as_const( mFrameItems ) )
466 {
467 mLayout->removeLayoutItem( frame );
468 }
469 mLayout->undoStack()->blockCommands( false );
470 mFrameItems.clear();
471 mResizeMode = bkResizeMode;
472 mBlockUpdates = false;
473}
474
476{
477 if ( i < 0 || i >= mFrameItems.size() )
478 {
479 return nullptr;
480 }
481 return mFrameItems.at( i );
482}
483
485{
486 return mFrameItems.indexOf( frame );
487}
488
489bool QgsLayoutMultiFrame::writeXml( QDomElement &parentElement, QDomDocument &doc, const QgsReadWriteContext &context, bool includeFrames ) const
490{
491 QDomElement element = doc.createElement( QStringLiteral( "LayoutMultiFrame" ) );
492 element.setAttribute( QStringLiteral( "resizeMode" ), mResizeMode );
493 element.setAttribute( QStringLiteral( "uuid" ), mUuid );
494 element.setAttribute( QStringLiteral( "templateUuid" ), mUuid );
495 element.setAttribute( QStringLiteral( "type" ), type() );
496
498 {
499 if ( !frame )
500 continue;
501
502 QDomElement childItem = doc.createElement( QStringLiteral( "childFrame" ) );
503 childItem.setAttribute( QStringLiteral( "uuid" ), frame->uuid() );
504 childItem.setAttribute( QStringLiteral( "templateUuid" ), frame->uuid() );
505
506 if ( includeFrames )
507 {
508 frame->writeXml( childItem, doc, context );
509 }
510
511 element.appendChild( childItem );
512 }
513
514 writeObjectPropertiesToElement( element, doc, context );
515 writePropertiesToElement( element, doc, context );
516 parentElement.appendChild( element );
517 return true;
518}
519
520bool QgsLayoutMultiFrame::readXml( const QDomElement &element, const QDomDocument &doc, const QgsReadWriteContext &context, bool includeFrames )
521{
522 if ( element.nodeName() != QLatin1String( "LayoutMultiFrame" ) )
523 {
524 return false;
525 }
526
527 mBlockUndoCommands = true;
528 mLayout->undoStack()->blockCommands( true );
529
530 readObjectPropertiesFromElement( element, doc, context );
531
532 mUuid = element.attribute( QStringLiteral( "uuid" ), QUuid::createUuid().toString() );
533 mTemplateUuid = element.attribute( QStringLiteral( "templateUuid" ), QUuid::createUuid().toString() );
534 mResizeMode = static_cast< ResizeMode >( element.attribute( QStringLiteral( "resizeMode" ), QStringLiteral( "0" ) ).toInt() );
535
536 deleteFrames();
537 mFrameUuids.clear();
538 mFrameTemplateUuids.clear();
539 QDomNodeList elementNodes = element.elementsByTagName( QStringLiteral( "childFrame" ) );
540 for ( int i = 0; i < elementNodes.count(); ++i )
541 {
542 QDomNode elementNode = elementNodes.at( i );
543 if ( !elementNode.isElement() )
544 continue;
545
546 QDomElement frameElement = elementNode.toElement();
547
548 QString uuid = frameElement.attribute( QStringLiteral( "uuid" ) );
549 mFrameUuids << uuid;
550 QString templateUuid = frameElement.attribute( QStringLiteral( "templateUuid" ) );
551 mFrameTemplateUuids << templateUuid;
552
553 if ( includeFrames )
554 {
555 QDomNodeList frameNodes = frameElement.elementsByTagName( QStringLiteral( "LayoutItem" ) );
556 if ( !frameNodes.isEmpty() )
557 {
558 QDomElement frameItemElement = frameNodes.at( 0 ).toElement();
559 std::unique_ptr< QgsLayoutFrame > newFrame = std::make_unique< QgsLayoutFrame >( mLayout, this );
560 newFrame->readXml( frameItemElement, doc, context );
561 addFrame( newFrame.release(), false );
562 }
563 }
564 }
565
566 bool result = readPropertiesFromElement( element, doc, context );
567
568 mBlockUndoCommands = false;
569 mLayout->undoStack()->blockCommands( false );
570 return result;
571}
572
573bool QgsLayoutMultiFrame::writePropertiesToElement( QDomElement &, QDomDocument &, const QgsReadWriteContext & ) const
574{
575 return true;
576}
577
578bool QgsLayoutMultiFrame::readPropertiesFromElement( const QDomElement &, const QDomDocument &, const QgsReadWriteContext & )
579{
580
581 return true;
582}
583
Base class for commands to undo/redo layout and layout object changes.
static QgsExpressionContextScope * multiFrameScope(const QgsLayoutMultiFrame *frame)
Creates a new scope which contains variables and functions relating to a QgsLayoutMultiFrame.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Base class for frame items, which form a layout multiframe item.
void setContentSection(const QRectF &section)
Sets the visible part of the multiframe's content which is visible within this frame (relative to the...
bool hideBackgroundIfEmpty() const
Returns whether the background and frame stroke should be hidden if this frame is empty.
void setHideBackgroundIfEmpty(bool hideBackgroundIfEmpty)
Sets whether the background and frame stroke should be hidden if this frame is empty.
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.
virtual void setFrameStrokeWidth(QgsLayoutMeasurement width)
Sets the frame stroke width.
void setBackgroundColor(const QColor &color)
Sets the background color for this item.
QgsLayoutMeasurement frameStrokeWidth() const
Returns the frame's stroke width.
double itemOpacity() const
Returns the item's opacity.
void setItemOpacity(double opacity)
Sets the item's opacity.
void refreshItemSize()
Refreshes an item's size by rechecking it against any possible item fixed or minimum sizes.
int page() const
Returns the page the item is currently on, with the first page returning 0.
QColor backgroundColor() const
Returns the background color for this item.
void setFrameStrokeColor(const QColor &color)
Sets the frame stroke color.
void setFrameJoinStyle(Qt::PenJoinStyle style)
Sets the join style used when drawing the item's frame.
virtual void setFrameEnabled(bool drawFrame)
Sets whether this item has a frame drawn around it or not.
void sizePositionChanged()
Emitted when the item's size or position changes.
virtual QString uuid() const
Returns the item identification string.
QPointF pagePos() const
Returns the item's position (in layout units) relative to the top left corner of its current page.
void setBlendMode(QPainter::CompositionMode mode)
Sets the item's composition blending mode.
bool frameEnabled() const
Returns true if the item includes a frame.
bool hasBackground() const
Returns true if the item has a background.
void attemptSetSceneRect(const QRectF &rect, bool includesFrame=false)
Attempts to update the item's position and size to match the passed rect in layout coordinates.
QColor frameStrokeColor() const
Returns the frame's stroke color.
void setBackgroundEnabled(bool drawBackground)
Sets whether this item has a background drawn under it or not.
QPainter::CompositionMode blendMode() const
Returns the item's composition blending mode.
Qt::PenJoinStyle frameJoinStyle() const
Returns the join style used for drawing the item's frame.
virtual bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const
Stores multiframe state within an XML DOM element.
void setResizeMode(ResizeMode mode)
Sets the resize mode for the multiframe, and recalculates frame sizes to match.
virtual QSizeF totalSize() const =0
Returns the total size of the multiframe's content, in layout units.
virtual void addFrame(QgsLayoutFrame *frame, bool recalcFrameSizes=true)
Adds a frame to the multiframe.
QgsLayoutMultiFrame(QgsLayout *layout)
Construct a new multiframe item, attached to the specified layout.
bool writeXml(QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context, bool includeFrames=false) const
Stores the multiframe state in a DOM element.
virtual void finalizeRestoreFromXml()
Called after all pending items have been restored from XML.
QgsAbstractLayoutUndoCommand * createCommand(const QString &text, int id, QUndoCommand *parent=nullptr) override
Creates a new layout undo command with the specified text and parent.
bool readXml(const QDomElement &itemElement, const QDomDocument &document, const QgsReadWriteContext &context, bool includeFrames=false)
Sets the item state from a DOM element.
void deleteFrames()
Removes and deletes all child frames.
QgsLayoutFrame * frame(int index) const
Returns the child frame at a specified index from the multiframe.
virtual QSizeF fixedFrameSize(int frameIndex=-1) const
Returns the fixed size for a frame, if desired.
void removeFrame(int index, bool removeEmptyPages=false)
Removes a frame by index from the multiframe.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QList< QgsLayoutFrame * > mFrameItems
void cancelCommand()
Cancels the current item command and discards it.
virtual int type() const =0
Returns unique multiframe type id.
ResizeMode resizeMode() const
Returns the resize mode for the multiframe.
virtual QSizeF minFrameSize(int frameIndex=-1) const
Returns the minimum size for a frames, if desired.
virtual double findNearbyPageBreak(double yPos)
Finds the optimal position to break a frame at.
QString uuid() const
Returns the multiframe identification string.
ResizeMode
Specifies the behavior for creating new frames to fit the multiframe's content.
@ UseExistingFrames
Don't automatically create new frames, just use existing frames.
@ RepeatOnEveryPage
Repeats the same frame on every page.
@ ExtendToNextPage
Creates new full page frames on the following page(s) until the entire multiframe content is visible.
void refresh() override
Refreshes the multiframe, causing a recalculation of any property overrides.
void endCommand()
Completes the current item command and push it onto the layout's undo stack.
QgsLayoutFrame * createNewFrame(QgsLayoutFrame *currentFrame, QPointF pos, QSizeF size)
Creates a new frame and adds it to the multi frame and layout.
void beginCommand(const QString &commandText, UndoCommand command=UndoNone)
Starts new undo command for this item.
QList< QgsLayoutFrame * > frames() const
Returns a list of all child frames for this multiframe.
virtual void recalculateFrameSizes()
Recalculates the portion of the multiframe item which is shown in each of its component frames.
void update()
Forces a redraw of all child frames.
int frameIndex(QgsLayoutFrame *frame) const
Returns the index of a frame within the multiframe.
void recalculateFrameRects()
Forces a recalculation of all the associated frame's scene rectangles.
virtual bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context)
Sets multiframe state from a DOM element.
virtual QString displayName() const
Returns the multiframe display name.
UndoCommand
Multiframe item undo commands, used for collapsing undo commands.
virtual void refreshDataDefinedProperty(QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::AllProperties)
Refreshes a data defined property for the multi frame by reevaluating the property's value and redraw...
A base class for objects which belong to a layout.
bool readObjectPropertiesFromElement(const QDomElement &parentElement, const QDomDocument &document, const QgsReadWriteContext &context)
Sets object properties from a DOM element.
void changed()
Emitted when the object's properties change.
virtual void refresh()
Refreshes the object, causing a recalculation of any property overrides.
QPointer< QgsLayout > mLayout
DataDefinedProperty
Data defined properties for different item types.
QgsExpressionContext createExpressionContext() const override
Creates an expression context relating to the objects' current state.
bool writeObjectPropertiesToElement(QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context) const
Stores object properties within an XML DOM element.
void changed()
Emitted when pages are added or removed from the collection.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:51
The class is used as a container of context for various read/write operations on other objects.