QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 = std::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 : std::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  if ( !sink->addFeature( feat, QgsFeatureSink::FastInsert ) )
152  throw QgsProcessingException( writeFeatureError( sink.get(), parameters, QStringLiteral( "OUTPUT" ) ) );
153 
154  feedback->setProgress( current++ * step );
155  }
156 
157  QVariantMap outputs;
158  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
159  return outputs;
160 }
161 
162 
163 //
164 // QgsLayerToBookmarksAlgorithm
165 //
166 
167 void QgsLayerToBookmarksAlgorithm::initAlgorithm( const QVariantMap & )
168 {
169  addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ), QList< int >() << QgsProcessing::TypeVectorLine << QgsProcessing::TypeVectorPolygon ) );
170 
171  std::unique_ptr< QgsProcessingParameterEnum > sourceParam = std::make_unique<QgsProcessingParameterEnum >( QStringLiteral( "DESTINATION" ), QObject::tr( "Bookmark destination" ), QStringList() <<
172  QObject::tr( "Project bookmarks" ) << QObject::tr( "User bookmarks" ), false, 0 );
173  addParameter( sourceParam.release() );
174 
175  addParameter( new QgsProcessingParameterExpression( QStringLiteral( "NAME_EXPRESSION" ), QObject::tr( "Name field" ), QVariant(), QStringLiteral( "INPUT" ) ) );
176  addParameter( new QgsProcessingParameterExpression( QStringLiteral( "GROUP_EXPRESSION" ), QObject::tr( "Group field" ), QVariant(), QStringLiteral( "INPUT" ), true ) );
177 
178  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "COUNT" ), QObject::tr( "Count of bookmarks added" ) ) );
179 }
180 
181 QString QgsLayerToBookmarksAlgorithm::name() const
182 {
183  return QStringLiteral( "layertobookmarks" );
184 }
185 
186 QString QgsLayerToBookmarksAlgorithm::displayName() const
187 {
188  return QObject::tr( "Convert layer to spatial bookmarks" );
189 }
190 
191 QStringList QgsLayerToBookmarksAlgorithm::tags() const
192 {
193  return QObject::tr( "save,extract,store" ).split( ',' );
194 }
195 
196 QString QgsLayerToBookmarksAlgorithm::group() const
197 {
198  return QObject::tr( "Vector general" );
199 }
200 
201 QString QgsLayerToBookmarksAlgorithm::groupId() const
202 {
203  return QStringLiteral( "vectorgeneral" );
204 }
205 
206 QString QgsLayerToBookmarksAlgorithm::shortHelpString() const
207 {
208  return QObject::tr( "This algorithm creates spatial bookmarks corresponding to the extent of features contained in a layer." );
209 }
210 
211 QString QgsLayerToBookmarksAlgorithm::shortDescription() const
212 {
213  return QObject::tr( "Converts feature extents to stored spatial bookmarks." );
214 }
215 
216 QIcon QgsLayerToBookmarksAlgorithm::icon() const
217 {
218  return QgsApplication::getThemeIcon( QStringLiteral( "mActionShowBookmarks.svg" ) );
219 }
220 
221 QString QgsLayerToBookmarksAlgorithm::svgIconPath() const
222 {
223  return QgsApplication::iconPath( QStringLiteral( "mActionShowBookmarks.svg" ) );
224 }
225 
226 QgsLayerToBookmarksAlgorithm *QgsLayerToBookmarksAlgorithm::createInstance() const
227 {
228  return new QgsLayerToBookmarksAlgorithm();
229 }
230 
231 QVariantMap QgsLayerToBookmarksAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
232 {
233  mDest = parameterAsEnum( parameters, QStringLiteral( "DESTINATION" ), context );
234  std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
235  if ( !source )
236  throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
237 
238 
239  QString nameExpressionString = parameterAsExpression( parameters, QStringLiteral( "NAME_EXPRESSION" ), context );
240  QString groupExpressionString = parameterAsExpression( parameters, QStringLiteral( "GROUP_EXPRESSION" ), context );
241 
242  QgsExpressionContext expressionContext = context.expressionContext();
243  expressionContext.appendScope( source->createExpressionContextScope() );
244 
245  QgsExpression nameExpression = QgsExpression( nameExpressionString );
246  if ( !nameExpression.prepare( &expressionContext ) )
247  throw QgsProcessingException( QObject::tr( "Invalid name expression: %1" ).arg( nameExpression.parserErrorString() ) );
248 
249  QSet< QString > requiredColumns = nameExpression.referencedColumns();
250 
251  std::unique_ptr< QgsExpression > groupExpression;
252  if ( !groupExpressionString.isEmpty() )
253  {
254  groupExpression = std::make_unique< QgsExpression >( groupExpressionString );
255  if ( !groupExpression->prepare( &expressionContext ) )
256  throw QgsProcessingException( QObject::tr( "Invalid group expression: %1" ).arg( groupExpression->parserErrorString() ) );
257  requiredColumns.unite( groupExpression->referencedColumns() );
258  }
259 
260  QgsFeatureRequest req;
261  req.setSubsetOfAttributes( requiredColumns, source->fields() );
262 
263  double step = source->featureCount() > 0 ? 100.0 / source->featureCount() : 1;
265  QgsFeature f;
266  int current = 0;
267  while ( fi.nextFeature( f ) )
268  {
269  if ( feedback->isCanceled() )
270  {
271  break;
272  }
273 
274  if ( f.hasGeometry() )
275  {
276  const QgsReferencedRectangle extent( f.geometry().boundingBox(), source->sourceCrs() );
277  expressionContext.setFeature( f );
278  const QString name = nameExpression.evaluate( &expressionContext ).toString();
279  if ( !nameExpression.evalErrorString().isEmpty() )
280  {
281  feedback->reportError( QObject::tr( "Error evaluating name expression: %1" ).arg( nameExpression.evalErrorString() ) );
282  feedback->setProgress( current * step );
283  current++;
284  continue;
285  }
286  QString group;
287  if ( groupExpression )
288  {
289  group = groupExpression->evaluate( &expressionContext ).toString();
290  if ( !groupExpression->evalErrorString().isEmpty() )
291  {
292  feedback->reportError( QObject::tr( "Error evaluating group expression: %1" ).arg( groupExpression->evalErrorString() ) );
293  feedback->setProgress( current * step );
294  current++;
295  continue;
296  }
297  }
298 
299  QgsBookmark b;
300  b.setName( name );
301  b.setGroup( group );
302  b.setExtent( extent );
303  mBookmarks << b;
304  }
305  feedback->setProgress( current * step );
306  current++;
307  }
308 
309  return QVariantMap();
310 }
311 
312 QVariantMap QgsLayerToBookmarksAlgorithm::postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback * )
313 {
314  QgsBookmarkManager *dest = nullptr;
315  switch ( mDest )
316  {
317  case 0:
318  dest = context.project()->bookmarkManager();
319  break;
320 
321  case 1:
323  break;
324  }
325 
326  for ( const QgsBookmark &b : std::as_const( mBookmarks ) )
327  dest->addBookmark( b );
328 
329  QVariantMap res;
330  res.insert( QStringLiteral( "COUNT" ), mBookmarks.size() );
331  return res;
332 }
333 
335 
336 
337 
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:406
QgsFeedback::setProgress
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:76
QgsExpression::evalErrorString
QString evalErrorString() const
Returns evaluation error.
Definition: qgsexpression.cpp:383
QgsProcessingContext::project
QgsProject * project() const
Returns the project in which the algorithm is being executed.
Definition: qgsprocessingcontext.h:121
QgsExpression::referencedColumns
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
Definition: qgsexpression.cpp:221
QgsReferencedRectangle
A QgsRectangle with associated coordinate reference system.
Definition: qgsreferencedgeometry.h:73
QgsProcessingFeedback
Base class for providing feedback from a processing algorithm.
Definition: qgsprocessingfeedback.h:37
QgsGeometry::transform
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Definition: qgsgeometry.cpp:3128
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:105
QgsProcessingFeedback::reportError
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
Definition: qgsprocessingfeedback.cpp:59
QgsProcessing::TypeVectorPolygon
@ TypeVectorPolygon
Vector polygon layers.
Definition: qgsprocessing.h:51
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:44
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsFeedback::isCanceled
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.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:78
QgsProcessing::TypeVectorLine
@ TypeVectorLine
Vector line layers.
Definition: qgsprocessing.h:50
QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks
@ FlagSkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Definition: qgsprocessingutils.h:584
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:3057
QgsFeatureRequest::setSubsetOfAttributes
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Definition: qgsfeaturerequest.cpp:228
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:682
QgsBookmarkManager::addBookmark
QString addBookmark(const QgsBookmark &bookmark, bool *ok=nullptr)
Adds a bookmark to the manager.
Definition: qgsbookmarkmanager.cpp:126
QgsProcessingOutputNumber
A numeric output for processing algorithms.
Definition: qgsprocessingoutputs.h:312
QgsProcessingParameterFeatureSink
A feature sink output for processing algorithms.
Definition: qgsprocessingparameters.h:3219
qgsapplication.h
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:83
QgsProject::bookmarkManager
const QgsBookmarkManager * bookmarkManager() const
Returns the project's bookmark manager, which manages bookmarks within the project.
Definition: qgsproject.cpp:3481
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
QgsBookmarkManager::bookmarks
QList< QgsBookmark > bookmarks() const
Returns a list of all bookmarks contained in the manager.
Definition: qgsbookmarkmanager.cpp:252
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:2263
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:170
QgsExpression::parserErrorString
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.cpp:211
QgsProcessingParameterCrs
A coordinate reference system parameter for processing algorithms.
Definition: qgsprocessingparameters.h:1740
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:88
QgsProcessingContext
Contains information about the context in which a processing algorithm is executed.
Definition: qgsprocessingcontext.h:46
QgsBookmark
Represents a spatial bookmark, with a name, CRS and extent.
Definition: qgsbookmarkmanager.h:37
QgsProcessingContext::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Definition: qgsprocessingcontext.h:165
QgsApplication::bookmarkManager
static QgsBookmarkManager * bookmarkManager()
Returns the application's bookmark manager, used for storing installation-wide bookmarks.
Definition: qgsapplication.cpp:2425
QgsExpression::prepare
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
Definition: qgsexpression.cpp:327
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:211
QgsExpression::evaluate
QVariant evaluate()
Evaluate the feature and return the result.
Definition: qgsexpression.cpp:350
QgsExpressionContext::appendScope
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Definition: qgsexpressioncontext.cpp:494
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:399
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:230
QgsProcessingParameterExpression
An expression parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2739
QgsWkbTypes::Polygon
@ Polygon
Definition: qgswkbtypes.h:74
QgsProcessingContext::expressionContext
QgsExpressionContext & expressionContext()
Returns the expression context.
Definition: qgsprocessingcontext.h:149
QgsGeometry::fromRect
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
Definition: qgsgeometry.cpp:241
QgsGeometry::boundingBox
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Definition: qgsgeometry.cpp:1080
QgsAttributes
A vector of attributes. Mostly equal to QVector<QVariant>.
Definition: qgsattributes.h:57
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Definition: qgsapplication.cpp:693
QgsFeature::setAttributes
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:160
QgsExpression
Class for parsing and evaluation of expressions (formerly called "search strings")....
Definition: qgsexpression.h:102
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
QgsFeatureIterator
Wrapper for iterator of features from vector data provider or vector layer.
Definition: qgsfeatureiterator.h:289
QgsBookmark::setExtent
void setExtent(const QgsReferencedRectangle &extent)
Sets the bookmark's spatial extent.
Definition: qgsbookmarkmanager.cpp:98
qgsbookmarkalgorithms.h
QgsProcessingException
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
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:525
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50