QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsbookmarkalgorithms.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsbookmarkalgorithms.cpp
3  ---------------------
4  begin : September 2019
5  copyright : (C) 2019 by Nyall Dawson
6  email : nyall dot dawson 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 
18 #include "qgsbookmarkalgorithms.h"
19 #include "qgsapplication.h"
20 
22 
23 //
24 // QgsBookmarksToLayerAlgorithm
25 //
26 
27 void QgsBookmarksToLayerAlgorithm::initAlgorithm( const QVariantMap & )
28 {
29  std::unique_ptr< QgsProcessingParameterEnum > sourceParam = qgis::make_unique<QgsProcessingParameterEnum >( QStringLiteral( "SOURCE" ), QObject::tr( "Bookmark source" ), QStringList() <<
30  QObject::tr( "Project bookmarks" ) << QObject::tr( "User bookmarks" ), true, QVariantList() << 0 << 1 );
31  QVariantMap wrapperMetadata;
32  wrapperMetadata.insert( QStringLiteral( "useCheckBoxes" ), true );
33  QVariantMap metadata;
34  metadata.insert( QStringLiteral( "widget_wrapper" ), wrapperMetadata );
35  sourceParam->setMetadata( metadata );
36  addParameter( sourceParam.release() );
37  addParameter( new QgsProcessingParameterCrs( QStringLiteral( "CRS" ), QObject::tr( "Output CRS" ), QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) ) );
38  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Output" ), QgsProcessing::TypeVectorPolygon ) );
39 }
40 
41 QString QgsBookmarksToLayerAlgorithm::name() const
42 {
43  return QStringLiteral( "bookmarkstolayer" );
44 }
45 
46 QString QgsBookmarksToLayerAlgorithm::displayName() const
47 {
48  return QObject::tr( "Convert spatial bookmarks to layer" );
49 }
50 
51 QStringList QgsBookmarksToLayerAlgorithm::tags() const
52 {
53  return QObject::tr( "save,extract" ).split( ',' );
54 }
55 
56 QString QgsBookmarksToLayerAlgorithm::group() const
57 {
58  return QObject::tr( "Vector general" );
59 }
60 
61 QString QgsBookmarksToLayerAlgorithm::groupId() const
62 {
63  return QStringLiteral( "vectorgeneral" );
64 }
65 
66 QString QgsBookmarksToLayerAlgorithm::shortHelpString() const
67 {
68  return QObject::tr( "This algorithm creates a new layer containing polygon features for stored spatial bookmarks.\n\n"
69  "The export can be filtered to only bookmarks belonging to the current project, to all user bookmarks, or a combination of both." );
70 }
71 
72 QString QgsBookmarksToLayerAlgorithm::shortDescription() const
73 {
74  return QObject::tr( "Converts stored spatial bookmarks to a polygon layer." );
75 }
76 
77 QIcon QgsBookmarksToLayerAlgorithm::icon() const
78 {
79  return QgsApplication::getThemeIcon( QStringLiteral( "mActionShowBookmarks.svg" ) );
80 }
81 
82 QString QgsBookmarksToLayerAlgorithm::svgIconPath() const
83 {
84  return QgsApplication::iconPath( QStringLiteral( "mActionShowBookmarks.svg" ) );
85 }
86 
87 QgsBookmarksToLayerAlgorithm *QgsBookmarksToLayerAlgorithm::createInstance() const
88 {
89  return new QgsBookmarksToLayerAlgorithm();
90 }
91 
92 bool QgsBookmarksToLayerAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
93 {
94  QList< int > sources = parameterAsEnums( parameters, QStringLiteral( "SOURCE" ), context );
95  if ( sources.contains( 0 ) )
96  {
97  if ( !context.project() )
98  throw QgsProcessingException( QObject::tr( "No project is available for bookmark extraction" ) );
99  mBookmarks.append( context.project()->bookmarkManager()->bookmarks() );
100  }
101  if ( sources.contains( 1 ) )
102  mBookmarks.append( QgsApplication::bookmarkManager()->bookmarks() );
103 
104  return true;
105 }
106 
107 QVariantMap QgsBookmarksToLayerAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
108 {
109  const QgsCoordinateReferenceSystem crs = parameterAsCrs( parameters, QStringLiteral( "CRS" ), context );
110  QgsFields fields;
111  fields.append( QgsField( QStringLiteral( "name" ), QVariant::String ) );
112  fields.append( QgsField( QStringLiteral( "group" ), QVariant::String ) );
113  QString dest;
114  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, QgsWkbTypes::Polygon, crs ) );
115  if ( !sink )
116  throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
117 
118  int count = mBookmarks.count();
119  int current = 0;
120  double step = count > 0 ? 100.0 / count : 1;
121 
122  for ( const QgsBookmark &b : qgis::as_const( mBookmarks ) )
123  {
124  if ( feedback->isCanceled() )
125  {
126  break;
127  }
128 
129  QgsFeature feat;
130  feat.setAttributes( QgsAttributes() << b.name() << b.group() );
131 
132  QgsGeometry geom = QgsGeometry::fromRect( b.extent() );
133  if ( b.extent().crs() != crs )
134  {
135  QgsCoordinateTransform xform( b.extent().crs(), crs, context.transformContext() );
136  geom = geom.densifyByCount( 20 );
137  try
138  {
139  geom.transform( xform );
140  }
141  catch ( QgsCsException & )
142  {
143  feedback->reportError( QObject::tr( "Could not reproject bookmark %1 to destination CRS" ).arg( b.name() ) );
144  feedback->setProgress( current++ * step );
145  continue;
146  }
147  }
148 
149  feat.setGeometry( geom );
150 
151  sink->addFeature( feat, QgsFeatureSink::FastInsert );
152 
153  feedback->setProgress( current++ * step );
154  }
155 
156  QVariantMap outputs;
157  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
158  return outputs;
159 }
160 
161 
162 //
163 // QgsLayerToBookmarksAlgorithm
164 //
165 
166 void QgsLayerToBookmarksAlgorithm::initAlgorithm( const QVariantMap & )
167 {
168  addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ), QList< int >() << QgsProcessing::TypeVectorLine << QgsProcessing::TypeVectorPolygon ) );
169 
170  std::unique_ptr< QgsProcessingParameterEnum > sourceParam = qgis::make_unique<QgsProcessingParameterEnum >( QStringLiteral( "DESTINATION" ), QObject::tr( "Bookmark destination" ), QStringList() <<
171  QObject::tr( "Project bookmarks" ) << QObject::tr( "User bookmarks" ), false, 0 );
172  addParameter( sourceParam.release() );
173 
174  addParameter( new QgsProcessingParameterExpression( QStringLiteral( "NAME_EXPRESSION" ), QObject::tr( "Name field" ), QVariant(), QStringLiteral( "INPUT" ) ) );
175  addParameter( new QgsProcessingParameterExpression( QStringLiteral( "GROUP_EXPRESSION" ), QObject::tr( "Group field" ), QVariant(), QStringLiteral( "INPUT" ), true ) );
176 
177  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "COUNT" ), QObject::tr( "Count of bookmarks added" ) ) );
178 }
179 
180 QString QgsLayerToBookmarksAlgorithm::name() const
181 {
182  return QStringLiteral( "layertobookmarks" );
183 }
184 
185 QString QgsLayerToBookmarksAlgorithm::displayName() const
186 {
187  return QObject::tr( "Convert layer to spatial bookmarks" );
188 }
189 
190 QStringList QgsLayerToBookmarksAlgorithm::tags() const
191 {
192  return QObject::tr( "save,extract,store" ).split( ',' );
193 }
194 
195 QString QgsLayerToBookmarksAlgorithm::group() const
196 {
197  return QObject::tr( "Vector general" );
198 }
199 
200 QString QgsLayerToBookmarksAlgorithm::groupId() const
201 {
202  return QStringLiteral( "vectorgeneral" );
203 }
204 
205 QString QgsLayerToBookmarksAlgorithm::shortHelpString() const
206 {
207  return QObject::tr( "This algorithm creates spatial bookmarks corresponding to the extent of features contained in a layer." );
208 }
209 
210 QString QgsLayerToBookmarksAlgorithm::shortDescription() const
211 {
212  return QObject::tr( "Converts feature extents to stored spatial bookmarks." );
213 }
214 
215 QIcon QgsLayerToBookmarksAlgorithm::icon() const
216 {
217  return QgsApplication::getThemeIcon( QStringLiteral( "mActionShowBookmarks.svg" ) );
218 }
219 
220 QString QgsLayerToBookmarksAlgorithm::svgIconPath() const
221 {
222  return QgsApplication::iconPath( QStringLiteral( "mActionShowBookmarks.svg" ) );
223 }
224 
225 QgsLayerToBookmarksAlgorithm *QgsLayerToBookmarksAlgorithm::createInstance() const
226 {
227  return new QgsLayerToBookmarksAlgorithm();
228 }
229 
230 QVariantMap QgsLayerToBookmarksAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
231 {
232  mDest = parameterAsEnum( parameters, QStringLiteral( "DESTINATION" ), context );
233  std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
234  if ( !source )
235  throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
236 
237 
238  QString nameExpressionString = parameterAsExpression( parameters, QStringLiteral( "NAME_EXPRESSION" ), context );
239  QString groupExpressionString = parameterAsExpression( parameters, QStringLiteral( "GROUP_EXPRESSION" ), context );
240 
241  QgsExpressionContext expressionContext = context.expressionContext();
242  expressionContext.appendScope( source->createExpressionContextScope() );
243 
244  QgsExpression nameExpression = QgsExpression( nameExpressionString );
245  if ( !nameExpression.prepare( &expressionContext ) )
246  throw QgsProcessingException( QObject::tr( "Invalid name expression: %1" ).arg( nameExpression.parserErrorString() ) );
247 
248  QSet< QString > requiredColumns = nameExpression.referencedColumns();
249 
250  std::unique_ptr< QgsExpression > groupExpression;
251  if ( !groupExpressionString.isEmpty() )
252  {
253  groupExpression = qgis::make_unique< QgsExpression >( groupExpressionString );
254  if ( !groupExpression->prepare( &expressionContext ) )
255  throw QgsProcessingException( QObject::tr( "Invalid group expression: %1" ).arg( groupExpression->parserErrorString() ) );
256  requiredColumns.unite( groupExpression->referencedColumns() );
257  }
258 
259  QgsFeatureRequest req;
260  req.setSubsetOfAttributes( requiredColumns, source->fields() );
261 
262  double step = source->featureCount() > 0 ? 100.0 / source->featureCount() : 1;
264  QgsFeature f;
265  int current = 0;
266  while ( fi.nextFeature( f ) )
267  {
268  if ( feedback->isCanceled() )
269  {
270  break;
271  }
272 
273  if ( f.hasGeometry() )
274  {
275  const QgsReferencedRectangle extent( f.geometry().boundingBox(), source->sourceCrs() );
276  expressionContext.setFeature( f );
277  const QString name = nameExpression.evaluate( &expressionContext ).toString();
278  if ( !nameExpression.evalErrorString().isEmpty() )
279  {
280  feedback->reportError( QObject::tr( "Error evaluating name expression: %1" ).arg( nameExpression.evalErrorString() ) );
281  feedback->setProgress( current * step );
282  current++;
283  continue;
284  }
285  QString group;
286  if ( groupExpression )
287  {
288  group = groupExpression->evaluate( &expressionContext ).toString();
289  if ( !groupExpression->evalErrorString().isEmpty() )
290  {
291  feedback->reportError( QObject::tr( "Error evaluating group expression: %1" ).arg( groupExpression->evalErrorString() ) );
292  feedback->setProgress( current * step );
293  current++;
294  continue;
295  }
296  }
297 
298  QgsBookmark b;
299  b.setName( name );
300  b.setGroup( group );
301  b.setExtent( extent );
302  mBookmarks << b;
303  }
304  feedback->setProgress( current * step );
305  current++;
306  }
307 
308  return QVariantMap();
309 }
310 
311 QVariantMap QgsLayerToBookmarksAlgorithm::postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback * )
312 {
313  QgsBookmarkManager *dest = nullptr;
314  switch ( mDest )
315  {
316  case 0:
317  dest = context.project()->bookmarkManager();
318  break;
319 
320  case 1:
322  break;
323  }
324 
325  for ( const QgsBookmark &b : qgis::as_const( mBookmarks ) )
326  dest->addBookmark( b );
327 
328  QVariantMap res;
329  res.insert( QStringLiteral( "COUNT" ), mBookmarks.size() );
330  return res;
331 }
332 
334 
335 
336 
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:370
QgsFeedback::setProgress
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:62
QgsGeometry::transform
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Definition: qgsgeometry.cpp:2813
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:626
QgsExpression::evalErrorString
QString evalErrorString() const
Returns evaluation error.
Definition: qgsexpression.cpp:379
QgsProcessingContext::project
QgsProject * project() const
Returns the project in which the algorithm is being executed.
Definition: qgsprocessingcontext.h:105
QgsExpression::referencedColumns
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
Definition: qgsexpression.cpp:217
QgsReferencedRectangle
A QgsRectangle with associated coordinate reference system.
Definition: qgsreferencedgeometry.h:74
QgsProcessingFeedback
Base class for providing feedback from a processing algorithm.
Definition: qgsprocessingfeedback.h:38
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:51
QgsProcessingFeedback::reportError
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
Definition: qgsprocessingfeedback.cpp:39
QgsProcessing::TypeVectorPolygon
@ TypeVectorPolygon
Vector polygon layers.
Definition: qgsprocessing.h:50
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:45
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:67
QgsBookmark::setName
void setName(const QString &name)
Sets the bookmark's name, which is a user-visible string identifying the bookmark.
Definition: qgsbookmarkmanager.cpp:77
QgsProcessing::TypeVectorLine
@ TypeVectorLine
Vector line layers.
Definition: qgsprocessing.h:49
QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks
@ FlagSkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Definition: qgsprocessingutils.h:477
QgsBookmarkManager
Manages storage of a set of bookmarks.
Definition: qgsbookmarkmanager.h:145
QgsProcessingParameterFeatureSource
An input feature source (such as vector layers) parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2734
QgsFeatureRequest::setSubsetOfAttributes
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Definition: qgsfeaturerequest.cpp:185
QgsFields::append
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
QgsApplication::iconPath
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
Definition: qgsapplication.cpp:615
QgsBookmarkManager::addBookmark
QString addBookmark(const QgsBookmark &bookmark, bool *ok=nullptr)
Adds a bookmark to the manager.
Definition: qgsbookmarkmanager.cpp:125
QgsProcessingOutputNumber
A numeric output for processing algorithms.
Definition: qgsprocessingoutputs.h:295
QgsProcessingParameterFeatureSink
A feature sink output for processing algorithms.
Definition: qgsprocessingparameters.h:2895
qgsapplication.h
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:76
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
QgsBookmarkManager::bookmarks
QList< QgsBookmark > bookmarks() const
Returns a list of all bookmarks contained in the manager.
Definition: qgsbookmarkmanager.cpp:251
QgsGeometry::densifyByCount
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Returns a copy of the geometry which has been densified by adding the specified number of extra nodes...
Definition: qgsgeometry.cpp:2117
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:139
QgsExpression::parserErrorString
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.cpp:207
QgsProcessingParameterCrs
A coordinate reference system parameter for processing algorithms.
Definition: qgsprocessingparameters.h:1538
QgsBookmark::setGroup
void setGroup(const QString &group)
Sets the bookmark's group, which is a user-visible string identifying the bookmark's category.
Definition: qgsbookmarkmanager.cpp:87
QgsProcessingContext
Contains information about the context in which a processing algorithm is executed.
Definition: qgsprocessingcontext.h:44
QgsBookmark
Represents a spatial bookmark, with a name, CRS and extent.
Definition: qgsbookmarkmanager.h:38
QgsProcessingContext::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Definition: qgsprocessingcontext.h:149
QgsApplication::bookmarkManager
static QgsBookmarkManager * bookmarkManager()
Returns the application's bookmark manager, used for storing installation-wide bookmarks.
Definition: qgsapplication.cpp:2238
QgsExpression::prepare
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
Definition: qgsexpression.cpp:323
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:206
QgsExpression::evaluate
QVariant evaluate()
Evaluate the feature and return the result.
Definition: qgsexpression.cpp:346
QgsExpressionContext::appendScope
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Definition: qgsexpressioncontext.cpp:490
QgsProject::bookmarkManager
const QgsBookmarkManager * bookmarkManager() const
Returns the project's bookmark manager, which manages bookmarks within the project.
Definition: qgsproject.cpp:3060
QgsFeedback::isCanceled
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:53
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:374
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsFeature::hasGeometry
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:199
QgsProcessingParameterExpression
An expression parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2416
QgsWkbTypes::Polygon
@ Polygon
Definition: qgswkbtypes.h:74
QgsProcessingContext::expressionContext
QgsExpressionContext & expressionContext()
Returns the expression context.
Definition: qgsprocessingcontext.h:133
QgsGeometry::fromRect
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
Definition: qgsgeometry.cpp:229
QgsGeometry::boundingBox
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Definition: qgsgeometry.cpp:996
QgsAttributes
A vector of attributes.
Definition: qgsattributes.h:58
QgsFeature
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
QgsFeature::setAttributes
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:129
QgsExpression
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:105
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:53
QgsFeatureIterator
Wrapper for iterator of features from vector data provider or vector layer.
Definition: qgsfeatureiterator.h:265
QgsBookmark::setExtent
void setExtent(const QgsReferencedRectangle &extent)
Sets the bookmark's spatial extent.
Definition: qgsbookmarkmanager.cpp:97
qgsbookmarkalgorithms.h
QgsProcessingException
Custom exception class for processing related exceptions.
Definition: qgsexception.h:83
QgsFeatureSink::FastInsert
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
Definition: qgsfeaturesink.h:70
QgsExpressionContext::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Definition: qgsexpressioncontext.cpp:521
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50