Skip to content

Commit

Permalink
Add a clone method to QgsLayout
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jan 5, 2018
1 parent 5bc543a commit 4d2f0de
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 10 deletions.
6 changes: 6 additions & 0 deletions python/core/layout/qgslayout.sip
Expand Up @@ -56,6 +56,12 @@ called on the new layout.

~QgsLayout();

virtual QgsLayout *clone() const /Factory/;
%Docstring
Creates a clone of the layout. Ownership of the return layout
is transferred to the caller.
%End

void initializeDefaults();
%Docstring
Initializes an empty layout, e.g. by adding a default page to the layout. This should be called after creating
Expand Down
3 changes: 3 additions & 0 deletions python/core/layout/qgsprintlayout.sip
Expand Up @@ -26,6 +26,9 @@ class QgsPrintLayout : QgsLayout
Constructor for QgsPrintLayout.
%End

virtual QgsPrintLayout *clone() const /Factory/;


QgsLayoutAtlas *atlas();
%Docstring
Returns the print layout's atlas.
Expand Down
12 changes: 2 additions & 10 deletions src/core/composer/qgslayoutmanager.cpp
Expand Up @@ -283,16 +283,8 @@ QgsComposition *QgsLayoutManager::duplicateComposition( const QString &name, con

QgsLayout *QgsLayoutManager::duplicateLayout( const QgsLayout *layout, const QString &newName )
{
QDomDocument currentDoc;

QgsReadWriteContext context;
QDomElement elem = layout->writeXml( currentDoc, context );
currentDoc.appendChild( elem );

std::unique_ptr< QgsLayout > newLayout = qgis::make_unique< QgsPrintLayout >( mProject );
bool ok = false;
newLayout->loadFromTemplate( currentDoc, context, true, &ok );
if ( !ok )
std::unique_ptr< QgsLayout > newLayout( layout->clone() );
if ( !newLayout )
{
return nullptr;
}
Expand Down
19 changes: 19 additions & 0 deletions src/core/layout/qgslayout.cpp
Expand Up @@ -75,6 +75,25 @@ QgsLayout::~QgsLayout()
mItemsModel.reset(); // manually delete, so we can control order of destruction
}

QgsLayout *QgsLayout::clone() const
{
QDomDocument currentDoc;

QgsReadWriteContext context;
QDomElement elem = writeXml( currentDoc, context );
currentDoc.appendChild( elem );

std::unique_ptr< QgsLayout > newLayout = qgis::make_unique< QgsLayout >( mProject );
bool ok = false;
newLayout->loadFromTemplate( currentDoc, context, true, &ok );
if ( !ok )
{
return nullptr;
}

return newLayout.release();
}

void QgsLayout::initializeDefaults()
{
// default to a A4 landscape page
Expand Down
6 changes: 6 additions & 0 deletions src/core/layout/qgslayout.h
Expand Up @@ -83,6 +83,12 @@ class CORE_EXPORT QgsLayout : public QGraphicsScene, public QgsExpressionContext

~QgsLayout() override;

/**
* Creates a clone of the layout. Ownership of the return layout
* is transferred to the caller.
*/
virtual QgsLayout *clone() const SIP_FACTORY;

/**
* Initializes an empty layout, e.g. by adding a default page to the layout. This should be called after creating
* a new layout.
Expand Down
20 changes: 20 additions & 0 deletions src/core/layout/qgsprintlayout.cpp
Expand Up @@ -16,13 +16,33 @@

#include "qgsprintlayout.h"
#include "qgslayoutatlas.h"
#include "qgsreadwritecontext.h"

QgsPrintLayout::QgsPrintLayout( QgsProject *project )
: QgsLayout( project )
, mAtlas( new QgsLayoutAtlas( this ) )
{
}

QgsPrintLayout *QgsPrintLayout::clone() const
{
QDomDocument currentDoc;

QgsReadWriteContext context;
QDomElement elem = writeXml( currentDoc, context );
currentDoc.appendChild( elem );

std::unique_ptr< QgsPrintLayout > newLayout = qgis::make_unique< QgsPrintLayout >( project() );
bool ok = false;
newLayout->loadFromTemplate( currentDoc, context, true, &ok );
if ( !ok )
{
return nullptr;
}

return newLayout.release();
}

QgsLayoutAtlas *QgsPrintLayout::atlas()
{
return mAtlas;
Expand Down
2 changes: 2 additions & 0 deletions src/core/layout/qgsprintlayout.h
Expand Up @@ -38,6 +38,8 @@ class CORE_EXPORT QgsPrintLayout : public QgsLayout
*/
QgsPrintLayout( QgsProject *project );

QgsPrintLayout *clone() const override SIP_FACTORY;

/**
* Returns the print layout's atlas.
*/
Expand Down
41 changes: 41 additions & 0 deletions tests/src/core/testqgslayout.cpp
Expand Up @@ -26,6 +26,8 @@
#include "qgslayoutitempolyline.h"
#include "qgslayoutitemhtml.h"
#include "qgslayoutframe.h"
#include "qgsprintlayout.h"
#include "qgslayoutatlas.h"

class TestQgsLayout: public QObject
{
Expand Down Expand Up @@ -54,6 +56,7 @@ class TestQgsLayout: public QObject
void pageIsEmpty();
void clear();
void georeference();
void clone();

private:
QString mReport;
Expand Down Expand Up @@ -844,6 +847,44 @@ void TestQgsLayout::georeference()
t.reset();
}

void TestQgsLayout::clone()
{
QgsProject proj;
QgsLayout l( &proj );
QgsLayoutItemPage *page = new QgsLayoutItemPage( &l );
page->setPageSize( "A4" );
l.pageCollection()->addPage( page );
QgsLayoutItemPage *page2 = new QgsLayoutItemPage( &l );
page2->setPageSize( "A4" );
l.pageCollection()->addPage( page2 );
QgsLayoutItemPage *page3 = new QgsLayoutItemPage( &l );
page3->setPageSize( "A4" );
l.pageCollection()->addPage( page3 );

//add some items to the composition
QgsLayoutItemShape *label1 = new QgsLayoutItemShape( &l );
l.addLayoutItem( label1 );
QgsLayoutItemShape *label2 = new QgsLayoutItemShape( &l );
l.addLayoutItem( label2 );
QgsLayoutItemShape *label3 = new QgsLayoutItemShape( &l );
l.addLayoutItem( label3 );

// clone and check a few poperties
std::unique_ptr< QgsLayout > cloned( l.clone() );
QVERIFY( cloned.get() );
QCOMPARE( cloned->pageCollection()->pageCount(), 3 );
QList< QgsLayoutItem * > items;
cloned->layoutItems( items );
QCOMPARE( items.count(), 6 ); // 3 pages + 3 items

// clone a print layout
QgsPrintLayout pl( &proj );
pl.atlas()->setPageNameExpression( QStringLiteral( "not a real expression" ) );
std::unique_ptr< QgsPrintLayout > plClone( pl.clone() );
QVERIFY( plClone.get() );
QCOMPARE( plClone->atlas()->pageNameExpression(), QStringLiteral( "not a real expression" ) );
}


QGSTEST_MAIN( TestQgsLayout )
#include "testqgslayout.moc"

0 comments on commit 4d2f0de

Please sign in to comment.