Port some more tests to layouts, drop composer tests which

have been ported to layouts
This commit is contained in:
Nyall Dawson 2018-01-06 15:49:11 +10:00
parent 0779b88729
commit b691998c68
38 changed files with 711 additions and 7770 deletions

View File

@ -38,7 +38,7 @@ QgsLayoutItemLegend::QgsLayoutItemLegend( QgsLayout *layout )
: QgsLayoutItem( layout )
, mLegendModel( new QgsLegendModel( layout->project()->layerTreeRoot() ) )
{
#if 0 //TODO
#if 0 //no longer required?
connect( &layout->atlasComposition(), &QgsAtlasComposition::renderEnded, this, &QgsLayoutItemLegend::onAtlasEnded );
#endif

View File

@ -199,6 +199,9 @@ void QgsLayoutItemPolyline::updateMarkerSvgSizes()
void QgsLayoutItemPolyline::drawArrowHead( QPainter *p, const double x, const double y, const double angle, const double arrowHeadWidth )
{
if ( !p )
return;
double angleRad = angle / 180.0 * M_PI;
QPointF middlePoint( x, y );
//rotate both arrow points

View File

@ -259,6 +259,8 @@ class CORE_EXPORT QgsLayoutItemPolyline: public QgsLayoutNodesItem
void drawSvgMarker( QPainter *p, QPointF point, double angle, const QString &markerPath, double height ) const;
double computeMarkerMargin() const;
friend class TestQgsLayoutPolyline;
};
#endif // QGSLAYOUTITEMPOLYLINE_H

View File

@ -73,7 +73,6 @@ ENDMACRO (ADD_QGIS_TEST)
SET(TESTS
testqgs25drenderer.cpp
testqgsapplication.cpp
testqgsatlascomposition.cpp
testqgsauthcrypto.cpp
testqgsauthcertutils.cpp
testqgsauthconfig.cpp
@ -83,23 +82,8 @@ SET(TESTS
testqgsclipper.cpp
testqgscolorscheme.cpp
testqgscolorschemeregistry.cpp
testqgscomposerdd.cpp
testqgscomposereffects.cpp
testqgscomposergroup.cpp
testqgscomposerlabel.cpp
testqgscomposermapgrid.cpp
testqgscomposermapoverview.cpp
testqgscomposermap.cpp
testqgscomposermodel.cpp
testqgscomposermultiframe.cpp
testqgscomposerobject.cpp
testqgscomposerpaper.cpp
testqgscomposerpicture.cpp
testqgscomposerrotation.cpp
testqgscomposerscalebar.cpp
testqgscomposershapes.cpp
testqgscomposertablev2.cpp
testqgscomposerutils.cpp
testqgsconnectionpool.cpp
testcontrastenhancements.cpp
testqgscoordinatereferencesystem.cpp
@ -148,6 +132,7 @@ SET(TESTS
testqgslayoutobject.cpp
testqgslayoutpage.cpp
testqgslayoutpicture.cpp
testqgslayoutpolyline.cpp
testqgslayoutscalebar.cpp
testqgslayoutshapes.cpp
testqgslayouttable.cpp
@ -208,7 +193,6 @@ SET(TESTS
IF(WITH_QTWEBKIT)
SET(TESTS ${TESTS}
testqgscomposerhtml.cpp
testqgscomposition.cpp
)
ENDIF(WITH_QTWEBKIT)

View File

@ -1,416 +0,0 @@
/***************************************************************************
testqgsatlascomposition.cpp
---------------------------
begin : Sept 2012
copyright : (C) 2012 by Hugo Mercier
email : hugo dot mercier at oslandia dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h"
#include "qgscomposition.h"
#include "qgsmultirenderchecker.h"
#include "qgscomposermap.h"
#include "qgscomposermapoverview.h"
#include "qgsatlascomposition.h"
#include "qgscomposerlabel.h"
#include "qgsproject.h"
#include "qgsvectorlayer.h"
#include "qgsvectordataprovider.h"
#include "qgssymbol.h"
#include "qgssinglesymbolrenderer.h"
#include "qgsfontutils.h"
#include <QObject>
#include <QtTest/QSignalSpy>
#include "qgstest.h"
class TestQgsAtlasComposition : public QObject
{
Q_OBJECT
public:
TestQgsAtlasComposition() = default;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
// test filename pattern evaluation
void filename();
// test rendering with an autoscale atlas
void autoscale_render();
// test rendering with a fixed scale atlas
void fixedscale_render();
// test rendering with predefined scales
void predefinedscales_render();
// test rendering with two atlas-driven maps
void two_map_autoscale_render();
// test rendering with a hidden coverage
void hiding_render();
// test rendering with feature sorting
void sorting_render();
// test rendering with feature filtering
void filtering_render();
// test render signals
void test_signals();
// test removing coverage layer while atlas is enabled
void test_remove_layer();
private:
QgsComposition *mComposition = nullptr;
QgsComposerLabel *mLabel1 = nullptr;
QgsComposerLabel *mLabel2 = nullptr;
QgsComposerMap *mAtlasMap = nullptr;
QgsComposerMap *mOverview = nullptr;
QgsVectorLayer *mVectorLayer = nullptr;
QgsVectorLayer *mVectorLayer2 = nullptr;
QgsAtlasComposition *mAtlas = nullptr;
QString mReport;
};
void TestQgsAtlasComposition::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
//create maplayers from testdata and add to layer registry
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/france_parts.shp" );
mVectorLayer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
mVectorLayer2 = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsVectorSimplifyMethod simplifyMethod;
simplifyMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification );
mVectorLayer->setSimplifyMethod( simplifyMethod );
mReport = QStringLiteral( "<h1>Composer Atlas Tests</h1>\n" );
}
void TestQgsAtlasComposition::cleanupTestCase()
{
delete mComposition;
delete mVectorLayer;
QgsApplication::exitQgis();
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
}
void TestQgsAtlasComposition::init()
{
//create composition with composer map
// select epsg:2154
QgsCoordinateReferenceSystem crs;
crs.createFromSrid( 2154 );
QgsProject::instance()->setCrs( crs );
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
// fix the renderer, fill with green
QgsStringMap props;
props.insert( QStringLiteral( "color" ), QStringLiteral( "0,127,0" ) );
QgsFillSymbol *fillSymbol = QgsFillSymbol::createSimple( props );
QgsSingleSymbolRenderer *renderer = new QgsSingleSymbolRenderer( fillSymbol );
mVectorLayer->setRenderer( renderer );
// the atlas map
mAtlasMap = new QgsComposerMap( mComposition, 20, 20, 130, 130 );
mAtlasMap->setFrameEnabled( true );
mComposition->addComposerMap( mAtlasMap );
mAtlasMap->setLayers( QList<QgsMapLayer *>() << mVectorLayer );
mAtlas = &mComposition->atlasComposition();
mAtlas->setCoverageLayer( mVectorLayer );
mAtlas->setEnabled( true );
mComposition->setAtlasMode( QgsComposition::ExportAtlas );
// an overview
mOverview = new QgsComposerMap( mComposition, 180, 20, 50, 50 );
mOverview->setFrameEnabled( true );
mOverview->overview()->setFrameMap( mAtlasMap->id() );
mOverview->setLayers( QList<QgsMapLayer *>() << mVectorLayer );
mComposition->addComposerMap( mOverview );
mOverview->setNewExtent( QgsRectangle( 49670.718, 6415139.086, 699672.519, 7065140.887 ) );
// set the fill symbol of the overview map
QgsStringMap props2;
props2.insert( QStringLiteral( "color" ), QStringLiteral( "127,0,0,127" ) );
QgsFillSymbol *fillSymbol2 = QgsFillSymbol::createSimple( props2 );
mOverview->overview()->setFrameSymbol( fillSymbol2 );
// header label
mLabel1 = new QgsComposerLabel( mComposition );
mComposition->addComposerLabel( mLabel1 );
mLabel1->setText( QStringLiteral( "[% \"NAME_1\" %] area" ) );
mLabel1->setFont( QgsFontUtils::getStandardTestFont() );
//need to explicitly set width, since expression hasn't been evaluated against
//an atlas feature yet and will be shorter than required
mLabel1->setSceneRect( QRectF( 150, 5, 60, 15 ) );
// feature number label
mLabel2 = new QgsComposerLabel( mComposition );
mComposition->addComposerLabel( mLabel2 );
mLabel2->setText( QStringLiteral( "# [%@atlas_featurenumber || ' / ' || @atlas_totalfeatures%]" ) );
mLabel2->setFont( QgsFontUtils::getStandardTestFont() );
mLabel2->setSceneRect( QRectF( 150, 200, 60, 15 ) );
qDebug() << "header label font: " << mLabel1->font().toString() << " exactMatch:" << mLabel1->font().exactMatch();
qDebug() << "feature number label font: " << mLabel2->font().toString() << " exactMatch:" << mLabel2->font().exactMatch();
}
void TestQgsAtlasComposition::cleanup()
{
delete mComposition;
mComposition = nullptr;
}
void TestQgsAtlasComposition::filename()
{
mAtlas->setFilenamePattern( QStringLiteral( "'output_' || @atlas_featurenumber" ) );
mAtlas->beginRender();
for ( int fi = 0; fi < mAtlas->numFeatures(); ++fi )
{
mAtlas->prepareForFeature( fi );
QString expected = QStringLiteral( "output_%1" ).arg( ( int )( fi + 1 ) );
QCOMPARE( mAtlas->currentFilename(), expected );
}
mAtlas->endRender();
}
void TestQgsAtlasComposition::autoscale_render()
{
mAtlasMap->setAtlasDriven( true );
mAtlasMap->setAtlasScalingMode( QgsComposerMap::Auto );
mAtlasMap->setAtlasMargin( 0.10 );
mAtlas->beginRender();
for ( int fit = 0; fit < 2; ++fit )
{
mAtlas->prepareForFeature( fit );
mLabel1->adjustSizeToText();
QgsCompositionChecker checker( QStringLiteral( "atlas_autoscale%1" ).arg( ( ( int )fit ) + 1 ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "atlas" ) );
QVERIFY( checker.testComposition( mReport, 0, 100 ) );
}
mAtlas->endRender();
}
void TestQgsAtlasComposition::fixedscale_render()
{
//TODO QGIS3.0 - setting the extent AFTER setting atlas driven/fixed scaling mode should
//also update the set fixed scale
mAtlasMap->setNewExtent( QgsRectangle( 209838.166, 6528781.020, 610491.166, 6920530.620 ) );
mAtlasMap->setAtlasDriven( true );
mAtlasMap->setAtlasScalingMode( QgsComposerMap::Fixed );
mAtlas->beginRender();
for ( int fit = 0; fit < 2; ++fit )
{
mAtlas->prepareForFeature( fit );
mLabel1->adjustSizeToText();
QgsCompositionChecker checker( QStringLiteral( "atlas_fixedscale%1" ).arg( ( ( int )fit ) + 1 ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "atlas" ) );
QVERIFY( checker.testComposition( mReport, 0, 100 ) );
}
mAtlas->endRender();
}
void TestQgsAtlasComposition::predefinedscales_render()
{
//TODO QGIS3.0 - setting the extent AFTER setting atlas driven/predefined scaling mode should
//also update the atlas map scale
mAtlasMap->setNewExtent( QgsRectangle( 209838.166, 6528781.020, 610491.166, 6920530.620 ) );
mAtlasMap->setAtlasDriven( true );
mAtlasMap->setAtlasScalingMode( QgsComposerMap::Predefined );
QVector<qreal> scales;
scales << 1800000.0;
scales << 5000000.0;
mAtlas->setPredefinedScales( scales );
{
const QVector<qreal> &setScales = mAtlas->predefinedScales();
for ( int i = 0; i < setScales.size(); i++ )
{
QVERIFY( setScales[i] == scales[i] );
}
}
mAtlas->beginRender();
for ( int fit = 0; fit < 2; ++fit )
{
mAtlas->prepareForFeature( fit );
mLabel1->adjustSizeToText();
QgsCompositionChecker checker( QStringLiteral( "atlas_predefinedscales%1" ).arg( ( ( int )fit ) + 1 ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "atlas" ) );
QVERIFY( checker.testComposition( mReport, 0, 100 ) );
}
mAtlas->endRender();
}
void TestQgsAtlasComposition::two_map_autoscale_render()
{
mAtlasMap->setAtlasDriven( true );
mAtlasMap->setAtlasScalingMode( QgsComposerMap::Auto );
mAtlasMap->setAtlasMargin( 0.10 );
mOverview->setAtlasDriven( true );
mOverview->setAtlasScalingMode( QgsComposerMap::Auto );
mOverview->setAtlasMargin( 2.0 );
mAtlas->beginRender();
for ( int fit = 0; fit < 2; ++fit )
{
mAtlas->prepareForFeature( fit );
mLabel1->adjustSizeToText();
QgsCompositionChecker checker( QStringLiteral( "atlas_two_maps%1" ).arg( ( ( int )fit ) + 1 ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "atlas" ) );
QVERIFY( checker.testComposition( mReport, 0, 100 ) );
}
mAtlas->endRender();
}
void TestQgsAtlasComposition::hiding_render()
{
mAtlasMap->setNewExtent( QgsRectangle( 209838.166, 6528781.020, 610491.166, 6920530.620 ) );
mAtlasMap->setAtlasDriven( true );
mAtlasMap->setAtlasScalingMode( QgsComposerMap::Fixed );
mAtlas->setHideCoverage( true );
mAtlas->beginRender();
for ( int fit = 0; fit < 2; ++fit )
{
mAtlas->prepareForFeature( fit );
mLabel1->adjustSizeToText();
QgsCompositionChecker checker( QStringLiteral( "atlas_hiding%1" ).arg( ( ( int )fit ) + 1 ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "atlas" ) );
QVERIFY( checker.testComposition( mReport, 0, 100 ) );
}
mAtlas->endRender();
}
void TestQgsAtlasComposition::sorting_render()
{
mAtlasMap->setNewExtent( QgsRectangle( 209838.166, 6528781.020, 610491.166, 6920530.620 ) );
mAtlasMap->setAtlasDriven( true );
mAtlasMap->setAtlasScalingMode( QgsComposerMap::Fixed );
mAtlas->setHideCoverage( false );
mAtlas->setSortFeatures( true );
mAtlas->setSortKeyAttributeName( QStringLiteral( "NAME_1" ) ); // departement name
mAtlas->setSortAscending( false );
mAtlas->beginRender();
for ( int fit = 0; fit < 2; ++fit )
{
mAtlas->prepareForFeature( fit );
mLabel1->adjustSizeToText();
QgsCompositionChecker checker( QStringLiteral( "atlas_sorting%1" ).arg( ( ( int )fit ) + 1 ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "atlas" ) );
QVERIFY( checker.testComposition( mReport, 0, 100 ) );
}
mAtlas->endRender();
}
void TestQgsAtlasComposition::filtering_render()
{
mAtlasMap->setNewExtent( QgsRectangle( 209838.166, 6528781.020, 610491.166, 6920530.620 ) );
mAtlasMap->setAtlasDriven( true );
mAtlasMap->setAtlasScalingMode( QgsComposerMap::Fixed );
mAtlas->setHideCoverage( false );
mAtlas->setSortFeatures( false );
mAtlas->setFilterFeatures( true );
mAtlas->setFeatureFilter( QStringLiteral( "substr(NAME_1,1,1)='P'" ) ); // select only 'Pays de la Loire'
mAtlas->beginRender();
for ( int fit = 0; fit < 1; ++fit )
{
mAtlas->prepareForFeature( fit );
mLabel1->adjustSizeToText();
QgsCompositionChecker checker( QStringLiteral( "atlas_filtering%1" ).arg( ( ( int )fit ) + 1 ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "atlas" ) );
QVERIFY( checker.testComposition( mReport, 0, 100 ) );
}
mAtlas->endRender();
}
void TestQgsAtlasComposition::test_signals()
{
mAtlasMap->setNewExtent( QgsRectangle( 209838.166, 6528781.020, 610491.166, 6920530.620 ) );
mAtlasMap->setAtlasDriven( true );
mAtlasMap->setAtlasScalingMode( QgsComposerMap::Fixed );
mAtlas->setHideCoverage( false );
mAtlas->setSortFeatures( false );
mAtlas->setFilterFeatures( false );
QSignalSpy spyRenderBegun( mAtlas, SIGNAL( renderBegun() ) );
QSignalSpy spyRenderEnded( mAtlas, SIGNAL( renderEnded() ) );
QSignalSpy spyPreparedForAtlas( mAtlasMap, SIGNAL( preparedForAtlas() ) );
mAtlas->beginRender();
QVERIFY( spyRenderBegun.count() == 1 );
for ( int fit = 0; fit < 2; ++fit )
{
mAtlas->prepareForFeature( fit );
mLabel1->adjustSizeToText();
}
QVERIFY( spyPreparedForAtlas.count() == 2 );
mAtlas->endRender();
QVERIFY( spyRenderEnded.count() == 1 );
}
void TestQgsAtlasComposition::test_remove_layer()
{
QgsProject::instance()->addMapLayer( mVectorLayer2 );
mAtlas->setCoverageLayer( mVectorLayer2 );
mAtlas->setEnabled( true );
QSignalSpy spyToggled( mAtlas, SIGNAL( toggled( bool ) ) );
//remove coverage layer while atlas is enabled
QgsProject::instance()->removeMapLayer( mVectorLayer2->id() );
mVectorLayer2 = nullptr;
QVERIFY( !mAtlas->enabled() );
QVERIFY( spyToggled.count() == 1 );
}
QGSTEST_MAIN( TestQgsAtlasComposition )
#include "testqgsatlascomposition.moc"

View File

@ -1,136 +0,0 @@
/***************************************************************************
testqgscomposertable.cpp
----------------------
begin : July 2014
copyright : (C) 2014 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h"
#include "qgscomposition.h"
#include "qgscomposermap.h"
#include "qgscomposertexttable.h"
#include "qgsproject.h"
#include "qgsmapsettings.h"
#include "qgsvectorlayer.h"
#include "qgsvectordataprovider.h"
#include "qgsfeature.h"
#include "qgssymbol.h"
#include "qgssinglesymbolrenderer.h"
#include "qgsproperty.h"
#include <QObject>
#include "qgstest.h"
class TestQgsComposerDD : public QObject
{
Q_OBJECT
public:
TestQgsComposerDD() = default;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void ddEvaluate(); //test setting/evaluating data defined value
private:
QgsComposition *mComposition = nullptr;
QgsVectorLayer *mVectorLayer = nullptr;
QgsComposerMap *mAtlasMap = nullptr;
QgsAtlasComposition *mAtlas = nullptr;
QString mReport;
};
void TestQgsComposerDD::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
//create maplayers from testdata and add to layer registry
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/france_parts.shp" );
mVectorLayer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsVectorSimplifyMethod simplifyMethod;
simplifyMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification );
mVectorLayer->setSimplifyMethod( simplifyMethod );
//create composition with composer map
// select epsg:2154
QgsCoordinateReferenceSystem crs;
crs.createFromSrid( 2154 );
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
// fix the renderer, fill with green
QgsStringMap props;
props.insert( QStringLiteral( "color" ), QStringLiteral( "0,127,0" ) );
QgsFillSymbol *fillSymbol = QgsFillSymbol::createSimple( props );
QgsSingleSymbolRenderer *renderer = new QgsSingleSymbolRenderer( fillSymbol );
mVectorLayer->setRenderer( renderer );
// the atlas map
mAtlasMap = new QgsComposerMap( mComposition, 20, 20, 130, 130 );
mAtlasMap->setFrameEnabled( true );
mComposition->addComposerMap( mAtlasMap );
mAtlas = &mComposition->atlasComposition();
mAtlas->setCoverageLayer( mVectorLayer );
mAtlas->setEnabled( true );
mComposition->setAtlasMode( QgsComposition::ExportAtlas );
mReport = QStringLiteral( "<h1>Composer Data Defined Tests</h1>\n" );
}
void TestQgsComposerDD::cleanupTestCase()
{
delete mComposition;
delete mVectorLayer;
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}
void TestQgsComposerDD::init()
{
}
void TestQgsComposerDD::cleanup()
{
}
void TestQgsComposerDD::ddEvaluate()
{
//set a data defined property
mAtlasMap->dataDefinedProperties().setProperty( QgsComposerItem::PositionY, QgsProperty::fromExpression( QStringLiteral( "20+30" ) ) );
//evaluate property
mAtlasMap->refreshDataDefinedProperty( QgsComposerItem::PositionY );
QCOMPARE( mAtlasMap->pos().y(), 50.0 );
mAtlasMap->dataDefinedProperties().setProperty( QgsComposerItem::PositionY, QgsProperty() );
}
QGSTEST_MAIN( TestQgsComposerDD )
#include "testqgscomposerdd.moc"

View File

@ -1,118 +0,0 @@
/***************************************************************************
testqgscomposereffects.cpp
----------------------
begin : April 2013
copyright : (C) 2013 by Marco Hugentobler, Nyall Dawson
email : nyall dot dawson at gmail.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h"
#include "qgscomposition.h"
#include "qgsmultirenderchecker.h"
#include "qgscomposershape.h"
#include "qgsproject.h"
#include <QObject>
#include "qgstest.h"
#include <QColor>
#include <QPainter>
class TestQgsComposerEffects : public QObject
{
Q_OBJECT
public:
TestQgsComposerEffects() = default;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void blend_modes(); //test if composer item blending is functioning
void transparency(); //test if composer transparency is functioning
private:
QgsComposition *mComposition = nullptr;
QgsComposerShape *mComposerRect1 = nullptr;
QgsComposerShape *mComposerRect2 = nullptr;
QString mReport;
};
void TestQgsComposerEffects::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
//create composition with two rectangles
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mComposerRect1 = new QgsComposerShape( 20, 20, 150, 100, mComposition );
mComposerRect1->setShapeType( QgsComposerShape::Rectangle );
mComposerRect1->setBackgroundColor( QColor::fromRgb( 255, 150, 0 ) );
mComposition->addComposerShape( mComposerRect1 );
mComposerRect2 = new QgsComposerShape( 50, 50, 150, 100, mComposition );
mComposerRect2->setBackgroundColor( QColor::fromRgb( 0, 100, 150 ) );
mComposerRect2->setShapeType( QgsComposerShape::Rectangle );
mComposition->addComposerShape( mComposerRect2 );
mReport = QStringLiteral( "<h1>Composer Effects Tests</h1>\n" );
}
void TestQgsComposerEffects::cleanupTestCase()
{
delete mComposition;
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}
void TestQgsComposerEffects::init()
{
}
void TestQgsComposerEffects::cleanup()
{
}
void TestQgsComposerEffects::blend_modes()
{
mComposerRect2->setBlendMode( QPainter::CompositionMode_Multiply );
QgsCompositionChecker checker( QStringLiteral( "composereffects_blend" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_effects" ) );
QVERIFY( checker.testComposition( mReport ) );
// reset blending
mComposerRect2->setBlendMode( QPainter::CompositionMode_SourceOver );
}
void TestQgsComposerEffects::transparency()
{
mComposerRect2->setItemOpacity( 0.5 );
QgsCompositionChecker checker( QStringLiteral( "composereffects_transparency" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_effects" ) );
QVERIFY( checker.testComposition( mReport ) );
}
QGSTEST_MAIN( TestQgsComposerEffects )
#include "testqgscomposereffects.moc"

View File

@ -1,431 +0,0 @@
/***************************************************************************
testqgscomposergroup.cpp
-----------------------
begin : October 2014
copyright : (C) 2014 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgscomposeritemgroup.h"
#include "qgscomposerlabel.h"
#include "qgscomposerpolygon.h"
#include "qgscomposition.h"
#include "qgsmultirenderchecker.h"
#include "qgsapplication.h"
#include "qgslogger.h"
#include "qgsproject.h"
#include <QObject>
#include <QtTest/QSignalSpy>
#include "qgstest.h"
class TestQgsComposerGroup : public QObject
{
Q_OBJECT
public:
TestQgsComposerGroup() = default;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void createGroup(); //test grouping items
void ungroup(); //test ungrouping items
void deleteGroup(); //test deleting group works
void undoRedo(); //test that group/ungroup undo/redo commands don't crash
private:
void dumpUndoStack( const QUndoStack &, QString prefix = QString() ) const;
QgsComposition *mComposition = nullptr;
QgsMapSettings *mMapSettings = nullptr;
QgsComposerLabel *mItem1 = nullptr;
QgsComposerLabel *mItem2 = nullptr;
QgsComposerItemGroup *mGroup = nullptr;
QString mReport;
};
// private
void TestQgsComposerGroup::dumpUndoStack( const QUndoStack &us, QString prefix ) const
{
if ( ! prefix.isEmpty() ) prefix += QLatin1String( ": " );
for ( int i = 0; i < us.count(); ++i )
{
QgsDebugMsg( QString( "%4US %1: %2%3" )
.arg( i ). arg( i >= us.index() ? "-" : "",
us.text( i ), prefix ) );
}
}
void TestQgsComposerGroup::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
mMapSettings = new QgsMapSettings();
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
//create some items
mItem1 = new QgsComposerLabel( mComposition );
mComposition->addItem( mItem1 );
mItem2 = new QgsComposerLabel( mComposition );
mComposition->addItem( mItem2 );
mGroup = nullptr;
mReport = QStringLiteral( "<h1>Composer Grouped Item Tests</h1>\n" );
}
void TestQgsComposerGroup::cleanupTestCase()
{
delete mComposition;
delete mMapSettings;
QgsApplication::exitQgis();
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
}
void TestQgsComposerGroup::init()
{
}
void TestQgsComposerGroup::cleanup()
{
}
void TestQgsComposerGroup::createGroup()
{
//group items
QList<QgsComposerItem *> items;
items << mItem1 << mItem2;
mGroup = mComposition->groupItems( items );
//check result
QVERIFY( mGroup );
QCOMPARE( mGroup->items().size(), 2 );
QVERIFY( mGroup->items().contains( mItem1 ) );
QVERIFY( mGroup->items().contains( mItem2 ) );
QVERIFY( mItem1->isGroupMember() );
QVERIFY( mItem2->isGroupMember() );
}
void TestQgsComposerGroup::ungroup()
{
//test ungrouping items
//simple tests - check that we don't crash
mComposition->ungroupItems( nullptr ); //no item
//ungroup mGroup
QList<QgsComposerItem *> ungroupedItems;
ungroupedItems = mComposition->ungroupItems( mGroup );
QCOMPARE( ungroupedItems.size(), 2 );
QVERIFY( ungroupedItems.contains( mItem1 ) );
QVERIFY( ungroupedItems.contains( mItem2 ) );
QVERIFY( !mItem1->isGroupMember() );
QVERIFY( !mItem2->isGroupMember() );
//should also be no groups left in the composition
QList<QgsComposerItemGroup *> groups;
mComposition->composerItems( groups );
QCOMPARE( groups.size(), 0 );
}
void TestQgsComposerGroup::deleteGroup()
{
//group items
QList<QgsComposerItem *> groupItems;
groupItems << mItem1 << mItem2;
mGroup = mComposition->groupItems( groupItems );
QList<QgsComposerItem *> items;
mComposition->composerItems( items );
//expect initially 4 items, as paper counts as an item
QCOMPARE( items.size(), 4 );
//test that deleting group also removes all grouped items
mComposition->removeComposerItem( mGroup );
mComposition->composerItems( items );
//expect a single item (paper item)
QCOMPARE( items.size(), 1 );
QVERIFY( mItem1->isRemoved() );
QVERIFY( mItem2->isRemoved() );
QVERIFY( mGroup->isRemoved() );
}
Q_DECLARE_METATYPE( QgsComposerItemGroup * )
Q_DECLARE_METATYPE( QgsComposerPolygon * )
Q_DECLARE_METATYPE( QgsComposerItem * )
void TestQgsComposerGroup::undoRedo()
{
QgsComposerPolygon *item1, *item2;
int polygonsAdded = 0;
int groupsAdded = 0;
int itemsRemoved = 0;
qRegisterMetaType<QgsComposerPolygon *>();
QSignalSpy spyPolygonAdded( mComposition, &QgsComposition::itemAdded );
QCOMPARE( spyPolygonAdded.count(), 0 );
qRegisterMetaType<QgsComposerItemGroup *>();
QSignalSpy spyGroupAdded( mComposition, &QgsComposition::composerItemGroupAdded );
QCOMPARE( spyGroupAdded.count(), 0 );
qRegisterMetaType<QgsComposerItem *>();
QSignalSpy spyItemRemoved( mComposition, &QgsComposition::itemRemoved );
QCOMPARE( spyItemRemoved.count(), 0 );
//test for crash when undo/redoing with groups
// Set initial condition
QUndoStack *us = mComposition->undoStack();
QgsDebugMsg( QString( "clearing" ) );
us->clear();
QgsDebugMsg( QString( "clearing completed" ) );
QList<QgsComposerItem *> items;
mComposition->composerItems( items );
QCOMPARE( items.size(), 1 ); // paper only
QgsDebugMsg( QString( "clear stack count:%1 index:%2" ) .arg( us->count() ) .arg( us->index() ) );
//create some items
item1 = new QgsComposerPolygon( QPolygonF( QRectF( 0, 0, 1, 1 ) ), mComposition ); //QgsComposerLabel( mComposition );
mComposition->addComposerPolygon( item1 );
QCOMPARE( spyPolygonAdded.count(), ++polygonsAdded );
item2 = new QgsComposerPolygon( QPolygonF( QRectF( -1, -2, 1, 1 ) ), mComposition ); //QgsComposerLabel( mComposition );
mComposition->addComposerPolygon( item2 );
QCOMPARE( spyPolygonAdded.count(), ++polygonsAdded );
mComposition->composerItems( items );
QCOMPARE( items.size(), 3 ); // paper, 2 shapes
QgsDebugMsg( QString( "addedItems stack count:%1 index:%2" ) .arg( us->count() ) .arg( us->index() ) );
QCOMPARE( item1->pos(), QPointF( 0, 0 ) );
QCOMPARE( item2->pos(), QPointF( -1, -2 ) );
//dumpUndoStack(*us, "after initial items addition");
//group items
items.clear();
items << item1 << item2;
mGroup = mComposition->groupItems( items );
QCOMPARE( spyPolygonAdded.count(), polygonsAdded );
QCOMPARE( spyGroupAdded.count(), ++groupsAdded );
QCOMPARE( spyItemRemoved.count(), itemsRemoved );
QCOMPARE( mGroup->items().size(), 2 );
mComposition->composerItems( items );
QCOMPARE( items.size(), 4 ); // paper, 2 shapes, 1 group
QVERIFY( ! item1->isRemoved() );
QCOMPARE( item1->pos(), QPointF( 0, 0 ) );
QVERIFY( ! item2->isRemoved() );
QCOMPARE( item2->pos(), QPointF( -1, -2 ) );
QVERIFY( ! mGroup->isRemoved() );
QCOMPARE( mGroup->pos(), QPointF( -1, -2 ) );
//dumpUndoStack(*us, "after initial items addition");
//move group
QgsDebugMsg( QString( "moving group" ) );
mGroup->beginCommand( QStringLiteral( "move group" ) );
mGroup->move( 10.0, 20.0 );
mGroup->endCommand();
QCOMPARE( spyPolygonAdded.count(), polygonsAdded );
QCOMPARE( spyGroupAdded.count(), groupsAdded );
QCOMPARE( spyItemRemoved.count(), itemsRemoved );
QgsDebugMsg( QString( "groupItems stack count:%1 index:%2" ) .arg( us->count() ) .arg( us->index() ) );
QCOMPARE( mGroup->items().size(), 2 );
mComposition->composerItems( items );
QCOMPARE( items.size(), 4 ); // paper, 2 shapes, 1 group
QVERIFY( ! item1->isRemoved() );
QCOMPARE( item1->pos(), QPointF( 10, 20 ) );
QVERIFY( ! item2->isRemoved() );
QCOMPARE( item2->pos(), QPointF( 9, 18 ) );
QVERIFY( ! mGroup->isRemoved() );
QCOMPARE( mGroup->pos(), QPointF( 9, 18 ) );
//ungroup
QgsDebugMsg( QString( "ungrouping" ) );
mComposition->ungroupItems( mGroup );
QCOMPARE( spyPolygonAdded.count(), polygonsAdded );
QCOMPARE( spyGroupAdded.count(), groupsAdded );
QCOMPARE( spyItemRemoved.count(), ++itemsRemoved );
mComposition->composerItems( items );
QCOMPARE( items.size(), 3 ); // paper, 2 shapes
QVERIFY( ! item1->isRemoved() );
QVERIFY( ! item2->isRemoved() );
QVERIFY( mGroup->isRemoved() );
QCOMPARE( mGroup->pos(), QPointF( 9, 18 ) ); // should not rely on this
//dumpUndoStack(*us, "after ungroup");
// US 0: Items grouped
// US 1: move group
// US 2: Remove item group
//undo (groups again) -- crashed here before #11371 got fixed
QgsDebugMsg( QString( "undo ungrouping" ) );
us->undo();
QCOMPARE( spyPolygonAdded.count(), polygonsAdded );
QCOMPARE( spyGroupAdded.count(), ++groupsAdded );
QCOMPARE( spyItemRemoved.count(), itemsRemoved );
QCOMPARE( mGroup->items().size(), 2 ); // WARNING: might not be alive anymore
mComposition->composerItems( items );
QCOMPARE( items.size(), 4 ); // paper, 2 shapes, 1 group
QVERIFY( ! item1->isRemoved() );
QCOMPARE( item1->pos(), QPointF( 10, 20 ) );
QVERIFY( ! item2->isRemoved() );
QCOMPARE( item2->pos(), QPointF( 9, 18 ) );
QVERIFY( ! mGroup->isRemoved() );
QCOMPARE( mGroup->pos(), QPointF( 9, 18 ) );
//dumpUndoStack(*us, "after undo ungroup");
// US 0: Items grouped
// US 1: move group
// US 2: -Remove item group
//remove group
QgsDebugMsg( QString( "remove group" ) );
mComposition->removeComposerItem( mGroup, true, true );
QCOMPARE( spyPolygonAdded.count(), polygonsAdded );
QCOMPARE( spyGroupAdded.count(), groupsAdded );
itemsRemoved += 3; // the group and the two items
QCOMPARE( spyItemRemoved.count(), itemsRemoved );
mComposition->composerItems( items );
QCOMPARE( items.size(), 1 ); // paper only
QgsDebugMsg( QString( "remove stack count:%1 index:%2" ) .arg( us->count() ) .arg( us->index() ) );
//dumpUndoStack(*us, "after remove group");
// US 0: Items grouped
// US 1: move group
// US 2: Remove item group
//undo remove group
QgsDebugMsg( QString( "undo remove group" ) );
us->undo();
polygonsAdded += 2;
QCOMPARE( spyPolygonAdded.count(), polygonsAdded );
QCOMPARE( spyGroupAdded.count(), ++groupsAdded );
QCOMPARE( spyItemRemoved.count(), itemsRemoved );
mComposition->composerItems( items );
QCOMPARE( mGroup->items().size(), 2 );
QCOMPARE( items.size(), 4 ); // paper, 2 shapes, 1 group
QgsDebugMsg( QString( "undo stack count:%1 index:%2" ) .arg( us->count() ) .arg( us->index() ) );
//dumpUndoStack(*us, "after undo remove group");
// US 0: Items grouped
// US 1: move group
// US 2: -Remove item group
//undo move group
QgsDebugMsg( QString( "undo move group" ) );
us->undo();
QCOMPARE( spyPolygonAdded.count(), polygonsAdded );
QCOMPARE( spyGroupAdded.count(), groupsAdded );
QCOMPARE( spyItemRemoved.count(), itemsRemoved );
QCOMPARE( mGroup->items().size(), 2 );
mComposition->composerItems( items );
QCOMPARE( items.size(), 4 ); // paper, 2 shapes, 1 group
QCOMPARE( item1->isGroupMember(), true );
QCOMPARE( item2->isGroupMember(), true );
QVERIFY( ! item1->isRemoved() );
QCOMPARE( item1->pos(), QPointF( 0, 0 ) );
QVERIFY( ! item2->isRemoved() );
QCOMPARE( item2->pos(), QPointF( -1, -2 ) );
QVERIFY( ! mGroup->isRemoved() );
QCOMPARE( mGroup->pos(), QPointF( -1, -2 ) );
//dumpUndoStack(*us, "after undo move group");
// US 0: Items grouped
// US 1: -move group
// US 2: -Remove item group
//undo group
QgsDebugMsg( QString( "undo group" ) );
us->undo();
QCOMPARE( spyPolygonAdded.count(), polygonsAdded );
QCOMPARE( spyGroupAdded.count(), groupsAdded );
QCOMPARE( spyItemRemoved.count(), ++itemsRemoved );
//QCOMPARE( mGroup->items().size(), 2 ); // not important
mComposition->composerItems( items );
QCOMPARE( items.size(), 3 ); // paper, 2 shapes
QCOMPARE( item1->isGroupMember(), false );
QCOMPARE( item2->isGroupMember(), false );
QVERIFY( ! item1->isRemoved() );
QCOMPARE( item1->pos(), QPointF( 0, 0 ) );
QVERIFY( ! item2->isRemoved() );
QCOMPARE( item2->pos(), QPointF( -1, -2 ) );
QVERIFY( mGroup->isRemoved() );
//QCOMPARE( mGroup->pos(), QPointF( -1, -2 ) );
//dumpUndoStack(*us, "after undo group");
// US 0: -Items grouped
// US 1: -move group
// US 2: -Remove item group
//redo group
QgsDebugMsg( QString( "redo group" ) );
us->redo();
QCOMPARE( spyPolygonAdded.count(), polygonsAdded );
QCOMPARE( spyGroupAdded.count(), ++groupsAdded );
QCOMPARE( spyItemRemoved.count(), itemsRemoved );
mComposition->composerItems( items );
QCOMPARE( items.size(), 4 ); // paper, 2 shapes, 1 group
QCOMPARE( item1->isGroupMember(), true );
QCOMPARE( item2->isGroupMember(), true );
//// QCOMPARE( mGroup->pos(), QPointF( 0, 0 ) ); // getting nan,nan here
//dumpUndoStack(*us, "after redo group");
// US 0: Items grouped
// US 1: -move group
// US 2: -Remove item group
//redo move group
QgsDebugMsg( QString( "redo move group" ) );
us->redo();
QCOMPARE( spyPolygonAdded.count(), polygonsAdded );
QCOMPARE( spyGroupAdded.count(), groupsAdded );
QCOMPARE( spyItemRemoved.count(), itemsRemoved );
mComposition->composerItems( items );
QCOMPARE( items.size(), 4 ); // paper, 2 shapes, 1 group
QCOMPARE( item1->isGroupMember(), true );
QCOMPARE( item2->isGroupMember(), true );
QCOMPARE( mGroup->pos(), QPointF( 9, 18 ) );
//dumpUndoStack(*us, "after redo move group");
// US 0: Items grouped
// US 1: move group
// US 2: -Remove item group
//redo remove group
QgsDebugMsg( QString( "redo remove group" ) );
us->redo();
QCOMPARE( spyPolygonAdded.count(), polygonsAdded );
QCOMPARE( spyGroupAdded.count(), groupsAdded );
itemsRemoved += 3; // 1 group, 2 contained items
QCOMPARE( spyItemRemoved.count(), itemsRemoved );
mComposition->composerItems( items );
QCOMPARE( items.size(), 1 ); // paper only
QgsDebugMsg( QString( "undo stack count:%1 index:%2" ) .arg( us->count() ) .arg( us->index() ) );
//dumpUndoStack(*us, "after redo remove group");
// US 0: Items grouped
// US 1: move group
// US 2: Remove item group
//unwind the whole stack
us->clear();
QgsDebugMsg( QString( "clear stack count:%1 index:%2" ) .arg( us->count() ) .arg( us->index() ) );
}
QGSTEST_MAIN( TestQgsComposerGroup )
#include "testqgscomposergroup.moc"

View File

@ -1,320 +0,0 @@
/***************************************************************************
testqgscomposerhtml.cpp
-----------------------
begin : August 2012
copyright : (C) 2012 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h"
#include "qgscomposerhtml.h"
#include "qgscomposerframe.h"
#include "qgscomposition.h"
#include "qgsmultirenderchecker.h"
#include "qgsfontutils.h"
#include "qgsvectorlayer.h"
#include "qgsrelationmanager.h"
#include "qgsvectordataprovider.h"
#include "qgsproject.h"
#include <QObject>
#include "qgstest.h"
class TestQgsComposerHtml : public QObject
{
Q_OBJECT
public:
TestQgsComposerHtml();
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void sourceMode(); //test if rendering manual HTML works
void userStylesheets(); //test if user stylesheets work
void evalExpressions(); //test if rendering with expressions works
void evalExpressionsOff(); //test if rendering with expressions disabled works
void table(); //test if rendering a HTML url works
void tableMultiFrame(); //tests multiframe capabilities of composer html
void htmlMultiFrameSmartBreak(); //tests smart page breaks in html multi frame
void javascriptSetFeature(); //test that JavaScript setFeature() function is correctly called
private:
QgsComposition *mComposition = nullptr;
QString mReport;
QFont mTestFont;
};
TestQgsComposerHtml::TestQgsComposerHtml() = default;
void TestQgsComposerHtml::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mReport = QStringLiteral( "<h1>Composer HTML Tests</h1>\n" );
QgsFontUtils::loadStandardTestFonts( QStringList() << QStringLiteral( "Oblique" ) );
mTestFont = QgsFontUtils::getStandardTestFont( QStringLiteral( "Oblique " ) );
}
void TestQgsComposerHtml::cleanupTestCase()
{
delete mComposition;
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}
void TestQgsComposerHtml::init()
{
}
void TestQgsComposerHtml::cleanup()
{
}
void TestQgsComposerHtml::sourceMode()
{
QgsComposerHtml *htmlItem = new QgsComposerHtml( mComposition, false );
QgsComposerFrame *htmlFrame = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 200 );
htmlFrame->setFrameEnabled( true );
htmlItem->addFrame( htmlFrame );
htmlItem->setContentMode( QgsComposerHtml::ManualHtml );
htmlItem->setHtml( QStringLiteral( "<body style=\"margin: 10px;\"><div style=\"width: 100px; height: 50px; background-color: red;\"></div></body>" ) );
htmlItem->loadHtml();
QgsCompositionChecker checker( QStringLiteral( "composerhtml_manual" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_html" ) );
bool result = checker.testComposition( mReport, 0, 100 );
mComposition->removeMultiFrame( htmlItem );
delete htmlItem;
QVERIFY( result );
}
void TestQgsComposerHtml::userStylesheets()
{
QgsComposerHtml *htmlItem = new QgsComposerHtml( mComposition, false );
QgsComposerFrame *htmlFrame = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 200 );
htmlFrame->setFrameEnabled( true );
htmlItem->addFrame( htmlFrame );
htmlItem->setContentMode( QgsComposerHtml::ManualHtml );
htmlItem->setHtml( QStringLiteral( "<body style=\"margin: 10px;\"><div style=\"width: 100px; height: 50px; background-color: red;\"></div></body>" ) );
//set user stylesheet
htmlItem->setUserStylesheet( QStringLiteral( "div { background-color: green !important; }" ) );
//setting user stylesheet enabled automatically loads html
htmlItem->setUserStylesheetEnabled( true );
QgsCompositionChecker checker( QStringLiteral( "composerhtml_userstylesheet" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_html" ) );
bool result = checker.testComposition( mReport, 0, 100 );
mComposition->removeMultiFrame( htmlItem );
delete htmlItem;
QVERIFY( result );
}
void TestQgsComposerHtml::evalExpressions()
{
QgsComposerHtml *htmlItem = new QgsComposerHtml( mComposition, false );
QgsComposerFrame *htmlFrame = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 200 );
htmlFrame->setFrameEnabled( true );
htmlItem->addFrame( htmlFrame );
htmlItem->setContentMode( QgsComposerHtml::ManualHtml );
htmlItem->setEvaluateExpressions( true );
htmlItem->setHtml( QStringLiteral( "<body style=\"margin: 10px;\"><div style=\"width: [% 10 * 10 %]px; height: [% 30 + 20 %]px; background-color: [% 'yel' || 'low' %];\"></div></body>" ) );
htmlItem->loadHtml();
QgsCompositionChecker checker( QStringLiteral( "composerhtml_expressions_enabled" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_html" ) );
bool result = checker.testComposition( mReport );
mComposition->removeMultiFrame( htmlItem );
delete htmlItem;
QVERIFY( result );
}
void TestQgsComposerHtml::evalExpressionsOff()
{
QgsComposerHtml *htmlItem = new QgsComposerHtml( mComposition, false );
QgsComposerFrame *htmlFrame = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 200 );
htmlFrame->setFrameEnabled( true );
htmlItem->addFrame( htmlFrame );
htmlItem->setContentMode( QgsComposerHtml::ManualHtml );
htmlItem->setEvaluateExpressions( false );
htmlItem->setHtml( QStringLiteral( "<body style=\"margin: 10px;\"><div style=\"width: [% 10 * 10 %]px; height: [% 30 + 20 %]px; background-color: [% 'yel' || 'low' %];\"></div></body>" ) );
htmlItem->loadHtml();
QgsCompositionChecker checker( QStringLiteral( "composerhtml_expressions_disabled" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_html" ) );
bool result = checker.testComposition( mReport );
mComposition->removeMultiFrame( htmlItem );
delete htmlItem;
QVERIFY( result );
}
void TestQgsComposerHtml::table()
{
QgsComposerHtml *htmlItem = new QgsComposerHtml( mComposition, false );
QgsComposerFrame *htmlFrame = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 200 );
htmlFrame->setFrameEnabled( true );
htmlItem->addFrame( htmlFrame );
htmlItem->setUrl( QUrl( QStringLiteral( "file:///%1/test_html.html" ).arg( TEST_DATA_DIR ) ) );
QgsCompositionChecker checker( QStringLiteral( "composerhtml_table" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_html" ) );
bool result = checker.testComposition( mReport );
mComposition->removeMultiFrame( htmlItem );
delete htmlItem;
QVERIFY( result );
}
void TestQgsComposerHtml::tableMultiFrame()
{
QgsComposerHtml *htmlItem = new QgsComposerHtml( mComposition, false );
QgsComposerFrame *htmlFrame = new QgsComposerFrame( mComposition, htmlItem, 10, 10, 100, 50 );
htmlItem->addFrame( htmlFrame );
htmlItem->setResizeMode( QgsComposerMultiFrame::RepeatUntilFinished );
htmlItem->setUseSmartBreaks( false );
//page1
htmlItem->setUrl( QUrl( QStringLiteral( "file:///%1/test_html.html" ).arg( TEST_DATA_DIR ) ) );
htmlItem->frame( 0 )->setFrameEnabled( true );
QgsCompositionChecker checker1( QStringLiteral( "composerhtml_multiframe1" ), mComposition );
checker1.setControlPathPrefix( QStringLiteral( "composer_html" ) );
bool result = checker1.testComposition( mReport );
//page2
QgsCompositionChecker checker2( QStringLiteral( "composerhtml_multiframe2" ), mComposition );
checker2.setControlPathPrefix( QStringLiteral( "composer_html" ) );
result = checker2.testComposition( mReport, 1 ) && result;
mComposition->removeMultiFrame( htmlItem );
delete htmlItem;
QVERIFY( result );
}
void TestQgsComposerHtml::htmlMultiFrameSmartBreak()
{
QgsComposerHtml *htmlItem = new QgsComposerHtml( mComposition, false );
QgsComposerFrame *htmlFrame = new QgsComposerFrame( mComposition, htmlItem, 10, 10, 100, 52 );
htmlItem->addFrame( htmlFrame );
htmlItem->setResizeMode( QgsComposerMultiFrame::RepeatUntilFinished );
htmlItem->setUseSmartBreaks( true );
//page1
htmlItem->setUrl( QUrl( QStringLiteral( "file:///%1/test_html.html" ).arg( TEST_DATA_DIR ) ) );
htmlItem->frame( 0 )->setFrameEnabled( true );
QgsCompositionChecker checker1( QStringLiteral( "composerhtml_smartbreaks1" ), mComposition );
checker1.setControlPathPrefix( QStringLiteral( "composer_html" ) );
bool result = checker1.testComposition( mReport, 0, 200 );
//page2
QgsCompositionChecker checker2( QStringLiteral( "composerhtml_smartbreaks2" ), mComposition );
checker2.setControlPathPrefix( QStringLiteral( "composer_html" ) );
result = checker2.testComposition( mReport, 1, 200 ) && result;
mComposition->removeMultiFrame( htmlItem );
delete htmlItem;
QVERIFY( result );
}
void TestQgsComposerHtml::javascriptSetFeature()
{
//test that JavaScript setFeature() function is correctly called
// first need to setup some layers with a relation
//parent layer
QgsVectorLayer *parentLayer = new QgsVectorLayer( QStringLiteral( "Point?field=fldtxt:string&field=fldint:integer&field=foreignkey:integer" ), QStringLiteral( "parent" ), QStringLiteral( "memory" ) );
QgsVectorDataProvider *pr = parentLayer->dataProvider();
QgsFeature pf1;
pf1.setFields( parentLayer->fields() );
pf1.setAttributes( QgsAttributes() << "test1" << 67 << 123 );
QgsFeature pf2;
pf2.setFields( parentLayer->fields() );
pf2.setAttributes( QgsAttributes() << "test2" << 68 << 124 );
QVERIFY( pr->addFeatures( QgsFeatureList() << pf1 << pf2 ) );
// child layer
QgsVectorLayer *childLayer = new QgsVectorLayer( QStringLiteral( "Point?field=x:string&field=y:integer&field=z:integer" ), QStringLiteral( "referencedlayer" ), QStringLiteral( "memory" ) );
pr = childLayer->dataProvider();
QgsFeature f1;
f1.setFields( childLayer->fields() );
f1.setAttributes( QgsAttributes() << "foo" << 123 << 321 );
QgsFeature f2;
f2.setFields( childLayer->fields() );
f2.setAttributes( QgsAttributes() << "bar" << 123 << 654 );
QgsFeature f3;
f3.setFields( childLayer->fields() );
f3.setAttributes( QgsAttributes() << "foobar" << 124 << 554 );
QVERIFY( pr->addFeatures( QgsFeatureList() << f1 << f2 << f3 ) );
QgsProject::instance()->addMapLayers( QList<QgsMapLayer *>() << childLayer << parentLayer );
//atlas
mComposition->atlasComposition().setCoverageLayer( parentLayer );
mComposition->atlasComposition().setEnabled( true );
QgsRelation rel;
rel.setId( QStringLiteral( "rel1" ) );
rel.setName( QStringLiteral( "relation one" ) );
rel.setReferencingLayer( childLayer->id() );
rel.setReferencedLayer( parentLayer->id() );
rel.addFieldPair( QStringLiteral( "y" ), QStringLiteral( "foreignkey" ) );
QgsProject::instance()->relationManager()->addRelation( rel );
QgsComposerHtml *htmlItem = new QgsComposerHtml( mComposition, false );
QgsComposerFrame *htmlFrame = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 200 );
htmlFrame->setFrameEnabled( true );
htmlItem->addFrame( htmlFrame );
htmlItem->setContentMode( QgsComposerHtml::ManualHtml );
htmlItem->setEvaluateExpressions( true );
// hopefully arial bold 40px is big enough to avoid cross-platform rendering issues
htmlItem->setHtml( QString( "<body style=\"margin: 10px; font-family: Arial; font-weight: bold; font-size: 40px;\">"
"<div id=\"dest\"></div><script>setFeature=function(feature){"
"document.getElementById('dest').innerHTML = feature.properties.foreignkey + ',' +"
" feature.properties['relation one'][0].z + ',' + feature.properties['relation one'][1].z;}"
"</script></body>" ) );
mComposition->setAtlasMode( QgsComposition::ExportAtlas );
QVERIFY( mComposition->atlasComposition().beginRender() );
QVERIFY( mComposition->atlasComposition().prepareForFeature( 0 ) );
htmlItem->loadHtml();
QgsCompositionChecker checker( QStringLiteral( "composerhtml_setfeature" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_html" ) );
bool result = checker.testComposition( mReport );
mComposition->removeMultiFrame( htmlItem );
delete htmlItem;
QVERIFY( result );
QgsProject::instance()->removeMapLayers( QList<QgsMapLayer *>() << childLayer << parentLayer );
}
QGSTEST_MAIN( TestQgsComposerHtml )
#include "testqgscomposerhtml.moc"

View File

@ -1,264 +0,0 @@
/***************************************************************************
testqgscomposerlabel.cpp
----------------------
begin : Sept 2012
copyright : (C) 2012 by Hugo Mercier
email : hugo dot mercier at oslandia dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h"
#include "qgscomposition.h"
#include "qgscomposerlabel.h"
#include "qgsvectorlayer.h"
#include "qgsvectordataprovider.h"
#include "qgsmultirenderchecker.h"
#include "qgsfontutils.h"
#include "qgsproject.h"
#include <QObject>
#include "qgstest.h"
class TestQgsComposerLabel : public QObject
{
Q_OBJECT
public:
TestQgsComposerLabel() = default;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
// test simple expression evaluation
void evaluation();
// test expression evaluation when a feature is set
void feature_evaluation();
// test page expressions
void page_evaluation();
void marginMethods(); //tests getting/setting margins
void render();
void renderAsHtml();
void renderAsHtmlRelative();
private:
QgsComposition *mComposition = nullptr;
QgsComposerLabel *mComposerLabel = nullptr;
QgsVectorLayer *mVectorLayer = nullptr;
QString mReport;
};
void TestQgsComposerLabel::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
//create maplayers from testdata and add to layer registry
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + '/' + "france_parts.shp" );
mVectorLayer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
//create composition with composer map
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mComposition->atlasComposition().setCoverageLayer( mVectorLayer );
mComposerLabel = new QgsComposerLabel( mComposition );
mComposition->addComposerLabel( mComposerLabel );
qWarning() << "composer label font: " << mComposerLabel->font().toString() << " exactMatch:" << mComposerLabel->font().exactMatch();
}
void TestQgsComposerLabel::cleanupTestCase()
{
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
delete mComposition;
delete mVectorLayer;
QgsApplication::exitQgis();
}
void TestQgsComposerLabel::init()
{
mComposerLabel = new QgsComposerLabel( mComposition );
mComposition->addComposerLabel( mComposerLabel );
}
void TestQgsComposerLabel::cleanup()
{
mComposition->removeItem( mComposerLabel );
delete mComposerLabel;
mComposerLabel = nullptr;
}
void TestQgsComposerLabel::evaluation()
{
{
// $CURRENT_DATE evaluation
QString expected = "__" + QDate::currentDate().toString() + "__";
mComposerLabel->setText( QStringLiteral( "__$CURRENT_DATE__" ) );
QString evaluated = mComposerLabel->displayText();
QCOMPARE( evaluated, expected );
}
{
// $CURRENT_DATE() evaluation
QDateTime now = QDateTime::currentDateTime();
QString expected = "__" + now.toString( QStringLiteral( "dd" ) ) + "(ok)__";
mComposerLabel->setText( QStringLiteral( "__$CURRENT_DATE(dd)(ok)__" ) );
QString evaluated = mComposerLabel->displayText();
QCOMPARE( evaluated, expected );
}
{
// $CURRENT_DATE() evaluation (inside an expression)
QDate now = QDate::currentDate();
int dd = now.day();
QString expected = "__" + QStringLiteral( "%1" ).arg( dd + 1 ) + "(ok)__";
mComposerLabel->setText( QStringLiteral( "__[%$CURRENT_DATE(dd) + 1%](ok)__" ) );
QString evaluated = mComposerLabel->displayText();
QCOMPARE( evaluated, expected );
}
{
// expression evaluation (without feature)
QString expected = QStringLiteral( "__[NAME_1]42__" );
mComposerLabel->setText( QStringLiteral( "__[%\"NAME_1\"%][%21*2%]__" ) );
QString evaluated = mComposerLabel->displayText();
QCOMPARE( evaluated, expected );
}
}
void TestQgsComposerLabel::feature_evaluation()
{
mComposition->atlasComposition().setEnabled( true );
mComposition->setAtlasMode( QgsComposition::ExportAtlas );
mComposition->atlasComposition().updateFeatures();
mComposition->atlasComposition().prepareForFeature( 0 );
{
// evaluation with a feature
mComposerLabel->setText( QStringLiteral( "[%\"NAME_1\"||'_ok'%]" ) );
QString evaluated = mComposerLabel->displayText();
QString expected = QStringLiteral( "Basse-Normandie_ok" );
QCOMPARE( evaluated, expected );
}
mComposition->atlasComposition().prepareForFeature( 1 );
{
// evaluation with a feature
mComposerLabel->setText( QStringLiteral( "[%\"NAME_1\"||'_ok'%]" ) );
QString evaluated = mComposerLabel->displayText();
QString expected = QStringLiteral( "Bretagne_ok" );
QCOMPARE( evaluated, expected );
}
mComposition->atlasComposition().setEnabled( false );
}
void TestQgsComposerLabel::page_evaluation()
{
mComposition->setNumPages( 2 );
{
mComposerLabel->setText( QStringLiteral( "[%@layout_page||'/'||@layout_numpages%]" ) );
QString evaluated = mComposerLabel->displayText();
QString expected = QStringLiteral( "1/2" );
QCOMPARE( evaluated, expected );
// move to the second page and re-evaluate
mComposerLabel->setItemPosition( 0, 320 );
QCOMPARE( mComposerLabel->displayText(), QString( "2/2" ) );
}
}
void TestQgsComposerLabel::marginMethods()
{
QgsComposerLabel label( mComposition );
//test setting margins separately
label.setMarginX( 3.0 );
label.setMarginY( 4.0 );
QCOMPARE( label.marginX(), 3.0 );
QCOMPARE( label.marginY(), 4.0 );
//test setting margins together
label.setMargin( 5.0 );
QCOMPARE( label.marginX(), 5.0 );
QCOMPARE( label.marginY(), 5.0 );
//test reading label margins from pre 2.7 projects
QDomDocument labelDoc;
QString labelXml;
labelXml = QStringLiteral( "<ComposerLabel margin=\"9\"><ComposerItem></ComposerItem></ComposerLabel" );
labelDoc.setContent( labelXml );
QgsComposerLabel label2( mComposition );
label2.readXml( labelDoc.firstChildElement(), labelDoc );
QCOMPARE( label2.marginX(), 9.0 );
QCOMPARE( label2.marginY(), 9.0 );
//test reading label margins from >=2.7 projects
labelXml = QStringLiteral( "<ComposerLabel marginX=\"11\" marginY=\"12\"><ComposerItem></ComposerItem></ComposerLabel" );
labelDoc.setContent( labelXml );
QgsComposerLabel label3( mComposition );
label3.readXml( labelDoc.firstChildElement(), labelDoc );
QCOMPARE( label3.marginX(), 11.0 );
QCOMPARE( label3.marginY(), 12.0 );
}
void TestQgsComposerLabel::render()
{
mComposerLabel->setText( QStringLiteral( "test label" ) );
mComposerLabel->setFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ), 48 ) );
mComposerLabel->setPos( 70, 70 );
mComposerLabel->adjustSizeToText();
QgsCompositionChecker checker( QStringLiteral( "composerlabel_render" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_label" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
}
void TestQgsComposerLabel::renderAsHtml()
{
mComposerLabel->setFontColor( QColor( 200, 40, 60 ) );
mComposerLabel->setText( QStringLiteral( "test <i>html</i>" ) );
mComposerLabel->setFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ), 48 ) );
mComposerLabel->setPos( 70, 70 );
mComposerLabel->adjustSizeToText();
mComposerLabel->setHtmlState( 1 );
mComposerLabel->update();
QgsCompositionChecker checker( QStringLiteral( "composerlabel_renderhtml" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_label" ) );
QVERIFY( checker.testComposition( mReport, 0, 10 ) );
}
void TestQgsComposerLabel::renderAsHtmlRelative()
{
QgsProject::instance()->setFileName( QStringLiteral( TEST_DATA_DIR ) + QDir::separator() + "test.qgs" );
mComposerLabel->setFontColor( QColor( 200, 40, 60 ) );
mComposerLabel->setText( QStringLiteral( "test <img src=\"small_sample_image.png\" />" ) );
mComposerLabel->setFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ), 48 ) );
mComposerLabel->setPos( 70, 70 );
mComposerLabel->adjustSizeToText();
mComposerLabel->setHtmlState( 1 );
mComposerLabel->update();
QgsCompositionChecker checker( QStringLiteral( "composerlabel_renderhtmlrelative" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_label" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
}
QGSTEST_MAIN( TestQgsComposerLabel )
#include "testqgscomposerlabel.moc"

View File

@ -1,388 +0,0 @@
/***************************************************************************
testqgscomposermap.cpp
----------------------
begin : Juli 2012
copyright : (C) 2012 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h"
#include "qgscomposition.h"
#include "qgsmultirenderchecker.h"
#include "qgscomposermap.h"
#include "qgsmultibandcolorrenderer.h"
#include "qgsrasterlayer.h"
#include "qgsrasterdataprovider.h"
#include "qgsvectorlayer.h"
#include "qgsvectordataprovider.h"
#include "qgsproject.h"
#include "qgsmapthemecollection.h"
#include "qgsproperty.h"
#include <QObject>
#include "qgstest.h"
class TestQgsComposerMap : public QObject
{
Q_OBJECT
public:
TestQgsComposerMap() = default;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void render(); //test if rendering of the composition with composr map is correct
void uniqueId(); //test if map id is adapted when doing copy paste
void worldFileGeneration(); // test world file generation
void mapPolygonVertices(); // test mapPolygon function with no map rotation
void dataDefinedLayers(); //test data defined layer string
void dataDefinedStyles(); //test data defined styles
private:
QgsComposition *mComposition = nullptr;
QgsComposerMap *mComposerMap = nullptr;
QgsRasterLayer *mRasterLayer = nullptr;
QgsVectorLayer *mPointsLayer = nullptr;
QgsVectorLayer *mPolysLayer = nullptr;
QgsVectorLayer *mLinesLayer = nullptr;
QString mReport;
};
void TestQgsComposerMap::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
//create maplayers from testdata and add to layer registry
QFileInfo rasterFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/landsat.tif" );
mRasterLayer = new QgsRasterLayer( rasterFileInfo.filePath(),
rasterFileInfo.completeBaseName() );
QgsMultiBandColorRenderer *rasterRenderer = new QgsMultiBandColorRenderer( mRasterLayer->dataProvider(), 2, 3, 4 );
mRasterLayer->setRenderer( rasterRenderer );
QFileInfo pointFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points.shp" );
mPointsLayer = new QgsVectorLayer( pointFileInfo.filePath(),
pointFileInfo.completeBaseName(), QStringLiteral( "ogr" ) );
QFileInfo polyFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/polys.shp" );
mPolysLayer = new QgsVectorLayer( polyFileInfo.filePath(),
polyFileInfo.completeBaseName(), QStringLiteral( "ogr" ) );
QFileInfo lineFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/lines.shp" );
mLinesLayer = new QgsVectorLayer( lineFileInfo.filePath(),
lineFileInfo.completeBaseName(), QStringLiteral( "ogr" ) );
// some layers need to be in project for data-defined layers functionality
QgsProject::instance()->addMapLayers( QList<QgsMapLayer *>() << mRasterLayer << mPointsLayer << mPolysLayer << mLinesLayer );
}
void TestQgsComposerMap::cleanupTestCase()
{
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}
void TestQgsComposerMap::init()
{
//create composition with composer map
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mComposerMap = new QgsComposerMap( mComposition, 20, 20, 200, 100 );
mComposerMap->setFrameEnabled( true );
mComposerMap->setLayers( QList<QgsMapLayer *>() << mRasterLayer );
mComposition->addComposerMap( mComposerMap );
mReport = QStringLiteral( "<h1>Composer Map Tests</h1>\n" );
}
void TestQgsComposerMap::cleanup()
{
delete mComposition;
}
void TestQgsComposerMap::render()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
QgsCompositionChecker checker( QStringLiteral( "composermap_render" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_map" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
}
void TestQgsComposerMap::uniqueId()
{
QDomDocument doc;
QDomElement documentElement = doc.createElement( QStringLiteral( "ComposerItemClipboard" ) );
mComposerMap->writeXml( documentElement, doc );
mComposition->addItemsFromXml( documentElement, doc, false );
//test if both composer maps have different ids
const QgsComposerMap *newMap = nullptr;
QList<const QgsComposerMap *> mapList = mComposition->composerMapItems();
QList<const QgsComposerMap *>::const_iterator mapIt = mapList.constBegin();
for ( ; mapIt != mapList.constEnd(); ++mapIt )
{
if ( *mapIt != mComposerMap )
{
newMap = *mapIt;
break;
}
}
QVERIFY( newMap );
int oldId = mComposerMap->id();
int newId = newMap->id();
mComposition->removeComposerItem( const_cast<QgsComposerMap *>( newMap ) );
QVERIFY( oldId != newId );
}
void TestQgsComposerMap::worldFileGeneration()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->setMapRotation( 30.0 );
mComposition->setGenerateWorldFile( true );
mComposition->setReferenceMap( mComposerMap );
double a, b, c, d, e, f;
mComposition->computeWorldFileParameters( a, b, c, d, e, f );
QGSCOMPARENEAR( a, 4.18048, 0.001 );
QGSCOMPARENEAR( b, 2.41331, 0.001 );
QGSCOMPARENEAR( c, 779444, 1 );
QGSCOMPARENEAR( d, 2.4136, 0.001 );
QGSCOMPARENEAR( e, -4.17997, 0.001 );
QGSCOMPARENEAR( f, 3.34241e+06, 1e+03 );
//test with map on second page. Parameters should be the same
mComposerMap->setItemPosition( 20, 20, QgsComposerItem::UpperLeft, 2 );
mComposition->computeWorldFileParameters( a, b, c, d, e, f );
QGSCOMPARENEAR( a, 4.18048, 0.001 );
QGSCOMPARENEAR( b, 2.41331, 0.001 );
QGSCOMPARENEAR( c, 779444, 1 );
QGSCOMPARENEAR( d, 2.4136, 0.001 );
QGSCOMPARENEAR( e, -4.17997, 0.001 );
QGSCOMPARENEAR( f, 3.34241e+06, 1e+03 );
//test computing parameters for specific region
mComposerMap->setItemPosition( 20, 20, QgsComposerItem::UpperLeft, 2 );
mComposition->computeWorldFileParameters( QRectF( 10, 5, 260, 200 ), a, b, c, d, e, f );
QGSCOMPARENEAR( a, 4.18061, 0.001 );
QGSCOMPARENEAR( b, 2.41321, 0.001 );
QGSCOMPARENEAR( c, 773810, 1 );
QGSCOMPARENEAR( d, 2.4137, 0.001 );
QGSCOMPARENEAR( e, -4.1798, 0.001 );
QGSCOMPARENEAR( f, 3.35331e+06, 1e+03 );
mComposition->setGenerateWorldFile( false );
mComposerMap->setMapRotation( 0.0 );
}
void TestQgsComposerMap::mapPolygonVertices()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
QPolygonF visibleExtent = mComposerMap->visibleExtentPolygon();
//vertices should be returned in clockwise order starting at the top-left point
QVERIFY( std::fabs( visibleExtent[0].x() - 781662.375 ) < 0.001 );
QVERIFY( std::fabs( visibleExtent[0].y() - 3345223.125 ) < 0.001 );
QVERIFY( std::fabs( visibleExtent[1].x() - 793062.375 ) < 0.001 );
QVERIFY( std::fabs( visibleExtent[1].y() - 3345223.125 ) < 0.001 );
QVERIFY( std::fabs( visibleExtent[2].x() - 793062.375 ) < 0.001 );
QVERIFY( std::fabs( visibleExtent[2].y() - 3339523.125 ) < 0.001 );
QVERIFY( std::fabs( visibleExtent[3].x() - 781662.375 ) < 0.001 );
QVERIFY( std::fabs( visibleExtent[3].y() - 3339523.125 ) < 0.001 );
//polygon should be closed
QVERIFY( visibleExtent.isClosed() );
//now test with rotated map
mComposerMap->setMapRotation( 10 );
visibleExtent = mComposerMap->visibleExtentPolygon();
//vertices should be returned in clockwise order starting at the top-left point
QVERIFY( std::fabs( visibleExtent[0].x() - 781254.0735015 ) < 0.001 );
QVERIFY( std::fabs( visibleExtent[0].y() - 3344190.0324834 ) < 0.001 );
QVERIFY( std::fabs( visibleExtent[1].x() - 792480.881886 ) < 0.001 );
QVERIFY( std::fabs( visibleExtent[1].y() - 3346169.62171 ) < 0.001 );
QVERIFY( std::fabs( visibleExtent[2].x() - 793470.676499 ) < 0.001 );
QVERIFY( std::fabs( visibleExtent[2].y() - 3340556.21752 ) < 0.001 );
QVERIFY( std::fabs( visibleExtent[3].x() - 782243.868114 ) < 0.001 );
QVERIFY( std::fabs( visibleExtent[3].y() - 3338576.62829 ) < 0.001 );
//polygon should be closed
QVERIFY( visibleExtent.isClosed() );
mComposerMap->setMapRotation( 0 );
}
void TestQgsComposerMap::dataDefinedLayers()
{
delete mComposition;
QgsMapSettings ms;
ms.setLayers( QList<QgsMapLayer *>() << mRasterLayer << mPolysLayer << mPointsLayer << mLinesLayer );
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mComposerMap = new QgsComposerMap( mComposition, 20, 20, 200, 100 );
mComposerMap->setFrameEnabled( true );
mComposition->addComposerMap( mComposerMap );
//test malformed layer set string
mComposerMap->dataDefinedProperties().setProperty( QgsComposerObject::MapLayers, QgsProperty::fromExpression( QStringLiteral( "'x'" ) ) );
QList<QgsMapLayer *> result = mComposerMap->layersToRender();
QVERIFY( result.isEmpty() );
mComposerMap->dataDefinedProperties().setProperty( QgsComposerObject::MapLayers, QgsProperty::fromExpression( QStringLiteral( "'x|'" ) ) );
result = mComposerMap->layersToRender();
QVERIFY( result.isEmpty() );
//test subset of valid layers
mComposerMap->dataDefinedProperties().setProperty( QgsComposerObject::MapLayers, QgsProperty::fromExpression(
QStringLiteral( "'%1|%2'" ).arg( mPolysLayer->name(), mRasterLayer->name() ) ) );
result = mComposerMap->layersToRender();
QCOMPARE( result.count(), 2 );
QVERIFY( result.contains( mPolysLayer ) );
QVERIFY( result.contains( mRasterLayer ) );
//test non-existent layer
mComposerMap->dataDefinedProperties().setProperty( QgsComposerObject::MapLayers, QgsProperty::fromExpression(
QStringLiteral( "'x|%1|%2'" ).arg( mLinesLayer->name(), mPointsLayer->name() ) ) );
result = mComposerMap->layersToRender();
QCOMPARE( result.count(), 2 );
QVERIFY( result.contains( mLinesLayer ) );
QVERIFY( result.contains( mPointsLayer ) );
//test no layers
mComposerMap->dataDefinedProperties().setProperty( QgsComposerObject::MapLayers, QgsProperty::fromExpression(
QStringLiteral( "''" ) ) );
result = mComposerMap->layersToRender();
QVERIFY( result.isEmpty() );
//test with atlas feature evaluation
QgsVectorLayer *atlasLayer = new QgsVectorLayer( QStringLiteral( "Point?field=col1:string" ), QStringLiteral( "atlas" ), QStringLiteral( "memory" ) );
QVERIFY( atlasLayer->isValid() );
QgsFeature f1( atlasLayer->dataProvider()->fields(), 1 );
f1.setAttribute( QStringLiteral( "col1" ), mLinesLayer->name() );
QgsFeature f2( atlasLayer->dataProvider()->fields(), 1 );
f2.setAttribute( QStringLiteral( "col1" ), mPointsLayer->name() );
atlasLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 << f2 );
mComposition->atlasComposition().setCoverageLayer( atlasLayer );
mComposition->atlasComposition().setEnabled( true );
mComposition->setAtlasMode( QgsComposition::ExportAtlas );
mComposition->atlasComposition().beginRender();
mComposition->atlasComposition().prepareForFeature( 0 );
mComposerMap->dataDefinedProperties().setProperty( QgsComposerObject::MapLayers, QgsProperty::fromField( QStringLiteral( "col1" ) ) );
result = mComposerMap->layersToRender();
QCOMPARE( result.count(), 1 );
QCOMPARE( result.at( 0 ), mLinesLayer );
mComposition->atlasComposition().prepareForFeature( 1 );
result = mComposerMap->layersToRender();
QCOMPARE( result.count(), 1 );
QCOMPARE( result.at( 0 ), mPointsLayer );
mComposition->atlasComposition().setEnabled( false );
delete atlasLayer;
//render test
mComposerMap->dataDefinedProperties().setProperty( QgsComposerObject::MapLayers, QgsProperty::fromExpression(
QStringLiteral( "'%1|%2'" ).arg( mPolysLayer->name(), mPointsLayer->name() ) ) );
mComposerMap->setNewExtent( QgsRectangle( -110.0, 25.0, -90, 40.0 ) );
QgsCompositionChecker checker( QStringLiteral( "composermap_ddlayers" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_map" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
}
void TestQgsComposerMap::dataDefinedStyles()
{
delete mComposition;
QList<QgsMapLayer *> layers = QList<QgsMapLayer *>() << mRasterLayer << mPolysLayer << mPointsLayer << mLinesLayer;
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mComposerMap = new QgsComposerMap( mComposition, 20, 20, 200, 100 );
mComposerMap->setFrameEnabled( true );
mComposerMap->setLayers( layers );
mComposition->addComposerMap( mComposerMap );
QgsMapThemeCollection::MapThemeRecord rec;
rec.setLayerRecords( QList<QgsMapThemeCollection::MapThemeLayerRecord>()
<< QgsMapThemeCollection::MapThemeLayerRecord( mPointsLayer )
<< QgsMapThemeCollection::MapThemeLayerRecord( mLinesLayer )
);
QgsProject::instance()->mapThemeCollection()->insert( QStringLiteral( "test preset" ), rec );
// test following of preset
mComposerMap->setFollowVisibilityPreset( true );
mComposerMap->setFollowVisibilityPresetName( QStringLiteral( "test preset" ) );
QSet<QgsMapLayer *> result = mComposerMap->layersToRender().toSet();
QCOMPARE( result.count(), 2 );
mComposerMap->setFollowVisibilityPresetName( QString() );
//test malformed style string
mComposerMap->dataDefinedProperties().setProperty( QgsComposerObject::MapStylePreset, QgsProperty::fromExpression( QStringLiteral( "5" ) ) );
result = mComposerMap->layersToRender().toSet();
QCOMPARE( result, layers.toSet() );
//test valid preset
mComposerMap->dataDefinedProperties().setProperty( QgsComposerObject::MapStylePreset, QgsProperty::fromExpression( QStringLiteral( "'test preset'" ) ) );
result = mComposerMap->layersToRender().toSet();
QCOMPARE( result.count(), 2 );
QVERIFY( result.contains( mLinesLayer ) );
QVERIFY( result.contains( mPointsLayer ) );
//test non-existent preset
mComposerMap->dataDefinedProperties().setProperty( QgsComposerObject::MapStylePreset, QgsProperty::fromExpression( QStringLiteral( "'bad preset'" ) ) );
result = mComposerMap->layersToRender().toSet();
QCOMPARE( result, layers.toSet() );
//test that dd layer set overrides style layers
mComposerMap->dataDefinedProperties().setProperty( QgsComposerObject::MapStylePreset, QgsProperty::fromExpression( QStringLiteral( "'test preset'" ) ) );
mComposerMap->dataDefinedProperties().setProperty( QgsComposerObject::MapLayers, QgsProperty::fromExpression(
QStringLiteral( "'%1'" ).arg( mPolysLayer->name() ) ) );
result = mComposerMap->layersToRender().toSet();
QCOMPARE( result.count(), 1 );
QVERIFY( result.contains( mPolysLayer ) );
mComposerMap->dataDefinedProperties().setProperty( QgsComposerObject::MapLayers, QgsProperty() );
//render test
mComposerMap->dataDefinedProperties().setProperty( QgsComposerObject::MapStylePreset, QgsProperty::fromExpression( QStringLiteral( "'test preset'" ) ) );
mComposerMap->setNewExtent( QgsRectangle( -110.0, 25.0, -90, 40.0 ) );
QgsCompositionChecker checker( QStringLiteral( "composermap_ddstyles" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_map" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
}
QGSTEST_MAIN( TestQgsComposerMap )
#include "testqgscomposermap.moc"

View File

@ -1,704 +0,0 @@
/***************************************************************************
testqgscomposermapgrid.cpp
----------------------
begin : August 2014
copyright : (C) 2014 by Nyall Dawosn, Marco Hugentobler
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h"
#include "qgscomposition.h"
#include "qgsmultirenderchecker.h"
#include "qgscomposermap.h"
#include "qgscomposermapgrid.h"
#include "qgsfontutils.h"
#include "qgsproject.h"
#include <QObject>
#include "qgstest.h"
class TestQgsComposerMapGrid : public QObject
{
Q_OBJECT
public:
TestQgsComposerMapGrid();
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void grid(); //test if grid and grid annotation works
void reprojected(); //test if reprojected grid works
void crossGrid(); //test if grid "cross" mode works
void markerGrid(); //test if grid "marker" mode works
void frameOnly(); //test if grid "frame/annotation" mode works
void zebraStyle(); //test zebra map border style
void zebraStyleSides(); //test zebra border on certain sides
void frameDivisions(); //test filtering frame divisions
void annotationFilter(); //test filtering annotations
void interiorTicks(); //test interior tick mode
void interiorTicksAnnotated(); //test interior tick mode with annotations
void exteriorTicks(); //test exterior tick mode
void exteriorTicksAnnotated(); //test exterior tick mode with annotations
void interiorExteriorTicks(); //test interior & exterior tick mode
void interiorExteriorTicksAnnotated(); //test interior & exterior tick mode with annotations
void lineBorder(); //test line border frame mode
void lineBorderAnnotated(); //test line border frame with annotations
void annotationFormats(); //various tests for annotation formats
void descendingAnnotations(); //test descending annotation direction
private:
QgsComposition *mComposition = nullptr;
QgsComposerMap *mComposerMap = nullptr;
QgsMapSettings *mMapSettings = nullptr;
QString mReport;
};
TestQgsComposerMapGrid::TestQgsComposerMapGrid() = default;
void TestQgsComposerMapGrid::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
mMapSettings = new QgsMapSettings();
mReport = QStringLiteral( "<h1>Composer Map Grid Tests</h1>\n" );
}
void TestQgsComposerMapGrid::cleanupTestCase()
{
delete mMapSettings;
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}
void TestQgsComposerMapGrid::init()
{
QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem( 32633 );
mMapSettings->setDestinationCrs( crs );
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mComposerMap = new QgsComposerMap( mComposition, 20, 20, 200, 100 );
mComposerMap->setFrameEnabled( true );
mComposerMap->setBackgroundColor( QColor( 150, 100, 100 ) );
mComposerMap->grid()->setAnnotationFont( QgsFontUtils::getStandardTestFont() );
mComposerMap->grid()->setAnnotationPrecision( 0 );
mComposerMap->grid()->setIntervalX( 2000 );
mComposerMap->grid()->setIntervalY( 2000 );
mComposerMap->grid()->setGridLineWidth( 0.5 );
mComposerMap->grid()->setGridLineColor( QColor( 0, 0, 0 ) );
mComposerMap->updateBoundingRect();
mComposition->addComposerMap( mComposerMap );
}
void TestQgsComposerMapGrid::cleanup()
{
delete mComposition;
}
void TestQgsComposerMapGrid::grid()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setAnnotationEnabled( true );
mComposerMap->grid()->setGridLineColor( QColor( 0, 255, 0 ) );
mComposerMap->grid()->setAnnotationDisplay( QgsComposerMapGrid::HideAll, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationDisplay( QgsComposerMapGrid::HideAll, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Bottom );
mComposerMap->grid()->setAnnotationDirection( QgsComposerMapGrid::Horizontal, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationDirection( QgsComposerMapGrid::Horizontal, QgsComposerMapGrid::Bottom );
mComposerMap->grid()->setAnnotationFontColor( QColor( 255, 0, 0, 150 ) );
mComposerMap->grid()->setBlendMode( QPainter::CompositionMode_Overlay );
mComposerMap->updateBoundingRect();
qWarning() << "grid annotation font: " << mComposerMap->grid()->annotationFont().toString() << " exactMatch:" << mComposerMap->grid()->annotationFont().exactMatch();
QgsCompositionChecker checker( QStringLiteral( "composermap_grid" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
mComposerMap->grid()->setEnabled( false );
mComposerMap->grid()->setAnnotationEnabled( false );
QVERIFY( testResult );
}
void TestQgsComposerMapGrid::reprojected()
{
mComposerMap->setNewExtent( QgsRectangle( -243577.565, 2939084.773, 1215622.435, 3668684.773 ) );
QgsCoordinateReferenceSystem geographic = QgsCoordinateReferenceSystem( 4326 );
mComposerMap->grid()->setCrs( geographic );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setIntervalX( 1 );
mComposerMap->grid()->setIntervalY( 1 );
mComposerMap->grid()->setAnnotationEnabled( false );
mComposerMap->grid()->setBlendMode( QPainter::CompositionMode_SourceOver );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::ExteriorTicks );
mComposerMap->grid()->setFrameWidth( 10 );
mComposerMap->setFrameEnabled( false );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_gridreprojected" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
mComposerMap->grid()->setEnabled( false );
mComposerMap->grid()->setCrs( mMapSettings->destinationCrs() );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::NoFrame );
mComposerMap->setFrameEnabled( true );
QVERIFY( testResult );
}
void TestQgsComposerMapGrid::crossGrid()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::Cross );
mComposerMap->grid()->setCrossLength( 2.0 );
mComposerMap->grid()->setAnnotationEnabled( false );
mComposerMap->grid()->setGridLineColor( QColor( 0, 255, 0 ) );
mComposerMap->grid()->setBlendMode( QPainter::CompositionMode_SourceOver );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_crossgrid" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::Solid );
mComposerMap->grid()->setEnabled( false );
mComposerMap->grid()->setAnnotationEnabled( false );
QVERIFY( testResult );
}
void TestQgsComposerMapGrid::markerGrid()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::Markers );
mComposerMap->grid()->setAnnotationEnabled( false );
mComposerMap->grid()->setBlendMode( QPainter::CompositionMode_SourceOver );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_markergrid" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::Solid );
mComposerMap->grid()->setEnabled( false );
mComposerMap->grid()->setAnnotationEnabled( false );
QVERIFY( testResult );
}
void TestQgsComposerMapGrid::frameOnly()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::FrameAnnotationsOnly );
mComposerMap->grid()->setAnnotationEnabled( false );
//set a frame for testing
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::Zebra );
mComposerMap->grid()->setFrameWidth( 2.0 );
mComposerMap->grid()->setFramePenSize( 0.5 );
mComposerMap->grid()->setBlendMode( QPainter::CompositionMode_SourceOver );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_gridframeonly" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::Solid );
mComposerMap->grid()->setEnabled( false );
mComposerMap->grid()->setAnnotationEnabled( false );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::NoFrame );
QVERIFY( testResult );
}
void TestQgsComposerMapGrid::zebraStyle()
{
mComposerMap->setNewExtent( QgsRectangle( 785462.375, 3341423.125, 789262.375, 3343323.125 ) ); //zoom in
mComposerMap->grid()->setAnnotationFontColor( QColor( 0, 0, 0, 0 ) );
mComposerMap->grid()->setBlendMode( QPainter::CompositionMode_SourceOver );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::Zebra );
mComposerMap->grid()->setFrameWidth( 10 );
mComposerMap->grid()->setFramePenSize( 1 );
mComposerMap->grid()->setFramePenColor( QColor( 255, 100, 0, 200 ) );
mComposerMap->grid()->setFrameFillColor1( QColor( 50, 90, 50, 100 ) );
mComposerMap->grid()->setFrameFillColor2( QColor( 200, 220, 100, 60 ) );
mComposerMap->grid()->setEnabled( true );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_zebrastyle" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
}
void TestQgsComposerMapGrid::zebraStyleSides()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->grid()->setAnnotationFontColor( QColor( 0, 0, 0, 0 ) );
mComposerMap->grid()->setBlendMode( QPainter::CompositionMode_SourceOver );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::Zebra );
mComposerMap->grid()->setFrameWidth( 10 );
mComposerMap->grid()->setFramePenSize( 1 );
mComposerMap->grid()->setFramePenColor( Qt::black );
mComposerMap->grid()->setFrameFillColor1( Qt::black );
mComposerMap->grid()->setFrameFillColor2( Qt::white );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setFrameSideFlag( QgsComposerMapGrid::FrameLeft, true );
mComposerMap->grid()->setFrameSideFlag( QgsComposerMapGrid::FrameRight, false );
mComposerMap->grid()->setFrameSideFlag( QgsComposerMapGrid::FrameTop, false );
mComposerMap->grid()->setFrameSideFlag( QgsComposerMapGrid::FrameBottom, false );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_zebrastyle_left" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
mComposerMap->grid()->setFrameSideFlag( QgsComposerMapGrid::FrameTop, true );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker2( QStringLiteral( "composermap_zebrastyle_lefttop" ), mComposition );
checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult2 = checker2.testComposition( mReport, 0, 0 );
QVERIFY( testResult2 );
mComposerMap->grid()->setFrameSideFlag( QgsComposerMapGrid::FrameRight, true );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker3( QStringLiteral( "composermap_zebrastyle_lefttopright" ), mComposition );
checker3.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult3 = checker3.testComposition( mReport, 0, 0 );
QVERIFY( testResult3 );
mComposerMap->grid()->setFrameSideFlag( QgsComposerMapGrid::FrameBottom, true );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::NoFrame );
}
void TestQgsComposerMapGrid::frameDivisions()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
//rotate map, so we mix latitude and longitude coordinates on every map side
mComposerMap->setMapRotation( 45.0 );
//setup defaults
mComposerMap->grid()->setAnnotationFontColor( QColor( 0, 0, 0, 0 ) );
mComposerMap->grid()->setBlendMode( QPainter::CompositionMode_SourceOver );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::Zebra );
mComposerMap->grid()->setFrameWidth( 10 );
mComposerMap->grid()->setFramePenSize( 1 );
mComposerMap->grid()->setFramePenColor( Qt::black );
mComposerMap->grid()->setFrameFillColor1( Qt::black );
mComposerMap->grid()->setFrameFillColor2( Qt::white );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setFrameSideFlag( QgsComposerMapGrid::FrameLeft, true );
mComposerMap->grid()->setFrameSideFlag( QgsComposerMapGrid::FrameRight, true );
mComposerMap->grid()->setFrameSideFlag( QgsComposerMapGrid::FrameTop, true );
mComposerMap->grid()->setFrameSideFlag( QgsComposerMapGrid::FrameBottom, true );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_rotatedframe" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
mComposerMap->grid()->setFrameDivisions( QgsComposerMapGrid::LatitudeOnly, QgsComposerMapGrid::Left );
mComposerMap->grid()->setFrameDivisions( QgsComposerMapGrid::LongitudeOnly, QgsComposerMapGrid::Right );
mComposerMap->grid()->setFrameDivisions( QgsComposerMapGrid::LatitudeOnly, QgsComposerMapGrid::Top );
mComposerMap->grid()->setFrameDivisions( QgsComposerMapGrid::LongitudeOnly, QgsComposerMapGrid::Bottom );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker2( QStringLiteral( "composermap_framedivisions" ), mComposition );
checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
testResult = checker2.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
mComposerMap->grid()->setFrameDivisions( QgsComposerMapGrid::ShowAll, QgsComposerMapGrid::Left );
mComposerMap->grid()->setFrameDivisions( QgsComposerMapGrid::ShowAll, QgsComposerMapGrid::Right );
mComposerMap->grid()->setFrameDivisions( QgsComposerMapGrid::ShowAll, QgsComposerMapGrid::Top );
mComposerMap->grid()->setFrameDivisions( QgsComposerMapGrid::ShowAll, QgsComposerMapGrid::Bottom );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::NoFrame );
mComposerMap->setMapRotation( 0.0 );
}
void TestQgsComposerMapGrid::annotationFilter()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
//rotate map, so we mix latitude and longitude coordinates on every map side
mComposerMap->setMapRotation( 45.0 );
//setup defaults
mComposerMap->grid()->setAnnotationFontColor( QColor( 0, 0, 0, 0 ) );
mComposerMap->grid()->setBlendMode( QPainter::CompositionMode_SourceOver );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::NoFrame );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setAnnotationEnabled( true );
mComposerMap->grid()->setAnnotationFontColor( Qt::black );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Bottom );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_rotatedannotations" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
mComposerMap->grid()->setAnnotationDisplay( QgsComposerMapGrid::HideAll, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationDisplay( QgsComposerMapGrid::LongitudeOnly, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationDisplay( QgsComposerMapGrid::LatitudeOnly, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationDisplay( QgsComposerMapGrid::LongitudeOnly, QgsComposerMapGrid::Bottom );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker2( QStringLiteral( "composermap_filteredannotations" ), mComposition );
checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
testResult = checker2.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
mComposerMap->grid()->setAnnotationEnabled( false );
mComposerMap->grid()->setAnnotationDisplay( QgsComposerMapGrid::ShowAll, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationDisplay( QgsComposerMapGrid::ShowAll, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationDisplay( QgsComposerMapGrid::ShowAll, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationDisplay( QgsComposerMapGrid::ShowAll, QgsComposerMapGrid::Bottom );
mComposerMap->setMapRotation( 0.0 );
}
void TestQgsComposerMapGrid::interiorTicks()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::InteriorTicks );
mComposerMap->grid()->setFrameWidth( 10 );
mComposerMap->grid()->setFramePenSize( 1 );
mComposerMap->grid()->setFramePenColor( Qt::black );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::FrameAnnotationsOnly );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_interiorticks" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::NoFrame );
}
void TestQgsComposerMapGrid::interiorTicksAnnotated()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::InteriorTicks );
mComposerMap->grid()->setFrameWidth( 10 );
mComposerMap->grid()->setFramePenSize( 1 );
mComposerMap->grid()->setFramePenColor( Qt::black );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::FrameAnnotationsOnly );
mComposerMap->grid()->setAnnotationEnabled( true );
mComposerMap->grid()->setAnnotationFontColor( Qt::black );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Bottom );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_interiorticks_annotated" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Bottom );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker2( QStringLiteral( "composermap_interiorticks_annotated2" ), mComposition );
checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult2 = checker2.testComposition( mReport, 0, 0 );
QVERIFY( testResult2 );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::NoFrame );
mComposerMap->grid()->setAnnotationEnabled( false );
}
void TestQgsComposerMapGrid::exteriorTicks()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::ExteriorTicks );
mComposerMap->grid()->setFrameWidth( 10 );
mComposerMap->grid()->setFramePenSize( 1 );
mComposerMap->grid()->setFramePenColor( Qt::black );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::FrameAnnotationsOnly );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_exteriorticks" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::NoFrame );
}
void TestQgsComposerMapGrid::exteriorTicksAnnotated()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::ExteriorTicks );
mComposerMap->grid()->setFrameWidth( 10 );
mComposerMap->grid()->setFramePenSize( 1 );
mComposerMap->grid()->setFramePenColor( Qt::black );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::FrameAnnotationsOnly );
mComposerMap->grid()->setAnnotationEnabled( true );
mComposerMap->grid()->setAnnotationFontColor( Qt::black );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Bottom );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_exteriorticks_annotated" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Bottom );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker2( QStringLiteral( "composermap_exteriorticks_annotated2" ), mComposition );
checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult2 = checker2.testComposition( mReport, 0, 0 );
QVERIFY( testResult2 );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::NoFrame );
mComposerMap->grid()->setAnnotationEnabled( false );
}
void TestQgsComposerMapGrid::interiorExteriorTicks()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::InteriorExteriorTicks );
mComposerMap->grid()->setFrameWidth( 10 );
mComposerMap->grid()->setFramePenSize( 1 );
mComposerMap->grid()->setFramePenColor( Qt::black );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::FrameAnnotationsOnly );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_interiorexteriorticks" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::NoFrame );
}
void TestQgsComposerMapGrid::interiorExteriorTicksAnnotated()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::InteriorExteriorTicks );
mComposerMap->grid()->setFrameWidth( 10 );
mComposerMap->grid()->setFramePenSize( 1 );
mComposerMap->grid()->setFramePenColor( Qt::black );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::FrameAnnotationsOnly );
mComposerMap->grid()->setAnnotationEnabled( true );
mComposerMap->grid()->setAnnotationFontColor( Qt::black );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Bottom );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_interiorexteriorticks_annotated" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Bottom );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker2( QStringLiteral( "composermap_interiorexteriorticks_annotated2" ), mComposition );
checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult2 = checker2.testComposition( mReport, 0, 0 );
QVERIFY( testResult2 );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::NoFrame );
mComposerMap->grid()->setAnnotationEnabled( false );
}
void TestQgsComposerMapGrid::lineBorder()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::LineBorder );
mComposerMap->grid()->setFrameWidth( 10 );
mComposerMap->grid()->setFramePenSize( 1 );
mComposerMap->grid()->setFramePenColor( Qt::black );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::FrameAnnotationsOnly );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_lineborder" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::NoFrame );
}
void TestQgsComposerMapGrid::lineBorderAnnotated()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::LineBorder );
mComposerMap->grid()->setFrameWidth( 10 );
mComposerMap->grid()->setFramePenSize( 1 );
mComposerMap->grid()->setFramePenColor( Qt::black );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::FrameAnnotationsOnly );
mComposerMap->grid()->setAnnotationEnabled( true );
mComposerMap->grid()->setAnnotationFontColor( Qt::black );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Bottom );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_lineborder_annotated" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Bottom );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker2( QStringLiteral( "composermap_lineborder_annotated2" ), mComposition );
checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult2 = checker2.testComposition( mReport, 0, 0 );
QVERIFY( testResult2 );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::NoFrame );
mComposerMap->grid()->setAnnotationEnabled( false );
}
void TestQgsComposerMapGrid::annotationFormats()
{
//create grids in geographic and projected coordinates
QgsCoordinateReferenceSystem projectedCrs;
projectedCrs.createFromSrid( 3994 );
QgsCoordinateReferenceSystem geographicCrs;
geographicCrs.createFromSrid( 4326 );
QgsComposerMapGrid gridGeographic( QStringLiteral( "geographic grid" ), mComposerMap );
gridGeographic.setCrs( geographicCrs );
QgsComposerMapGrid gridProjected( QStringLiteral( "projected grid" ), mComposerMap );
gridProjected.setCrs( projectedCrs );
//decimal degrees format
gridGeographic.setAnnotationFormat( QgsComposerMapGrid::DecimalWithSuffix );
gridGeographic.setAnnotationPrecision( 1 );
gridProjected.setAnnotationFormat( QgsComposerMapGrid::DecimalWithSuffix );
gridProjected.setAnnotationPrecision( 1 );
QgsExpressionContext expressionContext = gridGeographic.createExpressionContext();
//normal e/w
QCOMPARE( gridGeographic.gridAnnotationString( 90, QgsComposerMapGrid::Longitude, expressionContext ), QString( "90.0" ) + QChar( 176 ) + QString( "E" ) );
QCOMPARE( gridProjected.gridAnnotationString( 90, QgsComposerMapGrid::Longitude, expressionContext ), QString( "90.0E" ) );
//0 degrees
QCOMPARE( gridGeographic.gridAnnotationString( 0, QgsComposerMapGrid::Longitude, expressionContext ), QString( "0.0" ) + QChar( 176 ) );
QCOMPARE( gridProjected.gridAnnotationString( 0, QgsComposerMapGrid::Longitude, expressionContext ), QString( "0.0E" ) );
//180 degrees
QCOMPARE( gridGeographic.gridAnnotationString( 180, QgsComposerMapGrid::Longitude, expressionContext ), QString( "180.0" ) + QChar( 176 ) );
QCOMPARE( gridProjected.gridAnnotationString( 180, QgsComposerMapGrid::Longitude, expressionContext ), QString( "180.0E" ) );
//normal n/s
QCOMPARE( gridGeographic.gridAnnotationString( 45, QgsComposerMapGrid::Latitude, expressionContext ), QString( "45.0" ) + QChar( 176 ) + QString( "N" ) );
QCOMPARE( gridProjected.gridAnnotationString( 45, QgsComposerMapGrid::Latitude, expressionContext ), QString( "45.0N" ) );
//0 north/south
QCOMPARE( gridGeographic.gridAnnotationString( 0, QgsComposerMapGrid::Latitude, expressionContext ), QString( "0.0" ) + QChar( 176 ) );
QCOMPARE( gridProjected.gridAnnotationString( 0, QgsComposerMapGrid::Latitude, expressionContext ), QString( "0.0N" ) );
//Custom format annotations
gridProjected.setAnnotationFormat( QgsComposerMapGrid::CustomFormat );
gridProjected.setAnnotationExpression( QStringLiteral( "(@grid_number/10) || case when @grid_axis ='x' then 'a' else 'b' end" ) );
QCOMPARE( gridProjected.gridAnnotationString( 45, QgsComposerMapGrid::Latitude, expressionContext ), QString( "4.5b" ) );
QCOMPARE( gridProjected.gridAnnotationString( 33, QgsComposerMapGrid::Longitude, expressionContext ), QString( "3.3a" ) );
}
void TestQgsComposerMapGrid::descendingAnnotations()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
mComposerMap->grid()->setFrameStyle( QgsComposerMapGrid::NoFrame );
mComposerMap->grid()->setEnabled( true );
mComposerMap->grid()->setStyle( QgsComposerMapGrid::FrameAnnotationsOnly );
mComposerMap->grid()->setAnnotationEnabled( true );
mComposerMap->grid()->setAnnotationFontColor( Qt::black );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::InsideMapFrame, QgsComposerMapGrid::Bottom );
mComposerMap->grid()->setAnnotationDirection( QgsComposerMapGrid::VerticalDescending, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationDirection( QgsComposerMapGrid::VerticalDescending, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationDirection( QgsComposerMapGrid::VerticalDescending, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationDirection( QgsComposerMapGrid::VerticalDescending, QgsComposerMapGrid::Bottom );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker( QStringLiteral( "composermap_verticaldescending_inside" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
QVERIFY( testResult );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Left );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Right );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Top );
mComposerMap->grid()->setAnnotationPosition( QgsComposerMapGrid::OutsideMapFrame, QgsComposerMapGrid::Bottom );
mComposerMap->updateBoundingRect();
QgsCompositionChecker checker2( QStringLiteral( "composermap_verticaldescending_outside" ), mComposition );
checker2.setControlPathPrefix( QStringLiteral( "composer_mapgrid" ) );
bool testResult2 = checker2.testComposition( mReport, 0, 0 );
QVERIFY( testResult2 );
mComposerMap->grid()->setAnnotationEnabled( false );
}
QGSTEST_MAIN( TestQgsComposerMapGrid )
#include "testqgscomposermapgrid.moc"

View File

@ -1,240 +0,0 @@
/***************************************************************************
testqgscomposermapoverview.cpp
----------------------
begin : September 2014
copyright : (C) 2014 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h"
#include "qgscomposition.h"
#include "qgsmultirenderchecker.h"
#include "qgscomposermap.h"
#include "qgscomposermapoverview.h"
#include "qgsproject.h"
#include "qgsmultibandcolorrenderer.h"
#include "qgsrasterlayer.h"
#include "qgsrasterdataprovider.h"
#include "qgsfontutils.h"
#include <QObject>
#include "qgstest.h"
class TestQgsComposerMapOverview : public QObject
{
Q_OBJECT
public:
TestQgsComposerMapOverview() = default;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void overviewMap(); //test if overview map frame works
void overviewMapRotated(); //test if overview map frame works with rotated overview
void overviewMapRotated2(); //test if overview map frame works with rotated map
void overviewMapBlending(); //test if blend modes with overview map frame works
void overviewMapInvert(); //test if invert of overview map frame works
void overviewMapCenter(); //test if centering of overview map frame works
void overviewReprojected(); //test that overview frame is reprojected
private:
QgsComposition *mComposition = nullptr;
QgsComposerMap *mComposerMap = nullptr;
QgsRasterLayer *mRasterLayer = nullptr;
QString mReport;
};
void TestQgsComposerMapOverview::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
//create maplayers from testdata and add to layer registry
QFileInfo rasterFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/rgb256x256.png" );
mRasterLayer = new QgsRasterLayer( rasterFileInfo.filePath(),
rasterFileInfo.completeBaseName() );
QgsMultiBandColorRenderer *rasterRenderer = new QgsMultiBandColorRenderer( mRasterLayer->dataProvider(), 1, 2, 3 );
mRasterLayer->setRenderer( rasterRenderer );
//create composition with composer map
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mComposerMap = new QgsComposerMap( mComposition, 20, 20, 200, 100 );
mComposerMap->setFrameEnabled( true );
mComposerMap->setLayers( QList<QgsMapLayer *>() << mRasterLayer );
mComposition->addComposerMap( mComposerMap );
mReport = QStringLiteral( "<h1>Composer Map Overview Tests</h1>\n" );
}
void TestQgsComposerMapOverview::cleanupTestCase()
{
delete mComposition;
delete mRasterLayer;
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}
void TestQgsComposerMapOverview::init()
{
}
void TestQgsComposerMapOverview::cleanup()
{
}
void TestQgsComposerMapOverview::overviewMap()
{
QgsComposerMap *overviewMap = new QgsComposerMap( mComposition, 20, 130, 70, 70 );
overviewMap->setFrameEnabled( true );
overviewMap->setLayers( QList<QgsMapLayer *>() << mRasterLayer );
mComposition->addComposerMap( overviewMap );
mComposerMap->setNewExtent( QgsRectangle( 96, -152, 160, -120 ) ); //zoom in
overviewMap->setNewExtent( QgsRectangle( 0, -256, 256, 0 ) );
overviewMap->overview()->setFrameMap( mComposerMap->id() );
QgsCompositionChecker checker( QStringLiteral( "composermap_overview" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapoverview" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
mComposition->removeComposerItem( overviewMap );
QVERIFY( testResult );
}
void TestQgsComposerMapOverview::overviewMapRotated()
{
QgsComposerMap *overviewMap = new QgsComposerMap( mComposition, 20, 130, 70, 70 );
overviewMap->setFrameEnabled( true );
overviewMap->setLayers( QList<QgsMapLayer *>() << mRasterLayer );
mComposition->addComposerMap( overviewMap );
mComposerMap->setNewExtent( QgsRectangle( 96, -144, 160, -112 ) ); //zoom in
mComposerMap->setMapRotation( 30 );
overviewMap->setNewExtent( QgsRectangle( 0, -256, 256, 0 ) );
overviewMap->overview()->setFrameMap( mComposerMap->id() );
QgsCompositionChecker checker( QStringLiteral( "composermap_overview_rotated" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapoverview" ) );
bool testResult = checker.testComposition( mReport, 0, 600 );
mComposition->removeComposerItem( overviewMap );
mComposerMap->setMapRotation( 0 );
QVERIFY( testResult );
}
void TestQgsComposerMapOverview::overviewMapRotated2()
{
QgsComposerMap *overviewMap = new QgsComposerMap( mComposition, 20, 130, 70, 70 );
overviewMap->setFrameEnabled( true );
overviewMap->setLayers( QList<QgsMapLayer *>() << mRasterLayer );
mComposition->addComposerMap( overviewMap );
mComposerMap->setNewExtent( QgsRectangle( 96, -152, 160, -120 ) ); //zoom in
overviewMap->setMapRotation( 30 );
overviewMap->setNewExtent( QgsRectangle( 0, -256, 256, 0 ) );
overviewMap->overview()->setFrameMap( mComposerMap->id() );
QgsCompositionChecker checker( QStringLiteral( "composermap_overview_rotated2" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapoverview" ) );
bool testResult = checker.testComposition( mReport, 0, 600 );
mComposition->removeComposerItem( overviewMap );
QVERIFY( testResult );
}
void TestQgsComposerMapOverview::overviewMapBlending()
{
QgsComposerMap *overviewMapBlend = new QgsComposerMap( mComposition, 20, 130, 70, 70 );
overviewMapBlend->setFrameEnabled( true );
overviewMapBlend->setLayers( QList<QgsMapLayer *>() << mRasterLayer );
mComposition->addComposerMap( overviewMapBlend );
mComposerMap->setNewExtent( QgsRectangle( 96, -152, 160, -120 ) ); //zoom in
overviewMapBlend->setNewExtent( QgsRectangle( 0, -256, 256, 0 ) );
overviewMapBlend->overview()->setFrameMap( mComposerMap->id() );
overviewMapBlend->overview()->setBlendMode( QPainter::CompositionMode_Multiply );
QgsCompositionChecker checker( QStringLiteral( "composermap_overview_blending" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapoverview" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
mComposition->removeComposerItem( overviewMapBlend );
QVERIFY( testResult );
}
void TestQgsComposerMapOverview::overviewMapInvert()
{
QgsComposerMap *overviewMapInvert = new QgsComposerMap( mComposition, 20, 130, 70, 70 );
overviewMapInvert->setFrameEnabled( true );
overviewMapInvert->setLayers( QList<QgsMapLayer *>() << mRasterLayer );
mComposition->addComposerMap( overviewMapInvert );
mComposerMap->setNewExtent( QgsRectangle( 96, -152, 160, -120 ) ); //zoom in
overviewMapInvert->setNewExtent( QgsRectangle( 0, -256, 256, 0 ) );
overviewMapInvert->overview()->setFrameMap( mComposerMap->id() );
overviewMapInvert->overview()->setInverted( true );
QgsCompositionChecker checker( QStringLiteral( "composermap_overview_invert" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapoverview" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
mComposition->removeComposerItem( overviewMapInvert );
QVERIFY( testResult );
}
void TestQgsComposerMapOverview::overviewMapCenter()
{
QgsComposerMap *overviewMapCenter = new QgsComposerMap( mComposition, 20, 130, 70, 70 );
overviewMapCenter->setFrameEnabled( true );
overviewMapCenter->setLayers( QList<QgsMapLayer *>() << mRasterLayer );
mComposition->addComposerMap( overviewMapCenter );
mComposerMap->setNewExtent( QgsRectangle( 192, -288, 320, -224 ) );
overviewMapCenter->setNewExtent( QgsRectangle( 0, -256, 256, 0 ) );
overviewMapCenter->overview()->setFrameMap( mComposerMap->id() );
overviewMapCenter->overview()->setCentered( true );
QgsCompositionChecker checker( QStringLiteral( "composermap_overview_center" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapoverview" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
mComposition->removeComposerItem( overviewMapCenter );
QVERIFY( testResult );
}
void TestQgsComposerMapOverview::overviewReprojected()
{
QgsComposerMap *overviewMap = new QgsComposerMap( mComposition, 20, 130, 70, 70 );
overviewMap->setFrameEnabled( true );
//overviewMap->setLayers( QList<QgsMapLayer *>() << mRasterLayer );
mComposition->addComposerMap( overviewMap );
mComposerMap->setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 4326 ) );
overviewMap->setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 54030 ) );
mComposerMap->setNewExtent( QgsRectangle( 93, -64.245, 120.6, -45 ) );
overviewMap->setNewExtent( QgsRectangle( 4712502, -7620278, 10872777, -2531356 ) );
overviewMap->overview()->setFrameMap( mComposerMap->id() );
QgsCompositionChecker checker( QStringLiteral( "composermap_overview_reprojected" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_mapoverview" ) );
bool testResult = checker.testComposition( mReport, 0, 0 );
mComposition->removeComposerItem( overviewMap );
QVERIFY( testResult );
}
QGSTEST_MAIN( TestQgsComposerMapOverview )
#include "testqgscomposermapoverview.moc"

View File

@ -1,630 +0,0 @@
/***************************************************************************
testqgscomposermodel.cpp
-----------------------
begin : July 2014
copyright : (C) 2014 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgscomposition.h"
#include "qgscomposermodel.h"
#include "qgscomposerlabel.h"
#include "qgsapplication.h"
#include "qgsmapsettings.h"
#include "qgsproject.h"
#include <QObject>
#include "qgstest.h"
#include <QList>
class TestQgsComposerModel : public QObject
{
Q_OBJECT
public:
TestQgsComposerModel() = default;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void creation(); //check that model has been created
void addItems(); //add some items to the composition and test model
void zList(); //check model z order list
void clear(); //check clearing the model
void addItemDirectly(); //add an item directly to the model
void rebuildZList(); //test rebuilding the z list from the current composer stacking
void removeItem(); //test removing an item from the model
void reorderUp(); //test reordering an item up
void reorderDown(); //test reordering an item down
void reorderTop(); //test reordering an item to top
void reorderBottom(); //test reordering an item to bottom
void getComposerItemAbove(); //test getting composer item above
void getComposerItemBelow(); //test getting composer item below
void setItemRemoved(); //test setting an item as removed
void rebuildZListWithRemoved(); //test rebuilding z list with removed items
void reorderUpWithRemoved(); //test reordering up with removed items
void reorderDownWithRemoved(); //test reordering down with removed items
void reorderToTopWithRemoved(); //test reordering to top with removed items
void reorderToBottomWithRemoved(); //test reordering to bottom with removed items
void proxyCrash();
private:
QgsComposition *mComposition = nullptr;
QgsComposerLabel *mItem1 = nullptr;
QgsComposerLabel *mItem2 = nullptr;
QgsComposerLabel *mItem3 = nullptr;
};
void TestQgsComposerModel::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
}
void TestQgsComposerModel::cleanupTestCase()
{
delete mItem1;
delete mItem2;
delete mItem3;
delete mComposition;
QgsApplication::exitQgis();
}
void TestQgsComposerModel::init()
{
}
void TestQgsComposerModel::cleanup()
{
}
void TestQgsComposerModel::creation()
{
QVERIFY( mComposition->itemsModel() );
//check some basic things
QCOMPARE( mComposition->itemsModel()->columnCount(), 3 );
QCOMPARE( mComposition->itemsModel()->rowCount(), 0 );
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 0 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 0 );
}
void TestQgsComposerModel::addItems()
{
//add some items to the composition
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 0 );
mItem1 = new QgsComposerLabel( mComposition );
mComposition->addItem( mItem1 );
mItem2 = new QgsComposerLabel( mComposition );
mComposition->addItem( mItem2 );
mItem3 = new QgsComposerLabel( mComposition );
mComposition->addItem( mItem3 );
//check that these items have been added to the model
QCOMPARE( mComposition->itemsModel()->rowCount(), 3 );
//and the scene list
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 3 );
}
void TestQgsComposerModel::zList()
{
//check z list for items added by TestQgsComposerModel::addItems()
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
//also check scene list
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 3 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 2 ), mItem1 );
}
void TestQgsComposerModel::clear()
{
mComposition->itemsModel()->clear();
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 0 );
QCOMPARE( mComposition->itemsModel()->rowCount(), 0 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 0 );
}
void TestQgsComposerModel::addItemDirectly()
{
//create some items not attached to the composition
QgsComposerLabel *bottomItem = new QgsComposerLabel( nullptr );
QgsComposerLabel *topItem = new QgsComposerLabel( nullptr );
mComposition->itemsModel()->clear();
mComposition->itemsModel()->addItemAtTop( bottomItem );
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 1 );
QCOMPARE( mComposition->itemsModel()->rowCount(), 1 );
mComposition->itemsModel()->addItemAtTop( topItem );
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 2 );
QCOMPARE( mComposition->itemsModel()->rowCount(), 2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), topItem );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), bottomItem );
//also check scene list (these items are treated by the model as belonging to the scene,
//as they will have isRemoved() as false
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), topItem );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), bottomItem );
mComposition->itemsModel()->clear();
delete bottomItem;
delete topItem;
}
void TestQgsComposerModel::rebuildZList()
{
//start with an empty model
mComposition->itemsModel()->clear();
//some items are in composition, added by TestQgsComposerModel::addItems
mComposition->itemsModel()->rebuildZList();
//check that these items have been added to the model
QCOMPARE( mComposition->itemsModel()->rowCount(), 3 );
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
//also check scene list
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 3 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 2 ), mItem1 );
}
void TestQgsComposerModel::removeItem()
{
//start with an empty model
mComposition->itemsModel()->clear();
QgsComposerLabel *item1 = new QgsComposerLabel( nullptr );
QgsComposerLabel *item2 = new QgsComposerLabel( nullptr );
//add one item to the model
mComposition->itemsModel()->addItemAtTop( item1 );
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 1 );
QCOMPARE( mComposition->itemsModel()->rowCount(), 1 );
//also check scene list (this item is treated by the model as belonging to the scene,
//as it has isRemoved() as false
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 1 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), item1 );
//try removing a missing item
mComposition->itemsModel()->removeItem( nullptr );
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 1 );
QCOMPARE( mComposition->itemsModel()->rowCount(), 1 );
//try removing an item not in the model
mComposition->itemsModel()->removeItem( item2 );
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 1 );
QCOMPARE( mComposition->itemsModel()->rowCount(), 1 );
//remove the item which is in the model
mComposition->itemsModel()->removeItem( item1 );
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 0 );
QCOMPARE( mComposition->itemsModel()->rowCount(), 0 );
//also check scene list
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 0 );
delete item1;
delete item2;
}
void TestQgsComposerModel::reorderUp()
{
mComposition->itemsModel()->clear();
mComposition->itemsModel()->rebuildZList();
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
//try reordering some bad items
QVERIFY( ! mComposition->itemsModel()->reorderItemUp( nullptr ) );
QgsComposerLabel *label = new QgsComposerLabel( nullptr );
QVERIFY( ! mComposition->itemsModel()->reorderItemUp( label ) );
//trying to reorder up the topmost item should fail
QVERIFY( ! mComposition->itemsModel()->reorderItemUp( mItem3 ) );
//try reorder a good item, should succeed
QVERIFY( mComposition->itemsModel()->reorderItemUp( mItem2 ) );
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
//also check scene list
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 3 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 2 ), mItem1 );
delete label;
}
void TestQgsComposerModel::reorderDown()
{
mComposition->itemsModel()->clear();
mComposition->itemsModel()->rebuildZList();
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
//try reordering some bad items
QVERIFY( ! mComposition->itemsModel()->reorderItemDown( nullptr ) );
QgsComposerLabel *label = new QgsComposerLabel( nullptr );
QVERIFY( ! mComposition->itemsModel()->reorderItemDown( label ) );
//trying to reorder down the bottommost item should fail
QVERIFY( ! mComposition->itemsModel()->reorderItemDown( mItem1 ) );
//try reorder a good item, should succeed
QVERIFY( mComposition->itemsModel()->reorderItemDown( mItem2 ) );
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem2 );
//also check scene list
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 3 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 2 ), mItem2 );
delete label;
}
void TestQgsComposerModel::reorderTop()
{
mComposition->itemsModel()->clear();
mComposition->itemsModel()->rebuildZList();
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
//try reordering some bad items
QVERIFY( ! mComposition->itemsModel()->reorderItemToTop( nullptr ) );
QgsComposerLabel *label = new QgsComposerLabel( nullptr );
QVERIFY( ! mComposition->itemsModel()->reorderItemToTop( label ) );
//trying to reorder up the topmost item should fail
QVERIFY( ! mComposition->itemsModel()->reorderItemToTop( mItem3 ) );
//try reorder a good item, should succeed
QVERIFY( mComposition->itemsModel()->reorderItemToTop( mItem1 ) );
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem2 );
//also check scene list
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 3 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 2 ), mItem2 );
delete label;
}
void TestQgsComposerModel::reorderBottom()
{
mComposition->itemsModel()->clear();
mComposition->itemsModel()->rebuildZList();
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
//try reordering some bad items
QVERIFY( ! mComposition->itemsModel()->reorderItemToBottom( nullptr ) );
QgsComposerLabel *label = new QgsComposerLabel( nullptr );
QVERIFY( ! mComposition->itemsModel()->reorderItemToBottom( label ) );
//trying to reorder down the bottommost item should fail
QVERIFY( ! mComposition->itemsModel()->reorderItemToBottom( mItem1 ) );
//try reorder a good item, should succeed
QVERIFY( mComposition->itemsModel()->reorderItemToBottom( mItem3 ) );
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem3 );
//also check scene list
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 3 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 2 ), mItem3 );
delete label;
}
void TestQgsComposerModel::getComposerItemAbove()
{
mComposition->itemsModel()->clear();
mComposition->itemsModel()->rebuildZList();
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
//try getting item above some bad items
QVERIFY( ! mComposition->itemsModel()->getComposerItemAbove( nullptr ) );
QgsComposerLabel *label = new QgsComposerLabel( nullptr );
QVERIFY( ! mComposition->itemsModel()->getComposerItemAbove( label ) );
//trying to get item above topmost item should fail
QVERIFY( ! mComposition->itemsModel()->getComposerItemAbove( mItem3 ) );
//try using a good item
QCOMPARE( mComposition->itemsModel()->getComposerItemAbove( mItem2 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->getComposerItemAbove( mItem1 ), mItem2 );
delete label;
}
void TestQgsComposerModel::getComposerItemBelow()
{
mComposition->itemsModel()->clear();
mComposition->itemsModel()->rebuildZList();
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
//try getting item below some bad items
QVERIFY( ! mComposition->itemsModel()->getComposerItemBelow( nullptr ) );
QgsComposerLabel *label = new QgsComposerLabel( nullptr );
QVERIFY( ! mComposition->itemsModel()->getComposerItemBelow( label ) );
//trying to get item below bottom most item should fail
QVERIFY( ! mComposition->itemsModel()->getComposerItemBelow( mItem1 ) );
//try using a good item
QCOMPARE( mComposition->itemsModel()->getComposerItemBelow( mItem3 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->getComposerItemBelow( mItem2 ), mItem1 );
delete label;
}
void TestQgsComposerModel::setItemRemoved()
{
mComposition->itemsModel()->clear();
mComposition->itemsModel()->rebuildZList();
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 3 );
//try marking some bad items as removed
mComposition->itemsModel()->setItemRemoved( nullptr );
QgsComposerLabel *label = new QgsComposerLabel( nullptr );
mComposition->itemsModel()->setItemRemoved( label );
QVERIFY( !label->isRemoved() );
//try using a good item
mComposition->itemsModel()->setItemRemoved( mItem3 );
QVERIFY( mItem3->isRemoved() );
//item should still be in z-list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
//but not in scene list
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem1 );
delete label;
}
void TestQgsComposerModel::rebuildZListWithRemoved()
{
QVERIFY( mItem3->isRemoved() );
//start with an empty model
mComposition->itemsModel()->clear();
//rebuild z list
mComposition->itemsModel()->rebuildZList();
//check that only items in the scene are shown by the model
QCOMPARE( mComposition->itemsModel()->rowCount(), 2 );
//check z list contains ALL items
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
//check that scene list is missing removed item
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem1 );
}
void TestQgsComposerModel::reorderUpWithRemoved()
{
mComposition->itemsModel()->clear();
mComposition->itemsModel()->rebuildZList();
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem1 );
//try reorder a good item, should succeed
QVERIFY( mComposition->itemsModel()->reorderItemUp( mItem1 ) );
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem2 );
//also check scene list
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem2 );
}
void TestQgsComposerModel::reorderDownWithRemoved()
{
mComposition->itemsModel()->clear();
mComposition->itemsModel()->rebuildZList();
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem1 );
//try reorder a good item, should succeed
QVERIFY( mComposition->itemsModel()->reorderItemDown( mItem2 ) );
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem2 );
//also check scene list
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem2 );
}
void TestQgsComposerModel::reorderToTopWithRemoved()
{
mComposition->itemsModel()->clear();
mComposition->itemsModel()->rebuildZList();
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem1 );
//try reorder a good item, should succeed
QVERIFY( mComposition->itemsModel()->reorderItemToTop( mItem1 ) );
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem2 );
//also check scene list
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem2 );
}
void TestQgsComposerModel::reorderToBottomWithRemoved()
{
mComposition->itemsModel()->clear();
mComposition->itemsModel()->rebuildZList();
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem1 );
//try reorder a good item, should succeed
QVERIFY( mComposition->itemsModel()->reorderItemToBottom( mItem2 ) );
//check z list
QCOMPARE( mComposition->itemsModel()->zOrderListSize(), 3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 0 ), mItem3 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 1 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->zOrderList()->at( 2 ), mItem2 );
//also check scene list
QCOMPARE( mComposition->itemsModel()->mItemsInScene.size(), 2 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 0 ), mItem1 );
QCOMPARE( mComposition->itemsModel()->mItemsInScene.at( 1 ), mItem2 );
}
void TestQgsComposerModel::proxyCrash()
{
// test for a possible crash when using QgsComposerProxyModel and reordering items
QgsComposition *composition = new QgsComposition( QgsProject::instance() );
// create a proxy - it's not used, but will be watching...
QgsComposerProxyModel *proxy = new QgsComposerProxyModel( composition );
Q_UNUSED( proxy );
// add some items to composition
QgsComposerLabel *item1 = new QgsComposerLabel( composition );
composition->addItem( item1 );
QgsComposerLabel *item2 = new QgsComposerLabel( composition );
composition->addItem( item2 );
QgsComposerLabel *item3 = new QgsComposerLabel( composition );
composition->addItem( item3 );
// reorder items - expect no crash!
composition->itemsModel()->reorderItemUp( item1 );
}
QGSTEST_MAIN( TestQgsComposerModel )
#include "testqgscomposermodel.moc"

View File

@ -1,258 +0,0 @@
/***************************************************************************
testqgscomposerobject.cpp
-----------------------
begin : July 2014
copyright : (C) 2014 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgscomposerobject.h"
#include "qgscomposition.h"
#include "qgsmultirenderchecker.h"
#include "qgsproperty.h"
#include "qgsexpression.h"
#include "qgsapplication.h"
#include "qgsproject.h"
#include <QObject>
#include "qgstest.h"
class TestQgsComposerObject : public QObject
{
Q_OBJECT
public:
TestQgsComposerObject() = default;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void creation(); //test creation of QgsComposerObject
void composition(); //test fetching composition from QgsComposerObject
void writeReadXml(); //test writing object to xml and reading back from it
void writeRetrieveDDProperty(); //test writing and retrieving dd properties from xml
void customProperties(); //test setting/getting custom properties
void writeRetrieveCustomProperties(); //test writing/retreiving custom properties from xml
private:
bool renderCheck( const QString &testName, QImage &image, int mismatchCount = 0 );
QgsComposition *mComposition = nullptr;
QString mReport;
};
void TestQgsComposerObject::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mReport = QStringLiteral( "<h1>Composer Object Tests</h1>\n" );
}
void TestQgsComposerObject::cleanupTestCase()
{
delete mComposition;
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}
void TestQgsComposerObject::init()
{
}
void TestQgsComposerObject::cleanup()
{
}
void TestQgsComposerObject::creation()
{
QgsComposerObject *object = new QgsComposerObject( mComposition );
QVERIFY( object );
delete object;
}
void TestQgsComposerObject::composition()
{
QgsComposerObject *object = new QgsComposerObject( mComposition );
QCOMPARE( object->composition(), mComposition );
delete object;
}
void TestQgsComposerObject::writeReadXml()
{
QgsComposerObject *object = new QgsComposerObject( mComposition );
QDomImplementation DomImplementation;
QDomDocumentType documentType =
DomImplementation.createDocumentType(
QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
QDomDocument doc( documentType );
//test writing with no node
QDomElement rootNode = doc.createElement( QStringLiteral( "qgis" ) );
QDomElement noNode;
QCOMPARE( object->writeXml( noNode, doc ), false );
//test writing with node
QDomElement composerObjectElem = doc.createElement( QStringLiteral( "ComposerObject" ) );
rootNode.appendChild( composerObjectElem );
QVERIFY( object->writeXml( composerObjectElem, doc ) );
//check if object node was written
QDomNodeList evalNodeList = rootNode.elementsByTagName( QStringLiteral( "ComposerObject" ) );
QCOMPARE( evalNodeList.count(), 1 );
//test reading node
QgsComposerObject *readObject = new QgsComposerObject( mComposition );
//test reading with no node
QCOMPARE( readObject->readXml( noNode, doc ), false );
//test reading node
QVERIFY( readObject->readXml( composerObjectElem, doc ) );
delete object;
delete readObject;
}
void TestQgsComposerObject::writeRetrieveDDProperty()
{
QgsComposerObject *object = new QgsComposerObject( mComposition );
object->dataDefinedProperties().setProperty( QgsComposerObject::TestProperty, QgsProperty::fromExpression( QStringLiteral( "10 + 40" ) ) );
object->prepareProperties();
//test writing object with dd settings
QDomImplementation DomImplementation;
QDomDocumentType documentType =
DomImplementation.createDocumentType(
QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
QDomDocument doc( documentType );
QDomElement rootNode = doc.createElement( QStringLiteral( "qgis" ) );
QDomElement composerObjectElem = doc.createElement( QStringLiteral( "ComposerObject" ) );
rootNode.appendChild( composerObjectElem );
QVERIFY( object->writeXml( composerObjectElem, doc ) );
//check if object node was written
QDomNodeList evalNodeList = rootNode.elementsByTagName( QStringLiteral( "ComposerObject" ) );
QCOMPARE( evalNodeList.count(), 1 );
//test reading node containing dd settings
QgsComposerObject *readObject = new QgsComposerObject( mComposition );
QVERIFY( readObject->readXml( composerObjectElem, doc ) );
//test getting not set dd from restored object
QgsProperty dd = readObject->dataDefinedProperties().property( QgsComposerObject::BlendMode );
QVERIFY( !dd );
//test getting good property
dd = readObject->dataDefinedProperties().property( QgsComposerObject::TestProperty );
QVERIFY( dd );
QVERIFY( dd.isActive() );
QCOMPARE( dd.propertyType(), QgsProperty::ExpressionBasedProperty );
delete object;
delete readObject;
}
void TestQgsComposerObject::customProperties()
{
QgsComposerObject *object = new QgsComposerObject( mComposition );
QCOMPARE( object->customProperty( "noprop", "defaultval" ).toString(), QString( "defaultval" ) );
QVERIFY( object->customProperties().isEmpty() );
object->setCustomProperty( QStringLiteral( "testprop" ), "testval" );
QCOMPARE( object->customProperty( "testprop", "defaultval" ).toString(), QString( "testval" ) );
QCOMPARE( object->customProperties().length(), 1 );
QCOMPARE( object->customProperties().at( 0 ), QString( "testprop" ) );
//test no crash
object->removeCustomProperty( QStringLiteral( "badprop" ) );
object->removeCustomProperty( QStringLiteral( "testprop" ) );
QVERIFY( object->customProperties().isEmpty() );
QCOMPARE( object->customProperty( "noprop", "defaultval" ).toString(), QString( "defaultval" ) );
object->setCustomProperty( QStringLiteral( "testprop1" ), "testval1" );
object->setCustomProperty( QStringLiteral( "testprop2" ), "testval2" );
QStringList keys = object->customProperties();
QCOMPARE( keys.length(), 2 );
QVERIFY( keys.contains( "testprop1" ) );
QVERIFY( keys.contains( "testprop2" ) );
delete object;
}
void TestQgsComposerObject::writeRetrieveCustomProperties()
{
QgsComposerObject *object = new QgsComposerObject( mComposition );
object->setCustomProperty( QStringLiteral( "testprop" ), "testval" );
object->setCustomProperty( QStringLiteral( "testprop2" ), 5 );
//test writing object with custom properties
QDomImplementation DomImplementation;
QDomDocumentType documentType =
DomImplementation.createDocumentType(
QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
QDomDocument doc( documentType );
QDomElement rootNode = doc.createElement( QStringLiteral( "qgis" ) );
QDomElement composerObjectElem = doc.createElement( QStringLiteral( "ComposerObject" ) );
rootNode.appendChild( composerObjectElem );
QVERIFY( object->writeXml( composerObjectElem, doc ) );
//check if object node was written
QDomNodeList evalNodeList = rootNode.elementsByTagName( QStringLiteral( "ComposerObject" ) );
QCOMPARE( evalNodeList.count(), 1 );
//test reading node containing custom properties
QgsComposerObject *readObject = new QgsComposerObject( mComposition );
QVERIFY( readObject->readXml( composerObjectElem, doc ) );
//test retrieved custom properties
QCOMPARE( readObject->customProperties().length(), 2 );
QVERIFY( readObject->customProperties().contains( QString( "testprop" ) ) );
QVERIFY( readObject->customProperties().contains( QString( "testprop2" ) ) );
QCOMPARE( readObject->customProperty( "testprop" ).toString(), QString( "testval" ) );
QCOMPARE( readObject->customProperty( "testprop2" ).toInt(), 5 );
delete object;
delete readObject;
}
bool TestQgsComposerObject::renderCheck( const QString &testName, QImage &image, int mismatchCount )
{
mReport += "<h2>" + testName + "</h2>\n";
QString myTmpDir = QDir::tempPath() + '/';
QString myFileName = myTmpDir + testName + ".png";
image.save( myFileName, "PNG" );
QgsRenderChecker myChecker;
myChecker.setControlName( "expected_" + testName );
myChecker.setRenderedImage( myFileName );
bool myResultFlag = myChecker.compareImages( testName, mismatchCount );
mReport += myChecker.report();
return myResultFlag;
}
QGSTEST_MAIN( TestQgsComposerObject )
#include "testqgscomposerobject.moc"

View File

@ -1,165 +0,0 @@
/***************************************************************************
testqgscomposerpaper.cpp
----------------------
begin : January 2014
copyright : (C) 2014 by Marco Hugentobler, Nyall Dawson
email : nyall dot dawson at gmail.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h"
#include "qgscomposition.h"
#include "qgsmultirenderchecker.h"
#include "qgscomposershape.h"
#include "qgsproject.h"
#include "qgssymbol.h"
#include "qgssinglesymbolrenderer.h"
#include "qgsfillsymbollayer.h"
#include "qgslinesymbollayer.h"
#include <QObject>
#include "qgstest.h"
#include <QColor>
#include <QPainter>
class TestQgsComposerPaper : public QObject
{
Q_OBJECT
public:
TestQgsComposerPaper() = default;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void defaultPaper(); //test default paper style
void transparentPaper(); //test totally transparent paper style
void borderedPaper(); //test page with border
void markerLinePaper(); //test page with marker line border
void hiddenPages(); //test hidden page boundaries
private:
QgsComposition *mComposition = nullptr;
QString mReport;
// QgsSingleSymbolRenderer* mSymbolRenderer;
};
void TestQgsComposerPaper::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
//create empty composition
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mReport = QStringLiteral( "<h1>Composer Paper Tests</h1>\n" );
}
void TestQgsComposerPaper::cleanupTestCase()
{
delete mComposition;
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}
void TestQgsComposerPaper::init()
{
}
void TestQgsComposerPaper::cleanup()
{
}
void TestQgsComposerPaper::defaultPaper()
{
QgsCompositionChecker checker( QStringLiteral( "composerpaper_default" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_paper" ) );
QVERIFY( checker.testComposition( mReport ) );
}
void TestQgsComposerPaper::transparentPaper()
{
QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( Qt::transparent );
simpleFill->setStrokeColor( Qt::transparent );
mComposition->setPageStyleSymbol( fillSymbol );
delete fillSymbol;
QgsCompositionChecker checker( QStringLiteral( "composerpaper_transparent" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_paper" ) );
QVERIFY( checker.testComposition( mReport ) );
}
void TestQgsComposerPaper::borderedPaper()
{
QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( Qt::white );
simpleFill->setStrokeColor( Qt::black );
simpleFill->setStrokeWidth( 6 );
mComposition->setPageStyleSymbol( fillSymbol );
delete fillSymbol;
QgsCompositionChecker checker( QStringLiteral( "composerpaper_bordered" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_paper" ) );
QVERIFY( checker.testComposition( mReport ) );
}
void TestQgsComposerPaper::markerLinePaper()
{
QgsMarkerLineSymbolLayer *markerLine = new QgsMarkerLineSymbolLayer();
QgsFillSymbol *markerLineSymbol = new QgsFillSymbol();
markerLineSymbol->changeSymbolLayer( 0, markerLine );
mComposition->setPageStyleSymbol( markerLineSymbol );
delete markerLineSymbol;
QgsCompositionChecker checker( QStringLiteral( "composerpaper_markerborder" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_paper" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
}
void TestQgsComposerPaper::hiddenPages()
{
QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( Qt::blue );
simpleFill->setStrokeColor( Qt::transparent );
mComposition->setPageStyleSymbol( fillSymbol );
delete fillSymbol;
mComposition->setPagesVisible( false );
QgsCompositionChecker checker( QStringLiteral( "composerpaper_hidden" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_paper" ) );
bool result = checker.testComposition( mReport );
mComposition->setPagesVisible( true );
QVERIFY( result );
}
QGSTEST_MAIN( TestQgsComposerPaper )
#include "testqgscomposerpaper.moc"

View File

@ -1,418 +0,0 @@
/***************************************************************************
testqgscomposerpicture.cpp
----------------------
begin : April 2014
copyright : (C) 2014 by Nyall Dawson
email : nyall dot dawson at gmail.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h"
#include "qgscomposition.h"
#include "qgsmultirenderchecker.h"
#include "qgscomposerpicture.h"
#include "qgsproject.h"
#include "qgsproperty.h"
#include <QObject>
#include "qgstest.h"
#include <QColor>
#include <QPainter>
class TestQgsComposerPicture : public QObject
{
Q_OBJECT
public:
TestQgsComposerPicture();
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void pictureRotation(); //test if picture pictureRotation is functioning
void pictureItemRotation(); //test if composer picture item rotation is functioning
void pictureResizeZoom();
void pictureResizeStretch();
void pictureResizeClip();
void pictureResizeZoomAndResize();
void pictureResizeFrameToImage();
void pictureClipAnchor();
void pictureClipAnchorOversize();
void pictureZoomAnchor();
void pictureSvgZoom();
void pictureSvgStretch();
void pictureSvgZoomAndResize();
void pictureSvgFrameToImage();
void svgParameters();
void issue_14644();
void pictureExpression();
void pictureInvalidExpression();
private:
QgsComposition *mComposition = nullptr;
QgsComposerPicture *mComposerPicture = nullptr;
QString mReport;
QString mPngImage;
QString mSvgImage;
QString mSvgParamsImage;
};
TestQgsComposerPicture::TestQgsComposerPicture() = default;
void TestQgsComposerPicture::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
mPngImage = QStringLiteral( TEST_DATA_DIR ) + "/sample_image.png";
mSvgImage = QStringLiteral( TEST_DATA_DIR ) + "/sample_svg.svg";
mSvgParamsImage = QStringLiteral( TEST_DATA_DIR ) + "/svg_params.svg";
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mComposerPicture = new QgsComposerPicture( mComposition );
mComposerPicture->setPicturePath( mPngImage );
mComposerPicture->setSceneRect( QRectF( 70, 70, 100, 100 ) );
mComposerPicture->setFrameEnabled( true );
mReport = QStringLiteral( "<h1>Composer Picture Tests</h1>\n" );
}
void TestQgsComposerPicture::cleanupTestCase()
{
delete mComposerPicture;
delete mComposition;
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}
void TestQgsComposerPicture::init()
{
}
void TestQgsComposerPicture::cleanup()
{
}
void TestQgsComposerPicture::pictureRotation()
{
//test picture rotation
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setPictureRotation( 45 );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_rotation" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setPictureRotation( 0 );
}
void TestQgsComposerPicture::pictureItemRotation()
{
//test picture item rotation
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setItemRotation( 45, true );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_itemrotation" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setItemRotation( 0, true );
}
void TestQgsComposerPicture::pictureResizeZoom()
{
//test picture resize Zoom mode
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Zoom );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_resize_zoom" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
}
void TestQgsComposerPicture::pictureResizeStretch()
{
//test picture resize Stretch mode
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Stretch );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_resize_stretch" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Zoom );
}
void TestQgsComposerPicture::pictureResizeClip()
{
//test picture resize Clip mode
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Clip );
mComposerPicture->setSceneRect( QRectF( 70, 70, 30, 50 ) );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_resize_clip" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Zoom );
mComposerPicture->setSceneRect( QRectF( 70, 70, 100, 100 ) );
}
void TestQgsComposerPicture::pictureResizeZoomAndResize()
{
//test picture resize ZoomResizeFrame mode
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::ZoomResizeFrame );
mComposerPicture->setSceneRect( QRectF( 70, 70, 50, 300 ) );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_resize_zoomresize" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Zoom );
mComposerPicture->setSceneRect( QRectF( 70, 70, 100, 100 ) );
}
void TestQgsComposerPicture::pictureResizeFrameToImage()
{
//test picture resize FrameToImageSize mode
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::FrameToImageSize );
mComposerPicture->setSceneRect( QRectF( 70, 70, 50, 300 ) );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_resize_frametoimage" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Zoom );
mComposerPicture->setSceneRect( QRectF( 70, 70, 100, 100 ) );
}
void TestQgsComposerPicture::pictureClipAnchor()
{
//test picture anchor in Clip mode
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Clip );
mComposerPicture->setSceneRect( QRectF( 70, 70, 30, 50 ) );
mComposerPicture->setPictureAnchor( QgsComposerItem::LowerRight );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_clip_anchor" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Zoom );
mComposerPicture->setPictureAnchor( QgsComposerItem::UpperLeft );
mComposerPicture->setSceneRect( QRectF( 70, 70, 100, 100 ) );
}
void TestQgsComposerPicture::pictureClipAnchorOversize()
{
//test picture anchor in Clip mode
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Clip );
mComposerPicture->setSceneRect( QRectF( 70, 70, 150, 120 ) );
mComposerPicture->setPictureAnchor( QgsComposerItem::LowerMiddle );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_clip_anchoroversize" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Zoom );
mComposerPicture->setPictureAnchor( QgsComposerItem::UpperLeft );
mComposerPicture->setSceneRect( QRectF( 70, 70, 100, 100 ) );
}
void TestQgsComposerPicture::pictureZoomAnchor()
{
//test picture anchor in Zoom mode
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Zoom );
mComposerPicture->setSceneRect( QRectF( 70, 10, 30, 100 ) );
mComposerPicture->setPictureAnchor( QgsComposerItem::LowerMiddle );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_zoom_anchor" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setPictureAnchor( QgsComposerItem::UpperLeft );
mComposerPicture->setSceneRect( QRectF( 70, 70, 100, 100 ) );
}
void TestQgsComposerPicture::pictureSvgZoom()
{
//test picture resize Zoom mode
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Zoom );
mComposerPicture->setPicturePath( mSvgImage );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_svg_zoom" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setPicturePath( mPngImage );
}
void TestQgsComposerPicture::pictureSvgStretch()
{
//test picture resize Stretch mode
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Stretch );
mComposerPicture->setPicturePath( mSvgImage );
mComposerPicture->setSceneRect( QRectF( 70, 70, 20, 100 ) );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_svg_stretch" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Zoom );
mComposerPicture->setPicturePath( mPngImage );
mComposerPicture->setSceneRect( QRectF( 70, 70, 100, 100 ) );
}
void TestQgsComposerPicture::pictureSvgZoomAndResize()
{
//test picture resize ZoomResizeFrame mode
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::ZoomResizeFrame );
mComposerPicture->setPicturePath( mSvgImage );
mComposerPicture->setSceneRect( QRectF( 70, 70, 50, 300 ) );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_svg_zoomresize" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Zoom );
mComposerPicture->setSceneRect( QRectF( 70, 70, 100, 100 ) );
mComposerPicture->setPicturePath( mPngImage );
}
void TestQgsComposerPicture::pictureSvgFrameToImage()
{
//test picture resize FrameToImageSize mode
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::FrameToImageSize );
mComposerPicture->setPicturePath( mSvgImage );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_svg_frametoimage" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Zoom );
mComposerPicture->setSceneRect( QRectF( 70, 70, 100, 100 ) );
mComposerPicture->setPicturePath( mPngImage );
}
void TestQgsComposerPicture::svgParameters()
{
//test rendering an SVG file with parameters
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Zoom );
mComposerPicture->setPicturePath( mSvgParamsImage );
mComposerPicture->setSvgFillColor( QColor( 30, 90, 200, 100 ) );
mComposerPicture->setSvgStrokeColor( QColor( 255, 45, 20, 200 ) );
mComposerPicture->setSvgStrokeWidth( 2.2 );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_svg_params" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setSceneRect( QRectF( 70, 70, 100, 100 ) );
mComposerPicture->setPicturePath( mPngImage );
}
void TestQgsComposerPicture::issue_14644()
{
//test rendering SVG file with text
mComposition->addComposerPicture( mComposerPicture );
mComposerPicture->setResizeMode( QgsComposerPicture::Zoom );
mComposerPicture->setPicturePath( QStringLiteral( TEST_DATA_DIR ) + "/svg/issue_14644.svg" );
QgsCompositionChecker checker( QStringLiteral( "composerpicture_issue_14644" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->setSceneRect( QRectF( 70, 70, 100, 100 ) );
mComposerPicture->setPicturePath( mPngImage );
}
void TestQgsComposerPicture::pictureExpression()
{
//test picture source via expression
mComposition->addComposerPicture( mComposerPicture );
QString expr = QStringLiteral( "'%1' || '/sample_svg.svg'" ).arg( TEST_DATA_DIR );
mComposerPicture->dataDefinedProperties().setProperty( QgsComposerObject::PictureSource, QgsProperty::fromExpression( expr ) );
mComposerPicture->refreshPicture();
QgsCompositionChecker checker( QStringLiteral( "composerpicture_expression" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->dataDefinedProperties().setProperty( QgsComposerObject::PictureSource, QgsProperty() );
}
void TestQgsComposerPicture::pictureInvalidExpression()
{
//test picture source via bad expression
mComposition->addComposerPicture( mComposerPicture );
QString expr = QStringLiteral( "bad expression" );
mComposerPicture->dataDefinedProperties().setProperty( QgsComposerObject::PictureSource, QgsProperty::fromExpression( expr ) );
mComposerPicture->refreshPicture();
QgsCompositionChecker checker( QStringLiteral( "composerpicture_badexpression" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_picture" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
mComposition->removeItem( mComposerPicture );
mComposerPicture->dataDefinedProperties().setProperty( QgsComposerObject::PictureSource, QgsProperty() );
}
QGSTEST_MAIN( TestQgsComposerPicture )
#include "testqgscomposerpicture.moc"

View File

@ -1,189 +0,0 @@
/***************************************************************************
testqgscomposerrotation.cpp
----------------------
begin : April 2013
copyright : (C) 2013 by Marco Hugentobler, Nyall Dawson
email : nyall dot dawson at gmail.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h"
#include "qgscomposition.h"
#include "qgsmultirenderchecker.h"
#include "qgscomposershape.h"
#include "qgscomposermap.h"
#include "qgscomposerlabel.h"
#include "qgsmultibandcolorrenderer.h"
#include "qgsrasterlayer.h"
#include "qgsproject.h"
#include "qgsfontutils.h"
#include "qgsrasterdataprovider.h"
#include <QObject>
#include "qgstest.h"
#include <QColor>
#include <QPainter>
class TestQgsComposerRotation : public QObject
{
Q_OBJECT
public:
TestQgsComposerRotation() = default;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void shapeRotation(); //test if composer shape rotation is functioning
void labelRotation(); //test if composer label rotation is functioning
void mapRotation(); //test if composer map mapRotation is functioning
void mapItemRotation(); //test if composer map item rotation is functioning
private:
QgsComposition *mComposition = nullptr;
QgsComposerShape *mComposerRect = nullptr;
QgsComposerLabel *mComposerLabel = nullptr;
QgsComposerMap *mComposerMap = nullptr;
QgsRasterLayer *mRasterLayer = nullptr;
QString mReport;
};
void TestQgsComposerRotation::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
//create maplayers from testdata and add to layer registry
QFileInfo rasterFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/rgb256x256.png" );
mRasterLayer = new QgsRasterLayer( rasterFileInfo.filePath(),
rasterFileInfo.completeBaseName() );
QgsMultiBandColorRenderer *rasterRenderer = new QgsMultiBandColorRenderer( mRasterLayer->dataProvider(), 1, 2, 3 );
mRasterLayer->setRenderer( rasterRenderer );
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mComposerRect = new QgsComposerShape( 70, 70, 150, 100, mComposition );
mComposerRect->setShapeType( QgsComposerShape::Rectangle );
mComposerRect->setBackgroundColor( QColor::fromRgb( 255, 150, 0 ) );
mComposerLabel = new QgsComposerLabel( mComposition );
mComposerLabel->setText( QStringLiteral( "test label" ) );
mComposerLabel->setFont( QgsFontUtils::getStandardTestFont() );
mComposerLabel->setPos( 70, 70 );
mComposerLabel->adjustSizeToText();
mComposerLabel->setBackgroundColor( QColor::fromRgb( 255, 150, 0 ) );
mComposerLabel->setBackgroundEnabled( true );
mReport = QStringLiteral( "<h1>Composer Rotation Tests</h1>\n" );
}
void TestQgsComposerRotation::cleanupTestCase()
{
if ( mComposerMap )
{
mComposition->removeItem( mComposerMap );
delete mComposerMap;
}
delete mComposerLabel;
delete mComposerRect;
delete mComposition;
delete mRasterLayer;
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}
void TestQgsComposerRotation::init()
{
}
void TestQgsComposerRotation::cleanup()
{
}
void TestQgsComposerRotation::shapeRotation()
{
mComposition->addComposerShape( mComposerRect );
mComposerRect->setItemRotation( 45, true );
QgsCompositionChecker checker( QStringLiteral( "composerrotation_shape" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_items" ) );
QVERIFY( checker.testComposition( mReport ) );
mComposition->removeItem( mComposerRect );
mComposerRect->setItemRotation( 0, true );
}
void TestQgsComposerRotation::labelRotation()
{
mComposition->addComposerLabel( mComposerLabel );
mComposerLabel->setItemRotation( 135, true );
QgsCompositionChecker checker( QStringLiteral( "composerrotation_label" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_items" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
}
void TestQgsComposerRotation::mapRotation()
{
// cleanup after labelRotation()
mComposition->removeItem( mComposerLabel );
mComposerLabel->setItemRotation( 0, true );
//test map rotation
mComposerMap = new QgsComposerMap( mComposition, 20, 20, 100, 50 );
mComposerMap->setFrameEnabled( true );
mComposition->addItem( mComposerMap );
mComposerMap->setNewExtent( QgsRectangle( 0, -192, 256, -64 ) );
mComposerMap->setMapRotation( 90 );
mComposerMap->setLayers( QList<QgsMapLayer *>() << mRasterLayer );
QgsCompositionChecker checker( QStringLiteral( "composerrotation_maprotation" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_items" ) );
QVERIFY( checker.testComposition( mReport, 0, 200 ) );
}
void TestQgsComposerRotation::mapItemRotation()
{
// cleanup after mapRotation()
mComposition->removeItem( mComposerMap );
delete mComposerMap;
//test map item rotation
mComposerMap = new QgsComposerMap( mComposition, 20, 50, 100, 50 );
mComposerMap->setFrameEnabled( true );
mComposition->addItem( mComposerMap );
mComposerMap->setNewExtent( QgsRectangle( 0, -192, 256, -64 ) );
mComposerMap->setItemRotation( 90, true );
mComposerMap->setLayers( QList<QgsMapLayer *>() << mRasterLayer );
QgsCompositionChecker checker( QStringLiteral( "composerrotation_mapitemrotation" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_items" ) );
QVERIFY( checker.testComposition( mReport ) );
}
QGSTEST_MAIN( TestQgsComposerRotation )
#include "testqgscomposerrotation.moc"

View File

@ -1,217 +0,0 @@
/***************************************************************************
testqgscomposerscalebar.cpp
---------------------------
begin : August 2012
copyright : (C) 2012 by Marco Hugentobler
email : marco at sourcepole dot ch
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h"
#include "qgscomposition.h"
#include "qgsmultirenderchecker.h"
#include "qgscomposermap.h"
#include "qgscomposerscalebar.h"
#include "qgsmultibandcolorrenderer.h"
#include "qgsrasterlayer.h"
#include "qgsrasterdataprovider.h"
#include "qgsfontutils.h"
#include "qgsproperty.h"
#include "qgsproject.h"
#include <QLocale>
#include <QObject>
#include "qgstest.h"
class TestQgsComposerScaleBar : public QObject
{
Q_OBJECT
public:
TestQgsComposerScaleBar() = default;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void singleBox();
void singleBoxAlpha();
void doubleBox();
void numeric();
void tick();
void dataDefined();
private:
QgsComposition *mComposition = nullptr;
QgsComposerMap *mComposerMap = nullptr;
QgsComposerScaleBar *mComposerScaleBar = nullptr;
QgsRasterLayer *mRasterLayer = nullptr;
QString mReport;
};
void TestQgsComposerScaleBar::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
// the scale denominator is formatted in a locale aware manner
// so 10000 is rendered as "10,000" in C (or en_US) locale, however
// other locales may render the number differently (e.g. "10 000" in cs_CZ)
// so we enforce C locale to make sure we get expected result
QLocale::setDefault( QLocale::c() );
//reproject to WGS84
QgsCoordinateReferenceSystem destCRS;
destCRS.createFromId( 4326, QgsCoordinateReferenceSystem::EpsgCrsId );
QgsProject::instance()->setCrs( destCRS );
QgsProject::instance()->setEllipsoid( QStringLiteral( "WGS84" ) );
//create maplayers from testdata and add to layer registry
QFileInfo rasterFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/landsat.tif" );
mRasterLayer = new QgsRasterLayer( rasterFileInfo.filePath(),
rasterFileInfo.completeBaseName() );
QgsMultiBandColorRenderer *rasterRenderer = new QgsMultiBandColorRenderer( mRasterLayer->dataProvider(), 2, 3, 4 );
mRasterLayer->setRenderer( rasterRenderer );
//create composition with composer map
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mComposerMap = new QgsComposerMap( mComposition, 20, 20, 150, 150 );
mComposerMap->setFrameEnabled( true );
mComposition->addComposerMap( mComposerMap );
mComposerMap->setNewExtent( QgsRectangle( 17.923, 30.160, 18.023, 30.260 ) );
mComposerMap->setLayers( QList<QgsMapLayer *>() << mRasterLayer );
mComposerScaleBar = new QgsComposerScaleBar( mComposition );
mComposerScaleBar->setSceneRect( QRectF( 20, 180, 50, 20 ) );
mComposition->addComposerScaleBar( mComposerScaleBar );
mComposerScaleBar->setComposerMap( mComposerMap );
mComposerScaleBar->setFont( QgsFontUtils::getStandardTestFont() );
mComposerScaleBar->setUnits( QgsUnitTypes::DistanceMeters );
mComposerScaleBar->setNumUnitsPerSegment( 2000 );
mComposerScaleBar->setNumSegmentsLeft( 0 );
mComposerScaleBar->setNumSegments( 2 );
mComposerScaleBar->setHeight( 5 );
mComposerScaleBar->setLineWidth( 1.0 );
qWarning() << "scalebar font: " << mComposerScaleBar->font().toString() << " exactMatch:" << mComposerScaleBar->font().exactMatch();
mReport = QStringLiteral( "<h1>Composer Scalebar Tests</h1>\n" );
}
void TestQgsComposerScaleBar::cleanupTestCase()
{
delete mComposition;
delete mRasterLayer;
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}
void TestQgsComposerScaleBar::init()
{
}
void TestQgsComposerScaleBar::cleanup()
{
}
void TestQgsComposerScaleBar::singleBox()
{
mComposerScaleBar->setStyle( QStringLiteral( "Single Box" ) );
QgsCompositionChecker checker( QStringLiteral( "composerscalebar_singlebox" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_scalebar" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
}
void TestQgsComposerScaleBar::singleBoxAlpha()
{
mComposerScaleBar->setStyle( QStringLiteral( "Single Box" ) );
mComposerScaleBar->setFillColor( QColor( 255, 0, 0, 100 ) );
mComposerScaleBar->setFillColor2( QColor( 0, 255, 0, 50 ) );
mComposerScaleBar->setLineColor( QColor( 0, 0, 255, 150 ) );
mComposerScaleBar->setFontColor( QColor( 255, 0, 255, 100 ) );
mComposerScaleBar->setLineWidth( 1.0 );
QgsCompositionChecker checker( QStringLiteral( "composerscalebar_singlebox_alpha" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_scalebar" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
}
void TestQgsComposerScaleBar::doubleBox()
{
// cleanup singleBoxAlpha
mComposerScaleBar->setFillColor( Qt::black );
mComposerScaleBar->setFillColor2( Qt::white );
mComposerScaleBar->setLineColor( Qt::black );
mComposerScaleBar->setLineWidth( 1.0 );
mComposerScaleBar->setFontColor( Qt::black );
mComposerScaleBar->setStyle( QStringLiteral( "Double Box" ) );
QgsCompositionChecker checker( QStringLiteral( "composerscalebar_doublebox" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_scalebar" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
}
void TestQgsComposerScaleBar::numeric()
{
QFont f = mComposerScaleBar->font();
QFont newFont = QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ) );
newFont.setPointSizeF( 12 );
mComposerScaleBar->setFont( newFont );
mComposerScaleBar->setStyle( QStringLiteral( "Numeric" ) );
mComposerScaleBar->setSceneRect( QRectF( 20, 180, 50, 20 ) );
QgsCompositionChecker checker( QStringLiteral( "composerscalebar_numeric" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_scalebar" ) );
bool result = checker.testComposition( mReport, 0, 0 );
mComposerScaleBar->setFont( f );
QVERIFY( result );
}
void TestQgsComposerScaleBar::tick()
{
mComposerScaleBar->setStyle( QStringLiteral( "Line Ticks Up" ) );
mComposerScaleBar->setLineWidth( 1.0 );
QgsCompositionChecker checker( QStringLiteral( "composerscalebar_tick" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_scalebar" ) );
QVERIFY( checker.testComposition( mReport, 0, 0 ) );
}
void TestQgsComposerScaleBar::dataDefined()
{
mComposerScaleBar->dataDefinedProperties().setProperty( QgsComposerObject::ScalebarFillColor, QgsProperty::fromExpression( QStringLiteral( "'red'" ) ) );
mComposerScaleBar->dataDefinedProperties().setProperty( QgsComposerObject::ScalebarFillColor2, QgsProperty::fromExpression( QStringLiteral( "'blue'" ) ) );
mComposerScaleBar->dataDefinedProperties().setProperty( QgsComposerObject::ScalebarLineColor, QgsProperty::fromExpression( QStringLiteral( "'yellow'" ) ) );
mComposerScaleBar->dataDefinedProperties().setProperty( QgsComposerObject::ScalebarLineWidth, QgsProperty::fromExpression( QStringLiteral( "1.2" ) ) );
mComposerScaleBar->refreshDataDefinedProperty();
QCOMPARE( mComposerScaleBar->brush().color().name(), QColor( 255, 0, 0 ).name() );
QCOMPARE( mComposerScaleBar->brush2().color().name(), QColor( 0, 0, 255 ).name() );
QCOMPARE( mComposerScaleBar->pen().color().name(), QColor( 255, 255, 0 ).name() );
QCOMPARE( mComposerScaleBar->pen().widthF(), 1.2 );
mComposerScaleBar->setDataDefinedProperties( QgsPropertyCollection() );
mComposerScaleBar->setLineWidth( 1.0 );
}
QGSTEST_MAIN( TestQgsComposerScaleBar )
#include "testqgscomposerscalebar.moc"

View File

@ -1,156 +0,0 @@
/***************************************************************************
testqgscomposershapes.cpp
----------------------
begin : April 2013
copyright : (C) 2013 by Marco Hugentobler, Nyall Dawson
email : nyall dot dawson at gmail.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h"
#include "qgscomposition.h"
#include "qgsmultirenderchecker.h"
#include "qgscomposershape.h"
#include "qgsmapsettings.h"
#include "qgsproject.h"
#include "qgssymbol.h"
#include "qgssinglesymbolrenderer.h"
#include "qgsfillsymbollayer.h"
#include <QObject>
#include "qgstest.h"
#include <QColor>
#include <QPainter>
class TestQgsComposerShapes : public QObject
{
Q_OBJECT
public:
TestQgsComposerShapes() = default;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void rectangle(); //test if rectangle shape is functioning
void triangle(); //test if triange shape is functioning
void ellipse(); //test if ellipse shape is functioning
void roundedRectangle(); //test if rounded rectangle shape is functioning
void symbol(); //test is styling shapes via symbol is working
private:
QgsComposition *mComposition = nullptr;
QgsComposerShape *mComposerShape = nullptr;
QString mReport;
};
void TestQgsComposerShapes::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
//create composition with two rectangles
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mComposerShape = new QgsComposerShape( 20, 20, 150, 100, mComposition );
mComposerShape->setBackgroundColor( QColor::fromRgb( 255, 150, 0 ) );
mComposition->addComposerShape( mComposerShape );
mReport = QStringLiteral( "<h1>Composer Shape Tests</h1>\n" );
}
void TestQgsComposerShapes::cleanupTestCase()
{
delete mComposition;
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}
void TestQgsComposerShapes::init()
{
}
void TestQgsComposerShapes::cleanup()
{
}
void TestQgsComposerShapes::rectangle()
{
mComposerShape->setShapeType( QgsComposerShape::Rectangle );
QgsCompositionChecker checker( QStringLiteral( "composershapes_rectangle" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) );
QVERIFY( checker.testComposition( mReport ) );
}
void TestQgsComposerShapes::triangle()
{
mComposerShape->setShapeType( QgsComposerShape::Triangle );
QgsCompositionChecker checker( QStringLiteral( "composershapes_triangle" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) );
QVERIFY( checker.testComposition( mReport ) );
}
void TestQgsComposerShapes::ellipse()
{
mComposerShape->setShapeType( QgsComposerShape::Ellipse );
QgsCompositionChecker checker( QStringLiteral( "composershapes_ellipse" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) );
QVERIFY( checker.testComposition( mReport ) );
}
void TestQgsComposerShapes::roundedRectangle()
{
mComposerShape->setShapeType( QgsComposerShape::Rectangle );
mComposerShape->setCornerRadius( 30 );
QgsCompositionChecker checker( QStringLiteral( "composershapes_roundedrect" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) );
QVERIFY( checker.testComposition( mReport ) );
mComposerShape->setCornerRadius( 0 );
}
void TestQgsComposerShapes::symbol()
{
mComposerShape->setShapeType( QgsComposerShape::Rectangle );
//setup simple fill
QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( Qt::green );
simpleFill->setStrokeColor( Qt::yellow );
simpleFill->setStrokeWidth( 6 );
mComposerShape->setShapeStyleSymbol( fillSymbol );
mComposerShape->setUseSymbol( true );
delete fillSymbol;
QgsCompositionChecker checker( QStringLiteral( "composershapes_symbol" ), mComposition );
checker.setControlPathPrefix( QStringLiteral( "composer_shapes" ) );
QVERIFY( checker.testComposition( mReport ) );
}
QGSTEST_MAIN( TestQgsComposerShapes )
#include "testqgscomposershapes.moc"

File diff suppressed because it is too large Load Diff

View File

@ -1,754 +0,0 @@
/***************************************************************************
testqgscomposerutils.cpp
-----------------------
begin : July 2014
copyright : (C) 2014 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h" //for standard test font
#include "qgscomposerutils.h"
#include "qgscomposition.h"
#include "qgscomposermap.h"
#include "qgsmultirenderchecker.h"
#include "qgsfontutils.h"
#include "qgsproject.h"
#include "qgsproperty.h"
#include <QObject>
#include "qgstest.h"
#include <QMap>
class TestQgsComposerUtils : public QObject
{
Q_OBJECT
public:
TestQgsComposerUtils();
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void drawArrowHead(); //test drawing an arrow head
void angle(); //test angle utility function
void rotate(); //test rotation helper function
void normalizedAngle(); //test normalised angle function
void snappedAngle(); //test snapped angle function
void largestRotatedRect(); //test largest rotated rect helper function
void pointsToMM(); //test conversion of point size to mm
void mmToPoints(); //test conversion of mm to point size
void relativePosition(); //test relative position function
void relativeResizeRect(); //test relative resize of rectangle function
void decodePaperOrientation(); //test decoding paper orientation
void decodePaperSize(); //test decoding paper size
void readOldDataDefinedProperty(); //test reading a data defined property
void readOldDataDefinedPropertyMap(); //test reading a whole data defined property map
void scaledFontPixelSize(); //test creating a scaled font
void fontAscentMM(); //test calculating font ascent in mm
void fontDescentMM(); //test calculating font descent in mm
void fontHeightMM(); //test calculating font height in mm
void fontHeightCharacterMM(); //test calculating font character height in mm
void textWidthMM(); //test calculating text width in mm
void textHeightMM(); //test calculating text height in mm
void drawTextPos(); //test drawing text at a pos
void drawTextRect(); //test drawing text in a rect
void createRenderContextFromComposition();
void createRenderContextFromMap();
private:
bool renderCheck( const QString &testName, QImage &image, int mismatchCount = 0 );
QgsComposition *mComposition = nullptr;
QString mReport;
QFont mTestFont;
};
TestQgsComposerUtils::TestQgsComposerUtils() = default;
void TestQgsComposerUtils::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis(); //for access to test font
mComposition = new QgsComposition( QgsProject::instance() );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mReport = QStringLiteral( "<h1>Composer Utils Tests</h1>\n" );
QgsFontUtils::loadStandardTestFonts( QStringList() << QStringLiteral( "Oblique" ) );
mTestFont = QgsFontUtils::getStandardTestFont( QStringLiteral( "Oblique " ) );
mTestFont.setItalic( true );
}
void TestQgsComposerUtils::cleanupTestCase()
{
delete mComposition;
QgsApplication::exitQgis();
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
}
void TestQgsComposerUtils::init()
{
}
void TestQgsComposerUtils::cleanup()
{
}
void TestQgsComposerUtils::drawArrowHead()
{
//test drawing with no painter
QgsComposerUtils::drawArrowHead( nullptr, 100, 100, 90, 30 );
//test painting on to image
QImage testImage = QImage( 250, 250, QImage::Format_RGB32 );
testImage.fill( qRgb( 152, 219, 249 ) );
QPainter testPainter;
testPainter.begin( &testImage );
QgsComposerUtils::drawArrowHead( &testPainter, 100, 100, 45, 30 );
testPainter.end();
QVERIFY( renderCheck( "composerutils_drawarrowhead", testImage, 40 ) );
}
void TestQgsComposerUtils::angle()
{
//test angle with zero length line
QCOMPARE( QgsComposerUtils::angle( QPointF( 1, 1 ), QPointF( 1, 1 ) ), 0.0 );
//test angles to different quadrants
QCOMPARE( QgsComposerUtils::angle( QPointF( 1, 1 ), QPointF( 1, 2 ) ), 180.0 );
QCOMPARE( QgsComposerUtils::angle( QPointF( 1, 1 ), QPointF( 2, 2 ) ), 135.0 );
QCOMPARE( QgsComposerUtils::angle( QPointF( 1, 1 ), QPointF( 2, 1 ) ), 90.0 );
QCOMPARE( QgsComposerUtils::angle( QPointF( 1, 1 ), QPointF( 2, 0 ) ), 45.0 );
QCOMPARE( QgsComposerUtils::angle( QPointF( 1, 1 ), QPointF( 1, 0 ) ), 0.0 );
QCOMPARE( QgsComposerUtils::angle( QPointF( 1, 1 ), QPointF( 0, 0 ) ), 315.0 );
QCOMPARE( QgsComposerUtils::angle( QPointF( 1, 1 ), QPointF( 0, 1 ) ), 270.0 );
QCOMPARE( QgsComposerUtils::angle( QPointF( 1, 1 ), QPointF( 0, 2 ) ), 225.0 );
}
void TestQgsComposerUtils::rotate()
{
// pairs of lines from before -> expected after position and angle to rotate
QList< QPair< QLineF, double > > testVals;
testVals << qMakePair( QLineF( 0, 1, 0, 1 ), 0.0 );
testVals << qMakePair( QLineF( 0, 1, -1, 0 ), 90.0 );
testVals << qMakePair( QLineF( 0, 1, 0, -1 ), 180.0 );
testVals << qMakePair( QLineF( 0, 1, 1, 0 ), 270.0 );
testVals << qMakePair( QLineF( 0, 1, 0, 1 ), 360.0 );
//test rotate helper function
QList< QPair< QLineF, double > >::const_iterator it = testVals.constBegin();
for ( ; it != testVals.constEnd(); ++it )
{
double x = ( *it ).first.x1();
double y = ( *it ).first.y1();
QgsComposerUtils::rotate( ( *it ).second, x, y );
QGSCOMPARENEAR( x, ( *it ).first.x2(), 4 * DBL_EPSILON );
QGSCOMPARENEAR( y, ( *it ).first.y2(), 4 * DBL_EPSILON );
}
}
void TestQgsComposerUtils::normalizedAngle()
{
QList< QPair< double, double > > testVals;
testVals << qMakePair( 0.0, 0.0 );
testVals << qMakePair( 90.0, 90.0 );
testVals << qMakePair( 180.0, 180.0 );
testVals << qMakePair( 270.0, 270.0 );
testVals << qMakePair( 360.0, 0.0 );
testVals << qMakePair( 390.0, 30.0 );
testVals << qMakePair( 720.0, 0.0 );
testVals << qMakePair( 730.0, 10.0 );
testVals << qMakePair( -10.0, 350.0 );
testVals << qMakePair( -360.0, 0.0 );
testVals << qMakePair( -370.0, 350.0 );
testVals << qMakePair( -760.0, 320.0 );
//test normalized angle helper function
QList< QPair< double, double > >::const_iterator it = testVals.constBegin();
for ( ; it != testVals.constEnd(); ++it )
{
QGSCOMPARENEAR( QgsComposerUtils::normalizedAngle( ( *it ).first ), ( *it ).second, 4 * DBL_EPSILON );
}
}
void TestQgsComposerUtils::snappedAngle()
{
QList< QPair< double, double > > testVals;
testVals << qMakePair( 0.0, 0.0 );
testVals << qMakePair( 10.0, 0.0 );
testVals << qMakePair( 20.0, 0.0 );
testVals << qMakePair( 30.0, 45.0 );
testVals << qMakePair( 40.0, 45.0 );
testVals << qMakePair( 50.0, 45.0 );
testVals << qMakePair( 60.0, 45.0 );
testVals << qMakePair( 70.0, 90.0 );
testVals << qMakePair( 80.0, 90.0 );
testVals << qMakePair( 90.0, 90.0 );
testVals << qMakePair( 100.0, 90.0 );
testVals << qMakePair( 110.0, 90.0 );
testVals << qMakePair( 120.0, 135.0 );
testVals << qMakePair( 130.0, 135.0 );
testVals << qMakePair( 140.0, 135.0 );
testVals << qMakePair( 150.0, 135.0 );
testVals << qMakePair( 160.0, 180.0 );
testVals << qMakePair( 170.0, 180.0 );
testVals << qMakePair( 180.0, 180.0 );
testVals << qMakePair( 190.0, 180.0 );
testVals << qMakePair( 200.0, 180.0 );
testVals << qMakePair( 210.0, 225.0 );
testVals << qMakePair( 220.0, 225.0 );
testVals << qMakePair( 230.0, 225.0 );
testVals << qMakePair( 240.0, 225.0 );
testVals << qMakePair( 250.0, 270.0 );
testVals << qMakePair( 260.0, 270.0 );
testVals << qMakePair( 270.0, 270.0 );
testVals << qMakePair( 280.0, 270.0 );
testVals << qMakePair( 290.0, 270.0 );
testVals << qMakePair( 300.0, 315.0 );
testVals << qMakePair( 310.0, 315.0 );
testVals << qMakePair( 320.0, 315.0 );
testVals << qMakePair( 330.0, 315.0 );
testVals << qMakePair( 340.0, 0.0 );
testVals << qMakePair( 350.0, 0.0 );
testVals << qMakePair( 360.0, 0.0 );
//test snapped angle helper function
QList< QPair< double, double > >::const_iterator it = testVals.constBegin();
for ( ; it != testVals.constEnd(); ++it )
{
QGSCOMPARENEAR( QgsComposerUtils::snappedAngle( ( *it ).first ), ( *it ).second, 4 * DBL_EPSILON );
}
}
void TestQgsComposerUtils::largestRotatedRect()
{
QRectF wideRect = QRectF( 0, 0, 2, 1 );
QRectF highRect = QRectF( 0, 0, 1, 2 );
QRectF bounds = QRectF( 0, 0, 4, 2 );
//simple cases
//0 rotation
QRectF result = QgsComposerUtils::largestRotatedRectWithinBounds( wideRect, bounds, 0 );
QCOMPARE( result, QRectF( 0, 0, 4, 2 ) );
result = QgsComposerUtils::largestRotatedRectWithinBounds( highRect, bounds, 0 );
QCOMPARE( result, QRectF( 1.5, 0, 1, 2 ) );
// 90 rotation
result = QgsComposerUtils::largestRotatedRectWithinBounds( wideRect, bounds, 90 );
QCOMPARE( result, QRectF( 1.5, 0, 2, 1 ) );
result = QgsComposerUtils::largestRotatedRectWithinBounds( highRect, bounds, 90 );
QCOMPARE( result, QRectF( 0, 0, 2, 4 ) );
// 180 rotation
result = QgsComposerUtils::largestRotatedRectWithinBounds( wideRect, bounds, 180 );
QCOMPARE( result, QRectF( 0, 0, 4, 2 ) );
result = QgsComposerUtils::largestRotatedRectWithinBounds( highRect, bounds, 0 );
QCOMPARE( result, QRectF( 1.5, 0, 1, 2 ) );
// 270 rotation
result = QgsComposerUtils::largestRotatedRectWithinBounds( wideRect, bounds, 270 );
QCOMPARE( result, QRectF( 1.5, 0, 2, 1 ) );
result = QgsComposerUtils::largestRotatedRectWithinBounds( highRect, bounds, 270 );
QCOMPARE( result, QRectF( 0, 0, 2, 4 ) );
//360 rotation
result = QgsComposerUtils::largestRotatedRectWithinBounds( wideRect, bounds, 360 );
QCOMPARE( result, QRectF( 0, 0, 4, 2 ) );
result = QgsComposerUtils::largestRotatedRectWithinBounds( highRect, bounds, 360 );
QCOMPARE( result, QRectF( 1.5, 0, 1, 2 ) );
//full test, run through a circle in 10 degree increments
for ( double rotation = 10; rotation < 360; rotation += 10 )
{
result = QgsComposerUtils::largestRotatedRectWithinBounds( wideRect, bounds, rotation );
QTransform t;
t.rotate( rotation );
QRectF rotatedRectBounds = t.mapRect( result );
//one of the rotated rects dimensions must equal the bounding rectangles dimensions (ie, it has been constrained by one dimension)
//and the other dimension must be less than or equal to bounds dimension
QVERIFY( ( qgsDoubleNear( rotatedRectBounds.width(), bounds.width(), 0.001 ) && ( rotatedRectBounds.height() <= bounds.height() ) )
|| ( qgsDoubleNear( rotatedRectBounds.height(), bounds.height(), 0.001 ) && ( rotatedRectBounds.width() <= bounds.width() ) ) );
//also verify that aspect ratio of rectangle has not changed
QGSCOMPARENEAR( result.width() / result.height(), wideRect.width() / wideRect.height(), 4 * DBL_EPSILON );
}
//and again for the high rectangle
for ( double rotation = 10; rotation < 360; rotation += 10 )
{
result = QgsComposerUtils::largestRotatedRectWithinBounds( highRect, bounds, rotation );
QTransform t;
t.rotate( rotation );
QRectF rotatedRectBounds = t.mapRect( result );
//one of the rotated rects dimensions must equal the bounding rectangles dimensions (ie, it has been constrained by one dimension)
//and the other dimension must be less than or equal to bounds dimension
QVERIFY( ( qgsDoubleNear( rotatedRectBounds.width(), bounds.width(), 0.001 ) && ( rotatedRectBounds.height() <= bounds.height() ) )
|| ( qgsDoubleNear( rotatedRectBounds.height(), bounds.height(), 0.001 ) && ( rotatedRectBounds.width() <= bounds.width() ) ) );
//also verify that aspect ratio of rectangle has not changed
QGSCOMPARENEAR( result.width() / result.height(), highRect.width() / highRect.height(), 4 * DBL_EPSILON );
}
}
void TestQgsComposerUtils::pointsToMM()
{
//test conversion of points to mm, based on 1 point = 1 / 72 of an inch
QGSCOMPARENEAR( QgsComposerUtils::pointsToMM( 72 / 25.4 ), 1, 0.001 );
}
void TestQgsComposerUtils::mmToPoints()
{
//test conversion of mm to points, based on 1 point = 1 / 72 of an inch
QGSCOMPARENEAR( QgsComposerUtils::mmToPoints( 25.4 / 72 ), 1, 0.001 );
}
void TestQgsComposerUtils::relativePosition()
{
//+ve gradient
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 1, 0, 2, 0, 4 ), 2, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 0, 0, 2, 0, 4 ), 0, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 2, 0, 2, 0, 4 ), 4, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 4, 0, 2, 0, 4 ), 8, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( -2, 0, 2, 0, 4 ), -4, 0.001 );
//-ve gradient
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 1, 0, 2, 4, 0 ), 2, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 0, 0, 2, 4, 0 ), 4, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 2, 0, 2, 4, 0 ), 0, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 4, 0, 2, 4, 0 ), -4, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( -2, 0, 2, 4, 0 ), 8, 0.001 );
//-ve domain
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 1, 2, 0, 0, 4 ), 2, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 0, 2, 0, 0, 4 ), 4, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 2, 2, 0, 0, 4 ), 0, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 4, 2, 0, 0, 4 ), -4, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( -2, 2, 0, 0, 4 ), 8, 0.001 );
//-ve domain and gradient
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 1, 2, 0, 4, 0 ), 2, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 0, 2, 0, 4, 0 ), 0, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 2, 2, 0, 4, 0 ), 4, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( 4, 2, 0, 4, 0 ), 8, 0.001 );
QGSCOMPARENEAR( QgsComposerUtils::relativePosition( -2, 2, 0, 4, 0 ), -4, 0.001 );
}
void TestQgsComposerUtils::relativeResizeRect()
{
//test rectangle which fills bounds
QRectF testRect = QRectF( 0, 0, 1, 1 );
QRectF boundsBefore = QRectF( 0, 0, 1, 1 );
QRectF boundsAfter = QRectF( 0, 0, 1, 1 );
QgsComposerUtils::relativeResizeRect( testRect, boundsBefore, boundsAfter );
QCOMPARE( testRect, QRectF( 0, 0, 1, 1 ) );
testRect = QRectF( 0, 0, 1, 1 );
boundsAfter = QRectF( 0, 0, 2, 2 );
QgsComposerUtils::relativeResizeRect( testRect, boundsBefore, boundsAfter );
QCOMPARE( testRect, QRectF( 0, 0, 2, 2 ) );
testRect = QRectF( 0, 0, 1, 1 );
boundsAfter = QRectF( 0, 0, 0.5, 4 );
QgsComposerUtils::relativeResizeRect( testRect, boundsBefore, boundsAfter );
QCOMPARE( testRect, QRectF( 0, 0, 0.5, 4 ) );
//test rectangle which doesn't fill bounds
testRect = QRectF( 1, 2, 1, 2 );
boundsBefore = QRectF( 0, 0, 4, 8 );
boundsAfter = QRectF( 0, 0, 2, 4 );
QgsComposerUtils::relativeResizeRect( testRect, boundsBefore, boundsAfter );
QCOMPARE( testRect, QRectF( 0.5, 1, 0.5, 1 ) );
}
void TestQgsComposerUtils::decodePaperOrientation()
{
QgsComposition::PaperOrientation orientation;
bool ok = false;
orientation = QgsComposerUtils::decodePaperOrientation( QStringLiteral( "bad string" ), ok );
QVERIFY( !ok );
QCOMPARE( orientation, QgsComposition::Landscape ); //should default to landscape
ok = false;
orientation = QgsComposerUtils::decodePaperOrientation( QStringLiteral( "portrait" ), ok );
QVERIFY( ok );
QCOMPARE( orientation, QgsComposition::Portrait );
ok = false;
orientation = QgsComposerUtils::decodePaperOrientation( QStringLiteral( "LANDSCAPE" ), ok );
QVERIFY( ok );
QCOMPARE( orientation, QgsComposition::Landscape );
}
void TestQgsComposerUtils::decodePaperSize()
{
double width = 0;
double height = 0;
QVERIFY( ! QgsComposerUtils::decodePresetPaperSize( "bad string", width, height ) );
//good strings
QVERIFY( QgsComposerUtils::decodePresetPaperSize( "a4", width, height ) );
QCOMPARE( width, 210.0 );
QCOMPARE( height, 297.0 );
QVERIFY( QgsComposerUtils::decodePresetPaperSize( "B0", width, height ) );
QCOMPARE( width, 1000.0 );
QCOMPARE( height, 1414.0 );
QVERIFY( QgsComposerUtils::decodePresetPaperSize( "letter", width, height ) );
QCOMPARE( width, 215.9 );
QCOMPARE( height, 279.4 );
QVERIFY( QgsComposerUtils::decodePresetPaperSize( "LEGAL", width, height ) );
QCOMPARE( width, 215.9 );
QCOMPARE( height, 355.6 );
}
void TestQgsComposerUtils::readOldDataDefinedProperty()
{
//create a test dom element
QDomImplementation DomImplementation;
QDomDocumentType documentType =
DomImplementation.createDocumentType(
QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
QDomDocument doc( documentType );
QDomElement rootNode = doc.createElement( QStringLiteral( "qgis" ) );
QDomElement itemElem = doc.createElement( QStringLiteral( "item" ) );
//dd element
QDomElement ddElem = doc.createElement( QStringLiteral( "dataDefinedTestProperty" ) );
ddElem.setAttribute( QStringLiteral( "active" ), QStringLiteral( "true" ) );
ddElem.setAttribute( QStringLiteral( "useExpr" ), QStringLiteral( "true" ) );
ddElem.setAttribute( QStringLiteral( "expr" ), QStringLiteral( "test expression" ) );
ddElem.setAttribute( QStringLiteral( "field" ), QStringLiteral( "test field" ) );
itemElem.appendChild( ddElem );
rootNode.appendChild( itemElem );
//try reading dd elements
//bad data defined properties - should not be read into dataDefinedProperties map
QVERIFY( !QgsComposerUtils::readOldDataDefinedProperty( QgsComposerObject::NoProperty, ddElem ) );
QVERIFY( !QgsComposerUtils::readOldDataDefinedProperty( QgsComposerObject::AllProperties, ddElem ) );
//read into valid property
QgsProperty p( QgsComposerUtils::readOldDataDefinedProperty( QgsComposerObject::TestProperty, ddElem ) );
QVERIFY( p );
QVERIFY( p.isActive() );
QCOMPARE( p.propertyType(), QgsProperty::ExpressionBasedProperty );
QCOMPARE( p.expressionString(), QString( "test expression" ) );
ddElem.setAttribute( QStringLiteral( "useExpr" ), QStringLiteral( "false" ) );
p = QgsComposerUtils::readOldDataDefinedProperty( QgsComposerObject::TestProperty, ddElem );
QVERIFY( p );
QVERIFY( p.isActive() );
QCOMPARE( p.propertyType(), QgsProperty::FieldBasedProperty );
QCOMPARE( p.field(), QString( "test field" ) );
//reading false parameters
QDomElement ddElem2 = doc.createElement( QStringLiteral( "dataDefinedProperty2" ) );
ddElem2.setAttribute( QStringLiteral( "active" ), QStringLiteral( "false" ) );
itemElem.appendChild( ddElem2 );
p = QgsComposerUtils::readOldDataDefinedProperty( QgsComposerObject::TestProperty, ddElem2 );
QVERIFY( p );
QVERIFY( !p.isActive() );
}
void TestQgsComposerUtils::readOldDataDefinedPropertyMap()
{
//create a test dom element
QDomImplementation DomImplementation;
QDomDocumentType documentType =
DomImplementation.createDocumentType(
QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
QDomDocument doc( documentType );
QDomElement rootNode = doc.createElement( QStringLiteral( "qgis" ) );
QDomElement itemElem = doc.createElement( QStringLiteral( "item" ) );
//dd elements
QDomElement ddElem = doc.createElement( QStringLiteral( "dataDefinedBlendMode" ) );
ddElem.setAttribute( QStringLiteral( "active" ), QStringLiteral( "true" ) );
ddElem.setAttribute( QStringLiteral( "useExpr" ), QStringLiteral( "true" ) );
ddElem.setAttribute( QStringLiteral( "expr" ), QStringLiteral( "test expression" ) );
ddElem.setAttribute( QStringLiteral( "field" ), QStringLiteral( "test field" ) );
itemElem.appendChild( ddElem );
QDomElement ddElem2 = doc.createElement( QStringLiteral( "dataDefinedTransparency" ) );
ddElem2.setAttribute( QStringLiteral( "active" ), QStringLiteral( "false" ) );
ddElem2.setAttribute( QStringLiteral( "useExpr" ), QStringLiteral( "false" ) );
ddElem2.setAttribute( QStringLiteral( "expr" ), QStringLiteral( "test expression 2" ) );
ddElem2.setAttribute( QStringLiteral( "field" ), QStringLiteral( "test field 2" ) );
itemElem.appendChild( ddElem2 );
QDomElement ddElem3 = doc.createElement( QStringLiteral( "dataDefinedProperty" ) );
ddElem3.setAttribute( QStringLiteral( "active" ), QStringLiteral( "true" ) );
ddElem3.setAttribute( QStringLiteral( "useExpr" ), QStringLiteral( "false" ) );
ddElem3.setAttribute( QStringLiteral( "expr" ), QStringLiteral( "test expression 3" ) );
ddElem3.setAttribute( QStringLiteral( "field" ), QStringLiteral( "test field 3" ) );
itemElem.appendChild( ddElem3 );
rootNode.appendChild( itemElem );
//try reading dd elements
QgsPropertyCollection dataDefinedProperties;
QgsComposerUtils::readOldDataDefinedPropertyMap( itemElem, dataDefinedProperties );
//check returned values
QCOMPARE( dataDefinedProperties.count(), 3 );
QVERIFY( ( dataDefinedProperties.property( QgsComposerObject::BlendMode ) ).isActive() );
QCOMPARE( ( dataDefinedProperties.property( QgsComposerObject::BlendMode ) ).propertyType(), QgsProperty::ExpressionBasedProperty );
QCOMPARE( dataDefinedProperties.property( QgsComposerObject::BlendMode ).expressionString(), QString( "test expression" ) );
QVERIFY( !( dataDefinedProperties.property( QgsComposerObject::Opacity ) ).isActive() );
QCOMPARE( ( dataDefinedProperties.property( QgsComposerObject::Opacity ) ).propertyType(), QgsProperty::FieldBasedProperty );
QCOMPARE( dataDefinedProperties.property( QgsComposerObject::Opacity ).field(), QString( "test field 2" ) );
QVERIFY( ( dataDefinedProperties.property( QgsComposerObject::TestProperty ) ).isActive() );
QCOMPARE( ( dataDefinedProperties.property( QgsComposerObject::TestProperty ) ).propertyType(), QgsProperty::FieldBasedProperty );
QCOMPARE( dataDefinedProperties.property( QgsComposerObject::TestProperty ).field(), QString( "test field 3" ) );
}
void TestQgsComposerUtils::scaledFontPixelSize()
{
//create a 12 point test font
mTestFont.setPointSize( 12 );
//test scaling of font for painting
QFont scaledFont = QgsComposerUtils::scaledFontPixelSize( mTestFont );
QCOMPARE( scaledFont.pixelSize(), 42 );
QCOMPARE( scaledFont.family(), mTestFont.family() );
}
void TestQgsComposerUtils::fontAscentMM()
{
mTestFont.setPointSize( 12 );
//platform specific font rendering differences mean these tests need to be very leniant
QGSCOMPARENEAR( QgsComposerUtils::fontAscentMM( mTestFont ), 3.9, 0.5 );
}
void TestQgsComposerUtils::fontDescentMM()
{
mTestFont.setPointSize( 12 );
QGSCOMPARENEAR( QgsComposerUtils::fontDescentMM( mTestFont ), 0.9, 0.05 );
}
void TestQgsComposerUtils::fontHeightMM()
{
mTestFont.setPointSize( 12 );
//platform specific font rendering differences mean these tests need to be very leniant
QGSCOMPARENEAR( QgsComposerUtils::fontHeightMM( mTestFont ), 4.9, 0.5 );
}
void TestQgsComposerUtils::fontHeightCharacterMM()
{
mTestFont.setPointSize( 12 );
//platform specific font rendering differences mean these tests need to be very leniant
QGSCOMPARENEAR( QgsComposerUtils::fontHeightCharacterMM( mTestFont, QChar( 'a' ) ), 2.4, 0.15 );
QGSCOMPARENEAR( QgsComposerUtils::fontHeightCharacterMM( mTestFont, QChar( 'l' ) ), 3.15, 0.16 );
QGSCOMPARENEAR( QgsComposerUtils::fontHeightCharacterMM( mTestFont, QChar( 'g' ) ), 3.2, 0.11 );
}
void TestQgsComposerUtils::textWidthMM()
{
//platform specific font rendering differences mean this test needs to be very leniant
mTestFont.setPointSize( 12 );
QGSCOMPARENEAR( QgsComposerUtils::textWidthMM( mTestFont, QString( "test string" ) ), 20, 2 );
}
void TestQgsComposerUtils::textHeightMM()
{
//platform specific font rendering differences mean this test needs to be very leniant
mTestFont.setPointSize( 12 );
QgsDebugMsg( QString( "height: %1" ).arg( QgsComposerUtils::textHeightMM( mTestFont, QString( "test string" ) ) ) );
QGSCOMPARENEAR( QgsComposerUtils::textHeightMM( mTestFont, QString( "test string" ) ), 3.9, 0.2 );
QgsDebugMsg( QString( "height: %1" ).arg( QgsComposerUtils::textHeightMM( mTestFont, QString( "test\nstring" ) ) ) );
QGSCOMPARENEAR( QgsComposerUtils::textHeightMM( mTestFont, QString( "test\nstring" ) ), 8.7, 0.2 );
QgsDebugMsg( QString( "height: %1" ).arg( QgsComposerUtils::textHeightMM( mTestFont, QString( "test\nstring" ), 2 ) ) );
QGSCOMPARENEAR( QgsComposerUtils::textHeightMM( mTestFont, QString( "test\nstring" ), 2 ), 13.5, 0.2 );
QgsDebugMsg( QString( "height: %1" ).arg( QgsComposerUtils::textHeightMM( mTestFont, QString( "test\nstring\nstring" ) ) ) );
QGSCOMPARENEAR( QgsComposerUtils::textHeightMM( mTestFont, QString( "test\nstring\nstring" ) ), 13.5, 0.2 );
}
void TestQgsComposerUtils::drawTextPos()
{
//test drawing with no painter
QgsComposerUtils::drawText( nullptr, QPointF( 5, 15 ), QStringLiteral( "Abc123" ), mTestFont );
//test drawing text on to image
mTestFont.setPointSize( 48 );
QImage testImage = QImage( 250, 250, QImage::Format_RGB32 );
testImage.fill( qRgb( 152, 219, 249 ) );
QPainter testPainter;
testPainter.begin( &testImage );
QgsComposerUtils::drawText( &testPainter, QPointF( 5, 15 ), QStringLiteral( "Abc123" ), mTestFont, Qt::white );
testPainter.end();
QVERIFY( renderCheck( "composerutils_drawtext_pos", testImage, 100 ) );
//test drawing with pen color set on painter and no specified color
//text should be drawn using painter pen color
testImage.fill( qRgb( 152, 219, 249 ) );
testPainter.begin( &testImage );
testPainter.setPen( QPen( Qt::green ) );
QgsComposerUtils::drawText( &testPainter, QPointF( 5, 15 ), QStringLiteral( "Abc123" ), mTestFont );
testPainter.end();
QVERIFY( renderCheck( "composerutils_drawtext_posnocolor", testImage, 100 ) );
}
void TestQgsComposerUtils::drawTextRect()
{
//test drawing with no painter
QgsComposerUtils::drawText( nullptr, QRectF( 5, 15, 200, 50 ), QStringLiteral( "Abc123" ), mTestFont );
//test drawing text on to image
mTestFont.setPointSize( 48 );
QImage testImage = QImage( 250, 250, QImage::Format_RGB32 );
testImage.fill( qRgb( 152, 219, 249 ) );
QPainter testPainter;
testPainter.begin( &testImage );
QgsComposerUtils::drawText( &testPainter, QRectF( 5, 15, 200, 50 ), QStringLiteral( "Abc123" ), mTestFont, Qt::white );
testPainter.end();
QVERIFY( renderCheck( "composerutils_drawtext_rect", testImage, 100 ) );
//test drawing with pen color set on painter and no specified color
//text should be drawn using painter pen color
testImage.fill( qRgb( 152, 219, 249 ) );
testPainter.begin( &testImage );
testPainter.setPen( QPen( Qt::green ) );
QgsComposerUtils::drawText( &testPainter, QRectF( 5, 15, 200, 50 ), QStringLiteral( "Abc123" ), mTestFont );
testPainter.end();
QVERIFY( renderCheck( "composerutils_drawtext_rectnocolor", testImage, 100 ) );
//test alignment settings
testImage.fill( qRgb( 152, 219, 249 ) );
testPainter.begin( &testImage );
QgsComposerUtils::drawText( &testPainter, QRectF( 5, 15, 200, 50 ), QStringLiteral( "Abc123" ), mTestFont, Qt::black, Qt::AlignRight, Qt::AlignBottom );
testPainter.end();
QVERIFY( renderCheck( "composerutils_drawtext_rectalign", testImage, 100 ) );
//test extra flags - render without clipping
testImage.fill( qRgb( 152, 219, 249 ) );
testPainter.begin( &testImage );
QgsComposerUtils::drawText( &testPainter, QRectF( 5, 15, 20, 50 ), QStringLiteral( "Abc123" ), mTestFont, Qt::white, Qt::AlignLeft, Qt::AlignTop, Qt::TextDontClip );
testPainter.end();
QVERIFY( renderCheck( "composerutils_drawtext_rectflag", testImage, 100 ) );
}
void TestQgsComposerUtils::createRenderContextFromComposition()
{
QImage testImage = QImage( 250, 250, QImage::Format_RGB32 );
testImage.setDotsPerMeterX( 150 / 25.4 * 1000 );
testImage.setDotsPerMeterY( 150 / 25.4 * 1000 );
QPainter p( &testImage );
// no composition
QgsRenderContext rc = QgsComposerUtils::createRenderContextForComposition( nullptr, &p );
QGSCOMPARENEAR( rc.scaleFactor(), 150 / 25.4, 0.001 );
QCOMPARE( rc.painter(), &p );
// no composition, no painter
rc = QgsComposerUtils::createRenderContextForComposition( nullptr, nullptr );
QGSCOMPARENEAR( rc.scaleFactor(), 88 / 25.4, 0.001 );
QVERIFY( !rc.painter() );
//create composition with no reference map
QgsRectangle extent( 2000, 2800, 2500, 2900 );
QgsComposition *composition = new QgsComposition( QgsProject::instance() );
rc = QgsComposerUtils::createRenderContextForComposition( composition, &p );
QGSCOMPARENEAR( rc.scaleFactor(), 150 / 25.4, 0.001 );
QCOMPARE( rc.painter(), &p );
// composition, no map, no painter
rc = QgsComposerUtils::createRenderContextForComposition( composition, nullptr );
QGSCOMPARENEAR( rc.scaleFactor(), 88 / 25.4, 0.001 );
QVERIFY( !rc.painter() );
// add a reference map
QgsComposerMap *map = new QgsComposerMap( composition );
map->setNewExtent( extent );
map->setSceneRect( QRectF( 30, 60, 200, 100 ) );
composition->addComposerMap( map );
composition->setReferenceMap( map );
rc = QgsComposerUtils::createRenderContextForComposition( composition, &p );
QGSCOMPARENEAR( rc.scaleFactor(), 150 / 25.4, 0.001 );
QGSCOMPARENEAR( rc.rendererScale(), map->scale(), 1000000 );
QCOMPARE( rc.painter(), &p );
// composition, reference map, no painter
rc = QgsComposerUtils::createRenderContextForComposition( composition, nullptr );
QGSCOMPARENEAR( rc.scaleFactor(), 88 / 25.4, 0.001 );
QGSCOMPARENEAR( rc.rendererScale(), map->scale(), 1000000 );
QVERIFY( !rc.painter() );
p.end();
}
void TestQgsComposerUtils::createRenderContextFromMap()
{
QImage testImage = QImage( 250, 250, QImage::Format_RGB32 );
testImage.setDotsPerMeterX( 150 / 25.4 * 1000 );
testImage.setDotsPerMeterY( 150 / 25.4 * 1000 );
QPainter p( &testImage );
// no map
QgsRenderContext rc = QgsComposerUtils::createRenderContextForMap( nullptr, &p );
QGSCOMPARENEAR( rc.scaleFactor(), 150 / 25.4, 0.001 );
QCOMPARE( rc.painter(), &p );
// no map, no painter
rc = QgsComposerUtils::createRenderContextForMap( nullptr, nullptr );
QGSCOMPARENEAR( rc.scaleFactor(), 88 / 25.4, 0.001 );
QVERIFY( !rc.painter() );
//create composition with no reference map
QgsRectangle extent( 2000, 2800, 2500, 2900 );
QgsComposition *composition = new QgsComposition( QgsProject::instance() );
// add a map
QgsComposerMap *map = new QgsComposerMap( composition );
map->setNewExtent( extent );
map->setSceneRect( QRectF( 30, 60, 200, 100 ) );
composition->addComposerMap( map );
rc = QgsComposerUtils::createRenderContextForMap( map, &p );
QGSCOMPARENEAR( rc.scaleFactor(), 150 / 25.4, 0.001 );
QGSCOMPARENEAR( rc.rendererScale(), map->scale(), 1000000 );
QCOMPARE( rc.painter(), &p );
// map, no painter
rc = QgsComposerUtils::createRenderContextForMap( map, nullptr );
QGSCOMPARENEAR( rc.scaleFactor(), 88 / 25.4, 0.001 );
QGSCOMPARENEAR( rc.rendererScale(), map->scale(), 1000000 );
QVERIFY( !rc.painter() );
// secondary map
QgsComposerMap *map2 = new QgsComposerMap( composition );
map2->setNewExtent( extent );
map2->setSceneRect( QRectF( 30, 60, 100, 50 ) );
composition->addComposerMap( map2 );
rc = QgsComposerUtils::createRenderContextForMap( map2, &p );
QGSCOMPARENEAR( rc.scaleFactor(), 150 / 25.4, 0.001 );
QGSCOMPARENEAR( rc.rendererScale(), map2->scale(), 1000000 );
QVERIFY( rc.painter() );
p.end();
}
bool TestQgsComposerUtils::renderCheck( const QString &testName, QImage &image, int mismatchCount )
{
mReport += "<h2>" + testName + "</h2>\n";
QString myTmpDir = QDir::tempPath() + '/';
QString myFileName = myTmpDir + testName + ".png";
image.save( myFileName, "PNG" );
QgsRenderChecker myChecker;
myChecker.setControlPathPrefix( QStringLiteral( "composer_utils" ) );
myChecker.setControlName( "expected_" + testName );
myChecker.setRenderedImage( myFileName );
bool myResultFlag = myChecker.compareImages( testName, mismatchCount );
mReport += myChecker.report();
return myResultFlag;
}
QGSTEST_MAIN( TestQgsComposerUtils )
#include "testqgscomposerutils.moc"

View File

@ -52,25 +52,8 @@ class TestQgsComposition : public QObject
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void itemsOnPage(); //test fetching matching items on a set page
void shouldExportPage(); //test the shouldExportPage method
void pageIsEmpty(); //test the pageIsEmpty method
void customProperties();
void writeRetrieveCustomProperties();
void bounds();
void resizeToContents();
void resizeToContentsMargin();
void resizeToContentsMultiPage();
void georeference();
void variablesEdited();
void itemVariablesFunction();
void referenceMap();
void legendRestoredFromTemplate();
void legendRestoredFromTemplateAutoUpdate();
void attributeTableRestoredFromTemplate();
void mapLayersRestoredFromTemplate();
void mapLayersStyleOverrideRestoredFromTemplate();
void atlasLayerRestoredFromTemplate();
private:
QgsComposition *mComposition = nullptr;
@ -117,699 +100,6 @@ void TestQgsComposition::cleanup()
{
}
void TestQgsComposition::itemsOnPage()
{
//add some items to the composition
QgsComposerLabel *label1 = new QgsComposerLabel( mComposition );
mComposition->addComposerLabel( label1 );
label1->setItemPosition( 10, 10, 50, 50, QgsComposerItem::UpperLeft, false, 1 );
QgsComposerLabel *label2 = new QgsComposerLabel( mComposition );
mComposition->addComposerLabel( label2 );
label2->setItemPosition( 10, 10, 50, 50, QgsComposerItem::UpperLeft, false, 1 );
QgsComposerLabel *label3 = new QgsComposerLabel( mComposition );
mComposition->addComposerLabel( label3 );
label3->setItemPosition( 10, 10, 50, 50, QgsComposerItem::UpperLeft, false, 2 );
QgsComposerShape *shape1 = new QgsComposerShape( mComposition );
mComposition->addComposerShape( shape1 );
shape1->setItemPosition( 10, 10, 50, 50, QgsComposerItem::UpperLeft, false, 1 );
QgsComposerShape *shape2 = new QgsComposerShape( mComposition );
mComposition->addComposerShape( shape2 );
shape2->setItemPosition( 10, 10, 50, 50, QgsComposerItem::UpperLeft, false, 2 );
QgsComposerArrow *arrow1 = new QgsComposerArrow( mComposition );
mComposition->addComposerArrow( arrow1 );
arrow1->setItemPosition( 10, 10, 50, 50, QgsComposerItem::UpperLeft, false, 3 );
QgsComposerArrow *arrow2 = new QgsComposerArrow( mComposition );
mComposition->addComposerArrow( arrow2 );
arrow2->setItemPosition( 10, 10, 50, 50, QgsComposerItem::UpperLeft, false, 3 );
//fetch items - remember that these numbers include the paper item!
QList<QgsComposerItem *> items;
mComposition->composerItemsOnPage( items, 0 );
//should be 4 items on page 1
QCOMPARE( items.length(), 4 );
mComposition->composerItemsOnPage( items, 1 );
//should be 3 items on page 2
QCOMPARE( items.length(), 3 );
mComposition->composerItemsOnPage( items, 2 );
//should be 3 items on page 3
QCOMPARE( items.length(), 3 );
//check fetching specific item types
QList<QgsComposerLabel *> labels;
mComposition->composerItemsOnPage( labels, 0 );
//should be 2 labels on page 1
QCOMPARE( labels.length(), 2 );
mComposition->composerItemsOnPage( labels, 1 );
//should be 1 label on page 2
QCOMPARE( labels.length(), 1 );
mComposition->composerItemsOnPage( labels, 2 );
//should be no label on page 3
QCOMPARE( labels.length(), 0 );
QList<QgsComposerShape *> shapes;
mComposition->composerItemsOnPage( shapes, 0 );
//should be 1 shapes on page 1
QCOMPARE( shapes.length(), 1 );
mComposition->composerItemsOnPage( shapes, 1 );
//should be 1 shapes on page 2
QCOMPARE( shapes.length(), 1 );
mComposition->composerItemsOnPage( shapes, 2 );
//should be no shapes on page 3
QCOMPARE( shapes.length(), 0 );
QList<QgsComposerArrow *> arrows;
mComposition->composerItemsOnPage( arrows, 0 );
//should be no arrows on page 1
QCOMPARE( arrows.length(), 0 );
mComposition->composerItemsOnPage( arrows, 1 );
//should be no arrows on page 2
QCOMPARE( arrows.length(), 0 );
mComposition->composerItemsOnPage( arrows, 2 );
//should be 2 arrows on page 3
QCOMPARE( arrows.length(), 2 );
mComposition->removeComposerItem( label1 );
mComposition->removeComposerItem( label2 );
mComposition->removeComposerItem( label3 );
mComposition->removeComposerItem( shape1 );
mComposition->removeComposerItem( shape2 );
mComposition->removeComposerItem( arrow1 );
mComposition->removeComposerItem( arrow2 );
//check again with removed items
mComposition->composerItemsOnPage( labels, 0 );
QCOMPARE( labels.length(), 0 );
mComposition->composerItemsOnPage( labels, 1 );
QCOMPARE( labels.length(), 0 );
mComposition->composerItemsOnPage( labels, 2 );
QCOMPARE( labels.length(), 0 );
}
void TestQgsComposition::shouldExportPage()
{
mComposition->setPaperSize( 297, 200 );
mComposition->setNumPages( 2 );
QgsComposerHtml *htmlItem = new QgsComposerHtml( mComposition, false );
//frame on page 1
QgsComposerFrame *frame1 = new QgsComposerFrame( mComposition, htmlItem, 0, 0, 100, 100 );
//frame on page 2
QgsComposerFrame *frame2 = new QgsComposerFrame( mComposition, htmlItem, 0, 320, 100, 100 );
frame2->setHidePageIfEmpty( true );
htmlItem->addFrame( frame1 );
htmlItem->addFrame( frame2 );
htmlItem->setContentMode( QgsComposerHtml::ManualHtml );
//short content, so frame 2 should be empty
htmlItem->setHtml( QStringLiteral( "<p><i>Test manual <b>html</b></i></p>" ) );
htmlItem->loadHtml();
QCOMPARE( mComposition->shouldExportPage( 1 ), true );
QCOMPARE( mComposition->shouldExportPage( 2 ), false );
//long content, so frame 2 should not be empty
htmlItem->setHtml( QStringLiteral( "<p style=\"height: 10000px\"><i>Test manual <b>html</b></i></p>" ) );
htmlItem->loadHtml();
QCOMPARE( mComposition->shouldExportPage( 1 ), true );
QCOMPARE( mComposition->shouldExportPage( 2 ), true );
//...and back again...
htmlItem->setHtml( QStringLiteral( "<p><i>Test manual <b>html</b></i></p>" ) );
htmlItem->loadHtml();
QCOMPARE( mComposition->shouldExportPage( 1 ), true );
QCOMPARE( mComposition->shouldExportPage( 2 ), false );
mComposition->removeMultiFrame( htmlItem );
delete htmlItem;
}
void TestQgsComposition::pageIsEmpty()
{
//add some items to the composition
QgsComposerLabel *label1 = new QgsComposerLabel( mComposition );
mComposition->addComposerLabel( label1 );
label1->setItemPosition( 10, 10, 50, 50, QgsComposerItem::UpperLeft, false, 1 );
QgsComposerLabel *label2 = new QgsComposerLabel( mComposition );
mComposition->addComposerLabel( label2 );
label2->setItemPosition( 10, 10, 50, 50, QgsComposerItem::UpperLeft, false, 1 );
QgsComposerLabel *label3 = new QgsComposerLabel( mComposition );
mComposition->addComposerLabel( label3 );
label3->setItemPosition( 10, 10, 50, 50, QgsComposerItem::UpperLeft, false, 3 );
//only page 2 should be empty
QCOMPARE( mComposition->pageIsEmpty( 1 ), false );
QCOMPARE( mComposition->pageIsEmpty( 2 ), true );
QCOMPARE( mComposition->pageIsEmpty( 3 ), false );
//remove the items
mComposition->removeComposerItem( label1 );
mComposition->removeComposerItem( label2 );
mComposition->removeComposerItem( label3 );
//expect everything to be empty now
QCOMPARE( mComposition->pageIsEmpty( 1 ), true );
QCOMPARE( mComposition->pageIsEmpty( 2 ), true );
QCOMPARE( mComposition->pageIsEmpty( 3 ), true );
}
void TestQgsComposition::customProperties()
{
QgsComposition *composition = new QgsComposition( QgsProject::instance() );
QCOMPARE( composition->customProperty( "noprop", "defaultval" ).toString(), QString( "defaultval" ) );
QVERIFY( composition->customProperties().isEmpty() );
composition->setCustomProperty( QStringLiteral( "testprop" ), "testval" );
QCOMPARE( composition->customProperty( "testprop", "defaultval" ).toString(), QString( "testval" ) );
QCOMPARE( composition->customProperties().length(), 1 );
QCOMPARE( composition->customProperties().at( 0 ), QString( "testprop" ) );
//test no crash
composition->removeCustomProperty( QStringLiteral( "badprop" ) );
composition->removeCustomProperty( QStringLiteral( "testprop" ) );
QVERIFY( composition->customProperties().isEmpty() );
QCOMPARE( composition->customProperty( "noprop", "defaultval" ).toString(), QString( "defaultval" ) );
composition->setCustomProperty( QStringLiteral( "testprop1" ), "testval1" );
composition->setCustomProperty( QStringLiteral( "testprop2" ), "testval2" );
QStringList keys = composition->customProperties();
QCOMPARE( keys.length(), 2 );
QVERIFY( keys.contains( "testprop1" ) );
QVERIFY( keys.contains( "testprop2" ) );
delete composition;
}
void TestQgsComposition::writeRetrieveCustomProperties()
{
QgsComposition *composition = new QgsComposition( QgsProject::instance() );
composition->setCustomProperty( QStringLiteral( "testprop" ), "testval" );
composition->setCustomProperty( QStringLiteral( "testprop2" ), 5 );
//test writing composition with custom properties
QDomImplementation DomImplementation;
QDomDocumentType documentType =
DomImplementation.createDocumentType(
QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
QDomDocument doc( documentType );
QDomElement rootNode = doc.createElement( QStringLiteral( "qgis" ) );
QVERIFY( composition->writeXml( rootNode, doc ) );
//check if composition node was written
QDomNodeList evalNodeList = rootNode.elementsByTagName( QStringLiteral( "Composition" ) );
QCOMPARE( evalNodeList.count(), 1 );
QDomElement compositionElem = evalNodeList.at( 0 ).toElement();
//test reading node containing custom properties
QgsComposition *readComposition = new QgsComposition( QgsProject::instance() );
QVERIFY( readComposition->readXml( compositionElem, doc ) );
//test retrieved custom properties
QCOMPARE( readComposition->customProperties().length(), 2 );
QVERIFY( readComposition->customProperties().contains( QString( "testprop" ) ) );
QVERIFY( readComposition->customProperties().contains( QString( "testprop2" ) ) );
QCOMPARE( readComposition->customProperty( "testprop" ).toString(), QString( "testval" ) );
QCOMPARE( readComposition->customProperty( "testprop2" ).toInt(), 5 );
delete composition;
delete readComposition;
}
void TestQgsComposition::bounds()
{
//add some items to a composition
QgsComposition *composition = new QgsComposition( QgsProject::instance() );
QgsComposerShape *shape1 = new QgsComposerShape( composition );
shape1->setShapeType( QgsComposerShape::Rectangle );
composition->addComposerShape( shape1 );
shape1->setItemPosition( 90, 50, 90, 50, QgsComposerItem::UpperLeft, false, 1 );
shape1->setItemRotation( 45 );
QgsComposerShape *shape2 = new QgsComposerShape( composition );
shape2->setShapeType( QgsComposerShape::Rectangle );
composition->addComposerShape( shape2 );
shape2->setItemPosition( 100, 150, 110, 50, QgsComposerItem::UpperLeft, false, 1 );
QgsComposerShape *shape3 = new QgsComposerShape( composition );
shape3->setShapeType( QgsComposerShape::Rectangle );
composition->addComposerShape( shape3 );
shape3->setItemPosition( 210, 30, 50, 100, QgsComposerItem::UpperLeft, false, 2 );
QgsComposerShape *shape4 = new QgsComposerShape( composition );
shape4->setShapeType( QgsComposerShape::Rectangle );
composition->addComposerShape( shape4 );
shape4->setItemPosition( 10, 120, 50, 30, QgsComposerItem::UpperLeft, false, 2 );
shape4->setVisibility( false );
//check bounds
QRectF compositionBounds = composition->compositionBounds( false );
QGSCOMPARENEAR( compositionBounds.height(), 372.15, 0.01 );
QGSCOMPARENEAR( compositionBounds.width(), 301.00, 0.01 );
QGSCOMPARENEAR( compositionBounds.left(), -2, 0.01 );
QGSCOMPARENEAR( compositionBounds.top(), -2, 0.01 );
QRectF compositionBoundsNoPage = composition->compositionBounds( true );
QGSCOMPARENEAR( compositionBoundsNoPage.height(), 320.36, 0.01 );
QGSCOMPARENEAR( compositionBoundsNoPage.width(), 250.30, 0.01 );
QGSCOMPARENEAR( compositionBoundsNoPage.left(), 9.85, 0.01 );
QGSCOMPARENEAR( compositionBoundsNoPage.top(), 49.79, 0.01 );
QRectF page1Bounds = composition->pageItemBounds( 0, true );
QGSCOMPARENEAR( page1Bounds.height(), 150.36, 0.01 );
QGSCOMPARENEAR( page1Bounds.width(), 155.72, 0.01 );
QGSCOMPARENEAR( page1Bounds.left(), 54.43, 0.01 );
QGSCOMPARENEAR( page1Bounds.top(), 49.79, 0.01 );
QRectF page2Bounds = composition->pageItemBounds( 1, true );
QGSCOMPARENEAR( page2Bounds.height(), 100.30, 0.01 );
QGSCOMPARENEAR( page2Bounds.width(), 50.30, 0.01 );
QGSCOMPARENEAR( page2Bounds.left(), 209.85, 0.01 );
QGSCOMPARENEAR( page2Bounds.top(), 249.85, 0.01 );
QRectF page2BoundsWithHidden = composition->pageItemBounds( 1, false );
QGSCOMPARENEAR( page2BoundsWithHidden.height(), 120.30, 0.01 );
QGSCOMPARENEAR( page2BoundsWithHidden.width(), 250.30, 0.01 );
QGSCOMPARENEAR( page2BoundsWithHidden.left(), 9.85, 0.01 );
QGSCOMPARENEAR( page2BoundsWithHidden.top(), 249.85, 0.01 );
delete composition;
}
void TestQgsComposition::resizeToContents()
{
//add some items to a composition
QgsComposition *composition = new QgsComposition( QgsProject::instance() );
QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( Qt::yellow );
simpleFill->setStrokeColor( Qt::transparent );
composition->setPageStyleSymbol( fillSymbol );
delete fillSymbol;
QgsComposerShape *shape1 = new QgsComposerShape( composition );
shape1->setBackgroundColor( QColor::fromRgb( 255, 150, 100 ) );
shape1->setShapeType( QgsComposerShape::Rectangle );
composition->addComposerShape( shape1 );
shape1->setItemPosition( 90, 50, 90, 50, QgsComposerItem::UpperLeft, false, 1 );
shape1->setItemRotation( 45 );
QgsComposerShape *shape2 = new QgsComposerShape( composition );
shape2->setShapeType( QgsComposerShape::Rectangle );
shape2->setBackgroundColor( QColor::fromRgb( 255, 150, 100 ) );
composition->addComposerShape( shape2 );
shape2->setItemPosition( 100, 150, 110, 50, QgsComposerItem::UpperLeft, false, 1 );
QgsComposerShape *shape3 = new QgsComposerShape( composition );
shape3->setShapeType( QgsComposerShape::Rectangle );
shape3->setBackgroundColor( QColor::fromRgb( 255, 150, 100 ) );
composition->addComposerShape( shape3 );
shape3->setItemPosition( 210, 30, 50, 100, QgsComposerItem::UpperLeft, false, 1 );
//resize to contents, no margin
composition->resizePageToContents();
QgsCompositionChecker checker( QStringLiteral( "composition_bounds" ), composition );
checker.setSize( QSize( 774, 641 ) );
checker.setControlPathPrefix( QStringLiteral( "composition" ) );
QVERIFY( checker.testComposition( mReport ) );
delete composition;
}
void TestQgsComposition::resizeToContentsMargin()
{
//resize to contents, with margin
QgsComposition *composition = new QgsComposition( QgsProject::instance() );
QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( Qt::yellow );
simpleFill->setStrokeColor( Qt::transparent );
composition->setPageStyleSymbol( fillSymbol );
delete fillSymbol;
QgsComposerShape *shape1 = new QgsComposerShape( composition );
shape1->setBackgroundColor( QColor::fromRgb( 255, 150, 100 ) );
shape1->setShapeType( QgsComposerShape::Rectangle );
composition->addComposerShape( shape1 );
shape1->setItemPosition( 90, 50, 90, 50, QgsComposerItem::UpperLeft, false, 1 );
shape1->setItemRotation( 45 );
QgsComposerShape *shape2 = new QgsComposerShape( composition );
shape2->setShapeType( QgsComposerShape::Rectangle );
shape2->setBackgroundColor( QColor::fromRgb( 255, 150, 100 ) );
composition->addComposerShape( shape2 );
shape2->setItemPosition( 100, 150, 110, 50, QgsComposerItem::UpperLeft, false, 1 );
QgsComposerShape *shape3 = new QgsComposerShape( composition );
shape3->setShapeType( QgsComposerShape::Rectangle );
shape3->setBackgroundColor( QColor::fromRgb( 255, 150, 100 ) );
composition->addComposerShape( shape3 );
shape3->setItemPosition( 210, 30, 50, 100, QgsComposerItem::UpperLeft, false, 1 );
//resize to contents, with margin
composition->resizePageToContents( 30, 20, 50, 40 );
QgsCompositionChecker checker( QStringLiteral( "composition_bounds_margin" ), composition );
checker.setSize( QSize( 1000, 942 ) );
checker.setControlPathPrefix( QStringLiteral( "composition" ) );
QVERIFY( checker.testComposition( mReport ) );
delete composition;
}
void TestQgsComposition::resizeToContentsMultiPage()
{
//resize to contents with multi-page composition, should result in a single page
QgsComposition *composition = new QgsComposition( QgsProject::instance() );
QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( Qt::yellow );
simpleFill->setStrokeColor( Qt::transparent );
composition->setPageStyleSymbol( fillSymbol );
delete fillSymbol;
composition->setNumPages( 3 );
QgsComposerShape *shape1 = new QgsComposerShape( composition );
shape1->setBackgroundColor( QColor::fromRgb( 255, 150, 100 ) );
shape1->setShapeType( QgsComposerShape::Rectangle );
composition->addComposerShape( shape1 );
shape1->setItemPosition( 90, 50, 90, 50, QgsComposerItem::UpperLeft, false, 1 );
shape1->setItemRotation( 45 );
QgsComposerShape *shape2 = new QgsComposerShape( composition );
shape2->setShapeType( QgsComposerShape::Rectangle );
shape2->setBackgroundColor( QColor::fromRgb( 255, 150, 100 ) );
composition->addComposerShape( shape2 );
shape2->setItemPosition( 100, 150, 110, 50, QgsComposerItem::UpperLeft, false, 2 );
QgsComposerShape *shape3 = new QgsComposerShape( composition );
shape3->setShapeType( QgsComposerShape::Rectangle );
shape3->setBackgroundColor( QColor::fromRgb( 255, 150, 100 ) );
composition->addComposerShape( shape3 );
shape3->setItemPosition( 210, 30, 50, 100, QgsComposerItem::UpperLeft, false, 3 );
//resize to contents, no margin
composition->resizePageToContents();
QCOMPARE( composition->numPages(), 1 );
QgsCompositionChecker checker( QStringLiteral( "composition_bounds_multipage" ), composition );
checker.setSize( QSize( 394, 996 ) );
checker.setControlPathPrefix( QStringLiteral( "composition" ) );
QVERIFY( checker.testComposition( mReport ) );
delete composition;
}
void TestQgsComposition::georeference()
{
QgsRectangle extent( 2000, 2800, 2500, 2900 );
QgsComposition *composition = new QgsComposition( QgsProject::instance() );
// no map
double *t = composition->computeGeoTransform( nullptr );
QVERIFY( !t );
QgsComposerMap *map = new QgsComposerMap( composition );
map->setNewExtent( extent );
map->setSceneRect( QRectF( 30, 60, 200, 100 ) );
composition->addComposerMap( map );
t = composition->computeGeoTransform( map );
QGSCOMPARENEAR( t[0], 1925.0, 1.0 );
QGSCOMPARENEAR( t[1], 0.211719, 0.0001 );
QGSCOMPARENEAR( t[2], 0.0, 4 * DBL_EPSILON );
QGSCOMPARENEAR( t[3], 3200, 1 );
QGSCOMPARENEAR( t[4], 0.0, 4 * DBL_EPSILON );
QGSCOMPARENEAR( t[5], -0.211694, 0.0001 );
delete[] t;
// don't specify map
composition->setReferenceMap( map );
t = composition->computeGeoTransform();
QGSCOMPARENEAR( t[0], 1925.0, 1.0 );
QGSCOMPARENEAR( t[1], 0.211719, 0.0001 );
QGSCOMPARENEAR( t[2], 0.0, 4 * DBL_EPSILON );
QGSCOMPARENEAR( t[3], 3200, 1 );
QGSCOMPARENEAR( t[4], 0.0, 4 * DBL_EPSILON );
QGSCOMPARENEAR( t[5], -0.211694, 0.0001 );
delete[] t;
// specify extent
t = composition->computeGeoTransform( map, QRectF( 70, 100, 50, 60 ) );
QGSCOMPARENEAR( t[0], 2100.0, 1.0 );
QGSCOMPARENEAR( t[1], 0.211864, 0.0001 );
QGSCOMPARENEAR( t[2], 0.0, 4 * DBL_EPSILON );
QGSCOMPARENEAR( t[3], 2950, 1 );
QGSCOMPARENEAR( t[4], 0.0, 4 * DBL_EPSILON );
QGSCOMPARENEAR( t[5], -0.211864, 0.0001 );
delete[] t;
// specify dpi
t = composition->computeGeoTransform( map, QRectF(), 75 );
QGSCOMPARENEAR( t[0], 1925.0, 1 );
QGSCOMPARENEAR( t[1], 0.847603, 0.0001 );
QGSCOMPARENEAR( t[2], 0.0, 4 * DBL_EPSILON );
QGSCOMPARENEAR( t[3], 3200.0, 1 );
QGSCOMPARENEAR( t[4], 0.0, 4 * DBL_EPSILON );
QGSCOMPARENEAR( t[5], -0.846774, 0.0001 );
delete[] t;
// rotation
map->setMapRotation( 45 );
t = composition->computeGeoTransform( map );
QGSCOMPARENEAR( t[0], 1825.7, 1 );
QGSCOMPARENEAR( t[1], 0.149708, 0.0001 );
QGSCOMPARENEAR( t[2], 0.149708, 0.0001 );
QGSCOMPARENEAR( t[3], 2889.64, 1 );
QGSCOMPARENEAR( t[4], 0.14969, 0.0001 );
QGSCOMPARENEAR( t[5], -0.14969, 0.0001 );
delete[] t;
delete composition;
}
void TestQgsComposition::variablesEdited()
{
QgsComposition c( QgsProject::instance() );
QSignalSpy spyVariablesChanged( &c, SIGNAL( variablesChanged() ) );
c.setCustomProperty( QStringLiteral( "not a variable" ), "1" );
QVERIFY( spyVariablesChanged.count() == 0 );
c.setCustomProperty( QStringLiteral( "variableNames" ), "1" );
QVERIFY( spyVariablesChanged.count() == 1 );
c.setCustomProperty( QStringLiteral( "variableValues" ), "1" );
QVERIFY( spyVariablesChanged.count() == 2 );
}
void TestQgsComposition::itemVariablesFunction()
{
QgsRectangle extent( 2000, 2800, 2500, 2900 );
QgsComposition *composition = new QgsComposition( QgsProject::instance() );
QgsExpression e( QStringLiteral( "map_get( item_variables( 'map_id' ), 'map_scale' )" ) );
// no map
QgsExpressionContext c = composition->createExpressionContext();
QVariant r = e.evaluate( &c );
QVERIFY( !r.isValid() );
QgsComposerMap *map = new QgsComposerMap( composition );
map->setNewExtent( extent );
map->setSceneRect( QRectF( 30, 60, 200, 100 ) );
map->setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) );
composition->addComposerMap( map );
map->setId( QStringLiteral( "map_id" ) );
c = composition->createExpressionContext();
r = e.evaluate( &c );
QGSCOMPARENEAR( r.toDouble(), 1.38916e+08, 100 );
QgsExpression e2( QStringLiteral( "map_get( item_variables( 'map_id' ), 'map_crs' )" ) );
r = e2.evaluate( &c );
QCOMPARE( r.toString(), QString( "EPSG:4326" ) );
QgsExpression e3( QStringLiteral( "map_get( item_variables( 'map_id' ), 'map_crs_definition' )" ) );
r = e3.evaluate( &c );
QCOMPARE( r.toString(), QString( "+proj=longlat +datum=WGS84 +no_defs" ) );
QgsExpression e4( QStringLiteral( "map_get( item_variables( 'map_id' ), 'map_units' )" ) );
r = e4.evaluate( &c );
QCOMPARE( r.toString(), QString( "degrees" ) );
delete composition;
}
void TestQgsComposition::referenceMap()
{
QgsRectangle extent( 2000, 2800, 2500, 2900 );
QgsComposition *composition = new QgsComposition( QgsProject::instance() );
// no maps
QVERIFY( !composition->referenceMap() );
QgsComposerMap *map = new QgsComposerMap( composition );
map->setNewExtent( extent );
map->setSceneRect( QRectF( 30, 60, 200, 100 ) );
composition->addComposerMap( map );
QCOMPARE( composition->referenceMap(), map );
// add a larger map
QgsComposerMap *map2 = new QgsComposerMap( composition );
map2->setNewExtent( extent );
map2->setSceneRect( QRectF( 30, 60, 250, 150 ) );
composition->addComposerMap( map2 );
QCOMPARE( composition->referenceMap(), map2 );
// explicitly set reference map
composition->setReferenceMap( map );
QCOMPARE( composition->referenceMap(), map );
delete composition;
}
void TestQgsComposition::legendRestoredFromTemplate()
{
// load a layer
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points.shp" );
QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsProject p;
p.addMapLayer( layer );
// create composition
QgsComposition c( &p );
// add a legend
QgsComposerLegend *legend = new QgsComposerLegend( &c );
c.addComposerLegend( legend );
legend->setAutoUpdateModel( false );
QgsLegendModel *model = legend->model();
QgsLayerTreeNode *node = model->rootGroup()->children().at( 0 );
// make sure we've got right node
QgsLayerTreeLayer *layerNode = dynamic_cast< QgsLayerTreeLayer * >( node );
QVERIFY( layerNode );
QCOMPARE( layerNode->layer(), layer );
// got it!
layerNode->setCustomProperty( QStringLiteral( "legend/title-label" ), QStringLiteral( "new title!" ) );
// make sure new title stuck
QCOMPARE( model->data( model->node2index( layerNode ), Qt::DisplayRole ).toString(), QString( "new title!" ) );
// save composition to template
QDomDocument doc;
QDomElement composerElem = doc.createElement( QStringLiteral( "Composer" ) );
doc.appendChild( composerElem );
c.writeXml( composerElem, doc );
c.atlasComposition().writeXml( composerElem, doc );
// make a new composition from template
QgsComposition c2( &p );
QVERIFY( c2.loadFromTemplate( doc ) );
// get legend from new composition
QList< QgsComposerLegend * > legends2;
c2.composerItems( legends2 );
QgsComposerLegend *legend2 = legends2.at( 0 );
QVERIFY( legend2 );
QgsLegendModel *model2 = legend2->model();
QgsLayerTreeNode *node2 = model2->rootGroup()->children().at( 0 );
QgsLayerTreeLayer *layerNode2 = dynamic_cast< QgsLayerTreeLayer * >( node2 );
QVERIFY( layerNode2 );
QCOMPARE( layerNode2->layer(), layer );
QCOMPARE( model2->data( model->node2index( layerNode2 ), Qt::DisplayRole ).toString(), QString( "new title!" ) );
QString oldId = layer->id();
// new test
// remove existing layer
p.removeMapLayer( layer );
// reload it, with a new id
QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
p.addMapLayer( layer2 );
QVERIFY( oldId != layer2->id() );
// load composition from template
QgsComposition c3( &p );
QVERIFY( c3.loadFromTemplate( doc ) );
// get legend from new composition
QList< QgsComposerLegend * > legends3;
c3.composerItems( legends3 );
QgsComposerLegend *legend3 = legends3.at( 0 );
QVERIFY( legend3 );
//make sure customisation remains intact
QgsLegendModel *model3 = legend3->model();
QgsLayerTreeNode *node3 = model3->rootGroup()->children().at( 0 );
QgsLayerTreeLayer *layerNode3 = dynamic_cast< QgsLayerTreeLayer * >( node3 );
QVERIFY( layerNode3 );
QCOMPARE( layerNode3->layer(), layer2 );
QCOMPARE( model3->data( model->node2index( layerNode3 ), Qt::DisplayRole ).toString(), QString( "new title!" ) );
}
void TestQgsComposition::legendRestoredFromTemplateAutoUpdate()
{
// load a layer
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points.shp" );
QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsProject p;
p.addMapLayer( layer );
// create composition
QgsComposition c( &p );
// add a legend
QgsComposerLegend *legend = new QgsComposerLegend( &c );
c.addComposerLegend( legend );
legend->setAutoUpdateModel( true );
QgsLegendModel *model = legend->model();
QgsLayerTreeNode *node = model->rootGroup()->children().at( 0 );
// make sure we've got right node
QgsLayerTreeLayer *layerNode = dynamic_cast< QgsLayerTreeLayer * >( node );
QVERIFY( layerNode );
QCOMPARE( layerNode->layer(), layer );
QCOMPARE( model->data( model->node2index( layerNode ), Qt::DisplayRole ).toString(), QString( "points" ) );
// save composition to template
QDomDocument doc;
QDomElement composerElem = doc.createElement( QStringLiteral( "Composer" ) );
doc.appendChild( composerElem );
c.writeXml( composerElem, doc );
c.atlasComposition().writeXml( composerElem, doc );
//new project
QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsProject p2;
p2.addMapLayer( layer2 );
// make a new composition from template
QgsComposition c2( &p2 );
QVERIFY( c2.loadFromTemplate( doc ) );
// get legend from new composition
QList< QgsComposerLegend * > legends2;
c2.composerItems( legends2 );
QgsComposerLegend *legend2 = legends2.at( 0 );
QVERIFY( legend2 );
QgsLegendModel *model2 = legend2->model();
QgsLayerTreeNode *node2 = model2->rootGroup()->children().at( 0 );
QgsLayerTreeLayer *layerNode2 = dynamic_cast< QgsLayerTreeLayer * >( node2 );
QVERIFY( layerNode2 );
QCOMPARE( layerNode2->layer(), layer2 );
QCOMPARE( model2->data( model->node2index( layerNode2 ), Qt::DisplayRole ).toString(), QString( "points" ) );
}
void TestQgsComposition::attributeTableRestoredFromTemplate()
{
// load some layers
@ -860,164 +150,5 @@ void TestQgsComposition::attributeTableRestoredFromTemplate()
QCOMPARE( table2->vectorLayer(), layer3 );
}
void TestQgsComposition::mapLayersRestoredFromTemplate()
{
// load some layers
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points.shp" );
QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QFileInfo vectorFileInfo2( QStringLiteral( TEST_DATA_DIR ) + "/polys.shp" );
QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo2.filePath(),
vectorFileInfo2.completeBaseName(),
QStringLiteral( "ogr" ) );
QFileInfo rasterFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/landsat.tif" );
QgsRasterLayer *rl = new QgsRasterLayer( rasterFileInfo.filePath(),
rasterFileInfo.completeBaseName() );
QgsProject p;
p.addMapLayer( layer2 );
p.addMapLayer( layer );
p.addMapLayer( rl );
// create composition
QgsComposition c( &p );
// add a map
QgsComposerMap *map = new QgsComposerMap( &c, 1, 1, 10, 10 );
c.addComposerMap( map );
map->setLayers( QList<QgsMapLayer *>() << layer << layer2 << rl );
// save composition to template
QDomDocument doc;
QDomElement composerElem = doc.createElement( QStringLiteral( "Composer" ) );
doc.appendChild( composerElem );
c.writeXml( composerElem, doc );
c.atlasComposition().writeXml( composerElem, doc );
// new project
QgsProject p2;
QgsVectorLayer *layer3 = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsVectorLayer *layer4 = new QgsVectorLayer( vectorFileInfo2.filePath(),
vectorFileInfo2.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsRasterLayer *rl5 = new QgsRasterLayer( rasterFileInfo.filePath(),
rasterFileInfo.completeBaseName() );
p2.addMapLayer( layer4 );
p2.addMapLayer( layer3 );
p2.addMapLayer( rl5 );
// make a new composition from template
QgsComposition c2( &p2 );
QVERIFY( c2.loadFromTemplate( doc ) );
// get map from new composition
QList< QgsComposerMap * > maps;
c2.composerItems( maps );
QgsComposerMap *map2 = static_cast< QgsComposerMap *>( maps.at( 0 ) );
QVERIFY( map2 );
QCOMPARE( map2->layers(), QList<QgsMapLayer *>() << layer3 << layer4 << rl5 );
}
void TestQgsComposition::mapLayersStyleOverrideRestoredFromTemplate()
{
// load some layers
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points.shp" );
QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QFileInfo vectorFileInfo2( QStringLiteral( TEST_DATA_DIR ) + "/polys.shp" );
QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo2.filePath(),
vectorFileInfo2.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsProject p;
p.addMapLayer( layer2 );
p.addMapLayer( layer );
// create composition
QgsComposition c( &p );
// add a map
QgsComposerMap *map = new QgsComposerMap( &c, 1, 1, 10, 10 );
c.addComposerMap( map );
map->setKeepLayerStyles( true );
QgsStringMap styles;
// just close your eyes and pretend these are real styles
styles.insert( layer->id(), QStringLiteral( "<b>xxxxx</b>" ) );
styles.insert( layer2->id(), QStringLiteral( "<blink>yyyyy</blink>" ) );
map->setLayerStyleOverrides( styles );
// save composition to template
QDomDocument doc;
QDomElement composerElem = doc.createElement( QStringLiteral( "Composer" ) );
doc.appendChild( composerElem );
c.writeXml( composerElem, doc );
c.atlasComposition().writeXml( composerElem, doc );
// new project
QgsProject p2;
QgsVectorLayer *layer3 = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsVectorLayer *layer4 = new QgsVectorLayer( vectorFileInfo2.filePath(),
vectorFileInfo2.completeBaseName(),
QStringLiteral( "ogr" ) );
p2.addMapLayer( layer4 );
p2.addMapLayer( layer3 );
// make a new composition from template
QgsComposition c2( &p2 );
QVERIFY( c2.loadFromTemplate( doc ) );
// get map from new composition
QList< QgsComposerMap * > maps;
c2.composerItems( maps );
QgsComposerMap *map2 = static_cast< QgsComposerMap *>( maps.at( 0 ) );
QVERIFY( map2 );
QVERIFY( map2->keepLayerStyles() );
QgsStringMap restoredStyles = map2->layerStyleOverrides();
QVERIFY( restoredStyles.contains( layer3->id() ) );
QCOMPARE( restoredStyles.value( layer3->id() ).trimmed(), QStringLiteral( "<b>xxxxx</b>" ) );
QVERIFY( restoredStyles.contains( layer4->id() ) );
QCOMPARE( restoredStyles.value( layer4->id() ).trimmed(), QStringLiteral( "<blink>yyyyy</blink>" ) );
}
void TestQgsComposition::atlasLayerRestoredFromTemplate()
{
// load some layers
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points.shp" );
QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsProject p;
p.addMapLayer( layer );
// create composition
QgsComposition c( &p );
// set atlas layer
c.atlasComposition().setEnabled( true );
c.atlasComposition().setCoverageLayer( layer );
// save composition to template
QDomDocument doc;
QDomElement composerElem = doc.createElement( QStringLiteral( "Composer" ) );
doc.appendChild( composerElem );
c.writeXml( composerElem, doc );
c.atlasComposition().writeXml( composerElem, doc );
// new project
QgsProject p2;
QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
p2.addMapLayer( layer2 );
// make a new composition from template
QgsComposition c2( &p2 );
QVERIFY( c2.loadFromTemplate( doc ) );
// check atlas layer
QCOMPARE( c2.atlasComposition().coverageLayer(), layer2 );
}
QGSTEST_MAIN( TestQgsComposition )
#include "testqgscomposition.moc"

View File

@ -28,6 +28,11 @@
#include "qgslayoutframe.h"
#include "qgsprintlayout.h"
#include "qgslayoutatlas.h"
#include "qgsreadwritecontext.h"
#include "qgslayoutitemlegend.h"
#include "qgslayertree.h"
#include "qgslayoutitemattributetable.h"
#include "qgsrasterlayer.h"
class TestQgsLayout: public QObject
{
@ -42,6 +47,7 @@ class TestQgsLayout: public QObject
void units();
void name();
void customProperties();
void writeRetrieveCustomProperties();
void variablesEdited();
void scope();
void referenceMap();
@ -57,6 +63,12 @@ class TestQgsLayout: public QObject
void clear();
void georeference();
void clone();
void legendRestoredFromTemplate();
void legendRestoredFromTemplateAutoUpdate();
// void attributeTableRestoredFromTemplate();
void mapLayersRestoredFromTemplate();
void mapLayersStyleOverrideRestoredFromTemplate();
void atlasLayerRestoredFromTemplate();
private:
QString mReport;
@ -65,6 +77,9 @@ class TestQgsLayout: public QObject
void TestQgsLayout::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
mReport = QStringLiteral( "<h1>Layout Tests</h1>\n" );
}
@ -78,6 +93,7 @@ void TestQgsLayout::cleanupTestCase()
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}
void TestQgsLayout::init()
@ -186,6 +202,33 @@ void TestQgsLayout::customProperties()
delete layout;
}
void TestQgsLayout::writeRetrieveCustomProperties()
{
QgsLayout layout( QgsProject::instance() );
layout.setCustomProperty( QStringLiteral( "testprop" ), "testval" );
layout.setCustomProperty( QStringLiteral( "testprop2" ), 5 );
//test writing composition with custom properties
QDomImplementation DomImplementation;
QDomDocumentType documentType =
DomImplementation.createDocumentType(
QStringLiteral( "qgis" ), QStringLiteral( "http://mrcc.com/qgis.dtd" ), QStringLiteral( "SYSTEM" ) );
QDomDocument doc( documentType );
QDomElement layoutNode = layout.writeXml( doc, QgsReadWriteContext() );
QVERIFY( !layoutNode.isNull() );
//test reading node containing custom properties
QgsLayout readLayout( QgsProject::instance() );
QVERIFY( readLayout.readXml( layoutNode, doc, QgsReadWriteContext() ) );
//test retrieved custom properties
QCOMPARE( readLayout.customProperties().length(), 2 );
QVERIFY( readLayout.customProperties().contains( QString( "testprop" ) ) );
QVERIFY( readLayout.customProperties().contains( QString( "testprop2" ) ) );
QCOMPARE( readLayout.customProperty( "testprop" ).toString(), QString( "testval" ) );
QCOMPARE( readLayout.customProperty( "testprop2" ).toInt(), 5 );
}
void TestQgsLayout::variablesEdited()
{
QgsProject p;
@ -886,5 +929,343 @@ void TestQgsLayout::clone()
}
void TestQgsLayout::legendRestoredFromTemplate()
{
// load a layer
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points.shp" );
QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QVERIFY( layer->isValid() );
QgsProject p;
p.addMapLayer( layer );
// create layout
QgsLayout c( &p );
// add a legend
QgsLayoutItemLegend *legend = new QgsLayoutItemLegend( &c );
c.addLayoutItem( legend );
legend->setAutoUpdateModel( false );
QgsLegendModel *model = legend->model();
QgsLayerTreeNode *node = model->rootGroup()->children().at( 0 );
// make sure we've got right node
QgsLayerTreeLayer *layerNode = dynamic_cast< QgsLayerTreeLayer * >( node );
QVERIFY( layerNode );
QCOMPARE( layerNode->layer(), layer );
// got it!
layerNode->setCustomProperty( QStringLiteral( "legend/title-label" ), QStringLiteral( "new title!" ) );
// make sure new title stuck
QCOMPARE( model->data( model->node2index( layerNode ), Qt::DisplayRole ).toString(), QString( "new title!" ) );
// save composition to template
QDomDocument doc;
doc.appendChild( c.writeXml( doc, QgsReadWriteContext() ) );
// make a new composition from template
QgsLayout c2( &p );
c2.loadFromTemplate( doc, QgsReadWriteContext() );
// get legend from new composition
QList< QgsLayoutItemLegend * > legends2;
c2.layoutItems( legends2 );
QgsLayoutItemLegend *legend2 = legends2.at( 0 );
QVERIFY( legend2 );
QgsLegendModel *model2 = legend2->model();
QgsLayerTreeNode *node2 = model2->rootGroup()->children().at( 0 );
QgsLayerTreeLayer *layerNode2 = dynamic_cast< QgsLayerTreeLayer * >( node2 );
QVERIFY( layerNode2 );
QCOMPARE( layerNode2->layer(), layer );
QCOMPARE( model2->data( model->node2index( layerNode2 ), Qt::DisplayRole ).toString(), QString( "new title!" ) );
QString oldId = layer->id();
// new test
// remove existing layer
p.removeMapLayer( layer );
// reload it, with a new id
QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
p.addMapLayer( layer2 );
QVERIFY( oldId != layer2->id() );
// load composition from template
QgsLayout c3( &p );
c3.loadFromTemplate( doc, QgsReadWriteContext() );
// get legend from new composition
QList< QgsLayoutItemLegend * > legends3;
c3.layoutItems( legends3 );
QgsLayoutItemLegend *legend3 = legends3.at( 0 );
QVERIFY( legend3 );
//make sure customisation remains intact
QgsLegendModel *model3 = legend3->model();
QgsLayerTreeNode *node3 = model3->rootGroup()->children().at( 0 );
QgsLayerTreeLayer *layerNode3 = dynamic_cast< QgsLayerTreeLayer * >( node3 );
QVERIFY( layerNode3 );
QCOMPARE( layerNode3->layer(), layer2 );
QCOMPARE( model3->data( model->node2index( layerNode3 ), Qt::DisplayRole ).toString(), QString( "new title!" ) );
}
void TestQgsLayout::legendRestoredFromTemplateAutoUpdate()
{
// load a layer
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points.shp" );
QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsProject p;
p.addMapLayer( layer );
// create composition
QgsLayout c( &p );
// add a legend
QgsLayoutItemLegend *legend = new QgsLayoutItemLegend( &c );
c.addLayoutItem( legend );
legend->setAutoUpdateModel( true );
QgsLegendModel *model = legend->model();
QgsLayerTreeNode *node = model->rootGroup()->children().at( 0 );
// make sure we've got right node
QgsLayerTreeLayer *layerNode = dynamic_cast< QgsLayerTreeLayer * >( node );
QVERIFY( layerNode );
QCOMPARE( layerNode->layer(), layer );
QCOMPARE( model->data( model->node2index( layerNode ), Qt::DisplayRole ).toString(), QString( "points" ) );
// save composition to template
QDomDocument doc;
doc.appendChild( c.writeXml( doc, QgsReadWriteContext() ) );
//new project
QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsProject p2;
p2.addMapLayer( layer2 );
// make a new composition from template
QgsLayout c2( &p2 );
c2.loadFromTemplate( doc, QgsReadWriteContext() );
// get legend from new composition
QList< QgsLayoutItemLegend * > legends2;
c2.layoutItems( legends2 );
QgsLayoutItemLegend *legend2 = legends2.at( 0 );
QVERIFY( legend2 );
QgsLegendModel *model2 = legend2->model();
QgsLayerTreeNode *node2 = model2->rootGroup()->children().at( 0 );
QgsLayerTreeLayer *layerNode2 = dynamic_cast< QgsLayerTreeLayer * >( node2 );
QVERIFY( layerNode2 );
QCOMPARE( layerNode2->layer(), layer2 );
QCOMPARE( model2->data( model->node2index( layerNode2 ), Qt::DisplayRole ).toString(), QString( "points" ) );
}
#if 0 //TODO
void TestQgsLayout::attributeTableRestoredFromTemplate()
{
// load some layers
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points.shp" );
QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsVectorLayer *layer2 = new QgsVectorLayer( QStringLiteral( "Point" ), QStringLiteral( "memory" ), QStringLiteral( "memory" ) );
QgsProject p;
p.addMapLayer( layer2 );
p.addMapLayer( layer );
// create composition
QgsLayout c( &p );
// add an attribute table
QgsLayoutItemAttributeTable *table = new QgsLayoutItemAttributeTable( &c );
c.addMultiFrame( table );
table->setVectorLayer( layer );
QgsLayoutFrame *frame = new QgsLayoutFrame( &c, table );
frame->attemptSetSceneRect( QRectF( 1, 1, 10, 10 ) );
c.addLayoutItem( frame );
table->addFrame( frame );
// save composition to template
QDomDocument doc;
doc.appendChild( c.writeXml( doc, QgsReadWriteContext() ) );
// new project
QgsProject p2;
QgsVectorLayer *layer3 = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsVectorLayer *layer4 = new QgsVectorLayer( QStringLiteral( "Point" ), QStringLiteral( "memory" ), QStringLiteral( "memory" ) );
p2.addMapLayer( layer4 );
p2.addMapLayer( layer3 );
// make a new composition from template
QgsLayout c2( &p2 );
c2.loadFromTemplate( doc, QgsReadWriteContext() );
// get table from new composition
QList< QgsLayoutFrame * > frames2;
c2.layoutItems( frames2 );
QgsLayoutItemAttributeTable *table2 = static_cast< QgsLayoutItemAttributeTable *>( frames2.at( 0 )->multiFrame() );
QVERIFY( table2 );
QCOMPARE( table2->vectorLayer(), layer3 );
}
#endif
void TestQgsLayout::mapLayersRestoredFromTemplate()
{
// load some layers
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points.shp" );
QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QFileInfo vectorFileInfo2( QStringLiteral( TEST_DATA_DIR ) + "/polys.shp" );
QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo2.filePath(),
vectorFileInfo2.completeBaseName(),
QStringLiteral( "ogr" ) );
QFileInfo rasterFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/landsat.tif" );
QgsRasterLayer *rl = new QgsRasterLayer( rasterFileInfo.filePath(),
rasterFileInfo.completeBaseName() );
QgsProject p;
p.addMapLayer( layer2 );
p.addMapLayer( layer );
p.addMapLayer( rl );
// create composition
QgsLayout c( &p );
// add a map
QgsLayoutItemMap *map = new QgsLayoutItemMap( &c );
map->attemptSetSceneRect( QRectF( 1, 1, 10, 10 ) );
c.addLayoutItem( map );
map->setLayers( QList<QgsMapLayer *>() << layer << layer2 << rl );
// save composition to template
QDomDocument doc;
doc.appendChild( c.writeXml( doc, QgsReadWriteContext() ) );
// new project
QgsProject p2;
QgsVectorLayer *layer3 = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsVectorLayer *layer4 = new QgsVectorLayer( vectorFileInfo2.filePath(),
vectorFileInfo2.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsRasterLayer *rl5 = new QgsRasterLayer( rasterFileInfo.filePath(),
rasterFileInfo.completeBaseName() );
p2.addMapLayer( layer4 );
p2.addMapLayer( layer3 );
p2.addMapLayer( rl5 );
// make a new composition from template
QgsLayout c2( &p2 );
c2.loadFromTemplate( doc, QgsReadWriteContext() );
// get map from new composition
QList< QgsLayoutItemMap * > maps;
c2.layoutItems( maps );
QgsLayoutItemMap *map2 = static_cast< QgsLayoutItemMap *>( maps.at( 0 ) );
QVERIFY( map2 );
QCOMPARE( map2->layers(), QList<QgsMapLayer *>() << layer3 << layer4 << rl5 );
}
void TestQgsLayout::mapLayersStyleOverrideRestoredFromTemplate()
{
// load some layers
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points.shp" );
QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QFileInfo vectorFileInfo2( QStringLiteral( TEST_DATA_DIR ) + "/polys.shp" );
QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo2.filePath(),
vectorFileInfo2.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsProject p;
p.addMapLayer( layer2 );
p.addMapLayer( layer );
// create composition
QgsLayout c( &p );
// add a map
QgsLayoutItemMap *map = new QgsLayoutItemMap( &c );
map->attemptSetSceneRect( QRectF( 1, 1, 10, 10 ) );
c.addLayoutItem( map );
map->setKeepLayerStyles( true );
QgsStringMap styles;
// just close your eyes and pretend these are real styles
styles.insert( layer->id(), QStringLiteral( "<b>xxxxx</b>" ) );
styles.insert( layer2->id(), QStringLiteral( "<blink>yyyyy</blink>" ) );
map->setLayerStyleOverrides( styles );
// save composition to template
QDomDocument doc;
doc.appendChild( c.writeXml( doc, QgsReadWriteContext() ) );
// new project
QgsProject p2;
QgsVectorLayer *layer3 = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsVectorLayer *layer4 = new QgsVectorLayer( vectorFileInfo2.filePath(),
vectorFileInfo2.completeBaseName(),
QStringLiteral( "ogr" ) );
p2.addMapLayer( layer4 );
p2.addMapLayer( layer3 );
// make a new composition from template
QgsLayout c2( &p2 );
c2.loadFromTemplate( doc, QgsReadWriteContext() );
// get map from new composition
QList< QgsLayoutItemMap * > maps;
c2.layoutItems( maps );
QgsLayoutItemMap *map2 = static_cast< QgsLayoutItemMap *>( maps.at( 0 ) );
QVERIFY( map2 );
QVERIFY( map2->keepLayerStyles() );
QgsStringMap restoredStyles = map2->layerStyleOverrides();
QVERIFY( restoredStyles.contains( layer3->id() ) );
QCOMPARE( restoredStyles.value( layer3->id() ).trimmed(), QStringLiteral( "<b>xxxxx</b>" ) );
QVERIFY( restoredStyles.contains( layer4->id() ) );
QCOMPARE( restoredStyles.value( layer4->id() ).trimmed(), QStringLiteral( "<blink>yyyyy</blink>" ) );
}
void TestQgsLayout::atlasLayerRestoredFromTemplate()
{
// load some layers
QFileInfo vectorFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/points.shp" );
QgsVectorLayer *layer = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
QgsProject p;
p.addMapLayer( layer );
// create composition
QgsPrintLayout c( &p );
// set atlas layer
c.atlas()->setEnabled( true );
c.atlas()->setCoverageLayer( layer );
// save composition to template
QDomDocument doc;
doc.appendChild( c.writeXml( doc, QgsReadWriteContext() ) );
// new project
QgsProject p2;
QgsVectorLayer *layer2 = new QgsVectorLayer( vectorFileInfo.filePath(),
vectorFileInfo.completeBaseName(),
QStringLiteral( "ogr" ) );
p2.addMapLayer( layer2 );
// make a new composition from template
QgsPrintLayout c2( &p2 );
c2.loadFromTemplate( doc, QgsReadWriteContext() );
// check atlas layer
QCOMPARE( c2.atlas()->coverageLayer(), layer2 );
}
QGSTEST_MAIN( TestQgsLayout )
#include "testqgslayout.moc"

View File

@ -1842,6 +1842,36 @@ void TestQgsLayoutItem::blendMode()
item->refreshDataDefinedProperty();
QCOMPARE( item->blendMode(), QPainter::CompositionMode_Darken ); // should not change
QCOMPARE( item->mEffect->compositionMode(), QPainter::CompositionMode_Lighten );
QgsLayout l2( QgsProject::instance() );
l2.initializeDefaults();
QgsLayoutItemShape *mComposerRect1 = new QgsLayoutItemShape( &l2 );
mComposerRect1->attemptSetSceneRect( QRectF( 20, 20, 150, 100 ) );
mComposerRect1->setShapeType( QgsLayoutItemShape::Rectangle );
QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( QColor( 255, 150, 0 ) );
mComposerRect1->setSymbol( fillSymbol );
delete fillSymbol;
l2.addLayoutItem( mComposerRect1 );
QgsLayoutItemShape *mComposerRect2 = new QgsLayoutItemShape( &l2 );
mComposerRect2->attemptSetSceneRect( QRectF( 50, 50, 150, 100 ) );
mComposerRect2->setShapeType( QgsLayoutItemShape::Rectangle );
l2.addLayoutItem( mComposerRect2 );
QgsSimpleFillSymbolLayer *simpleFill2 = new QgsSimpleFillSymbolLayer();
QgsFillSymbol *fillSymbol2 = new QgsFillSymbol();
fillSymbol2->changeSymbolLayer( 0, simpleFill2 );
simpleFill2->setColor( QColor( 0, 100, 150 ) );
mComposerRect2->setSymbol( fillSymbol2 );
delete fillSymbol2;
mComposerRect2->setBlendMode( QPainter::CompositionMode_Multiply );
QgsLayoutChecker checker( QStringLiteral( "composereffects_blend" ), &l2 );
checker.setControlPathPrefix( QStringLiteral( "composer_effects" ) );
QVERIFY( checker.testLayout( mReport ) );
}
void TestQgsLayoutItem::opacity()
@ -1860,6 +1890,37 @@ void TestQgsLayoutItem::opacity()
item->refreshDataDefinedProperty();
QCOMPARE( item->itemOpacity(), 0.75 ); // should not change
QCOMPARE( item->opacity(), 0.35 );
QgsLayout l2( QgsProject::instance() );
l2.initializeDefaults();
QgsLayoutItemShape *mComposerRect1 = new QgsLayoutItemShape( &l2 );
mComposerRect1->attemptSetSceneRect( QRectF( 20, 20, 150, 100 ) );
mComposerRect1->setShapeType( QgsLayoutItemShape::Rectangle );
QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( QColor( 255, 150, 0 ) );
mComposerRect1->setSymbol( fillSymbol );
delete fillSymbol;
l2.addLayoutItem( mComposerRect1 );
QgsLayoutItemShape *mComposerRect2 = new QgsLayoutItemShape( &l2 );
mComposerRect2->attemptSetSceneRect( QRectF( 50, 50, 150, 100 ) );
mComposerRect2->setShapeType( QgsLayoutItemShape::Rectangle );
l2.addLayoutItem( mComposerRect2 );
QgsSimpleFillSymbolLayer *simpleFill2 = new QgsSimpleFillSymbolLayer();
QgsFillSymbol *fillSymbol2 = new QgsFillSymbol();
fillSymbol2->changeSymbolLayer( 0, simpleFill2 );
simpleFill2->setColor( QColor( 0, 100, 150 ) );
mComposerRect2->setSymbol( fillSymbol2 );
delete fillSymbol2;
mComposerRect2->setItemOpacity( 0.5 );
QgsLayoutChecker checker( QStringLiteral( "composereffects_transparency" ), &l2 );
checker.setControlPathPrefix( QStringLiteral( "composer_effects" ) );
QVERIFY( checker.testLayout( mReport ) );
}
void TestQgsLayoutItem::excludeFromExports()

View File

@ -54,6 +54,7 @@ class TestQgsLayoutLabel : public QObject
void render();
void renderAsHtml();
void renderAsHtmlRelative();
void labelRotation();
private:
QgsVectorLayer *mVectorLayer = nullptr;
@ -316,5 +317,25 @@ void TestQgsLayoutLabel::renderAsHtmlRelative()
QVERIFY( checker.testLayout( mReport, 0, 0 ) );
}
void TestQgsLayoutLabel::labelRotation()
{
QgsLayout l( QgsProject::instance() );
l.initializeDefaults();
QgsLayoutItemLabel *label = new QgsLayoutItemLabel( &l );
label->setMargin( 1 );
l.addLayoutItem( label );
label->setText( QStringLiteral( "test label" ) );
label->setFont( QgsFontUtils::getStandardTestFont( QStringLiteral( "Bold" ), 30 ) );
label->attemptMove( QgsLayoutPoint( 70, 70 ) );
label->adjustSizeToText();
label->setBackgroundColor( QColor::fromRgb( 255, 150, 0 ) );
label->setBackgroundEnabled( true );
label->setItemRotation( 135 );
QgsLayoutChecker checker( QStringLiteral( "layoutrotation_label" ), &l );
checker.setControlPathPrefix( QStringLiteral( "composer_items" ) );
QVERIFY( checker.testLayout( mReport, 0, 0 ) );
}
QGSTEST_MAIN( TestQgsLayoutLabel )
#include "testqgslayoutlabel.moc"

View File

@ -29,6 +29,7 @@
#include "qgsproperty.h"
#include "qgslayoutpagecollection.h"
#include "qgslayoutitempolyline.h"
#include "qgsreadwritecontext.h"
#include <QObject>
#include "qgstest.h"
@ -46,9 +47,7 @@ class TestQgsLayoutMap : public QObject
void cleanup();// will be called after every testfunction.
void id();
void render();
#if 0
void uniqueId(); //test if map id is adapted when doing copy paste
#endif
void worldFileGeneration(); // test world file generation
void mapPolygonVertices(); // test mapPolygon function with no map rotation
@ -56,6 +55,8 @@ class TestQgsLayoutMap : public QObject
void dataDefinedStyles(); //test data defined styles
void rasterized();
void layersToRender();
void mapRotation();
void mapItemRotation();
private:
QgsRasterLayer *mRasterLayer = nullptr;
@ -164,21 +165,26 @@ void TestQgsLayoutMap::render()
QVERIFY( checker.testLayout( mReport, 0, 0 ) );
}
#if 0
void TestQgsLayoutMap::uniqueId()
{
QgsLayout l( QgsProject::instance() );
l.initializeDefaults();
QgsLayoutItemMap *map = new QgsLayoutItemMap( &l );
l.addLayoutItem( map );
QDomDocument doc;
QDomElement documentElement = doc.createElement( QStringLiteral( "ComposerItemClipboard" ) );
mComposerMap->writeXml( documentElement, doc );
mComposition->addItemsFromXml( documentElement, doc, false );
map->writeXml( documentElement, doc, QgsReadWriteContext() );
l.addItemsFromXml( documentElement, doc, QgsReadWriteContext() );
//test if both composer maps have different ids
const QgsComposerMap *newMap = 0;
QList<const QgsComposerMap *> mapList = mComposition->composerMapItems();
QList<const QgsComposerMap *>::const_iterator mapIt = mapList.constBegin();
for ( ; mapIt != mapList.constEnd(); ++mapIt )
QgsLayoutItemMap *newMap = 0;
QList<QgsLayoutItemMap *> mapList;
l.layoutItems( mapList );
for ( auto mapIt = mapList.constBegin() ; mapIt != mapList.constEnd(); ++mapIt )
{
if ( *mapIt != mComposerMap )
if ( *mapIt != map )
{
newMap = *mapIt;
break;
@ -187,14 +193,11 @@ void TestQgsLayoutMap::uniqueId()
QVERIFY( newMap );
int oldId = mComposerMap->id();
int newId = newMap->id();
mComposition->removeComposerItem( const_cast<QgsComposerMap *>( newMap ) );
QString oldId = map->displayName();
QString newId = newMap->displayName();
QVERIFY( oldId != newId );
}
#endif
void TestQgsLayoutMap::worldFileGeneration()
{
@ -526,5 +529,59 @@ void TestQgsLayoutMap::layersToRender()
QCOMPARE( map->layersToRender(), layers );
}
void TestQgsLayoutMap::mapRotation()
{
QgsProject p;
QFileInfo rasterFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/rgb256x256.png" );
QgsRasterLayer *layer = new QgsRasterLayer( rasterFileInfo.filePath(),
rasterFileInfo.completeBaseName() );
QgsMultiBandColorRenderer *rasterRenderer = new QgsMultiBandColorRenderer( mRasterLayer->dataProvider(), 1, 2, 3 );
layer->setRenderer( rasterRenderer );
p.addMapLayer( layer );
QgsLayout l( &p );
l.initializeDefaults();
//test map rotation
QgsLayoutItemMap *map = new QgsLayoutItemMap( &l );
map->attemptSetSceneRect( QRectF( 20, 20, 100, 50 ) );
map->setFrameEnabled( true );
l.addLayoutItem( map );
map->setExtent( QgsRectangle( 0, -192, 256, -64 ) );
map->setMapRotation( 90 );
map->setLayers( QList<QgsMapLayer *>() << layer );
QgsLayoutChecker checker( QStringLiteral( "composerrotation_maprotation" ), &l );
checker.setControlPathPrefix( QStringLiteral( "composer_items" ) );
QVERIFY( checker.testLayout( mReport, 0, 200 ) );
}
void TestQgsLayoutMap::mapItemRotation()
{
QgsProject p;
QFileInfo rasterFileInfo( QStringLiteral( TEST_DATA_DIR ) + "/rgb256x256.png" );
QgsRasterLayer *layer = new QgsRasterLayer( rasterFileInfo.filePath(),
rasterFileInfo.completeBaseName() );
QgsMultiBandColorRenderer *rasterRenderer = new QgsMultiBandColorRenderer( mRasterLayer->dataProvider(), 1, 2, 3 );
layer->setRenderer( rasterRenderer );
p.addMapLayer( layer );
QgsLayout l( &p );
l.initializeDefaults();
//test map rotation
QgsLayoutItemMap *map = new QgsLayoutItemMap( &l );
map->attemptSetSceneRect( QRectF( 20, 50, 100, 50 ) );
map->setFrameEnabled( true );
l.addLayoutItem( map );
map->setExtent( QgsRectangle( 0, -192, 256, -64 ) );
map->setItemRotation( 90 );
map->setLayers( QList<QgsMapLayer *>() << layer );
QgsLayoutChecker checker( QStringLiteral( "composerrotation_mapitemrotation" ), &l );
checker.setControlPathPrefix( QStringLiteral( "composer_items" ) );
QVERIFY( checker.testLayout( mReport, 0, 200 ) );
}
QGSTEST_MAIN( TestQgsLayoutMap )
#include "testqgslayoutmap.moc"

View File

@ -42,6 +42,7 @@ class TestQgsLayoutPage : public QObject
void pageSize();
void decodePageOrientation();
void grid();
void defaultPaper();
void transparentPaper(); //test totally transparent paper style
void borderedPaper(); //test page with border
void markerLinePaper(); //test page with marker line borde
@ -170,6 +171,19 @@ void TestQgsLayoutPage::grid()
}
void TestQgsLayoutPage::defaultPaper()
{
QgsProject p;
QgsLayout l( &p );
std::unique_ptr< QgsLayoutItemPage > page( new QgsLayoutItemPage( &l ) );
page->setPageSize( QgsLayoutSize( 297, 210, QgsUnitTypes::LayoutMillimeters ) );
l.pageCollection()->addPage( page.release() );
QgsLayoutChecker checker( QStringLiteral( "composerpaper_default" ), &l );
checker.setControlPathPrefix( QStringLiteral( "composer_paper" ) );
QVERIFY( checker.testLayout( mReport ) );
}
void TestQgsLayoutPage::transparentPaper()
{
QgsProject p;

View File

@ -0,0 +1,113 @@
/***************************************************************************
testqgslayoutpolyline.cpp
---------------------------
begin : January 2018
copyright : (C) 2018 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsapplication.h"
#include "qgslayout.h"
#include "qgsmultirenderchecker.h"
#include "qgslayoutitempolyline.h"
#include "qgsproject.h"
#include <QLocale>
#include <QObject>
#include "qgstest.h"
class TestQgsLayoutPolyline : public QObject
{
Q_OBJECT
public:
TestQgsLayoutPolyline() = default;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void drawArrowHead();
private:
bool renderCheck( const QString &testName, QImage &image, int mismatchCount = 0 );
QString mReport;
};
void TestQgsLayoutPolyline::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
mReport = QStringLiteral( "<h1>Layout Polyline Tests</h1>\n" );
}
void TestQgsLayoutPolyline::cleanupTestCase()
{
QString myReportFile = QDir::tempPath() + "/qgistest.html";
QFile myFile( myReportFile );
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
{
QTextStream myQTextStream( &myFile );
myQTextStream << mReport;
myFile.close();
}
QgsApplication::exitQgis();
}
void TestQgsLayoutPolyline::init()
{
}
void TestQgsLayoutPolyline::cleanup()
{
}
void TestQgsLayoutPolyline::drawArrowHead()
{
//test drawing with no painter
QgsLayoutItemPolyline::drawArrowHead( nullptr, 100, 100, 90, 30 );
//test painting on to image
QImage testImage = QImage( 250, 250, QImage::Format_RGB32 );
testImage.fill( qRgb( 152, 219, 249 ) );
QPainter testPainter;
testPainter.begin( &testImage );
QgsLayoutItemPolyline::drawArrowHead( &testPainter, 100, 100, 45, 30 );
testPainter.end();
QVERIFY( renderCheck( "composerutils_drawarrowhead", testImage, 40 ) );
}
bool TestQgsLayoutPolyline::renderCheck( const QString &testName, QImage &image, int mismatchCount )
{
mReport += "<h2>" + testName + "</h2>\n";
QString myTmpDir = QDir::tempPath() + '/';
QString myFileName = myTmpDir + testName + ".png";
image.save( myFileName, "PNG" );
QgsRenderChecker myChecker;
myChecker.setControlPathPrefix( QStringLiteral( "composer_utils" ) );
myChecker.setControlName( "expected_" + testName );
myChecker.setRenderedImage( myFileName );
bool myResultFlag = myChecker.compareImages( testName, mismatchCount );
mReport += myChecker.report();
return myResultFlag;
}
QGSTEST_MAIN( TestQgsLayoutPolyline )
#include "testqgslayoutpolyline.moc"

View File

@ -49,6 +49,7 @@ class TestQgsLayoutShapes : public QObject
void symbol(); //test is styling shapes via symbol is working
void readWriteXml();
void bounds();
void shapeRotation();
private:
@ -287,5 +288,31 @@ void TestQgsLayoutShapes::bounds()
QCOMPARE( bounds.bottom(), 103.0 );
}
void TestQgsLayoutShapes::shapeRotation()
{
QgsProject p;
QgsLayout l( &p );
l.initializeDefaults();
QgsLayoutItemShape *shape = new QgsLayoutItemShape( &l );
shape->attemptSetSceneRect( QRectF( 70, 70, 150, 100 ) );
shape->setItemRotation( 45 );
//setup simple fill
QgsSimpleFillSymbolLayer *simpleFill = new QgsSimpleFillSymbolLayer();
QgsFillSymbol *fillSymbol = new QgsFillSymbol();
fillSymbol->changeSymbolLayer( 0, simpleFill );
simpleFill->setColor( QColor( 255, 150, 0 ) );
//simpleFill->setStrokeColor( Qt::yellow );
//simpleFill->setStrokeWidth( 6 );
shape->setSymbol( fillSymbol );
delete fillSymbol;
l.addLayoutItem( shape );
QgsLayoutChecker checker( QStringLiteral( "composerrotation_shape" ), &l );
checker.setControlPathPrefix( QStringLiteral( "composer_items" ) );
QVERIFY( checker.testLayout( mReport ) );
}
QGSTEST_MAIN( TestQgsLayoutShapes )
#include "testqgslayoutshapes.moc"

View File

@ -145,6 +145,20 @@ void TestQgsPageSizeRegistry::decodePageSize()
QCOMPARE( result.name, QString( "A3" ) );
QCOMPARE( result.size, QgsLayoutSize( 297.0, 420.0 ) );
//good strings
QVERIFY( registry->decodePageSize( QStringLiteral( "a4" ), result ) );
QCOMPARE( result.size.width(), 210.0 );
QCOMPARE( result.size.height(), 297.0 );
QVERIFY( registry->decodePageSize( QStringLiteral( "B0" ), result ) );
QCOMPARE( result.size.width(), 1000.0 );
QCOMPARE( result.size.height(), 1414.0 );
QVERIFY( registry->decodePageSize( QStringLiteral( "letter" ), result ) );
QCOMPARE( result.size.width(), 215.9 );
QCOMPARE( result.size.height(), 279.4 );
QVERIFY( registry->decodePageSize( QStringLiteral( "LEGAL" ), result ) );
QCOMPARE( result.size.width(), 215.9 );
QCOMPARE( result.size.height(), 355.6 );
//test with bad string
QgsPageSize result2( QStringLiteral( "nomatch" ), QgsLayoutSize( 10.0, 20.0 ) );
QgsPageSize expected( result2 ); //for a bad match, expect page size to be unchanged

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB