QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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"
39
40QgsFeatureIterator QgsVectorLayerUtils::getValuesIterator( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly )
41{
42 std::unique_ptr<QgsExpression> expression;
44
45 int attrNum = layer->fields().lookupField( fieldOrExpression );
46 if ( attrNum == -1 )
47 {
48 // try to use expression
49 expression.reset( new QgsExpression( fieldOrExpression ) );
51
52 if ( expression->hasParserError() || !expression->prepare( &context ) )
53 {
54 ok = false;
55 return QgsFeatureIterator();
56 }
57 }
58
59 QSet<QString> lst;
60 if ( !expression )
61 lst.insert( fieldOrExpression );
62 else
63 lst = expression->referencedColumns();
64
66 .setFlags( ( expression && expression->needsGeometry() ) ?
69 .setSubsetOfAttributes( lst, layer->fields() );
70
71 ok = true;
72 if ( !selectedOnly )
73 {
74 return layer->getFeatures( request );
75 }
76 else
77 {
78 return layer->getSelectedFeatures( request );
79 }
80}
81
82QList<QVariant> QgsVectorLayerUtils::getValues( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly, QgsFeedback *feedback )
83{
84 QList<QVariant> values;
85 QgsFeatureIterator fit = getValuesIterator( layer, fieldOrExpression, ok, selectedOnly );
86 if ( ok )
87 {
88 std::unique_ptr<QgsExpression> expression;
90
91 int attrNum = layer->fields().lookupField( fieldOrExpression );
92 if ( attrNum == -1 )
93 {
94 // use expression, already validated in the getValuesIterator() function
95 expression.reset( new QgsExpression( fieldOrExpression ) );
97 }
98
99 QgsFeature f;
100 while ( fit.nextFeature( f ) )
101 {
102 if ( expression )
103 {
104 context.setFeature( f );
105 QVariant v = expression->evaluate( &context );
106 values << v;
107 }
108 else
109 {
110 values << f.attribute( attrNum );
111 }
112 if ( feedback && feedback->isCanceled() )
113 {
114 ok = false;
115 return values;
116 }
117 }
118 }
119 return values;
120}
121
122QList<double> QgsVectorLayerUtils::getDoubleValues( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly, int *nullCount, QgsFeedback *feedback )
123{
124 QList<double> values;
125
126 if ( nullCount )
127 *nullCount = 0;
128
129 QList<QVariant> variantValues = getValues( layer, fieldOrExpression, ok, selectedOnly, feedback );
130 if ( !ok )
131 return values;
132
133 bool convertOk;
134 const auto constVariantValues = variantValues;
135 for ( const QVariant &value : constVariantValues )
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 ) == QgsFields::FieldOrigin::OriginJoin )
166 {
167 int srcFieldIndex;
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 QVariant::String:
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 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 QVariant::String:
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 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.values().first().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::validateAttribute( const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors,
372{
373 if ( !layer )
374 return false;
375
376 if ( attributeIndex < 0 || attributeIndex >= layer->fields().count() )
377 return false;
378
379 QgsFields fields = layer->fields();
380 QgsField field = fields.at( attributeIndex );
381 const QVariant value = feature.attribute( attributeIndex );
382 bool valid = true;
383 errors.clear();
384
385 QgsFieldConstraints constraints = field.constraints();
386
387 if ( constraints.constraints() & QgsFieldConstraints::ConstraintExpression && !constraints.constraintExpression().isEmpty()
390 {
392 context.setFeature( feature );
393
394 QgsExpression expr( constraints.constraintExpression() );
395
396 valid = expr.evaluate( &context ).toBool();
397
398 if ( expr.hasParserError() )
399 {
400 errors << QObject::tr( "parser error: %1" ).arg( expr.parserErrorString() );
401 }
402 else if ( expr.hasEvalError() )
403 {
404 errors << QObject::tr( "evaluation error: %1" ).arg( expr.evalErrorString() );
405 }
406 else if ( !valid )
407 {
408 errors << QObject::tr( "%1 check failed" ).arg( constraints.constraintDescription() );
409 }
410 }
411
412 bool notNullConstraintViolated { false };
413
417 {
418 bool exempt = false;
419 if ( fields.fieldOrigin( attributeIndex ) == QgsFields::OriginProvider
421 {
422 int providerIdx = fields.fieldOriginIndex( attributeIndex );
423 exempt = layer->dataProvider()->skipConstraintCheck( providerIdx, QgsFieldConstraints::ConstraintNotNull, value );
424 }
425
426 if ( !exempt )
427 {
428 valid = valid && !QgsVariantUtils::isNull( value );
429
430 if ( QgsVariantUtils::isNull( value ) )
431 {
432 errors << QObject::tr( "value is NULL" );
433 notNullConstraintViolated = true;
434 }
435 }
436 }
437
438 // if a NOT NULL constraint is violated we don't need to check for UNIQUE
439 if ( ! notNullConstraintViolated )
440 {
441
445 {
446 bool exempt = false;
447 if ( fields.fieldOrigin( attributeIndex ) == QgsFields::OriginProvider
449 {
450 int providerIdx = fields.fieldOriginIndex( attributeIndex );
451 exempt = layer->dataProvider()->skipConstraintCheck( providerIdx, QgsFieldConstraints::ConstraintUnique, value );
452 }
453
454 if ( !exempt )
455 {
456
457 bool alreadyExists = QgsVectorLayerUtils::valueExists( layer, attributeIndex, value, QgsFeatureIds() << feature.id() );
458 valid = valid && !alreadyExists;
459
460 if ( alreadyExists )
461 {
462 errors << QObject::tr( "value is not unique" );
463 }
464 }
465 }
466 }
467
468 return valid;
469}
470
472 const QgsAttributeMap &attributes, QgsExpressionContext *context )
473{
474 QgsFeatureList features { createFeatures( layer, QgsFeaturesDataList() << QgsFeatureData( geometry, attributes ), context ) };
475 return features.isEmpty() ? QgsFeature() : features.first();
476}
477
479{
480 if ( !layer )
481 return QgsFeatureList();
482
483 QgsFeatureList result;
484 result.reserve( featuresData.length() );
485
486 QgsExpressionContext *evalContext = context;
487 std::unique_ptr< QgsExpressionContext > tempContext;
488 if ( !evalContext )
489 {
490 // no context passed, so we create a default one
492 evalContext = tempContext.get();
493 }
494
495 QgsFields fields = layer->fields();
496
497 // Cache unique values
498 QMap<int, QSet<QVariant>> uniqueValueCache;
499
500 auto checkUniqueValue = [ & ]( const int fieldIdx, const QVariant & value )
501 {
502 if ( ! uniqueValueCache.contains( fieldIdx ) )
503 {
504 // If the layer is filtered, get unique values from an unfiltered clone
505 if ( ! layer->subsetString().isEmpty() )
506 {
507 std::unique_ptr<QgsVectorLayer> unfilteredClone { layer->clone( ) };
508 unfilteredClone->setSubsetString( QString( ) );
509 uniqueValueCache[ fieldIdx ] = unfilteredClone->uniqueValues( fieldIdx );
510 }
511 else
512 {
513 uniqueValueCache[ fieldIdx ] = layer->uniqueValues( fieldIdx );
514 }
515 }
516 return uniqueValueCache[ fieldIdx ].contains( value );
517 };
518
519 for ( const auto &fd : std::as_const( featuresData ) )
520 {
521
522 QgsFeature newFeature( fields );
523 newFeature.setValid( true );
524 newFeature.setGeometry( fd.geometry() );
525
526 // initialize attributes
527 newFeature.initAttributes( fields.count() );
528 for ( int idx = 0; idx < fields.count(); ++idx )
529 {
530 QVariant v;
531 bool checkUnique = true;
532 const bool hasUniqueConstraint { static_cast<bool>( fields.at( idx ).constraints().constraints() & QgsFieldConstraints::ConstraintUnique ) };
533
534 // in order of priority:
535 // 1. passed attribute value and if field does not have a unique constraint like primary key
536 if ( fd.attributes().contains( idx ) )
537 {
538 v = fd.attributes().value( idx );
539 }
540
541 // 2. client side default expression
542 // note - deliberately not using else if!
543 QgsDefaultValue defaultValueDefinition = layer->defaultValueDefinition( idx );
544 if ( ( QgsVariantUtils::isNull( v ) || ( hasUniqueConstraint
545 && checkUniqueValue( idx, v ) )
546 || defaultValueDefinition.applyOnUpdate() )
547 && defaultValueDefinition.isValid() )
548 {
549 // client side default expression set - takes precedence over all. Why? Well, this is the only default
550 // which QGIS users have control over, so we assume that they're deliberately overriding any
551 // provider defaults for some good reason and we should respect that
552 v = layer->defaultValue( idx, newFeature, evalContext );
553 }
554
555 // 3. provider side default value clause
556 // note - not an else if deliberately. Users may return null from a default value expression to fallback to provider defaults
557 if ( ( QgsVariantUtils::isNull( v ) || ( hasUniqueConstraint
558 && checkUniqueValue( idx, v ) ) )
559 && fields.fieldOrigin( idx ) == QgsFields::OriginProvider )
560 {
561 int providerIndex = fields.fieldOriginIndex( idx );
562 QString providerDefault = layer->dataProvider()->defaultValueClause( providerIndex );
563 if ( !providerDefault.isEmpty() )
564 {
565 v = providerDefault;
566 checkUnique = false;
567 }
568 }
569
570 // 4. provider side default literal
571 // note - deliberately not using else if!
572 if ( ( QgsVariantUtils::isNull( v ) || ( checkUnique
573 && hasUniqueConstraint
574 && checkUniqueValue( idx, v ) ) )
575 && fields.fieldOrigin( idx ) == QgsFields::OriginProvider )
576 {
577 int providerIndex = fields.fieldOriginIndex( idx );
578 v = layer->dataProvider()->defaultValue( providerIndex );
579 if ( v.isValid() )
580 {
581 //trust that the provider default has been sensibly set not to violate any constraints
582 checkUnique = false;
583 }
584 }
585
586 // 5. passed attribute value
587 // note - deliberately not using else if!
588 if ( QgsVariantUtils::isNull( v ) && fd.attributes().contains( idx ) )
589 {
590 v = fd.attributes().value( idx );
591 }
592
593 // last of all... check that unique constraints are respected if the value is valid
594 if ( v.isValid() )
595 {
596 // we can't handle not null or expression constraints here, since there's no way to pick a sensible
597 // value if the constraint is violated
598 if ( checkUnique && hasUniqueConstraint )
599 {
600 if ( checkUniqueValue( idx, v ) )
601 {
602 // unique constraint violated
603 QVariant uniqueValue = QgsVectorLayerUtils::createUniqueValueFromCache( layer, idx, uniqueValueCache[ idx ], v );
604 if ( uniqueValue.isValid() )
605 v = uniqueValue;
606 }
607 }
608 if ( hasUniqueConstraint )
609 {
610 uniqueValueCache[ idx ].insert( v );
611 }
612 }
613 newFeature.setAttribute( idx, v );
614 }
615 result.append( newFeature );
616 }
617 return result;
618}
619
620QgsFeature QgsVectorLayerUtils::duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, QgsDuplicateFeatureContext &duplicateFeatureContext, const int maxDepth, int depth, QList<QgsVectorLayer *> referencedLayersBranch )
621{
622 if ( !layer )
623 return QgsFeature();
624
625 if ( !layer->isEditable() )
626 return QgsFeature();
627
628 //get context from layer
630 context.setFeature( feature );
631
632 QgsFeature newFeature = createFeature( layer, feature.geometry(), feature.attributes().toMap(), &context );
633 layer->addFeature( newFeature );
634
635 const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );
636
637 const int effectiveMaxDepth = maxDepth > 0 ? maxDepth : 100;
638
639 for ( const QgsRelation &relation : relations )
640 {
641 //check if composition (and not association)
642 if ( relation.strength() == Qgis::RelationshipStrength::Composition && !referencedLayersBranch.contains( relation.referencedLayer() ) && depth < effectiveMaxDepth )
643 {
644 depth++;
645 referencedLayersBranch << layer;
646
647 //get features connected over this relation
648 QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( feature );
649 QgsFeatureIds childFeatureIds;
650 QgsFeature childFeature;
651 while ( relatedFeaturesIt.nextFeature( childFeature ) )
652 {
653 //set childlayer editable
654 relation.referencingLayer()->startEditing();
655 //change the fk of the child to the id of the new parent
656 const auto pairs = relation.fieldPairs();
657 for ( const QgsRelation::FieldPair &fieldPair : pairs )
658 {
659 childFeature.setAttribute( fieldPair.first, newFeature.attribute( fieldPair.second ) );
660 }
661 //call the function for the child
662 childFeatureIds.insert( duplicateFeature( relation.referencingLayer(), childFeature, project, duplicateFeatureContext, maxDepth, depth, referencedLayersBranch ).id() );
663 }
664
665 //store for feedback
666 duplicateFeatureContext.setDuplicatedFeatures( relation.referencingLayer(), childFeatureIds );
667 }
668 }
669
670
671 return newFeature;
672}
673
674std::unique_ptr<QgsVectorLayerFeatureSource> QgsVectorLayerUtils::getFeatureSource( QPointer<QgsVectorLayer> layer, QgsFeedback *feedback )
675{
676 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource;
677
678 auto getFeatureSource = [ layer, &featureSource, feedback ]
679 {
680 Q_ASSERT( QThread::currentThread() == qApp->thread() || feedback );
681 QgsVectorLayer *lyr = layer.data();
682
683 if ( lyr )
684 {
685 featureSource.reset( new QgsVectorLayerFeatureSource( lyr ) );
686 }
687 };
688
690
691 return featureSource;
692}
693
695{
696 if ( !feature.fields().isEmpty() )
697 {
698 QgsAttributes attributes;
699 attributes.reserve( fields.size() );
700 // feature has a field mapping, so we can match attributes to field names
701 for ( const QgsField &field : fields )
702 {
703 int index = feature.fields().lookupField( field.name() );
704 attributes.append( index >= 0 ? feature.attribute( index ) : QVariant( field.type() ) );
705 }
706 feature.setAttributes( attributes );
707 }
708 else
709 {
710 // no field name mapping in feature, just use order
711 const int lengthDiff = feature.attributes().count() - fields.count();
712 if ( lengthDiff > 0 )
713 {
714 // truncate extra attributes
715 QgsAttributes attributes = feature.attributes().mid( 0, fields.count() );
716 feature.setAttributes( attributes );
717 }
718 else if ( lengthDiff < 0 )
719 {
720 // add missing null attributes
721 QgsAttributes attributes = feature.attributes();
722 attributes.reserve( fields.count() );
723 for ( int i = feature.attributes().count(); i < fields.count(); ++i )
724 {
725 attributes.append( QVariant( fields.at( i ).type() ) );
726 }
727 feature.setAttributes( attributes );
728 }
729 }
730 feature.setFields( fields );
731}
732
733QgsFeatureList QgsVectorLayerUtils::makeFeatureCompatible( const QgsFeature &feature, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags )
734{
735 QgsWkbTypes::Type inputWkbType( layer->wkbType( ) );
736 QgsFeatureList resultFeatures;
737 QgsFeature newF( feature );
738 // Fix attributes
740
741 if ( sinkFlags & QgsFeatureSink::RegeneratePrimaryKey )
742 {
743 // drop incoming primary key values, let them be regenerated
744 const QgsAttributeList pkIndexes = layer->dataProvider()->pkAttributeIndexes();
745 for ( int index : pkIndexes )
746 {
747 if ( index >= 0 )
748 newF.setAttribute( index, QVariant() );
749 }
750 }
751
752 // Does geometry need transformations?
754 bool newFHasGeom = newFGeomType !=
755 QgsWkbTypes::GeometryType::UnknownGeometry &&
756 newFGeomType != QgsWkbTypes::GeometryType::NullGeometry;
757 bool layerHasGeom = inputWkbType !=
758 QgsWkbTypes::Type::NoGeometry &&
759 inputWkbType != QgsWkbTypes::Type::Unknown;
760 // Drop geometry if layer is geometry-less
761 if ( ( newFHasGeom && !layerHasGeom ) || !newFHasGeom )
762 {
763 QgsFeature _f = QgsFeature( layer->fields() );
764 _f.setAttributes( newF.attributes() );
765 resultFeatures.append( _f );
766 }
767 else
768 {
769 // Geometry need fixing?
770 const QVector< QgsGeometry > geometries = newF.geometry().coerceToType( inputWkbType );
771
772 if ( geometries.count() != 1 )
773 {
774 QgsAttributeMap attrMap;
775 for ( int j = 0; j < newF.fields().count(); j++ )
776 {
777 attrMap[j] = newF.attribute( j );
778 }
779 resultFeatures.reserve( geometries.size() );
780 for ( const QgsGeometry &geometry : geometries )
781 {
782 QgsFeature _f( createFeature( layer, geometry, attrMap ) );
783 resultFeatures.append( _f );
784 }
785 }
786 else
787 {
788 newF.setGeometry( geometries.at( 0 ) );
789 resultFeatures.append( newF );
790 }
791 }
792 return resultFeatures;
793}
794
795QgsFeatureList QgsVectorLayerUtils::makeFeaturesCompatible( const QgsFeatureList &features, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags )
796{
797 QgsFeatureList resultFeatures;
798 for ( const QgsFeature &f : features )
799 {
800 const QgsFeatureList features( makeFeatureCompatible( f, layer, sinkFlags ) );
801 for ( const auto &_f : features )
802 {
803 resultFeatures.append( _f );
804 }
805 }
806 return resultFeatures;
807}
808
810{
811 QList<QgsVectorLayer *> layers;
812 QMap<QgsVectorLayer *, QgsFeatureIds>::const_iterator i;
813 for ( i = mDuplicatedFeatures.begin(); i != mDuplicatedFeatures.end(); ++i )
814 layers.append( i.key() );
815 return layers;
816}
817
819{
820 return mDuplicatedFeatures[layer];
821}
822
823void QgsVectorLayerUtils::QgsDuplicateFeatureContext::setDuplicatedFeatures( QgsVectorLayer *layer, const QgsFeatureIds &ids )
824{
825 if ( mDuplicatedFeatures.contains( layer ) )
826 mDuplicatedFeatures[layer] += ids;
827 else
828 mDuplicatedFeatures.insert( layer, ids );
829}
830/*
831QMap<QgsVectorLayer *, QgsFeatureIds> QgsVectorLayerUtils::QgsDuplicateFeatureContext::duplicateFeatureContext() const
832{
833 return mDuplicatedFeatures;
834}
835*/
836
838 mGeometry( geometry ),
839 mAttributes( attributes )
840{}
841
843{
844 return mGeometry;
845}
846
848{
849 return mAttributes;
850}
851
852bool _fieldIsEditable( const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature )
853{
854 return layer->isEditable() &&
855 !layer->editFormConfig().readOnly( fieldIndex ) &&
856 // Provider permissions
857 layer->dataProvider() &&
859 ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures && ( FID_IS_NULL( feature.id() ) || FID_IS_NEW( feature.id() ) ) ) ) &&
860 // Field must not be read only
861 !layer->fields().at( fieldIndex ).isReadOnly();
862}
863
864bool QgsVectorLayerUtils::fieldIsReadOnly( const QgsVectorLayer *layer, int fieldIndex )
865{
866 if ( layer->fields().fieldOrigin( fieldIndex ) == QgsFields::OriginJoin )
867 {
868 int srcFieldIndex;
869 const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
870
871 if ( !info || !info->isEditable() || !info->joinLayer() )
872 return true;
873
874 return fieldIsReadOnly( info->joinLayer(), srcFieldIndex );
875 }
876 else
877 {
878 // any of these properties makes the field read only
879 if ( !layer->isEditable() ||
880 layer->editFormConfig().readOnly( fieldIndex ) ||
881 !layer->dataProvider() ||
884 layer->fields().at( fieldIndex ).isReadOnly() )
885 return true;
886
887 return false;
888 }
889}
890
892{
893 // editability will vary feature-by-feature only for joined fields
894 if ( layer->fields().fieldOrigin( fieldIndex ) == QgsFields::OriginJoin )
895 {
896 int srcFieldIndex;
897 const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
898
899 if ( !info || !info->isEditable() || info->hasUpsertOnEdit() )
900 return false;
901
902 // join does not have upsert capabilities, so the ability to edit the joined field will
903 // vary feature-by-feature, depending on whether the join target feature already exists
904 return true;
905 }
906 else
907 {
908 return false;
909 }
910}
911
912bool QgsVectorLayerUtils::fieldIsEditable( const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature )
913{
914 if ( layer->fields().fieldOrigin( fieldIndex ) == QgsFields::OriginJoin )
915 {
916 int srcFieldIndex;
917 const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
918
919 if ( !info || !info->isEditable() )
920 return false;
921
922 // check that joined feature exist, else it is not editable
923 if ( !info->hasUpsertOnEdit() )
924 {
925 const QgsFeature joinedFeature = layer->joinBuffer()->joinedFeatureOf( info, feature );
926 if ( !joinedFeature.isValid() )
927 return false;
928 }
929
930 return _fieldIsEditable( info->joinLayer(), srcFieldIndex, feature );
931 }
932 else
933 return _fieldIsEditable( layer, fieldIndex, feature );
934}
935
936
937QHash<QString, QgsMaskedLayers> QgsVectorLayerUtils::labelMasks( const QgsVectorLayer *layer )
938{
939 class LabelMasksVisitor : public QgsStyleEntityVisitorInterface
940 {
941 public:
942 bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
943 {
945 {
946 currentRule = node.identifier;
947 return true;
948 }
949 return false;
950 }
951 bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
952 {
953 if ( leaf.entity && leaf.entity->type() == QgsStyle::LabelSettingsEntity )
954 {
955 auto labelSettingsEntity = static_cast<const QgsStyleLabelSettingsEntity *>( leaf.entity );
956 const QgsTextMaskSettings &maskSettings = labelSettingsEntity->settings().format().mask();
957 if ( maskSettings.enabled() )
958 {
959 // transparency is considered has effects because it implies rasterization when masking
960 // is involved
961 const bool hasEffects = maskSettings.opacity() < 1 ||
962 ( maskSettings.paintEffect() && maskSettings.paintEffect()->enabled() );
963 for ( const auto &r : maskSettings.maskedSymbolLayers() )
964 {
965 QgsMaskedLayer &maskedLayer = maskedLayers[currentRule][r.layerId()];
966 maskedLayer.symbolLayerIds.insert( r.symbolLayerId() );
967 maskedLayer.hasEffects = hasEffects;
968 }
969 }
970 }
971 return true;
972 }
973
974 QHash<QString, QgsMaskedLayers> maskedLayers;
975 // Current label rule, empty string for a simple labeling
976 QString currentRule;
977 };
978
979 if ( ! layer->labeling() )
980 return {};
981
982 LabelMasksVisitor visitor;
983 layer->labeling()->accept( &visitor );
984 return std::move( visitor.maskedLayers );
985}
986
988{
989 if ( ! layer->renderer() )
990 return {};
991
992 class SymbolLayerVisitor : public QgsStyleEntityVisitorInterface
993 {
994 public:
995 bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
996 {
998 }
999
1000 // Returns true if the visited symbol has effects
1001 bool visitSymbol( const QgsSymbol *symbol )
1002 {
1003 // transparency is considered has effects because it implies rasterization when masking
1004 // is involved
1005 bool symbolHasEffect = symbol->opacity() < 1;
1006 for ( int idx = 0; idx < symbol->symbolLayerCount(); idx++ )
1007 {
1008 const QgsSymbolLayer *sl = symbol->symbolLayer( idx );
1009 bool slHasEffects = sl->paintEffect() && sl->paintEffect()->enabled();
1010 symbolHasEffect |= slHasEffects;
1011
1012 // recurse over sub symbols
1013 const QgsSymbol *subSymbol = const_cast<QgsSymbolLayer *>( sl )->subSymbol();
1014 if ( subSymbol )
1015 slHasEffects |= visitSymbol( subSymbol );
1016
1017 for ( const auto &mask : sl->masks() )
1018 {
1019 QgsMaskedLayer &maskedLayer = maskedLayers[mask.layerId()];
1020 maskedLayer.hasEffects |= slHasEffects;
1021 maskedLayer.symbolLayerIds.insert( mask.symbolLayerId() );
1022 }
1023 }
1024
1025 return symbolHasEffect;
1026 }
1027
1028 bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
1029 {
1030 if ( leaf.entity && leaf.entity->type() == QgsStyle::SymbolEntity )
1031 {
1032 auto symbolEntity = static_cast<const QgsStyleSymbolEntity *>( leaf.entity );
1033 if ( symbolEntity->symbol() )
1034 visitSymbol( symbolEntity->symbol() );
1035 }
1036 return true;
1037 }
1038 QgsMaskedLayers maskedLayers;
1039 };
1040
1041 SymbolLayerVisitor visitor;
1042 layer->renderer()->accept( &visitor );
1043 return visitor.maskedLayers;
1044}
1045
1047{
1049
1050 QgsExpression exp( layer->displayExpression() );
1051 context.setFeature( feature );
1052 exp.prepare( &context );
1053 QString displayString = exp.evaluate( &context ).toString();
1054
1055 return displayString;
1056}
1057
1058bool QgsVectorLayerUtils::impactsCascadeFeatures( const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context, CascadedFeatureFlags flags )
1059{
1060 if ( !layer )
1061 return false;
1062
1063 const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );
1064 for ( const QgsRelation &relation : relations )
1065 {
1066 switch ( relation.strength() )
1067 {
1069 {
1070 QgsFeatureIds childFeatureIds;
1071
1072 const auto constFids = fids;
1073 for ( const QgsFeatureId fid : constFids )
1074 {
1075 //get features connected over this relation
1076 QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( layer->getFeature( fid ) );
1077 QgsFeature childFeature;
1078 while ( relatedFeaturesIt.nextFeature( childFeature ) )
1079 {
1080 childFeatureIds.insert( childFeature.id() );
1081 }
1082 }
1083
1084 if ( childFeatureIds.count() > 0 )
1085 {
1086 if ( context.layers().contains( relation.referencingLayer() ) )
1087 {
1088 QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( relation.referencingLayer() );
1089 // add feature ids
1090 handledFeatureIds.unite( childFeatureIds );
1091 context.setDuplicatedFeatures( relation.referencingLayer(), handledFeatureIds );
1092 }
1093 else
1094 {
1095 // add layer and feature id
1096 context.setDuplicatedFeatures( relation.referencingLayer(), childFeatureIds );
1097 }
1098 }
1099 break;
1100 }
1101
1103 break;
1104 }
1105 }
1106
1107 if ( layer->joinBuffer()->containsJoins() )
1108 {
1109 const QgsVectorJoinList joins = layer->joinBuffer()->vectorJoins();
1110 for ( const QgsVectorLayerJoinInfo &info : joins )
1111 {
1112 if ( qobject_cast< QgsAuxiliaryLayer * >( info.joinLayer() ) && flags & IgnoreAuxiliaryLayers )
1113 continue;
1114
1115 if ( info.isEditable() && info.hasCascadedDelete() )
1116 {
1117 QgsFeatureIds joinFeatureIds;
1118 const auto constFids = fids;
1119 for ( const QgsFeatureId &fid : constFids )
1120 {
1121 const QgsFeature joinFeature = layer->joinBuffer()->joinedFeatureOf( &info, layer->getFeature( fid ) );
1122 if ( joinFeature.isValid() )
1123 joinFeatureIds.insert( joinFeature.id() );
1124 }
1125
1126 if ( joinFeatureIds.count() > 0 )
1127 {
1128 if ( context.layers().contains( info.joinLayer() ) )
1129 {
1130 QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( info.joinLayer() );
1131 // add feature ids
1132 handledFeatureIds.unite( joinFeatureIds );
1133 context.setDuplicatedFeatures( info.joinLayer(), handledFeatureIds );
1134 }
1135 else
1136 {
1137 // add layer and feature id
1138 context.setDuplicatedFeatures( info.joinLayer(), joinFeatureIds );
1139 }
1140 }
1141 }
1142 }
1143 }
1144
1145 return !context.layers().isEmpty();
1146}
1147
1148QString QgsVectorLayerUtils::guessFriendlyIdentifierField( const QgsFields &fields, bool *foundFriendly )
1149{
1150 if ( foundFriendly )
1151 *foundFriendly = false;
1152
1153 if ( fields.isEmpty() )
1154 return QString();
1155
1156 // Check the fields and keep the first one that matches.
1157 // We assume that the user has organized the data with the
1158 // more "interesting" field names first. As such, name should
1159 // be selected before oldname, othername, etc.
1160 // This candidates list is a prioritized list of candidates ranked by "interestingness"!
1161 // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
1162 // but adding hardcoded localized variants of the strings is encouraged.
1163 static QStringList sCandidates{ QStringLiteral( "name" ),
1164 QStringLiteral( "title" ),
1165 QStringLiteral( "heibt" ),
1166 QStringLiteral( "desc" ),
1167 QStringLiteral( "nom" ),
1168 QStringLiteral( "street" ),
1169 QStringLiteral( "road" ),
1170 QStringLiteral( "label" ) };
1171
1172 // anti-names
1173 // this list of strings indicates parts of field names which make the name "less interesting".
1174 // For instance, we'd normally like to default to a field called "name" or "id", but if instead we
1175 // find one called "typename" or "typeid", then that's most likely a classification of the feature and not the
1176 // best choice to default to
1177 static QStringList sAntiCandidates{ QStringLiteral( "type" ),
1178 QStringLiteral( "class" ),
1179 QStringLiteral( "cat" )
1180 };
1181
1182 QString bestCandidateName;
1183 QString bestCandidateNameWithAntiCandidate;
1184
1185 for ( const QString &candidate : sCandidates )
1186 {
1187 for ( const QgsField &field : fields )
1188 {
1189 const QString fldName = field.name();
1190 if ( fldName.contains( candidate, Qt::CaseInsensitive ) )
1191 {
1192 bool isAntiCandidate = false;
1193 for ( const QString &antiCandidate : sAntiCandidates )
1194 {
1195 if ( fldName.contains( antiCandidate, Qt::CaseInsensitive ) )
1196 {
1197 isAntiCandidate = true;
1198 break;
1199 }
1200 }
1201
1202 if ( isAntiCandidate )
1203 {
1204 if ( bestCandidateNameWithAntiCandidate.isEmpty() )
1205 {
1206 bestCandidateNameWithAntiCandidate = fldName;
1207 }
1208 }
1209 else
1210 {
1211 bestCandidateName = fldName;
1212 break;
1213 }
1214 }
1215 }
1216
1217 if ( !bestCandidateName.isEmpty() )
1218 break;
1219 }
1220
1221 const QString candidateName = bestCandidateName.isEmpty() ? bestCandidateNameWithAntiCandidate : bestCandidateName;
1222 if ( !candidateName.isEmpty() )
1223 {
1224 if ( foundFriendly )
1225 *foundFriendly = true;
1226 return candidateName;
1227 }
1228 else
1229 {
1230 // no good matches found by name, so scan through and look for the first string field
1231 for ( const QgsField &field : fields )
1232 {
1233 if ( field.type() == QVariant::String )
1234 return field.name();
1235 }
1236
1237 // no string fields found - just return first field
1238 return fields.at( 0 ).name();
1239 }
1240}
@ 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...
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.
Definition: qgsattributes.h:59
CORE_EXPORT QgsAttributeMap toMap() const
Returns a QgsAttributeMap of the attribute values.
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)
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 & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
@ 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:56
bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
Definition: qgsfeature.cpp:265
QgsAttributes attributes
Definition: qgsfeature.h:65
QgsFields fields
Definition: qgsfeature.h:66
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
Definition: qgsfeature.cpp:238
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:160
void setFields(const QgsFields &fields, bool initAttributes=false)
Assigns a field map with the feature to allow attribute access by attribute name.
Definition: qgsfeature.cpp:198
QgsGeometry geometry
Definition: qgsfeature.h:67
void setValid(bool validity)
Sets the validity of the feature.
Definition: qgsfeature.cpp:224
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:219
QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Definition: qgsfeature.cpp:338
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:170
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:45
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
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.
Q_GADGET Constraints constraints
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
QString name
Definition: qgsfield.h:60
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
Definition: qgsfield.cpp:412
Q_GADGET bool isNumeric
Definition: qgsfield.h:54
QVariant::Type type
Definition: qgsfield.h:58
QgsFieldConstraints constraints
Definition: qgsfield.h:63
bool isReadOnly
Definition: qgsfield.h:65
Container of fields for a vector layer.
Definition: qgsfields.h:45
@ OriginJoin
Field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfields.h:52
@ OriginProvider
Field comes from the underlying data provider of the vector layer (originIndex = index in provider's ...
Definition: qgsfields.h:51
int count() const
Returns number of items.
Definition: qgsfields.cpp:133
FieldOrigin fieldOrigin(int fieldIdx) const
Returns the field's origin (value from an enumeration).
Definition: qgsfields.cpp:189
bool isEmpty() const
Checks whether the container is empty.
Definition: qgsfields.cpp:128
int size() const
Returns number of items.
Definition: qgsfields.cpp:138
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Definition: qgsfields.cpp:163
int fieldOriginIndex(int fieldIdx) const
Returns the field's origin index (its meaning is specific to each type of origin).
Definition: qgsfields.cpp:197
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:349
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:164
QVector< QgsGeometry > coerceToType(QgsWkbTypes::Type type, double defaultZ=0, double defaultM=0) const
Attempts to coerce this geometry into the specified destination type.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
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:104
QgsRelationManager * relationManager
Definition: qgsproject.h:114
QList< QgsRelation > referencedRelations(const QgsVectorLayer *layer=nullptr) const
Gets all relations where this layer is the referenced part (i.e.
Defines a relation between matching fields of the two involved tables of a relation.
Definition: qgsrelation.h:67
virtual QgsStyle::StyleEntity type() const =0
Returns the type of style entity.
An interface for classes which can visit style entity (e.g.
@ SymbolRule
Rule based symbology or label child rule.
A label settings entity for QgsStyle databases.
Definition: qgsstyle.h:1435
A symbol entity for QgsStyle databases.
Definition: qgsstyle.h:1342
@ LabelSettingsEntity
Label settings.
Definition: qgsstyle.h:185
@ SymbolEntity
Symbols.
Definition: qgsstyle.h:180
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
virtual QList< QgsSymbolLayerReference > masks() const
Returns masks defined by this symbol layer.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:93
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
Definition: qgssymbol.cpp:756
qreal opacity() const
Returns the opacity for the symbol.
Definition: qgssymbol.h:495
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Definition: qgssymbol.h:215
Container for settings relating to a selective masking around a text.
QList< QgsSymbolLayerReference > maskedSymbolLayers() const
Returns a list of references to symbol layers that are masked by this buffer.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the mask.
double opacity() const
Returns the mask's opacity.
bool enabled() const
Returns whether the mask is enabled.
static bool runOnMainThread(const Func &func, QgsFeedback *feedback=nullptr)
Guarantees that func is executed on the main thread.
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
@ ChangeAttributeValues
Allows modification of attribute values.
@ AddFeatures
Allows adding features.
virtual QgsAttributeList pkAttributeIndexes() const
Returns list of indexes of fields that make up the primary key.
virtual QString defaultValueClause(int fieldIndex) const
Returns any default value clauses which are present at the provider for a specified field index.
virtual QVariant defaultValue(int fieldIndex) const
Returns any literal default values which are present at the provider for a specified field index.
virtual Q_INVOKABLE QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
virtual bool skipConstraintCheck(int fieldIndex, QgsFieldConstraints::Constraint constraint, const QVariant &value=QVariant()) const
Returns true if a constraint check should be skipped for a specified field (e.g., if the value return...
Partial snapshot of vector layer's state (only the members necessary for access to features)
const QgsVectorLayerJoinInfo * joinForFieldIndex(int index, const QgsFields &fields, int &sourceFieldIndex) const
Finds the vector join for a layer field index.
bool containsJoins() const
Quick way to test if there is any join at all.
QgsFeature joinedFeatureOf(const QgsVectorLayerJoinInfo *info, const QgsFeature &feature) const
Returns the joined feature corresponding to the feature.
const QgsVectorJoinList & vectorJoins() const
Defines left outer join from our vector layer to some other vector layer.
bool hasUpsertOnEdit() const
Returns whether a feature created on the target layer has to impact the joined layer by creating a ne...
bool isEditable() const
Returns whether joined fields may be edited through the form of the target layer.
QgsVectorLayer * joinLayer() const
Returns joined layer (may be nullptr if the reference was set by layer ID and not resolved yet)
Contains mainly the QMap with QgsVectorLayer and QgsFeatureIds do list all the duplicated features.
QgsFeatureIds duplicatedFeatures(QgsVectorLayer *layer) const
Returns the duplicated features in the given layer.
QList< QgsVectorLayer * > layers() const
Returns all the layers on which features have been duplicated.
Encapsulate geometry and attributes for new features, to be passed to createFeatures.
QgsGeometry geometry() const
Returns geometry.
QgsAttributeMap attributes() const
Returns attributes.
QgsFeatureData(const QgsGeometry &geometry=QgsGeometry(), const QgsAttributeMap &attributes=QgsAttributeMap())
Constructs a new QgsFeatureData with given geometry and attributes.
static QgsFeature duplicateFeature(QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, QgsDuplicateFeatureContext &duplicateFeatureContext, const int maxDepth=0, int depth=0, QList< QgsVectorLayer * > referencedLayersBranch=QList< QgsVectorLayer * >())
Duplicates a feature and it's children (one level deep).
QList< QgsVectorLayerUtils::QgsFeatureData > QgsFeaturesDataList
Alias for list of QgsFeatureData.
static bool valueExists(const QgsVectorLayer *layer, int fieldIndex, const QVariant &value, const QgsFeatureIds &ignoreIds=QgsFeatureIds())
Returns true if the specified value already exists within a field.
static QgsFeatureList makeFeatureCompatible(const QgsFeature &feature, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags())
Converts input feature to be compatible with the given layer.
static QgsMaskedLayers symbolLayerMasks(const QgsVectorLayer *)
Returns all masks that may be defined on symbol layers for a given vector layer.
static QString guessFriendlyIdentifierField(const QgsFields &fields, bool *foundFriendly=nullptr)
Given a set of fields, attempts to pick the "most useful" field for user-friendly identification of f...
static QgsFeatureIterator getValuesIterator(const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly)
Create a feature iterator for a specified field name or expression.
static bool fieldEditabilityDependsOnFeature(const QgsVectorLayer *layer, int fieldIndex)
Returns true if the editability of the field at index fieldIndex from layer may vary feature by featu...
static QgsFeatureList makeFeaturesCompatible(const QgsFeatureList &features, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags())
Converts input features to be compatible with the given layer.
static std::unique_ptr< QgsVectorLayerFeatureSource > getFeatureSource(QPointer< QgsVectorLayer > layer, QgsFeedback *feedback=nullptr)
Gets the feature source from a QgsVectorLayer pointer.
static QString getFeatureDisplayString(const QgsVectorLayer *layer, const QgsFeature &feature)
static QgsFeature createFeature(const QgsVectorLayer *layer, const QgsGeometry &geometry=QgsGeometry(), const QgsAttributeMap &attributes=QgsAttributeMap(), QgsExpressionContext *context=nullptr)
Creates a new feature ready for insertion into a layer.
static bool fieldIsEditable(const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature)
Tests whether a field is editable for a particular feature.
static 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.
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.
Q_INVOKABLE QgsWkbTypes::Type wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
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.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
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.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
QString subsetString
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.
QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
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
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:968
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:141
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:42
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:922
#define FID_IS_NULL(fid)
Definition: qgsfeatureid.h:30
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
#define FID_IS_NEW(fid)
Definition: qgsfeatureid.h:31
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
QList< int > QgsAttributeList
Definition: qgsfield.h:26
const QgsField & field
Definition: qgsfield.h:463
QList< QgsVectorLayerJoinInfo > QgsVectorJoinList
bool _fieldIsEditable(const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature)
QHash< QString, QgsMaskedLayer > QgsMaskedLayers
QSet< QgsSymbolLayerId > 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.