Merge pull request #6470 from elpaso/template-convert

[layout] Automatic conversion of 2.x composition templates to layouts
This commit is contained in:
Alessandro Pasotti 2018-02-27 09:14:03 +00:00 committed by GitHub
commit 91b9a69d3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 112 additions and 4 deletions

View File

@ -452,6 +452,29 @@ QList<QgsLayoutObject *> QgsCompositionConverter::addItemsFromCompositionXml( Qg
return newItems; return newItems;
} }
bool QgsCompositionConverter::isCompositionTemplate( const QDomDocument &document )
{
return document.elementsByTagName( QStringLiteral( "Composition" ) ).count() > 0;
}
QDomDocument QgsCompositionConverter::convertCompositionTemplate( const QDomDocument &document, QgsProject *project )
{
QDomDocument doc;
QgsReadWriteContext context;
if ( project )
context.setPathResolver( project->pathResolver() );
if ( document.elementsByTagName( QStringLiteral( "Composition" ) ).count( ) > 0 )
{
QDomElement composerElem = document.elementsByTagName( QStringLiteral( "Composition" ) ).at( 0 ).toElement( );
std::unique_ptr<QgsLayout> layout = createLayoutFromCompositionXml( composerElem,
project );
QDomElement elem = layout->writeXml( doc, context );
doc.appendChild( elem );
}
return doc;
}
bool QgsCompositionConverter::readLabelXml( QgsLayoutItemLabel *layoutItem, const QDomElement &itemElem, const QgsProject *project ) bool QgsCompositionConverter::readLabelXml( QgsLayoutItemLabel *layoutItem, const QDomElement &itemElem, const QgsProject *project )
{ {
Q_UNUSED( project ); Q_UNUSED( project );

View File

@ -144,6 +144,24 @@ class CORE_EXPORT QgsCompositionConverter
QPointF *position = nullptr, QPointF *position = nullptr,
bool pasteInPlace = false ); bool pasteInPlace = false );
/**
* Check if the given \a document is a composition template
* \return true if the document is a composition template
* \since QGIS 3.0.1
*/
static bool isCompositionTemplate( const QDomDocument &document );
/**
* Convert a composition template \a document to a layout template
* \param document containing a composition
* \param project
* \return dom document with the converted template
* \since QGIS 3.0.1
*/
static QDomDocument convertCompositionTemplate( const QDomDocument
&document, QgsProject *project );
private: private:

View File

@ -27,6 +27,7 @@
#include "qgslayoutmultiframe.h" #include "qgslayoutmultiframe.h"
#include "qgslayoutitemmap.h" #include "qgslayoutitemmap.h"
#include "qgslayoutundostack.h" #include "qgslayoutundostack.h"
#include "qgscompositionconverter.h"
QgsLayout::QgsLayout( QgsProject *project ) QgsLayout::QgsLayout( QgsProject *project )
: mProject( project ) : mProject( project )
@ -609,7 +610,17 @@ QList< QgsLayoutItem * > QgsLayout::loadFromTemplate( const QDomDocument &docume
clear(); clear();
} }
QDomDocument doc = document; QDomDocument doc;
// If this is a 2.x composition template, convert it to a layout template
if ( QgsCompositionConverter::isCompositionTemplate( document ) )
{
doc = QgsCompositionConverter::convertCompositionTemplate( document, mProject );
}
else
{
doc = document;
}
// remove all uuid attributes since we don't want duplicates UUIDS // remove all uuid attributes since we don't want duplicates UUIDS
QDomNodeList itemsNodes = doc.elementsByTagName( QStringLiteral( "LayoutItem" ) ); QDomNodeList itemsNodes = doc.elementsByTagName( QStringLiteral( "LayoutItem" ) );

View File

