QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
qgsvectorlayerutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayerutils.cpp
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 #include <QRegularExpression>
17 
18 #include "qgsexpressioncontext.h"
19 #include "qgsfeatureiterator.h"
20 #include "qgsfeaturerequest.h"
21 #include "qgsvectorlayerutils.h"
22 #include "qgsvectordataprovider.h"
23 #include "qgsproject.h"
24 #include "qgsrelationmanager.h"
25 #include "qgsfeedback.h"
26 #include "qgsvectorlayer.h"
27 #include "qgsthreadingutils.h"
28 #include "qgsgeometrycollection.h"
30 #include "qgsmultisurface.h"
31 #include "qgsgeometryfactory.h"
32 #include "qgscurvepolygon.h"
33 #include "qgspolygon.h"
34 #include "qgslinestring.h"
35 #include "qgsmultipoint.h"
37 #include "qgsvectorlayerlabeling.h"
38 #include "qgspallabeling.h"
39 #include "qgsrenderer.h"
40 #include "qgssymbollayer.h"
41 #include "qgsstyleentityvisitor.h"
42 #include "qgsstyle.h"
43 #include "qgsauxiliarystorage.h"
45 
46 QgsFeatureIterator QgsVectorLayerUtils::getValuesIterator( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly )
47 {
48  std::unique_ptr<QgsExpression> expression;
49  QgsExpressionContext context;
50 
51  int attrNum = layer->fields().lookupField( fieldOrExpression );
52  if ( attrNum == -1 )
53  {
54  // try to use expression
55  expression.reset( new QgsExpression( fieldOrExpression ) );
57 
58  if ( expression->hasParserError() || !expression->prepare( &context ) )
59  {
60  ok = false;
61  return QgsFeatureIterator();
62  }
63  }
64 
65  QSet<QString> lst;
66  if ( !expression )
67  lst.insert( fieldOrExpression );
68  else
69  lst = expression->referencedColumns();
70 
72  .setFlags( ( expression && expression->needsGeometry() ) ?
75  .setSubsetOfAttributes( lst, layer->fields() );
76 
77  ok = true;
78  if ( !selectedOnly )
79  {
80  return layer->getFeatures( request );
81  }
82  else
83  {
84  return layer->getSelectedFeatures( request );
85  }
86 }
87 
88 QList<QVariant> QgsVectorLayerUtils::getValues( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly, QgsFeedback *feedback )
89 {
90  QList<QVariant> values;
91  QgsFeatureIterator fit = getValuesIterator( layer, fieldOrExpression, ok, selectedOnly );
92  if ( ok )
93  {
94  std::unique_ptr<QgsExpression> expression;
95  QgsExpressionContext context;
96 
97  int attrNum = layer->fields().lookupField( fieldOrExpression );
98  if ( attrNum == -1 )
99  {
100  // use expression, already validated in the getValuesIterator() function
101  expression.reset( new QgsExpression( fieldOrExpression ) );
103  }
104 
105  QgsFeature f;
106  while ( fit.nextFeature( f ) )
107  {
108  if ( expression )
109  {
110  context.setFeature( f );
111  QVariant v = expression->evaluate( &context );
112  values << v;
113  }
114  else
115  {
116  values << f.attribute( attrNum );
117  }
118  if ( feedback && feedback->isCanceled() )
119  {
120  ok = false;
121  return values;
122  }
123  }
124  }
125  return values;
126 }
127 
128 QList<double> QgsVectorLayerUtils::getDoubleValues( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly, int *nullCount, QgsFeedback *feedback )
129 {
130  QList<double> values;
131 
132  if ( nullCount )
133  *nullCount = 0;
134 
135  QList<QVariant> variantValues = getValues( layer, fieldOrExpression, ok, selectedOnly, feedback );
136  if ( !ok )
137  return values;
138 
139  bool convertOk;
140  const auto constVariantValues = variantValues;
141  for ( const QVariant &value : constVariantValues )
142  {
143  double val = value.toDouble( &convertOk );
144  if ( convertOk )
145  values << val;
146  else if ( value.isNull() )
147  {
148  if ( nullCount )
149  *nullCount += 1;
150  }
151  if ( feedback && feedback->isCanceled() )
152  {
153  ok = false;
154  return values;
155  }
156  }
157  return values;
158 }
159 
160 bool QgsVectorLayerUtils::valueExists( const QgsVectorLayer *layer, int fieldIndex, const QVariant &value, const QgsFeatureIds &ignoreIds )
161 {
162  if ( !layer )
163  return false;
164 
165  QgsFields fields = layer->fields();
166 
167  if ( fieldIndex < 0 || fieldIndex >= fields.count() )
168  return false;
169 
170  // If it's a joined field search the value in the source layer
171  if ( fields.fieldOrigin( fieldIndex ) == QgsFields::FieldOrigin::OriginJoin )
172  {
173  int srcFieldIndex;
174  const QgsVectorLayerJoinInfo *joinInfo { layer->joinBuffer()->joinForFieldIndex( fieldIndex, fields, srcFieldIndex ) };
175  if ( ! joinInfo )
176  {
177  return false;
178  }
179  fieldIndex = srcFieldIndex;
180  layer = joinInfo->joinLayer();
181  if ( ! layer )
182  {
183  return false;
184  }
185  fields = layer->fields();
186  }
187 
188  QString fieldName = fields.at( fieldIndex ).name();
189 
190  // build up an optimised feature request
191  QgsFeatureRequest request;
192  request.setNoAttributes();
194 
195  // at most we need to check ignoreIds.size() + 1 - the feature not in ignoreIds is the one we're interested in
196  int limit = ignoreIds.size() + 1;
197  request.setLimit( limit );
198 
199  request.setFilterExpression( QStringLiteral( "%1=%2" ).arg( QgsExpression::quotedColumnRef( fieldName ),
200  QgsExpression::quotedValue( value ) ) );
201 
202  QgsFeature feat;
203  QgsFeatureIterator it = layer->getFeatures( request );
204  while ( it.nextFeature( feat ) )
205  {
206  if ( ignoreIds.contains( feat.id() ) )
207  continue;
208 
209  return true;
210  }
211 
212  return false;
213 }
214 
215 QVariant QgsVectorLayerUtils::createUniqueValue( const QgsVectorLayer *layer, int fieldIndex, const QVariant &seed )
216 {
217  if ( !layer )
218  return QVariant();
219 
220  QgsFields fields = layer->fields();
221 
222  if ( fieldIndex < 0 || fieldIndex >= fields.count() )
223  return QVariant();
224 
225  QgsField field = fields.at( fieldIndex );
226 
227  if ( field.isNumeric() )
228  {
229  QVariant maxVal = layer->maximumValue( fieldIndex );
230  QVariant newVar( maxVal.toLongLong() + 1 );
231  if ( field.convertCompatible( newVar ) )
232  return newVar;
233  else
234  return QVariant();
235  }
236  else
237  {
238  switch ( field.type() )
239  {
240  case QVariant::String:
241  {
242  QString base;
243  if ( seed.isValid() )
244  base = seed.toString();
245 
246  if ( !base.isEmpty() )
247  {
248  // strip any existing _1, _2 from the seed
249  QRegularExpression rx( QStringLiteral( "(.*)_\\d+" ) );
250  QRegularExpressionMatch match = rx.match( base );
251  if ( match.hasMatch() )
252  {
253  base = match.captured( 1 );
254  }
255  }
256  else
257  {
258  // no base seed - fetch first value from layer
259  QgsFeatureRequest req;
260  req.setLimit( 1 );
261  req.setSubsetOfAttributes( QgsAttributeList() << fieldIndex );
263  QgsFeature f;
264  layer->getFeatures( req ).nextFeature( f );
265  base = f.attribute( fieldIndex ).toString();
266  }
267 
268  // try variants like base_1, base_2, etc until a new value found
269  QStringList vals = layer->uniqueStringsMatching( fieldIndex, base );
270 
271  // might already be unique
272  if ( !base.isEmpty() && !vals.contains( base ) )
273  return base;
274 
275  for ( int i = 1; i < 10000; ++i )
276  {
277  QString testVal = base + '_' + QString::number( i );
278  if ( !vals.contains( testVal ) )
279  return testVal;
280  }
281 
282  // failed
283  return QVariant();
284  }
285 
286  default:
287  // todo other types - dates? times?
288  break;
289  }
290  }
291 
292  return QVariant();
293 }
294 
295 QVariant QgsVectorLayerUtils::createUniqueValueFromCache( const QgsVectorLayer *layer, int fieldIndex, const QSet<QVariant> &existingValues, const QVariant &seed )
296 {
297  if ( !layer )
298  return QVariant();
299 
300  QgsFields fields = layer->fields();
301 
302  if ( fieldIndex < 0 || fieldIndex >= fields.count() )
303  return QVariant();
304 
305  QgsField field = fields.at( fieldIndex );
306 
307  if ( field.isNumeric() )
308  {
309  QVariant maxVal = existingValues.isEmpty() ? 0 : *std::max_element( existingValues.begin(), existingValues.end(), []( const QVariant & a, const QVariant & b ) { return a.toLongLong() < b.toLongLong(); } );
310  QVariant newVar( maxVal.toLongLong() + 1 );
311  if ( field.convertCompatible( newVar ) )
312  return newVar;
313  else
314  return QVariant();
315  }
316  else
317  {
318  switch ( field.type() )
319  {
320  case QVariant::String:
321  {
322  QString base;
323  if ( seed.isValid() )
324  base = seed.toString();
325 
326  if ( !base.isEmpty() )
327  {
328  // strip any existing _1, _2 from the seed
329  QRegularExpression rx( QStringLiteral( "(.*)_\\d+" ) );
330  QRegularExpressionMatch match = rx.match( base );
331  if ( match.hasMatch() )
332  {
333  base = match.captured( 1 );
334  }
335  }
336  else
337  {
338  // no base seed - fetch first value from layer
339  QgsFeatureRequest req;
340  base = existingValues.isEmpty() ? QString() : existingValues.values().first().toString();
341  }
342 
343  // try variants like base_1, base_2, etc until a new value found
344  QStringList vals;
345  for ( const auto &v : std::as_const( existingValues ) )
346  {
347  if ( v.toString().startsWith( base ) )
348  vals.push_back( v.toString() );
349  }
350 
351  // might already be unique
352  if ( !base.isEmpty() && !vals.contains( base ) )
353  return base;
354 
355  for ( int i = 1; i < 10000; ++i )
356  {
357  QString testVal = base + '_' + QString::number( i );
358  if ( !vals.contains( testVal ) )
359  return testVal;
360  }
361 
362  // failed
363  return QVariant();
364  }
365 
366  default:
367  // todo other types - dates? times?
368  break;
369  }
370  }
371 
372  return QVariant();
373 
374 }
375 
376 bool QgsVectorLayerUtils::validateAttribute( const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors,
378 {
379  if ( !layer )
380  return false;
381 
382  if ( attributeIndex < 0 || attributeIndex >= layer->fields().count() )
383  return false;
384 
385  QgsFields fields = layer->fields();
386  QgsField field = fields.at( attributeIndex );
387  const QVariant value = feature.attribute( attributeIndex );
388  bool valid = true;
389  errors.clear();
390 
391  QgsFieldConstraints constraints = field.constraints();
392 
393  if ( constraints.constraints() & QgsFieldConstraints::ConstraintExpression && !constraints.constraintExpression().isEmpty()
396  {
398  context.setFeature( feature );
399 
400  QgsExpression expr( constraints.constraintExpression() );
401 
402  valid = expr.evaluate( &context ).toBool();
403 
404  if ( expr.hasParserError() )
405  {
406  errors << QObject::tr( "parser error: %1" ).arg( expr.parserErrorString() );
407  }
408  else if ( expr.hasEvalError() )
409  {
410  errors << QObject::tr( "evaluation error: %1" ).arg( expr.evalErrorString() );
411  }
412  else if ( !valid )
413  {
414  errors << QObject::tr( "%1 check failed" ).arg( constraints.constraintDescription() );
415  }
416  }
417 
418  bool notNullConstraintViolated { false };
419 
423  {
424  bool exempt = false;
425  if ( fields.fieldOrigin( attributeIndex ) == QgsFields::OriginProvider
427  {
428  int providerIdx = fields.fieldOriginIndex( attributeIndex );
429  exempt = layer->dataProvider()->skipConstraintCheck( providerIdx, QgsFieldConstraints::ConstraintNotNull, value );
430  }
431 
432  if ( !exempt )
433  {
434  valid = valid && !value.isNull();
435 
436  if ( value.isNull() )
437  {
438  errors << QObject::tr( "value is NULL" );
439  notNullConstraintViolated = true;
440  }
441  }
442  }
443 
444  // if a NOT NULL constraint is violated we don't need to check for UNIQUE
445  if ( ! notNullConstraintViolated )
446  {
447 
451  {
452  bool exempt = false;
453  if ( fields.fieldOrigin( attributeIndex ) == QgsFields::OriginProvider
455  {
456  int providerIdx = fields.fieldOriginIndex( attributeIndex );
457  exempt = layer->dataProvider()->skipConstraintCheck( providerIdx, QgsFieldConstraints::ConstraintUnique, value );
458  }
459 
460  if ( !exempt )
461  {
462 
463  bool alreadyExists = QgsVectorLayerUtils::valueExists( layer, attributeIndex, value, QgsFeatureIds() << feature.id() );
464  valid = valid && !alreadyExists;
465 
466  if ( alreadyExists )
467  {
468  errors << QObject::tr( "value is not unique" );
469  }
470  }
471  }
472  }
473 
474  return valid;
475 }
476 
478  const QgsAttributeMap &attributes, QgsExpressionContext *context )
479 {
480  QgsFeatureList features { createFeatures( layer, QgsFeaturesDataList() << QgsFeatureData( geometry, attributes ), context ) };
481  return features.isEmpty() ? QgsFeature() : features.first();
482 }
483 
485 {
486  if ( !layer )
487  return QgsFeatureList();
488 
489  QgsFeatureList result;
490  result.reserve( featuresData.length() );
491 
492  QgsExpressionContext *evalContext = context;
493  std::unique_ptr< QgsExpressionContext > tempContext;
494  if ( !evalContext )
495  {
496  // no context passed, so we create a default one
498  evalContext = tempContext.get();
499  }
500 
501  QgsFields fields = layer->fields();
502 
503  // Cache unique values
504  QMap<int, QSet<QVariant>> uniqueValueCache;
505 
506  auto checkUniqueValue = [ & ]( const int fieldIdx, const QVariant & value )
507  {
508  if ( ! uniqueValueCache.contains( fieldIdx ) )
509  {
510  // If the layer is filtered, get unique values from an unfiltered clone
511  if ( ! layer->subsetString().isEmpty() )
512  {
513  std::unique_ptr<QgsVectorLayer> unfilteredClone { layer->clone( ) };
514  unfilteredClone->setSubsetString( QString( ) );
515  uniqueValueCache[ fieldIdx ] = unfilteredClone->uniqueValues( fieldIdx );
516  }
517  else
518  {
519  uniqueValueCache[ fieldIdx ] = layer->uniqueValues( fieldIdx );
520  }
521  }
522  return uniqueValueCache[ fieldIdx ].contains( value );
523  };
524 
525  for ( const auto &fd : std::as_const( featuresData ) )
526  {
527 
528  QgsFeature newFeature( fields );
529  newFeature.setValid( true );
530  newFeature.setGeometry( fd.geometry() );
531 
532  // initialize attributes
533  newFeature.initAttributes( fields.count() );
534  for ( int idx = 0; idx < fields.count(); ++idx )
535  {
536  QVariant v;
537  bool checkUnique = true;
538  const bool hasUniqueConstraint { static_cast<bool>( fields.at( idx ).constraints().constraints() & QgsFieldConstraints::ConstraintUnique ) };
539 
540  // in order of priority:
541  // 1. passed attribute value and if field does not have a unique constraint like primary key
542  if ( fd.attributes().contains( idx ) )
543  {
544  v = fd.attributes().value( idx );
545  }
546 
547  // 2. client side default expression
548  // note - deliberately not using else if!
549  QgsDefaultValue defaultValueDefinition = layer->defaultValueDefinition( idx );
550  if ( ( v.isNull() || ( hasUniqueConstraint
551  && checkUniqueValue( idx, v ) )
552  || defaultValueDefinition.applyOnUpdate() )
553  && defaultValueDefinition.isValid() )
554  {
555  // client side default expression set - takes precedence over all. Why? Well, this is the only default
556  // which QGIS users have control over, so we assume that they're deliberately overriding any
557  // provider defaults for some good reason and we should respect that
558  v = layer->defaultValue( idx, newFeature, evalContext );
559  }
560 
561  // 3. provider side default value clause
562  // note - not an else if deliberately. Users may return null from a default value expression to fallback to provider defaults
563  if ( ( v.isNull() || ( hasUniqueConstraint
564  && checkUniqueValue( idx, v ) ) )
565  && fields.fieldOrigin( idx ) == QgsFields::OriginProvider )
566  {
567  int providerIndex = fields.fieldOriginIndex( idx );
568  QString providerDefault = layer->dataProvider()->defaultValueClause( providerIndex );
569  if ( !providerDefault.isEmpty() )
570  {
571  v = providerDefault;
572  checkUnique = false;
573  }
574  }
575 
576  // 4. provider side default literal
577  // note - deliberately not using else if!
578  if ( ( v.isNull() || ( checkUnique
579  && hasUniqueConstraint
580  && checkUniqueValue( idx, v ) ) )
581  && fields.fieldOrigin( idx ) == QgsFields::OriginProvider )
582  {
583  int providerIndex = fields.fieldOriginIndex( idx );
584  v = layer->dataProvider()->defaultValue( providerIndex );
585  if ( v.isValid() )
586  {
587  //trust that the provider default has been sensibly set not to violate any constraints
588  checkUnique = false;
589  }
590  }
591 
592  // 5. passed attribute value
593  // note - deliberately not using else if!
594  if ( v.isNull() && fd.attributes().contains( idx ) )
595  {
596  v = fd.attributes().value( idx );
597  }
598 
599  // last of all... check that unique constraints are respected if the value is valid
600  if ( v.isValid() )
601  {
602  // we can't handle not null or expression constraints here, since there's no way to pick a sensible
603  // value if the constraint is violated
604  if ( checkUnique && hasUniqueConstraint )
605  {
606  if ( checkUniqueValue( idx, v ) )
607  {
608  // unique constraint violated
609  QVariant uniqueValue = QgsVectorLayerUtils::createUniqueValueFromCache( layer, idx, uniqueValueCache[ idx ], v );
610  if ( uniqueValue.isValid() )
611  v = uniqueValue;
612  }
613  }
614  if ( hasUniqueConstraint )
615  {
616  uniqueValueCache[ idx ].insert( v );
617  }
618  }
619  newFeature.setAttribute( idx, v );
620  }
621  result.append( newFeature );
622  }
623  return result;
624 }
625 
626 QgsFeature QgsVectorLayerUtils::duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, QgsDuplicateFeatureContext &duplicateFeatureContext, const int maxDepth, int depth, QList<QgsVectorLayer *> referencedLayersBranch )
627 {
628  if ( !layer )
629  return QgsFeature();
630 
631  if ( !layer->isEditable() )
632  return QgsFeature();
633 
634  //get context from layer
636  context.setFeature( feature );
637 
638  QgsFeature newFeature = createFeature( layer, feature.geometry(), feature.attributes().toMap(), &context );
639  layer->addFeature( newFeature );
640 
641  const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );
642 
643  const int effectiveMaxDepth = maxDepth > 0 ? maxDepth : 100;
644 
645  for ( const QgsRelation &relation : relations )
646  {
647  //check if composition (and not association)
648  if ( relation.strength() == QgsRelation::Composition && !referencedLayersBranch.contains( relation.referencedLayer() ) && depth < effectiveMaxDepth )
649  {
650  depth++;
651  referencedLayersBranch << layer;
652 
653  //get features connected over this relation
654  QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( feature );
655  QgsFeatureIds childFeatureIds;
656  QgsFeature childFeature;
657  while ( relatedFeaturesIt.nextFeature( childFeature ) )
658  {
659  //set childlayer editable
660  relation.referencingLayer()->startEditing();
661  //change the fk of the child to the id of the new parent
662  const auto pairs = relation.fieldPairs();
663  for ( const QgsRelation::FieldPair &fieldPair : pairs )
664  {
665  childFeature.setAttribute( fieldPair.first, newFeature.attribute( fieldPair.second ) );
666  }
667  //call the function for the child
668  childFeatureIds.insert( duplicateFeature( relation.referencingLayer(), childFeature, project, duplicateFeatureContext, maxDepth, depth, referencedLayersBranch ).id() );
669  }
670 
671  //store for feedback
672  duplicateFeatureContext.setDuplicatedFeatures( relation.referencingLayer(), childFeatureIds );
673  }
674  }
675 
676 
677  return newFeature;
678 }
679 
680 std::unique_ptr<QgsVectorLayerFeatureSource> QgsVectorLayerUtils::getFeatureSource( QPointer<QgsVectorLayer> layer, QgsFeedback *feedback )
681 {
682  std::unique_ptr<QgsVectorLayerFeatureSource> featureSource;
683 
684  auto getFeatureSource = [ layer, &featureSource, feedback ]
685  {
686  Q_ASSERT( QThread::currentThread() == qApp->thread() || feedback );
687  QgsVectorLayer *lyr = layer.data();
688 
689  if ( lyr )
690  {
691  featureSource.reset( new QgsVectorLayerFeatureSource( lyr ) );
692  }
693  };
694 
696 
697  return featureSource;
698 }
699 
701 {
702  if ( !feature.fields().isEmpty() )
703  {
704  QgsAttributes attributes;
705  attributes.reserve( fields.size() );
706  // feature has a field mapping, so we can match attributes to field names
707  for ( const QgsField &field : fields )
708  {
709  int index = feature.fields().lookupField( field.name() );
710  attributes.append( index >= 0 ? feature.attribute( index ) : QVariant( field.type() ) );
711  }
712  feature.setAttributes( attributes );
713  }
714  else
715  {
716  // no field name mapping in feature, just use order
717  const int lengthDiff = feature.attributes().count() - fields.count();
718  if ( lengthDiff > 0 )
719  {
720  // truncate extra attributes
721  QgsAttributes attributes = feature.attributes().mid( 0, fields.count() );
722  feature.setAttributes( attributes );
723  }
724  else if ( lengthDiff < 0 )
725  {
726  // add missing null attributes
727  QgsAttributes attributes = feature.attributes();
728  attributes.reserve( fields.count() );
729  for ( int i = feature.attributes().count(); i < fields.count(); ++i )
730  {
731  attributes.append( QVariant( fields.at( i ).type() ) );
732  }
733  feature.setAttributes( attributes );
734  }
735  }
736  feature.setFields( fields );
737 }
738 
739 QgsFeatureList QgsVectorLayerUtils::makeFeatureCompatible( const QgsFeature &feature, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags )
740 {
741  QgsWkbTypes::Type inputWkbType( layer->wkbType( ) );
742  QgsFeatureList resultFeatures;
743  QgsFeature newF( feature );
744  // Fix attributes
746 
747  if ( sinkFlags & QgsFeatureSink::RegeneratePrimaryKey )
748  {
749  // drop incoming primary key values, let them be regenerated
750  const QgsAttributeList pkIndexes = layer->dataProvider()->pkAttributeIndexes();
751  for ( int index : pkIndexes )
752  {
753  if ( index >= 0 )
754  newF.setAttribute( index, QVariant() );
755  }
756  }
757 
758  // Does geometry need transformations?
760  bool newFHasGeom = newFGeomType !=
761  QgsWkbTypes::GeometryType::UnknownGeometry &&
762  newFGeomType != QgsWkbTypes::GeometryType::NullGeometry;
763  bool layerHasGeom = inputWkbType !=
764  QgsWkbTypes::Type::NoGeometry &&
765  inputWkbType != QgsWkbTypes::Type::Unknown;
766  // Drop geometry if layer is geometry-less
767  if ( ( newFHasGeom && !layerHasGeom ) || !newFHasGeom )
768  {
769  QgsFeature _f = QgsFeature( layer->fields() );
770  _f.setAttributes( newF.attributes() );
771  resultFeatures.append( _f );
772  }
773  else
774  {
775  // Geometry need fixing?
776  const QVector< QgsGeometry > geometries = newF.geometry().coerceToType( inputWkbType );
777 
778  if ( geometries.count() != 1 )
779  {
780  QgsAttributeMap attrMap;
781  for ( int j = 0; j < newF.fields().count(); j++ )
782  {
783  attrMap[j] = newF.attribute( j );
784  }
785  resultFeatures.reserve( geometries.size() );
786  for ( const QgsGeometry &geometry : geometries )
787  {
788  QgsFeature _f( createFeature( layer, geometry, attrMap ) );
789  resultFeatures.append( _f );
790  }
791  }
792  else
793  {
794  newF.setGeometry( geometries.at( 0 ) );
795  resultFeatures.append( newF );
796  }
797  }
798  return resultFeatures;
799 }
800 
801 QgsFeatureList QgsVectorLayerUtils::makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags )
802 {
803  QgsFeatureList resultFeatures;
804  for ( const QgsFeature &f : features )
805  {
806  const QgsFeatureList features( makeFeatureCompatible( f, layer, sinkFlags ) );
807  for ( const auto &_f : features )
808  {
809  resultFeatures.append( _f );
810  }
811  }
812  return resultFeatures;
813 }
814 
816 {
817  QList<QgsVectorLayer *> layers;
818  QMap<QgsVectorLayer *, QgsFeatureIds>::const_iterator i;
819  for ( i = mDuplicatedFeatures.begin(); i != mDuplicatedFeatures.end(); ++i )
820  layers.append( i.key() );
821  return layers;
822 }
823 
825 {
826  return mDuplicatedFeatures[layer];
827 }
828 
829 void QgsVectorLayerUtils::QgsDuplicateFeatureContext::setDuplicatedFeatures( QgsVectorLayer *layer, const QgsFeatureIds &ids )
830 {
831  if ( mDuplicatedFeatures.contains( layer ) )
832  mDuplicatedFeatures[layer] += ids;
833  else
834  mDuplicatedFeatures.insert( layer, ids );
835 }
836 /*
837 QMap<QgsVectorLayer *, QgsFeatureIds> QgsVectorLayerUtils::QgsDuplicateFeatureContext::duplicateFeatureContext() const
838 {
839  return mDuplicatedFeatures;
840 }
841 */
842 
844  mGeometry( geometry ),
845  mAttributes( attributes )
846 {}
847 
849 {
850  return mGeometry;
851 }
852 
854 {
855  return mAttributes;
856 }
857 
858 bool _fieldIsEditable( const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature )
859 {
860  return layer->isEditable() &&
861  !layer->editFormConfig().readOnly( fieldIndex ) &&
862  // Provider permissions
863  layer->dataProvider() &&
865  ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures && ( FID_IS_NULL( feature.id() ) || FID_IS_NEW( feature.id() ) ) ) ) &&
866  // Field must not be read only
867  !layer->fields().at( fieldIndex ).isReadOnly();
868 }
869 
870 bool QgsVectorLayerUtils::fieldIsReadOnly( const QgsVectorLayer *layer, int fieldIndex )
871 {
872  if ( layer->fields().fieldOrigin( fieldIndex ) == QgsFields::OriginJoin )
873  {
874  int srcFieldIndex;
875  const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
876 
877  if ( !info || !info->isEditable() || !info->joinLayer() )
878  return true;
879 
880  return fieldIsReadOnly( info->joinLayer(), srcFieldIndex );
881  }
882  else
883  {
884  // any of these properties makes the field read only
885  if ( !layer->isEditable() ||
886  layer->editFormConfig().readOnly( fieldIndex ) ||
887  !layer->dataProvider() ||
890  layer->fields().at( fieldIndex ).isReadOnly() )
891  return true;
892 
893  return false;
894  }
895 }
896 
898 {
899  // editability will vary feature-by-feature only for joined fields
900  if ( layer->fields().fieldOrigin( fieldIndex ) == QgsFields::OriginJoin )
901  {
902  int srcFieldIndex;
903  const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
904 
905  if ( !info || !info->isEditable() || info->hasUpsertOnEdit() )
906  return false;
907 
908  // join does not have upsert capabilities, so the ability to edit the joined field will
909  // vary feature-by-feature, depending on whether the join target feature already exists
910  return true;
911  }
912  else
913  {
914  return false;
915  }
916 }
917 
918 bool QgsVectorLayerUtils::fieldIsEditable( const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature )
919 {
920  if ( layer->fields().fieldOrigin( fieldIndex ) == QgsFields::OriginJoin )
921  {
922  int srcFieldIndex;
923  const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
924 
925  if ( !info || !info->isEditable() )
926  return false;
927 
928  // check that joined feature exist, else it is not editable
929  if ( !info->hasUpsertOnEdit() )
930  {
931  const QgsFeature joinedFeature = layer->joinBuffer()->joinedFeatureOf( info, feature );
932  if ( !joinedFeature.isValid() )
933  return false;
934  }
935 
936  return _fieldIsEditable( info->joinLayer(), srcFieldIndex, feature );
937  }
938  else
939  return _fieldIsEditable( layer, fieldIndex, feature );
940 }
941 
942 
943 QHash<QString, QHash<QString, QSet<QgsSymbolLayerId>>> QgsVectorLayerUtils::labelMasks( const QgsVectorLayer *layer )
944 {
945  class LabelMasksVisitor : public QgsStyleEntityVisitorInterface
946  {
947  public:
948  bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
949  {
951  {
952  currentRule = node.identifier;
953  return true;
954  }
955  return false;
956  }
957  bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
958  {
959  if ( leaf.entity && leaf.entity->type() == QgsStyle::LabelSettingsEntity )
960  {
961  auto labelSettingsEntity = static_cast<const QgsStyleLabelSettingsEntity *>( leaf.entity );
962  if ( labelSettingsEntity->settings().format().mask().enabled() )
963  {
964  for ( const auto &r : labelSettingsEntity->settings().format().mask().maskedSymbolLayers() )
965  {
966  masks[currentRule][r.layerId()].insert( r.symbolLayerId() );
967  }
968  }
969  }
970  return true;
971  }
972 
973  QHash<QString, QHash<QString, QSet<QgsSymbolLayerId>>> masks;
974  // Current label rule, empty string for a simple labeling
975  QString currentRule;
976  };
977 
978  if ( ! layer->labeling() )
979  return {};
980 
981  LabelMasksVisitor visitor;
982  layer->labeling()->accept( &visitor );
983  return std::move( visitor.masks );
984 }
985 
986 QHash<QString, QSet<QgsSymbolLayerId>> QgsVectorLayerUtils::symbolLayerMasks( const QgsVectorLayer *layer )
987 {
988  if ( ! layer->renderer() )
989  return {};
990 
991  class SymbolLayerVisitor : public QgsStyleEntityVisitorInterface
992  {
993  public:
994  bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
995  {
997  }
998 
999  void visitSymbol( const QgsSymbol *symbol )
1000  {
1001  for ( int idx = 0; idx < symbol->symbolLayerCount(); idx++ )
1002  {
1003  const QgsSymbolLayer *sl = symbol->symbolLayer( idx );
1004  for ( const auto &mask : sl->masks() )
1005  {
1006  masks[mask.layerId()].insert( mask.symbolLayerId() );
1007  }
1008  // recurse over sub symbols
1009  const QgsSymbol *subSymbol = const_cast<QgsSymbolLayer *>( sl )->subSymbol();
1010  if ( subSymbol )
1011  visitSymbol( subSymbol );
1012  }
1013  }
1014 
1015  bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
1016  {
1017  if ( leaf.entity && leaf.entity->type() == QgsStyle::SymbolEntity )
1018  {
1019  auto symbolEntity = static_cast<const QgsStyleSymbolEntity *>( leaf.entity );
1020  if ( symbolEntity->symbol() )
1021  visitSymbol( symbolEntity->symbol() );
1022  }
1023  return true;
1024  }
1025  QHash<QString, QSet<QgsSymbolLayerId>> masks;
1026  };
1027 
1028  SymbolLayerVisitor visitor;
1029  layer->renderer()->accept( &visitor );
1030  return visitor.masks;
1031 }
1032 
1034 {
1036 
1037  QgsExpression exp( layer->displayExpression() );
1038  context.setFeature( feature );
1039  exp.prepare( &context );
1040  QString displayString = exp.evaluate( &context ).toString();
1041 
1042  return displayString;
1043 }
1044 
1045 bool QgsVectorLayerUtils::impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context, CascadedFeatureFlags flags )
1046 {
1047  if ( !layer )
1048  return false;
1049 
1050  const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );
1051  for ( const QgsRelation &relation : relations )
1052  {
1053  if ( relation.strength() == QgsRelation::Composition )
1054  {
1055  QgsFeatureIds childFeatureIds;
1056 
1057  const auto constFids = fids;
1058  for ( const QgsFeatureId fid : constFids )
1059  {
1060  //get features connected over this relation
1061  QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( layer->getFeature( fid ) );
1062  QgsFeature childFeature;
1063  while ( relatedFeaturesIt.nextFeature( childFeature ) )
1064  {
1065  childFeatureIds.insert( childFeature.id() );
1066  }
1067  }
1068 
1069  if ( childFeatureIds.count() > 0 )
1070  {
1071  if ( context.layers().contains( relation.referencingLayer() ) )
1072  {
1073  QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( relation.referencingLayer() );
1074  // add feature ids
1075  handledFeatureIds.unite( childFeatureIds );
1076  context.setDuplicatedFeatures( relation.referencingLayer(), handledFeatureIds );
1077  }
1078  else
1079  {
1080  // add layer and feature id
1081  context.setDuplicatedFeatures( relation.referencingLayer(), childFeatureIds );
1082  }
1083  }
1084  }
1085  }
1086 
1087  if ( layer->joinBuffer()->containsJoins() )
1088  {
1089  const QgsVectorJoinList joins = layer->joinBuffer()->vectorJoins();
1090  for ( const QgsVectorLayerJoinInfo &info : joins )
1091  {
1092  if ( qobject_cast< QgsAuxiliaryLayer * >( info.joinLayer() ) && flags & IgnoreAuxiliaryLayers )
1093  continue;
1094 
1095  if ( info.isEditable() && info.hasCascadedDelete() )
1096  {
1097  QgsFeatureIds joinFeatureIds;
1098  const auto constFids = fids;
1099  for ( const QgsFeatureId &fid : constFids )
1100  {
1101  const QgsFeature joinFeature = layer->joinBuffer()->joinedFeatureOf( &info, layer->getFeature( fid ) );
1102  if ( joinFeature.isValid() )
1103  joinFeatureIds.insert( joinFeature.id() );
1104  }
1105 
1106  if ( joinFeatureIds.count() > 0 )
1107  {
1108  if ( context.layers().contains( info.joinLayer() ) )
1109  {
1110  QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( info.joinLayer() );
1111  // add feature ids
1112  handledFeatureIds.unite( joinFeatureIds );
1113  context.setDuplicatedFeatures( info.joinLayer(), handledFeatureIds );
1114  }
1115  else
1116  {
1117  // add layer and feature id
1118  context.setDuplicatedFeatures( info.joinLayer(), joinFeatureIds );
1119  }
1120  }
1121  }
1122  }
1123  }
1124 
1125  return !context.layers().isEmpty();
1126 }
1127 
1128 QString QgsVectorLayerUtils::guessFriendlyIdentifierField( const QgsFields &fields, bool *foundFriendly )
1129 {
1130  if ( foundFriendly )
1131  *foundFriendly = false;
1132 
1133  if ( fields.isEmpty() )
1134  return QString();
1135 
1136  // Check the fields and keep the first one that matches.
1137  // We assume that the user has organized the data with the
1138  // more "interesting" field names first. As such, name should
1139  // be selected before oldname, othername, etc.
1140  // This candidates list is a prioritized list of candidates ranked by "interestingness"!
1141  // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
1142  // but adding hardcoded localized variants of the strings is encouraged.
1143  static QStringList sCandidates{ QStringLiteral( "name" ),
1144  QStringLiteral( "title" ),
1145  QStringLiteral( "heibt" ),
1146  QStringLiteral( "desc" ),
1147  QStringLiteral( "nom" ),
1148  QStringLiteral( "street" ),
1149  QStringLiteral( "road" ),
1150  QStringLiteral( "label" ) };
1151 
1152  // anti-names
1153  // this list of strings indicates parts of field names which make the name "less interesting".
1154  // For instance, we'd normally like to default to a field called "name" or "id", but if instead we
1155  // find one called "typename" or "typeid", then that's most likely a classification of the feature and not the
1156  // best choice to default to
1157  static QStringList sAntiCandidates{ QStringLiteral( "type" ),
1158  QStringLiteral( "class" ),
1159  QStringLiteral( "cat" )
1160  };
1161 
1162  QString bestCandidateName;
1163  QString bestCandidateNameWithAntiCandidate;
1164 
1165  for ( const QString &candidate : sCandidates )
1166  {
1167  for ( const QgsField &field : fields )
1168  {
1169  const QString fldName = field.name();
1170  if ( fldName.contains( candidate, Qt::CaseInsensitive ) )
1171  {
1172  bool isAntiCandidate = false;
1173  for ( const QString &antiCandidate : sAntiCandidates )
1174  {
1175  if ( fldName.contains( antiCandidate, Qt::CaseInsensitive ) )
1176  {
1177  isAntiCandidate = true;
1178  break;
1179  }
1180  }
1181 
1182  if ( isAntiCandidate )
1183  {
1184  if ( bestCandidateNameWithAntiCandidate.isEmpty() )
1185  {
1186  bestCandidateNameWithAntiCandidate = fldName;
1187  }
1188  }
1189  else
1190  {
1191  bestCandidateName = fldName;
1192  break;
1193  }
1194  }
1195  }
1196 
1197  if ( !bestCandidateName.isEmpty() )
1198  break;
1199  }
1200 
1201  const QString candidateName = bestCandidateName.isEmpty() ? bestCandidateNameWithAntiCandidate : bestCandidateName;
1202  if ( !candidateName.isEmpty() )
1203  {
1204  if ( foundFriendly )
1205  *foundFriendly = true;
1206  return candidateName;
1207  }
1208  else
1209  {
1210  // no good matches found by name, so scan through and look for the first string field
1211  for ( const QgsField &field : fields )
1212  {
1213  if ( field.type() == QVariant::String )
1214  return field.name();
1215  }
1216 
1217  // no string fields found - just return first field
1218  return fields.at( 0 ).name();
1219  }
1220 }
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the labeling...
A vector of attributes.
Definition: qgsattributes.h:58
CORE_EXPORT QgsAttributeMap toMap() const
Returns a QgsAttributeMap of the attribute values.
The QgsDefaultValue class provides a container for managing client side default values for fields.
bool isValid() const
Returns if this default value should be applied.
bool readOnly(int idx) const
This returns true if the field is manually set to read only or if the field does not support editing ...
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
QString evalErrorString() const
Returns evaluation error.
QString parserErrorString() const
Returns parser error.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
QVariant evaluate()
Evaluate the feature and return the result.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
Definition: qgsfeature.cpp:255
QgsAttributes attributes
Definition: qgsfeature.h:65
QgsFields fields
Definition: qgsfeature.h:66
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
Definition: qgsfeature.cpp:228
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:153
void setFields(const QgsFields &fields, bool initAttributes=false)
Assigns a field map with the feature to allow attribute access by attribute name.
Definition: qgsfeature.cpp:188
QgsGeometry geometry
Definition: qgsfeature.h:67
void setValid(bool validity)
Sets the validity of the feature.
Definition: qgsfeature.cpp:214
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:209
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:320
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:163
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:45
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
Stores information about constraints which may be present on a field.
ConstraintStrength
Strength of constraints.
@ ConstraintStrengthNotSet
Constraint is not set.
ConstraintOrigin
Origin of constraints.
@ ConstraintOriginNotSet
Constraint is not set.
@ ConstraintOriginProvider
Constraint was set at data provider.
ConstraintStrength constraintStrength(Constraint constraint) const
Returns the strength of a field constraint, or ConstraintStrengthNotSet if the constraint is not pres...
ConstraintOrigin constraintOrigin(Constraint constraint) const
Returns the origin of a field constraint, or ConstraintOriginNotSet if the constraint is not present ...
QString constraintExpression() const
Returns the constraint expression for the field, if set.
@ ConstraintNotNull
Field may not be null.
@ ConstraintUnique
Field must have a unique value.
@ ConstraintExpression
Field has an expression constraint set. See constraintExpression().
QString constraintDescription() const
Returns the descriptive name for the constraint expression.
Q_GADGET Constraints constraints
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
QString name
Definition: qgsfield.h:60
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
Definition: qgsfield.cpp:384
Q_GADGET bool isNumeric
Definition: qgsfield.h:54
QVariant::Type type
Definition: qgsfield.h:58
QgsFieldConstraints constraints
Definition: qgsfield.h:63
bool isReadOnly
Definition: qgsfield.h:65
Container of fields for a vector layer.
Definition: qgsfields.h:45
@ OriginJoin
Field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfields.h:52
@ OriginProvider
Field comes from the underlying data provider of the vector layer (originIndex = index in provider's ...
Definition: qgsfields.h:51
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
Definition: qgsfields.cpp:189
bool isEmpty() const
Checks whether the container is empty.
Definition: qgsfields.cpp:128
int size() const
Returns number of items.
Definition: qgsfields.cpp:138
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
int fieldOriginIndex(int fieldIdx) const
Returns the field's origin index (its meaning is specific to each type of origin).
Definition: qgsfields.cpp:197
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:344
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:125
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QVector< QgsGeometry > coerceToType(QgsWkbTypes::Type type) const
Attempts to coerce this geometry into the specified destination type.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:101
QgsRelationManager * relationManager
Definition: qgsproject.h:111
QList< QgsRelation > referencedRelations(const QgsVectorLayer *layer=nullptr) const
Gets all relations where this layer is the referenced part (i.e.
Defines a relation between matching fields of the two involved tables of a relation.
Definition: qgsrelation.h:89
@ Composition
Fix relation, related elements are part of the parent and a parent copy will copy any children or del...
Definition: qgsrelation.h:73
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
An interface for classes which can visit style entity (e.g.
@ SymbolRule
Rule based symbology or label child rule.
A label settings entity for QgsStyle databases.
Definition: qgsstyle.h:1312
A symbol entity for QgsStyle databases.
Definition: qgsstyle.h:1219
@ LabelSettingsEntity
Label settings.
Definition: qgsstyle.h:185
@ SymbolEntity
Symbols.
Definition: qgsstyle.h:180
virtual QList< QgsSymbolLayerReference > masks() const
Returns masks defined by this symbol layer.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:38
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
Definition: qgssymbol.cpp:420
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Definition: qgssymbol.h:160
static bool runOnMainThread(const Func &func, QgsFeedback *feedback=nullptr)
Guarantees that func is executed on the main thread.
@ ChangeAttributeValues
Allows modification of attribute values.
@ AddFeatures
Allows adding features.
virtual QgsAttributeList pkAttributeIndexes() const
Returns list of indexes of fields that make up the primary key.
virtual QString defaultValueClause(int fieldIndex) const
Returns any default value clauses which are present at the provider for a specified field index.
virtual QVariant defaultValue(int fieldIndex) const
Returns any literal default values which are present at the provider for a specified field index.
virtual Q_INVOKABLE QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
virtual bool skipConstraintCheck(int fieldIndex, QgsFieldConstraints::Constraint constraint, const QVariant &value=QVariant()) const
Returns true if a constraint check should be skipped for a specified field (e.g., if the value return...
Partial snapshot of vector layer's state (only the members necessary for access to features)
const QgsVectorJoinList & vectorJoins() const
const QgsVectorLayerJoinInfo * joinForFieldIndex(int index, const QgsFields &fields, int &sourceFieldIndex) const
Finds the vector join for a layer field index.
bool containsJoins() const
Quick way to test if there is any join at all.
QgsFeature joinedFeatureOf(const QgsVectorLayerJoinInfo *info, const QgsFeature &feature) const
Returns the joined feature corresponding to the feature.
Defines left outer join from our vector layer to some other vector layer.
bool hasUpsertOnEdit() const
Returns whether a feature created on the target layer has to impact the joined layer by creating a ne...
bool isEditable() const
Returns whether joined fields may be edited through the form of the target layer.
QgsVectorLayer * joinLayer() const
Returns joined layer (may be nullptr if the reference was set by layer ID and not resolved yet)
Contains mainly the QMap with QgsVectorLayer and QgsFeatureIds do list all the duplicated features.
QgsFeatureIds duplicatedFeatures(QgsVectorLayer *layer) const
Returns the duplicated features in the given layer.
QList< QgsVectorLayer * > layers() const
Returns all the layers on which features have been duplicated.
Encapsulate geometry and attributes for new features, to be passed to createFeatures.
QgsGeometry geometry() const
Returns geometry.
QgsAttributeMap attributes() const
Returns attributes.
QgsFeatureData(const QgsGeometry &geometry=QgsGeometry(), const QgsAttributeMap &attributes=QgsAttributeMap())
Constructs a new QgsFeatureData with given geometry and attributes.
static QgsFeature duplicateFeature(QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, QgsDuplicateFeatureContext &duplicateFeatureContext, const int maxDepth=0, int depth=0, QList< QgsVectorLayer * > referencedLayersBranch=QList< QgsVectorLayer * >())
Duplicates a feature and it's children (one level deep).
QList< QgsVectorLayerUtils::QgsFeatureData > QgsFeaturesDataList
Alias for list of QgsFeatureData.
static bool valueExists(const QgsVectorLayer *layer, int fieldIndex, const QVariant &value, const QgsFeatureIds &ignoreIds=QgsFeatureIds())
Returns true if the specified value already exists within a field.
static QgsFeatureList makeFeatureCompatible(const QgsFeature &feature, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags())
Converts input feature to be compatible with the given layer.
static QString guessFriendlyIdentifierField(const QgsFields &fields, bool *foundFriendly=nullptr)
Given a set of fields, attempts to pick the "most useful" field for user-friendly identification of f...
static QgsFeatureIterator getValuesIterator(const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly)
Create a feature iterator for a specified field name or expression.
static bool fieldEditabilityDependsOnFeature(const QgsVectorLayer *layer, int fieldIndex)
Returns true if the editability of the field at index fieldIndex from layer may vary feature by featu...
static QgsFeatureList makeFeaturesCompatible(const QgsFeatureList &features, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags())
Converts input features to be compatible with the given layer.
static std::unique_ptr< QgsVectorLayerFeatureSource > getFeatureSource(QPointer< QgsVectorLayer > layer, QgsFeedback *feedback=nullptr)
Gets the feature source from a QgsVectorLayer pointer.
static QString getFeatureDisplayString(const QgsVectorLayer *layer, const QgsFeature &feature)
static QHash< QString, QHash< QString, QSet< QgsSymbolLayerId > > > labelMasks(const QgsVectorLayer *)
Returns masks defined in labeling options of a layer.
static QgsFeature createFeature(const QgsVectorLayer *layer, const QgsGeometry &geometry=QgsGeometry(), const QgsAttributeMap &attributes=QgsAttributeMap(), QgsExpressionContext *context=nullptr)
Creates a new feature ready for insertion into a layer.
static bool fieldIsEditable(const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature)
Tests whether a field is editable for a particular feature.
static QHash< QString, QSet< QgsSymbolLayerId > > symbolLayerMasks(const QgsVectorLayer *)
Returns all masks that may be defined on symbol layers for a given vector layer.
static QList< double > getDoubleValues(const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly=false, int *nullCount=nullptr, QgsFeedback *feedback=nullptr)
Fetches all double values from a specified field name or expression.
static bool fieldIsReadOnly(const QgsVectorLayer *layer, int fieldIndex)
static QgsFeatureList createFeatures(const QgsVectorLayer *layer, const QgsFeaturesDataList &featuresData, QgsExpressionContext *context=nullptr)
Creates a set of new features ready for insertion into a layer.
static QVariant createUniqueValue(const QgsVectorLayer *layer, int fieldIndex, const QVariant &seed=QVariant())
Returns a new attribute value for the specified field index which is guaranteed to be unique.
static bool impactsCascadeFeatures(const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context, QgsVectorLayerUtils::CascadedFeatureFlags flags=QgsVectorLayerUtils::CascadedFeatureFlags())
static QList< QVariant > getValues(const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly=false, QgsFeedback *feedback=nullptr)
Fetches all values from a specified field name or expression.
static QVariant createUniqueValueFromCache(const QgsVectorLayer *layer, int fieldIndex, const QSet< QVariant > &existingValues, const QVariant &seed=QVariant())
Returns a new attribute value for the specified field index which is guaranteed to be unique within r...
static bool validateAttribute(const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthNotSet, QgsFieldConstraints::ConstraintOrigin origin=QgsFieldConstraints::ConstraintOriginNotSet)
Tests a feature attribute value to check whether it passes all constraints which are present on the c...
static void matchAttributesToFields(QgsFeature &feature, const QgsFields &fields)
Matches the attributes in feature to the specified fields.
@ IgnoreAuxiliaryLayers
Ignore auxiliary layers.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
QVariant maximumValue(int index) const FINAL
Returns the maximum value for an attribute column or an invalid variant in case of error.
QgsDefaultValue defaultValueDefinition(int index) const
Returns the definition of the expression used when calculating the default value for a field.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QgsVectorLayerJoinBuffer * joinBuffer()
Returns the join buffer object.
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
QString subsetString
QString displayExpression
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Returns an iterator of the selected features.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
QgsVectorLayer * clone() const override
Returns a new instance equivalent to this one.
QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
QStringList uniqueStringsMatching(int index, const QString &substring, int limit=-1, QgsFeedback *feedback=nullptr) const
Returns unique string values of an attribute which contain a specified subset string.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a single feature to the sink.
virtual bool setSubsetString(const QString &subset)
Sets the string (typically sql) used to define a subset of the layer.
QVariant defaultValue(int index, const QgsFeature &feature=QgsFeature(), QgsExpressionContext *context=nullptr) const
Returns the calculated default value for the specified field index.
const QgsAbstractVectorLayerLabeling * labeling() const
Access to const labeling configuration.
QgsEditFormConfig editFormConfig
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:968
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:141
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:38
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:882
#define FID_IS_NULL(fid)
Definition: qgsfeatureid.h:30
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
#define FID_IS_NEW(fid)
Definition: qgsfeatureid.h:31
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
QList< int > QgsAttributeList
Definition: qgsfield.h:26
const QgsField & field
Definition: qgsfield.h:463
QList< QgsVectorLayerJoinInfo > QgsVectorJoinList
bool _fieldIsEditable(const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature)
Contains information relating to a node (i.e.
QString identifier
A string identifying the node.
QgsStyleEntityVisitorInterface::NodeType type
Node type.
Contains information relating to the style entity currently being visited.
const QgsStyleEntityInterface * entity
Reference to style entity being visited.