Skip to content

Commit f2b5a59

Browse files
committed
Fix loading 2.x projects with custom CRS
Fixes #17257
1 parent e967881 commit f2b5a59

File tree

3 files changed

+173
-10
lines changed

3 files changed

+173
-10
lines changed

src/core/qgsproject.cpp

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -451,9 +451,6 @@ QgsCoordinateReferenceSystem QgsProject::crs() const
451451
void QgsProject::setCrs( const QgsCoordinateReferenceSystem &crs )
452452
{
453453
mCrs = crs;
454-
writeEntry( QStringLiteral( "SpatialRefSys" ), QStringLiteral( "/ProjectCRSProj4String" ), crs.toProj4() );
455-
writeEntry( QStringLiteral( "SpatialRefSys" ), QStringLiteral( "/ProjectCRSID" ), static_cast< int >( crs.srsid() ) );
456-
writeEntry( QStringLiteral( "SpatialRefSys" ), QStringLiteral( "/ProjectCrs" ), crs.authid() );
457454
writeEntry( QStringLiteral( "SpatialRefSys" ), QStringLiteral( "/ProjectionsEnabled" ), crs.isValid() ? 1 : 0 );
458455
setDirty( true );
459456
emit crsChanged();
@@ -884,10 +881,31 @@ bool QgsProject::readProjectFile( const QString &filename )
884881
QgsCoordinateReferenceSystem projectCrs;
885882
if ( readNumEntry( QStringLiteral( "SpatialRefSys" ), QStringLiteral( "/ProjectionsEnabled" ), 0 ) )
886883
{
887-
long currentCRS = readNumEntry( QStringLiteral( "SpatialRefSys" ), QStringLiteral( "/ProjectCRSID" ), -1 );
888-
if ( currentCRS != -1 )
884+
// first preference - dedicated projectCrs node
885+
QDomNode srsNode = doc->documentElement().namedItem( QStringLiteral( "projectCrs" ) );
886+
if ( !srsNode.isNull() )
889887
{
890-
projectCrs = QgsCoordinateReferenceSystem::fromSrsId( currentCRS );
888+
projectCrs.readXml( srsNode );
889+
}
890+
891+
if ( !projectCrs.isValid() )
892+
{
893+
// else we try using the stored proj4 string - it's consistent across different QGIS installs,
894+
// whereas the srsid can vary (e.g. for custom projections)
895+
QString projCrsString = readEntry( QStringLiteral( "SpatialRefSys" ), QStringLiteral( "/ProjectCRSProj4String" ) );
896+
if ( !projCrsString.isEmpty() )
897+
{
898+
projectCrs = QgsCoordinateReferenceSystem::fromProj4( projCrsString );
899+
}
900+
// last try using crs id - most fragile
901+
if ( !projectCrs.isValid() )
902+
{
903+
long currentCRS = readNumEntry( QStringLiteral( "SpatialRefSys" ), QStringLiteral( "/ProjectCRSID" ), -1 );
904+
if ( currentCRS != -1 && currentCRS < USER_CRS_START_ID )
905+
{
906+
projectCrs = QgsCoordinateReferenceSystem::fromSrsId( currentCRS );
907+
}
908+
}
891909
}
892910
}
893911
mCrs = projectCrs;
@@ -1340,6 +1358,11 @@ bool QgsProject::writeProjectFile( const QString &filename )
13401358
QDomText titleText = doc->createTextNode( title() ); // XXX why have title TWICE?
13411359
titleNode.appendChild( titleText );
13421360

1361+
// write project CRS
1362+
QDomElement srsNode = doc->createElement( QStringLiteral( "projectCrs" ) );
1363+
mCrs.writeXml( srsNode, *doc );
1364+
qgisNode.appendChild( srsNode );
1365+
13431366
// write layer tree - make sure it is without embedded subgroups
13441367
QgsLayerTreeNode *clonedRoot = mRootGroup->clone();
13451368
QgsLayerTreeUtils::replaceChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) );

tests/src/core/testqgscoordinatereferencesystem.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@ Email : sherman at mrcc dot com
1515
#include "qgstest.h"
1616
#include <QPixmap>
1717

18-
#include <qgsapplication.h>
18+
#include "qgsapplication.h"
1919
#include "qgslogger.h"
2020