@ -44,6 +44,16 @@
#include "qgslayoutitemattributetable.h" #include "qgslayoutitemattributetable.h"
// Debug output for dom nodes
QDebug operator<<( QDebug dbg, const QDomNode &node )
{
QString s;
QTextStream str( &s, QIODevice::WriteOnly );
node.save( str, 2 );
dbg << qPrintable( s );
return dbg;
}
class TestQgsCompositionConverter: public QObject class TestQgsCompositionConverter: public QObject
{ {
Q_OBJECT Q_OBJECT
@ -125,7 +135,17 @@ class TestQgsCompositionConverter: public QObject
/** /**
* Test automatic conversion from a composer template * Test automatic conversion from a composer template
*/ */
void convertComposerTemplate(); void convertComposition();
/**
* Test if a composition template can be detected from a dom document
*/
void isCompositionTemplate();
/**
* Test if a composition template can be converted to a layout template
*/
void convertCompositionTemplate();
private: private:
@ -523,7 +543,7 @@ void TestQgsCompositionConverter::importComposerTemplateScaleBar()
} }
void TestQgsCompositionConverter::convertComposerTemplate() void TestQgsCompositionConverter::convertComposition()
{ {
QgsProject project; QgsProject project;
@ -541,6 +561,42 @@ void TestQgsCompositionConverter::convertComposerTemplate()
} }
void TestQgsCompositionConverter::isCompositionTemplate()
{
QString templatePath( QStringLiteral( TEST_DATA_DIR ) + "/layouts/2x_template.qpt" );
QDomDocument doc( "mydocument" );
QFile file( templatePath );
file.open( QIODevice::ReadOnly );
doc.setContent( &file );
file.close();
QVERIFY( QgsCompositionConverter::isCompositionTemplate( doc ) );
}
void TestQgsCompositionConverter::convertCompositionTemplate()
{
QString templatePath( QStringLiteral( TEST_DATA_DIR ) + "/layouts/2x_template.qpt" );
QDomDocument doc( "mydocument" );
QFile file( templatePath );
file.open( QIODevice::ReadOnly );
doc.setContent( &file );
file.close();
QgsProject project;
QDomDocument layoutDoc = QgsCompositionConverter::convertCompositionTemplate( doc, &project );
//qDebug() << layoutDoc;
QCOMPARE( layoutDoc.elementsByTagName( QStringLiteral( "Layout" ) ).count(), 1 );
std::unique_ptr<QgsLayout> layout = qgis::make_unique<QgsLayout>( &project );
QgsReadWriteContext context;
context.setPathResolver( project.pathResolver() );
layout->readXml( layoutDoc.elementsByTagName( QStringLiteral( "Layout" ) ).at( 0 ).toElement(), layoutDoc, context );
QVERIFY( layout.get() );
QCOMPARE( layout->pageCollection()->pageCount(), 2 );
}
void TestQgsCompositionConverter::importComposerTemplate() void TestQgsCompositionConverter::importComposerTemplate()
{ {
QDomElement composerElem( loadComposer( "2x_template.qpt" ) ); QDomElement composerElem( loadComposer( "2x_template.qpt" ) );
@ -646,7 +702,7 @@ void TestQgsCompositionConverter::checkRenderedImage( QgsLayout *layout, const Q
QSize size( layout->pageCollection()->page( pageNumber )->sizeWithUnits().width() * 3.77, layout->pageCollection()->page( pageNumber )->sizeWithUnits().height() * 3.77 ); QSize size( layout->pageCollection()->page( pageNumber )->sizeWithUnits().width() * 3.77, layout->pageCollection()->page( pageNumber )->sizeWithUnits().height() * 3.77 );
checker.setSize( size ); checker.setSize( size );
checker.setControlPathPrefix( QStringLiteral( "compositionconverter" ) ); checker.setControlPathPrefix( QStringLiteral( "compositionconverter" ) );
QVERIFY( checker.testLayout( mReport, pageNumber, 0, true ) ); QVERIFY( checker.testLayout( mReport, pageNumber, 0, false ) );
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 KiB

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 80 KiB