40 , mGridSettings( this )
45 setBackgroundBrush( Qt::NoBrush );
52 mUndoStack->blockCommands(
true );
54 deleteAndRemoveMultiFrames();
62 QList<QGraphicsItem *> itemList = items();
67 for ( QGraphicsItem *item : qgis::as_const( itemList ) )
84 QDomDocument currentDoc;
87 QDomElement elem =
writeXml( currentDoc, context );
88 currentDoc.appendChild( elem );
90 std::unique_ptr< QgsLayout > newLayout = qgis::make_unique< QgsLayout >( mProject );
92 newLayout->loadFromTemplate( currentDoc, context,
true, &ok );
98 return newLayout.release();
106 mPageCollection->addPage( page );
107 mUndoStack->stack()->clear();
112 deleteAndRemoveMultiFrames();
115 const QList<QGraphicsItem *> itemList = items();
116 for ( QGraphicsItem *item : itemList )
120 if ( cItem && !pItem )
122 removeLayoutItemPrivate( cItem );
125 mItemsModel->clear();
127 mPageCollection->clear();
128 mUndoStack->stack()->clear();
138 return mItemsModel.get();
143 QList<QgsLayoutItem *> layoutItemList;
145 const QList<QGraphicsItem *> graphicsItemList = selectedItems();
146 for ( QGraphicsItem *item : graphicsItemList )
149 if ( layoutItem && ( includeLockedItems || !layoutItem->
isLocked() ) )
151 layoutItemList.push_back( layoutItem );
155 return layoutItemList;
174 const QList<QGraphicsItem *> selectedItemList = selectedItems();
175 for ( QGraphicsItem *item : selectedItemList )
179 layoutItem->setSelected(
false );
188 bool result = mItemsModel->reorderItemUp( item );
189 if ( result && !deferUpdate )
201 bool result = mItemsModel->reorderItemDown( item );
202 if ( result && !deferUpdate )
214 bool result = mItemsModel->reorderItemToTop( item );
215 if ( result && !deferUpdate )
227 bool result = mItemsModel->reorderItemToBottom( item );
228 if ( result && !deferUpdate )
239 QList<QgsLayoutItem *> itemList;
243 if ( item->uuid() == uuid )
245 else if ( includeTemplateUuids && item->mTemplateUuid == uuid )
254 QList<QgsLayoutItem *> itemList;
258 if ( item->mTemplateUuid == uuid )
267 const QList<QGraphicsItem *> itemList = items();
268 for ( QGraphicsItem *item : itemList )
271 if ( layoutItem && layoutItem->
id() == id )
283 if ( mf->uuid() == uuid )
285 else if ( includeTemplateUuids && mf->mTemplateUuid == uuid )
300 const QList<QGraphicsItem *> itemList = items( position, Qt::IntersectsItemShape, Qt::DescendingOrder );
302 bool foundBelowItem =
false;
303 for ( QGraphicsItem *graphicsItem : itemList )
307 if ( layoutItem && !paperItem )
311 if ( ( ! belowItem || foundBelowItem ) && ( !ignoreLocked || !layoutItem->
isLocked() ) )
317 if ( layoutItem == belowItem )
320 foundBelowItem =
true;
360 return *mRenderContext;
365 return *mRenderContext;
370 return *mReportContext;
375 return *mReportContext;
381 mPageCollection->redraw();
386 return mPageCollection->guides();
391 return mPageCollection->guides();
399 if ( mReportContext->
layer() )
408 mCustomProperties.
setValue( key, value );
410 if ( key.startsWith( QLatin1String(
"variable" ) ) )
416 return mCustomProperties.
value( key, defaultValue );
421 mCustomProperties.
remove( key );
426 return mCustomProperties.
keys();
436 QList< QgsLayoutItemMap * > maps;
439 double largestMapArea = 0;
442 double area = map->rect().width() * map->rect().height();
443 if ( area > largestMapArea )
445 largestMapArea = area;
454 mWorldFileMapId = map ? map->
uuid() : QString();
460 return mPageCollection.get();
465 return mPageCollection.get();
474 const auto constItems = items();
475 for (
const QGraphicsItem *item : constItems )
482 if ( !isPage || !ignorePages )
490 itemBounds = layoutItem->mapToScene( layoutItem->rect() ).boundingRect();
493 itemBounds = item->sceneBoundingRect();
495 if ( bounds.isValid() )
496 bounds = bounds.united( itemBounds );
502 if ( bounds.isValid() && margin > 0.0 )
505 double maxWidth = mPageCollection->maximumPageWidth();
506 bounds.adjust( -maxWidth * margin, -maxWidth * margin, maxWidth * margin, maxWidth * margin );
519 const QList<QGraphicsItem *> itemList = items();
520 for ( QGraphicsItem *item : itemList )
525 if ( visibleOnly && !layoutItem->isVisible() )
529 if ( bounds.isValid() )
530 bounds = bounds.united( item->sceneBoundingRect() );
532 bounds = item->sceneBoundingRect();
541 addLayoutItemPrivate( item );
545 undoText = tr(
"Create %1" ).arg( metadata->visibleName() );
549 undoText = tr(
"Create Item" );
551 if ( !mUndoStack->isBlocked() )
557 std::unique_ptr< QgsLayoutItemDeleteUndoCommand > deleteCommand;
558 if ( !mUndoStack->isBlocked() )
560 mUndoStack->beginMacro( tr(
"Delete Items" ) );
563 removeLayoutItemPrivate( item );
566 mUndoStack->push( deleteCommand.release() );
567 mUndoStack->endMacro();
576 if ( !mMultiFrames.contains( multiFrame ) )
577 mMultiFrames << multiFrame;
582 mMultiFrames.removeAll( multiFrame );
592 QFile templateFile( path );
593 if ( !templateFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
598 QDomDocument saveDocument;
599 QDomElement elem =
writeXml( saveDocument, context );
600 saveDocument.appendChild( elem );
602 if ( templateFile.write( saveDocument.toByteArray() ) == -1 )
613 QList< QgsLayoutItem * > result;
633 QDomNodeList itemsNodes = doc.elementsByTagName( QStringLiteral(
"LayoutItem" ) );
634 for (
int i = 0; i < itemsNodes.count(); ++i )
636 QDomNode itemNode = itemsNodes.at( i );
637 if ( itemNode.isElement() )
639 itemNode.toElement().removeAttribute( QStringLiteral(
"uuid" ) );
642 QDomNodeList multiFrameNodes = doc.elementsByTagName( QStringLiteral(
"LayoutMultiFrame" ) );
643 for (
int i = 0; i < multiFrameNodes.count(); ++i )
645 QDomNode multiFrameNode = multiFrameNodes.at( i );
646 if ( multiFrameNode.isElement() )
648 multiFrameNode.toElement().removeAttribute( QStringLiteral(
"uuid" ) );
649 QDomNodeList frameNodes = multiFrameNode.toElement().elementsByTagName( QStringLiteral(
"childFrame" ) );
650 QDomNode itemNode = frameNodes.at( i );
651 if ( itemNode.isElement() )
653 itemNode.toElement().removeAttribute( QStringLiteral(
"uuid" ) );
661 QDomElement layoutElem = doc.documentElement();
662 if ( layoutElem.isNull() )
667 bool loadOk =
readXml( layoutElem, doc, context );
687 return mUndoStack.get();
692 return mUndoStack.get();
707 void saveState( QDomDocument &stateDoc )
const override
710 QDomElement documentElement = stateDoc.createElement( QStringLiteral(
"UndoState" ) );
712 stateDoc.appendChild( documentElement );
722 mLayout->readXmlLayoutSettings( stateDoc.documentElement(), stateDoc,
QgsReadWriteContext() );
723 mLayout->project()->setDirty(
true );
739 if ( items.size() < 2 )
745 mUndoStack->beginMacro( tr(
"Group Items" ) );
749 itemGroup->addItem( item );
754 std::unique_ptr< QgsLayoutItemGroupUndoCommand >
c(
new QgsLayoutItemGroupUndoCommand( QgsLayoutItemGroupUndoCommand::Grouped, returnGroup,
this, tr(
"Group Items" ) ) );
755 mUndoStack->push(
c.release() );
758 mUndoStack->endMacro();
765 QList<QgsLayoutItem *> ungroupedItems;
768 return ungroupedItems;
771 mUndoStack->beginMacro( tr(
"Ungroup Items" ) );
774 std::unique_ptr< QgsLayoutItemGroupUndoCommand >
c(
new QgsLayoutItemGroupUndoCommand( QgsLayoutItemGroupUndoCommand::Ungrouped, group,
this, tr(
"Ungroup Items" ) ) );
775 mUndoStack->push(
c.release() );
779 ungroupedItems = group->
items();
783 mUndoStack->endMacro();
785 return ungroupedItems;
790 const QList< QGraphicsItem * > constItems = items();
791 for (
const QGraphicsItem *item : constItems )
797 if ( !layoutItem->
accept( visitor ) )
805 mUndoStack->blockCommands(
true );
806 mPageCollection->beginPageSizeChange();
808 mPageCollection->reflow();
809 mPageCollection->endPageSizeChange();
810 mUndoStack->blockCommands(
false );
814 void QgsLayout::writeXmlLayoutSettings( QDomElement &element, QDomDocument &document,
const QgsReadWriteContext & )
const
816 mCustomProperties.
writeXml( element, document );
818 element.setAttribute( QStringLiteral(
"worldFileMap" ), mWorldFileMapId );
819 element.setAttribute( QStringLiteral(
"printResolution" ), mRenderContext->
dpi() );
824 QDomElement element = document.createElement( QStringLiteral(
"Layout" ) );
827 return object->writeXml( element, document, context );
830 save( &mGridSettings );
831 save( mPageCollection.get() );
834 const QList<QGraphicsItem *> itemList = items();
835 for (
const QGraphicsItem *graphicsItem : itemList )
842 item->writeXml( element, document, context );
849 if ( mf->frameCount() > 0 )
850 mf->writeXml( element, document, context );
853 writeXmlLayoutSettings( element, document, context );
857 bool QgsLayout::readXmlLayoutSettings(
const QDomElement &layoutElement,
const QDomDocument &,
const QgsReadWriteContext & )
859 mCustomProperties.
readXml( layoutElement );
861 mWorldFileMapId = layoutElement.attribute( QStringLiteral(
"worldFileMap" ) );
862 mRenderContext->
setDpi( layoutElement.attribute( QStringLiteral(
"printResolution" ), QStringLiteral(
"300" ) ).toDouble() );
872 mItemsModel->rebuildZList();
876 void QgsLayout::removeLayoutItemPrivate(
QgsLayoutItem *item )
878 mItemsModel->setItemRemoved( item );
885 emit itemRemoved( item );
891 void QgsLayout::deleteAndRemoveMultiFrames()
893 qDeleteAll( mMultiFrames );
894 mMultiFrames.clear();
897 QPointF QgsLayout::minPointFromXml(
const QDomElement &elem )
const
899 double minX = std::numeric_limits<double>::max();
900 double minY = std::numeric_limits<double>::max();
901 const QDomNodeList itemList = elem.elementsByTagName( QStringLiteral(
"LayoutItem" ) );
903 for (
int i = 0; i < itemList.size(); ++i )
905 const QDomElement currentItemElem = itemList.at( i ).toElement();
910 minX = std::min( minX, layoutPoint.x() );
911 minY = std::min( minY, layoutPoint.y() );
914 return found ? QPointF( minX, minY ) : QPointF( 0, 0 );
919 int counter = mItemsModel->zOrderListSize();
920 const QList<QgsLayoutItem *> zOrderList = mItemsModel->zOrderList();
922 if ( addUndoCommands )
924 mUndoStack->beginMacro( tr(
"Change Item Stacking" ) );
930 if ( addUndoCommands )
932 mUndoStack->beginCommand( currentItem, QString() );
934 currentItem->setZValue( counter );
935 if ( addUndoCommands )
937 mUndoStack->endCommand();
942 if ( addUndoCommands )
944 mUndoStack->endMacro();
950 if ( layoutElement.nodeName() != QStringLiteral(
"Layout" ) )
957 return object->readXml( layoutElement, document, context );
960 blockSignals(
true );
961 readXmlLayoutSettings( layoutElement, document, context );
962 blockSignals(
false );
964 restore( mPageCollection.get() );
965 restore( &mSnapper );
966 restore( &mGridSettings );
976 QList< QgsLayoutItem * > newItems;
977 QList< QgsLayoutMultiFrame * > newMultiFrames;
982 int zOrderOffset = mItemsModel->zOrderListSize();
984 QPointF pasteShiftPos;
991 QPointF minItemPos = minPointFromXml( parentElement );
994 pasteShiftPos = *position - minItemPos;
997 pageNumber = mPageCollection->pageNumberForPoint( *position );
1003 const QDomNodeList multiFrameList = parentElement.elementsByTagName( QStringLiteral(
"LayoutMultiFrame" ) );
1004 for (
int i = 0; i < multiFrameList.size(); ++i )
1006 const QDomElement multiFrameElem = multiFrameList.at( i ).toElement();
1007 const int itemType = multiFrameElem.attribute( QStringLiteral(
"type" ) ).toInt();
1014 mf->readXml( multiFrameElem, document, context );
1017 mf->setCreateUndoCommands(
true );
1032 newMultiFrames << m;
1035 const QDomNodeList layoutItemList = parentElement.childNodes();
1036 for (
int i = 0; i < layoutItemList.size(); ++i )
1038 const QDomElement currentItemElem = layoutItemList.at( i ).toElement();
1039 if ( currentItemElem.nodeName() != QStringLiteral(
"LayoutItem" ) )
1042 const int itemType = currentItemElem.attribute( QStringLiteral(
"type" ) ).toInt();
1050 item->readXml( currentItemElem, document, context );
1056 item->attemptMove( posOnPage,
true,
false, pageNumber );
1060 item->attemptMoveBy( pasteShiftPos.x(), pasteShiftPos.y() );
1066 layoutItem->setZValue( layoutItem->zValue() + zOrderOffset );
1067 newItems << layoutItem;
1080 mf->finalizeRestoreFromXml();
1085 item->mTemplateUuid.clear();
1089 mf->mTemplateUuid.clear();
1095 mItemsModel->rebuildZList();
1105 void QgsLayout::itemBackgroundTaskCountChanged(
int count )
1107 QgsLayoutItem *item = qobject_cast<QgsLayoutItem *>( sender() );
1112 mBackgroundTaskCount.insert( item, count );
1114 mBackgroundTaskCount.remove( item );
1118 for (
auto it = mBackgroundTaskCount.constBegin(); it != mBackgroundTaskCount.constEnd(); ++it )
1120 total += it.value();