QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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  mBookmarks.append( context.project()->bookmarkManager()->bookmarks() );
97  if ( sources.contains( 1 ) )
98  mBookmarks.append( QgsApplication::bookmarkManager()->bookmarks() );
99 
100  return true;
101 }
102 
103 QVariantMap QgsBookmarksToLayerAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
104 {
105  const QgsCoordinateReferenceSystem crs = parameterAsCrs( parameters, QStringLiteral( "CRS" ), context );
106  QgsFields fields;
107  fields.append( QgsField( QStringLiteral( "name" ), QVariant::String ) );
108  fields.append( QgsField( QStringLiteral( "group" ), QVariant::String ) );
109  QString dest;
110  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, QgsWkbTypes::Polygon, crs ) );
111  if ( !sink )
112  throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
113 
114  int count = mBookmarks.count();
115  int current = 0;
116  double step = count > 0 ? 100.0 / count : 1;
117 
118  for ( const QgsBookmark &b : qgis::as_const( mBookmarks ) )
119  {
120  if ( feedback->isCanceled() )
121  {
122  break;
123  }
124 
125  QgsFeature feat;
126  feat.setAttributes( QgsAttributes() << b.name() << b.group() );
127 
128  QgsGeometry geom = QgsGeometry::fromRect( b.extent() );
129  if ( b.extent().crs() != crs )
130  {
131  QgsCoordinateTransform xform( b.extent().crs(), crs, context.transformContext() );
132  geom = geom.densifyByCount( 20 );
133  try
134  {
135  geom.transform( xform );
136  }
137  catch ( QgsCsException & )
138  {
139  feedback->reportError( QObject::tr( "Could not reproject bookmark %1 to destination CRS" ).arg( b.name() ) );
140  feedback->setProgress( current++ * step );
141  continue;
142  }
143  }
144 
145  feat.setGeometry( geom );
146 
147  sink->addFeature( feat, QgsFeatureSink::FastInsert );
148 
149  feedback->setProgress( current++ * step );
150  }
151 
152  QVariantMap outputs;
153  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
154  return outputs;
155 }
156 
157 
158 //
159 // QgsLayerToBookmarksAlgorithm
160 //
161 
162 void QgsLayerToBookmarksAlgorithm::initAlgorithm( const QVariantMap & )
163 {
164  addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ), QList< int >() << QgsProcessing::TypeVectorLine << QgsProcessing::TypeVectorPolygon ) );
165 
166  std::unique_ptr< QgsProcessingParameterEnum > sourceParam = qgis::make_unique<QgsProcessingParameterEnum >( QStringLiteral( "DESTINATION" ), QObject::tr( "Bookmark destination" ), QStringList() <<
167  QObject::tr( "Project bookmarks" ) << QObject::tr( "User bookmarks" ), false, 0 );
168  addParameter( sourceParam.release() );
169 
170  addParameter( new QgsProcessingParameterExpression( QStringLiteral( "NAME_EXPRESSION" ), QObject::tr( "Name field" ), QVariant(), QStringLiteral( "INPUT" ) ) );
171  addParameter( new QgsProcessingParameterExpression( QStringLiteral( "GROUP_EXPRESSION" ), QObject::tr( "Group field" ), QVariant(), QStringLiteral( "INPUT" ), true ) );
172 
173  addOutput( new QgsProcessingOutputNumber( QStringLiteral( "COUNT" ), QObject::tr( "Count of bookmarks added" ) ) );
174 }
175 
176 QString QgsLayerToBookmarksAlgorithm::name() const
177 {
178  return QStringLiteral( "layertobookmarks" );
179 }
180 
181 QString QgsLayerToBookmarksAlgorithm::displayName() const
182 {
183  return QObject::tr( "Convert layer to spatial bookmarks" );
184 }
185 
186 QStringList QgsLayerToBookmarksAlgorithm::tags() const
187 {
188  return QObject::tr( "save,extract,store" ).split( ',' );
189 }
190 
191 QString QgsLayerToBookmarksAlgorithm::group() const
192 {
193  return QObject::tr( "Vector general" );
194 }
195 
196 QString QgsLayerToBookmarksAlgorithm::groupId() const
197 {
198  return QStringLiteral( "vectorgeneral" );
199 }
200 
201 QString QgsLayerToBookmarksAlgorithm::shortHelpString() const
202 {
203  return QObject::tr( "This algorithm creates spatial bookmarks corresponding to the extent of features contained in a layer." );
204 }
205 
206 QString QgsLayerToBookmarksAlgorithm::shortDescription() const
207 {
208  return QObject::tr( "Converts feature extents to stored spatial bookmarks." );
209 }
210 
211 QIcon QgsLayerToBookmarksAlgorithm::icon() const
212 {
213  return QgsApplication::getThemeIcon( QStringLiteral( "mActionShowBookmarks.svg" ) );
214 }
215 
216 QString QgsLayerToBookmarksAlgorithm::svgIconPath() const
217 {
218  return QgsApplication::iconPath( QStringLiteral( "mActionShowBookmarks.svg" ) );
219 }
220 
221 QgsLayerToBookmarksAlgorithm *QgsLayerToBookmarksAlgorithm::createInstance() const
222 {
223  return new QgsLayerToBookmarksAlgorithm();
224 }
225 
226 QVariantMap QgsLayerToBookmarksAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
227 {
228  mDest = parameterAsEnum( parameters, QStringLiteral( "DESTINATION" ), context );
229  std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
230  if ( !source )
231  throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
232 
233 
234  QString nameExpressionString = parameterAsExpression( parameters, QStringLiteral( "NAME_EXPRESSION" ), context );
235  QString groupExpressionString = parameterAsExpression( parameters, QStringLiteral( "GROUP_EXPRESSION" ), context );
236 
237  QgsExpressionContext expressionContext = context.expressionContext();
238  expressionContext.appendScope( source->createExpressionContextScope() );
239 
240  QgsExpression nameExpression = QgsExpression( nameExpressionString );
241  if ( !nameExpression.prepare( &expressionContext ) )
242  throw QgsProcessingException( QObject::tr( "Invalid name expression: %1" ).arg( nameExpression.parserErrorString() ) );
243 
244  QSet< QString > requiredColumns = nameExpression.referencedColumns();
245 
246  std::unique_ptr< QgsExpression > groupExpression;
247  if ( !groupExpressionString.isEmpty() )
248  {
249  groupExpression = qgis::make_unique< QgsExpression >( groupExpressionString );
250  if ( !groupExpression->prepare( &expressionContext ) )
251  throw QgsProcessingException( QObject::tr( "Invalid group expression: %1" ).arg( groupExpression->parserErrorString() ) );
252  requiredColumns.unite( groupExpression->referencedColumns() );
253  }
254 
255  QgsFeatureRequest req;
256  req.setSubsetOfAttributes( requiredColumns, source->fields() );
257 
258  double step = source->featureCount() > 0 ? 100.0 / source->featureCount() : 1;
260  QgsFeature f;
261  int current = 0;
262  while ( fi.nextFeature( f ) )
263  {
264  if ( feedback->isCanceled() )
265  {
266  break;
267  }
268 
269  if ( f.hasGeometry() )
270  {
271  const QgsReferencedRectangle extent( f.geometry().boundingBox(), source->sourceCrs() );
272  expressionContext.setFeature( f );
273  const QString name = nameExpression.evaluate( &expressionContext ).toString();
274  if ( !nameExpression.evalErrorString().isEmpty() )
275  {
276  feedback->reportError( QObject::tr( "Error evaluating name expression: %1" ).arg( nameExpression.evalErrorString() ) );
277  feedback->setProgress( current * step );
278  current++;
279  continue;
280  }
281  QString group;
282  if ( groupExpression )
283  {
284  group = groupExpression->evaluate( &expressionContext ).toString();
285  if ( !groupExpression->evalErrorString().isEmpty() )
286  {
287  feedback->reportError( QObject::tr( "Error evaluating group expression: %1" ).arg( groupExpression->evalErrorString() ) );
288  feedback->setProgress( current * step );
289  current++;
290  continue;
291  }
292  }
293 
294  QgsBookmark b;
295  b.setName( name );
296  b.setGroup( group );
297  b.setExtent( extent );
298  mBookmarks << b;
299  }
300  feedback->setProgress( current * step );
301  current++;
302  }
303 
304  return QVariantMap();
305 }
306 
307 QVariantMap QgsLayerToBookmarksAlgorithm::postProcessAlgorithm( QgsProcessingContext &context, QgsProcessingFeedback * )
308 {
309  QgsBookmarkManager *dest = nullptr;
310  switch ( mDest )
311  {
312  case 0:
313  dest = context.project()->bookmarkManager();
314  break;
315 
316  case 1:
318  break;
319  }
320 
321  for ( const QgsBookmark &b : qgis::as_const( mBookmarks ) )
322  dest->addBookmark( b );
323 
324  QVariantMap res;
325  res.insert( QStringLiteral( "COUNT" ), mBookmarks.size() );
326  return res;
327 }
328 
330 
331 
332 
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:369
QgsFeedback::setProgress
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:75
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:2836
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:605
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:99
QgsExpression::referencedColumns
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
Definition: qgsexpression.cpp:217
QgsReferencedRectangle
Definition: qgsreferencedgeometry.h:72
QgsProcessingFeedback
Definition: qgsprocessingfeedback.h:37
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:39
QgsProcessing::TypeVectorPolygon
@ TypeVectorPolygon
Vector polygon layers.
Definition: qgsprocessing.h:50
QgsFields
Definition: qgsfields.h:44
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
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:475
QgsBookmarkManager
Manages storage of a set of bookmarks.
Definition: qgsbookmarkmanager.h:144
QgsProcessingParameterFeatureSource
Definition: qgsprocessingparameters.h:2612
QgsFeatureRequest::setSubsetOfAttributes
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Definition: qgsfeaturerequest.cpp:190
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:594
QgsBookmarkManager::addBookmark
QString addBookmark(const QgsBookmark &bookmark, bool *ok=nullptr)
Adds a bookmark to the manager.
Definition: qgsbookmarkmanager.cpp:125
QgsProcessingOutputNumber
Definition: qgsprocessingoutputs.h:294
QgsGeometry::fromRect
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
Definition: qgsgeometry.cpp:229
QgsProcessingParameterFeatureSink
Definition: qgsprocessingparameters.h:2773
qgsapplication.h
QgsFeatureRequest
Definition: qgsfeaturerequest.h:75
QgsProject::bookmarkManager
const QgsBookmarkManager * bookmarkManager() const
Returns the project's bookmark manager, which manages bookmarks within the project.
Definition: qgsproject.cpp:2976
QgsCsException
Definition: qgsexception.h:65
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:2132
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:137
QgsExpression::parserErrorString
QString parserErrorString() const
Returns parser error.
Definition: qgsexpression.cpp:207
QgsProcessingParameterCrs
Definition: qgsprocessingparameters.h:1470
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
Definition: qgsprocessingcontext.h:43
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:135
QgsApplication::bookmarkManager
static QgsBookmarkManager * bookmarkManager()
Returns the application's bookmark manager, used for storing installation-wide bookmarks.
Definition: qgsapplication.cpp:2179
QgsExpression::prepare
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
Definition: qgsexpression.cpp:323
QgsCoordinateReferenceSystem
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
QgsFeedback::isCanceled
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:66
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:373
QgsGeometry
Definition: qgsgeometry.h:122
QgsFeature::hasGeometry
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
QgsProcessingParameterExpression
Definition: qgsprocessingparameters.h:2294
QgsWkbTypes::Polygon
@ Polygon
Definition: qgswkbtypes.h:73
QgsProcessingContext::expressionContext
QgsExpressionContext & expressionContext()
Returns the expression context.
Definition: qgsprocessingcontext.h:119
QgsGeometry::boundingBox
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Definition: qgsgeometry.cpp:962
QgsAttributes
Definition: qgsattributes.h:57
QgsFeature
Definition: qgsfeature.h:55
QgsFeature::setAttributes
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:127
QgsExpression
Definition: qgsexpression.h:113
QgsCoordinateTransform
Definition: qgscoordinatetransform.h:52
QgsFeatureIterator
Definition: qgsfeatureiterator.h:263
QgsBookmark::setExtent
void setExtent(const QgsReferencedRectangle &extent)
Sets the bookmark's spatial extent.
Definition: qgsbookmarkmanager.cpp:97
qgsbookmarkalgorithms.h
QgsProcessingException
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:521
QgsField
Definition: qgsfield.h:49