Skip to content

Commit cd6e820

Browse files
committedJan 9, 2018
[layout] Import some more items: map, poly* and arrow
1 parent 2ad56ef commit cd6e820

File tree

5 files changed

+750
-101
lines changed

5 files changed

+750
-101
lines changed
 

‎src/core/layout/qgscompositionconverter.cpp

Lines changed: 497 additions & 37 deletions
Large diffs are not rendered by default.

‎src/core/layout/qgscompositionconverter.h

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,17 @@
2525

2626
class QgsLayout;
2727
class QgsLayoutItem;
28-
class QgsLayoutItemLabel;
29-
class QgsLayoutItemShape;
3028
class QgsReadWriteContext;
3129
class QgsProperty;
3230
class QgsPropertyCollection;
3331

32+
class QgsLayoutItemLabel;
33+
class QgsLayoutItemShape;
34+
class QgsLayoutItemPicture;
35+
class QgsLayoutItemPolygon;
36+
class QgsLayoutItemPolyline;
37+
class QgsLayoutItemMap;
38+
3439
class CORE_EXPORT QgsCompositionConverter
3540
{
3641
public:
@@ -89,6 +94,17 @@ class CORE_EXPORT QgsCompositionConverter
8994
ScalebarLineWidth, //!< Scalebar line width
9095
};
9196

97+
/**
98+
* The MarkerMode enum is the old 2.x arrow marker mode
99+
*/
100+
enum MarkerMode
101+
{
102+
DefaultMarker,
103+
NoMarker,
104+
SVGMarker
105+
};
106+
107+
92108
/**
93109
* \brief createLayoutFromCompositionXml is a factory that creates layout instances from a
94110
* QGIS 2.x XML composition \a document
@@ -98,25 +114,44 @@ class CORE_EXPORT QgsCompositionConverter
98114
* \return a QgsLayout instance
99115
*/
100116
static QgsLayout *createLayoutFromCompositionXml( const QDomElement &parentElement,
101-
const QgsReadWriteContext &context ) SIP_FACTORY;
117+
QgsProject *project ) SIP_FACTORY;
102118

103119

104120
static QList<QgsLayoutItem *> addItemsFromCompositionXml( QgsLayout *layout,
105121
const QDomElement &parentElement,
106-
const QgsReadWriteContext &context,
107122
QPointF *position = nullptr,
108123
bool pasteInPlace = false );
109124

110125
private:
126+
111127
//! Property definitions
112128
static QgsPropertiesDefinition sPropertyDefinitions;
113129

114-
static bool readLabelXml( QgsLayoutItemLabel *label,
130+
131+
static bool readLabelXml( QgsLayoutItemLabel *layoutItem,
115132
const QDomElement &itemElem,
116-
const QgsReadWriteContext &context );
133+
const QgsProject *project );
117134

118135
static bool readShapeXml( QgsLayoutItemShape *layoutItem,
119-
const QDomElement &itemElem );
136+
const QDomElement &itemElem,
137+
const QgsProject *project );
138+
139+
static bool readPictureXml( QgsLayoutItemPicture *layoutItem,
140+
const QDomElement &itemElem,
141+
const QgsProject *project );
142+
143+
//! For both polylines and polygons
144+
template <class T, class T2> static bool readPolyXml( T *layoutItem,
145+
const QDomElement &itemElem,
146+
const QgsProject *project );
147+
148+
static bool readArrowXml( QgsLayoutItemPolyline *layoutItem,
149+
const QDomElement &itemElem,
150+
const QgsProject *project );
151+
152+
static bool readMapXml( QgsLayoutItemMap *layoutItem,
153+
const QDomElement &itemElem,
154+
const QgsProject *project );
120155

121156

