Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsvectorlayerutils.h
3 : : ---------------------
4 : : Date : October 2016
5 : : Copyright : (C) 2016 by Nyall Dawson
6 : : Email : nyall dot dawson at gmail dot com
7 : : ***************************************************************************
8 : : * *
9 : : * This program is free software; you can redistribute it and/or modify *
10 : : * it under the terms of the GNU General Public License as published by *
11 : : * the Free Software Foundation; either version 2 of the License, or *
12 : : * (at your option) any later version. *
13 : : * *
14 : : ***************************************************************************/
15 : :
16 : : #ifndef QGSVECTORLAYERUTILS_H
17 : : #define QGSVECTORLAYERUTILS_H
18 : :
19 : : #include "qgis_core.h"
20 : : #include "qgsgeometry.h"
21 : : #include "qgsvectorlayerfeatureiterator.h"
22 : : #include "qgssymbollayerreference.h"
23 : : #include "qgsfeaturesink.h"
24 : :
25 : : class QgsFeatureRenderer;
26 : : class QgsSymbolLayer;
27 : :
28 : : /**
29 : : * \ingroup core
30 : : * \class QgsVectorLayerUtils
31 : : * \brief Contains utility methods for working with QgsVectorLayers.
32 : : *
33 : : * \since QGIS 3.0
34 : : */
35 : :
36 : : class CORE_EXPORT QgsVectorLayerUtils
37 : : {
38 : : public:
39 : :
40 : : /**
41 : : * \ingroup core
42 : : * \class QgsDuplicateFeatureContext
43 : : * \brief Contains mainly the QMap with QgsVectorLayer and QgsFeatureIds do list all the duplicated features
44 : : *
45 : : * \since QGIS 3.0
46 : : */
47 : : class CORE_EXPORT QgsDuplicateFeatureContext
48 : : {
49 : : public:
50 : :
51 : : //! Constructor for QgsDuplicateFeatureContext
52 : : QgsDuplicateFeatureContext() = default;
53 : :
54 : : /**
55 : : * Returns all the layers on which features have been duplicated
56 : : * \since QGIS 3.0
57 : : */
58 : : QList<QgsVectorLayer *> layers() const;
59 : :
60 : : /**
61 : : * Returns the duplicated features in the given layer
62 : : * \since QGIS 3.0
63 : : */
64 : : QgsFeatureIds duplicatedFeatures( QgsVectorLayer *layer ) const;
65 : :
66 : :
67 : : private:
68 : : QMap<QgsVectorLayer *, QgsFeatureIds> mDuplicatedFeatures;
69 : : friend class QgsVectorLayerUtils;
70 : :
71 : : /**
72 : : * To set info about duplicated features to the function feedback (layout and ids)
73 : : * \since QGIS 3.0
74 : : */
75 : : void setDuplicatedFeatures( QgsVectorLayer *layer, const QgsFeatureIds &ids );
76 : : };
77 : :
78 : : /**
79 : : * \ingroup core
80 : : * \class QgsFeatureData
81 : : * \brief Encapsulate geometry and attributes for new features, to be passed to createFeatures
82 : : * \see createFeatures()
83 : : * \since QGIS 3.6
84 : : */
85 : 3 : class CORE_EXPORT QgsFeatureData
86 : : {
87 : : public:
88 : :
89 : : /**
90 : : * Constructs a new QgsFeatureData with given \a geometry and \a attributes
91 : : */
92 : : QgsFeatureData( const QgsGeometry &geometry = QgsGeometry(), const QgsAttributeMap &attributes = QgsAttributeMap() );
93 : :
94 : : //! Returns geometry
95 : : QgsGeometry geometry() const;
96 : :
97 : : //! Returns attributes
98 : : QgsAttributeMap attributes() const;
99 : :
100 : : private:
101 : : QgsGeometry mGeometry;
102 : : QgsAttributeMap mAttributes;
103 : : };
104 : :
105 : : // SIP does not like "using", use legacy typedef
106 : : //! Alias for list of QgsFeatureData
107 : : typedef QList<QgsVectorLayerUtils::QgsFeatureData> QgsFeaturesDataList;
108 : :
109 : : /**
110 : : * Create a feature iterator for a specified field name or expression.
111 : : * \param layer vector layer to retrieve values from
112 : : * \param fieldOrExpression field name or an expression string
113 : : * \param ok will be set to FALSE if field or expression is invalid, otherwise TRUE
114 : : * \param selectedOnly set to TRUE to get values from selected features only
115 : : * \returns feature iterator
116 : : * \since QGIS 3.0
117 : : */
118 : : static QgsFeatureIterator getValuesIterator( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly );
119 : :
120 : : /**
121 : : * Fetches all values from a specified field name or expression.
122 : : * \param layer vector layer to retrieve values from
123 : : * \param fieldOrExpression field name or an expression string
124 : : * \param ok will be set to FALSE if field or expression is invalid, otherwise TRUE
125 : : * \param selectedOnly set to TRUE to get values from selected features only
126 : : * \param feedback optional feedback object to allow cancellation
127 : : * \returns list of fetched values
128 : : * \see getDoubleValues
129 : : * \since QGIS 3.0
130 : : */
131 : : static QList< QVariant > getValues( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly = false, QgsFeedback *feedback = nullptr );
132 : :
133 : : /**
134 : : * Fetches all double values from a specified field name or expression. Null values or
135 : : * invalid expression results are skipped.
136 : : * \param layer vector layer to retrieve values from
137 : : * \param fieldOrExpression field name or an expression string evaluating to a double value
138 : : * \param ok will be set to FALSE if field or expression is invalid, otherwise TRUE
139 : : * \param selectedOnly set to TRUE to get values from selected features only
140 : : * \param nullCount optional pointer to integer to store number of null values encountered in
141 : : * \param feedback optional feedback object to allow cancellation
142 : : * \returns list of fetched values
143 : : * \see getValues
144 : : * \since QGIS 3.0
145 : : */
146 : : static QList< double > getDoubleValues( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly = false, int *nullCount = nullptr, QgsFeedback *feedback = nullptr );
147 : :
148 : : /**
149 : : * Returns TRUE if the specified value already exists within a field. This method can be used to test for uniqueness
150 : : * of values inside a layer's attributes. An optional list of ignored feature IDs can be provided, if so, any features
151 : : * with IDs within this list are ignored when testing for existence of the value.
152 : : * \see createUniqueValue()
153 : : */
154 : : static bool valueExists( const QgsVectorLayer *layer, int fieldIndex, const QVariant &value, const QgsFeatureIds &ignoreIds = QgsFeatureIds() );
155 : :
156 : : /**
157 : : * Returns a new attribute value for the specified field index which is guaranteed to be unique. The optional seed
158 : : * value can be used as a basis for generated values.
159 : : * \see valueExists()
160 : : */
161 : : static QVariant createUniqueValue( const QgsVectorLayer *layer, int fieldIndex, const QVariant &seed = QVariant() );
162 : :
163 : : /**
164 : : * Returns a new attribute value for the specified field index which is guaranteed to
165 : : * be unique within regard to \a existingValues.
166 : : * The optional seed value can be used as a basis for generated values.
167 : : * \since QGIS 3.6
168 : : */
169 : : static QVariant createUniqueValueFromCache( const QgsVectorLayer *layer, int fieldIndex, const QSet<QVariant> &existingValues, const QVariant &seed = QVariant() );
170 : :
171 : : /**
172 : : * Tests an attribute value to check whether it passes all constraints which are present on the corresponding field.
173 : : * Returns TRUE if the attribute value is valid for the field. Any constraint failures will be reported in the errors argument.
174 : : * If the strength or origin parameter is set then only constraints with a matching strength/origin will be checked.
175 : : */
176 : : static bool validateAttribute( const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors SIP_OUT,
177 : : QgsFieldConstraints::ConstraintStrength strength = QgsFieldConstraints::ConstraintStrengthNotSet,
178 : : QgsFieldConstraints::ConstraintOrigin origin = QgsFieldConstraints::ConstraintOriginNotSet );
179 : :
180 : : /**
181 : : * Creates a new feature ready for insertion into a layer. Default values and constraints
182 : : * (e.g., unique constraints) will automatically be handled. An optional attribute map can be
183 : : * passed for the new feature to copy as many attribute values as possible from the map,
184 : : * assuming that they respect the layer's constraints. Note that the created feature is not
185 : : * automatically inserted into the layer.
186 : : * \see createFeatures()
187 : : */
188 : : static QgsFeature createFeature( const QgsVectorLayer *layer,
189 : : const QgsGeometry &geometry = QgsGeometry(),
190 : : const QgsAttributeMap &attributes = QgsAttributeMap(),
191 : : QgsExpressionContext *context = nullptr );
192 : :
193 : : /**
194 : : * Creates a set of new features ready for insertion into a layer. Default values and constraints
195 : : * (e.g., unique constraints) will automatically be handled. Note that the created features are not
196 : : * automatically inserted into the layer.
197 : : * \see createFeature()
198 : : * \since QGIS 3.6
199 : : */
200 : : static QgsFeatureList createFeatures( const QgsVectorLayer *layer,
201 : : const QgsFeaturesDataList &featuresData,
202 : : QgsExpressionContext *context = nullptr );
203 : :
204 : : /**
205 : : * Duplicates a feature and it's children (one level deep). It calls CreateFeature, so
206 : : * default values and constraints (e.g., unique constraints) will automatically be handled.
207 : : * The duplicated feature will be automatically inserted into the layer.
208 : : * \a duplicateFeatureContext stores all the layers and the featureids of the duplicated features (incl. children)
209 : : * \a maxDepth the maximum depth to duplicate children in relations, 0 is unlimited depth (in any case, limited to 100)
210 : : * \a depth the current depth, not exposed in Python
211 : : * \a referencedLayersBranch the current branch of layers across the relations, not exposed in Python, taken by copy not reference, used to avoid infinite loop
212 : : * \since QGIS 3.0
213 : : */
214 : : static QgsFeature duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, QgsDuplicateFeatureContext &duplicateFeatureContext SIP_OUT, const int maxDepth = 0, int depth SIP_PYARGREMOVE = 0, QList<QgsVectorLayer *> referencedLayersBranch SIP_PYARGREMOVE = QList<QgsVectorLayer *>() );
215 : :
216 : :
217 : : /**
218 : : * Gets the feature source from a QgsVectorLayer pointer.
219 : : * This method is thread-safe but will block the main thread for execution. Executing it from the main
220 : : * thread is safe too.
221 : : * This should be used in scenarios, where a ``QWeakPointer<QgsVectorLayer>`` is kept in a thread
222 : : * and features should be fetched from this layer. Using the layer directly is not safe to do.
223 : : * The result will be ``NULLPTR`` if the layer has been deleted.
224 : : * If \a feedback is specified, the call will return if the feedback is canceled.
225 : : * Returns a new feature source for the \a layer. The source may be NULLPTR if the layer no longer
226 : : * exists or if the feedback is canceled.
227 : : *
228 : : * \note Requires Qt >= 5.10 to make use of the thread-safe implementation
229 : : * \since QGIS 3.4
230 : : */
231 : : static std::unique_ptr<QgsVectorLayerFeatureSource> getFeatureSource( QPointer<QgsVectorLayer> layer, QgsFeedback *feedback = nullptr ) SIP_SKIP;
232 : :
233 : : /**
234 : : * Matches the attributes in \a feature to the specified \a fields.
235 : : *
236 : : * This causes the attributes contained within the given \a feature to be rearranged (or in
237 : : * some cases dropped) in order to match the fields and order indicated by \a fields.
238 : : *
239 : : * The exact behavior depends on whether or not \a feature has a valid fields container
240 : : * set (see QgsFeature::fields()). If a fields container is set, then the names of the
241 : : * feature's fields are matched to \a fields. In this case attributes from \a feature
242 : : * will be rearranged or dropped in order to match the field names from \a fields.
243 : : *
244 : : * If the \a feature does not have a valid fields container set, then the feature's attributes
245 : : * are simply truncated to match the number of fields present in \a fields (or if
246 : : * less attributes are present in \a feature than in \a fields, the feature's attributes
247 : : * are padded with NULL values to match the required length).
248 : : * Finally, the feature's fields are set to \a fields.
249 : : *
250 : : * \since QGIS 3.4
251 : : */
252 : : static void matchAttributesToFields( QgsFeature &feature, const QgsFields &fields );
253 : :
254 : : /**
255 : : * Converts input \a feature to be compatible with the given \a layer.
256 : : *
257 : : * This function returns a new list of transformed features compatible with the input
258 : : * layer, note that the number of features returned might be greater than one when
259 : : * converting a multi part geometry to single part
260 : : *
261 : : * The following operations will be performed to convert the input features:
262 : : *
263 : : * - convert single geometries to multi part
264 : : * - drop additional attributes
265 : : * - drop geometry if layer is geometry-less
266 : : * - add missing attribute fields
267 : : * - add back M/Z values (initialized to 0)
268 : : * - drop Z/M
269 : : * - convert multi part geometries to single part
270 : : *
271 : : * Optionally, \a sinkFlags can be specified to further refine the compatibility logic.
272 : : *
273 : : * \since QGIS 3.4
274 : : */
275 : : static QgsFeatureList makeFeatureCompatible( const QgsFeature &feature, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags = QgsFeatureSink::SinkFlags() );
276 : :
277 : : /**
278 : : * Converts input \a features to be compatible with the given \a layer.
279 : : *
280 : : * This function returns a new list of transformed features compatible with the input
281 : : * layer, note that the number of features returned might be greater than the number
282 : : * of input features.
283 : : *
284 : : * The following operations will be performed to convert the input features:
285 : : *
286 : : * - convert single geometries to multi part
287 : : * - drop additional attributes
288 : : * - drop geometry if layer is geometry-less
289 : : * - add missing attribute fields
290 : : * - add back M/Z values (initialized to 0)
291 : : * - drop Z/M
292 : : * - convert multi part geometries to single part
293 : : *
294 : : * Optionally, \a sinkFlags can be specified to further refine the compatibility logic.
295 : : *
296 : : * \since QGIS 3.4
297 : : */
298 : : static QgsFeatureList makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags = QgsFeatureSink::SinkFlags() );
299 : :
300 : : /**
301 : : * Tests whether a field is editable for a particular \a feature.
302 : : *
303 : : * \returns TRUE if the field at index \a fieldIndex from \a layer
304 : : * is editable, FALSE if the field is read only.
305 : : *
306 : : * \since QGIS 3.10
307 : : */
308 : : static bool fieldIsEditable( const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature );
309 : :
310 : : /**
311 : : * \returns TRUE if the field at index \a fieldIndex from \a layer
312 : : * is editable, FALSE if the field is read only.
313 : : *
314 : : * If this function returns TRUE then the editability of the field may still vary feature by
315 : : * feature. See fieldIsEditable() to determine this on a feature by feature basis.
316 : : *
317 : : * \since QGIS 3.18
318 : : */
319 : : static bool fieldIsReadOnly( const QgsVectorLayer *layer, int fieldIndex );
320 : :
321 : : /**
322 : : * Returns TRUE if the editability of the field at index \a fieldIndex from \a layer may vary
323 : : * feature by feature.
324 : : *
325 : : * I.e. if the field is taken from a joined layer, the value may or may not be editable for any individual
326 : : * feature depending on the join's "upsert on edit" capabilities.
327 : : *
328 : : * \since QGIS 3.18
329 : : */
330 : : static bool fieldEditabilityDependsOnFeature( const QgsVectorLayer *layer, int fieldIndex );
331 : :
332 : : /**
333 : : * Returns masks defined in labeling options of a layer.
334 : : * The returned type associates a labeling rule identifier to a set of layers that are masked given by their layer id,
335 : : * and a set of masked symbol layers if associated to each masked layers.
336 : : * \note Not available in Python bindings
337 : : * \since QGIS 3.12
338 : : */
339 : : static QHash<QString, QHash<QString, QSet<QgsSymbolLayerId>>> labelMasks( const QgsVectorLayer * ) SIP_SKIP;
340 : :
341 : : /**
342 : : * Returns all masks that may be defined on symbol layers for a given vector layer.
343 : : * The hash key is a layer id.
344 : : * The hash value is the set of symbol layers masked in the key's layer.
345 : : * \note Not available in Python bindings
346 : : * \since QGIS 3.12
347 : : */
348 : : static QHash<QString, QSet<QgsSymbolLayerId>> symbolLayerMasks( const QgsVectorLayer * ) SIP_SKIP;
349 : :
350 : : /**
351 : : * \returns a descriptive string for a \a feature, suitable for displaying to the user.
352 : : * The definition is taken from the ``displayExpression`` property of \a layer.
353 : : * \since QGIS 3.12
354 : : */
355 : : static QString getFeatureDisplayString( const QgsVectorLayer *layer, const QgsFeature &feature );
356 : :
357 : : /**
358 : : * Flags that can be used when determining cascaded features.
359 : : *
360 : : * \since QGIS 3.4
361 : : */
362 : : enum CascadedFeatureFlag
363 : : {
364 : : IgnoreAuxiliaryLayers = 1 << 1, //!< Ignore auxiliary layers
365 : : };
366 : : Q_DECLARE_FLAGS( CascadedFeatureFlags, CascadedFeatureFlag )
367 : :
368 : : /**
369 : : * \returns TRUE if at least one feature of the \a fids on \a layer is connected as parent in at
370 : : * least one composition relation of the \a project or contains joins, where cascade delete is set.
371 : : * Details about cascading effects will be written to \a context.
372 : : * \since QGIS 3.14
373 : : */
374 : : static bool impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context SIP_OUT, QgsVectorLayerUtils::CascadedFeatureFlags flags = QgsVectorLayerUtils::CascadedFeatureFlags() );
375 : :
376 : : /**
377 : : * Given a set of \a fields, attempts to pick the "most useful" field
378 : : * for user-friendly identification of features.
379 : : *
380 : : * For instance, if a field called "name" is present, this will be returned.
381 : : *
382 : : * Assumes that the user has organized the data with the more "interesting" field
383 : : * names first. As such, "name" would be selected before "oldname", "othername", etc.
384 : : *
385 : : * \since QGIS 3.18
386 : : */
387 : : static QString guessFriendlyIdentifierField( const QgsFields &fields );
388 : :
389 : : };
390 : :
391 : :
392 : : #endif // QGSVECTORLAYERUTILS_H
|