Skip to content

Commit 4a72ed4

Browse files
committed
Allow loading QLR files with invalid sources
E.g. if the layer path has moved, we still should allow these files to be read, so that the layer path can be fixed by the user manually.
1 parent e4dc3ba commit 4a72ed4

File tree

3 files changed

+287
-4
lines changed

3 files changed

+287
-4
lines changed

src/core/qgslayerdefinition.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,10 @@ QList<QgsMapLayer *> QgsLayerDefinition::loadLayerDefinitionLayers( QDomDocument
274274
if ( !layer )
275275
continue;
276276

277-
if ( layer->readLayerXml( layerElem, context ) )
278-
{
279-
layers << layer;
280-
}
277+
// always add the layer, even if the source is invalid -- this allows users to fix the source
278+
// at a later stage and still retain all the layer properties intact
279+
layer->readLayerXml( layerElem, context );
280+
layers << layer;
281281
}
282282
return layers;
283283
}

tests/src/python/test_qgslayerdefinition.py

+15
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,21 @@ def testVectorAndRaster(self):
110110
self.assertEqual(len(layers), 2)
111111
QgsProject.instance().removeAllMapLayers()
112112

113+
def testInvalidSource(self):
114+
# Load a QLR containing a vector layer with a broken path
115+
QgsProject.instance().removeAllMapLayers()
116+
layers = QgsProject.instance().mapLayers()
117+
self.assertEqual(len(layers), 0)
118+
119+
(result, errMsg) = QgsLayerDefinition.loadLayerDefinition(TEST_DATA_DIR + '/invalid_source.qlr', QgsProject.instance(), QgsProject.instance().layerTreeRoot())
120+
self.assertTrue(result)
121+
self.assertFalse(errMsg)
122+
123+
layers = QgsProject.instance().mapLayers()
124+
self.assertEqual(len(layers), 1)
125+
self.assertFalse(list(layers.values())[0].isValid())
126+
QgsProject.instance().removeAllMapLayers()
127+
113128

114129
if __name__ == '__main__':
115130
unittest.main()

tests/testdata/invalid_source.qlr

