23 #include "qgssettings.h" 
   27 QString QgsPackageAlgorithm::name()
 const 
   29   return QStringLiteral( 
"package" );
 
   32 QString QgsPackageAlgorithm::displayName()
 const 
   34   return QObject::tr( 
"Package layers" );
 
   37 QStringList QgsPackageAlgorithm::tags()
 const 
   39   return QObject::tr( 
"geopackage,collect,merge,combine,styles" ).split( 
',' );
 
   42 QString QgsPackageAlgorithm::group()
 const 
   44   return QObject::tr( 
"Database" );
 
   47 QString QgsPackageAlgorithm::groupId()
 const 
   49   return QStringLiteral( 
"database" );
 
   52 void QgsPackageAlgorithm::initAlgorithm( 
const QVariantMap & )
 
   56   outputParameter->
setMetadata( QVariantMap( {{QStringLiteral( 
"widget_wrapper" ), QVariantMap( {{QStringLiteral( 
"dontconfirmoverwrite" ), 
true }} ) }} ) );
 
   57   addParameter( outputParameter );
 
   59   addParameter( 
new QgsProcessingParameterBoolean( QStringLiteral( 
"SAVE_STYLES" ), QObject::tr( 
"Save layer styles into GeoPackage" ), 
true ) );
 
   60   addParameter( 
new QgsProcessingParameterBoolean( QStringLiteral( 
"SAVE_METADATA" ), QObject::tr( 
"Save layer metadata into GeoPackage" ), 
true ) );
 
   61   addParameter( 
new QgsProcessingParameterBoolean( QStringLiteral( 
"SELECTED_FEATURES_ONLY" ), QObject::tr( 
"Save only selected features" ), 
false ) );
 
   65 QString QgsPackageAlgorithm::shortHelpString()
 const 
   67   return QObject::tr( 
"This algorithm collects a number of existing layers and packages them together into a single GeoPackage database." );
 
   70 QgsPackageAlgorithm *QgsPackageAlgorithm::createInstance()
 const 
   72   return new QgsPackageAlgorithm();
 
   77   const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral( 
"LAYERS" ), context );
 
   80     mLayers.emplace_back( layer->clone() );
 
   83   if ( mLayers.empty() )
 
   84     feedback->
reportError( QObject::tr( 
"No layers selected, geopackage will be empty" ), 
false );
 
   91   const bool overwrite = parameterAsBoolean( parameters, QStringLiteral( 
"OVERWRITE" ), context );
 
   92   const bool saveStyles = parameterAsBoolean( parameters, QStringLiteral( 
"SAVE_STYLES" ), context );
 
   93   const bool saveMetadata = parameterAsBoolean( parameters, QStringLiteral( 
"SAVE_METADATA" ), context );
 
   94   const bool selectedFeaturesOnly = parameterAsBoolean( parameters, QStringLiteral( 
"SELECTED_FEATURES_ONLY" ), context );
 
   95   QString packagePath = parameterAsString( parameters, QStringLiteral( 
"OUTPUT" ), context );
 
   96   if ( packagePath.isEmpty() )
 
  100   if ( overwrite && QFile::exists( packagePath ) )
 
  102     feedback->