122157
/**

‎src/core/layout/qgslayoutitemmap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,7 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
657657
friend class QgsLayoutItemMapOverview;
658658
friend class QgsLayoutItemLegend;
659659
friend class TestQgsLayoutMap;
660+
friend class QgsCompositionConverter;
660661

661662
};
662663

‎src/core/layout/qgslayoutitempicture.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ class CORE_EXPORT QgsLayoutItemPicture: public QgsLayoutItem
347347

348348
void shapeChanged();
349349

350+
friend class QgsCompositionConverter;
351+
friend class TestQgsCompositionConverter;
352+
350353
};
351354

352355
#endif // QGSLAYOUTITEMPICTURE_H

‎tests/src/core/testqgscompositionconverter.cpp

Lines changed: 207 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,16 @@
2424
#include "qgsreadwritecontext.h"
2525
#include "qgslayoutexporter.h"
2626
#include "qgsmultirenderchecker.h"
27+
#include "qgssettings.h"
2728

2829

2930
#include "qgslayoutitemlabel.h"
3031
#include "qgslayoutitemshape.h"
32+
#include "qgslayoutitempicture.h"
33+
#include "qgslayoutitempolygon.h"
34+
#include "qgslayoutitempolyline.h"
35+
#include "qgslayoutitemmap.h"
36+
3137

3238
class TestQgsCompositionConverter: public QObject
3339
{
@@ -54,17 +60,49 @@ class TestQgsCompositionConverter: public QObject
5460
*/
5561
void importComposerTemplate();
5662

63+
/**
64+
* Test import pictures from a composer template
65+
*/
66+
void importComposerTemplatePicture();
67+
68+
/**
69+
* Test import polygon from a composer template
70+
*/
71+
void importComposerTemplatePolygon();
72+
73+
/**
74+
* Test import polyline from a composer template
75+
*/
76+
void importComposerTemplatePolyline();
77+
78+
/**
79+
* Test import arrow from a composer template
80+
*/
81+
void importComposerTemplateArrow();
82+
83+
/**
84+
* Test import map from a composer template
85+
*/
86+
void importComposerTemplateMap();
87+
5788
private:
5889

90+
91+
void checkRenderedImage( QgsLayout *layout, const QString testName, const int pageNumber = 0 );
92+
5993
void exportLayout( QgsLayout *layout, const QString testName );
6094

95+
QDomElement loadComposition( const QString name );
96+
6197
QString mReport;
6298

6399
};
64100

65101
void TestQgsCompositionConverter::initTestCase()
66102
{
67103
mReport = QStringLiteral( "<h1>Layout Tests</h1>\n" );
104+
QgsSettings settings;
105+
settings.setValue( QStringLiteral( "svg/searchPathsForSVG" ), QStringLiteral( TEST_DATA_DIR ) ) ;
68106
}
69107

70108
void TestQgsCompositionConverter::cleanupTestCase()
@@ -92,23 +130,10 @@ void TestQgsCompositionConverter::cleanup()
92130

93131
void TestQgsCompositionConverter::importComposerTemplateLabel()
94132
{
95-
QString templatePath( QStringLiteral( TEST_DATA_DIR ) + "/layouts/2x_template_label.qpt" );
96-
QDomDocument doc( "mydocument" );
97-
QFile file( templatePath );
98-
QVERIFY( file.open( QIODevice::ReadOnly ) );
99-
if ( !doc.setContent( &file ) )
100-
{
101-
file.close();
102-
return;
103-
}
104-
file.close();
105-
106-
QDomNodeList nodes( doc.elementsByTagName( QStringLiteral( "Composition" ) ) );
107-
QVERIFY( nodes.length() > 0 );
108-
QDomElement docElem = nodes.at( 0 ).toElement();
109-
133+
QDomElement docElem( loadComposition( "2x_template_label.qpt" ) );
110134
QgsReadWriteContext context;
111-
QgsLayout *layout = QgsCompositionConverter::createLayoutFromCompositionXml( docElem, context );
135+
QgsProject project;
136+
QgsLayout *layout = QgsCompositionConverter::createLayoutFromCompositionXml( docElem, &project );
112137

113138
QVERIFY( layout );
114139
QCOMPARE( layout->pageCollection()->pageCount(), 1 );
@@ -117,7 +142,7 @@ void TestQgsCompositionConverter::importComposerTemplateLabel()
117142
layout->layoutItems<QgsLayoutItemLabel>( items );
118143
QVERIFY( items.size() > 0 );
119144

120-
exportLayout( layout, QStringLiteral( "ComposerTemplateLabel" ) );
145+
//exportLayout( layout, QTest::currentTestFunction() );
121146

122147
// Check the label
123148
const QgsLayoutItemLabel *label = items.at( 0 );
@@ -132,35 +157,17 @@ void TestQgsCompositionConverter::importComposerTemplateLabel()
132157
QCOMPARE( label->frameStrokeWidth().length(), 0.2 );
133158
QCOMPARE( ( int )label->rotation(), 4 );
134159

135-
/*
136-
QgsCompositionChecker checker( QStringLiteral( "ComposerTemplateLabel" ), composition );
137-
checker.setSize( QSize( 774, 641 ) );
138-
checker.setControlPathPrefix( QStringLiteral( "compositionconverter" ) );
139-
QVERIFY( checker.testComposition( mReport ) );
140-
*/
160+
checkRenderedImage( layout, QTest::currentTestFunction(), 0 );
141161

142162
qDeleteAll( items );
143163
}
144164

