Thanks to visit codestin.com
Credit goes to api.qgis.org

QGIS API Documentation 3.99.0-Master (d270888f95f)
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::labelMasks( const QgsVectorLayer *layer )
1048{
1049 class LabelMasksVisitor : public QgsStyleEntityVisitorInterface
1050 {
1051 public:
1052 bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
1053 {
1055 {
1056 currentRule = 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 auto &r : maskSettings.maskedSymbolLayers() )
1074 {
1075 QgsMaskedLayer &maskedLayer = maskedLayers[currentRule][r.layerId()];
1076 maskedLayer.symbolLayerIds.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 currentRule;
1087 };
1088
1089 if ( ! layer->labeling() )
1090 return {};
1091
1092 LabelMasksVisitor visitor;
1093 layer->labeling()->accept( &visitor );
1094 return std::move( visitor.maskedLayers );
1095}
1096
1098{
1099 if ( ! layer->renderer() )
1100 return {};
1101
1102 class SymbolLayerVisitor : public QgsStyleEntityVisitorInterface
1103 {
1104 public:
1105 bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
1106 {
1108 }
1109
1110 // Returns true if the visited symbol has effects
1111 bool visitSymbol( const QgsSymbol *symbol )
1112 {
1113 // transparency is considered has effects because it implies rasterization when masking
1114 // is involved
1115 bool symbolHasEffect = symbol->opacity() < 1;
1116 for ( int idx = 0; idx < symbol->symbolLayerCount(); idx++ )
1117 {
1118 const QgsSymbolLayer *sl = symbol->symbolLayer( idx );
1119 bool slHasEffects = sl->paintEffect() && sl->paintEffect()->enabled();
1120 symbolHasEffect |= slHasEffects;
1121
1122 // recurse over sub symbols
1123 const QgsSymbol *subSymbol = const_cast<QgsSymbolLayer *>( sl )->subSymbol();
1124 if ( subSymbol )
1125 slHasEffects |= visitSymbol( subSymbol );
1126
1127 for ( const auto &mask : sl->masks() )
1128 {
1129 QgsMaskedLayer &maskedLayer = maskedLayers[mask.layerId()];
1130 maskedLayer.hasEffects |= slHasEffects;
1131 maskedLayer.symbolLayerIds.insert( mask.symbolLayerIdV2() );
1132 }
1133 }
1134
1135 return symbolHasEffect;
1136 }
1137
1138 bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
1139 {
1140 if ( leaf.entity && leaf.entity->type() == QgsStyle::SymbolEntity )
1141 {
1142 auto symbolEntity = static_cast<const QgsStyleSymbolEntity *>( leaf.entity );
1143 if ( symbolEntity->symbol() )
1144 visitSymbol( symbolEntity->symbol() );
1145 }
1146 return true;
1147 }
1148 QgsMaskedLayers maskedLayers;
1149 };
1150
1151 SymbolLayerVisitor visitor;
1152 layer->renderer()->accept( &visitor );
1153 return visitor.maskedLayers;
1154}
1155
1157{
1159
1160 QgsExpression exp( layer->displayExpression() );
1161 context.setFeature( feature );
1162 exp.prepare( &context );
1163 QString displayString = exp.evaluate( &context ).toString();
1164
1165 return displayString;
1166}
1167
1169{
1170 if ( !layer )
1171 return false;
1172
1173 const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );
1174 for ( const QgsRelation &relation : relations )
1175 {
1176 switch ( relation.strength() )
1177 {
1179 {
1180 QgsFeatureIds childFeatureIds;
1181
1182 const auto constFids = fids;
1183 for ( const QgsFeatureId fid : constFids )
1184 {
1185 //get features connected over this relation
1186 QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( layer->getFeature( fid ) );
1187 QgsFeature childFeature;
1188 while ( relatedFeaturesIt.nextFeature( childFeature ) )
1189 {
1190 childFeatureIds.insert( childFeature.id() );
1191 }
1192 }
1193
1194 if ( childFeatureIds.count() > 0 )
1195 {
1196 if ( context.layers().contains( relation.referencingLayer() ) )
1197 {
1198 QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( relation.referencingLayer() );
1199 // add feature ids
1200 handledFeatureIds.unite( childFeatureIds );
1201 context.setDuplicatedFeatures( relation.referencingLayer(), handledFeatureIds );
1202 }
1203 else
1204 {
1205 // add layer and feature id
1206 context.setDuplicatedFeatures( relation.referencingLayer(), childFeatureIds );
1207 }
1208 }
1209 break;
1210 }
1211
1213 break;
1214 }
1215 }
1216
1217 if ( layer->joinBuffer()->containsJoins() )
1218 {
1219 const QgsVectorJoinList joins = layer->joinBuffer()->vectorJoins();
1220 for ( const QgsVectorLayerJoinInfo &info : joins )
1221 {
1222 if ( qobject_cast< QgsAuxiliaryLayer * >( info.joinLayer() ) && flags & IgnoreAuxiliaryLayers )
1223 continue;
1224
1225 if ( info.isEditable() && info.hasCascadedDelete() )
1226 {
1227 QgsFeatureIds joinFeatureIds;
1228 const auto constFids = fids;
1229 for ( const QgsFeatureId &fid : constFids )
1230 {
1231 const QgsFeature joinFeature = layer->joinBuffer()->joinedFeatureOf( &info, layer->getFeature( fid ) );
1232 if ( joinFeature.isValid() )
1233 joinFeatureIds.insert( joinFeature.id() );
1234 }
1235
1236 if ( joinFeatureIds.count() > 0 )
1237 {
1238 if ( context.layers().contains( info.joinLayer() ) )
1239 {
1240 QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( info.joinLayer() );
1241 // add feature ids
1242 handledFeatureIds.unite( joinFeatureIds );
1243 context.setDuplicatedFeatures( info.joinLayer(), handledFeatureIds );
1244 }
1245 else
1246 {
1247 // add layer and feature id
1248 context.setDuplicatedFeatures( info.joinLayer(), joinFeatureIds );
1249 }
1250 }
1251 }
1252 }
1253 }
1254
1255 return !context.layers().isEmpty();
1256}
1257
1258QString QgsVectorLayerUtils::guessFriendlyIdentifierField( const QgsFields &fields, bool *foundFriendly )
1259{
1260 if ( foundFriendly )
1261 *foundFriendly = false;
1262
1263 if ( fields.isEmpty() )
1264 return QString();
1265
1266 // Check the fields and keep the first one that matches.
1267 // We assume that the user has organized the data with the
1268 // more "interesting" field names first. As such, name should
1269 // be selected before oldname, othername, etc.
1270 // This candidates list is a prioritized list of candidates ranked by "interestingness"!
1271 // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
1272 // but adding hardcoded localized variants of the strings is encouraged.
1273 static QStringList sCandidates{ u"name"_s,
1274 u"title"_s,
1275 u"heibt"_s,
1276 u"desc"_s,
1277 u"nom"_s,
1278 u"street"_s,
1279 u"road"_s,
1280 u"label"_s,
1281 // German candidates
1282 u"titel"_s, //#spellok
1283 u"beschreibung"_s,
1284 u"strasse"_s,
1285 u"beschriftung"_s };
1286
1287 // anti-names
1288 // this list of strings indicates parts of field names which make the name "less interesting".
1289 // For instance, we'd normally like to default to a field called "name" or "title", but if instead we
1290 // find one called "typename" or "typeid", then that's most likely a classification of the feature and not the
1291 // best choice to default to
1292 static QStringList sAntiCandidates{ u"type"_s,
1293 u"class"_s,
1294 u"cat"_s,
1295 // German anti-candidates
1296 u"typ"_s,
1297 u"klasse"_s,
1298 u"kategorie"_s
1299 };
1300
1301 QString bestCandidateName;
1302 QString bestCandidateContainsName;
1303 QString bestCandidateContainsNameWithAntiCandidate;
1304
1305 for ( const QString &candidate : sCandidates )
1306 {
1307 for ( const QgsField &field : fields )
1308 {
1309 const QString fldName = field.name();
1310
1311 if ( fldName.compare( candidate, Qt::CaseInsensitive ) == 0 )
1312 {
1313 bestCandidateName = fldName;
1314 }
1315 else if ( fldName.contains( candidate, Qt::CaseInsensitive ) )
1316 {
1317 bool isAntiCandidate = false;
1318 for ( const QString &antiCandidate : sAntiCandidates )
1319 {
1320 if ( fldName.contains( antiCandidate, Qt::CaseInsensitive ) )
1321 {
1322 isAntiCandidate = true;
1323 break;
1324 }
1325 }
1326
1327 if ( isAntiCandidate )
1328 {
1329 if ( bestCandidateContainsNameWithAntiCandidate.isEmpty() )
1330 {
1331 bestCandidateContainsNameWithAntiCandidate = fldName;
1332 }
1333 }
1334 else
1335 {
1336 if ( bestCandidateContainsName.isEmpty() )
1337 {
1338 bestCandidateContainsName = fldName;
1339 }
1340 }
1341 }
1342 }
1343
1344 if ( !bestCandidateName.isEmpty() )
1345 break;
1346 }
1347
1348 QString candidateName = bestCandidateName;
1349 if ( candidateName.isEmpty() )
1350 {
1351 candidateName = bestCandidateContainsName.isEmpty() ? bestCandidateContainsNameWithAntiCandidate : bestCandidateContainsName;
1352 }
1353
1354 if ( !candidateName.isEmpty() )
1355 {
1356 // Special case for layers got from WFS using the OGR GMLAS field parsing logic.
1357 // Such layers contain a "id" field (the gml:id attribute of the object),
1358 // as well as a gml_name (a <gml:name>) element. However this gml:name is often
1359 // absent, partly because it is a property of the base class in GML schemas, and
1360 // that a lot of readers are not able to deduce its potential presence.
1361 // So try to look at another field whose name would end with _name
1362 // And fallback to using the "id" field that should always be filled.
1363 if ( candidateName == "gml_name"_L1 &&
1364 fields.indexOf( "id"_L1 ) >= 0 )
1365 {
1366 candidateName.clear();
1367 // Try to find a field ending with "_name", which is not "gml_name"
1368 for ( const QgsField &field : std::as_const( fields ) )
1369 {
1370 const QString fldName = field.name();
1371 if ( fldName != "gml_name"_L1 && fldName.endsWith( "_name"_L1 ) )
1372 {
1373 candidateName = fldName;
1374 break;
1375 }
1376 }
1377 if ( candidateName.isEmpty() )
1378 {
1379 // Fallback to "id"
1380 candidateName = u"id"_s;
1381 }
1382 }
1383
1384 if ( foundFriendly )
1385 *foundFriendly = true;
1386 return candidateName;
1387 }
1388 else
1389 {
1390 // no good matches found by name, so scan through and look for the first string field
1391 for ( const QgsField &field : fields )
1392 {
1393 if ( field.type() == QMetaType::Type::QString )
1394 return field.name();
1395 }
1396
1397 // no string fields found - just return first field
1398 return fields.at( 0 ).name();
1399 }
1400}
1401
1402template <typename T, typename ConverterFunc>
1403void populateFieldDataArray( const QVector<QVariant> &values, const QVariant &nullValue, QByteArray &res, ConverterFunc converter )
1404{
1405 res.resize( values.size() * sizeof( T ) );
1406 T *data = reinterpret_cast<T *>( res.data() );
1407 for ( const QVariant &val : values )
1408 {
1409 if ( QgsVariantUtils::isNull( val ) )
1410 {
1411 *data++ = converter( nullValue );
1412 }
1413 else
1414 {
1415 *data++ = converter( val );
1416 }
1417 }
1418}
1419
1420QByteArray QgsVectorLayerUtils::fieldToDataArray( const QgsFields &fields, const QString &fieldName, QgsFeatureIterator &it, const QVariant &nullValue )
1421{
1422 const int fieldIndex = fields.lookupField( fieldName );
1423 if ( fieldIndex < 0 )
1424 return QByteArray();
1425
1426 QVector< QVariant > values;
1427 QgsFeature f;
1428 while ( it.nextFeature( f ) )
1429 {
1430 values.append( f.attribute( fieldIndex ) );
1431 }
1432
1433 const QgsField field = fields.at( fieldIndex );
1434 QByteArray res;
1435 switch ( field.type( ) )
1436 {
1437 case QMetaType::Int:
1438 {
1439 populateFieldDataArray<int>( values, nullValue, res, []( const QVariant & v ) { return v.toInt(); } );
1440 break;
1441 }
1442
1443 case QMetaType::UInt:
1444 {
1445 populateFieldDataArray<unsigned int>( values, nullValue, res, []( const QVariant & v ) { return v.toUInt(); } );
1446 break;
1447 }
1448
1449 case QMetaType::LongLong:
1450 {
1451 populateFieldDataArray<long long>( values, nullValue, res, []( const QVariant & v ) { return v.toLongLong(); } );
1452 break;
1453 }
1454
1455 case QMetaType::ULongLong:
1456 {
1457 populateFieldDataArray<unsigned long long>( values, nullValue, res, []( const QVariant & v ) { return v.toULongLong(); } );
1458 break;
1459 }
1460
1461 case QMetaType::Double:
1462 {
1463 populateFieldDataArray<double>( values, nullValue, res, []( const QVariant & v ) { return v.toDouble(); } );
1464 break;
1465 }
1466
1467 case QMetaType::Long:
1468 {
1469 populateFieldDataArray<long>( values, nullValue, res, []( const QVariant & v ) { return v.toLongLong(); } );
1470 break;
1471 }
1472
1473 case QMetaType::Short:
1474 {
1475 populateFieldDataArray<short>( values, nullValue, res, []( const QVariant & v ) { return v.toInt(); } );
1476 break;
1477 }
1478
1479 case QMetaType::ULong:
1480 {
1481 populateFieldDataArray<unsigned long>( values, nullValue, res, []( const QVariant & v ) { return v.toULongLong(); } );
1482 break;
1483 }
1484
1485 case QMetaType::UShort:
1486 {
1487 populateFieldDataArray<unsigned short>( values, nullValue, res, []( const QVariant & v ) { return v.toUInt(); } );
1488 break;
1489 }
1490
1491 case QMetaType::Float:
1492 {
1493 populateFieldDataArray<float>( values, nullValue, res, []( const QVariant & v ) { return v.toFloat(); } );
1494 break;
1495 }
1496
1497 default:
1498 break;
1499 }
1500
1501 return res;
1502}
@ 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:4466
@ Association
Loose relation, related elements are not part of the parent and a parent copy will not copy any child...
Definition qgis.h:4465
@ 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
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:4005
@ DefaultValue
Use default field value.
Definition qgis.h:4003
@ Duplicate
Duplicate original value.
Definition qgis.h:4004
@ 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.).
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:112
QgsRelationManager * relationManager
Definition qgsproject.h:123
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:1491
A symbol entity for QgsStyle databases.
Definition qgsstyle.h:1398
@ LabelSettingsEntity
Label settings.
Definition qgsstyle.h:211
@ SymbolEntity
Symbols.
Definition qgsstyle.h:206
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 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 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 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: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
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.