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