Branch data Line data Source code
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"
17 : : #include "qgslayoutmultiframeundocommand.h"
18 : : #include "qgslayoutframe.h"
19 : : #include "qgslayout.h"
20 : : #include "qgslayoutpagecollection.h"
21 : : #include "qgslayoutundostack.h"
22 : : #include "qgsexpressioncontextutils.h"
23 : : #include <QUuid>
24 : :
25 : 0 : QgsLayoutMultiFrame::QgsLayoutMultiFrame( QgsLayout *layout )
26 : 0 : : QgsLayoutObject( layout )
27 : 0 : , mUuid( QUuid::createUuid().toString() )
28 : 0 : {
29 : 0 : mLayout->addMultiFrame( this );
30 : :
31 : 0 : connect( mLayout->pageCollection(), &QgsLayoutPageCollection::changed, this, &QgsLayoutMultiFrame::handlePageChange );
32 : 0 : }
33 : :
34 : 0 : QgsLayoutMultiFrame::~QgsLayoutMultiFrame()
35 : 0 : {
36 : 0 : deleteFrames();
37 : 0 : }
38 : :
39 : 0 : QSizeF QgsLayoutMultiFrame::fixedFrameSize( const int frameIndex ) const
40 : : {
41 : : Q_UNUSED( frameIndex )
42 : 0 : return QSizeF( 0, 0 );
43 : : }
44 : :
45 : 0 : QSizeF QgsLayoutMultiFrame::minFrameSize( const int frameIndex ) const
46 : : {
47 : : Q_UNUSED( frameIndex )
48 : 0 : return QSizeF( 0, 0 );
49 : : }
50 : :
51 : 0 : double QgsLayoutMultiFrame::findNearbyPageBreak( double yPos )
52 : : {
53 : 0 : return yPos;
54 : : }
55 : :
56 : 0 : void QgsLayoutMultiFrame::addFrame( QgsLayoutFrame *frame, bool recalcFrameSizes )
57 : : {
58 : 0 : if ( !frame || mFrameItems.contains( frame ) )
59 : 0 : return;
60 : :
61 : 0 : mFrameItems.push_back( frame );
62 : 0 : frame->mMultiFrame = this;
63 : 0 : connect( frame, &QgsLayoutItem::sizePositionChanged, this, &QgsLayoutMultiFrame::recalculateFrameSizes );
64 : 0 : connect( frame, &QgsLayoutFrame::destroyed, this, [this, frame ]
65 : : {
66 : 0 : handleFrameRemoval( frame );
67 : 0 : } );
68 : 0 : if ( mLayout && !frame->scene() )
69 : : {
70 : 0 : mLayout->addLayoutItem( frame );
71 : 0 : }
72 : :
73 : 0 : if ( recalcFrameSizes )
74 : : {
75 : 0 : recalculateFrameSizes();
76 : 0 : }
77 : 0 : }
78 : :
79 : 0 : void QgsLayoutMultiFrame::setResizeMode( ResizeMode mode )
80 : : {
81 : 0 : if ( mode != mResizeMode )
82 : : {
83 : 0 : mLayout->undoStack()->beginMacro( tr( "Change Resize Mode" ) );
84 : 0 : mResizeMode = mode;
85 : 0 : recalculateFrameSizes();
86 : 0 : mLayout->undoStack()->endMacro();
87 : 0 : emit changed();
88 : 0 : }
89 : 0 : }
90 : :
91 : 0 : QList<QgsLayoutFrame *> QgsLayoutMultiFrame::frames() const
92 : : {
93 : 0 : return mFrameItems;
94 : : }
95 : :
96 : 0 : void QgsLayoutMultiFrame::recalculateFrameSizes()
97 : : {
98 : 0 : if ( mFrameItems.empty() )
99 : : {
100 : 0 : return;
101 : : }
102 : :
103 : 0 : QSizeF size = totalSize();
104 : 0 : double totalHeight = size.height();
105 : :
106 : 0 : if ( totalHeight < 1 )
107 : : {
108 : 0 : return;
109 : : }
110 : :
111 : 0 : if ( mBlockUndoCommands )
112 : 0 : mLayout->undoStack()->blockCommands( true );
113 : :
114 : 0 : double currentY = 0;
115 : 0 : double currentHeight = 0;
116 : 0 : QgsLayoutFrame *currentItem = nullptr;
117 : :
118 : 0 : for ( int i = 0; i < mFrameItems.size(); ++i )
119 : : {
120 : 0 : if ( mResizeMode != RepeatOnEveryPage && currentY >= totalHeight )
121 : : {
122 : 0 : if ( mResizeMode == RepeatUntilFinished || mResizeMode == ExtendToNextPage ) //remove unneeded frames in extent mode
123 : : {
124 : 0 : bool removingPages = true;
125 : 0 : for ( int j = mFrameItems.size(); j > i; --j )
126 : : {
127 : 0 : int numPagesBefore = mLayout->pageCollection()->pageCount();
128 : 0 : removeFrame( j - 1, removingPages );
129 : : //if removing the frame didn't also remove the page, then stop removing pages
130 : 0 : removingPages = removingPages && ( mLayout->pageCollection()->pageCount() < numPagesBefore );
131 : 0 : }
132 : 0 : return;
133 : : }
134 : 0 : }
135 : :
136 : 0 : currentItem = mFrameItems.value( i );
137 : 0 : currentHeight = currentItem->rect().height();
138 : 0 : if ( mResizeMode == RepeatOnEveryPage )
139 : : {
140 : 0 : currentItem->setContentSection( QRectF( 0, 0, currentItem->rect().width(), currentHeight ) );
141 : 0 : }
142 : : else
143 : : {
144 : 0 : currentHeight = findNearbyPageBreak( currentY + currentHeight ) - currentY;
145 : 0 : currentItem->setContentSection( QRectF( 0, currentY, currentItem->rect().width(), currentHeight ) );
146 : : }
147 : 0 : currentItem->update();
148 : 0 : currentY += currentHeight;
149 : 0 : }
150 : :
151 : : //at end of frames but there is still content left. Add other pages if ResizeMode ==
152 : 0 : if ( mLayout->pageCollection()->pageCount() > 0 && currentItem && mResizeMode != UseExistingFrames )
153 : : {
154 : 0 : while ( ( mResizeMode == RepeatOnEveryPage ) || currentY < totalHeight )
155 : : {
156 : : //find out on which page the lower left point of the last frame is
157 : 0 : int page = mLayout->pageCollection()->predictPageNumberForPoint( QPointF( 0, currentItem->pos().y() + currentItem->rect().height() ) ) + 1;
158 : :
159 : 0 : if ( mResizeMode == RepeatOnEveryPage )
160 : : {
161 : 0 : if ( page >= mLayout->pageCollection()->pageCount() )
162 : : {
163 : 0 : break;
164 : : }
165 : 0 : }
166 : : else
167 : : {
168 : : //add new pages if required
169 : 0 : for ( int p = mLayout->pageCollection()->pageCount() - 1 ; p < page; ++p )
170 : : {
171 : 0 : mLayout->pageCollection()->extendByNewPage();
172 : 0 : }
173 : : }
174 : :
175 : 0 : double currentPageHeight = mLayout->pageCollection()->page( page )->rect().height();
176 : :
177 : 0 : double frameHeight = 0;
178 : 0 : switch ( mResizeMode )
179 : : {
180 : : case RepeatUntilFinished:
181 : : case RepeatOnEveryPage:
182 : : {
183 : 0 : frameHeight = currentItem->rect().height();
184 : 0 : break;
185 : : }
186 : : case ExtendToNextPage:
187 : : {
188 : 0 : frameHeight = ( currentY + currentPageHeight ) > totalHeight ? totalHeight - currentY : currentPageHeight;
189 : 0 : break;
190 : : }
191 : :
192 : : case UseExistingFrames:
193 : 0 : break;
194 : : }
195 : :
196 : 0 : double newFrameY = mLayout->pageCollection()->page( page )->pos().y();
197 : 0 : if ( mResizeMode == RepeatUntilFinished || mResizeMode == RepeatOnEveryPage )
198 : : {
199 : 0 : newFrameY += currentItem->pagePos().y();
200 : 0 : }
201 : :
202 : : //create new frame
203 : 0 : QgsLayoutFrame *newFrame = createNewFrame( currentItem,
204 : 0 : QPointF( currentItem->pos().x(), newFrameY ),
205 : 0 : QSizeF( currentItem->rect().width(), frameHeight ) );
206 : :
207 : 0 : if ( mResizeMode == RepeatOnEveryPage )
208 : : {
209 : 0 : newFrame->setContentSection( QRectF( 0, 0, newFrame->rect().width(), newFrame->rect().height() ) );
210 : 0 : currentY += frameHeight;
211 : 0 : }
212 : : else
213 : : {
214 : 0 : double contentHeight = findNearbyPageBreak( currentY + newFrame->rect().height() ) - currentY;
215 : 0 : newFrame->setContentSection( QRectF( 0, currentY, newFrame->rect().width(), contentHeight ) );
216 : 0 : currentY += contentHeight;
217 : : }
218 : :
219 : 0 : currentItem = newFrame;
220 : : }
221 : 0 : }
222 : :
223 : 0 : if ( mBlockUndoCommands )
224 : 0 : mLayout->undoStack()->blockCommands( false );
225 : 0 : }
226 : :
227 : 0 : void QgsLayoutMultiFrame::recalculateFrameRects()
228 : : {
229 : 0 : if ( mFrameItems.empty() )
230 : : {
231 : : //no frames, nothing to do
232 : 0 : return;
233 : : }
234 : :
235 : 0 : const QList< QgsLayoutFrame * > frames = mFrameItems;
236 : 0 : for ( QgsLayoutFrame *frame : frames )
237 : : {
238 : 0 : frame->refreshItemSize();
239 : : }
240 : 0 : }
241 : :
242 : 0 : void QgsLayoutMultiFrame::refreshDataDefinedProperty( const QgsLayoutObject::DataDefinedProperty )
243 : : {
244 : :
245 : 0 : }
246 : :
247 : 0 : QgsLayoutFrame *QgsLayoutMultiFrame::createNewFrame( QgsLayoutFrame *currentFrame, QPointF pos, QSizeF size )
248 : : {
249 : 0 : if ( !currentFrame )
250 : : {
251 : 0 : return nullptr;
252 : : }
253 : :
254 : 0 : QgsLayoutFrame *newFrame = new QgsLayoutFrame( mLayout, this );
255 : 0 : newFrame->attemptSetSceneRect( QRectF( pos.x(), pos.y(), size.width(), size.height() ) );
256 : :
257 : : //copy some settings from the parent frame
258 : 0 : newFrame->setBackgroundColor( currentFrame->backgroundColor() );
259 : 0 : newFrame->setBackgroundEnabled( currentFrame->hasBackground() );
260 : 0 : newFrame->setBlendMode( currentFrame->blendMode() );
261 : 0 : newFrame->setFrameEnabled( currentFrame->frameEnabled() );
262 : 0 : newFrame->setFrameStrokeColor( currentFrame->frameStrokeColor() );
263 : 0 : newFrame->setFrameJoinStyle( currentFrame->frameJoinStyle() );
264 : 0 : newFrame->setFrameStrokeWidth( currentFrame->frameStrokeWidth() );
265 : 0 : newFrame->setItemOpacity( currentFrame->itemOpacity() );
266 : 0 : newFrame->setHideBackgroundIfEmpty( currentFrame->hideBackgroundIfEmpty() );
267 : :
268 : 0 : addFrame( newFrame, false );
269 : :
270 : 0 : return newFrame;
271 : 0 : }
272 : :
273 : 0 : QString QgsLayoutMultiFrame::displayName() const
274 : : {
275 : 0 : return tr( "<Multiframe>" );
276 : : }
277 : :
278 : 0 : QgsAbstractLayoutUndoCommand *QgsLayoutMultiFrame::createCommand( const QString &text, int id, QUndoCommand *parent )
279 : : {
280 : 0 : return new QgsLayoutMultiFrameUndoCommand( this, text, id, parent );
281 : 0 : }
282 : :
283 : 0 : QgsExpressionContext QgsLayoutMultiFrame::createExpressionContext() const
284 : : {
285 : 0 : QgsExpressionContext context = QgsLayoutObject::createExpressionContext();
286 : 0 : context.appendScope( QgsExpressionContextUtils::multiFrameScope( this ) );
287 : 0 : return context;
288 : 0 : }
289 : :
290 : 0 : void QgsLayoutMultiFrame::beginCommand( const QString &commandText, QgsLayoutMultiFrame::UndoCommand command )
291 : : {
292 : 0 : if ( !mLayout )
293 : 0 : return;
294 : :
295 : 0 : mLayout->undoStack()->beginCommand( this, commandText, command );
296 : 0 : }
297 : :
298 : 0 : void QgsLayoutMultiFrame::endCommand()
299 : : {
300 : 0 : if ( mLayout )
301 : 0 : mLayout->undoStack()->endCommand();
302 : 0 : }
303 : :
304 : 0 : void QgsLayoutMultiFrame::cancelCommand()
305 : : {
306 : 0 : if ( mLayout )
307 : 0 : mLayout->undoStack()->cancelCommand();
308 : 0 : }
309 : :
310 : 0 : void QgsLayoutMultiFrame::finalizeRestoreFromXml()
311 : : {
312 : 0 : for ( int i = 0; i < mFrameUuids.count(); ++i )
313 : : {
314 : 0 : QgsLayoutFrame *frame = nullptr;
315 : 0 : const QString uuid = mFrameUuids.at( i );
316 : 0 : if ( !uuid.isEmpty() )
317 : : {
318 : 0 : QgsLayoutItem *item = mLayout->itemByUuid( uuid, true );
319 : 0 : frame = qobject_cast< QgsLayoutFrame * >( item );
320 : 0 : }
321 : 0 : if ( !frame )
322 : : {
323 : 0 : const QString templateUuid = mFrameTemplateUuids.at( i );
324 : 0 : if ( !templateUuid.isEmpty() )
325 : : {
326 : 0 : QgsLayoutItem *item = mLayout->itemByTemplateUuid( templateUuid );
327 : 0 : frame = qobject_cast< QgsLayoutFrame * >( item );
328 : 0 : }
329 : 0 : }
330 : :
331 : 0 : if ( frame )
332 : : {
333 : 0 : addFrame( frame );
334 : 0 : }
335 : 0 : }
336 : 0 : }
337 : :
338 : 0 : void QgsLayoutMultiFrame::refresh()
339 : : {
340 : 0 : QgsLayoutObject::refresh();
341 : 0 : refreshDataDefinedProperty();
342 : 0 : }
343 : :
344 : 0 : void QgsLayoutMultiFrame::handleFrameRemoval( QgsLayoutFrame *frame )
345 : : {
346 : 0 : if ( mBlockUpdates )
347 : 0 : return;
348 : :
349 : 0 : if ( !frame )
350 : : {
351 : 0 : return;
352 : : }
353 : 0 : int index = mFrameItems.indexOf( frame );
354 : 0 : if ( index == -1 )
355 : : {
356 : 0 : return;
357 : : }
358 : :
359 : 0 : mFrameItems.removeAt( index );
360 : 0 : if ( !mFrameItems.isEmpty() )
361 : : {
362 : 0 : 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
366 : 0 : mResizeMode = QgsLayoutMultiFrame::UseExistingFrames;
367 : 0 : emit changed();
368 : 0 : recalculateFrameSizes();
369 : 0 : }
370 : 0 : }
371 : 0 : }
372 : :
373 : 0 : void QgsLayoutMultiFrame::handlePageChange()
374 : : {
375 : 0 : if ( mLayout->pageCollection()->pageCount() < 1 )
376 : : {
377 : 0 : return;
378 : : }
379 : :
380 : 0 : if ( mResizeMode != RepeatOnEveryPage )
381 : : {
382 : 0 : return;
383 : : }
384 : :
385 : : //remove items beginning on non-existing pages
386 : 0 : for ( int i = mFrameItems.size() - 1; i >= 0; --i )
387 : : {
388 : 0 : QgsLayoutFrame *frame = mFrameItems.at( i );
389 : 0 : int page = mLayout->pageCollection()->predictPageNumberForPoint( frame->pos() );
390 : 0 : if ( page >= mLayout->pageCollection()->pageCount() )
391 : : {
392 : 0 : removeFrame( i );
393 : 0 : }
394 : 0 : }
395 : :
396 : 0 : if ( !mFrameItems.empty() )
397 : : {
398 : : //page number of the last item
399 : 0 : QgsLayoutFrame *lastFrame = mFrameItems.last();
400 : 0 : int lastItemPage = mLayout->pageCollection()->predictPageNumberForPoint( lastFrame->pos() );
401 : :
402 : 0 : for ( int i = lastItemPage + 1; i < mLayout->pageCollection()->pageCount(); ++i )
403 : : {
404 : : //copy last frame to current page
405 : 0 : std::unique_ptr< QgsLayoutFrame > newFrame = std::make_unique< QgsLayoutFrame >( mLayout, this );
406 : :
407 : 0 : newFrame->attemptSetSceneRect( QRectF( lastFrame->pos().x(),
408 : 0 : mLayout->pageCollection()->page( i )->pos().y() + lastFrame->pagePos().y(),
409 : 0 : lastFrame->rect().width(), lastFrame->rect().height() ) );
410 : 0 : lastFrame = newFrame.get();
411 : 0 : addFrame( newFrame.release(), false );
412 : 0 : }
413 : 0 : }
414 : :
415 : 0 : recalculateFrameSizes();
416 : 0 : update();
417 : 0 : }
418 : :
419 : 0 : void QgsLayoutMultiFrame::removeFrame( int i, const bool removeEmptyPages )
420 : : {
421 : 0 : if ( i >= mFrameItems.count() )
422 : : {
423 : 0 : return;
424 : : }
425 : :
426 : 0 : QgsLayoutFrame *frameItem = mFrameItems.at( i );
427 : 0 : if ( mLayout )
428 : : {
429 : 0 : mIsRecalculatingSize = true;
430 : 0 : int pageNumber = frameItem->page();
431 : 0 : //remove item, but don't create undo command
432 : 0 : mLayout->undoStack()->blockCommands( true );
433 : 0 : mLayout->removeLayoutItem( frameItem );
434 : : //if frame was the only item on the page, remove the page
435 : 0 : if ( removeEmptyPages && mLayout->pageCollection()->pageIsEmpty( pageNumber ) )
436 : : {
437 : 0 : mLayout->pageCollection()->deletePage( pageNumber );
438 : 0 : }
439 : 0 : mLayout->undoStack()->blockCommands( false );
440 : 0 : mIsRecalculatingSize = false;
441 : 0 : }
442 : 0 : mFrameItems.removeAt( i );
443 : 0 : }
444 : :
445 : 0 : void QgsLayoutMultiFrame::update()
446 : : {
447 : 0 : for ( QgsLayoutFrame *frame : std::as_const( mFrameItems ) )
448 : : {
449 : 0 : frame->update();
450 : : }
451 : 0 : }
452 : :
453 : 0 : void QgsLayoutMultiFrame::deleteFrames()
454 : : {
455 : 0 : mBlockUpdates = true;
456 : 0 : ResizeMode bkResizeMode = mResizeMode;
457 : 0 : mResizeMode = UseExistingFrames;
458 : 0 : mLayout->undoStack()->blockCommands( true );
459 : 0 : for ( QgsLayoutFrame *frame : std::as_const( mFrameItems ) )
460 : : {
461 : 0 : mLayout->removeLayoutItem( frame );
462 : : }
463 : 0 : mLayout->undoStack()->blockCommands( false );
464 : 0 : mFrameItems.clear();
465 : 0 : mResizeMode = bkResizeMode;
466 : 0 : mBlockUpdates = false;
467 : 0 : }
468 : :
469 : 0 : QgsLayoutFrame *QgsLayoutMultiFrame::frame( int i ) const
470 : : {
471 : 0 : if ( i < 0 || i >= mFrameItems.size() )
472 : : {
473 : 0 : return nullptr;
474 : : }
475 : 0 : return mFrameItems.at( i );
476 : 0 : }
477 : :
478 : 0 : int QgsLayoutMultiFrame::frameIndex( QgsLayoutFrame *frame ) const
479 : : {
480 : 0 : return mFrameItems.indexOf( frame );
481 : : }
482 : :
483 : 0 : bool QgsLayoutMultiFrame::writeXml( QDomElement &parentElement, QDomDocument &doc, const QgsReadWriteContext &context, bool includeFrames ) const
484 : : {
485 : 0 : QDomElement element = doc.createElement( QStringLiteral( "LayoutMultiFrame" ) );
486 : 0 : element.setAttribute( QStringLiteral( "resizeMode" ), mResizeMode );
487 : 0 : element.setAttribute( QStringLiteral( "uuid" ), mUuid );
488 : 0 : element.setAttribute( QStringLiteral( "templateUuid" ), mUuid );
489 : 0 : element.setAttribute( QStringLiteral( "type" ), type() );
490 : :
491 : 0 : for ( QgsLayoutFrame *frame : mFrameItems )
492 : : {
493 : 0 : if ( !frame )
494 : 0 : continue;
495 : :
496 : 0 : QDomElement childItem = doc.createElement( QStringLiteral( "childFrame" ) );
497 : 0 : childItem.setAttribute( QStringLiteral( "uuid" ), frame->uuid() );
498 : 0 : childItem.setAttribute( QStringLiteral( "templateUuid" ), frame->uuid() );
499 : :
500 : 0 : if ( includeFrames )
501 : : {
502 : 0 : frame->writeXml( childItem, doc, context );
503 : 0 : }
504 : :
505 : 0 : element.appendChild( childItem );
506 : 0 : }
507 : :
508 : 0 : writeObjectPropertiesToElement( element, doc, context );
509 : 0 : writePropertiesToElement( element, doc, context );
510 : 0 : parentElement.appendChild( element );
511 : : return true;
512 : 0 : }
513 : :
514 : 0 : bool QgsLayoutMultiFrame::readXml( const QDomElement &element, const QDomDocument &doc, const QgsReadWriteContext &context, bool includeFrames )
515 : : {
516 : 0 : if ( element.nodeName() != QLatin1String( "LayoutMultiFrame" ) )
517 : : {
518 : 0 : return false;
519 : : }
520 : :
521 : 0 : mBlockUndoCommands = true;
522 : 0 : mLayout->undoStack()->blockCommands( true );
523 : :
524 : 0 : readObjectPropertiesFromElement( element, doc, context );
525 : :
526 : 0 : mUuid = element.attribute( QStringLiteral( "uuid" ), QUuid::createUuid().toString() );
527 : 0 : mTemplateUuid = element.attribute( QStringLiteral( "templateUuid" ), QUuid::createUuid().toString() );
528 : 0 : mResizeMode = static_cast< ResizeMode >( element.attribute( QStringLiteral( "resizeMode" ), QStringLiteral( "0" ) ).toInt() );
529 : :
530 : 0 : deleteFrames();
531 : 0 : mFrameUuids.clear();
532 : 0 : mFrameTemplateUuids.clear();
533 : 0 : QDomNodeList elementNodes = element.elementsByTagName( QStringLiteral( "childFrame" ) );
534 : 0 : for ( int i = 0; i < elementNodes.count(); ++i )
535 : : {
536 : 0 : QDomNode elementNode = elementNodes.at( i );
537 : 0 : if ( !elementNode.isElement() )
538 : 0 : continue;
539 : :
540 : 0 : QDomElement frameElement = elementNode.toElement();
541 : :
542 : 0 : QString uuid = frameElement.attribute( QStringLiteral( "uuid" ) );
543 : 0 : mFrameUuids << uuid;
544 : 0 : QString templateUuid = frameElement.attribute( QStringLiteral( "templateUuid" ) );
545 : 0 : mFrameTemplateUuids << templateUuid;
546 : :
547 : 0 : if ( includeFrames )
548 : : {
549 : 0 : QDomNodeList frameNodes = frameElement.elementsByTagName( QStringLiteral( "LayoutItem" ) );
550 : 0 : if ( !frameNodes.isEmpty() )
551 : : {
552 : 0 : QDomElement frameItemElement = frameNodes.at( 0 ).toElement();
553 : 0 : std::unique_ptr< QgsLayoutFrame > newFrame = std::make_unique< QgsLayoutFrame >( mLayout, this );
554 : 0 : newFrame->readXml( frameItemElement, doc, context );
555 : 0 : addFrame( newFrame.release(), false );
556 : 0 : }
557 : 0 : }
558 : 0 : }
559 : :
560 : 0 : bool result = readPropertiesFromElement( element, doc, context );
561 : :
562 : 0 : mBlockUndoCommands = false;
563 : 0 : mLayout->undoStack()->blockCommands( false );
564 : 0 : return result;
565 : 0 : }
566 : :
567 : 0 : bool QgsLayoutMultiFrame::writePropertiesToElement( QDomElement &, QDomDocument &, const QgsReadWriteContext & ) const
568 : : {
569 : 0 : return true;
570 : : }
571 : :
572 : 0 : bool QgsLayoutMultiFrame::readPropertiesFromElement( const QDomElement &, const QDomDocument &, const QgsReadWriteContext & )
573 : : {
574 : :
575 : 0 : return true;
576 : : }
577 : :
|