QGIS API Documentation 3.43.0-Master (6c62b930b02)
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
165 // If it's an unset value assume value doesn't exist
167 {
168 return false;
169 }
170
171 // If it's a joined field search the value in the source layer
172 if ( fields.fieldOrigin( fieldIndex ) == Qgis::FieldOrigin::Join )
173 {
174 int srcFieldIndex = -1;
175 const QgsVectorLayerJoinInfo *joinInfo { layer->joinBuffer()->joinForFieldIndex( fieldIndex, fields, srcFieldIndex ) };
176 if ( ! joinInfo )
177 {
178 return false;
179 }
180 fieldIndex = srcFieldIndex;
181 layer = joinInfo->joinLayer();
182 if ( ! layer )
183 {
184 return false;
185 }
186 fields = layer->fields();
187 }
188
189 QString fieldName = fields.at( fieldIndex ).name();
190
191 // build up an optimised feature request
192 QgsFeatureRequest request;
193 request.setNoAttributes();
195
196 // at most we need to check ignoreIds.size() + 1 - the feature not in ignoreIds is the one we're interested in
197 int limit = ignoreIds.size() + 1;
198 request.setLimit( limit );
199
200 request.setFilterExpression( QStringLiteral( "%1=%2" ).arg( QgsExpression::quotedColumnRef( fieldName ),
201 QgsExpression::quotedValue( value ) ) );
202
203 QgsFeature feat;
204 QgsFeatureIterator it = layer->getFeatures( request );
205 while ( it.nextFeature( feat ) )
206 {
207 if ( ignoreIds.contains( feat.id() ) )
208 continue;
209
210 return true;
211 }
212
213 return false;
214}
215
216QVariant QgsVectorLayerUtils::createUniqueValue( const QgsVectorLayer *layer, int fieldIndex, const QVariant &seed )
217{
218 if ( !layer )
219 return QVariant();
220
221 QgsFields fields = layer->fields();
222
223 if ( fieldIndex < 0 || fieldIndex >= fields.count() )
224 return QVariant();
225
226 QgsField field = fields.at( fieldIndex );
227
228 if ( field.isNumeric() )
229 {
230 QVariant maxVal = layer->maximumValue( fieldIndex );
231 QVariant newVar( maxVal.toLongLong() + 1 );
232 if ( field.convertCompatible( newVar ) )
233 return newVar;
234 else
235 return QVariant();
236 }
237 else
238 {
239 switch ( field.type() )
240 {
241 case QMetaType::Type::QString:
242 {
243 QString base;
244 if ( seed.isValid() )
245 base = seed.toString();
246
247 if ( !base.isEmpty() )
248 {
249 // strip any existing _1, _2 from the seed
250 const thread_local QRegularExpression rx( QStringLiteral( "(.*)_\\d+" ) );
251 QRegularExpressionMatch match = rx.match( base );
252 if ( match.hasMatch() )
253 {
254 base = match.captured( 1 );
255 }
256 }
257 else
258 {
259 // no base seed - fetch first value from layer
261 req.setLimit( 1 );
262 req.setSubsetOfAttributes( QgsAttributeList() << fieldIndex );
264 QgsFeature f;
265 layer->getFeatures( req ).nextFeature( f );
266 base = f.attribute( fieldIndex ).toString();
267 }
268
269 // try variants like base_1, base_2, etc until a new value found
270 QStringList vals = layer->uniqueStringsMatching( fieldIndex, base );
271
272 // might already be unique
273 if ( !base.isEmpty() && !vals.contains( base ) )
274 return base;
275
276 for ( int i = 1; i < 10000; ++i )
277 {
278 QString testVal = base + '_' + QString::number( i );
279 if ( !vals.contains( testVal ) )
280 return testVal;
281 }
282
283 // failed
284 return QVariant();
285 }
286
287 default:
288 // todo other types - dates? times?
289 break;
290 }
291 }
292
293 return QVariant();
294}
295
296QVariant QgsVectorLayerUtils::createUniqueValueFromCache( const QgsVectorLayer *layer, int fieldIndex, const QSet<QVariant> &existingValues, const QVariant &seed )
297{
298 if ( !layer )
299 return QVariant();
300
301 QgsFields fields = layer->fields();
302
303 if ( fieldIndex < 0 || fieldIndex >= fields.count() )
304 return QVariant();
305
306 QgsField field = fields.at( fieldIndex );
307
308 if ( field.isNumeric() )
309 {
310 QVariant maxVal = existingValues.isEmpty() ? 0 : *std::max_element( existingValues.begin(), existingValues.end(), []( const QVariant & a, const QVariant & b ) { return a.toLongLong() < b.toLongLong(); } );
311 QVariant newVar( maxVal.toLongLong() + 1 );
312 if ( field.convertCompatible( newVar ) )
313 return newVar;
314 else
315 return QVariant();
316 }
317 else
318 {
319 switch ( field.type() )
320 {
321 case QMetaType::Type::QString:
322 {
323 QString base;
324 if ( seed.isValid() )
325 base = seed.toString();
326
327 if ( !base.isEmpty() )
328 {
329 // strip any existing _1, _2 from the seed
330 const thread_local QRegularExpression rx( QStringLiteral( "(.*)_\\d+" ) );
331 QRegularExpressionMatch match = rx.match( base );
332 if ( match.hasMatch() )
333 {
334 base = match.captured( 1 );
335 }
336 }
337 else
338 {
339 // no base seed - fetch first value from layer
341 base = existingValues.isEmpty() ? QString() : existingValues.constBegin()->toString();
342 }
343
344 // try variants like base_1, base_2, etc until a new value found
345 QStringList vals;
346 for ( const auto &v : std::as_const( existingValues ) )
347 {
348 if ( v.toString().startsWith( base ) )
349 vals.push_back( v.toString() );
350 }
351
352 // might already be unique
353 if ( !base.isEmpty() && !vals.contains( base ) )
354 return base;
355
356 for ( int i = 1; i < 10000; ++i )
357 {
358 QString testVal = base + '_' + QString::number( i );
359 if ( !vals.contains( testVal ) )
360 return testVal;
361 }
362
363 // failed
364 return QVariant();
365 }
366
367 default:
368 // todo other types - dates? times?
369 break;
370 }
371 }
372
373 return QVariant();
374
375}
376
377bool QgsVectorLayerUtils::attributeHasConstraints( const QgsVectorLayer *layer, int attributeIndex )
378{
379 if ( !layer )
380 return false;
381
382 if ( attributeIndex < 0 || attributeIndex >= layer->fields().count() )
383 return false;
384
385 const QgsFieldConstraints constraints = layer->fields().at( attributeIndex ).constraints();
386 return ( constraints.constraints() & QgsFieldConstraints::ConstraintNotNull ||
389}
390
391bool QgsVectorLayerUtils::validateAttribute( const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors,
393{
394 if ( !layer )
395 return false;
396
397 if ( attributeIndex < 0 || attributeIndex >= layer->fields().count() )
398 return false;
399
400 QgsFields fields = layer->fields();
401 QgsField field = fields.at( attributeIndex );
402 const QVariant value = feature.attribute( attributeIndex );
403 bool valid = true;
404 errors.clear();
405
406 QgsFieldConstraints constraints = field.constraints();
407
408 if ( constraints.constraints() & QgsFieldConstraints::ConstraintExpression && !constraints.constraintExpression().isEmpty()
411 {
413 context.setFeature( feature );
414
415 QgsExpression expr( constraints.constraintExpression() );
416
417 valid = expr.evaluate( &context ).toBool();
418
419 if ( expr.hasParserError() )
420 {
421 errors << QObject::tr( "parser error: %1" ).arg( expr.parserErrorString() );
422 }
423 else if ( expr.hasEvalError() )
424 {
425 errors << QObject::tr( "evaluation error: %1" ).arg( expr.evalErrorString() );
426 }
427 else if ( !valid )
428 {
429 errors << QObject::tr( "%1 check failed" ).arg( constraints.constraintDescription() );
430 }
431 }
432
433 bool notNullConstraintViolated { false };
434
438 {
439 bool exempt = false;
440 if ( fields.fieldOrigin( attributeIndex ) == Qgis::FieldOrigin::Provider
442 {
443 int providerIdx = fields.fieldOriginIndex( attributeIndex );
444 exempt = layer->dataProvider()->skipConstraintCheck( providerIdx, QgsFieldConstraints::ConstraintNotNull, value );
445 }
446
447 if ( !exempt )
448 {
449
450 const bool isNullOrUnset { QgsVariantUtils::isNull( value ) || QgsVariantUtils::isUnsetAttributeValue( value ) };
451 valid = valid && !isNullOrUnset;
452
453 if ( isNullOrUnset )
454 {
455 errors << QObject::tr( "value is NULL" );
456 notNullConstraintViolated = true;
457 }
458 }
459 }
460
461 // if a NOT NULL constraint is violated we don't need to check for UNIQUE
462 if ( ! notNullConstraintViolated )
463 {
464
468 {
469 bool exempt = false;
470 if ( fields.fieldOrigin( attributeIndex ) == Qgis::FieldOrigin::Provider
472 {
473 int providerIdx = fields.fieldOriginIndex( attributeIndex );
474 exempt = layer->dataProvider()->skipConstraintCheck( providerIdx, QgsFieldConstraints::ConstraintUnique, value );
475 }
476
477 if ( !exempt )
478 {
479
480 bool alreadyExists = QgsVectorLayerUtils::valueExists( layer, attributeIndex, value, QgsFeatureIds() << feature.id() );
481 valid = valid && !alreadyExists;
482
483 if ( alreadyExists )
484 {
485 errors << QObject::tr( "value is not unique" );
486 }
487 }
488 }
489 }
490
491 return valid;
492}
493
495 const QgsAttributeMap &attributes, QgsExpressionContext *context )
496{
497 QgsFeatureList features { createFeatures( layer, QgsFeaturesDataList() << QgsFeatureData( geometry, attributes ), context ) };
498 return features.isEmpty() ? QgsFeature() : features.first();
499}
500
502{
503 if ( !layer )
504 return QgsFeatureList();
505
506 QgsFeatureList result;
507 result.reserve( featuresData.length() );
508
509 QgsExpressionContext *evalContext = context;
510 std::unique_ptr< QgsExpressionContext > tempContext;
511 if ( !evalContext )
512 {
513 // no context passed, so we create a default one
515 evalContext = tempContext.get();
516 }
517
518 QgsFields fields = layer->fields();
519
520 // Cache unique values
521 QMap<int, QSet<QVariant>> uniqueValueCache;
522
523 auto checkUniqueValue = [ & ]( const int fieldIdx, const QVariant & value )
524 {
525 if ( ! uniqueValueCache.contains( fieldIdx ) )
526 {
527 // If the layer is filtered, get unique values from an unfiltered clone
528 if ( ! layer->subsetString().isEmpty() )
529 {
530 std::unique_ptr<QgsVectorLayer> unfilteredClone { layer->clone( ) };
531 unfilteredClone->setSubsetString( QString( ) );
532 uniqueValueCache[ fieldIdx ] = unfilteredClone->uniqueValues( fieldIdx );
533 }
534 else
535 {
536 uniqueValueCache[ fieldIdx ] = layer->uniqueValues( fieldIdx );
537 }
538 }
539 return uniqueValueCache[ fieldIdx ].contains( value );
540 };
541
542 for ( const auto &fd : std::as_const( featuresData ) )
543 {
544
545 QgsFeature newFeature( fields );
546 newFeature.setValid( true );
547 newFeature.setGeometry( fd.geometry() );
548
549 // initialize attributes
550 newFeature.initAttributes( fields.count() );
551 for ( int idx = 0; idx < fields.count(); ++idx )
552 {
553 QVariant v;
554 bool checkUnique = true;
555 const bool hasUniqueConstraint { static_cast<bool>( fields.at( idx ).constraints().constraints() & QgsFieldConstraints::ConstraintUnique ) };
556
557 // in order of priority:
558 // 1. passed attribute value and if field does not have a unique constraint like primary key
559 if ( fd.attributes().contains( idx ) )
560 {
561 v = fd.attributes().value( idx );
562 }
563
564 // 2. client side default expression
565 // note - deliberately not using else if!
566 QgsDefaultValue defaultValueDefinition = layer->defaultValueDefinition( idx );
567 if ( ( QgsVariantUtils::isNull( v ) || ( hasUniqueConstraint
568 && checkUniqueValue( idx, v ) )
569 || defaultValueDefinition.applyOnUpdate() )
570 && defaultValueDefinition.isValid() )
571 {
572 // client side default expression set - takes precedence over all. Why? Well, this is the only default
573 // which QGIS users have control over, so we assume that they're deliberately overriding any
574 // provider defaults for some good reason and we should respect that
575 v = layer->defaultValue( idx, newFeature, evalContext );
576 }
577
578 // 3. provider side default value clause
579 // note - not an else if deliberately. Users may return null from a default value expression to fallback to provider defaults
580 if ( ( QgsVariantUtils::isNull( v ) || ( hasUniqueConstraint
581 && checkUniqueValue( idx, v ) ) )
582 && fields.fieldOrigin( idx ) == Qgis::FieldOrigin::Provider )
583 {
584 int providerIndex = fields.fieldOriginIndex( idx );
585 QString providerDefault = layer->dataProvider()->defaultValueClause( providerIndex );
586 if ( !providerDefault.isEmpty() )
587 {
588 v = QgsUnsetAttributeValue( providerDefault );
589 checkUnique = false;
590 }
591 }
592
593 // 4. provider side default literal
594 // note - deliberately not using else if!
595 if ( ( QgsVariantUtils::isNull( v ) || ( checkUnique
596 && hasUniqueConstraint
597 && checkUniqueValue( idx, v ) ) )
598 && fields.fieldOrigin( idx ) == Qgis::FieldOrigin::Provider )
599 {
600 int providerIndex = fields.fieldOriginIndex( idx );
601 v = layer->dataProvider()->defaultValue( providerIndex );
602 if ( v.isValid() )
603 {
604 //trust that the provider default has been sensibly set not to violate any constraints
605 checkUnique = false;
606 }
607 }
608
609 // 5. passed attribute value
610 // note - deliberately not using else if!
611 if ( QgsVariantUtils::isNull( v ) && fd.attributes().contains( idx ) )
612 {
613 v = fd.attributes().value( idx );
614 }
615
616 // last of all... check that unique constraints are respected if the value is valid
617 if ( v.isValid() )
618 {
619 // we can't handle not null or expression constraints here, since there's no way to pick a sensible
620 // value if the constraint is violated
621 if ( checkUnique && hasUniqueConstraint )
622 {
623 if ( checkUniqueValue( idx, v ) )
624 {
625 // unique constraint violated
626 QVariant uniqueValue = QgsVectorLayerUtils::createUniqueValueFromCache( layer, idx, uniqueValueCache[ idx ], v );
627 if ( uniqueValue.isValid() )
628 v = uniqueValue;
629 }
630 }
631 if ( hasUniqueConstraint )
632 {
633 uniqueValueCache[ idx ].insert( v );
634 }
635 }
636 newFeature.setAttribute( idx, v );
637 }
638 result.append( newFeature );
639 }
640 return result;
641}
642
643QgsFeature QgsVectorLayerUtils::duplicateFeature( QgsVectorLayer *layer, const QgsFeature &feature, QgsProject *project, QgsDuplicateFeatureContext &duplicateFeatureContext, const int maxDepth, int depth, QList<QgsVectorLayer *> referencedLayersBranch )
644{
645 if ( !layer )
646 return QgsFeature();
647
648 if ( !layer->isEditable() )
649 return QgsFeature();
650
651 //get context from layer
653 context.setFeature( feature );
654
655 //respect field duplicate policy
656 QgsAttributeMap attributeMap;
657 const int fieldCount = layer->fields().count();
658 for ( int fieldIdx = 0; fieldIdx < fieldCount; ++fieldIdx )
659 {
660 const QgsField field = layer->fields().at( fieldIdx );
661 switch ( field.duplicatePolicy() )
662 {
664 //do nothing - default values ​​are determined
665 break;
666
668 attributeMap.insert( fieldIdx, feature.attribute( fieldIdx ) );
669 break;
670
672 attributeMap.insert( fieldIdx, QgsUnsetAttributeValue() );
673 break;
674 }
675 }
676
677 QgsFeature newFeature = createFeature( layer, feature.geometry(), attributeMap, &context );
678 layer->addFeature( newFeature );
679
680 const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );
681 referencedLayersBranch << layer;
682
683 const int effectiveMaxDepth = maxDepth > 0 ? maxDepth : 100;
684
685 for ( const QgsRelation &relation : relations )
686 {
687 //check if composition (and not association)
688 if ( relation.strength() == Qgis::RelationshipStrength::Composition && !referencedLayersBranch.contains( relation.referencingLayer() ) && depth < effectiveMaxDepth )
689 {
690 //get features connected over this relation
691 QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( feature );
692 QgsFeatureIds childFeatureIds;
693 QgsFeature childFeature;
694 while ( relatedFeaturesIt.nextFeature( childFeature ) )
695 {
696 //set childlayer editable
697 relation.referencingLayer()->startEditing();
698 //change the fk of the child to the id of the new parent
699 const auto pairs = relation.fieldPairs();
700 for ( const QgsRelation::FieldPair &fieldPair : pairs )
701 {
702 childFeature.setAttribute( fieldPair.first, newFeature.attribute( fieldPair.second ) );
703 }
704 //call the function for the child
705 childFeatureIds.insert( duplicateFeature( relation.referencingLayer(), childFeature, project, duplicateFeatureContext, maxDepth, depth + 1, referencedLayersBranch ).id() );
706 }
707
708 //store for feedback
709 duplicateFeatureContext.setDuplicatedFeatures( relation.referencingLayer(), childFeatureIds );
710 }
711 }
712
713
714 return newFeature;
715}
716
717std::unique_ptr<QgsVectorLayerFeatureSource> QgsVectorLayerUtils::getFeatureSource( QPointer<QgsVectorLayer> layer, QgsFeedback *feedback )
718{
719 std::unique_ptr<QgsVectorLayerFeatureSource> featureSource;
720
721 auto getFeatureSource = [ layer = std::move( layer ), &featureSource, feedback ]
722 {
723 Q_ASSERT( QThread::currentThread() == qApp->thread() || feedback );
724 QgsVectorLayer *lyr = layer.data();
725
726 if ( lyr )
727 {
728 featureSource.reset( new QgsVectorLayerFeatureSource( lyr ) );
729 }
730 };
731
733
734 return featureSource;
735}
736
738{
739 if ( !feature.fields().isEmpty() )
740 {
741 QgsAttributes attributes;
742 attributes.reserve( fields.size() );
743 // feature has a field mapping, so we can match attributes to field names
744 for ( const QgsField &field : fields )
745 {
746 int index = feature.fields().lookupField( field.name() );
747 attributes.append( index >= 0 ? feature.attribute( index ) : QgsVariantUtils::createNullVariant( field.type() ) );
748 }
749 feature.setAttributes( attributes );
750 }
751 else
752 {
753 // no field name mapping in feature, just use order
754 const int lengthDiff = feature.attributeCount() - fields.count();
755 if ( lengthDiff > 0 )
756 {
757 // truncate extra attributes
758 QgsAttributes attributes = feature.attributes().mid( 0, fields.count() );
759 feature.setAttributes( attributes );
760 }
761 else if ( lengthDiff < 0 )
762 {
763 // add missing null attributes
764 QgsAttributes attributes = feature.attributes();
765 attributes.reserve( fields.count() );
766 const int attributeCount = feature.attributeCount();
767 for ( int i = attributeCount; i < fields.count(); ++i )
768 {
769 attributes.append( QgsVariantUtils::createNullVariant( fields.at( i ).type() ) );
770 }
771 feature.setAttributes( attributes );
772 }
773 }
774 feature.setFields( fields );
775}
776
778{
779 Qgis::WkbType inputWkbType( layer->wkbType( ) );
780 QgsFeatureList resultFeatures;
781 QgsFeature newF( feature );
782 // Fix attributes
784
785 if ( sinkFlags & QgsFeatureSink::RegeneratePrimaryKey )
786 {
787 // drop incoming primary key values, let them be regenerated
788 const QgsAttributeList pkIndexes = layer->dataProvider()->pkAttributeIndexes();
789 for ( int index : pkIndexes )
790 {
791 if ( index >= 0 )
792 newF.setAttribute( index, QVariant() );
793 }
794 }
795
796 // Does geometry need transformations?
798 bool newFHasGeom = newFGeomType !=
800 newFGeomType != Qgis::GeometryType::Null;
801 bool layerHasGeom = inputWkbType !=
803 inputWkbType != Qgis::WkbType::Unknown;
804 // Drop geometry if layer is geometry-less
805 if ( ( newFHasGeom && !layerHasGeom ) || !newFHasGeom )
806 {
807 QgsFeature _f = QgsFeature( layer->fields() );
808 _f.setAttributes( newF.attributes() );
809 resultFeatures.append( _f );
810 }
811 else
812 {
813 // Geometry need fixing?
814 const QVector< QgsGeometry > geometries = newF.geometry().coerceToType( inputWkbType );
815
816 if ( geometries.count() != 1 )
817 {
818 QgsAttributeMap attrMap;
819 for ( int j = 0; j < newF.fields().count(); j++ )
820 {
821 attrMap[j] = newF.attribute( j );
822 }
823 resultFeatures.reserve( geometries.size() );
824 for ( const QgsGeometry &geometry : geometries )
825 {
826 QgsFeature _f( createFeature( layer, geometry, attrMap ) );
827 resultFeatures.append( _f );
828 }
829 }
830 else
831 {
832 newF.setGeometry( geometries.at( 0 ) );
833 resultFeatures.append( newF );
834 }
835 }
836 return resultFeatures;
837}
838
840{
841 QgsFeatureList resultFeatures;
842 for ( const QgsFeature &f : features )
843 {
844 const QgsFeatureList features( makeFeatureCompatible( f, layer, sinkFlags ) );
845 for ( const auto &_f : features )
846 {
847 resultFeatures.append( _f );
848 }
849 }
850 return resultFeatures;
851}
852
854{
855 QList<QgsVectorLayer *> layers;
856 QMap<QgsVectorLayer *, QgsFeatureIds>::const_iterator i;
857 for ( i = mDuplicatedFeatures.begin(); i != mDuplicatedFeatures.end(); ++i )
858 layers.append( i.key() );
859 return layers;
860}
861
863{
864 return mDuplicatedFeatures[layer];
865}
866
867void QgsVectorLayerUtils::QgsDuplicateFeatureContext::setDuplicatedFeatures( QgsVectorLayer *layer, const QgsFeatureIds &ids )
868{
869 if ( mDuplicatedFeatures.contains( layer ) )
870 mDuplicatedFeatures[layer] += ids;
871 else
872 mDuplicatedFeatures.insert( layer, ids );
873}
874/*
875QMap<QgsVectorLayer *, QgsFeatureIds> QgsVectorLayerUtils::QgsDuplicateFeatureContext::duplicateFeatureContext() const
876{
877 return mDuplicatedFeatures;
878}
879*/
880
882 mGeometry( geometry ),
883 mAttributes( attributes )
884{}
885
887{
888 return mGeometry;
889}
890
892{
893 return mAttributes;
894}
895
896bool _fieldIsEditable( const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature )
897{
898 return layer->isEditable() &&
899 !layer->editFormConfig().readOnly( fieldIndex ) &&
900 // Provider permissions
901 layer->dataProvider() &&
903 ( layer->dataProvider()->capabilities() & Qgis::VectorProviderCapability::AddFeatures && ( FID_IS_NULL( feature.id() ) || FID_IS_NEW( feature.id() ) ) ) ) &&
904 // Field must not be read only
905 !layer->fields().at( fieldIndex ).isReadOnly();
906}
907
908bool QgsVectorLayerUtils::fieldIsReadOnly( const QgsVectorLayer *layer, int fieldIndex )
909{
910 if ( layer->fields().fieldOrigin( fieldIndex ) == Qgis::FieldOrigin::Join )
911 {
912 int srcFieldIndex;
913 const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
914
915 if ( !info || !info->isEditable() || !info->joinLayer() )
916 return true;
917
918 return fieldIsReadOnly( info->joinLayer(), srcFieldIndex );
919 }
920 else
921 {
922 // any of these properties makes the field read only
923 if ( !layer->isEditable() ||
924 layer->editFormConfig().readOnly( fieldIndex ) ||
925 !layer->dataProvider() ||
928 layer->fields().at( fieldIndex ).isReadOnly() )
929 return true;
930
931 return false;
932 }
933}
934
936{
937 // editability will vary feature-by-feature only for joined fields
938 if ( layer->fields().fieldOrigin( fieldIndex ) == Qgis::FieldOrigin::Join )
939 {
940 int srcFieldIndex;
941 const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
942
943 if ( !info || !info->isEditable() || info->hasUpsertOnEdit() )
944 return false;
945
946 // join does not have upsert capabilities, so the ability to edit the joined field will
947 // vary feature-by-feature, depending on whether the join target feature already exists
948 return true;
949 }
950 else
951 {
952 return false;
953 }
954}
955
956bool QgsVectorLayerUtils::fieldIsEditable( const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature )
957{
958 if ( layer->fields().fieldOrigin( fieldIndex ) == Qgis::FieldOrigin::Join )
959 {
960 int srcFieldIndex;
961 const QgsVectorLayerJoinInfo *info = layer->joinBuffer()->joinForFieldIndex( fieldIndex, layer->fields(), srcFieldIndex );
962
963 if ( !info || !info->isEditable() )
964 return false;
965
966 // check that joined feature exist, else it is not editable
967 if ( !info->hasUpsertOnEdit() )
968 {
969 const QgsFeature joinedFeature = layer->joinBuffer()->joinedFeatureOf( info, feature );
970 if ( !joinedFeature.isValid() )
971 return false;
972 }
973
974 return _fieldIsEditable( info->joinLayer(), srcFieldIndex, feature );
975 }
976 else
977 return _fieldIsEditable( layer, fieldIndex, feature );
978}
979
980
981QHash<QString, QgsMaskedLayers> QgsVectorLayerUtils::labelMasks( const QgsVectorLayer *layer )
982{
983 class LabelMasksVisitor : public QgsStyleEntityVisitorInterface
984 {
985 public:
986 bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
987 {
989 {
990 currentRule = node.identifier;
991 return true;
992 }
993 return false;
994 }
995 bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
996 {
997 if ( leaf.entity && leaf.entity->type() == QgsStyle::LabelSettingsEntity )
998 {
999 auto labelSettingsEntity = static_cast<const QgsStyleLabelSettingsEntity *>( leaf.entity );
1000 const QgsTextMaskSettings &maskSettings = labelSettingsEntity->settings().format().mask();
1001 if ( maskSettings.enabled() )
1002 {
1003 // transparency is considered has effects because it implies rasterization when masking
1004 // is involved
1005 const bool hasEffects = maskSettings.opacity() < 1 ||
1006 ( maskSettings.paintEffect() && maskSettings.paintEffect()->enabled() );
1007 for ( const auto &r : maskSettings.maskedSymbolLayers() )
1008 {
1009 QgsMaskedLayer &maskedLayer = maskedLayers[currentRule][r.layerId()];
1010 maskedLayer.symbolLayerIds.insert( r.symbolLayerIdV2() );
1011 maskedLayer.hasEffects = hasEffects;
1012 }
1013 }
1014 }
1015 return true;
1016 }
1017
1018 QHash<QString, QgsMaskedLayers> maskedLayers;
1019 // Current label rule, empty string for a simple labeling
1020 QString currentRule;
1021 };
1022
1023 if ( ! layer->labeling() )
1024 return {};
1025
1026 LabelMasksVisitor visitor;
1027 layer->labeling()->accept( &visitor );
1028 return std::move( visitor.maskedLayers );
1029}
1030
1032{
1033 if ( ! layer->renderer() )
1034 return {};
1035
1036 class SymbolLayerVisitor : public QgsStyleEntityVisitorInterface
1037 {
1038 public:
1039 bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
1040 {
1042 }
1043
1044 // Returns true if the visited symbol has effects
1045 bool visitSymbol( const QgsSymbol *symbol )
1046 {
1047 // transparency is considered has effects because it implies rasterization when masking
1048 // is involved
1049 bool symbolHasEffect = symbol->opacity() < 1;
1050 for ( int idx = 0; idx < symbol->symbolLayerCount(); idx++ )
1051 {
1052 const QgsSymbolLayer *sl = symbol->symbolLayer( idx );
1053 bool slHasEffects = sl->paintEffect() && sl->paintEffect()->enabled();
1054 symbolHasEffect |= slHasEffects;
1055
1056 // recurse over sub symbols
1057 const QgsSymbol *subSymbol = const_cast<QgsSymbolLayer *>( sl )->subSymbol();
1058 if ( subSymbol )
1059 slHasEffects |= visitSymbol( subSymbol );
1060
1061 for ( const auto &mask : sl->masks() )
1062 {
1063 QgsMaskedLayer &maskedLayer = maskedLayers[mask.layerId()];
1064 maskedLayer.hasEffects |= slHasEffects;
1065 maskedLayer.symbolLayerIds.insert( mask.symbolLayerIdV2() );
1066 }
1067 }
1068
1069 return symbolHasEffect;
1070 }
1071
1072 bool visit( const QgsStyleEntityVisitorInterface::StyleLeaf &leaf ) override
1073 {
1074 if ( leaf.entity && leaf.entity->type() == QgsStyle::SymbolEntity )
1075 {
1076 auto symbolEntity = static_cast<const QgsStyleSymbolEntity *>( leaf.entity );
1077 if ( symbolEntity->symbol() )
1078 visitSymbol( symbolEntity->symbol() );
1079 }
1080 return true;
1081 }
1082 QgsMaskedLayers maskedLayers;
1083 };
1084
1085 SymbolLayerVisitor visitor;
1086 layer->renderer()->accept( &visitor );
1087 return visitor.maskedLayers;
1088}
1089
1091{
1093
1094 QgsExpression exp( layer->displayExpression() );
1095 context.setFeature( feature );
1096 exp.prepare( &context );
1097 QString displayString = exp.evaluate( &context ).toString();
1098
1099 return displayString;
1100}
1101
1103{
1104 if ( !layer )
1105 return false;
1106
1107 const QList<QgsRelation> relations = project->relationManager()->referencedRelations( layer );
1108 for ( const QgsRelation &relation : relations )
1109 {
1110 switch ( relation.strength() )
1111 {
1113 {
1114 QgsFeatureIds childFeatureIds;
1115
1116 const auto constFids = fids;
1117 for ( const QgsFeatureId fid : constFids )
1118 {
1119 //get features connected over this relation
1120 QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( layer->getFeature( fid ) );
1121 QgsFeature childFeature;
1122 while ( relatedFeaturesIt.nextFeature( childFeature ) )
1123 {
1124 childFeatureIds.insert( childFeature.id() );
1125 }
1126 }
1127
1128 if ( childFeatureIds.count() > 0 )
1129 {
1130 if ( context.layers().contains( relation.referencingLayer() ) )
1131 {
1132 QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( relation.referencingLayer() );
1133 // add feature ids
1134 handledFeatureIds.unite( childFeatureIds );
1135 context.setDuplicatedFeatures( relation.referencingLayer(), handledFeatureIds );
1136 }
1137 else
1138 {
1139 // add layer and feature id
1140 context.setDuplicatedFeatures( relation.referencingLayer(), childFeatureIds );
1141 }
1142 }
1143 break;
1144 }
1145
1147 break;
1148 }
1149 }
1150
1151 if ( layer->joinBuffer()->containsJoins() )
1152 {
1153 const QgsVectorJoinList joins = layer->joinBuffer()->vectorJoins();
1154 for ( const QgsVectorLayerJoinInfo &info : joins )
1155 {
1156 if ( qobject_cast< QgsAuxiliaryLayer * >( info.joinLayer() ) && flags & IgnoreAuxiliaryLayers )
1157 continue;
1158
1159 if ( info.isEditable() && info.hasCascadedDelete() )
1160 {
1161 QgsFeatureIds joinFeatureIds;
1162 const auto constFids = fids;
1163 for ( const QgsFeatureId &fid : constFids )
1164 {
1165 const QgsFeature joinFeature = layer->joinBuffer()->joinedFeatureOf( &info, layer->getFeature( fid ) );
1166 if ( joinFeature.isValid() )
1167 joinFeatureIds.insert( joinFeature.id() );
1168 }
1169
1170 if ( joinFeatureIds.count() > 0 )
1171 {
1172 if ( context.layers().contains( info.joinLayer() ) )
1173 {
1174 QgsFeatureIds handledFeatureIds = context.duplicatedFeatures( info.joinLayer() );
1175 // add feature ids
1176 handledFeatureIds.unite( joinFeatureIds );
1177 context.setDuplicatedFeatures( info.joinLayer(), handledFeatureIds );
1178 }
1179 else
1180 {
1181 // add layer and feature id
1182 context.setDuplicatedFeatures( info.joinLayer(), joinFeatureIds );
1183 }
1184 }
1185 }
1186 }
1187 }
1188
1189 return !context.layers().isEmpty();
1190}
1191
1192QString QgsVectorLayerUtils::guessFriendlyIdentifierField( const QgsFields &fields, bool *foundFriendly )
1193{
1194 if ( foundFriendly )
1195 *foundFriendly = false;
1196
1197 if ( fields.isEmpty() )
1198 return QString();
1199
1200 // Check the fields and keep the first one that matches.
1201 // We assume that the user has organized the data with the
1202 // more "interesting" field names first. As such, name should
1203 // be selected before oldname, othername, etc.
1204 // This candidates list is a prioritized list of candidates ranked by "interestingness"!
1205 // See discussion at https://github.com/qgis/QGIS/pull/30245 - this list must NOT be translated,
1206 // but adding hardcoded localized variants of the strings is encouraged.
1207 static QStringList sCandidates{ QStringLiteral( "name" ),
1208 QStringLiteral( "title" ),
1209 QStringLiteral( "heibt" ),
1210 QStringLiteral( "desc" ),
1211 QStringLiteral( "nom" ),
1212 QStringLiteral( "street" ),
1213 QStringLiteral( "road" ),
1214 QStringLiteral( "label" ),
1215 // German candidates
1216 QStringLiteral( "titel" ), //#spellok
1217 QStringLiteral( "beschreibung" ),
1218 QStringLiteral( "strasse" ),
1219 QStringLiteral( "beschriftung" ) };
1220
1221 // anti-names
1222 // this list of strings indicates parts of field names which make the name "less interesting".
1223 // For instance, we'd normally like to default to a field called "name" or "title", but if instead we
1224 // find one called "typename" or "typeid", then that's most likely a classification of the feature and not the
1225 // best choice to default to
1226 static QStringList sAntiCandidates{ QStringLiteral( "type" ),
1227 QStringLiteral( "class" ),
1228 QStringLiteral( "cat" ),
1229 // German anti-candidates
1230 QStringLiteral( "typ" ),
1231 QStringLiteral( "klasse" ),
1232 QStringLiteral( "kategorie" )
1233 };
1234
1235 QString bestCandidateName;
1236 QString bestCandidateNameWithAntiCandidate;
1237
1238 for ( const QString &candidate : sCandidates )
1239 {
1240 for ( const QgsField &field : fields )
1241 {
1242 const QString fldName = field.name();
1243 if ( fldName.contains( candidate, Qt::CaseInsensitive ) )
1244 {
1245 bool isAntiCandidate = false;
1246 for ( const QString &antiCandidate : sAntiCandidates )
1247 {
1248 if ( fldName.contains( antiCandidate, Qt::CaseInsensitive ) )
1249 {
1250 isAntiCandidate = true;
1251 break;
1252 }
1253 }
1254
1255 if ( isAntiCandidate )
1256 {
1257 if ( bestCandidateNameWithAntiCandidate.isEmpty() )
1258 {
1259 bestCandidateNameWithAntiCandidate = fldName;
1260 }
1261 }
1262 else
1263 {
1264 bestCandidateName = fldName;
1265 break;
1266 }
1267 }
1268 }
1269
1270 if ( !bestCandidateName.isEmpty() )
1271 break;
1272 }
1273
1274 QString candidateName = bestCandidateName.isEmpty() ? bestCandidateNameWithAntiCandidate : bestCandidateName;
1275 if ( !candidateName.isEmpty() )
1276 {
1277 // Special case for layers got from WFS using the OGR GMLAS field parsing logic.
1278 // Such layers contain a "id" field (the gml:id attribute of the object),
1279 // as well as a gml_name (a <gml:name>) element. However this gml:name is often
1280 // absent, partly because it is a property of the base class in GML schemas, and
1281 // that a lot of readers are not able to deduce its potential presence.
1282 // So try to look at another field whose name would end with _name
1283 // And fallback to using the "id" field that should always be filled.
1284 if ( candidateName == QLatin1String( "gml_name" ) &&
1285 fields.indexOf( QLatin1String( "id" ) ) >= 0 )
1286 {
1287 candidateName.clear();
1288 // Try to find a field ending with "_name", which is not "gml_name"
1289 for ( const QgsField &field : std::as_const( fields ) )
1290 {
1291 const QString fldName = field.name();
1292 if ( fldName != QLatin1String( "gml_name" ) && fldName.endsWith( QLatin1String( "_name" ) ) )
1293 {
1294 candidateName = fldName;
1295 break;
1296 }
1297 }
1298 if ( candidateName.isEmpty() )
1299 {
1300 // Fallback to "id"
1301 candidateName = QStringLiteral( "id" );
1302 }
1303 }
1304
1305 if ( foundFriendly )
1306 *foundFriendly = true;
1307 return candidateName;
1308 }
1309 else
1310 {
1311 // no good matches found by name, so scan through and look for the first string field
1312 for ( const QgsField &field : fields )
1313 {
1314 if ( field.type() == QMetaType::Type::QString )
1315 return field.name();
1316 }
1317
1318 // no string fields found - just return first field
1319 return fields.at( 0 ).name();
1320 }
1321}
@ 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.
Provides a container for managing client side default values for fields.
bool isValid() const
Returns if this default value should be applied.
bool readOnly(int idx) const
This returns true if the field is manually set to read only or if the field does not support editing ...
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
Handles parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
static QString quotedValue(const QVariant &value)
Returns a string representation of a literal value, including appropriate quotations where required.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
QString evalErrorString() const
Returns evaluation error.
QString parserErrorString() const
Returns parser error.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
QVariant evaluate()
Evaluate the feature and return the result.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the renderer...
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setLimit(long long limit)
Set the maximum number of features to request.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QFlags< SinkFlag > SinkFlags
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
Q_INVOKABLE bool setAttribute(int field, const QVariant &attr)
Sets an attribute's value by field index.
QgsAttributes attributes
Definition qgsfeature.h:67
QgsFields fields
Definition qgsfeature.h:68
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
QgsFeatureId id
Definition qgsfeature.h:66
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
void setFields(const QgsFields &fields, bool initAttributes=false)
Assigns a field map with the feature to allow attribute access by attribute name.
int attributeCount() const
Returns the number of attributes attached to the feature.
QgsGeometry geometry
Definition qgsfeature.h:69
void setValid(bool validity)
Sets the validity of the feature.
bool isValid() const
Returns the validity of this feature.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition qgsfeedback.h:44
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:53
Stores information about constraints which may be present on a field.
ConstraintStrength
Strength of constraints.
@ ConstraintStrengthNotSet
Constraint is not set.
ConstraintOrigin
Origin of constraints.
@ ConstraintOriginNotSet
Constraint is not set.
@ ConstraintOriginProvider
Constraint was set at data provider.
ConstraintStrength constraintStrength(Constraint constraint) const
Returns the strength of a field constraint, or ConstraintStrengthNotSet if the constraint is not pres...
ConstraintOrigin constraintOrigin(Constraint constraint) const
Returns the origin of a field constraint, or ConstraintOriginNotSet if the constraint is not present ...
QString constraintExpression() const
Returns the constraint expression for the field, if set.
@ ConstraintNotNull
Field may not be null.
@ ConstraintUnique
Field must have a unique value.
@ ConstraintExpression
Field has an expression constraint set. See constraintExpression().
QString constraintDescription() const
Returns the descriptive name for the constraint expression.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h: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:474
Qgis::FieldDuplicatePolicy duplicatePolicy() const
Returns the field's duplicate policy, which indicates how field values should be handled during a dup...
Definition qgsfield.cpp:771
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, bool avoidDuplicates=true) const
Attempts to coerce this geometry into the specified destination type.
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
bool enabled() const
Returns whether the effect is enabled.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h: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:1490
A symbol entity for QgsStyle databases.
Definition qgsstyle.h:1397
@ LabelSettingsEntity
Label settings.
Definition qgsstyle.h:210
@ SymbolEntity
Symbols.
Definition qgsstyle.h:205
Abstract base class for symbol layers.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
virtual QList< QgsSymbolLayerReference > masks() const
Returns masks defined by this symbol layer.
Abstract base class for all rendered symbols.
Definition qgssymbol.h:231
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
qreal opacity() const
Returns the opacity for the symbol.
Definition qgssymbol.h:644
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
Definition qgssymbol.h:353
Container for settings relating to a selective masking around a text.
QList< QgsSymbolLayerReference > maskedSymbolLayers() const
Returns a list of references to symbol layers that are masked by this buffer.
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the mask.
double opacity() const
Returns the mask's opacity.
bool enabled() const
Returns whether the mask is enabled.
static bool runOnMainThread(const Func &func, QgsFeedback *feedback=nullptr)
Guarantees that func is executed on the main thread.
Represents a default, "not-specified" value for a feature attribute.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static QVariant createNullVariant(QMetaType::Type metaType)
Helper method to properly create a null QVariant from a metaType Returns the created QVariant.
static bool isUnsetAttributeValue(const QVariant &variant)
Check if the variant is a QgsUnsetAttributeValue.
virtual Q_INVOKABLE Qgis::VectorProviderCapabilities capabilities() const
Returns flags containing the supported capabilities.
virtual QgsAttributeList pkAttributeIndexes() const
Returns list of indexes of fields that make up the primary key.
virtual QString defaultValueClause(int fieldIndex) const
Returns any default value clauses which are present at the provider for a specified field index.
virtual QVariant defaultValue(int fieldIndex) const
Returns any literal default values which are present at the provider for a specified field index.
virtual bool skipConstraintCheck(int fieldIndex, QgsFieldConstraints::Constraint constraint, const QVariant &value=QVariant()) const
Returns true if a constraint check should be skipped for a specified field (e.g., if the value return...
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 which list all the duplicated features...
QgsFeatureIds duplicatedFeatures(QgsVectorLayer *layer) const
Returns the duplicated features in the given layer.
QList< QgsVectorLayer * > layers() const
Returns all the layers on which features have been duplicated.
Encapsulate geometry and attributes for new features, to be passed to createFeatures.
QgsGeometry geometry() const
Returns geometry.
QgsAttributeMap attributes() const
Returns attributes.
QgsFeatureData(const QgsGeometry &geometry=QgsGeometry(), const QgsAttributeMap &attributes=QgsAttributeMap())
Constructs a new QgsFeatureData with given geometry and attributes.
static 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)
Returns a descriptive string for a feature, suitable for displaying to the user.
static QgsFeature createFeature(const QgsVectorLayer *layer, const QgsGeometry &geometry=QgsGeometry(), const QgsAttributeMap &attributes=QgsAttributeMap(), QgsExpressionContext *context=nullptr)
Creates a new feature ready for insertion into a layer.
static bool fieldIsEditable(const QgsVectorLayer *layer, int fieldIndex, const QgsFeature &feature)
Tests whether a field is editable for a particular feature.
static bool attributeHasConstraints(const QgsVectorLayer *layer, int attributeIndex)
Returns true if a feature attribute has active constraints.
static QList< double > getDoubleValues(const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly=false, int *nullCount=nullptr, QgsFeedback *feedback=nullptr)
Fetches all double values from a specified field name or expression.
QFlags< CascadedFeatureFlag > CascadedFeatureFlags
static bool fieldIsReadOnly(const QgsVectorLayer *layer, int fieldIndex)
Returns true if the field at index fieldIndex from layer is editable, false if the field is read only...
static QHash< QString, QgsMaskedLayers > labelMasks(const QgsVectorLayer *)
Returns masks defined in labeling options of a layer.
static QgsFeatureList createFeatures(const QgsVectorLayer *layer, const QgsFeaturesDataList &featuresData, QgsExpressionContext *context=nullptr)
Creates a set of new features ready for insertion into a layer.
static QVariant createUniqueValue(const QgsVectorLayer *layer, int fieldIndex, const QVariant &seed=QVariant())
Returns a new attribute value for the specified field index which is guaranteed to be unique.
static bool impactsCascadeFeatures(const QgsVectorLayer *layer, const QgsFeatureIds &fids, const QgsProject *project, QgsDuplicateFeatureContext &context, QgsVectorLayerUtils::CascadedFeatureFlags flags=QgsVectorLayerUtils::CascadedFeatureFlags())
Returns true if at least one feature of the fids on layer is connected as parent in at least one comp...
static QList< QVariant > getValues(const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly=false, QgsFeedback *feedback=nullptr)
Fetches all values from a specified field name or expression.
static QVariant createUniqueValueFromCache(const QgsVectorLayer *layer, int fieldIndex, const QSet< QVariant > &existingValues, const QVariant &seed=QVariant())
Returns a new attribute value for the specified field index which is guaranteed to be unique within r...
static bool validateAttribute(const QgsVectorLayer *layer, const QgsFeature &feature, int attributeIndex, QStringList &errors, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthNotSet, QgsFieldConstraints::ConstraintOrigin origin=QgsFieldConstraints::ConstraintOriginNotSet)
Tests a feature attribute value to check whether it passes all constraints which are present on the c...
static void matchAttributesToFields(QgsFeature &feature, const QgsFields &fields)
Matches the attributes in feature to the specified fields.
@ IgnoreAuxiliaryLayers
Ignore auxiliary layers.
Represents a vector layer which manages a vector based dataset.
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.