Skip to content
Permalink
Browse files

[layout] Automatic conversion of 2.x composition templates to layouts

(cherry-picked from 3bdb6c2)
  • Loading branch information
elpaso authored and nyalldawson committed Feb 28, 2018
1 parent 06181e6 commit 7b4f69e9f8e42b8e8a528cc26ecbc4b40a6fd39d
Showing with 111 additions and 4 deletions.
  1. +23 −0 src/core/layout/qgscompositionconverter.cpp
  2. +17 −0 src/core/layout/qgscompositionconverter.h
  3. +12 −1 src/core/layout/qgslayout.cpp
  4. +59 −3 tests/src/core/testqgscompositionconverter.cpp
  5. BIN ...rol_images/compositionconverter/expected_importComposerAtlas_0/expected_importComposerAtlas_0.png
  6. BIN ...sitionconverter/expected_importComposerTemplateArrow_0/expected_importComposerTemplateArrow_0.png
  7. BIN ...pected_importComposerTemplateAttributeTable_0/expected_importComposerTemplateAttributeTable_0.png
  8. BIN ...positionconverter/expected_importComposerTemplateHtml_0/expected_importComposerTemplateHtml_0.png
  9. BIN ...tionconverter/expected_importComposerTemplateLegend_0/expected_importComposerTemplateLegend_0.png
  10. BIN ...ompositionconverter/expected_importComposerTemplateMap_0/expected_importComposerTemplateMap_0.png
  11. BIN ...onconverter/expected_importComposerTemplatePicture_0/expected_importComposerTemplatePicture_0.png
  12. BIN ...onconverter/expected_importComposerTemplatePolygon_0/expected_importComposerTemplatePolygon_0.png
  13. BIN ...converter/expected_importComposerTemplatePolyline_0/expected_importComposerTemplatePolyline_0.png
  14. BIN ...converter/expected_importComposerTemplateScaleBar_0/expected_importComposerTemplateScaleBar_0.png
  15. BIN ...sitionconverter/expected_importComposerTemplateShape_0/expected_importComposerTemplateShape_0.png
  16. BIN ...ages/compositionconverter/expected_importComposerTemplate_0/expected_importComposerTemplate_0.png
  17. BIN ...ages/compositionconverter/expected_importComposerTemplate_1/expected_importComposerTemplate_1.png
@@ -452,6 +452,29 @@ QList<QgsLayoutObject *> QgsCompositionConverter::addItemsFromCompositionXml( Qg
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 )
{
Q_UNUSED( project );
@@ -144,6 +144,23 @@ class CORE_EXPORT QgsCompositionConverter
QPointF *position = nullptr,
bool pasteInPlace = false );

/**
* Check if the given \a document is a composition template
* \param document a dom document
* \return true if the document is a composition template
*/
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
*/
static QDomDocument convertCompositionTemplate( const QDomDocument
&document, QgsProject *project );


private:


@@ -27,6 +27,7 @@
#include "qgslayoutmultiframe.h"
#include "qgslayoutitemmap.h"
#include "qgslayoutundostack.h"
#include "qgscompositionconverter.h"

QgsLayout::QgsLayout( QgsProject *project )
: mProject( project )
@@ -609,7 +610,17 @@ QList< QgsLayoutItem * > QgsLayout::loadFromTemplate( const QDomDocument &docume
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
QDomNodeList itemsNodes = doc.elementsByTagName( QStringLiteral( "LayoutItem" ) );
@@ -44,6 +44,16 @@
#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
{
Q_OBJECT
@@ -125,7 +135,17 @@ class TestQgsCompositionConverter: public QObject
/**
* 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:
@@ -523,7 +543,7 @@ void TestQgsCompositionConverter::importComposerTemplateScaleBar()
}


void TestQgsCompositionConverter::convertComposerTemplate()
void TestQgsCompositionConverter::convertComposition()
{

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()
{
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 );
checker.setSize( size );
checker.setControlPathPrefix( QStringLiteral( "compositionconverter" ) );
QVERIFY( checker.testLayout( mReport, pageNumber, 0, true ) );
QVERIFY( checker.testLayout( mReport, pageNumber, 0, false ) );
}


Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit 7b4f69e

Please sign in to comment.
You can’t perform that action at this time.