[api] Add option to QgsVectorFileWriter to store layer metadata for

created layer
This commit is contained in:
Nyall Dawson 2021-05-05 10:27:25 +10:00
parent 921e6fa1a1
commit 93b7a0c3d5
4 changed files with 116 additions and 3 deletions

View File

@ -135,6 +135,7 @@ Constructor for MetaData
ErrProjection,
ErrFeatureWriteFailed,
ErrInvalidLayer,
ErrSavingMetadata,
Canceled,
};
@ -393,6 +394,10 @@ Constructor
QgsFeedback *feedback;
FieldNameSource fieldNameSource;
bool saveMetadata;
QgsLayerMetadata layerMetadata;
};

View File

@ -3192,9 +3192,18 @@ QgsVectorFileWriter::WriterError QgsVectorFileWriter::writeAsVectorFormatV2( Pre
}
}
std::unique_ptr< QgsVectorFileWriter > writer( create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, options, QgsFeatureSink::SinkFlags(), newFilename, newLayer ) );
QString tempNewFilename;
QString tempNewLayer;
std::unique_ptr< QgsVectorFileWriter > writer( create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, options, QgsFeatureSink::SinkFlags(), &tempNewFilename, &tempNewLayer ) );
writer->setSymbologyScale( options.symbologyScale );
if ( newFilename )
*newFilename = tempNewFilename;
if ( newLayer )
*newLayer = tempNewLayer;
if ( newFilename )
{
QgsDebugMsgLevel( "newFilename = " + *newFilename, 2 );
@ -3335,7 +3344,44 @@ QgsVectorFileWriter::WriterError QgsVectorFileWriter::writeAsVectorFormatV2( Pre
*errorMessage += QObject::tr( "\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
}
return errors == 0 ? NoError : ErrFeatureWriteFailed;
writer.reset();
bool metadataFailure = false;
if ( options.saveMetadata )
{
QString uri = QgsProviderRegistry::instance()->encodeUri( QStringLiteral( "ogr" ), QVariantMap
{
{QStringLiteral( "path" ), tempNewFilename },
{QStringLiteral( "layerName" ), tempNewLayer }
} );
try
{
QString error;
if ( !QgsProviderRegistry::instance()->saveLayerMetadata( QStringLiteral( "ogr" ), uri, options.layerMetadata, error ) )
{
if ( errorMessage )
{
if ( !errorMessage->isEmpty() )
*errorMessage += '\n';
*errorMessage += error;
}
metadataFailure = true;
}
}
catch ( QgsNotSupportedException &e )
{
if ( errorMessage )
{
if ( !errorMessage->isEmpty() )
*errorMessage += '\n';
*errorMessage += e.what();
}
metadataFailure = true;
}
}
return errors == 0 ? ( !metadataFailure ? NoError : ErrSavingMetadata ) : ErrFeatureWriteFailed;
}
QgsVectorFileWriter::WriterError QgsVectorFileWriter::writeAsVectorFormat( QgsVectorLayer *layer,

View File

@ -177,6 +177,7 @@ class CORE_EXPORT QgsVectorFileWriter : public QgsFeatureSink
ErrProjection,
ErrFeatureWriteFailed,
ErrInvalidLayer,
ErrSavingMetadata, //!< Metadata saving failed
Canceled, //!< Writing was interrupted by manual cancellation
};
@ -533,6 +534,22 @@ class CORE_EXPORT QgsVectorFileWriter : public QgsFeatureSink
* \since QGIS 3.18
*/
FieldNameSource fieldNameSource = Original;
/**
* Set to TRUE to save layer metadata for the exported vector file.
*
* \see layerMetadata
* \since QGIS 3.20
*/
bool saveMetadata = false;
/**
* Layer metadata to save for the exported vector file. This will only be used if saveMetadata is TRUE.
*
* \see saveMetadata
* \since QGIS 3.20
*/
QgsLayerMetadata layerMetadata;
};
#ifndef SIP_RUN

View File

@ -33,7 +33,8 @@ from qgis.core import (QgsVectorLayer,
QgsFields,
QgsCoordinateTransformContext,
QgsFeatureSink,
QgsMemoryProviderUtils
QgsMemoryProviderUtils,
QgsLayerMetadata
)
from qgis.PyQt.QtCore import QDate, QTime, QDateTime, QVariant, QDir, QByteArray
import os
@ -1410,6 +1411,50 @@ class TestQgsVectorFileWriter(unittest.TestCase):
vl = QgsVectorLayer(dest_file_name)
self.assertTrue(vl.isValid())
def testPersistMetadata(self):
"""
Test that metadata from the source layer is saved as default for the destination if the
persist metadat option is enabled
"""
vl = QgsVectorLayer('Point?crs=epsg:4326&field=int:integer', 'test', 'memory')
self.assertTrue(vl.startEditing())
f = QgsFeature(vl.fields())
f.setGeometry(QgsGeometry.fromWkt('point(9 45)'))
f.setAttribute(0, 'QGIS Rocks!') # not valid!
self.assertTrue(vl.addFeatures([f]))
f.setAttribute(0, 12345) # valid!
self.assertTrue(vl.addFeatures([f]))
# set some metadata on the source layer
metadata = QgsLayerMetadata()
metadata.setTitle('my title')
metadata.setAbstract('my abstract')
metadata.setLicenses(['l1', 'l2'])
dest_file_name = os.path.join(str(QDir.tempPath()), 'save_metadata.gpkg')
options = QgsVectorFileWriter.SaveVectorOptions()
options.driverName = 'GPKG'
options.layerName = 'test'
options.saveMetadata = True
options.layerMetadata = metadata
write_result, error_message, new_file, new_layer = QgsVectorFileWriter.writeAsVectorFormatV3(
vl,
dest_file_name,
QgsProject.instance().transformContext(),
options)
self.assertEqual(write_result, QgsVectorFileWriter.ErrFeatureWriteFailed, error_message)
# Open result and check
created_layer = QgsVectorLayer(f'{new_file}|layerName={new_layer}', 'test', 'ogr')
self.assertTrue(created_layer.isValid())
# layer should have metadata stored
self.assertEqual(created_layer.metadata().title(), 'my title')
self.assertEqual(created_layer.metadata().abstract(), 'my abstract')
self.assertEqual(created_layer.metadata().licenses(), ['l1', 'l2'])
if __name__ == '__main__':
unittest.main()