17#include "moc_qgslayoutmultiframe.cpp" 
   28  , mUuid( QUuid::createUuid().toString() )
 
 
   43  return QSizeF( 0, 0 );
 
 
   49  return QSizeF( 0, 0 );
 
 
   63  frame->mMultiFrame = 
this;
 
   65  connect( 
frame, &QgsLayoutFrame::destroyed, 
this, [
this, 
frame ]
 
   67    handleFrameRemoval( 
frame );
 
   74  if ( recalcFrameSizes )
 
 
   84    mLayout->undoStack()->beginMacro( tr( 
"Change Resize Mode" ) );
 
   87    mLayout->undoStack()->endMacro();
 
 
  105  double totalHeight = size.height();
 
  107  if ( totalHeight < 1 )
 
  112  if ( mBlockUndoCommands )
 
  113    mLayout->undoStack()->blockCommands( 
true );
 
  116  double currentHeight = 0;
 
  125        bool removingPages = 
true;
 
  128          int numPagesBefore = 
mLayout->pageCollection()->pageCount();
 
  131          removingPages = removingPages && ( 
mLayout->pageCollection()->pageCount() < numPagesBefore );
 
  138    currentHeight = currentItem->rect().height();
 
  141      currentItem->
setContentSection( QRectF( 0, 0, currentItem->rect().width(), currentHeight ) );
 
  146      currentItem->
setContentSection( QRectF( 0, currentY, currentItem->rect().width(), currentHeight ) );
 
  148    currentItem->update();
 
  149    currentY += currentHeight;
 
  158      int page = 
mLayout->pageCollection()->predictPageNumberForPoint( QPointF( 0, currentItem->pos().y() + currentItem->rect().height() ) ) + 1;
 
  162        if ( page >= 
mLayout->pageCollection()->pageCount() )
 
  170        for ( 
int p = 
mLayout->pageCollection()->pageCount() - 1 ; p < page; ++p )
 
  172          mLayout->pageCollection()->extendByNewPage();
 
  176      double currentPageHeight = 
mLayout->pageCollection()->
page( page )->rect().height();
 
  178      double frameHeight = 0;
 
  184          frameHeight = currentItem->rect().height();
 
  189          frameHeight = ( currentY + currentPageHeight ) > totalHeight ?  totalHeight - currentY : currentPageHeight;
 
  197      double newFrameY = 
mLayout->pageCollection()->page( page )->pos().y();
 
  200        newFrameY += currentItem->
pagePos().y();
 
  205                                 QPointF( currentItem->pos().x(), newFrameY ),
 
  206                                 QSizeF( currentItem->rect().width(), frameHeight ) );
 
  210        newFrame->
setContentSection( QRectF( 0, 0, newFrame->rect().width(), newFrame->rect().height() ) );
 
  211        currentY += frameHeight;
 
  215        double contentHeight = 
findNearbyPageBreak( currentY + newFrame->rect().height() ) - currentY;
 
  216        newFrame->
setContentSection( QRectF( 0, currentY, newFrame->rect().width(), contentHeight ) );
 
  217        currentY += contentHeight;
 
  220      currentItem = newFrame;
 
  224  if ( mBlockUndoCommands )
 
  225    mLayout->undoStack()->blockCommands( 
false );
 
 
  276  return tr( 
"<Multiframe>" );
 
 
  281  return new QgsLayoutMultiFrameUndoCommand( 
this, text, 
id, parent );
 
 
  296  mLayout->undoStack()->beginCommand( 
this, commandText, command );
 
 
  302    mLayout->undoStack()->endCommand();
 
 
  308    mLayout->undoStack()->cancelCommand();
 
 
  313  for ( 
int i = 0; i < mFrameUuids.count(); ++i )
 
  316    const QString 
uuid = mFrameUuids.at( i );
 
  317    if ( !
uuid.isEmpty() )
 
  320      frame = qobject_cast< QgsLayoutFrame * >( item );
 
  324      const QString templateUuid = mFrameTemplateUuids.at( i );
 
  325      if ( !templateUuid.isEmpty() )
 
  328        frame = qobject_cast< QgsLayoutFrame * >( item );
 
 
  345void QgsLayoutMultiFrame::handleFrameRemoval( 
QgsLayoutFrame *frame )
 
  374void QgsLayoutMultiFrame::handlePageChange()
 
  376  if ( 
mLayout->pageCollection()->pageCount() < 1 )
 
  387  for ( 
int i = 
mFrameItems.size() - 1; i >= 0; --i )
 
  390    int page = 
mLayout->pageCollection()->predictPageNumberForPoint( 
frame->pos() );
 
  391    if ( page >= 
mLayout->pageCollection()->pageCount() )
 
  401    int lastItemPage = 
