QGIS API Documentation 3.39.0-Master (47f7b3a4989)
Loading...
Searching...
No Matches
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
19#include "qgsfeatureiterator.h"
20#include "qgsfeaturerequest.h"
21#include "qgsvectorlayerutils.h"
23#include "qgsproject.h"
24#include "qgsrelationmanager.h"
25#include "qgsfeedback.h"
26#include "qgsvectorlayer.h"
27#include "qgsthreadingutils.h"
31#include "qgspallabeling.h"
32#include "qgsrenderer.h"
33#include "qgssymbollayer.h"
35#include "qgsstyle.h"
36#include "qgsauxiliarystorage.h"
38#include "qgspainteffect.h"
40
41QgsFeatureIterator QgsVectorLayerUtils::getValuesIterator( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly )
42{
43 std::unique_ptr<QgsExpression> expression;
45
46 int attrNum = layer->fields().lookupField( fieldOrExpression );
47 if ( attrNum == -1 )
48 {
49 // try to use expression
50 expression.reset( new QgsExpression( fieldOrExpression ) );
52
53 if ( expression->hasParserError() || !expression->prepare( &context ) )
54 {
55 ok = false;
56 return QgsFeatureIterator();
57 }
58 }
59
60 QSet<QString> lst;
61 if ( !expression )
62 lst.insert( fieldOrExpression );
63 else
64 lst = expression->referencedColumns();
65
67 .setFlags( ( expression && expression->needsGeometry() ) ?
70 .setSubsetOfAttributes( lst, layer->fields() );
71
72 ok = true;
73 if ( !selectedOnly )
74 {
75 return layer->getFeatures( request );
76 }
77 else
78 {
79 return layer->getSelectedFeatures( request );
80 }
81}
82
83QList<QVariant> QgsVectorLayerUtils::getValues( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly, QgsFeedback *feedback )
84{
85 QList<QVariant> values;
86 QgsFeatureIterator fit = getValuesIterator( layer, fieldOrExpression, ok, selectedOnly );
87 if ( ok )
88 {
89 std::unique_ptr<QgsExpression> expression;
91
92 int attrNum = layer->fields().lookupField( fieldOrExpression );
93 if ( attrNum == -1 )
94 {
95 // use expression, already validated in the getValuesIterator() function
96 expression.reset( new QgsExpression( fieldOrExpression ) );
98 }
99
100 QgsFeature f;
101 while ( fit.nextFeature( f ) )
102 {
103 if ( expression )
104 {
105 context.setFeature( f );
106 QVariant v = expression->evaluate( &context );
107 values << v;
108 }
109 else
110 {
111 values << f.attribute( attrNum );
112 }
113 if ( feedback && feedback->isCanceled() )
114 {
115 ok = false;
116 return values;
117 }
118 }
119 }
120 return values;
121}
122
123QList<double> QgsVectorLayerUtils::getDoubleValues( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly, int *nullCount, QgsFeedback *feedback )
124{
125 QList<double> values;
126
127 if ( nullCount )
128 *nullCount = 0;
129
130 QList<QVariant> variantValues = getValues( layer, fieldOrExpression, ok, selectedOnly, feedback );
131 if ( !ok )
132 return values;
133
134 bool convertOk;
135 const auto constVariantValues = variantValues;
136 for ( const QVariant &value : constVariantValues )
137 {
138 double val = value.toDouble( &convertOk );
139 if ( convertOk )
140 values << val;
141 else if ( QgsVariantUtils::isNull( value ) )
142 {
143 if ( nullCount )
144 *nullCount += 1;
145 }
146 if ( feedback && feedback->isCanceled() )
147 {
148 ok = false;
149 return values;
150 }
151 }
152 return values;
153}
154
155bool QgsVectorLayerUtils::valueExists( const QgsVectorLayer *layer, int fieldIndex, const QVariant &value, const QgsFeatureIds &ignoreIds )
156{
157 if ( !layer )
158 return false;
159
160 QgsFields fields = layer->fields();
161
162 if ( fieldIndex < 0 || fieldIndex >= fields.count() )
163 return false;
164
165 // If it's a joined field search the value in the source layer
166 if ( fields.fieldOrigin( fieldIndex ) == Qgis::FieldOrigin::Join )
167 {
168 int srcFieldIndex;
169 const QgsVectorLayerJoinInfo *joinInfo { layer->joinBuffer()->joinForFieldIndex( fieldIndex, fields, srcFieldIndex ) };
170 if ( ! joinInfo )
171 {
172 return false;
173 }
174 fieldIndex = srcFieldIndex;
175 layer = joinInfo->joinLayer();
176 if ( ! layer )
177 {
178 return false;
179 }
180 fields = layer->fields();
181 }
182
183 QString fieldName = fields.at( fieldIndex ).name();
184
185 // build up an optimised feature request
186 QgsFeatureRequest request;
187 request.setNoAttributes();
189
190 // at most we need to check ignoreIds.size() + 1 - the feature not in ignoreIds is the one we're interested in
191 int limit = ignoreIds.size() + 1;
192 request.setLimit( limit );
193
194 request.setFilterExpression( QStringLiteral( "%1=%2" ).arg( QgsExpression::quotedColumnRef( fieldName ),
195 QgsExpression::quotedValue( value ) ) );
196
197 QgsFeature feat;
198 QgsFeatureIterator it = layer->getFeatures( request );
199 while ( it.nextFeature( feat ) )
200 {
201 if ( ignoreIds.contains( feat.id() ) )
202 continue;
203
204 return true;
205 }
206
207 return false;
208}
209
210QVariant QgsVectorLayerUtils::createUniqueValue( const QgsVectorLayer *layer, int fieldIndex, const QVariant &seed )
211{
212 if ( !layer )
213 return QVariant();
214
215 QgsFields fields = layer->fields();
216
217 if ( fieldIndex < 0 || fieldIndex >= fields.count() )
218 return QVariant();
219
220 QgsField field = fields.at( fieldIndex );
221
222 if ( field.isNumeric() )
223 {
224 QVariant maxVal = layer->maximumValue( fieldIndex );
225 QVariant newVar( maxVal.toLongLong() + 1 );
226 if ( field.convertCompatible( newVar ) )
227 return newVar;
228 else
229 return QVariant();
230 }
231 else
232 {
233 switch ( field.type() )
234 {
235 case QMetaType::Type::QString:
236 {
237 QString base;
238 if ( seed.isValid() )
239 base = seed.toString();
240
241 if ( !base.isEmpty() )
242 {
243 // strip any existing _1, _2 from the seed
244 const thread_local QRegularExpression rx( QStringLiteral( "(.*)_\\d+" ) );
245 QRegularExpressionMatch match = rx.match( base );
246 if ( match.hasMatch() )
247 {
248 base = match.captured( 1 );
249 }
250 }
251 else
252 {
253 // no base seed - fetch first value from layer
255 req.setLimit( 1 );
256 req.setSubsetOfAttributes( QgsAttributeList() << fieldIndex );
258 QgsFeature f;
259 layer->getFeatures( req ).nextFeature( f );
260 base = f.attribute( fieldIndex ).toString();
261 }
262
263 // try variants like base_1, base_2, etc until a new value found
264 QStringList vals = layer->uniqueStringsMatching( fieldIndex, base );
265
266 // might already be unique
267 if ( !base.isEmpty() && !vals.contains( base ) )
268 return base;
269
270 for ( int i = 1; i < 10000; ++i )
271 {
272 QString testVal = base + '_' + QString::number( i );
273 if ( !vals.contains( testVal ) )
274 return testVal;
275 }
276
277 // failed
278 return QVariant();
279 }
280
281 default:
282 // todo other types - dates? times?
283 break;
284 }
285 }
286
287 return QVariant();
288}
289
290QVariant QgsVectorLayerUtils::createUniqueValueFromCache( const QgsVectorLayer *layer, int fieldIndex, const QSet<QVariant> &existingValues, const QVariant &seed )
291{
292 if ( !layer )
293 return QVariant();
294
295 QgsFields fields = layer->fields();
296
297 if ( fieldIndex < 0 || fieldIndex >= fields.count() )
298 return QVariant();
299
300 QgsField field = fields.at( fieldIndex );
301
302 if ( field.isNumeric() )
303 {
304 QVariant maxVal = existingValues.isEmpty() ? 0 : *std::max_element( existingValues.begin(), existingValues.end(), []( const QVariant & a, const QVariant & b ) { return a.toLongLong() < b.toLongLong(); } );
305 QVariant newVar( maxVal.toLongLong() + 1 );
306 if ( field.convertCompatible( newVar ) )
307 return newVar;
308 else
309 return QVariant();
310 }
311 else
312 {
313 switch ( field.type() )
314 {
315 case QMetaType::Type::QString:
316 {
317 QString base;
318 if ( seed.isValid() )
319 base = seed.toString();
320
321 if ( !base.isEmpty() )
322 {
323 // strip any existing _1, _2 from the seed
324 const thread_local QRegularExpression rx( QStringLiteral( "(.*)_\\d+" ) );
325 QRegularExpressionMatch match = rx.match( base );
326 if ( match.hasMatch() )
327 {
328 base = match.captured( 1 );
329 }
330 }
331 else
332 {
333 // no base seed - fetch first value from layer
335 base = existingValues.isEmpty() ? QString() : existingValues.constBegin()->toString();
336 }
337
338 // try variants like base_1, base_2, etc until a new value found
339 QStringList vals;
340 for ( const auto &v : std::as_const( existingValues ) )
341 {
342 if ( v.toString().startsWith( base ) )
343 vals.push_back( v.toString() );
344 }
345
346 // might already be unique
347 if ( !base.isEmpty() && !vals.contains( base ) )
348 return base;
349
350 for ( int i = 1; i < 10000; ++i )
351 {
352 QString testVal = base + '_' + QString::number( i );
353 if ( !vals.contains( testVal ) )
354 return testVal;
355 }
356
357 // failed
358 return QVariant();
359 }
360
361 default:
362 // todo other types - dates? times?
363 break;
364 }
365 }
366
367 return QVariant();
368
369}
370
371bool QgsVectorLayerUtils::attributeHasConstraints( const QgsVectorLayer *layer, int attributeIndex )
372{
373 if ( !layer )
374 return false;
375
376 if ( attributeIndex < 0 || attributeIndex >= layer->fields().count() )
377 return false;
378
379 const QgsFieldConstraints constraints = layer->fields().at( attributeIndex ).constraints();
380 return ( constraints.constraints() & QgsFieldConstraints::ConstraintNotNull ||
383}
384
385bool QgsVectorLayerUtils::validateAttribute( const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors,
387{
388 if ( !layer )
389 return false;
390
391 if ( attributeIndex < 0 || attributeIndex >= layer->fields().count() )
392 return false;
393
394 QgsFields fields = layer->fields();
395 QgsField field = fields.at( attributeIndex );
396 const QVariant value = feature.attribute( attributeIndex );
397 bool valid = true;
398 errors.clear();
399
400 QgsFieldConstraints constraints = field.constraints();
401
402 if ( constraints.constraints() & QgsFieldConstraints::ConstraintExpression && !constraints.constraintExpression().isEmpty()
405 {
407 context.setFeature( feature );
408
409 QgsExpression expr( constraints.constraintExpression() );
410
411 valid = expr.evaluate( &context ).toBool();
412
413 if ( expr.hasParserError() )
414 {
415 errors << QObject::tr( "parser error: %1" ).arg( expr.parserErrorString() );
416 }
417 else if ( expr.hasEvalError() )
418 {
419 errors << QObject::tr( "evaluation error: %1" ).arg( expr.evalErrorString() );
420 }
421 else if ( !valid )
422 {
423 errors << QObject::tr( "%1 check failed" ).arg( constraints.constraintDescription() );
424 }
425 }
426
427 bool notNullConstraintViolated { false };
428
432 {
433 bool exempt = false;
434 if ( fields.fieldOrigin( attributeIndex ) == Qgis::FieldOrigin::Provider
436 {
437 int providerIdx = fields.fieldOriginIndex( attributeIndex );
438 exempt = layer->dataProvider()->skipConstraintCheck( providerIdx, QgsFieldConstraints::ConstraintNotNull, value );
439 }
440
441 if ( !exempt )
442 {
443 valid = valid && !QgsVariantUtils::isNull( value );
444
445 if ( QgsVariantUtils::isNull( value ) )
446 {
447 errors << QObject::tr( "value is NULL" );
448 notNullConstraintViolated = true;
449 }
450 }
451 }
452
453 // if a NOT NULL constraint is violated we don't need to check for UNIQUE
454 if ( ! notNullConstraintViolated )
455 {
456
460 {
461 bool exempt = false;
462 if ( fields.fieldOrigin( attributeIndex ) == Qgis::FieldOrigin::Provider
464 {
465 int providerIdx = fields.fieldOriginIndex( attributeIndex );
466 exempt = layer->dataProvider()->skipConstraintCheck( providerIdx, QgsFieldConstraints::ConstraintUnique, value );
467 }
468
469 if ( !exempt )
470 {
471
472 bool alreadyExists = QgsVectorLayerUtils::valueExists( layer, attributeIndex, value, QgsFeatureIds() << feature.id() );
473 valid = valid && !alreadyExists;
474
475 if ( alreadyExists )
476 {
477 errors << QObject::tr( "value is not unique" );
478 }
479 }
480 }
481 }
482
483 return valid;
484}
485
487 const QgsAttributeMap &attributes, QgsExpressionContext *context )
488{
489 QgsFeatureList features { createFeatures( layer, QgsFeaturesDataList() << QgsFeatureData( geometry, attributes ), context ) };
490 return features.isEmpty() ? QgsFeature() : features.first();
491}
492
494{
495 if ( !layer )
496 return QgsFeatureList();
497
498 QgsFeatureList result;
499 result.reserve( featuresData.length() );
500
501 QgsExpressionContext *evalContext = context;
502 std::unique_ptr< QgsExpressionContext > tempContext;
503 if ( !evalContext )
504 {
505 // no context passed, so we create a default one
507 evalContext = tempContext.get();
508 }
509
510 QgsFields fields = layer->fields();
511
512 // Cache unique values
513 QMap<int, QSet<QVariant>> uniqueValueCache;
514
515 auto checkUniqueValue = [ & ]( const int fieldIdx, const QVariant & value )
516 {
517 if ( ! uniqueValueCache.contains( fieldIdx ) )
518 {
519 // If the layer is filtered, get unique values from an unfiltered clone
520 if ( ! layer->subsetString().isEmpty() )
521 {
522 std::unique_ptr<QgsVectorLayer> unfilteredClone { layer->clone( ) };
523 unfilteredClone->setSubsetString( QString( ) );
524 uniqueValueCache[ fieldIdx ] = unfilteredClone->uniqueValues( fieldIdx );
525 }
526 else
527 {
528 uniqueValueCache[ fieldIdx ] = layer->uniqueValues( fieldIdx );
529 }
530 }
531 return uniqueValueCache[ fieldIdx ].contains( value );
532 };
533
534 for ( const auto &fd : std::as_const( featuresData ) )
535 {
536
537 QgsFeature newFeature( fields );
538 newFeature.setValid( true );
539 newFeature.setGeometry( fd.geometry() );
540
541 // initialize attributes
542 newFeature.initAttributes( fields.count() );
543 for ( int idx = 0; idx < fields.count(); ++idx )
544 {
545 QVariant v;
546 bool checkUnique = true;
547 const bool hasUniqueConstraint { static_cast<bool>( fields.at( idx ).constraints().constraints() & QgsFieldConstraints::ConstraintUnique ) };
548
549 // in order of priority:
550 // 1. passed attribute value and if field does not have a unique constraint like primary key
551 if ( fd.attributes().contains( idx ) )
552 {
553 v = fd.attributes().value( idx );
554 }
555
556 // 2. client side default expression
557 // note - deliberately not using else if!
558 QgsDefaultValue defaultValueDefinition = layer->defaultValueDefinition( idx );
559 if ( ( QgsVariantUtils::isNull( v ) || ( hasUniqueConstraint
560 && checkUniqueValue( idx, v ) )
561 || defaultValueDefinition.applyOnUpdate() )
562 && defaultValueDefinition.isValid() )
563 {
564 // client side default expression set - takes precedence over all. Why? Well, this is the only default
565 // which QGIS users have control over, so we assume that they're deliberately overriding any
566 // provider defaults for some good reason and we should respect that
567 v = layer->defaultValue( idx, newFeature, evalContext );
568 }
569
570 // 3. provider side default value clause
571 // note - not an else if deliberately. Users may return null from a default value expression to fallback to provider defaults
572 if ( ( QgsVariantUtils::isNull( v ) || ( hasUniqueConstraint
573 && checkUniqueValue( idx, v ) ) )
574 && fields.fieldOrigin( idx ) == Qgis::FieldOrigin::Provider )
575 {
576 int providerIndex = fields.fieldOriginIndex( idx );
577 QString providerDefault = layer->dataProvider()->defaultValueClause( providerIndex );
578 if ( !providerDefault.isEmpty() )
579 {
580 v = providerDefault;
581 checkUnique = false;
582 }
583 }
584
585 // 4. provider side default literal
586 // note - deliberately not using else if!
587 if ( ( QgsVariantUtils::isNull( v ) || ( checkUnique
588 && hasUniqueConstraint
589 && checkUniqueValue( idx, v ) ) )
590 && fields.fieldOrigin( idx ) == Qgis::FieldOrigin::Provider )
591 {
592 int providerIndex = fields.fieldOriginIndex( idx );
593 v = layer->dataProvider()->defaultValue( providerIndex );
594 if ( v.isValid() )
595 {
596 //trust that the provider default has been sensibly set not to violate any constraints
597 checkUnique = false;
598 }
599 }
600
601 // 5. passed attribute value
602 // note - deliberately not using else if!
603 if ( QgsVariantUtils::isNull( v ) && fd.attributes().contains( idx ) )
604 {
605 v = fd.attributes().value( idx );
606 }
607
608 // last of all... check that unique constraints are respected if the value is valid
609 if ( v.isValid() )
610 {
611 // we can't handle not null or expression constraints here, since there's no way to pick a sensible
612 // value if the constraint is violated
613 if ( checkUnique && hasUniqueConstraint )
614 {
615 if ( checkUniqueValue( idx, v ) )
616 {
617 // unique constraint violated
618 QVariant uniqueValue = QgsVectorLayerUtils::createUniqueValueFromCache( layer, idx, uniqueValueCache[ idx ], v );
619 if ( uniqueValue.isValid() )
620 v = uniqueValue;
621 }
622 }
623 if ( hasUniqueConstraint )
624 {
625 uniqueValueCache[ idx ].insert( v );
626 }
627 }
628 newFeature.setAttribute( idx, v );
629 }
630 result.append( newFeature );
631 }
632 return result;
633}
634
635QgsFeature QgsVectorLayerUtils::duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, QgsDuplicateFeatureContext &duplicateFeatureContext, const int maxDepth, int depth, QList<QgsVectorLayer *> referencedLayersBranch )
636{
637 if ( !layer )
638 return QgsFeature();
639
640 if ( !layer->isEditable() )
641 return QgsFeature();
642
643 //get context from layer
645 context.setFeature( feature );
646
647 //respect field duplicate policy
648 QgsAttributeMap attributeMap;
649 const int fieldCount = layer->fields().count();
650 for ( int fieldIdx = 0; fieldIdx < fieldCount; ++fieldIdx )
651 {
652 const QgsField field = layer->fields().at( fieldIdx );
653 switch ( field.duplicatePolicy() )
654 {
656 //do nothing - default values ​​are determined
657 break;
658
660 attributeMap.insert( fieldIdx, feature.attribute( fieldIdx ) );
661 break;
662
664 attributeMap.insert( fieldIdx, QgsUnsetAttributeValue() );
665 break;
666 }
667 }
668
669 QgsFeature newFeature = createFeature( layer, feature.geometry(), attributeMap, &context );
670 layer->addFeature( newFeature );
671
672 const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );
673 referencedLayersBranch << layer;
674
675 const int effectiveMaxDepth = maxDepth > 0 ? maxDepth : 100;
676
677 for ( const QgsRelation &relation : relations )
678 {
679 //check if composition (and not association)
680 if ( relation.strength() == Qgis::RelationshipStrength::Composition && !referencedLayersBranch.contains( relation.referencingLayer() ) && depth < effectiveMaxDepth )
681 {
682 //get features connected over this relation
683 QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( feature );
684 QgsFeatureIds childFeatureIds;
685 QgsFeature childFeature;
686 while ( relatedFeaturesIt.nextFeature( childFeature ) )
687 {
688 //set childlayer editable
689 relation.referencingLayer()->startEditing();
690 //change the fk of the child to the id of the new parent
691 const auto pairs = relation.fieldPairs();
692 for ( const QgsRelation::FieldPair &fieldPair : pairs )
693 {
694 childFeature.setAttribute( fieldPair.first, newFeature.attribute( fieldPair.second ) );
695 }
696 //call the function for the child
697 childFeatureIds.insert( duplicateFeature( relation.referencingLayer(), childFeature, project, duplicateFeatureContext, maxDepth, depth + 1, referencedLayersBranch ).id() );
698 }
699
700 //store for feedback
701 duplicateFeatureContext.setDuplicatedFeatures( relation.referencingLayer(), childFeatureIds );
702 }
703 }
704
705
706 return newFeature;
707}
708
709std::unique_ptr<QgsVectorLayerFeatureSource> QgsVectorLayerUtils::getFeatureSource( QPointer<QgsVectorLayer> layer, QgsFeedback *feedback )
710{
711 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource;
712
713 auto getFeatureSource = [ layer, &featureSource, feedback ]
714 {
715 Q_ASSERT( QThread::currentThread() == qApp->thread() || feedback );
716 QgsVectorLayer *lyr = layer.data();
717
718 if ( lyr )
719 {
720 featureSource.reset( new QgsVectorLayerFeatureSource( lyr ) );
721 }
722 };
723
725
726 return featureSource;
727}
728
730{
731 if ( !feature.fields().isEmpty() )
732 {
733 QgsAttributes attributes;
734 attributes.reserve( fields.size() );
735 // feature has a field mapping, so we can match attributes to field names
736 for ( const QgsField &field : fields )
737 {
738 int index = feature.fields().lookupField( field.name() );
739 attributes.append( index >= 0 ? feature.attribute( index ) : QgsVariantUtils::createNullVariant( field.type() ) );
740 }
741 feature.setAttributes( attributes );
742 }
743 else
744 {
745 // no field name mapping in feature, just use order
746 const int lengthDiff = feature.attributeCount() - fields.count();
747 if ( lengthDiff > 0 )
748 {
749 // truncate extra attributes
750 QgsAttributes attributes = feature.attributes().mid( 0, fields.count() );
751 feature.setAttributes( attributes );
752 }
753 else if ( lengthDiff < 0 )
754 {
755 // add missing null attributes
756 QgsAttributes attributes = feature.attributes();
757 attributes.reserve( fields.count() );
758 const int attributeCount = feature.attributeCount();
759 for ( int i = attributeCount; i < fields.count(); ++i )
760 {
761 attributes.append( QgsVariantUtils::createNullVariant( fields.at( i ).type() ) );
762 }
763 feature.setAttributes( attributes );
764 }
765 }
766 feature.setFields( fields );
767}
768
770{
771 Qgis::WkbType inputWkbType( layer->wkbType( ) );
772 QgsFeatureList resultFeatures;
773 QgsFeature newF( feature );
774 // Fix attributes
776
777 if ( sinkFlags & QgsFeatureSink::RegeneratePrimaryKey )
778 {
779 // drop incoming primary key values, let them be regenerated
780 const QgsAttributeList pkIndexes = layer->dataProvider()->pkAttributeIndexes();
781 for ( int index : pkIndexes )
782 {
783 if ( index >= 0 )
784 newF.setAttribute( index, QVariant() );
785 }
786 }
787
788 // Does geometry need transformations?
790 bool newFHasGeom = newFGeomType !=
792 newFGeomType != Qgis::GeometryType::Null;
793 bool layerHasGeom = inputWkbType !=
795 inputWkbType != Qgis::WkbType::Unknown;
796 // Drop geometry if layer is geometry-less
797 if ( ( newFHasGeom && !layerHasGeom ) || !newFHasGeom )
798 {
799 QgsFeature _f = QgsFeature( layer->fields() );
800 _f.setAttributes( newF.attributes() );
801 resultFeatures.append( _f );
802 }
803 else
804 {
805 // Geometry need fixing?
806 const QVector< QgsGeometry > geometries = newF.geometry().coerceToType( inputWkbType );
807
808 if ( geometries.count() != 1 )
809 {
810 QgsAttributeMap attrMap;
811 for ( int j = 0; j < newF.fields().count(); j++ )
812 {
813 attrMap[j] = newF.attribute( j );
814 }
815 resultFeatures.reserve( geometries.size() );
816 for ( const QgsGeometry &geometry : geometries )
817 {
818 QgsFeature _f( createFeature( layer, geometry, attrMap ) );
819 resultFeatures.append( _f );
820 }
821 }
822 else
823 {
824 newF.setGeometry( geometries.at( 0 ) );
825 resultFeatures.append( newF );
826 }
827 }
828 return resultFeatures;
829}
830
832{
833 QgsFeatureList resultFeatures;
834 for ( const QgsFeature &f : features )
835 {
836 const QgsFeatureList features( makeFeatureCompatible( f, layer, sinkFlags ) );
837 for ( const auto &_f : features )
838 {
839 resultFeatures.append( _f );
840 }
841 }
842 return resultFeatures;
843}
844
846{
847 QList<QgsVectorLayer *> layers;
848 QMap<QgsVectorLayer *, QgsFeatureIds>::const_iterator i;
849 for ( i = mDuplicatedFeatures.begin(); i != mDuplicatedFeatures.end(); ++i )
850 layers.append( i.key() );
851 return layers;
852}
853
855{
856 return mDuplicatedFeatures[layer];
857}
858
859void QgsVectorLayerUtils::QgsDuplicateFeatureContext::setDuplicatedFeatures( QgsVectorLayer *layer, const QgsFeatureIds &ids )
860{
861 if ( mDuplicatedFeatures.contains( layer ) )
862 mDuplicatedFeatures[layer] += ids;
863 else
864 mDuplicatedFeatures.insert( layer, ids );
865}
866/*
867QMap<QgsVectorLayer *, QgsFeatureIds> QgsVectorLayerUtils::QgsDuplicateFeatureContext::duplicateFeatureContext() const
868{
869 return mDuplicatedFeatures;
870}
871*/
872
874 mGeometry( geometry ),
875 mAttributes( attributes )
876{}
877
879{
880 return mGeometry;
881}
882
884{
885 return mAttributes;
886}
887
888bool _fieldIsEditable( const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature )
889{
890 return layer->isEditable() &&
891 !layer->editFormConfig().readOnly( fieldIndex ) &&
892 // Provider permissions
893 layer->dataProvider() &&
895 ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures && ( FID_IS_NULL( feature.id() ) || FID_IS_NEW( feature.id() ) ) ) ) &&
896 // Field must not be read only
897 !layer->fields().at( fieldIndex ).isReadOnly();
898}
899
900bool QgsVectorLayerUtils::fieldIsReadOnly( const QgsVectorLayer *layer, int fieldIndex )
901{
902 if ( layer->fields().fieldOrigin( fieldIndex ) == Qgis::FieldOrigin::Join )
903 {
904 int srcFieldIndex;
905 const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
906
907 if ( !info || !info->isEditable() || !info->joinLayer() )
908 return true;
909
910 return fieldIsReadOnly( info->joinLayer(), srcFieldIndex );
911 }
912 else
913 {
914 // any of these properties makes the field read only
915 if ( !layer->isEditable() ||
916 layer->editFormConfig().readOnly( fieldIndex ) ||
917 !layer->dataProvider() ||
920 layer->fields().at( fieldIndex ).isReadOnly() )
921 return true;
922
923 return false;
924 }
925}
926
928{
929 // editability will vary feature-by-feature only for joined fields
930 if ( layer->fields().fieldOrigin( fieldIndex ) == Qgis::FieldOrigin::Join )
931 {
932 int srcFieldIndex;
933 const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
934
935 if ( !info || !info->isEditable() || info->hasUpsertOnEdit() )
936 return false;
937
938 // join does not have upsert capabilities, so the ability to edit the joined field will
939 // vary feature-by-feature, depending on whether the join target feature already exists
940 return true;
941 }
942 else
943 {
944 return false;
945 }
946}
947
948bool QgsVectorLayerUtils::fieldIsEditable( const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature )
949{
950 if ( layer->fields().fieldOrigin( fieldIndex ) == Qgis::FieldOrigin::Join )
951 {
952 int srcFieldIndex;
953 const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
954
955 if ( !info || !info->isEditable() )
956 return false;
957
958 // check that joined feature exist, else it is not editable
959 if ( !info->hasUpsertOnEdit() )
960 {
961 const QgsFeature joinedFeature = layer->joinBuffer()->joinedFeatureOf( info, feature );
962 if ( !joinedFeature.isValid() )
963 return false;
964 }
965
966 return _fieldIsEditable( info->joinLayer(), srcFieldIndex, feature );
967 }
968 else
969 return _fieldIsEditable( layer, fieldIndex, feature );
970}
971
972
973QHash<QString, QgsMaskedLayers> QgsVectorLayerUtils::labelMasks( const QgsVectorLayer *layer )
974{
975 class LabelMasksVisitor : public QgsStyleEntityVisitorInterface
976 {
977 public:
978 bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
979 {
981 {
982 currentRule = node.identifier;
983 return true;
984 }
985 return false;
986 }
987 bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
988 {
989 if ( leaf.entity && leaf.entity->type() == QgsStyle::LabelSettingsEntity )
990 {
991 auto labelSettingsEntity = static_cast<const QgsStyleLabelSettingsEntity *>( leaf.entity );
992 const QgsTextMaskSettings &maskSettings = labelSettingsEntity->settings().format().mask();
993 if ( maskSettings.enabled() )
994 {
995 // transparency is considered has effects because it implies rasterization when masking
996 // is involved
997 const bool hasEffects = maskSettings.opacity() < 1 ||
998 ( maskSettings.paintEffect() && maskSettings.paintEffect()->enabled() );
999 for ( const auto &r : maskSettings.maskedSymbolLayers() )
1000 {
1001 QgsMaskedLayer &maskedLayer = maskedLayers[currentRule][r.layerId()];
1002 maskedLayer.symbolLayerIds.insert( r.symbolLayerIdV2() );
1003 maskedLayer.hasEffects = hasEffects;
1004 }
1005 }
1006 }
1007 return true;
1008 }
1009
1010 QHash<QString, QgsMaskedLayers> maskedLayers;
1011 // Current label rule, empty string for a simple labeling
1012 QString currentRule;
1013 };
1014
1015 if ( ! layer->labeling() )
1016 return {};
1017
1018 LabelMasksVisitor visitor;
1019 layer->labeling()->accept( &visitor );
1020 return std::move( visitor.maskedLayers );
1021}
1022
1024{
1025 if ( ! layer->renderer() )
1026 return {};
1027
1028 class SymbolLayerVisitor : public QgsStyleEntityVisitorInterface
1029 {
1030 public:
1031 bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
1032 {
1034 }
1035
1036 // Returns true if the visited symbol has effects
1037 bool visitSymbol( const QgsSymbol *symbol )
1038 {
1039 // transparency is considered has effects because it implies rasterization when masking
1040 // is involved
1041 bool symbolHasEffect = symbol->opacity() < 1;
1042 for ( int idx = 0; idx < symbol->symbolLayerCount(); idx++ )
1043 {
1044 const QgsSymbolLayer *sl = symbol->symbolLayer( idx );
1045 bool slHasEffects = sl->paintEffect() && sl->paintEffect()->enabled();
1046 symbolHasEffect |= slHasEffects;
1047
1048 // recurse over sub symbols
1049 const QgsSymbol *subSymbol = const_cast<QgsSymbolLayer *>( sl )->subSymbol();
1050 if ( subSymbol )
1051 slHasEffects |= visitSymbol( subSymbol );
1052
1053 for ( const auto &mask : sl->masks() )
1054 {
1055 QgsMaskedLayer &maskedLayer = maskedLayers[mask.layerId()];
1056 maskedLayer.hasEffects |= slHasEffects;
1057 maskedLayer.symbolLayerIds.insert( mask.symbolLayerIdV2() );
1058 }
1059 }
1060
1061 return symbolHasEffect;
1062 }
1063
1064 bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
1065 {
1066 if ( leaf.entity && leaf.entity->type() == QgsStyle::SymbolEntity )
1067 {
1068 auto symbolEntity = static_cast<const QgsStyleSymbolEntity *>( leaf.entity );
1069 if ( symbolEntity->symbol() )
1070 visitSymbol( symbolEntity->symbol() );
1071 }
1072 return true;
1073 }
1074 QgsMaskedLayers maskedLayers;
1075 };
1076
1077 SymbolLayerVisitor visitor;
1078 layer->renderer()->accept( &visitor );
1079 return visitor.maskedLayers;
1080}
1081
1083{
1085
1086 QgsExpression exp( layer->displayExpression() );
1087 context.setFeature( feature );
1088 exp.prepare( &context );
1089 QString displayString = exp.evaluate( &context ).toString();
1090
1091 return displayString;
1092}
1093
1095{
1096 if ( !layer )
1097 return false;
1098
1099 const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );
1100 for ( const QgsRelation &relation : relations )
1101 {
1102 switch ( relation.strength() )
1103 {
1105 {
1106 QgsFeatureIds childFeatureIds;
1107
1108 const auto constFids = fids;
1109 for ( const QgsFeatureId fid : constFids )
1110 {
1111 //get features connected over this relation
1112 QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( layer->getFeature( fid ) );
1113 QgsFeature childFeature;
1114 while ( relatedFeaturesIt.nextFeature( childFeature ) )
1115 {
1116 childFeatureIds.insert( childFeature.id() );
1117 }
1118 }
1119
1120 if ( childFeatureIds.count() > 0 )
1121 {
1122 if ( context.layers().contains( relation.referencingLayer() ) )
1123 {
1124 QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( relation.referencingLayer() );
1125 // add feature ids
1126 handledFeatureIds.unite( childFeatureIds );
1127 context.setDuplicatedFeatures( relation.referencingLayer(), handledFeatureIds );
1128 }
1129 else
1130 {
1131 // add layer and feature id
1132 context.setDuplicatedFeatures( relation.referencingLayer(), childFeatureIds );
1133 }
1134 }
1135 break;
1136 }
1137
1139 break;
1140 }
1141 }
1142
1143 if ( layer->joinBuffer()->containsJoins() )
1144 {
1145 const QgsVectorJoinList joins = layer->joinBuffer()->vectorJoins();
1146 for ( const QgsVectorLayerJoinInfo &info : joins )
1147 {
1148 if ( qobject_cast< QgsAuxiliaryLayer * >( info.joinLayer() ) && flags & IgnoreAuxiliaryLayers )
1149 continue;
1150
1151 if ( info.isEditable() && info.hasCascadedDelete() )
1152 {
1153 QgsFeatureIds joinFeatureIds;
1154 const auto constFids = fids;
1155 for ( const QgsFeatureId &fid : constFids )
1156 {
1157 const QgsFeature joinFeature = layer->joinBuffer()->joinedFeatureOf( &info, layer->getFeature( fid ) );
1158 if ( joinFeature.isValid() )
1159 joinFeatureIds.insert( joinFeature.id() );
1160 }
1161
1162 if ( joinFeatureIds.count() > 0 )
1163 {
1164 if ( context.layers().contains( info.joinLayer() ) )
1165 {
1166 QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( info.joinLayer() );
1167 // add feature ids
1168 handledFeatureIds.unite( joinFeatureIds );
1169 context.setDuplicatedFeatures( info.joinLayer(), handledFeatureIds );
1170 }
1171 else
1172 {
1173 // add layer and feature id
1174 context.setDuplicatedFeatures( info.joinLayer(), joinFeatureIds );
1175 }
1176 }
1177 }
1178 }
1179 }
1180
1181 return !context.layers().isEmpty();
1182}
1183
1184QString QgsVectorLayerUtils::guessFriendlyIdentifierField( const QgsFields &fields, bool *foundFriendly )
1185{
1186 if ( foundFriendly )
1187 *foundFriendly = false;
1188
1189 if ( fields.isEmpty() )
1190 return QString();
1191
1192 // Check the fields and keep the first one that matches.
1193 // We assume that the user has organized the data with the
1194 // more "interesting" field names first. As such, name should
1195 // be selected before oldname, othername, etc.
1196 // This candidates list is a prioritized list of candidates ranked by "interestingness"!
1197 // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
1198 // but adding hardcoded localized variants of the strings is encouraged.
1199 static QStringList sCandidates{ QStringLiteral( "name" ),
1200 QStringLiteral( "title" ),
1201 QStringLiteral( "heibt" ),
1202 QStringLiteral( "desc" ),
1203 QStringLiteral( "nom" ),
1204 QStringLiteral( "street" ),
1205 QStringLiteral( "road" ),
1206 QStringLiteral( "label" ),
1207 // German candidates
1208 QStringLiteral( "titel" ), //#spellok
1209 QStringLiteral( "beschreibung" ),
1210 QStringLiteral( "strasse" ),
1211 QStringLiteral( "beschriftung" ) };
1212
1213 // anti-names
1214 // this list of strings indicates parts of field names which make the name "less interesting".
1215 // For instance, we'd normally like to default to a field called "name" or "title", but if instead we
1216 // find one called "typename" or "typeid", then that's most likely a classification of the feature and not the
1217 // best choice to default to
1218 static QStringList sAntiCandidates{ QStringLiteral( "type" ),
1219 QStringLiteral( "class" ),
1220 QStringLiteral( "cat" ),
1221 // German anti-candidates
1222 QStringLiteral( "typ" ),
1223 QStringLiteral( "klasse" ),
1224 QStringLiteral( "kategorie" )
1225 };
1226
1227 QString bestCandidateName;
1228 QString bestCandidateNameWithAntiCandidate;
1229
1230 for ( const QString &candidate : sCandidates )
1231 {
1232 for ( const QgsField &field : fields )
1233 {
1234 const QString fldName = field.name();
1235 if ( fldName.contains( candidate, Qt::CaseInsensitive ) )
1236 {
1237 bool isAntiCandidate = false;
1238 for ( const QString &antiCandidate : sAntiCandidates )
1239 {
1240 if ( fldName.contains( antiCandidate, Qt::CaseInsensitive ) )
1241 {
1242 isAntiCandidate = true;
1243 break;
1244 }
1245 }
1246
1247 if ( isAntiCandidate )
1248 {
1249 if ( bestCandidateNameWithAntiCandidate.isEmpty() )
1250 {
1251 bestCandidateNameWithAntiCandidate = fldName;
1252 }
1253 }
1254 else
1255 {
1256 bestCandidateName = fldName;
1257 break;
1258 }
1259 }
1260 }
1261
1262 if ( !bestCandidateName.isEmpty() )
1263 break;
1264 }
1265
1266 QString candidateName = bestCandidateName.isEmpty() ? bestCandidateNameWithAntiCandidate : bestCandidateName;
1267 if ( !candidateName.isEmpty() )
1268 {
1269 // Special case for layers got from WFS using the OGR GMLAS field parsing logic.
1270 // Such layers contain a "id" field (the gml:id attribute of the object),
1271 // as well as a gml_name (a <gml:name>) element. However this gml:name is often
1272 // absent, partly because it is a property of the base class in GML schemas, and
1273 // that a lot of readers are not able to deduce its potential presence.
1274 // So try to look at another field whose name would end with _name
1275 // And fallback to using the "id" field that should always be filled.
1276 if ( candidateName == QLatin1String( "gml_name" ) &&
1277 fields.indexOf( QLatin1String( "id" ) ) >= 0 )
1278 {
1279 candidateName.clear();
1280 // Try to find a field ending with "_name", which is not "gml_name"
1281 for ( const QgsField &field : std::as_const( fields ) )
1282 {
1283 const QString fldName = field.name();
1284 if ( fldName != QLatin1String( "gml_name" ) && fldName.endsWith( QLatin1String( "_name" ) ) )
1285 {
1286 candidateName = fldName;
1287 break;
1288 }
1289 }
1290 if ( candidateName.isEmpty() )
1291 {
1292 // Fallback to "id"
1293 candidateName = QStringLiteral( "id" );
1294 }
1295 }
1296
1297 if ( foundFriendly )
1298 *foundFriendly = true;
1299 return candidateName;
1300 }
1301 else
1302 {
1303 // no good matches found by name, so scan through and look for the first string field
1304 for ( const QgsField &field : fields )
1305 {
1306 if ( field.type() == QMetaType::Type::QString )
1307 return field.name();
1308 }
1309
1310 // no string fields found - just return first field
1311 return fields.at( 0 ).name();
1312 }
1313}
@ Composition
Fix relation, related elements are part of the parent and a parent copy will copy any children or del...
@ Association
Loose relation, related elements are not part of the parent and a parent copy will not copy any child...
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
@ NoFlags
No flags are set.
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
Definition qgis.h:274
@ Unknown
Unknown types.
@ Null
No geometry.
@ UnsetField
Clears the field value so that the data provider backend will populate using any backend triggers or ...
@ DefaultValue
Use default field value.
@ Duplicate
Duplicate original value.
@ Provider
Field originates from the underlying data provider of the vector layer.
@ Join
Field originates from a joined layer.
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:201
@ NoGeometry
No geometry.
@ Unknown
Unknown.
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.
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)
Fetch next feature and stores in f, returns true on success.
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(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QFlags< SinkFlag > SinkFlags
@ 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:58
Q_INVOKABLE bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
QgsAttributes attributes
Definition qgsfeature.h:67
QgsFields fields
Definition qgsfeature.h:68
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
QgsFeatureId id
Definition qgsfeature.h:66
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
void setFields(const QgsFields &fields, bool initAttributes=false)
Assigns a field map with the feature to allow attribute access by attribute name.
int attributeCount() const
Returns the number of attributes attached to the feature.
QgsGeometry geometry
Definition qgsfeature.h:69
void setValid(bool validity)
Sets the validity of the feature.
bool isValid() const
Returns the validity of this feature.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition qgsfeedback.h:44
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:53
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.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:53
QMetaType::Type type
Definition qgsfield.h:60
QString name
Definition qgsfield.h:62
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
Definition qgsfield.cpp:472
Qgis::FieldDuplicatePolicy duplicatePolicy() const
Returns the field's duplicate policy, which indicates how field values should be handled during a dup...
Definition qgsfield.cpp:764
bool isNumeric
Definition qgsfield.h:56
QgsFieldConstraints constraints
Definition qgsfield.h:65
bool isReadOnly
Definition qgsfield.h:67
Container of fields for a vector layer.
Definition qgsfields.h:46
int count
Definition qgsfields.h:50
bool isEmpty
Definition qgsfields.h:49
Q_INVOKABLE int indexOf(const QString &fieldName) const
Gets the field index from the field name.
Qgis::FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
int size() const
Returns number of items.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
int fieldOriginIndex(int fieldIdx) const
Returns the field's origin index (its meaning is specific to each type of origin).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A geometry is the spatial representation of a feature.
QVector< QgsGeometry > coerceToType(Qgis::WkbType type, double defaultZ=0, double defaultM=0) const
Attempts to coerce this geometry into the specified destination type.
Qgis::WkbType wkbType() const
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:107
QgsRelationManager * relationManager
Definition qgsproject.h:117
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:67
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:1465
A symbol entity for QgsStyle databases.
Definition qgsstyle.h:1372
@ 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:94
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
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.
Represents a default, "not-specified" value for a feature attribute.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
@ 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 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.
const QgsVectorJoinList & vectorJoins() const
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 bool attributeHasConstraints(const QgsVectorLayer *layer, int attributeIndex)
Returns true if a feature attribute has active constraints.
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.
QFlags< CascadedFeatureFlag > CascadedFeatureFlags
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.
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.
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
const QgsAbstractVectorLayerLabeling * labeling() const
Access to const labeling configuration.
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
Q_INVOKABLE Qgis::WkbType wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
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.
QgsVectorLayerJoinBuffer * joinBuffer()
Returns the join buffer object.
QgsVectorLayer * clone() const override
Returns a new instance equivalent to this one.
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.
QgsEditFormConfig editFormConfig
Q_INVOKABLE QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
QMap< int, QVariant > QgsAttributeMap
QList< QgsFeature > QgsFeatureList
#define FID_IS_NULL(fid)
QSet< QgsFeatureId > QgsFeatureIds
#define FID_IS_NEW(fid)
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
QList< int > QgsAttributeList
Definition qgsfield.h:27
QList< QgsVectorLayerJoinInfo > QgsVectorJoinList
bool _fieldIsEditable(const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature)
QHash< QString, QgsMaskedLayer > QgsMaskedLayers
masked layers where key is the layer id
QSet< QString > 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.