Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Don't reset metadata when changing a layer's source
Fixes #42821
Fixes #39226
  • Loading branch information
nyalldawson committed May 4, 2021
1 parent b4f1090 commit bdf8b79
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 2 deletions.
8 changes: 7 additions & 1 deletion src/core/vector/qgsvectorlayer.cpp
Expand Up @@ -1783,7 +1783,13 @@ bool QgsVectorLayer::setDataProvider( QString const &provider, const QgsDataProv
profile->switchTask( tr( "Read layer metadata" ) );
if ( mDataProvider->capabilities() & QgsVectorDataProvider::ReadLayerMetadata )
{
setMetadata( mDataProvider->layerMetadata() );
// we combine the provider metadata with the layer's existing metadata, so as not to reset any user customisations to the metadata
// back to the default if a layer's data source is changed
QgsLayerMetadata newMetadata = mDataProvider->layerMetadata();
// this overwrites the provider metadata with any properties which are non-empty from the existing layer metadata
newMetadata.combine( &mMetadata );

setMetadata( newMetadata );
QgsDebugMsgLevel( QStringLiteral( "Set Data provider QgsLayerMetadata identifier[%1]" ).arg( metadata().identifier() ), 4 );
}

Expand Down
36 changes: 35 additions & 1 deletion tests/src/python/test_qgsmaplayer.py
Expand Up @@ -20,7 +20,8 @@
from qgis.core import (QgsReadWriteContext,
QgsVectorLayer,
QgsRasterLayer,
QgsProject)
QgsProject,
QgsLayerMetadata)
from qgis.testing import start_app, unittest
from qgis.PyQt.QtXml import QDomDocument
from qgis.PyQt.QtCore import QTemporaryDir
Expand Down Expand Up @@ -200,6 +201,39 @@ def testQgsMapLayerProject(self):
project2.removeMapLayer(layer)
self.assertTrue(sip.isdeleted(layer))

def testRetainLayerMetadataWhenChangingDataSource(self):
"""
Test that we retain existing layer metadata when a layer's source is changed
"""
vl = QgsVectorLayer(os.path.join(TEST_DATA_DIR, 'points.shp'), "layer", "ogr")

metadata = QgsLayerMetadata()
metadata.setRights(['original right 1', 'original right 2'])
metadata.setAbstract('original abstract')
vl.setMetadata(metadata)

# now change layer datasource to one which has embedded provider medata
datasource = os.path.join(unitTestDataPath(), 'gdb_metadata.gdb')
vl.setDataSource(datasource, 'test', 'ogr')
self.assertTrue(vl.isValid())

# these settings weren't present in the original layer metadata, so should have been taken from the GDB file
self.assertEqual(vl.metadata().identifier(), 'Test')
self.assertEqual(vl.metadata().title(), 'Title')
self.assertEqual(vl.metadata().type(), 'dataset')
self.assertEqual(vl.metadata().language(), 'ENG')
self.assertEqual(vl.metadata().keywords(), {'Search keys': ['Tags']})
self.assertEqual(vl.metadata().constraints()[0].type, 'Limitations of use')
self.assertEqual(vl.metadata().constraints()[0].constraint, 'This is the use limitation')
self.assertEqual(vl.metadata().extent().spatialExtents()[0].bounds.xMinimum(), 1)
self.assertEqual(vl.metadata().extent().spatialExtents()[0].bounds.xMaximum(), 2)
self.assertEqual(vl.metadata().extent().spatialExtents()[0].bounds.yMinimum(), 3)
self.assertEqual(vl.metadata().extent().spatialExtents()[0].bounds.yMaximum(), 4)

# these setting WERE present, so must be retained
self.assertIn('original abstract', vl.metadata().abstract())
self.assertEqual(vl.metadata().rights(), ['original right 1', 'original right 2'])


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

0 comments on commit bdf8b79

Please sign in to comment.