+268
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
<!DOCTYPE qgis-layer-definition>
2+
<qlr>
3+
<layer-tree-group expanded="1" name="" checked="Qt::Checked">
4+
<customproperties/>
5+
<layer-tree-layer source="C:\temp/points.shp" expanded="1" id="points_1cff66ba_ca06_4c6d_8542_610e215f65ca" name="points" providerKey="ogr" checked="Qt::Checked">
6+
<customproperties/>
7+
</layer-tree-layer>
8+
</layer-tree-group>
9+
<maplayers>
10+
<maplayer geometry="Point" labelsEnabled="0" autoRefreshEnabled="0" styleCategories="AllStyleCategories" refreshOnNotifyEnabled="0" maxScale="0" refreshOnNotifyMessage="" simplifyLocal="1" wkbType="Point" simplifyDrawingTol="1" autoRefreshTime="0" simplifyMaxScale="1" readOnly="0" minScale="0" simplifyDrawingHints="1" simplifyAlgorithm="0" type="vector" hasScaleBasedVisibilityFlag="0">
11+
<id>points_1cff66ba_ca06_4c6d_8542_610e215f65ca</id>
12+
<datasource>C:\temp/points.shp</datasource>
13+
<keywordList>
14+
<value></value>
15+
</keywordList>
16+
<layername>points</layername>
17+
<srs>
18+
<spatialrefsys>
19+
<proj4>+proj=longlat +datum=WGS84 +no_defs</proj4>
20+
<srsid>3452</srsid>
21+
<srid>4326</srid>
22+
<authid>EPSG:4326</authid>
23+
<description>WGS 84</description>
24+
<projectionacronym>longlat</projectionacronym>
25+
<ellipsoidacronym>WGS84</ellipsoidacronym>
26+
<geographicflag>true</geographicflag>
27+
</spatialrefsys>
28+
</srs>
29+
<resourceMetadata>
30+
<identifier></identifier>
31+
<parentidentifier></parentidentifier>
32+
<language></language>
33+
<type></type>
34+
<title></title>
35+
<abstract></abstract>
36+
<links/>
37+
<fees></fees>
38+
<encoding></encoding>
39+
<crs>
40+
<spatialrefsys>
41+
<proj4></proj4>
42+
<srsid>0</srsid>
43+
<srid>0</srid>
44+
<authid></authid>
45+
<description></description>
46+
<projectionacronym></projectionacronym>
47+
<ellipsoidacronym></ellipsoidacronym>
48+
<geographicflag>false</geographicflag>
49+
</spatialrefsys>
50+
</crs>
51+
<extent/>
52+
</resourceMetadata>
53+
<provider encoding="UTF-8">ogr</provider>
54+
<vectorjoins/>
55+
<layerDependencies/>
56+
<dataDependencies/>
57+
<legend type="default-vector"/>
58+
<expressionfields/>
59+
<map-layer-style-manager current="default">
60+
<map-layer-style name="default"/>
61+
</map-layer-style-manager>
62+
<auxiliaryLayer/>
63+
<flags>
64+
<Identifiable>1</Identifiable>
65+
<Removable>1</Removable>
66+
<Searchable>1</Searchable>
67+
</flags>
68+
<renderer-v2 symbollevels="0" graduatedMethod="GraduatedColor" attr="Importance" enableorderby="0" type="graduatedSymbol" forceraster="0">
69+
<ranges>
70+
<range render="true" upper="1.000000000000000" symbol="0" label="1.000" lower="1.000000000000000"/>
71+
<range render="true" upper="3.000000000000000" symbol="1" label="1.001 - 3.000" lower="1.001000000000000"/>
72+
<range render="true" upper="4.000000000000000" symbol="2" label="3.001 - 4.000" lower="3.001000000000000"/>
73+
<range render="true" upper="10.000000000000000" symbol="3" label="4.001 - 10.000" lower="4.001000000000000"/>
74+
<range render="true" upper="20.000000000000000" symbol="4" label="10.001 - 20.000" lower="10.000999999999999"/>
75+
</ranges>
76+
<symbols>
77+
<symbol alpha="1" force_rhr="0" clip_to_extent="1" type="marker" name="0">
78+
<layer enabled="1" pass="0" class="SimpleMarker" locked="0">
79+
<prop k="angle" v="0"/>
80+
<prop k="color" v="255,255,127,255"/>
81+
<prop k="horizontal_anchor_point" v="1"/>
82+
<prop k="joinstyle" v="bevel"/>
83+
<prop k="name" v="circle"/>
84+
<prop k="offset" v="0,0"/>
85+
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
86+
<prop k="offset_unit" v="Point"/>
87+
<prop k="outline_color" v="0,0,0,255"/>
88+
<prop k="outline_style" v="solid"/>
89+
<prop k="outline_width" v="0.5"/>
90+
<prop k="outline_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
91+
<prop k="outline_width_unit" v="Point"/>
92+
<prop k="scale_method" v="diameter"/>
93+
<prop k="size" v="4"/>
94+
<prop k="size_map_unit_scale" v="3x:0,0,0,0,0,0"/>
95+
<prop k="size_unit" v="Point"/>
96+
<prop k="vertical_anchor_point" v="1"/>
97+
<data_defined_properties>
98+
<Option type="Map">
99+
<Option value="" type="QString" name="name"/>
100+
<Option name="properties"/>
101+
<Option value="collection" type="QString" name="type"/>
102+
</Option>
103+
</data_defined_properties>
104+
</layer>
105+
</symbol>
106+
<symbol alpha="1" force_rhr="0" clip_to_extent="1" type="marker" name="1">
107+
<layer enabled="1" pass="0" class="SimpleMarker" locked="0">
108+
<prop k="angle" v="0"/>
109+
<prop k="color" v="250,209,85,255"/>
110+
<prop k="horizontal_anchor_point" v="1"/>
111+
<prop k="joinstyle" v="bevel"/>
112+
<prop k="name" v="circle"/>
113+
<prop k="offset" v="0,0"/>
114+
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
115+
<prop k="offset_unit" v="Point"/>
116+
<prop k="outline_color" v="0,0,0,255"/>
117+
<prop k="outline_style" v="solid"/>
118+
<prop k="outline_width" v="0.5"/>
119+
<prop k="outline_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
120+
<prop k="outline_width_unit" v="Point"/>
121+
<prop k="scale_method" v="diameter"/>
122+
<prop k="size" v="4"/>
123+
<prop k="size_map_unit_scale" v="3x:0,0,0,0,0,0"/>
124+
<prop k="size_unit" v="Point"/>
125+
<prop k="vertical_anchor_point" v="1"/>
126+
<data_defined_properties>
127+
<Option type="Map">
128+
<Option value="" type="QString" name="name"/>
129+
<Option name="properties"/>
130+
<Option value="collection" type="QString" name="type"/>
131+
</Option>
132+
</data_defined_properties>
133+
</layer>
134+
</symbol>
135+
<symbol alpha="1" force_rhr="0" clip_to_extent="1" type="marker" name="2">
136+
<layer enabled="1" pass="0" class="SimpleMarker" locked="0">
137+
<prop k="angle" v="0"/>
138+
<prop k="color" v="242,167,46,255"/>
139+
<prop k="horizontal_anchor_point" v="1"/>
140+
<prop k="joinstyle" v="bevel"/>
141+
<prop k="name" v="circle"/>
142+
<prop k="offset" v="0,0"/>
143+
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
144+
<prop k="offset_unit" v="Point"/>
145+
<prop k="outline_color" v="0,0,0,255"/>
146+
<prop k="outline_style" v="solid"/>
147+
<prop k="outline_width" v="0.5"/>
148+
<prop k="outline_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
149+
<prop k="outline_width_unit" v="Point"/>
150+
<prop k="scale_method" v="diameter"/>
151+
<prop k="size" v="4"/>
152+
<prop k="size_map_unit_scale" v="3x:0,0,0,0,0,0"/>
153+
<prop k="size_unit" v="Point"/>
154+
<prop k="vertical_anchor_point" v="1"/>
155+
<data_defined_properties>
156+
<Option type="Map">
157+
<Option value="" type="QString" name="name"/>
158+
<Option name="properties"/>
159+
<Option value="collection" type="QString" name="type"/>
160+
</Option>
161+
</data_defined_properties>
162+
</layer>
163+
</symbol>
164+
<symbol alpha="1" force_rhr="0" clip_to_extent="1" type="marker" name="3">
165+
<layer enabled="1" pass="0" class="SimpleMarker" locked="0">
166+
<prop k="angle" v="0"/>
167+
<prop k="color" v="173,83,19,255"/>
168+
<prop k="horizontal_anchor_point" v="1"/>
169+
<prop k="joinstyle" v="bevel"/>
170+
<prop k="name" v="circle"/>
171+
<prop k="offset" v="0,0"/>
172+
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
173+
<prop k="offset_unit" v="Point"/>
174+
<prop k="outline_color" v="0,0,0,255"/>
175+
<prop k="outline_style" v="solid"/>
176+
<prop k="outline_width" v="0.5"/>
177+
<prop k="outline_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
178+
<prop k="outline_width_unit" v="Point"/>
179+
<prop k="scale_method" v="diameter"/>
180+
<prop k="size" v="4"/>
181+
<prop k="size_map_unit_scale" v="3x:0,0,0,0,0,0"/>
182+
<prop k="size_unit" v="Point"/>
183+
<prop k="vertical_anchor_point" v="1"/>
184+
<data_defined_properties>
185+
<Option type="Map">
186+
<Option value="" type="QString" name="name"/>
187+
<Option name="properties"/>
188+
<Option value="collection" type="QString" name="type"/>
189+
</Option>
190+
</data_defined_properties>
191+
</layer>
192+
</symbol>
193+
<symbol alpha="1" force_rhr="0" clip_to_extent="1" type="marker" name="4">
194+
<layer enabled="1" pass="0" class="SimpleMarker" locked="0">
195+
<prop k="angle" v="0"/>
196+
<prop k="color" v="107,0,0,255"/>
197+
<prop k="horizontal_anchor_point" v="1"/>
198+
<prop k="joinstyle" v="bevel"/>
199+
<prop k="name" v="circle"/>
200+
<prop k="offset" v="0,0"/>
201+
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
202+
<prop k="offset_unit" v="Point"/>
203+
<prop k="outline_color" v="0,0,0,255"/>
204+
<prop k="outline_style" v="solid"/>
205+
<prop k="outline_width" v="0.5"/>
206+
<prop k="outline_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
207+
<prop k="outline_width_unit" v="Point"/>
208+
<prop k="scale_method" v="diameter"/>
209+
<prop k="size" v="4"/>
210+
<prop k="size_map_unit_scale" v="3x:0,0,0,0,0,0"/>
211+
<prop k="size_unit" v="Point"/>
212+
<prop k="vertical_anchor_point" v="1"/>
213+
<data_defined_properties>
214+
<Option type="Map">
215+
<Option value="" type="QString" name="name"/>
216+
<Option name="properties"/>
217+
<Option value="collection" type="QString" name="type"/>
218+
</Option>
219+
</data_defined_properties>
220+
</layer>
221+
</symbol>
222+
</symbols>
223+
<symmetricMode enabled="false" symmetryPoint="0" astride="false"/>
224+
<rotation/>
225+
<sizescale/>
226+
<labelformat trimtrailingzeroes="false" decimalplaces="4" format="%1 - %2"/>
227+
</renderer-v2>
228+
<customproperties/>
229+
<blendMode>0</blendMode>
230+
<featureBlendMode>0</featureBlendMode>
231+
<layerOpacity>1</layerOpacity>
232+
<geometryOptions removeDuplicateNodes="0" geometryPrecision="0">
233+
<activeChecks type="StringList">
234+
<Option value="" type="QString"/>
235+
</activeChecks>
236+
<checkConfiguration/>
237+
</geometryOptions>
238+
<fieldConfiguration/>
239+
<aliases/>
240+
<excludeAttributesWMS/>
241+
<excludeAttributesWFS/>
242+
<defaults/>
243+
<constraints/>
244+
<constraintExpressions/>
245+
<expressionfields/>
246+
<attributeactions/>
247+
<attributetableconfig sortExpression="" actionWidgetStyle="dropDown" sortOrder="0">
248+
<columns/>
249+
</attributetableconfig>
250+
<conditionalstyles>
251+
<rowstyles/>
252+
<fieldstyles/>
253+
</conditionalstyles>
254+
<editform tolerant="1"></editform>
255+
<editforminit/>
256+
<editforminitcodesource>0</editforminitcodesource>
257+
<editforminitfilepath></editforminitfilepath>
258+
<editforminitcode><![CDATA[]]></editforminitcode>
259+
<featformsuppress>0</featformsuppress>
260+
<editorlayout>generatedlayout</editorlayout>
261+
<editable/>
262+
<labelOnTop/>
263+
<widgets/>
264+
<previewExpression></previewExpression>
265+
<mapTip></mapTip>
266+
</maplayer>
267+
</maplayers>
268+
</qlr>

0 commit comments

Comments
 (0)