2121
//header for class being tested
22-
#include <qgscoordinatereferencesystem.h>
23-
#include <qgis.h>
24-
#include <qgsvectorlayer.h>
22+
#include "qgscoordinatereferencesystem.h"
23+
#include "qgis.h"
24+
#include "qgsvectorlayer.h"
25+
#include "qgsproject.h"
2526

2627
#include <proj_api.h>
2728
#include <gdal.h>
@@ -77,6 +78,7 @@ class TestQgsCoordinateReferenceSystem: public QObject
7778
void asVariant();
7879
void bounds();
7980
void saveAsUserCrs();
81+
void projectWithCustomCrs();
8082

8183
private:
8284
void debugPrint( QgsCoordinateReferenceSystem &crs );
@@ -834,5 +836,14 @@ void TestQgsCoordinateReferenceSystem::saveAsUserCrs()
834836
QCOMPARE( userCrs2.description(), QStringLiteral( "babies first projection" ) );
835837
}
836838

839+
void TestQgsCoordinateReferenceSystem::projectWithCustomCrs()
840+
{
841+
// tests loading a 2.x project with a custom CRS defined
842+
QgsProject p;
843+
QVERIFY( p.read( TEST_DATA_DIR + QStringLiteral( "/projects/custom_crs.qgs" ) ) );
844+
QVERIFY( p.crs().isValid() );
845+
QCOMPARE( p.crs().toProj4(), QStringLiteral( "+proj=ortho +lat_0=42.1 +lon_0=12.8 +x_0=0 +y_0=0 +a=6371000 +b=6371000 +units=m +no_defs" ) );
846+
}
847+
837848
QGSTEST_MAIN( TestQgsCoordinateReferenceSystem )
838849
#include "testqgscoordinatereferencesystem.moc"
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<!DOCTYPE qgis PUBLIC 'http://mrcc.com/qgis.dtd' 'SYSTEM'>
2+
<qgis projectname="" version="2.18.9">
3+
<title></title>
4+
<autotransaction active="0"/>
5+
<evaluateDefaultValues active="0"/>
6+
<layer-tree-group expanded="1" checked="Qt::Checked" name="">
7+
<customproperties/>
8+
</layer-tree-group>
9+
<relations/>
10+
<mapcanvas>
11+
<units>meters</units>
12+
<extent>
13+
<xmin>-1579730.21282207453623414</xmin>
14+
<ymin>-4271174.32985332515090704</ymin>
15+
<xmax>-1242009.40286419028416276</xmax>
16+
<ymax>-4054770.71263487357646227</ymax>
17+
</extent>
18+
<rotation>0</rotation>
19+
<projections>1</projections>
20+
<destinationsrs>
21+
<spatialrefsys>
22+
<proj4>+proj=ortho +lat_0=42.1 +lon_0=12.8 +x_0=0 +y_0=0 +a=6371000 +b=6371000 +units=m +no_defs</proj4>
23+
<srsid>100001</srsid>
24+
<srid>0</srid>
25+
<authid>USER:100001</authid>
26+
<description>new CRS</description>
27+
<projectionacronym>ortho</projectionacronym>
28+
<ellipsoidacronym></ellipsoidacronym>
29+
<geographicflag>false</geographicflag>
30+
</spatialrefsys>
31+
</destinationsrs>
32+
<rendermaptile>0</rendermaptile>
33+
<layer_coordinate_transform_info/>
34+
</mapcanvas>
35+
<layer-tree-canvas>
36+
<custom-order enabled="0"/>
37+
</layer-tree-canvas>
38+
<legend updateDrawingOrder="true"/>
39+
<projectlayers/>
40+
<properties>
41+
<WMSContactPerson type="QString"></WMSContactPerson>
42+
<Variables>
43+
<variableNames type="QStringList"/>
44+
<variableValues type="QStringList"/>
45+
</Variables>
46+
<WMSOnlineResource type="QString"></WMSOnlineResource>
47+
<WMSUseLayerIDs type="bool">false</WMSUseLayerIDs>
48+
<WMSContactOrganization type="QString"></WMSContactOrganization>
49+
<WMSKeywordList type="QStringList">
50+
<value></value>
51+
</WMSKeywordList>
52+
<WFSUrl type="QString"></WFSUrl>
53+
<Paths>
54+
<Absolute type="bool">false</Absolute>
55+
</Paths>
56+
<WMSServiceTitle type="QString"></WMSServiceTitle>
57+
<WFSLayers type="QStringList"/>
58+
<WMSContactMail type="QString"></WMSContactMail>
59+
<PositionPrecision>
60+
<DecimalPlaces type="int">2</DecimalPlaces>
61+
<Automatic type="bool">true</Automatic>
62+
<DegreeFormat type="QString">MU</DegreeFormat>
63+
</PositionPrecision>
64+
<WCSUrl type="QString"></WCSUrl>
65+
<WMSContactPhone type="QString"></WMSContactPhone>
66+
<WMSServiceCapabilities type="bool">false</WMSServiceCapabilities>
67+
<WMSServiceAbstract type="QString"></WMSServiceAbstract>
68+
<WMSContactPosition type="QString"></WMSContactPosition>
69+
<WMSAddWktGeometry type="bool">false</WMSAddWktGeometry>
70+
<Measure>
71+
<Ellipsoid type="QString">NONE</Ellipsoid>
72+
</Measure>
73+
<WMSPrecision type="QString">8</WMSPrecision>
74+
<WMSSegmentizeFeatureInfoGeometry type="bool">false</WMSSegmentizeFeatureInfoGeometry>
75+
<WFSTLayers>
76+
<Insert type="QStringList"/>
77+
<Update type="QStringList"/>
78+
<Delete type="QStringList"/>
79+
</WFSTLayers>
80+
<Gui>
81+
<SelectionColorBluePart type="int">0</SelectionColorBluePart>
82+
<CanvasColorGreenPart type="int">255</CanvasColorGreenPart>
83+
<CanvasColorRedPart type="int">255</CanvasColorRedPart>
84+
<SelectionColorRedPart type="int">255</SelectionColorRedPart>
85+
<SelectionColorAlphaPart type="int">255</SelectionColorAlphaPart>
86+
<SelectionColorGreenPart type="int">255</SelectionColorGreenPart>
87+
<CanvasColorBluePart type="int">255</CanvasColorBluePart>
88+
</Gui>
89+
<Digitizing>
90+
<DefaultSnapToleranceUnit type="int">2</DefaultSnapToleranceUnit>
91+
<SnappingMode type="QString">current_layer</SnappingMode>
92+
<DefaultSnapType type="QString">off</DefaultSnapType>
93+
<DefaultSnapTolerance type="double">0</DefaultSnapTolerance>
94+
</Digitizing>
95+
<Identify>
96+
<disabledLayers type="QStringList"/>
97+
</Identify>
98+
<Macros>
99+
<pythonCode type="QString"></pythonCode>
100+
</Macros>
101+
<WMSAccessConstraints type="QString">None</WMSAccessConstraints>
102+
<WCSLayers type="QStringList"/>
103+
<Legend>
104+
<filterByMap type="bool">false</filterByMap>
105+
</Legend>
106+
<SpatialRefSys>
107+
<ProjectCRSProj4String type="QString">+proj=ortho +lat_0=42.1 +lon_0=12.8 +x_0=0 +y_0=0 +a=6371000 +b=6371000 +units=m +no_defs</ProjectCRSProj4String>
108+
<ProjectCrs type="QString">USER:100001</ProjectCrs>
109+
<ProjectCRSID type="int">100001</ProjectCRSID>
110+
<ProjectionsEnabled type="int">1</ProjectionsEnabled>
111+
</SpatialRefSys>
112+
<DefaultStyles>
113+
<Fill type="QString"></Fill>
114+
<Line type="QString"></Line>
115+
<Marker type="QString"></Marker>
116+
<RandomColors type="bool">true</RandomColors>
117+
<AlphaInt type="int">255</AlphaInt>
118+
<ColorRamp type="QString"></ColorRamp>
119+
</DefaultStyles>
120+
<WMSFees type="QString">conditions unknown</WMSFees>
121+
<WMSImageQuality type="int">90</WMSImageQuality>
122+
<Measurement>
123+
<DistanceUnits type="QString">meters</DistanceUnits>
124+
<AreaUnits type="QString">m2</AreaUnits>
125+
</Measurement>
126+
<WMSUrl type="QString"></WMSUrl>
127+
</properties>
128+
<visibility-presets/>
129+
</qgis>

0 commit comments

Comments
 (0)