41 , mGridSettings( this )
46 setBackgroundBrush( Qt::NoBrush );
53 mUndoStack->blockCommands(
true );
55 deleteAndRemoveMultiFrames();
63 QList<QGraphicsItem *> itemList = items();
68 for ( QGraphicsItem *item : std::as_const( itemList ) )
85 QDomDocument currentDoc;
88 QDomElement elem =
writeXml( currentDoc, context );
89 currentDoc.appendChild( elem );
91 std::unique_ptr< QgsLayout > newLayout = std::make_unique< QgsLayout >( mProject );
93 newLayout->loadFromTemplate( currentDoc, context,
true, &ok );
99 return newLayout.release();
107 mPageCollection->addPage( page );
108 mUndoStack->stack()->clear();
113 deleteAndRemoveMultiFrames();
116 const QList<QGraphicsItem *> itemList = items();
117 for ( QGraphicsItem *item : itemList )
121 if ( cItem && !pItem )
123 removeLayoutItemPrivate( cItem );
126 mItemsModel->clear();
128 mPageCollection->clear();
129 mUndoStack->stack()->clear();
139 return mItemsModel.get();
144 QList<QgsLayoutItem *> layoutItemList;
146 const QList<QGraphicsItem *> graphicsItemList = selectedItems();
147 for ( QGraphicsItem *item : graphicsItemList )
150 if ( layoutItem && ( includeLockedItems || !layoutItem->
isLocked() ) )
152 layoutItemList.push_back( layoutItem );
156 return layoutItemList;
175 const QList<QGraphicsItem *> selectedItemList = selectedItems();
176 for ( QGraphicsItem *item : selectedItemList )
180 layoutItem->setSelected(
false );
189 bool result = mItemsModel->reorderItemUp( item );
190 if ( result && !deferUpdate )
202 bool result = mItemsModel->reorderItemDown( item );
203 if ( result && !deferUpdate )
215 bool result = mItemsModel->reorderItemToTop( item );
216 if ( result && !deferUpdate )
228 bool result = mItemsModel->reorderItemToBottom( item );
229 if ( result && !deferUpdate )
240 QList<QgsLayoutItem *> itemList;
244 if ( item->uuid() == uuid )
246 else if ( includeTemplateUuids && item->mTemplateUuid == uuid )
255 QList<QgsLayoutItem *> itemList;
259 if ( item->mTemplateUuid == uuid )
268 const QList<QGraphicsItem *> itemList = items();
269 for ( QGraphicsItem *item : itemList )
272 if ( layoutItem && layoutItem->
id() == id )
284 if ( mf->uuid() == uuid )
286 else if ( includeTemplateUuids && mf->mTemplateUuid == uuid )
301 const QList<QGraphicsItem *> itemList = items( position, Qt::IntersectsItemShape, Qt::DescendingOrder );
303 bool foundBelowItem =
false;
304 for ( QGraphicsItem *graphicsItem : itemList )
308 if ( layoutItem && !paperItem )
312 if ( ( ! belowItem || foundBelowItem ) && ( !ignoreLocked || !layoutItem->
isLocked() ) )
318 if ( layoutItem == belowItem )
321 foundBelowItem =
true;
361 return *mRenderContext;
366 return *mRenderContext;
371 return *mReportContext;
376 return *mReportContext;
382 mPageCollection->redraw();
387 return mPageCollection->guides();
392 return mPageCollection->guides();
400 if ( mReportContext->
layer() )
409 mCustomProperties.
setValue( key, value );
411 if ( key.startsWith( QLatin1String(
"variable" ) ) )
417 return mCustomProperties.
value( key, defaultValue );
422 mCustomProperties.
remove( key );
427 return mCustomProperties.
keys();
437 QList< QgsLayoutItemMap * > maps;
440 double largestMapArea = 0;
443 double area = map->rect().width() * map->rect().height();
444 if ( area > largestMapArea )
446 largestMapArea = area;
455 mWorldFileMapId = map ? map->
uuid() : QString();
461 return mPageCollection.get();
466 return mPageCollection.get();
475 const auto constItems = items();
476 for (
const QGraphicsItem *item : constItems )
483 if ( !isPage || !ignorePages )
491 itemBounds = layoutItem->mapToScene( layoutItem->rect() ).boundingRect();
494 itemBounds = item->sceneBoundingRect();
496 if ( bounds.isValid() )
497 bounds = bounds.united( itemBounds );
503 if ( bounds.isValid() && margin > 0.0 )
506 double maxWidth = mPageCollection->maximumPageWidth();
507 bounds.adjust( -maxWidth * margin, -maxWidth * margin, maxWidth * margin, maxWidth * margin );
520 const QList<QGraphicsItem *> itemList = items();
521 for ( QGraphicsItem *item : itemList )
526 if ( visibleOnly && !layoutItem->isVisible() )
530 if ( bounds.isValid() )
531 bounds = bounds.united( item->sceneBoundingRect() );
533 bounds = item->sceneBoundingRect();
542 addLayoutItemPrivate( item );
546 undoText = tr(
"Create %1" ).arg( metadata->visibleName() );
550 undoText = tr(
"Create Item" );
552 if ( !mUndoStack->isBlocked() )
558 std::unique_ptr< QgsLayoutItemDeleteUndoCommand > deleteCommand;
559 if ( !mUndoStack->isBlocked() )
561 mUndoStack->beginMacro( tr(
"Delete Items" ) );
564 removeLayoutItemPrivate( item );
567 mUndoStack->push( deleteCommand.release() );
568 mUndoStack->endMacro();
577 if ( !mMultiFrames.contains( multiFrame ) )
578 mMultiFrames << multiFrame;
583 mMultiFrames.removeAll( multiFrame );
593 QFile templateFile( path );
594 if ( !templateFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
599 QDomDocument saveDocument;
600 QDomElement elem =
writeXml( saveDocument, context );
601 saveDocument.appendChild( elem );
603 if ( templateFile.write( saveDocument.toByteArray() ) == -1 )
614 QList< QgsLayoutItem * > result;
634 QDomNodeList itemsNodes = doc.elementsByTagName( QStringLiteral(
"LayoutItem" ) );
635 for (
int i = 0; i < itemsNodes.count(); ++i )
637 QDomNode itemNode = itemsNodes.at( i );
638 if ( itemNode.isElement() )
640 itemNode.toElement().removeAttribute( QStringLiteral(
"uuid" ) );
643 QDomNodeList multiFrameNodes = doc.elementsByTagName( QStringLiteral(
"LayoutMultiFrame" ) );
644 for (
int i = 0; i < multiFrameNodes.count(); ++i )
646 QDomNode multiFrameNode = multiFrameNodes.at( i );
647 if ( multiFrameNode.isElement() )
649 multiFrameNode.toElement().removeAttribute( QStringLiteral(
"uuid" ) );
650 QDomNodeList frameNodes = multiFrameNode.toElement().elementsByTagName( QStringLiteral(
"childFrame" ) );
651 QDomNode itemNode = frameNodes.at( i );
652 if ( itemNode.isElement() )
654 itemNode.toElement().removeAttribute( QStringLiteral(
"uuid" ) );
662 QDomElement layoutElem = doc.documentElement();
663 if ( layoutElem.isNull() )
668 bool loadOk =
readXml( layoutElem, doc, context );
688 return mUndoStack.get();
693 return mUndoStack.get();
708 void saveState( QDomDocument &stateDoc )
const override
711 QDomElement documentElement = stateDoc.createElement( QStringLiteral(
"UndoState" ) );
713 stateDoc.appendChild( documentElement );
723 mLayout->readXmlLayoutSettings( stateDoc.documentElement(), stateDoc,
QgsReadWriteContext() );
724 mLayout->project()->setDirty(
true );
740 if ( items.size() < 2 )
746 mUndoStack->beginMacro( tr(
"Group Items" ) );
750 itemGroup->addItem( item );
755 std::unique_ptr< QgsLayoutItemGroupUndoCommand >
c(
new QgsLayoutItemGroupUndoCommand( QgsLayoutItemGroupUndoCommand::Grouped, returnGroup,
this, tr(
"Group Items" ) ) );
756 mUndoStack->push(
c.release() );
759 mUndoStack->endMacro();
766 QList<QgsLayoutItem *> ungroupedItems;
769 return ungroupedItems;
772 mUndoStack->beginMacro( tr(
"Ungroup Items" ) );
775 std::unique_ptr< QgsLayoutItemGroupUndoCommand >
c(
new QgsLayoutItemGroupUndoCommand( QgsLayoutItemGroupUndoCommand::Ungrouped, group,
this, tr(
"Ungroup Items" ) ) );
776 mUndoStack->push(
c.release() );
780 ungroupedItems = group->
items();
784 mUndoStack->endMacro();
786 return ungroupedItems;
791 const QList< QGraphicsItem * > constItems = items();
792 for (
const QGraphicsItem *item : constItems )
798 if ( !layoutItem->
accept( visitor ) )
806 mUndoStack->blockCommands(
true );
807 mPageCollection->beginPageSizeChange();
809 mPageCollection->reflow();
810 mPageCollection->endPageSizeChange();
811 mUndoStack->blockCommands(
false );
815 void QgsLayout::writeXmlLayoutSettings( QDomElement &element, QDomDocument &document,
const QgsReadWriteContext & )
const
817 mCustomProperties.
writeXml( element, document );
819 element.setAttribute( QStringLiteral(
"worldFileMap" ), mWorldFileMapId );
820 element.setAttribute( QStringLiteral(
"printResolution" ), mRenderContext->
dpi() );
825 QDomElement element = document.createElement( QStringLiteral(
"Layout" ) );
828 return object->writeXml( element, document, context );
831 save( &mGridSettings );
832 save( mPageCollection.get() );
835 const QList<QGraphicsItem *> itemList = items();
836 for (
const QGraphicsItem *graphicsItem : itemList )
843 item->writeXml( element, document, context );
850 if ( mf->frameCount() > 0 )
851 mf->writeXml( element, document, context );
854 writeXmlLayoutSettings( element, document, context );
858 bool QgsLayout::readXmlLayoutSettings(
const QDomElement &layoutElement,
const QDomDocument &,
const QgsReadWriteContext & )
860 mCustomProperties.
readXml( layoutElement );
862 mWorldFileMapId = layoutElement.attribute( QStringLiteral(
"worldFileMap" ) );
863 mRenderContext->
setDpi( layoutElement.attribute( QStringLiteral(
"printResolution" ), QStringLiteral(
"300" ) ).toDouble() );
873 mItemsModel->rebuildZList();
878 void QgsLayout::removeLayoutItemPrivate(
QgsLayoutItem *item )
880 mItemsModel->setItemRemoved( item );
887 emit itemRemoved( item );
893 void QgsLayout::deleteAndRemoveMultiFrames()
895 qDeleteAll( mMultiFrames );
896 mMultiFrames.clear();
899 QPointF QgsLayout::minPointFromXml(
const QDomElement &elem )
const
901 double minX = std::numeric_limits<double>::max();
902 double minY = std::numeric_limits<double>::max();
903 const QDomNodeList itemList = elem.elementsByTagName( QStringLiteral(
"LayoutItem" ) );
905 for (
int i = 0; i < itemList.size(); ++i )
907 const QDomElement currentItemElem = itemList.at( i ).toElement();
912 minX = std::min( minX, layoutPoint.x() );
913 minY = std::min( minY, layoutPoint.y() );
916 return found ? QPointF( minX, minY ) : QPointF( 0, 0 );
921 int counter = mItemsModel->zOrderListSize();
922 const QList<QgsLayoutItem *> zOrderList = mItemsModel->zOrderList();
924 if ( addUndoCommands )
926 mUndoStack->beginMacro( tr(
"Change Item Stacking" ) );
932 if ( addUndoCommands )
934 mUndoStack->beginCommand( currentItem, QString() );
936 currentItem->setZValue( counter );
937 if ( addUndoCommands )
939 mUndoStack->endCommand();
944 if ( addUndoCommands )
946 mUndoStack->endMacro();
952 if ( layoutElement.nodeName() != QLatin1String(
"Layout" ) )
959 return object->readXml( layoutElement, document, context );
962 std::unique_ptr< QgsScopedRuntimeProfile > profile;
964 profile = std::make_unique< QgsScopedRuntimeProfile >( tr(
"Read layout settings" ), QStringLiteral(
"projectload" ) );
966 blockSignals(
true );
967 readXmlLayoutSettings( layoutElement, document, context );
968 blockSignals(
false );
971 profile->switchTask( tr(
"Load pages" ) );
972 restore( mPageCollection.get() );
974 profile->switchTask( tr(
"Load snapping settings" ) );
975 restore( &mSnapper );
977 profile->switchTask( tr(
"Load grid settings" ) );
978 restore( &mGridSettings );
981 profile->switchTask( tr(
"Restore items" ) );
991 QList< QgsLayoutItem * > newItems;
992 QList< QgsLayoutMultiFrame * > newMultiFrames;
997 int zOrderOffset = mItemsModel->zOrderListSize();
999 QPointF pasteShiftPos;
1000 int pageNumber = -1;
1006 QPointF minItemPos = minPointFromXml( parentElement );
1009 pasteShiftPos = *position - minItemPos;
1012 pageNumber = mPageCollection->pageNumberForPoint( *position );
1016 std::unique_ptr< QgsScopedRuntimeProfile > profile;
1018 profile = std::make_unique< QgsScopedRuntimeProfile >( tr(
"Read items" ), QStringLiteral(
"projectload" ) );
1023 const QDomNodeList multiFrameList = parentElement.elementsByTagName( QStringLiteral(
"LayoutMultiFrame" ) );
1024 for (
int i = 0; i < multiFrameList.size(); ++i )
1026 const QDomElement multiFrameElem = multiFrameList.at( i ).toElement();
1027 const int itemType = multiFrameElem.attribute( QStringLiteral(
"type" ) ).toInt();
1033 profile->switchTask( tr(
"Load %1" ).arg( metadata->visibleName() ) );
1043 mf->readXml( multiFrameElem, document, context );
1046 mf->setCreateUndoCommands(
true );
1061 newMultiFrames << m;
1064 const QDomNodeList layoutItemList = parentElement.childNodes();
1065 for (
int i = 0; i < layoutItemList.size(); ++i )
1067 const QDomElement currentItemElem = layoutItemList.at( i ).toElement();
1068 if ( currentItemElem.nodeName() != QLatin1String(
"LayoutItem" ) )
1071 const int itemType = currentItemElem.attribute( QStringLiteral(
"type" ) ).toInt();
1077 profile->switchTask( tr(
"Load %1" ).arg( metadata->visibleName() ) );
1088 item->readXml( currentItemElem, document, context );
1094 item->attemptMove( posOnPage,
true,
false, pageNumber );
1098 item->attemptMoveBy( pasteShiftPos.x(), pasteShiftPos.y() );
1104 layoutItem->setZValue( layoutItem->zValue() + zOrderOffset );
1105 newItems << layoutItem;
1112 std::unique_ptr< QgsScopedRuntimeProfile > itemProfile;
1115 profile->switchTask( tr(
"Finalize restore" ) );
1120 itemProfile = std::make_unique< QgsScopedRuntimeProfile >( item->
displayName(), QStringLiteral(
"projectload" ) );
1123 itemProfile.reset();
1128 itemProfile = std::make_unique< QgsScopedRuntimeProfile >( mf->displayName(), QStringLiteral(
"projectload" ) );
1129 mf->finalizeRestoreFromXml();
1131 itemProfile.reset();
1136 item->mTemplateUuid.clear();
1140 mf->mTemplateUuid.clear();
1148 profile->switchTask( tr(
"Update model" ) );
1149 mItemsModel->rebuildZList();
1159 void QgsLayout::itemBackgroundTaskCountChanged(
int count )
1161 QgsLayoutItem *item = qobject_cast<QgsLayoutItem *>( sender() );
1166 mBackgroundTaskCount.insert( item, count );
1168 mBackgroundTaskCount.remove( item );
1172 for (
auto it = mBackgroundTaskCount.constBegin(); it != mBackgroundTaskCount.constEnd(); ++it )
1174 total += it.value();