Skip to content

Commit

Permalink
Allow loading QLR files with invalid sources
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nyalldawson committed Apr 30, 2019
1 parent e4dc3ba commit 7ae28bf
Show file tree
Hide file tree
Showing 3 changed files with 287 additions and 4 deletions.
8 changes: 4 additions & 4 deletions src/core/qgslayerdefinition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,10 @@ QList<QgsMapLayer *> QgsLayerDefinition::loadLayerDefinitionLayers( QDomDocument
if ( !layer )
continue;

if ( layer->readLayerXml( layerElem, context ) )
{
layers << layer;
}
// always add the layer, even if the source is invalid -- this allows users to fix the source
// at a later stage and still retain all the layer properties intact
layer->readLayerXml( layerElem, context );
layers << layer;
}
return layers;
}
Expand Down
15 changes: 15 additions & 0 deletions tests/src/python/test_qgslayerdefinition.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,21 @@ def testVectorAndRaster(self):
self.assertEqual(len(layers), 2)
QgsProject.instance().removeAllMapLayers()

def testInvalidSource(self):
# Load a QLR containing a vector layer with a broken path
QgsProject.instance().removeAllMapLayers()
layers = QgsProject.instance().mapLayers()
self.assertEqual(len(layers), 0)

(result, errMsg) = QgsLayerDefinition.loadLayerDefinition(TEST_DATA_DIR + '/invalid_source.qlr', QgsProject.instance(), QgsProject.instance().layerTreeRoot())
self.assertTrue(result)
self.assertFalse(errMsg)

layers = QgsProject.instance().mapLayers()
self.assertEqual(len(layers), 1)
self.assertFalse(list(layers.values())[0].isValid())
QgsProject.instance().removeAllMapLayers()