145165
void TestQgsCompositionConverter::importComposerTemplateShape()
146166
{
147-
QString templatePath( QStringLiteral( TEST_DATA_DIR ) + "/layouts/2x_template_shape.qpt" );
148-
QDomDocument doc( "mydocument" );
149-
QFile file( templatePath );
150-
QVERIFY( file.open( QIODevice::ReadOnly ) );
151-
if ( !doc.setContent( &file ) )
152-
{
153-
file.close();
154-
return;
155-
}
156-
file.close();
157-
158-
QDomNodeList nodes( doc.elementsByTagName( QStringLiteral( "Composition" ) ) );
159-
QVERIFY( nodes.length() > 0 );
160-
QDomElement docElem = nodes.at( 0 ).toElement();
161-
167+
QDomElement docElem( loadComposition( "2x_template_shape.qpt" ) );
162168
QgsReadWriteContext context;
163-
QgsLayout *layout = QgsCompositionConverter::createLayoutFromCompositionXml( docElem, context );
169+
QgsProject project;
170+
QgsLayout *layout = QgsCompositionConverter::createLayoutFromCompositionXml( docElem, &project );
164171

165172
QVERIFY( layout );
166173
QCOMPARE( layout->pageCollection()->pageCount(), 1 );
@@ -169,7 +176,7 @@ void TestQgsCompositionConverter::importComposerTemplateShape()
169176
layout->layoutItems<QgsLayoutItemShape>( items );
170177
QVERIFY( items.size() > 0 );
171178

172-
exportLayout( layout, QString( "ComposerTemplateShape" ) );
179+
//exportLayout( layout, QTest::currentTestFunction() );
173180

174181
// Check the shape
175182
const QgsLayoutItemShape *shape = items.at( 0 );
@@ -185,37 +192,162 @@ void TestQgsCompositionConverter::importComposerTemplateShape()
185192
QCOMPARE( shape->hasFrame(), false );
186193
QCOMPARE( shape->hasBackground(), false );
187194

195+
checkRenderedImage( layout, QTest::currentTestFunction(), 0 );
196+
188197
qDeleteAll( items );
189198
}
190199

