41 , mGridSettings( this )
46 setBackgroundBrush( Qt::NoBrush );
53 mUndoStack->blockCommands(
true );
55 deleteAndRemoveMultiFrames();
63 QList<QGraphicsItem *> itemList = items();
68 for ( QGraphicsItem *item : qgis::as_const( itemList ) )
85 QDomDocument currentDoc;
88 QDomElement elem =
writeXml( currentDoc, context );
89 currentDoc.appendChild( elem );
91 std::unique_ptr< QgsLayout > newLayout = qgis::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();
877 void QgsLayout::removeLayoutItemPrivate(
QgsLayoutItem *item )
879 mItemsModel->setItemRemoved( item );
886 emit itemRemoved( item );
892 void QgsLayout::deleteAndRemoveMultiFrames()
894 qDeleteAll( mMultiFrames );
895 mMultiFrames.clear();
898 QPointF QgsLayout::minPointFromXml(
const QDomElement &elem )
const
900 double minX = std::numeric_limits<double>::max();
901 double minY = std::numeric_limits<double>::max();
902 const QDomNodeList itemList = elem.elementsByTagName( QStringLiteral(
"LayoutItem" ) );
904 for (
int i = 0; i < itemList.size(); ++i )
906 const QDomElement currentItemElem = itemList.at( i ).toElement();
911 minX = std::min( minX, layoutPoint.x() );
912 minY = std::min( minY, layoutPoint.y() );
915 return found ? QPointF( minX, minY ) : QPointF( 0, 0 );
920 int counter = mItemsModel->zOrderListSize();
921 const QList<QgsLayoutItem *> zOrderList = mItemsModel->zOrderList();
923 if ( addUndoCommands )
925 mUndoStack->beginMacro( tr(
"Change Item Stacking" ) );
931 if ( addUndoCommands )
933 mUndoStack->beginCommand( currentItem, QString() );
935 currentItem->setZValue( counter );
936 if ( addUndoCommands )
938 mUndoStack->endCommand();
943 if ( addUndoCommands )
945 mUndoStack->endMacro();
951 if ( layoutElement.nodeName() != QLatin1String(
"Layout" ) )
958 return object->readXml( layoutElement, document, context );
961 std::unique_ptr< QgsScopedRuntimeProfile > profile;
963 profile = qgis::make_unique< QgsScopedRuntimeProfile >( tr(
"Read layout settings" ), QStringLiteral(
"projectload" ) );
965 blockSignals(
true );
966 readXmlLayoutSettings( layoutElement, document, context );
967 blockSignals(
false );
970 profile->switchTask( tr(
"Load pages" ) );
971 restore( mPageCollection.get() );
973 profile->switchTask( tr(
"Load snapping settings" ) );
974 restore( &mSnapper );
976 profile->switchTask( tr(
"Load grid settings" ) );
977 restore( &mGridSettings );
980 profile->switchTask( tr(
"Restore items" ) );
990 QList< QgsLayoutItem * > newItems;
991 QList< QgsLayoutMultiFrame * > newMultiFrames;
996 int zOrderOffset = mItemsModel->zOrderListSize();
998 QPointF pasteShiftPos;
1005 QPointF minItemPos = minPointFromXml( parentElement );
1008 pasteShiftPos = *position - minItemPos;
1011 pageNumber = mPageCollection->pageNumberForPoint( *position );
1015 std::unique_ptr< QgsScopedRuntimeProfile > profile;
1017 profile = qgis::make_unique< QgsScopedRuntimeProfile >( tr(
"Read items" ), QStringLiteral(
"projectload" ) );
1022 const QDomNodeList multiFrameList = parentElement.elementsByTagName( QStringLiteral(
"LayoutMultiFrame" ) );
1023 for (
int i = 0; i < multiFrameList.size(); ++i )
1025 const QDomElement multiFrameElem = multiFrameList.at( i ).toElement();
1026 const int itemType = multiFrameElem.attribute( QStringLiteral(
"type" ) ).toInt();
1032 profile->switchTask( tr(
"Load %1" ).arg( metadata->visibleName() ) );
1042 mf->readXml( multiFrameElem, document, context );
1045 mf->setCreateUndoCommands(
true );
1060 newMultiFrames << m;
1063 const QDomNodeList layoutItemList = parentElement.childNodes();
1064 for (
int i = 0; i < layoutItemList.size(); ++i )
1066 const QDomElement currentItemElem = layoutItemList.at( i ).toElement();
1067 if ( currentItemElem.nodeName() != QLatin1String(
"LayoutItem" ) )
1070 const int itemType = currentItemElem.attribute( QStringLiteral(
"type" ) ).toInt();
1076 profile->switchTask( tr(
"Load %1" ).arg( metadata->visibleName() ) );
1087 item->readXml( currentItemElem, document, context );
1093 item->attemptMove( posOnPage,
true,
false, pageNumber );
1097 item->attemptMoveBy( pasteShiftPos.x(), pasteShiftPos.y() );
1103 layoutItem->setZValue( layoutItem->zValue() + zOrderOffset );
1104 newItems << layoutItem;
1111 std::unique_ptr< QgsScopedRuntimeProfile > itemProfile;
1114 profile->switchTask( tr(
"Finalize restore" ) );
1119 itemProfile = qgis::make_unique< QgsScopedRuntimeProfile >( item->
displayName(), QStringLiteral(
"projectload" ) );
1122 itemProfile.reset();
1127 itemProfile = qgis::make_unique< QgsScopedRuntimeProfile >( mf->displayName(), QStringLiteral(
"projectload" ) );
1128 mf->finalizeRestoreFromXml();
1130 itemProfile.reset();
1135 item->mTemplateUuid.clear();
1139 mf->mTemplateUuid.clear();
1147 profile->switchTask( tr(
"Update model" ) );
1148 mItemsModel->rebuildZList();
1158 void QgsLayout::itemBackgroundTaskCountChanged(
int count )
1160 QgsLayoutItem *item = qobject_cast<QgsLayoutItem *>( sender() );
1165 mBackgroundTaskCount.insert( item, count );
1167 mBackgroundTaskCount.remove( item );
1171 for (
auto it = mBackgroundTaskCount.constBegin(); it != mBackgroundTaskCount.constEnd(); ++it )
1173 total += it.value();