diff --git a/src/core/qgsmaplayer.cpp b/src/core/qgsmaplayer.cpp index 93aa8bbe044..0f233ba63b6 100644 --- a/src/core/qgsmaplayer.cpp +++ b/src/core/qgsmaplayer.cpp @@ -755,8 +755,15 @@ bool QgsMapLayer::writeLayerXml( QDomElement &layerElement, QDomDocument &docume if ( !mExtent3D.isNull() && dataProvider() && dataProvider()->elevationProperties() && dataProvider()->elevationProperties()->containsElevationData() ) layerElement.appendChild( QgsXmlUtils::writeBox3D( mExtent3D, document ) ); - else if ( !mExtent2D.isNull() ) - layerElement.appendChild( QgsXmlUtils::writeRectangle( mExtent2D, document ) ); + else + { + // Extent might be null because lazily set + const QgsRectangle extent2D { mExtent2D.isNull() ? extent() : mExtent2D }; + if ( !extent2D.isNull() ) + { + layerElement.appendChild( QgsXmlUtils::writeRectangle( extent2D, document ) ); + } + } if ( const QgsRectangle lWgs84Extent = wgs84Extent( true ); !lWgs84Extent.isNull() ) { diff --git a/tests/src/python/test_qgsproject.py b/tests/src/python/test_qgsproject.py index f2e4d725e4b..6473ea191f6 100644 --- a/tests/src/python/test_qgsproject.py +++ b/tests/src/python/test_qgsproject.py @@ -17,6 +17,7 @@ from io import BytesIO from shutil import copyfile from tempfile import TemporaryDirectory from zipfile import ZipFile +from lxml import etree as et from osgeo import ogr from qgis.PyQt import sip @@ -2119,6 +2120,43 @@ class TestQgsProject(QgisTestCase): del project + def testVectorExtentIsStored(self): + """ + Test that vector layer extent is stored in the project + Test for GH #61181 + """ + + tmpDir = QTemporaryDir() + tmpFile = f"{tmpDir.path()}/project.qgs" + for ext in ["shp", "shx", "dbf"]: + copyfile( + os.path.join(TEST_DATA_DIR, "points." + ext), + os.path.join(tmpDir.path(), "points." + ext), + ) + + project = QgsProject() + + l0 = QgsVectorLayer(os.path.join(tmpDir.path(), "points.shp"), "points", "ogr") + #l0.extent() + self.assertTrue(l0.isValid()) + self.assertTrue(project.addMapLayers([l0])) + self.assertTrue(project.write(tmpFile)) + + del project + + # Read the project.qgs as XML using etree and check that the maplayer extent is in the XML file + with open(tmpFile, "r") as f: + xml = f.read() + root = et.XML(xml) + layerXML = root.findall('.//projectlayers/maplayer')[0] + extentXML = layerXML.findall('.//extent')[0] + self.assertNotEqual(len(extentXML.getchildren()), 0) + + + + + + if __name__ == "__main__": unittest.main()