mLayout->pageCollection()->predictPageNumberForPoint( lastFrame->pos() );
 
  403    for ( 
int i = lastItemPage + 1; i < 
mLayout->pageCollection()->pageCount(); ++i )
 
  406      auto newFrame = std::make_unique< QgsLayoutFrame >( 
mLayout, 
this );
 
  408      newFrame->attemptSetSceneRect( QRectF( lastFrame->pos().x(),
 
  410                                             lastFrame->rect().width(), lastFrame->rect().height() ) );
 
  411      lastFrame = newFrame.get();
 
  412      addFrame( newFrame.release(), 
false );
 
  430    mIsRecalculatingSize = 
true;
 
  431    int pageNumber = frameItem->
page();
 
  433    mLayout->undoStack()->blockCommands( 
true );
 
  434    mLayout->removeLayoutItem( frameItem );
 
  436    if ( removeEmptyPages && 
mLayout->pageCollection()->pageIsEmpty( pageNumber ) )
 
  438      mLayout->pageCollection()->deletePage( pageNumber );
 
  440    mLayout->undoStack()->blockCommands( 
false );
 
  441    mIsRecalculatingSize = 
false;
 
 
  462  mBlockUpdates = 
true;
 
  465  mLayout->undoStack()->blockCommands( 
true );
 
  470  mLayout->undoStack()->blockCommands( 
false );
 
  473  mBlockUpdates = 
false;
 
 
  492  QDomElement element = doc.createElement( QStringLiteral( 
"LayoutMultiFrame" ) );
 
  493  element.setAttribute( QStringLiteral( 
"resizeMode" ), 
mResizeMode );
 
  494  element.setAttribute( QStringLiteral( 
"uuid" ), mUuid );
 
  495  element.setAttribute( QStringLiteral( 
"templateUuid" ), mUuid );
 
  496  element.setAttribute( QStringLiteral( 
"type" ), 
type() );
 
  503    QDomElement childItem = doc.createElement( QStringLiteral( 
"childFrame" ) );
 
  504    childItem.setAttribute( QStringLiteral( 
"uuid" ), 
frame->
uuid() );
 
  505    childItem.setAttribute( QStringLiteral( 
"templateUuid" ), 
frame->
uuid() );
 
  512    element.appendChild( childItem );
 
  517  parentElement.appendChild( element );
 
 
  523  if ( element.nodeName() != QLatin1String( 
"LayoutMultiFrame" ) )
 
  528  mBlockUndoCommands = 
true;
 
  529  mLayout->undoStack()->blockCommands( 
true );
 
  533  mUuid = element.attribute( QStringLiteral( 
"uuid" ), QUuid::createUuid().toString() );
 
  534  mTemplateUuid = element.attribute( QStringLiteral( 
"templateUuid" ), QUuid::createUuid().toString() );
 
  535  mResizeMode = 
static_cast< ResizeMode >( element.attribute( QStringLiteral( 
"resizeMode" ), QStringLiteral( 
"0" ) ).toInt() );
 
  539  mFrameTemplateUuids.clear();
 
  540  QDomNodeList elementNodes = element.elementsByTagName( QStringLiteral( 
"childFrame" ) );
 
  541  for ( 
int i = 0; i < elementNodes.count(); ++i )
 
  543    QDomNode elementNode = elementNodes.at( i );
 
  544    if ( !elementNode.isElement() )
 
  547    QDomElement frameElement = elementNode.toElement();
 
  549    QString 
uuid = frameElement.attribute( QStringLiteral( 
"uuid" ) );
 
  551    QString templateUuid = frameElement.attribute( QStringLiteral( 
"templateUuid" ) );
 
  552    mFrameTemplateUuids << templateUuid;
 
  556      QDomNodeList frameNodes = frameElement.elementsByTagName( QStringLiteral( 
"LayoutItem" ) );
 
  557      if ( !frameNodes.isEmpty() )
 
  559        QDomElement frameItemElement = frameNodes.at( 0 ).toElement();
 
  560        auto newFrame = std::make_unique< QgsLayoutFrame >( 
mLayout, 
this );
 
  561        newFrame->readXml( frameItemElement, doc, context );
 
  562        addFrame( newFrame.release(), 
false );
 
  569  mBlockUndoCommands = 
false;
 
  570  mLayout->undoStack()->blockCommands( 
false );
 
 
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 §ion)
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.
 
QColor backgroundColor(bool useDataDefined=true) const
Returns the background color for this item.
 
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.
 
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
 
~QgsLayoutMultiFrame() override
 
void cancelCommand()
Cancels the current item command and discards it.
 
friend class QgsLayoutFrame
 
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.
 
virtual void refreshDataDefinedProperty(QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::DataDefinedProperty::AllProperties)
Refreshes a data defined property for the multi frame by reevaluating the property's value and redraw...
 
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.
 
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
 
QgsExpressionContext createExpressionContext() const override
Creates an expression context relating to the objects' current state.
 
DataDefinedProperty
Data defined properties for different item types.
 
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.
 
A container for the context for various read/write operations on objects.