QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
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"
44 
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() );
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 : qgis::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  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 : qgis::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 #if QT_VERSION >= QT_VERSION_CHECK( 5, 10, 0 )
687  Q_ASSERT( QThread::currentThread() == qApp->thread() || feedback );
688 #else
689  Q_UNUSED( feedback )
690 #endif
691  QgsVectorLayer *lyr = layer.data();
692 
693  if ( lyr )
694  {
695  featureSource.reset( new QgsVectorLayerFeatureSource( lyr ) );
696  }
697  };
698 
700 
701  return featureSource;
702 }
703 
705 {
706  if ( !feature.fields().isEmpty() )
707  {
708  QgsAttributes attributes;
709  attributes.reserve( fields.size() );
710  // feature has a field mapping, so we can match attributes to field names
711  for ( const QgsField &field : fields )
712  {
713  int index = feature.fields().lookupField( field.name() );
714  attributes.append( index >= 0 ? feature.attribute( index ) : QVariant( field.type() ) );
715  }
716  feature.setAttributes( attributes );
717  }
718  else
719  {
720  // no field name mapping in feature, just use order
721  const int lengthDiff = feature.attributes().count() - fields.count();
722  if ( lengthDiff > 0 )
723  {
724  // truncate extra attributes
725  QgsAttributes attributes = feature.attributes().mid( 0, fields.count() );
726  feature.setAttributes( attributes );
727  }
728  else if ( lengthDiff < 0 )
729  {
730  // add missing null attributes
731  QgsAttributes attributes = feature.attributes();
732  attributes.reserve( fields.count() );
733  for ( int i = feature.attributes().count(); i < fields.count(); ++i )
734  {
735  attributes.append( QVariant( fields.at( i ).type() ) );
736  }
737  feature.setAttributes( attributes );
738  }
739  }
740  feature.setFields( fields );
741 }
742 
743 QgsFeatureList QgsVectorLayerUtils::makeFeatureCompatible( const QgsFeature &feature, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags )
744 {
745  QgsWkbTypes::Type inputWkbType( layer->wkbType( ) );
746  QgsFeatureList resultFeatures;
747  QgsFeature newF( feature );
748  // Fix attributes
750 
751  if ( sinkFlags & QgsFeatureSink::RegeneratePrimaryKey )
752  {
753  // drop incoming primary key values, let them be regenerated
754  const QgsAttributeList pkIndexes = layer->dataProvider()->pkAttributeIndexes();
755  for ( int index : pkIndexes )
756  {
757  if ( index >= 0 )
758  newF.setAttribute( index, QVariant() );
759  }
760  }
761 
762  // Does geometry need transformations?
764  bool newFHasGeom = newFGeomType !=
765  QgsWkbTypes::GeometryType::UnknownGeometry &&
766  newFGeomType != QgsWkbTypes::GeometryType::NullGeometry;
767  bool layerHasGeom = inputWkbType !=
768  QgsWkbTypes::Type::NoGeometry &&
769  inputWkbType != QgsWkbTypes::Type::Unknown;
770  // Drop geometry if layer is geometry-less
771  if ( ( newFHasGeom && !layerHasGeom ) || !newFHasGeom )
772  {
773  QgsFeature _f = QgsFeature( layer->fields() );
774  _f.setAttributes( newF.attributes() );
775  resultFeatures.append( _f );
776  }
777  else
778  {
779  // Geometry need fixing?
780  const QVector< QgsGeometry > geometries = newF.geometry().coerceToType( inputWkbType );
781 
782  if ( geometries.count() != 1 )
783  {
784  QgsAttributeMap attrMap;
785  for ( int j = 0; j < newF.fields().count(); j++ )
786  {
787  attrMap[j] = newF.attribute( j );
788  }
789  resultFeatures.reserve( geometries.size() );
790  for ( const QgsGeometry &geometry : geometries )
791  {
792  QgsFeature _f( createFeature( layer, geometry, attrMap ) );
793  resultFeatures.append( _f );
794  }
795  }
796  else
797  {
798  newF.setGeometry( geometries.at( 0 ) );
799  resultFeatures.append( newF );
800  }
801  }
802  return resultFeatures;
803 }
804 
805 QgsFeatureList QgsVectorLayerUtils::makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags )
806 {
807  QgsFeatureList resultFeatures;
808  for ( const QgsFeature &f : features )
809  {
810  const QgsFeatureList features( makeFeatureCompatible( f, layer, sinkFlags ) );
811  for ( const auto &_f : features )
812  {
813  resultFeatures.append( _f );
814  }
815  }
816  return resultFeatures;
817 }
818 
820 {
821  QList<QgsVectorLayer *> layers;
822  QMap<QgsVectorLayer *, QgsFeatureIds>::const_iterator i;
823  for ( i = mDuplicatedFeatures.begin(); i != mDuplicatedFeatures.end(); ++i )
824  layers.append( i.key() );
825  return layers;
826 }
827 
829 {
830  return mDuplicatedFeatures[layer];
831 }
832 
833 void QgsVectorLayerUtils::QgsDuplicateFeatureContext::setDuplicatedFeatures( QgsVectorLayer *layer, const QgsFeatureIds &ids )
834 {
835  if ( mDuplicatedFeatures.contains( layer ) )
836  mDuplicatedFeatures[layer] += ids;
837  else
838  mDuplicatedFeatures.insert( layer, ids );
839 }
840 /*
841 QMap<QgsVectorLayer *, QgsFeatureIds> QgsVectorLayerUtils::QgsDuplicateFeatureContext::duplicateFeatureContext() const
842 {
843  return mDuplicatedFeatures;
844 }
845 */
846 
848  mGeometry( geometry ),
849  mAttributes( attributes )
850 {}
851 
853 {
854  return mGeometry;
855 }
856 
858 {
859  return mAttributes;
860 }
861 
862 bool _fieldIsEditable( const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature )
863 {
864  return layer->isEditable() &&
865  !layer->editFormConfig().readOnly( fieldIndex ) &&
866  // Provider permissions
867  layer->dataProvider() &&
869  ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures && ( FID_IS_NULL( feature.id() ) || FID_IS_NEW( feature.id() ) ) ) ) &&
870  // Field must not be read only
871  !layer->fields().at( fieldIndex ).isReadOnly();
872 }
873 
874 bool QgsVectorLayerUtils::fieldIsReadOnly( const QgsVectorLayer *layer, int fieldIndex )
875 {
876  if ( layer->fields().fieldOrigin( fieldIndex ) == QgsFields::OriginJoin )
877  {
878  int srcFieldIndex;
879  const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
880 
881  if ( !info || !info->isEditable() || !info->joinLayer() )
882  return true;
883 
884  return fieldIsReadOnly( info->joinLayer(), srcFieldIndex );
885  }
886  else
887  {
888  // any of these properties makes the field read only
889  if ( !layer->isEditable() ||
890  layer->editFormConfig().readOnly( fieldIndex ) ||
891  !layer->dataProvider() ||
894  layer->fields().at( fieldIndex ).isReadOnly() )
895  return true;
896 
897  return false;
898  }
899 }
900 
902 {
903  // editability will vary feature-by-feature only for joined fields
904  if ( layer->fields().fieldOrigin( fieldIndex ) == QgsFields::OriginJoin )
905  {
906  int srcFieldIndex;
907  const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
908 
909  if ( !info || !info->isEditable() || info->hasUpsertOnEdit() )
910  return false;
911 
912  // join does not have upsert capabilities, so the ability to edit the joined field will
913  // vary feature-by-feature, depending on whether the join target feature already exists
914  return true;
915  }
916  else
917  {
918  return false;
919  }
920 }
921 
922 bool QgsVectorLayerUtils::fieldIsEditable( const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature )
923 {
924  if ( layer->fields().fieldOrigin( fieldIndex ) == QgsFields::OriginJoin )
925  {
926  int srcFieldIndex;
927  const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
928 
929  if ( !info || !info->isEditable() )
930  return false;
931 
932  // check that joined feature exist, else it is not editable
933  if ( !info->hasUpsertOnEdit() )
934  {
935  const QgsFeature joinedFeature = layer->joinBuffer()->joinedFeatureOf( info, feature );
936  if ( !joinedFeature.isValid() )
937  return false;
938  }
939 
940  return _fieldIsEditable( info->joinLayer(), srcFieldIndex, feature );
941  }
942  else
943  return _fieldIsEditable( layer, fieldIndex, feature );
944 }
945 
946 
947 QHash<QString, QHash<QString, QSet<QgsSymbolLayerId>>> QgsVectorLayerUtils::labelMasks( const QgsVectorLayer *layer )
948 {
949  class LabelMasksVisitor : public QgsStyleEntityVisitorInterface
950  {
951  public:
952  bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
953  {
955  {
956  currentRule = node.identifier;
957  return true;
958  }
959  return false;
960  }
961  bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
962  {
963  if ( leaf.entity && leaf.entity->type() == QgsStyle::LabelSettingsEntity )
964  {
965  auto labelSettingsEntity = static_cast<const QgsStyleLabelSettingsEntity *>( leaf.entity );
966  if ( labelSettingsEntity->settings().format().mask().enabled() )
967  {
968  for ( const auto &r : labelSettingsEntity->settings().format().mask().maskedSymbolLayers() )
969  {
970  masks[currentRule][r.layerId()].insert( r.symbolLayerId() );
971  }
972  }
973  }
974  return true;
975  }
976 
977  QHash<QString, QHash<QString, QSet<QgsSymbolLayerId>>> masks;
978  // Current label rule, empty string for a simple labeling
979  QString currentRule;
980  };
981 
982  if ( ! layer->labeling() )
983  return {};
984 
985  LabelMasksVisitor visitor;
986  layer->labeling()->accept( &visitor );
987  return std::move( visitor.masks );
988 }
989 
990 QHash<QString, QSet<QgsSymbolLayerId>> QgsVectorLayerUtils::symbolLayerMasks( const QgsVectorLayer *layer )
991 {
992  if ( ! layer->renderer() )
993  return {};
994 
995  class SymbolLayerVisitor : public QgsStyleEntityVisitorInterface
996  {
997  public:
998  bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
999  {
1001  }
1002 
1003  void visitSymbol( const QgsSymbol *symbol )
1004  {
1005  for ( int idx = 0; idx < symbol->symbolLayerCount(); idx++ )
1006  {
1007  const QgsSymbolLayer *sl = symbol->symbolLayer( idx );
1008  for ( const auto &mask : sl->masks() )
1009  {
1010  masks[mask.layerId()].insert( mask.symbolLayerId() );
1011  }
1012  // recurse over sub symbols
1013  const QgsSymbol *subSymbol = const_cast<QgsSymbolLayer *>( sl )->subSymbol();
1014  if ( subSymbol )
1015  visitSymbol( subSymbol );
1016  }
1017  }
1018 
1019  bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
1020  {
1021  if ( leaf.entity && leaf.entity->type() == QgsStyle::SymbolEntity )
1022  {
1023  auto symbolEntity = static_cast<const QgsStyleSymbolEntity *>( leaf.entity );
1024  if ( symbolEntity->symbol() )
1025  visitSymbol( symbolEntity->symbol() );
1026  }
1027  return true;
1028  }
1029  QHash<QString, QSet<QgsSymbolLayerId>> masks;
1030  };
1031 
1032  SymbolLayerVisitor visitor;
1033  layer->renderer()->accept( &visitor );
1034  return visitor.masks;
1035 }
1036 
1038 {
1040 
1041  QgsExpression exp( layer->displayExpression() );
1042  context.setFeature( feature );
1043  exp.prepare( &context );
1044  QString displayString = exp.evaluate( &context ).toString();
1045 
1046  return displayString;
1047 }
1048 
1049 bool QgsVectorLayerUtils::impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context, CascadedFeatureFlags flags )
1050 {
1051  if ( !layer )
1052  return false;
1053 
1054  const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );
1055  for ( const QgsRelation &relation : relations )
1056  {
1057  if ( relation.strength() == QgsRelation::Composition )
1058  {
1059  QgsFeatureIds childFeatureIds;
1060 
1061  const auto constFids = fids;
1062  for ( const QgsFeatureId fid : constFids )
1063  {
1064  //get features connected over this relation
1065  QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( layer->getFeature( fid ) );
1066  QgsFeature childFeature;
1067  while ( relatedFeaturesIt.nextFeature( childFeature ) )
1068  {
1069  childFeatureIds.insert( childFeature.id() );
1070  }
1071  }
1072 
1073  if ( childFeatureIds.count() > 0 )
1074  {
1075  if ( context.layers().contains( relation.referencingLayer() ) )
1076  {
1077  QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( relation.referencingLayer() );
1078  // add feature ids
1079  handledFeatureIds.unite( childFeatureIds );
1080  context.setDuplicatedFeatures( relation.referencingLayer(), handledFeatureIds );
1081  }
1082  else
1083  {
1084  // add layer and feature id
1085  context.setDuplicatedFeatures( relation.referencingLayer(), childFeatureIds );
1086  }
1087  }
1088  }
1089  }
1090 
1091  if ( layer->joinBuffer()->containsJoins() )
1092  {
1093  const QgsVectorJoinList joins = layer->joinBuffer()->vectorJoins();
1094  for ( const QgsVectorLayerJoinInfo &info : joins )
1095  {
1096  if ( qobject_cast< QgsAuxiliaryLayer * >( info.joinLayer() ) && flags & IgnoreAuxiliaryLayers )
1097  continue;
1098 
1099  if ( info.isEditable() && info.hasCascadedDelete() )
1100  {
1101  QgsFeatureIds joinFeatureIds;
1102  const auto constFids = fids;
1103  for ( const QgsFeatureId &fid : constFids )
1104  {
1105  const QgsFeature joinFeature = layer->joinBuffer()->joinedFeatureOf( &info, layer->getFeature( fid ) );
1106  if ( joinFeature.isValid() )
1107  joinFeatureIds.insert( joinFeature.id() );
1108  }
1109 
1110  if ( joinFeatureIds.count() > 0 )
1111  {
1112  if ( context.layers().contains( info.joinLayer() ) )
1113  {
1114  QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( info.joinLayer() );
1115  // add feature ids
1116  handledFeatureIds.unite( joinFeatureIds );
1117  context.setDuplicatedFeatures( info.joinLayer(), handledFeatureIds );
1118  }
1119  else
1120  {
1121  // add layer and feature id
1122  context.setDuplicatedFeatures( info.joinLayer(), joinFeatureIds );
1123  }
1124  }
1125  }
1126  }
1127  }
1128 
1129  return !context.layers().isEmpty();
1130 }
1131 
1133 {
1134  if ( fields.isEmpty() )
1135  return QString();
1136 
1137  // Check the fields and keep the first one that matches.
1138  // We assume that the user has organized the data with the
1139  // more "interesting" field names first. As such, name should
1140  // be selected before oldname, othername, etc.
1141  // This candidates list is a prioritized list of candidates ranked by "interestingness"!
1142  // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
1143  // but adding hardcoded localized variants of the strings is encouraged.
1144  static QStringList sCandidates{ QStringLiteral( "name" ),
1145  QStringLiteral( "title" ),
1146  QStringLiteral( "heibt" ),
1147  QStringLiteral( "desc" ),
1148  QStringLiteral( "nom" ),
1149  QStringLiteral( "street" ),
1150  QStringLiteral( "road" ) };
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  return candidateName;
1205  }
1206  else
1207  {
1208  // no good matches found by name, so scan through and look for the first string field
1209  for ( const QgsField &field : fields )
1210  {
1211  if ( field.type() == QVariant::String )
1212  return field.name();
1213  }
1214 
1215  // no string fields found - just return first field
1216  return fields.at( 0 ).name();
1217  }
1218 }
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.
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 & 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 & setLimit(long limit)
Set the maximum number of features to request.
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 id, geometry and a list of field/values...
Definition: qgsfeature.h:56
bool setAttribute(int field, const QVariant &attr)
Set an attribute's value by field index.
Definition: qgsfeature.cpp:236
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:209
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:134
void setFields(const QgsFields &fields, bool initAttributes=false)
Assign a field map with the feature to allow attribute access by attribute name.
Definition: qgsfeature.cpp:169
QgsGeometry geometry
Definition: qgsfeature.h:67
void setValid(bool validity)
Sets the validity of the feature.
Definition: qgsfeature.cpp:195
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:190
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:287
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:144
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
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:371
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
Gets 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
Gets field at particular index (must be in range 0..N-1)
Definition: qgsfields.cpp:163
int fieldOriginIndex(int fieldIdx) const
Gets 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:124
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:99
QgsRelationManager * relationManager
Definition: qgsproject.h:109
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:1294
A symbol entity for QgsStyle databases.
Definition: qgsstyle.h:1201
@ LabelSettingsEntity
Label settings.
Definition: qgsstyle.h:185
@ SymbolEntity
Symbols.
Definition: qgsstyle.h:180
virtual QgsSymbolLayerReferenceList masks() const
Returns masks defined by this symbol layer.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:65
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
Definition: qgssymbol.cpp:411
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Definition: qgssymbol.h:199
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 QString guessFriendlyIdentifierField(const QgsFields &fields)
Given a set of fields, attempts to pick the "most useful" field for user-friendly identification of f...
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 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 an attribute value to check whether it passes all constraints which are present on the correspo...
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:938
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:614
#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:472
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.