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