if __name__ == '__main__':
unittest.main()
268 changes: 268 additions & 0 deletions tests/testdata/invalid_source.qlr
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
<!DOCTYPE qgis-layer-definition>
<qlr>
<layer-tree-group expanded="1" name="" checked="Qt::Checked">
<customproperties/>
<layer-tree-layer source="C:\temp/points.shp" expanded="1" id="points_1cff66ba_ca06_4c6d_8542_610e215f65ca" name="points" providerKey="ogr" checked="Qt::Checked">
<customproperties/>
</layer-tree-layer>
</layer-tree-group>
<maplayers>
<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">
<id>points_1cff66ba_ca06_4c6d_8542_610e215f65ca</id>
<datasource>C:\temp/points.shp</datasource>
<keywordList>
<value></value>
</keywordList>
<layername>points</layername>
<srs>
<spatialrefsys>
<proj4>+proj=longlat +datum=WGS84 +no_defs</proj4>
<srsid>3452</srsid>
<srid>4326</srid>
<authid>EPSG:4326</authid>
<description>WGS 84</description>
<projectionacronym>longlat</projectionacronym>
<ellipsoidacronym>WGS84</ellipsoidacronym>
<geographicflag>true</geographicflag>
</spatialrefsys>
</srs>
<resourceMetadata>
<identifier></identifier>
<parentidentifier></parentidentifier>
<language></language>
<type></type>
<title></title>
<abstract></abstract>
<links/>
<fees></fees>
<encoding></encoding>
<crs>
<spatialrefsys>
<proj4></proj4>
<srsid>0</srsid>
<srid>0</srid>
<authid></authid>
<description></description>
<projectionacronym></projectionacronym>
<ellipsoidacronym></ellipsoidacronym>
<geographicflag>false</geographicflag>
</spatialrefsys>
</crs>
<extent/>
</resourceMetadata>
<provider encoding="UTF-8">ogr</provider>
<vectorjoins/>
<layerDependencies/>
<dataDependencies/>
<legend type="default-vector"/>
<expressionfields/>
<map-layer-style-manager current="default">
<map-layer-style name="default"/>
</map-layer-style-manager>
<auxiliaryLayer/>
<flags>
<Identifiable>1</Identifiable>
<Removable>1</Removable>
<Searchable>1</Searchable>
</flags>
<renderer-v2 symbollevels="0" graduatedMethod="GraduatedColor" attr="Importance" enableorderby="0" type="graduatedSymbol" forceraster="0">
<ranges>
<range render="true" upper="1.000000000000000" symbol="0" label="1.000" lower="1.000000000000000"/>
<range render="true" upper="3.000000000000000" symbol="1" label="1.001 - 3.000" lower="1.001000000000000"/>
<range render="true" upper="4.000000000000000" symbol="2" label="3.001 - 4.000" lower="3.001000000000000"/>
<range render="true" upper="10.000000000000000" symbol="3" label="4.001 - 10.000" lower="4.001000000000000"/>
<range render="true" upper="20.000000000000000" symbol="4" label="10.001 - 20.000" lower="10.000999999999999"/>
</ranges>
<symbols>
<symbol alpha="1" force_rhr="0" clip_to_extent="1" type="marker" name="0">
<layer enabled="1" pass="0" class="SimpleMarker" locked="0">
<prop k="angle" v="0"/>
<prop k="color" v="255,255,127,255"/>
<prop k="horizontal_anchor_point" v="1"/>
<prop k="joinstyle" v="bevel"/>
<prop k="name" v="circle"/>
<prop k="offset" v="0,0"/>
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="offset_unit" v="Point"/>
<prop k="outline_color" v="0,0,0,255"/>
<prop k="outline_style" v="solid"/>
<prop k="outline_width" v="0.5"/>
<prop k="outline_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="outline_width_unit" v="Point"/>
<prop k="scale_method" v="diameter"/>
<prop k="size" v="4"/>
<prop k="size_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="size_unit" v="Point"/>
<prop k="vertical_anchor_point" v="1"/>
<data_defined_properties>
<Option type="Map">
<Option value="" type="QString" name="name"/>
<Option name="properties"/>
<Option value="collection" type="QString" name="type"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
<symbol alpha="1" force_rhr="0" clip_to_extent="1" type="marker" name="1">
<layer enabled="1" pass="0" class="SimpleMarker" locked="0">
<prop k="angle" v="0"/>
<prop k="color" v="250,209,85,255"/>
<prop k="horizontal_anchor_point" v="1"/>
<prop k="joinstyle" v="bevel"/>
<prop k="name" v="circle"/>
<prop k="offset" v="0,0"/>
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="offset_unit" v="Point"/>
<prop k="outline_color" v="0,0,0,255"/>
<prop k="outline_style" v="solid"/>
<prop k="outline_width" v="0.5"/>
<prop k="outline_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="outline_width_unit" v="Point"/>
<prop k="scale_method" v="diameter"/>
<prop k="size" v="4"/>
<prop k="size_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="size_unit" v="Point"/>
<prop k="vertical_anchor_point" v="1"/>
<data_defined_properties>
<Option type="Map">
<Option value="" type="QString" name="name"/>
<Option name="properties"/>
<Option value="collection" type="QString" name="type"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
<symbol alpha="1" force_rhr="0" clip_to_extent="1" type="marker" name="2">
<layer enabled="1" pass="0" class="SimpleMarker" locked="0">
<prop k="angle" v="0"/>
<prop k="color" v="242,167,46,255"/>
<prop k="horizontal_anchor_point" v="1"/>
<prop k="joinstyle" v="bevel"/>
<prop k="name" v="circle"/>
<prop k="offset" v="0,0"/>
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="offset_unit" v="Point"/>
<prop k="outline_color" v="0,0,0,255"/>
<prop k="outline_style" v="solid"/>
<prop k="outline_width" v="0.5"/>
<prop k="outline_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="outline_width_unit" v="Point"/>
<prop k="scale_method" v="diameter"/>
<prop k="size" v="4"/>
<prop k="size_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="size_unit" v="Point"/>
<prop k="vertical_anchor_point" v="1"/>
<data_defined_properties>
<Option type="Map">
<Option value="" type="QString" name="name"/>
<Option name="properties"/>
<Option value="collection" type="QString" name="type"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
<symbol alpha="1" force_rhr="0" clip_to_extent="1" type="marker" name="3">
<layer enabled="1" pass="0" class="SimpleMarker" locked="0">
<prop k="angle" v="0"/>
<prop k="color" v="173,83,19,255"/>
<prop k="horizontal_anchor_point" v="1"/>
<prop k="joinstyle" v="bevel"/>
<prop k="name" v="circle"/>
<prop k="offset" v="0,0"/>
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="offset_unit" v="Point"/>
<prop k="outline_color" v="0,0,0,255"/>
<prop k="outline_style" v="solid"/>
<prop k="outline_width" v="0.5"/>
<prop k="outline_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="outline_width_unit" v="Point"/>
<prop k="scale_method" v="diameter"/>
<prop k="size" v="4"/>
<prop k="size_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="size_unit" v="Point"/>
<prop k="vertical_anchor_point" v="1"/>
<data_defined_properties>
<Option type="Map">
<Option value="" type="QString" name="name"/>
<Option name="properties"/>
<Option value="collection" type="QString" name="type"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
<symbol alpha="1" force_rhr="0" clip_to_extent="1" type="marker" name="4">
<layer enabled="1" pass="0" class="SimpleMarker" locked="0">
<prop k="angle" v="0"/>
<prop k="color" v="107,0,0,255"/>
<prop k="horizontal_anchor_point" v="1"/>
<prop k="joinstyle" v="bevel"/>
<prop k="name" v="circle"/>
<prop k="offset" v="0,0"/>
<prop k="offset_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="offset_unit" v="Point"/>
<prop k="outline_color" v="0,0,0,255"/>
<prop k="outline_style" v="solid"/>
<prop k="outline_width" v="0.5"/>
<prop k="outline_width_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="outline_width_unit" v="Point"/>
<prop k="scale_method" v="diameter"/>
<prop k="size" v="4"/>
<prop k="size_map_unit_scale" v="3x:0,0,0,0,0,0"/>
<prop k="size_unit" v="Point"/>
<prop k="vertical_anchor_point" v="1"/>
<data_defined_properties>
<Option type="Map">
<Option value="" type="QString" name="name"/>
<Option name="properties"/>
<Option value="collection" type="QString" name="type"/>
</Option>
</data_defined_properties>
</layer>
</symbol>
</symbols>
<symmetricMode enabled="false" symmetryPoint="0" astride="false"/>
<rotation/>
<sizescale/>
<labelformat trimtrailingzeroes="false" decimalplaces="4" format="%1 - %2"/>
</renderer-v2>
<customproperties/>
<blendMode>0</blendMode>
<featureBlendMode>0</featureBlendMode>
<layerOpacity>1</layerOpacity>
<geometryOptions removeDuplicateNodes="0" geometryPrecision="0">
<activeChecks type="StringList">
<Option value="" type="QString"/>
</activeChecks>
<checkConfiguration/>
</geometryOptions>
<fieldConfiguration/>
<aliases/>
<excludeAttributesWMS/>
<excludeAttributesWFS/>
<defaults/>
<constraints/>
<constraintExpressions/>
<expressionfields/>
<attributeactions/>
<attributetableconfig sortExpression="" actionWidgetStyle="dropDown" sortOrder="0">
<columns/>
</attributetableconfig>
<conditionalstyles>
<rowstyles/>
<fieldstyles/>
</conditionalstyles>
<editform tolerant="1"></editform>
<editforminit/>
<editforminitcodesource>0</editforminitcodesource>
<editforminitfilepath></editforminitfilepath>
<editforminitcode><![CDATA[]]></editforminitcode>
<featformsuppress>0</featformsuppress>
<editorlayout>generatedlayout</editorlayout>
<editable/>
<labelOnTop/>
<widgets/>
<previewExpression></previewExpression>
<mapTip></mapTip>
</maplayer>
</maplayers>
</qlr>

0 comments on commit 7ae28bf

Please sign in to comment.