QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
qgsalgorithmexportlayersinformation.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmexportlayersinformation.cpp
3  ---------------------------------
4  begin : December 2020
5  copyright : (C) 2020 by Mathieu Pellerin
6  email : nirvn dot asia at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 #include "qgsproviderregistry.h"
20 
22 
23 QString QgsExportLayersInformationAlgorithm::name() const
24 {
25  return QStringLiteral( "exportlayersinformation" );
26 }
27 
28 QString QgsExportLayersInformationAlgorithm::displayName() const
29 {
30  return QObject::tr( "Export layer(s) information" );
31 }
32 
33 QStringList QgsExportLayersInformationAlgorithm::tags() const
34 {
35  return QObject::tr( "metadata,details,extent" ).split( ',' );
36 }
37 
38 QString QgsExportLayersInformationAlgorithm::group() const
39 {
40  return QObject::tr( "Layer tools" );
41 }
42 
43 QString QgsExportLayersInformationAlgorithm::groupId() const
44 {
45  return QStringLiteral( "layertools" );
46 }
47 
48 void QgsExportLayersInformationAlgorithm::initAlgorithm( const QVariantMap & )
49 {
50  addParameter( new QgsProcessingParameterMultipleLayers( QStringLiteral( "LAYERS" ), QObject::tr( "Input layer(s)" ), QgsProcessing::TypeMapLayer ) );
51  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Output" ), QgsProcessing::TypeVectorPolygon, QVariant() ) );
52 }
53 
54 QString QgsExportLayersInformationAlgorithm::shortHelpString() const
55 {
56  return QObject::tr( "Creates a polygon layer with features corresponding to the extent of selected layer(s).\n\n"
57  "Additional layer details - CRS, provider name, file path, layer name, subset filter, abstract and attribution - are attached as attributes to each feature." );
58 }
59 
60 QgsExportLayersInformationAlgorithm *QgsExportLayersInformationAlgorithm::createInstance() const
61 {
62  return new QgsExportLayersInformationAlgorithm();
63 }
64 
65 bool QgsExportLayersInformationAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
66 {
67  const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral( "LAYERS" ), context );
68  for ( QgsMapLayer *layer : layers )
69  {
70  if ( !mCrs.isValid() )
71  {
72  mCrs = layer->crs();
73  }
74  else if ( mCrs.authid() != QLatin1String( "EPSG:4326" ) )
75  {
76  if ( mCrs != layer->crs() )
77  {
78  // mixed CRSes, set output CRS to EPSG:4326
79  mCrs = QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) );
80  }
81  }
82  mLayers.emplace_back( layer->clone() );
83  }
84 
85  if ( !mCrs.isValid() )
86  mCrs = QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) );
87 
88  if ( mLayers.empty() )
89  feedback->reportError( QObject::tr( "No layers selected" ), false );
90 
91  return true;
92 }
93 
94 QVariantMap QgsExportLayersInformationAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
95 {
96  QgsFields outFields;
97  outFields.append( QgsField( QStringLiteral( "name" ), QVariant::String ) );
98  outFields.append( QgsField( QStringLiteral( "source" ), QVariant::String ) );
99  outFields.append( QgsField( QStringLiteral( "crs" ), QVariant::String ) );
100  outFields.append( QgsField( QStringLiteral( "provider" ), QVariant::String ) );
101  outFields.append( QgsField( QStringLiteral( "file_path" ), QVariant::String ) );
102  outFields.append( QgsField( QStringLiteral( "layer_name" ), QVariant::String ) );
103  outFields.append( QgsField( QStringLiteral( "subset" ), QVariant::String ) );
104  outFields.append( QgsField( QStringLiteral( "abstract" ), QVariant::String ) );
105  outFields.append( QgsField( QStringLiteral( "attribution" ), QVariant::String ) );
106 
107  QString outputDest;
108  std::unique_ptr< QgsFeatureSink > outputSink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, outputDest, outFields,
109  QgsWkbTypes::Polygon, mCrs ) );
110 
111  const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral( "LAYERS" ), context );
112 
113  const double step = layers.size() > 0 ? 100.0 / layers.size() : 1;
114  int i = 0;
115  for ( const std::unique_ptr< QgsMapLayer > &layer : mLayers )
116  {
117  i++;
118  if ( feedback->isCanceled() )
119  {
120  break;
121  }
122 
123  feedback->setProgress( i * step );
124 
125  QgsFeature feature;
126 
127  QgsAttributes attributes;
128  attributes << layer->name()
129  << layer->source()
130  << layer->crs().authid();
131  if ( layer->dataProvider() )
132  {
133  const QVariantMap parts = QgsProviderRegistry::instance()->decodeUri( layer->dataProvider()->name(), layer->source() );
134  attributes << layer->dataProvider()->name()
135  << parts[ QStringLiteral( "path" ) ]
136  << parts[ QStringLiteral( "layerName" ) ]
137  << parts[ QStringLiteral( "subset" ) ];
138  }
139  else
140  {
141  attributes << QVariant() << QVariant() << QVariant() << QVariant();
142  }
143  attributes << layer->metadata().rights().join( ';' )
144  << layer->abstract();
145  feature.setAttributes( attributes );
146 
147  QgsRectangle rect = layer->extent();
148  if ( !rect.isEmpty() )
149  {
150  if ( layer->crs() != mCrs )
151  {
152  QgsCoordinateTransform transform( layer->crs(), mCrs, context.transformContext() );
153  transform.setBallparkTransformsAreAppropriate( true );
154  try
155  {
156  rect = transform.transformBoundingBox( rect );
157  }
158  catch ( QgsCsException &e )
159  {
160  Q_UNUSED( e )
161  rect = QgsRectangle();
162  feedback->pushInfo( QObject::tr( "Extent of layer %1 could not be reprojected" ).arg( layer->name() ) );
163  }
164  }
165  feature.setGeometry( QgsGeometry::fromRect( rect ) );
166  }
167  if ( !outputSink->addFeature( feature, QgsFeatureSink::FastInsert ) )
168  throw QgsProcessingException( writeFeatureError( outputSink.get(), parameters, QStringLiteral( "OUTPUT" ) ) );
169  }
170 
171  QVariantMap outputs;
172  outputs.insert( QStringLiteral( "OUTPUT" ), outputDest );
173  return outputs;
174 }
175 
A vector of attributes.
Definition: qgsattributes.h:58
This class represents a coordinate reference system (CRS).
Class for doing transforms between two map coordinate systems.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:153
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:163
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:63
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
Container of fields for a vector layer.
Definition: qgsfields.h:45
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
Definition: qgsfields.cpp:59
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
Contains information about the context in which a processing algorithm is executed.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Custom exception class for processing related exceptions.
Definition: qgsexception.h:83
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 reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
A feature sink output for processing algorithms.
A parameter for processing algorithms which accepts multiple map layers.
@ TypeMapLayer
Any map layer type (raster, vector, mesh, point cloud, annotation or plugin layer)
Definition: qgsprocessing.h:47
@ TypeVectorPolygon
Vector polygon layers.
Definition: qgsprocessing.h:51
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:469