pushInfo( QObject::tr( 
"Removing existing file '%1'" ).arg( packagePath ) );
 
  103     if ( !QFile( packagePath ).remove() )
 
  109   OGRSFDriverH hGpkgDriver = OGRGetDriverByName( 
"GPKG" );
 
  117   if ( !QFile::exists( packagePath ) )
 
  121       throw QgsProcessingException( QObject::tr( 
"Creation of database %1 failed (OGR error: %2)" ).arg( packagePath, QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
 
  127       throw QgsProcessingException( QObject::tr( 
"Opening database %1 failed (OGR error: %2)" ).arg( packagePath, QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
 
  131   bool errored = 
false;
 
  135   QStringList outputLayers;
 
  137   for ( 
const auto &layer : mLayers )
 
  142     multiStepFeedback.setCurrentStep( i );
 
  148       feedback->
pushDebugInfo( QObject::tr( 
"Error retrieving map layer." ) );
 
  153     feedback->
pushInfo( QObject::tr( 
"Packaging layer %1/%2: %3" ).arg( i ).arg( mLayers.size() ).arg( layer ? layer->name() : QString() ) );
 
  155     switch ( layer->type() )
 
  159         QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer.get() );
 
  161         if ( !packageVectorLayer( vectorLayer, packagePath, context, &multiStepFeedback, saveStyles, saveMetadata, onlySaveSelected ) )
 
  164           outputLayers.append( QStringLiteral( 
"%1|layername=%2" ).arg( packagePath, layer->name() ) );
 
  171         feedback->
pushDebugInfo( QObject::tr( 
"Packaging raster layers is not supported." ) );
 
  178         feedback->
pushDebugInfo( QObject::tr( 
"Packaging plugin layers is not supported." ) );
 
  184         feedback->
pushDebugInfo( QObject::tr( 
"Packaging mesh layers is not supported." ) );
 
  190         feedback->
pushDebugInfo( QObject::tr( 
"Packaging point cloud layers is not supported." ) );
 
  196         feedback->
pushDebugInfo( QObject::tr( 
"Packaging vector tile layers is not supported." ) );
 
  202         feedback->
pushDebugInfo( QObject::tr( 
"Packaging annotation layers is not supported." ) );
 
  212   outputs.insert( QStringLiteral( 
"OUTPUT" ), packagePath );
 
  213   outputs.insert( QStringLiteral( 
"OUTPUT_LAYERS" ), outputLayers );
 
  221   options.
driverName = QStringLiteral( 
"GPKG" );
 
  236   const int fidIndex = fields.
lookupField( QStringLiteral( 
"fid" ) );
 
  252     feedback->
reportError( QObject::tr( 
"Packaging layer failed: %1" ).arg( error ) );
 
  259       std::unique_ptr< QgsVectorLayer > res = std::make_unique< QgsVectorLayer >( QStringLiteral( 
"%1|layername=%2" ).arg( newFilename, newLayer ) );
 
  263         QDomDocument doc( QStringLiteral( 
"qgis" ) );
 
  266         if ( !errorMsg.isEmpty() )
 
  268           feedback->
reportError( QObject::tr( 
"Could not retrieve existing layer style: %1 " ).arg( errorMsg ) );
 
  272           if ( !res->importNamedStyle( doc, errorMsg ) )
 
  274             feedback->
reportError( QObject::tr( 
"Could not set existing layer style: %1 " ).arg( errorMsg ) );
 
  278             QgsSettings settings;
 
  280             QVariant prevOverwriteStyle = settings.value( QStringLiteral( 
"qgis/overwriteStyle" ) );
 
  281             settings.setValue( QStringLiteral( 
"qgis/overwriteStyle" ), 
true );
 
  282             res->saveStyleToDatabase( newLayer, QString(), 
true, QString(), errorMsg );
 
  283             settings.setValue( QStringLiteral( 
"qgis/overwriteStyle" ), prevOverwriteStyle );
 
  284             if ( !errorMsg.isEmpty() )
 
  286               feedback->
reportError( QObject::tr( 
"Could not save layer style: %1 " ).arg( errorMsg ) );
 
  293         feedback->
reportError( QObject::tr( 
"Could not save layer style -- error loading: %1 %2" ).arg( newFilename, newLayer ) );
 
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Container of fields for a vector layer.
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Base class for all map layer types.
virtual void exportNamedStyle(QDomDocument &doc, QString &errorMsg, const QgsReadWriteContext &context=QgsReadWriteContext(), QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const
Export the properties of this layer as named style in a QDomDocument.
QgsLayerMetadata metadata
Contains information about the context in which a processing algorithm is executed.
QString defaultEncoding() const
Returns the default encoding to use for newly created files.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
virtual void pushDebugInfo(const QString &info)
Pushes an informational message containing debugging helpers from the algorithm.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
Processing feedback object for multi-step operations.
A multi-layer output for processing algorithms which create map layers, when the number and nature of...
A boolean parameter for processing algorithms.
void setMetadata(const QVariantMap &metadata)
Sets the parameter's freeform metadata.
A generic file based destination parameter, for specifying the destination path for a file (non-map l...
A parameter for processing algorithms which accepts multiple map layers.
@ TypeVector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
The class is used as a container of context for various read/write operations on other objects.
Options to pass to writeAsVectorFormat()
QString fileEncoding
Encoding to use.
QString driverName
OGR driver to use.
QgsLayerMetadata layerMetadata
Layer metadata to save for the exported vector file.
QString layerName
Layer name. If let empty, it will be derived from the filename.
bool saveMetadata
Set to true to save layer metadata for the exported vector file.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
QgsAttributeList attributes
Attributes to export (empty means all unless skipAttributeCreation is set)
bool onlySelectedFeatures
Write only selected features of layer.
bool skipAttributeCreation
Only write geometries.
QgsFeedback * feedback
Optional feedback object allowing cancellation of layer save.
static QgsVectorFileWriter::WriterError writeAsVectorFormatV3(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *errorMessage=nullptr, QString *newFilename=nullptr, QString *newLayer=nullptr)
Writes a layer out to a vector file.
@ CreateOrOverwriteLayer
Create or overwrite layer.
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
@ PointCloudLayer
Added in 3.18.
@ VectorTileLayer
Added in 3.14.
@ AnnotationLayer
Contains freeform, georeferenced annotations. Added in QGIS 3.16.
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.