191-
void TestQgsCompositionConverter::importComposerTemplate()
200+
void TestQgsCompositionConverter::importComposerTemplatePicture()
192201
{
193-
QString templatePath( QStringLiteral( TEST_DATA_DIR ) + "/layouts/2x_template.qpt" );
194-
QDomDocument doc( "mydocument" );
195-
QFile file( templatePath );
196-
QVERIFY( file.open( QIODevice::ReadOnly ) );
197-
if ( !doc.setContent( &file ) )
198-
{
199-
file.close();
200-
return;
201-
}
202-
file.close();
202+
QDomElement docElem( loadComposition( "2x_template_pictures.qpt" ) );
203+
QVERIFY( !docElem.isNull() );
204+
QgsProject project;
205+
QgsLayout *layout = QgsCompositionConverter::createLayoutFromCompositionXml( docElem, &project );
206+
QVERIFY( layout );
207+
QCOMPARE( layout->pageCollection()->pageCount(), 1 );
203208

204-
QDomNodeList nodes( doc.elementsByTagName( QStringLiteral( "Composition" ) ) );
205-
QVERIFY( nodes.length() > 0 );
206-
QDomElement docElem = nodes.at( 0 ).toElement();
209+
QList<QgsLayoutItemPicture *> items;
210+
layout->layoutItems<QgsLayoutItemPicture>( items );
211+
QCOMPARE( items.size(), 1 );
212+
QVERIFY( QFile( items.at( 0 )->picturePath() ).exists() );
207213

208-
QgsReadWriteContext context;
209-
QgsLayout *layout = QgsCompositionConverter::createLayoutFromCompositionXml( docElem, context );
214+
QgsLayoutItemPicture *item = items.at( 0 );
215+
QCOMPARE( item->mPictureHeight, 18.1796 );
216+
QCOMPARE( item->mPictureWidth, 18.1796 );
217+
QCOMPARE( item->sizeWithUnits().width(), 25.7099 );
218+
QCOMPARE( item->sizeWithUnits().height(), 30.7511 );
219+
QCOMPARE( item->pos().x(), 207.192 );
220+
QCOMPARE( item->pos().y(), 12.6029 );
221+
QVERIFY( item->isVisible() );
222+
223+
checkRenderedImage( layout, QTest::currentTestFunction(), 0 );
224+
225+
qDeleteAll( items );
226+
227+
}
228+
229+
void TestQgsCompositionConverter::importComposerTemplatePolygon()
230+
{
231+
QDomElement docElem( loadComposition( "2x_template_polygon.qpt" ) );
232+
QVERIFY( !docElem.isNull() );
233+
QgsProject project;
234+
QgsLayout *layout = QgsCompositionConverter::createLayoutFromCompositionXml( docElem, &project );
235+
QVERIFY( layout );
236+
QCOMPARE( layout->pageCollection()->pageCount(), 1 );
237+
238+
QList<QgsLayoutItemPolygon *> items;
239+
layout->layoutItems<QgsLayoutItemPolygon>( items );
240+
QCOMPARE( items.size(), 1 );
241+
242+
QgsLayoutItemPolygon *item = items.at( 0 );
243+
QVERIFY( item->isVisible() );
244+
QCOMPARE( item->nodes().count(), 7 );
245+
246+
checkRenderedImage( layout, QTest::currentTestFunction(), 0 );
247+
248+
qDeleteAll( items );
249+
250+
}
251+
252+
void TestQgsCompositionConverter::importComposerTemplatePolyline()
253+
{
254+
QDomElement docElem( loadComposition( "2x_template_polyline.qpt" ) );
255+
QVERIFY( !docElem.isNull() );
256+
QgsProject project;
257+
QgsLayout *layout = QgsCompositionConverter::createLayoutFromCompositionXml( docElem, &project );
258+
QVERIFY( layout );
259+
QCOMPARE( layout->pageCollection()->pageCount(), 1 );
260+
261+
QList<QgsLayoutItemPolyline *> items;
262+
layout->layoutItems<QgsLayoutItemPolyline>( items );
263+
QCOMPARE( items.size(), 1 );
264+
265+
QgsLayoutItemPolyline *item = items.at( 0 );
266+
QVERIFY( item->isVisible() );
267+
QCOMPARE( item->nodes().count(), 4 );
268+
QCOMPARE( item->startMarker(), QgsLayoutItemPolyline::MarkerMode::NoMarker );
269+
QCOMPARE( item->endMarker(), QgsLayoutItemPolyline::MarkerMode::NoMarker );
270+
//QCOMPARE( item->nodes().at(0), QPointF( 266.622, 371.215) );
271+
//QCOMPARE( item->nodes().at(1), QPointF( 261.581, 296.606) );
272+
273+
checkRenderedImage( layout, QTest::currentTestFunction(), 0 );
274+
275+
qDeleteAll( items );
276+
277+
}
278+
279+
void TestQgsCompositionConverter::importComposerTemplateArrow()
280+
{
281+
QDomElement docElem( loadComposition( "2x_template_arrow.qpt" ) );
282+
QVERIFY( !docElem.isNull() );
283+
QgsProject project;
284+
QgsLayout *layout = QgsCompositionConverter::createLayoutFromCompositionXml( docElem, &project );
285+
QVERIFY( layout );
286+
QCOMPARE( layout->pageCollection()->pageCount(), 1 );
287+
288+
QList<QgsLayoutItemPolyline *> items;
289+
layout->layoutItems<QgsLayoutItemPolyline>( items );
290+
QCOMPARE( items.size(), 1 );
291+
292+
QgsLayoutItemPolyline *item = items.at( 0 );
293+
QVERIFY( item->isVisible() );
294+
QCOMPARE( item->nodes().count(), 2 );
295+
QCOMPARE( item->startMarker(), QgsLayoutItemPolyline::MarkerMode::NoMarker );
296+
QCOMPARE( item->endMarker(), QgsLayoutItemPolyline::MarkerMode::ArrowHead );
297+
298+
checkRenderedImage( layout, QTest::currentTestFunction(), 0 );
299+
300+
qDeleteAll( items );
301+
302+
}
303+
304+
305+
void TestQgsCompositionConverter::importComposerTemplateMap()
306+
{
307+
QDomElement docElem( loadComposition( "2x_template_map_overview.qpt" ) );
308+
QVERIFY( !docElem.isNull() );
309+
QgsProject project;
310+
QgsLayout *layout = QgsCompositionConverter::createLayoutFromCompositionXml( docElem, &project );
311+
QVERIFY( layout );
312+
QCOMPARE( layout->pageCollection()->pageCount(), 1 );
313+
314+
QList<QgsLayoutItemMap *> items;
315+
layout->layoutItems<QgsLayoutItemMap>( items );
316+
QCOMPARE( items.size(), 2 );
317+
318+
QgsLayoutItemMap *item = items.at( 0 );
319+
QVERIFY( item->isVisible() );
320+
321+
checkRenderedImage( layout, QTest::currentTestFunction(), 0 );
322+
323+
qDeleteAll( items );
324+
325+
}
326+
327+
void TestQgsCompositionConverter::importComposerTemplate()
328+
{
329+
QDomElement docElem( loadComposition( "2x_template.qpt" ) );
330+
QgsProject project;
331+
QgsLayout *layout = QgsCompositionConverter::createLayoutFromCompositionXml( docElem, &project );
210332

211333
QVERIFY( layout );
212334
QCOMPARE( layout->pageCollection()->pageCount(), 2 );
213335

336+
checkRenderedImage( layout, QTest::currentTestFunction(), 0 );
337+
checkRenderedImage( layout, QTest::currentTestFunction(), 1 );
214338

215-
exportLayout( layout, QString( "ComposerTemplate" ) );
216339
delete layout;
217340
}
218341

