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