26 , mUuid( QUuid::createUuid().toString() )
40 Q_UNUSED( frameIndex )
41 return QSizeF( 0, 0 );
46 Q_UNUSED( frameIndex )
47 return QSizeF( 0, 0 );
61 frame->mMultiFrame =
this;
63 connect( frame, &QgsLayoutFrame::destroyed,
this, [
this, frame ]
65 handleFrameRemoval( frame );
67 if (
mLayout && !frame->scene() )
69 mLayout->addLayoutItem( frame );
72 if ( recalcFrameSizes )
82 mLayout->undoStack()->beginMacro( tr(
"Change Resize Mode" ) );
85 mLayout->undoStack()->endMacro();
103 double totalHeight = size.height();
105 if ( totalHeight < 1 )
110 if ( mBlockUndoCommands )
111 mLayout->undoStack()->blockCommands(
true );
114 double currentHeight = 0;
123 bool removingPages =
true;
126 int numPagesBefore =
mLayout->pageCollection()->pageCount();
129 removingPages = removingPages && (
mLayout->pageCollection()->pageCount() < numPagesBefore );
136 currentHeight = currentItem->rect().height();
139 currentItem->
setContentSection( QRectF( 0, 0, currentItem->rect().width(), currentHeight ) );
144 currentItem->
setContentSection( QRectF( 0, currentY, currentItem->rect().width(), currentHeight ) );
146 currentItem->update();
147 currentY += currentHeight;
156 int page =
mLayout->pageCollection()->predictPageNumberForPoint( QPointF( 0, currentItem->pos().y() + currentItem->rect().height() ) ) + 1;
160 if ( page >=
mLayout->pageCollection()->pageCount() )
168 for (
int p =
mLayout->pageCollection()->pageCount() - 1 ; p < page; ++p )
170 mLayout->pageCollection()->extendByNewPage();
174 double currentPageHeight =
mLayout->pageCollection()->page( page )->rect().height();
176 double frameHeight = 0;
182 frameHeight = currentItem->rect().height();
187 frameHeight = ( currentY + currentPageHeight ) > totalHeight ? totalHeight - currentY : currentPageHeight;
195 double newFrameY =
mLayout->pageCollection()->page( page )->pos().y();
198 newFrameY += currentItem->
pagePos().y();
203 QPointF( currentItem->pos().x(), newFrameY ),
204 QSizeF( currentItem->rect().width(), frameHeight ) );
208 newFrame->
setContentSection( QRectF( 0, 0, newFrame->rect().width(), newFrame->rect().height() ) );
209 currentY += frameHeight;
213 double contentHeight =
findNearbyPageBreak( currentY + newFrame->rect().height() ) - currentY;
214 newFrame->
setContentSection( QRectF( 0, currentY, newFrame->rect().width(), contentHeight ) );
215 currentY += contentHeight;
218 currentItem = newFrame;
222 if ( mBlockUndoCommands )
223 mLayout->undoStack()->blockCommands(
false );
274 return tr(
"<Multiframe>" );
279 return new QgsLayoutMultiFrameUndoCommand(
this, text,
id, parent );
287 mLayout->undoStack()->beginCommand(
this, commandText, command );
293 mLayout->undoStack()->endCommand();
299 mLayout->undoStack()->cancelCommand();
304 for (
int i = 0; i < mFrameUuids.count(); ++i )
307 const QString
uuid = mFrameUuids.at( i );
308 if ( !uuid.isEmpty() )
315 const QString templateUuid = mFrameTemplateUuids.at( i );
316 if ( !templateUuid.isEmpty() )
365 void QgsLayoutMultiFrame::handlePageChange()
367 if (
mLayout->pageCollection()->pageCount() < 1 )
378 for (
int i =
mFrameItems.size() - 1; i >= 0; --i )
381 int page =
mLayout->pageCollection()->predictPageNumberForPoint( frame->pos() );
382 if ( page >=
mLayout->pageCollection()->pageCount() )
392 int lastItemPage =
mLayout->pageCollection()->predictPageNumberForPoint( lastFrame->pos() );
394 for (
int i = lastItemPage + 1; i <
mLayout->pageCollection()->pageCount(); ++i )
397 std::unique_ptr< QgsLayoutFrame > newFrame = qgis::make_unique< QgsLayoutFrame >(
mLayout, this );
399 newFrame->attemptSetSceneRect( QRectF( lastFrame->pos().x(),
400 mLayout->pageCollection()->
page( i )->pos().y() + lastFrame->
pagePos().y(),
401 lastFrame->rect().width(), lastFrame->rect().height() ) );
402 lastFrame = newFrame.get();
403 addFrame( newFrame.release(), false );
421 mIsRecalculatingSize =
true;
422 int pageNumber = frameItem->
page();
424 mLayout->undoStack()->blockCommands(
true );
425 mLayout->removeLayoutItem( frameItem );
427 if ( removeEmptyPages &&
mLayout->pageCollection()->pageIsEmpty( pageNumber ) )
429 mLayout->pageCollection()->deletePage( pageNumber );
431 mLayout->undoStack()->blockCommands(
false );
432 mIsRecalculatingSize =
false;
447 mBlockUpdates =
true;
450 mLayout->undoStack()->blockCommands(
true );
453 mLayout->removeLayoutItem( frame );
455 mLayout->undoStack()->blockCommands(
false );
458 mBlockUpdates =
false;
477 QDomElement element = doc.createElement( QStringLiteral(
"LayoutMultiFrame" ) );
478 element.setAttribute( QStringLiteral(
"resizeMode" ),
mResizeMode );
479 element.setAttribute( QStringLiteral(
"uuid" ), mUuid );
480 element.setAttribute( QStringLiteral(
"templateUuid" ), mUuid );
481 element.setAttribute( QStringLiteral(
"type" ),
type() );
488 QDomElement childItem = doc.createElement( QStringLiteral(
"childFrame" ) );
489 childItem.setAttribute( QStringLiteral(
"uuid" ), frame->
uuid() );
490 childItem.setAttribute( QStringLiteral(
"templateUuid" ), frame->
uuid() );
494 frame->
writeXml( childItem, doc, context );
497 element.appendChild( childItem );
502 parentElement.appendChild( element );
508 if ( element.nodeName() != QStringLiteral(
"LayoutMultiFrame" ) )
513 mBlockUndoCommands =
true;
514 mLayout->undoStack()->blockCommands(
true );
518 mUuid = element.attribute( QStringLiteral(
"uuid" ), QUuid::createUuid().toString() );
519 mTemplateUuid = element.attribute( QStringLiteral(
"templateUuid" ), QUuid::createUuid().toString() );
520 mResizeMode =
static_cast< ResizeMode >( element.attribute( QStringLiteral(
"resizeMode" ), QStringLiteral(
"0" ) ).toInt() );
524 mFrameTemplateUuids.clear();
525 QDomNodeList elementNodes = element.elementsByTagName( QStringLiteral(
"childFrame" ) );
526 for (
int i = 0; i < elementNodes.count(); ++i )
528 QDomNode elementNode = elementNodes.at( i );
529 if ( !elementNode.isElement() )
532 QDomElement frameElement = elementNode.toElement();
534 QString
uuid = frameElement.attribute( QStringLiteral(
"uuid" ) );
536 QString templateUuid = frameElement.attribute( QStringLiteral(
"templateUuid" ) );
537 mFrameTemplateUuids << templateUuid;
541 QDomNodeList frameNodes = frameElement.elementsByTagName( QStringLiteral(
"LayoutItem" ) );
542 if ( !frameNodes.isEmpty() )
544 QDomElement frameItemElement = frameNodes.at( 0 ).toElement();
545 std::unique_ptr< QgsLayoutFrame > newFrame = qgis::make_unique< QgsLayoutFrame >(
mLayout, this );
546 newFrame->readXml( frameItemElement, doc, context );
547 addFrame( newFrame.release(), false );
554 mBlockUndoCommands =
false;
555 mLayout->undoStack()->blockCommands(
false );
QgsLayoutMultiFrame(QgsLayout *layout)
Construct a new multiframe item, attached to the specified layout.
QString uuid() const
Returns the multiframe identification string.
The class is used as a container of context for various read/write operations on other objects...
virtual QSizeF totalSize() const =0
Returns the total size of the multiframe's content, in layout units.
void refresh() override
Refreshes the multiframe, causing a recalculation of any property overrides.
virtual QSizeF minFrameSize(int frameIndex=-1) const
Returns the minimum size for a frames, if desired.
Base class for graphical items within a QgsLayout.
bool readObjectPropertiesFromElement(const QDomElement &parentElement, const QDomDocument &document, const QgsReadWriteContext &context)
Sets object properties from a DOM element.
Base class for commands to undo/redo layout and layout object changes.
int frameIndex(QgsLayoutFrame *frame) const
Returns the index of a frame within the multiframe.
virtual bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const
Stores multiframe state within an XML DOM element.
bool readXml(const QDomElement &itemElement, const QDomDocument &document, const QgsReadWriteContext &context, bool includeFrames=false)
Sets the item state from a DOM element.
QgsLayoutFrame * createNewFrame(QgsLayoutFrame *currentFrame, QPointF pos, QSizeF size)
Creates a new frame and adds it to the multi frame and layout.
QList< QgsLayoutFrame * > frames() const
Returns a list of all child frames for this multiframe.
bool frameEnabled() const
Returns true if the item includes a frame.
Don't automatically create new frames, just use existing frames.
void beginCommand(const QString &commandText, UndoCommand command=UndoNone)
Starts new undo command for this item.
friend class QgsLayoutFrame
void deleteFrames()
Removes and deletes all child frames.
virtual void setFrameStrokeWidth(QgsLayoutMeasurement width)
Sets the frame stroke width.
QList< QgsLayoutFrame * > mFrameItems
void changed()
Emitted when pages are added or removed from the collection.
void setFrameStrokeColor(const QColor &color)
Sets the frame stroke color.
void recalculateFrameRects()
Forces a recalculation of all the associated frame's scene rectangles.
Creates new full page frames on the following page(s) until the entire multiframe content is visible...
void setContentSection(const QRectF §ion)
Sets the visible part of the multiframe's content which is visible within this frame (relative to the...
QgsLayoutMeasurement frameStrokeWidth() const
Returns the frame's stroke width.
void refreshItemSize()
Refreshes an item's size by rechecking it against any possible item fixed or minimum sizes...
void sizePositionChanged()
Emitted when the item's size or position changes.
bool writeXml(QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context) const
Stores the item state in a DOM element.
QgsAbstractLayoutUndoCommand * createCommand(const QString &text, int id, QUndoCommand *parent=nullptr) override
Creates a new layout undo command with the specified text and parent.
void setFrameJoinStyle(Qt::PenJoinStyle style)
Sets the join style used when drawing the item's frame.
bool hasBackground() const
Returns true if the item has a background.
void setBlendMode(QPainter::CompositionMode mode)
Sets the item's composition blending mode.
Repeats the same frame on every page.
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...
void setResizeMode(ResizeMode mode)
Sets the resize mode for the multiframe, and recalculates frame sizes to match.
QColor backgroundColor() const
Returns the background color for this item.
QPointer< QgsLayout > mLayout
void setHideBackgroundIfEmpty(bool hideBackgroundIfEmpty)
Sets whether the background and frame stroke should be hidden if this frame is empty.
int page() const
Returns the page the item is currently on, with the first page returning 0.
double itemOpacity() const
Returns the item's opacity.
QPainter::CompositionMode blendMode() const
Returns the item's composition blending mode.
virtual void finalizeRestoreFromXml()
Called after all pending items have been restored from XML.
void endCommand()
Completes the current item command and push it onto the layout's undo stack.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
QColor frameStrokeColor() const
Returns the frame's stroke color.
virtual void recalculateFrameSizes()
Recalculates the portion of the multiframe item which is shown in each of its component frames...
void setBackgroundEnabled(bool drawBackground)
Sets whether this item has a background drawn under it or not.
QgsLayoutFrame * frame(int index) const
Returns the child frame at a specified index from the multiframe.
virtual bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context)
Sets multiframe state from a DOM element.
QPointF pagePos() const
Returns the item's position (in layout units) relative to the top left corner of its current page...
bool writeObjectPropertiesToElement(QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context) const
Stores object properties within an XML DOM element.
virtual QString displayName() const
Returns the multiframe display name.
ResizeMode
Specifies the behavior for creating new frames to fit the multiframe's content.
virtual double findNearbyPageBreak(double yPos)
Finds the optimal position to break a frame at.
virtual QSizeF fixedFrameSize(int frameIndex=-1) const
Returns the fixed size for a frame, if desired.
Qt::PenJoinStyle frameJoinStyle() const
Returns the join style used for drawing the item's frame.
void update()
Forces a redraw of all child frames.
ResizeMode resizeMode() const
Returns the resize mode for the multiframe.
virtual int type() const =0
Returns unique multiframe type id.
virtual QString uuid() const
Returns the item identification string.
void removeFrame(int index, bool removeEmptyPages=false)
Removes a frame by index from the multiframe.
virtual void setFrameEnabled(bool drawFrame)
Sets whether this item has a frame drawn around it or not.
bool writeXml(QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context, bool includeFrames=false) const
Stores the multiframe state in a DOM element.
A base class for objects which belong to a layout.
bool hideBackgroundIfEmpty() const
Returns whether the background and frame stroke should be hidden if this frame is empty...
~QgsLayoutMultiFrame() override
UndoCommand
Multiframe item undo commands, used for collapsing undo commands.
virtual void addFrame(QgsLayoutFrame *frame, bool recalcFrameSizes=true)
Adds a frame to the multiframe.
virtual void refresh()
Refreshes the object, causing a recalculation of any property overrides.
void changed()
Emitted when the object's properties change.
DataDefinedProperty
Data defined properties for different item types.
Base class for frame items, which form a layout multiframe item.
void setItemOpacity(double opacity)
Sets the item's opacity.
void cancelCommand()
Cancels the current item command and discards it.
void setBackgroundColor(const QColor &color)
Sets the background color for this item.
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...