342+
void TestQgsCompositionConverter::checkRenderedImage( QgsLayout *layout, const QString testName, const int pageNumber )
343+
{
344+
QgsLayoutChecker checker( testName + "_" + QString::number( pageNumber ), layout );
345+
QSize size( layout->pageCollection()->page( pageNumber )->sizeWithUnits().width() * 3.77, layout->pageCollection()->page( pageNumber )->sizeWithUnits().height() * 3.77 );
346+
checker.setSize( size );
347+
checker.setControlPathPrefix( QStringLiteral( "compositionconverter" ) );
348+
QVERIFY( checker.testLayout( mReport, pageNumber ) );
349+
}
350+
219351
void TestQgsCompositionConverter::exportLayout( QgsLayout *layout, const QString testName )
220352
{
221353
// Save the template for inspection
@@ -247,6 +379,24 @@ void TestQgsCompositionConverter::exportLayout( QgsLayout *layout, const QString
247379
}
248380
}
249381

382+
QDomElement TestQgsCompositionConverter::loadComposition( const QString name )
383+
{
384+
QString templatePath( QStringLiteral( TEST_DATA_DIR ) + "/layouts/" + name );
385+
QDomDocument doc( "mydocument" );
386+
QFile file( templatePath );
387+
file.open( QIODevice::ReadOnly );
388+
doc.setContent( &file );
389+
file.close();
390+
QDomNodeList nodes( doc.elementsByTagName( QStringLiteral( "Composition" ) ) );
391+
if ( nodes.length() > 0 )
392+
return nodes.at( 0 ).toElement();
393+
else
394+
{
395+
QDomElement elem;
396+
return elem;
397+
}
398+
}
399+
250400

251401
QGSTEST_MAIN( TestQgsCompositionConverter )
252402
#include "testqgscompositionconverter.moc"

0 commit comments

Comments
 (0)
Please sign in to comment.