QGIS API Documentation  3.27.0-Master (e113457133)
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 #include "qgspainteffect.h"
46 
47 QgsFeatureIterator QgsVectorLayerUtils::getValuesIterator( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly )
48 {
49  std::unique_ptr<QgsExpression> expression;
50  QgsExpressionContext context;
51 
52  int attrNum = layer->fields().lookupField( fieldOrExpression );
53  if ( attrNum == -1 )
54  {
55  // try to use expression
56  expression.reset( new QgsExpression( fieldOrExpression ) );
58 
59  if ( expression->hasParserError() || !expression->prepare( &context ) )
60  {
61  ok = false;
62  return QgsFeatureIterator();
63  }
64  }
65 
66  QSet<QString> lst;
67  if ( !expression )
68  lst.insert( fieldOrExpression );
69  else
70  lst = expression->referencedColumns();
71 
73  .setFlags( ( expression && expression->needsGeometry() ) ?
76  .setSubsetOfAttributes( lst, layer->fields() );
77 
78  ok = true;
79  if ( !selectedOnly )
80  {
81  return layer->getFeatures( request );
82  }
83  else
84  {
85  return layer->getSelectedFeatures( request );
86  }
87 }
88 
89 QList<QVariant> QgsVectorLayerUtils::getValues( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly, QgsFeedback *feedback )
90 {
91  QList<QVariant> values;
92  QgsFeatureIterator fit = getValuesIterator( layer, fieldOrExpression, ok, selectedOnly );
93  if ( ok )
94  {
95  std::unique_ptr<QgsExpression> expression;
96  QgsExpressionContext context;
97 
98  int attrNum = layer->fields().lookupField( fieldOrExpression );
99  if ( attrNum == -1 )
100  {
101  // use expression, already validated in the getValuesIterator() function
102  expression.reset( new QgsExpression( fieldOrExpression ) );
104  }
105 
106  QgsFeature f;
107  while ( fit.nextFeature( f ) )
108  {
109  if ( expression )
110  {
111  context.setFeature( f );
112  QVariant v = expression->evaluate( &context );
113  values << v;
114  }
115  else
116  {
117  values << f.attribute( attrNum );
118  }
119  if ( feedback && feedback->isCanceled() )
120  {
121  ok = false;
122  return values;
123  }
124  }
125  }
126  return values;
127 }
128 
129 QList<double> QgsVectorLayerUtils::getDoubleValues( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly, int *nullCount, QgsFeedback *feedback )
130 {
131  QList<double> values;
132 
133  if ( nullCount )
134  *nullCount = 0;
135 
136  QList<QVariant> variantValues = getValues( layer, fieldOrExpression, ok, selectedOnly, feedback );
137  if ( !ok )
138  return values;
139 
140  bool convertOk;
141  const auto constVariantValues = variantValues;
142  for ( const QVariant &value : constVariantValues )
143  {
144  double val = value.toDouble( &convertOk );
145  if ( convertOk )
146  values << val;
147  else if ( value.isNull() )
148  {
149  if ( nullCount )
150  *nullCount += 1;
151  }
152  if ( feedback && feedback->isCanceled() )
153  {
154  ok = false;
155  return values;
156  }
157  }
158  return values;
159 }
160 
161 bool QgsVectorLayerUtils::valueExists( const QgsVectorLayer *layer, int fieldIndex, const QVariant &value, const QgsFeatureIds &ignoreIds )
162 {
163  if ( !layer )
164  return false;
165 
166  QgsFields fields = layer->fields();
167 
168  if ( fieldIndex < 0 || fieldIndex >= fields.count() )
169  return false;
170 
171  // If it's a joined field search the value in the source layer
172  if ( fields.fieldOrigin( fieldIndex ) == QgsFields::FieldOrigin::OriginJoin )
173  {
174  int srcFieldIndex;
175  const QgsVectorLayerJoinInfo *joinInfo { layer->joinBuffer()->joinForFieldIndex( fieldIndex, fields, srcFieldIndex ) };
176  if ( ! joinInfo )
177  {
178  return false;
179  }
180  fieldIndex = srcFieldIndex;
181  layer = joinInfo->joinLayer();
182  if ( ! layer )
183  {
184  return false;
185  }
186  fields = layer->fields();
187  }
188 
189  QString fieldName = fields.at( fieldIndex ).name();
190 
191  // build up an optimised feature request
192  QgsFeatureRequest request;
193  request.setNoAttributes();
195 
196  // at most we need to check ignoreIds.size() + 1 - the feature not in ignoreIds is the one we're interested in
197  int limit = ignoreIds.size() + 1;
198  request.setLimit( limit );
199 
200  request.setFilterExpression( QStringLiteral( "%1=%2" ).arg( QgsExpression::quotedColumnRef( fieldName ),
201  QgsExpression::quotedValue( value ) ) );
202 
203  QgsFeature feat;
204  QgsFeatureIterator it = layer->getFeatures( request );
205  while ( it.nextFeature( feat ) )
206  {
207  if ( ignoreIds.contains( feat.id() ) )
208  continue;
209 
210  return true;
211  }
212 
213  return false;
214 }
215 
216 QVariant QgsVectorLayerUtils::createUniqueValue( const QgsVectorLayer *layer, int fieldIndex, const QVariant &seed )
217 {
218  if ( !layer )
219  return QVariant();
220 
221  QgsFields fields = layer->fields();
222 
223  if ( fieldIndex < 0 || fieldIndex >= fields.count() )
224  return QVariant();
225 
226  QgsField field = fields.at( fieldIndex );
227 
228  if ( field.isNumeric() )
229  {
230  QVariant maxVal = layer->maximumValue( fieldIndex );
231  QVariant newVar( maxVal.toLongLong() + 1 );
232  if ( field.convertCompatible( newVar ) )
233  return newVar;
234  else
235  return QVariant();
236  }
237  else
238  {
239  switch ( field.type() )
240  {
241  case QVariant::String:
242  {
243  QString base;
244  if ( seed.isValid() )
245  base = seed.toString();
246 
247  if ( !base.isEmpty() )
248  {
249  // strip any existing _1, _2 from the seed
250  QRegularExpression rx( QStringLiteral( "(.*)_\\d+" ) );
251  QRegularExpressionMatch match = rx.match( base );
252  if ( match.hasMatch() )
253  {
254  base = match.captured( 1 );
255  }
256  }
257  else
258  {
259  // no base seed - fetch first value from layer
260  QgsFeatureRequest req;
261  req.setLimit( 1 );
262  req.setSubsetOfAttributes( QgsAttributeList() << fieldIndex );
264  QgsFeature f;
265  layer->getFeatures( req ).nextFeature( f );
266  base = f.attribute( fieldIndex ).toString();
267  }
268 
269  // try variants like base_1, base_2, etc until a new value found
270  QStringList vals = layer->uniqueStringsMatching( fieldIndex, base );
271 
272  // might already be unique
273  if ( !base.isEmpty() && !vals.contains( base ) )
274  return base;
275 
276  for ( int i = 1; i < 10000; ++i )
277  {
278  QString testVal = base + '_' + QString::number( i );
279  if ( !vals.contains( testVal ) )
280  return testVal;
281  }
282 
283  // failed
284  return QVariant();
285  }
286 
287  default:
288  // todo other types - dates? times?
289  break;
290  }
291  }
292 
293  return QVariant();
294 }
295 
296 QVariant QgsVectorLayerUtils::createUniqueValueFromCache( const QgsVectorLayer *layer, int fieldIndex, const QSet<QVariant> &existingValues, const QVariant &seed )
297 {
298  if ( !layer )
299  return QVariant();
300 
301  QgsFields fields = layer->fields();
302 
303  if ( fieldIndex < 0 || fieldIndex >= fields.count() )
304  return QVariant();
305 
306  QgsField field = fields.at( fieldIndex );
307 
308  if ( field.isNumeric() )
309  {
310  QVariant maxVal = existingValues.isEmpty() ? 0 : *std::max_element( existingValues.begin(), existingValues.end(), []( const QVariant & a, const QVariant & b ) { return a.toLongLong() < b.toLongLong(); } );
311  QVariant newVar( maxVal.toLongLong() + 1 );
312  if ( field.convertCompatible( newVar ) )
313  return newVar;
314  else
315  return QVariant();
316  }
317  else
318  {
319  switch ( field.type() )
320  {
321  case QVariant::String:
322  {
323  QString base;
324  if ( seed.isValid() )
325  base = seed.toString();
326 
327  if ( !base.isEmpty() )
328  {
329  // strip any existing _1, _2 from the seed
330  QRegularExpression rx( QStringLiteral( "(.*)_\\d+" ) );
331  QRegularExpressionMatch match = rx.match( base );
332  if ( match.hasMatch() )
333  {
334  base = match.captured( 1 );
335  }
336  }
337  else
338  {
339  // no base seed - fetch first value from layer
340  QgsFeatureRequest req;
341  base = existingValues.isEmpty() ? QString() : existingValues.values().first().toString();
342  }
343 
344  // try variants like base_1, base_2, etc until a new value found
345  QStringList vals;
346  for ( const auto &v : std::as_const( existingValues ) )
347  {
348  if ( v.toString().startsWith( base ) )
349  vals.push_back( v.toString() );
350  }
351 
352  // might already be unique
353  if ( !base.isEmpty() && !vals.contains( base ) )
354  return base;
355 
356  for ( int i = 1; i < 10000; ++i )
357  {
358  QString testVal = base + '_' + QString::number( i );
359  if ( !vals.contains( testVal ) )
360  return testVal;
361  }
362 
363  // failed
364  return QVariant();
365  }
366 
367  default:
368  // todo other types - dates? times?
369  break;
370  }
371  }
372 
373  return QVariant();
374 
375 }
376 
377 bool QgsVectorLayerUtils::validateAttribute( const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors,
379 {
380  if ( !layer )
381  return false;
382 
383  if ( attributeIndex < 0 || attributeIndex >= layer->fields().count() )
384  return false;
385 
386  QgsFields fields = layer->fields();
387  QgsField field = fields.at( attributeIndex );
388  const QVariant value = feature.attribute( attributeIndex );
389  bool valid = true;
390  errors.clear();
391 
392  QgsFieldConstraints constraints = field.constraints();
393 
394  if ( constraints.constraints() & QgsFieldConstraints::ConstraintExpression && !constraints.constraintExpression().isEmpty()
397  {
399  context.setFeature( feature );
400 
401  QgsExpression expr( constraints.constraintExpression() );
402 
403  valid = expr.evaluate( &context ).toBool();
404 
405  if ( expr.hasParserError() )
406  {
407  errors << QObject::tr( "parser error: %1" ).arg( expr.parserErrorString() );
408  }
409  else if ( expr.hasEvalError() )
410  {
411  errors << QObject::tr( "evaluation error: %1" ).arg( expr.evalErrorString() );
412  }
413  else if ( !valid )
414  {
415  errors << QObject::tr( "%1 check failed" ).arg( constraints.constraintDescription() );
416  }
417  }
418 
419  bool notNullConstraintViolated { false };
420 
424  {
425  bool exempt = false;
426  if ( fields.fieldOrigin( attributeIndex ) == QgsFields::OriginProvider
428  {
429  int providerIdx = fields.fieldOriginIndex( attributeIndex );
430  exempt = layer->dataProvider()->skipConstraintCheck( providerIdx, QgsFieldConstraints::ConstraintNotNull, value );
431  }
432 
433  if ( !exempt )
434  {
435  valid = valid && !value.isNull();
436 
437  if ( value.isNull() )
438  {
439  errors << QObject::tr( "value is NULL" );
440  notNullConstraintViolated = true;
441  }
442  }
443  }
444 
445  // if a NOT NULL constraint is violated we don't need to check for UNIQUE
446  if ( ! notNullConstraintViolated )
447  {
448 
452  {
453  bool exempt = false;
454  if ( fields.fieldOrigin( attributeIndex ) == QgsFields::OriginProvider
456  {
457  int providerIdx = fields.fieldOriginIndex( attributeIndex );
458  exempt = layer->dataProvider()->skipConstraintCheck( providerIdx, QgsFieldConstraints::ConstraintUnique, value );
459  }
460 
461  if ( !exempt )
462  {
463 
464  bool alreadyExists = QgsVectorLayerUtils::valueExists( layer, attributeIndex, value, QgsFeatureIds() << feature.id() );
465  valid = valid && !alreadyExists;
466 
467  if ( alreadyExists )
468  {
469  errors << QObject::tr( "value is not unique" );
470  }
471  }
472  }
473  }
474 
475  return valid;
476 }
477 
479  const QgsAttributeMap &attributes, QgsExpressionContext *context )
480 {
481  QgsFeatureList features { createFeatures( layer, QgsFeaturesDataList() << QgsFeatureData( geometry, attributes ), context ) };
482  return features.isEmpty() ? QgsFeature() : features.first();
483 }
484 
486 {
487  if ( !layer )
488  return QgsFeatureList();
489 
490  QgsFeatureList result;
491  result.reserve( featuresData.length() );
492 
493  QgsExpressionContext *evalContext = context;
494  std::unique_ptr< QgsExpressionContext > tempContext;
495  if ( !evalContext )
496  {
497  // no context passed, so we create a default one
499  evalContext = tempContext.get();
500  }
501 
502  QgsFields fields = layer->fields();
503 
504  // Cache unique values
505  QMap<int, QSet<QVariant>> uniqueValueCache;
506 
507  auto checkUniqueValue = [ & ]( const int fieldIdx, const QVariant & value )
508  {
509  if ( ! uniqueValueCache.contains( fieldIdx ) )
510  {
511  // If the layer is filtered, get unique values from an unfiltered clone
512  if ( ! layer->subsetString().isEmpty() )
513  {
514  std::unique_ptr<QgsVectorLayer> unfilteredClone { layer->clone( ) };
515  unfilteredClone->setSubsetString( QString( ) );
516  uniqueValueCache[ fieldIdx ] = unfilteredClone->uniqueValues( fieldIdx );
517  }
518  else
519  {
520  uniqueValueCache[ fieldIdx ] = layer->uniqueValues( fieldIdx );
521  }
522  }
523  return uniqueValueCache[ fieldIdx ].contains( value );
524  };
525 
526  for ( const auto &fd : std::as_const( featuresData ) )
527  {
528 
529  QgsFeature newFeature( fields );
530  newFeature.setValid( true );
531  newFeature.setGeometry( fd.geometry() );
532 
533  // initialize attributes
534  newFeature.initAttributes( fields.count() );
535  for ( int idx = 0; idx < fields.count(); ++idx )
536  {
537  QVariant v;
538  bool checkUnique = true;
539  const bool hasUniqueConstraint { static_cast<bool>( fields.at( idx ).constraints().constraints() & QgsFieldConstraints::ConstraintUnique ) };
540 
541  // in order of priority:
542  // 1. passed attribute value and if field does not have a unique constraint like primary key
543  if ( fd.attributes().contains( idx ) )
544  {
545  v = fd.attributes().value( idx );
546  }
547 
548  // 2. client side default expression
549  // note - deliberately not using else if!
550  QgsDefaultValue defaultValueDefinition = layer->defaultValueDefinition( idx );
551  if ( ( v.isNull() || ( hasUniqueConstraint
552  && checkUniqueValue( idx, v ) )
553  || defaultValueDefinition.applyOnUpdate() )
554  && defaultValueDefinition.isValid() )
555  {
556  // client side default expression set - takes precedence over all. Why? Well, this is the only default
557  // which QGIS users have control over, so we assume that they're deliberately overriding any
558  // provider defaults for some good reason and we should respect that
559  v = layer->defaultValue( idx, newFeature, evalContext );
560  }
561 
562  // 3. provider side default value clause
563  // note - not an else if deliberately. Users may return null from a default value expression to fallback to provider defaults
564  if ( ( v.isNull() || ( hasUniqueConstraint
565  && checkUniqueValue( idx, v ) ) )
566  && fields.fieldOrigin( idx ) == QgsFields::OriginProvider )
567  {
568  int providerIndex = fields.fieldOriginIndex( idx );
569  QString providerDefault = layer->dataProvider()->defaultValueClause( providerIndex );
570  if ( !providerDefault.isEmpty() )
571  {
572  v = providerDefault;
573  checkUnique = false;
574  }
575  }
576 
577  // 4. provider side default literal
578  // note - deliberately not using else if!
579  if ( ( v.isNull() || ( checkUnique
580  && hasUniqueConstraint
581  && checkUniqueValue( idx, v ) ) )
582  && fields.fieldOrigin( idx ) == QgsFields::OriginProvider )
583  {
584  int providerIndex = fields.fieldOriginIndex( idx );
585  v = layer->dataProvider()->defaultValue( providerIndex );
586  if ( v.isValid() )
587  {
588  //trust that the provider default has been sensibly set not to violate any constraints
589  checkUnique = false;
590  }
591  }
592 
593  // 5. passed attribute value
594  // note - deliberately not using else if!
595  if ( v.isNull() && fd.attributes().contains( idx ) )
596  {
597  v = fd.attributes().value( idx );
598  }
599 
600  // last of all... check that unique constraints are respected if the value is valid
601  if ( v.isValid() )
602  {
603  // we can't handle not null or expression constraints here, since there's no way to pick a sensible
604  // value if the constraint is violated
605  if ( checkUnique && hasUniqueConstraint )
606  {
607  if ( checkUniqueValue( idx, v ) )
608  {
609  // unique constraint violated
610  QVariant uniqueValue = QgsVectorLayerUtils::createUniqueValueFromCache( layer, idx, uniqueValueCache[ idx ], v );
611  if ( uniqueValue.isValid() )
612  v = uniqueValue;
613  }
614  }
615  if ( hasUniqueConstraint )
616  {
617  uniqueValueCache[ idx ].insert( v );
618  }
619  }
620  newFeature.setAttribute( idx, v );
621  }
622  result.append( newFeature );
623  }
624  return result;
625 }
626 
627 QgsFeature QgsVectorLayerUtils::duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, QgsDuplicateFeatureContext &duplicateFeatureContext, const int maxDepth, int depth, QList<QgsVectorLayer *> referencedLayersBranch )
628 {
629  if ( !layer )
630  return QgsFeature();
631 
632  if ( !layer->isEditable() )
633  return QgsFeature();
634 
635  //get context from layer
637  context.setFeature( feature );
638 
639  QgsFeature newFeature = createFeature( layer, feature.geometry(), feature.attributes().toMap(), &context );
640  layer->addFeature( newFeature );
641 
642  const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );
643 
644  const int effectiveMaxDepth = maxDepth > 0 ? maxDepth : 100;
645 
646  for ( const QgsRelation &relation : relations )
647  {
648  //check if composition (and not association)
649  if ( relation.strength() == QgsRelation::Composition && !referencedLayersBranch.contains( relation.referencedLayer() ) && depth < effectiveMaxDepth )
650  {
651  depth++;
652  referencedLayersBranch << layer;
653 
654  //get features connected over this relation
655  QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( feature );
656  QgsFeatureIds childFeatureIds;
657  QgsFeature childFeature;
658  while ( relatedFeaturesIt.nextFeature( childFeature ) )
659  {
660  //set childlayer editable
661  relation.referencingLayer()->startEditing();
662  //change the fk of the child to the id of the new parent
663  const auto pairs = relation.fieldPairs();
664  for ( const QgsRelation::FieldPair &fieldPair : pairs )
665  {
666  childFeature.setAttribute( fieldPair.first, newFeature.attribute( fieldPair.second ) );
667  }
668  //call the function for the child
669  childFeatureIds.insert( duplicateFeature( relation.referencingLayer(), childFeature, project, duplicateFeatureContext, maxDepth, depth, referencedLayersBranch ).id() );
670  }
671 
672  //store for feedback
673  duplicateFeatureContext.setDuplicatedFeatures( relation.referencingLayer(), childFeatureIds );
674  }
675  }
676 
677 
678  return newFeature;
679 }
680 
681 std::unique_ptr<QgsVectorLayerFeatureSource> QgsVectorLayerUtils::getFeatureSource( QPointer<QgsVectorLayer> layer, QgsFeedback *feedback )
682 {
683  std::unique_ptr<QgsVectorLayerFeatureSource> featureSource;
684 
685  auto getFeatureSource = [ layer, &featureSource, feedback ]
686  {
687  Q_ASSERT( QThread::currentThread() == qApp->thread() || feedback );
688  QgsVectorLayer *lyr = layer.data();
689 
690  if ( lyr )
691  {
692  featureSource.reset( new QgsVectorLayerFeatureSource( lyr ) );
693  }
694  };
695 
697 
698  return featureSource;
699 }
700 
702 {
703  if ( !feature.fields().isEmpty() )
704  {
705  QgsAttributes attributes;
706  attributes.reserve( fields.size() );
707  // feature has a field mapping, so we can match attributes to field names
708  for ( const QgsField &field : fields )
709  {
710  int index = feature.fields().lookupField( field.name() );
711  attributes.append( index >= 0 ? feature.attribute( index ) : QVariant( field.type() ) );
712  }
713  feature.setAttributes( attributes );
714  }
715  else
716  {
717  // no field name mapping in feature, just use order
718  const int lengthDiff = feature.attributes().count() - fields.count();
719  if ( lengthDiff > 0 )
720  {
721  // truncate extra attributes
722  QgsAttributes attributes = feature.attributes().mid( 0, fields.count() );
723  feature.setAttributes( attributes );
724  }
725  else if ( lengthDiff < 0 )
726  {
727  // add missing null attributes
728  QgsAttributes attributes = feature.attributes();
729  attributes.reserve( fields.count() );
730  for ( int i = feature.attributes().count(); i < fields.count(); ++i )
731  {
732  attributes.append( QVariant( fields.at( i ).type() ) );
733  }
734  feature.setAttributes( attributes );
735  }
736  }
737  feature.setFields( fields );
738 }
739 
740 QgsFeatureList QgsVectorLayerUtils::makeFeatureCompatible( const QgsFeature &feature, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags )
741 {
742  QgsWkbTypes::Type inputWkbType( layer->wkbType( ) );
743  QgsFeatureList resultFeatures;
744  QgsFeature newF( feature );
745  // Fix attributes
747 
748  if ( sinkFlags & QgsFeatureSink::RegeneratePrimaryKey )
749  {
750  // drop incoming primary key values, let them be regenerated
751  const QgsAttributeList pkIndexes = layer->dataProvider()->pkAttributeIndexes();
752  for ( int index : pkIndexes )
753  {
754  if ( index >= 0 )
755  newF.setAttribute( index, QVariant() );
756  }
757  }
758 
759  // Does geometry need transformations?
761  bool newFHasGeom = newFGeomType !=
762  QgsWkbTypes::GeometryType::UnknownGeometry &&
763  newFGeomType != QgsWkbTypes::GeometryType::NullGeometry;
764  bool layerHasGeom = inputWkbType !=
765  QgsWkbTypes::Type::NoGeometry &&
766  inputWkbType != QgsWkbTypes::Type::Unknown;
767  // Drop geometry if layer is geometry-less
768  if ( ( newFHasGeom && !layerHasGeom ) || !newFHasGeom )
769  {
770  QgsFeature _f = QgsFeature( layer->fields() );
771  _f.setAttributes( newF.attributes() );
772  resultFeatures.append( _f );
773  }
774  else
775  {
776  // Geometry need fixing?
777  const QVector< QgsGeometry > geometries = newF.geometry().coerceToType( inputWkbType );
778 
779  if ( geometries.count() != 1 )
780  {
781  QgsAttributeMap attrMap;
782  for ( int j = 0; j < newF.fields().count(); j++ )
783  {
784  attrMap[j] = newF.attribute( j );
785  }
786  resultFeatures.reserve( geometries.size() );
787  for ( const QgsGeometry &geometry : geometries )
788  {
789  QgsFeature _f( createFeature( layer, geometry, attrMap ) );
790  resultFeatures.append( _f );
791  }
792  }
793  else
794  {
795  newF.setGeometry( geometries.at( 0 ) );
796  resultFeatures.append( newF );
797  }
798  }
799  return resultFeatures;
800 }
801 
802 QgsFeatureList QgsVectorLayerUtils::makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags )
803 {
804  QgsFeatureList resultFeatures;
805  for ( const QgsFeature &f : features )
806  {
807  const QgsFeatureList features( makeFeatureCompatible( f, layer, sinkFlags ) );
808  for ( const auto &_f : features )
809  {
810  resultFeatures.append( _f );
811  }
812  }
813  return resultFeatures;
814 }
815 
817 {
818  QList<QgsVectorLayer *> layers;
819  QMap<QgsVectorLayer *, QgsFeatureIds>::const_iterator i;
820  for ( i = mDuplicatedFeatures.begin(); i != mDuplicatedFeatures.end(); ++i )
821  layers.append( i.key() );
822  return layers;
823 }
824 
826 {
827  return mDuplicatedFeatures[layer];
828 }
829 
830 void QgsVectorLayerUtils::QgsDuplicateFeatureContext::setDuplicatedFeatures( QgsVectorLayer *layer, const QgsFeatureIds &ids )
831 {
832  if ( mDuplicatedFeatures.contains( layer ) )
833  mDuplicatedFeatures[layer] += ids;
834  else
835  mDuplicatedFeatures.insert( layer, ids );
836 }
837 /*
838 QMap<QgsVectorLayer *, QgsFeatureIds> QgsVectorLayerUtils::QgsDuplicateFeatureContext::duplicateFeatureContext() const
839 {
840  return mDuplicatedFeatures;
841 }
842 */
843 
845  mGeometry( geometry ),
846  mAttributes( attributes )
847 {}
848 
850 {
851  return mGeometry;
852 }
853 
855 {
856  return mAttributes;
857 }
858 
859 bool _fieldIsEditable( const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature )
860 {
861  return layer->isEditable() &&
862  !layer->editFormConfig().readOnly( fieldIndex ) &&
863  // Provider permissions
864  layer->dataProvider() &&
866  ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures && ( FID_IS_NULL( feature.id() ) || FID_IS_NEW( feature.id() ) ) ) ) &&
867  // Field must not be read only
868  !layer->fields().at( fieldIndex ).isReadOnly();
869 }
870 
871 bool QgsVectorLayerUtils::fieldIsReadOnly( const QgsVectorLayer *layer, int fieldIndex )
872 {
873  if ( layer->fields().fieldOrigin( fieldIndex ) == QgsFields::OriginJoin )
874  {
875  int srcFieldIndex;
876  const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
877 
878  if ( !info || !info->isEditable() || !info->joinLayer() )
879  return true;
880 
881  return fieldIsReadOnly( info->joinLayer(), srcFieldIndex );
882  }
883  else
884  {
885  // any of these properties makes the field read only
886  if ( !layer->isEditable() ||
887  layer->editFormConfig().readOnly( fieldIndex ) ||
888  !layer->dataProvider() ||
891  layer->fields().at( fieldIndex ).isReadOnly() )
892  return true;
893 
894  return false;
895  }
896 }
897 
899 {
900  // editability will vary feature-by-feature only for joined fields
901  if ( layer->fields().fieldOrigin( fieldIndex ) == QgsFields::OriginJoin )
902  {
903  int srcFieldIndex;
904  const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
905 
906  if ( !info || !info->isEditable() || info->hasUpsertOnEdit() )
907  return false;
908 
909  // join does not have upsert capabilities, so the ability to edit the joined field will
910  // vary feature-by-feature, depending on whether the join target feature already exists
911  return true;
912  }
913  else
914  {
915  return false;
916  }
917 }
918 
919 bool QgsVectorLayerUtils::fieldIsEditable( const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature )
920 {
921  if ( layer->fields().fieldOrigin( fieldIndex ) == QgsFields::OriginJoin )
922  {
923  int srcFieldIndex;
924  const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
925 
926  if ( !info || !info->isEditable() )
927  return false;
928 
929  // check that joined feature exist, else it is not editable
930  if ( !info->hasUpsertOnEdit() )
931  {
932  const QgsFeature joinedFeature = layer->joinBuffer()->joinedFeatureOf( info, feature );
933  if ( !joinedFeature.isValid() )
934  return false;
935  }
936 
937  return _fieldIsEditable( info->joinLayer(), srcFieldIndex, feature );
938  }
939  else
940  return _fieldIsEditable( layer, fieldIndex, feature );
941 }
942 
943 
944 QHash<QString, QgsMaskedLayers> QgsVectorLayerUtils::labelMasks( const QgsVectorLayer *layer )
945 {
946  class LabelMasksVisitor : public QgsStyleEntityVisitorInterface
947  {
948  public:
949  bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
950  {
952  {
953  currentRule = node.identifier;
954  return true;
955  }
956  return false;
957  }
958  bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
959  {
960  if ( leaf.entity && leaf.entity->type() == QgsStyle::LabelSettingsEntity )
961  {
962  auto labelSettingsEntity = static_cast<const QgsStyleLabelSettingsEntity *>( leaf.entity );
963  const QgsTextMaskSettings &maskSettings = labelSettingsEntity->settings().format().mask();
964  if ( maskSettings.enabled() )
965  {
966  // transparency is considered has effects because it implies rasterization when masking
967  // is involved
968  const bool hasEffects = maskSettings.opacity() < 1 ||
969  ( maskSettings.paintEffect() && maskSettings.paintEffect()->enabled() );
970  for ( const auto &r : maskSettings.maskedSymbolLayers() )
971  {
972  QgsMaskedLayer &maskedLayer = maskedLayers[currentRule][r.layerId()];
973  maskedLayer.symbolLayerIds.insert( r.symbolLayerId() );
974  maskedLayer.hasEffects = hasEffects;
975  }
976  }
977  }
978  return true;
979  }
980 
981  QHash<QString, QgsMaskedLayers> maskedLayers;
982  // Current label rule, empty string for a simple labeling
983  QString currentRule;
984  };
985 
986  if ( ! layer->labeling() )
987  return {};
988 
989  LabelMasksVisitor visitor;
990  layer->labeling()->accept( &visitor );
991  return std::move( visitor.maskedLayers );
992 }
993 
995 {
996  if ( ! layer->renderer() )
997  return {};
998 
999  class SymbolLayerVisitor : public QgsStyleEntityVisitorInterface
1000  {
1001  public:
1002  bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
1003  {
1005  }
1006 
1007  // Returns true if the visited symbol has effects
1008  bool visitSymbol( const QgsSymbol *symbol )
1009  {
1010  // transparency is considered has effects because it implies rasterization when masking
1011  // is involved
1012  bool symbolHasEffect = symbol->opacity() < 1;
1013  for ( int idx = 0; idx < symbol->symbolLayerCount(); idx++ )
1014  {
1015  const QgsSymbolLayer *sl = symbol->symbolLayer( idx );
1016  bool slHasEffects = sl->paintEffect() && sl->paintEffect()->enabled();
1017  symbolHasEffect |= slHasEffects;
1018 
1019  // recurse over sub symbols
1020  const QgsSymbol *subSymbol = const_cast<QgsSymbolLayer *>( sl )->subSymbol();
1021  if ( subSymbol )
1022  slHasEffects |= visitSymbol( subSymbol );
1023 
1024  for ( const auto &mask : sl->masks() )
1025  {
1026  QgsMaskedLayer &maskedLayer = maskedLayers[mask.layerId()];
1027  maskedLayer.hasEffects |= slHasEffects;
1028  maskedLayer.symbolLayerIds.insert( mask.symbolLayerId() );
1029  }
1030  }
1031 
1032  return symbolHasEffect;
1033  }
1034 
1035  bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
1036  {
1037  if ( leaf.entity && leaf.entity->type() == QgsStyle::SymbolEntity )
1038  {
1039  auto symbolEntity = static_cast<const QgsStyleSymbolEntity *>( leaf.entity );
1040  if ( symbolEntity->symbol() )
1041  visitSymbol( symbolEntity->symbol() );
1042  }
1043  return true;
1044  }
1045  QgsMaskedLayers maskedLayers;
1046  };
1047 
1048  SymbolLayerVisitor visitor;
1049  layer->renderer()->accept( &visitor );
1050  return visitor.maskedLayers;
1051 }
1052 
1054 {
1056 
1057  QgsExpression exp( layer->displayExpression() );
1058  context.setFeature( feature );
1059  exp.prepare( &context );
1060  QString displayString = exp.evaluate( &context ).toString();
1061 
1062  return displayString;
1063 }
1064 
1065 bool QgsVectorLayerUtils::impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context, CascadedFeatureFlags flags )
1066 {
1067  if ( !layer )
1068  return false;
1069 
1070  const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );
1071  for ( const QgsRelation &relation : relations )
1072  {
1073  if ( relation.strength() == QgsRelation::Composition )
1074  {
1075  QgsFeatureIds childFeatureIds;
1076 
1077  const auto constFids = fids;
1078  for ( const QgsFeatureId fid : constFids )
1079  {
1080  //get features connected over this relation
1081  QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( layer->getFeature( fid ) );
1082  QgsFeature childFeature;
1083  while ( relatedFeaturesIt.nextFeature( childFeature ) )
1084  {
1085  childFeatureIds.insert( childFeature.id() );
1086  }
1087  }
1088 
1089  if ( childFeatureIds.count() > 0 )
1090  {
1091  if ( context.layers().contains( relation.referencingLayer() ) )
1092  {
1093  QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( relation.referencingLayer() );
1094  // add feature ids
1095  handledFeatureIds.unite( childFeatureIds );
1096  context.setDuplicatedFeatures( relation.referencingLayer(), handledFeatureIds );
1097  }
1098  else
1099  {
1100  // add layer and feature id
1101  context.setDuplicatedFeatures( relation.referencingLayer(), childFeatureIds );
1102  }
1103  }
1104  }
1105  }
1106 
1107  if ( layer->joinBuffer()->containsJoins() )
1108  {
1109  const QgsVectorJoinList joins = layer->joinBuffer()->vectorJoins();
1110  for ( const QgsVectorLayerJoinInfo &info : joins )
1111  {
1112  if ( qobject_cast< QgsAuxiliaryLayer * >( info.joinLayer() ) && flags & IgnoreAuxiliaryLayers )
1113  continue;
1114 
1115  if ( info.isEditable() && info.hasCascadedDelete() )
1116  {
1117  QgsFeatureIds joinFeatureIds;
1118  const auto constFids = fids;
1119  for ( const QgsFeatureId &fid : constFids )
1120  {
1121  const QgsFeature joinFeature = layer->joinBuffer()->joinedFeatureOf( &info, layer->getFeature( fid ) );
1122  if ( joinFeature.isValid() )
1123  joinFeatureIds.insert( joinFeature.id() );
1124  }
1125 
1126  if ( joinFeatureIds.count() > 0 )
1127  {
1128  if ( context.layers().contains( info.joinLayer() ) )
1129  {
1130  QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( info.joinLayer() );
1131  // add feature ids
1132  handledFeatureIds.unite( joinFeatureIds );
1133  context.setDuplicatedFeatures( info.joinLayer(), handledFeatureIds );
1134  }
1135  else
1136  {
1137  // add layer and feature id
1138  context.setDuplicatedFeatures( info.joinLayer(), joinFeatureIds );
1139  }
1140  }
1141  }
1142  }
1143  }
1144 
1145  return !context.layers().isEmpty();
1146 }
1147 
1148 QString QgsVectorLayerUtils::guessFriendlyIdentifierField( const QgsFields &fields, bool *foundFriendly )
1149 {
1150  if ( foundFriendly )
1151  *foundFriendly = false;
1152 
1153  if ( fields.isEmpty() )
1154  return QString();
1155 
1156  // Check the fields and keep the first one that matches.
1157  // We assume that the user has organized the data with the
1158  // more "interesting" field names first. As such, name should
1159  // be selected before oldname, othername, etc.
1160  // This candidates list is a prioritized list of candidates ranked by "interestingness"!
1161  // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
1162  // but adding hardcoded localized variants of the strings is encouraged.
1163  static QStringList sCandidates{ QStringLiteral( "name" ),
1164  QStringLiteral( "title" ),
1165  QStringLiteral( "heibt" ),
1166  QStringLiteral( "desc" ),
1167  QStringLiteral( "nom" ),
1168  QStringLiteral( "street" ),
1169  QStringLiteral( "road" ),
1170  QStringLiteral( "label" ) };
1171 
1172  // anti-names
1173  // this list of strings indicates parts of field names which make the name "less interesting".
1174  // For instance, we'd normally like to default to a field called "name" or "id", but if instead we
1175  // find one called "typename" or "typeid", then that's most likely a classification of the feature and not the
1176  // best choice to default to
1177  static QStringList sAntiCandidates{ QStringLiteral( "type" ),
1178  QStringLiteral( "class" ),
1179  QStringLiteral( "cat" )
1180  };
1181 
1182  QString bestCandidateName;
1183  QString bestCandidateNameWithAntiCandidate;
1184 
1185  for ( const QString &candidate : sCandidates )
1186  {
1187  for ( const QgsField &field : fields )
1188  {
1189  const QString fldName = field.name();
1190  if ( fldName.contains( candidate, Qt::CaseInsensitive ) )
1191  {
1192  bool isAntiCandidate = false;
1193  for ( const QString &antiCandidate : sAntiCandidates )
1194  {
1195  if ( fldName.contains( antiCandidate, Qt::CaseInsensitive ) )
1196  {
1197  isAntiCandidate = true;
1198  break;
1199  }
1200  }
1201 
1202  if ( isAntiCandidate )
1203  {
1204  if ( bestCandidateNameWithAntiCandidate.isEmpty() )
1205  {
1206  bestCandidateNameWithAntiCandidate = fldName;
1207  }
1208  }
1209  else
1210  {
1211  bestCandidateName = fldName;
1212  break;
1213  }
1214  }
1215  }
1216 
1217  if ( !bestCandidateName.isEmpty() )
1218  break;
1219  }
1220 
1221  const QString candidateName = bestCandidateName.isEmpty() ? bestCandidateNameWithAntiCandidate : bestCandidateName;
1222  if ( !candidateName.isEmpty() )
1223  {
1224  if ( foundFriendly )
1225  *foundFriendly = true;
1226  return candidateName;
1227  }
1228  else
1229  {
1230  // no good matches found by name, so scan through and look for the first string field
1231  for ( const QgsField &field : fields )
1232  {
1233  if ( field.type() == QVariant::String )
1234  return field.name();
1235  }
1236 
1237  // no string fields found - just return first field
1238  return fields.at( 0 ).name();
1239  }
1240 }
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:402
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:349
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:125
QVector< QgsGeometry > coerceToType(QgsWkbTypes::Type type, double defaultZ=0, double defaultM=0) const
Attempts to coerce this geometry into the specified destination type.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
bool enabled() const
Returns whether the effect is enabled.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:104
QgsRelationManager * relationManager
Definition: qgsproject.h:114
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:1435
A symbol entity for QgsStyle databases.
Definition: qgsstyle.h:1342
@ LabelSettingsEntity
Label settings.
Definition: qgsstyle.h:185
@ SymbolEntity
Symbols.
Definition: qgsstyle.h:180
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
virtual QList< QgsSymbolLayerReference > masks() const
Returns masks defined by this symbol layer.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:93
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
Definition: qgssymbol.cpp:727
qreal opacity() const
Returns the opacity for the symbol.
Definition: qgssymbol.h:495
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Definition: qgssymbol.h:215
Container for settings relating to a selective masking around a text.
QList< QgsSymbolLayerReference > maskedSymbolLayers() const
Returns a list of references to symbol layers that are masked by this buffer.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the mask.
double opacity() const
Returns the mask's opacity.
bool enabled() const
Returns whether the mask is enabled.
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 QgsMaskedLayers symbolLayerMasks(const QgsVectorLayer *)
Returns all masks that may be defined on symbol layers for a given vector 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 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 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 QHash< QString, QgsMaskedLayers > labelMasks(const QgsVectorLayer *)
Returns masks defined in labeling options of a layer.
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)
QHash< QString, QgsMaskedLayer > QgsMaskedLayers
QSet< QgsSymbolLayerId > symbolLayerIds
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.