QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgsvectorlayer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsvectorlayer.cpp
3 --------------------
4 begin : Oct 29, 2003
5 copyright : (C) 2003 by Gary E.Sherman
6 email : sherman at mrcc.com
7
8 This class implements a generic means to display vector layers. The features
9 and attributes are read from the data store using a "data provider" plugin.
10 QgsVectorLayer can be used with any data store for which an appropriate
11 plugin is available.
12
13***************************************************************************/
14
15/***************************************************************************
16 * *
17 * This program is free software; you can redistribute it and/or modify *
18 * it under the terms of the GNU General Public License as published by *
19 * the Free Software Foundation; either version 2 of the License, or *
20 * (at your option) any later version. *
21 * *
22 ***************************************************************************/
23
24#include "qgis.h" //for globals
25#include "qgssettings.h"
26#include "qgsvectorlayer.h"
27#include "qgsactionmanager.h"
28#include "qgsapplication.h"
29#include "qgsconditionalstyle.h"
31#include "qgscurve.h"
32#include "qgsdatasourceuri.h"
35#include "qgsfeature.h"
36#include "qgsfeaturerequest.h"
37#include "qgsfields.h"
38#include "qgsmaplayerfactory.h"
39#include "qgsgeometry.h"
41#include "qgslogger.h"
42#include "qgsmaplayerlegend.h"
43#include "qgsmessagelog.h"
44#include "qgsogcutils.h"
45#include "qgspainting.h"
46#include "qgspointxy.h"
47#include "qgsproject.h"
48#include "qgsproviderregistry.h"
49#include "qgsrectangle.h"
50#include "qgsrelationmanager.h"
51#include "qgsweakrelation.h"
52#include "qgsrendercontext.h"
64#include "qgspoint.h"
65#include "qgsrenderer.h"
66#include "qgssymbollayer.h"
67#include "qgsdiagramrenderer.h"
68#include "qgspallabeling.h"
72#include "qgsfeedback.h"
73#include "qgsxmlutils.h"
74#include "qgsunittypes.h"
75#include "qgstaskmanager.h"
76#include "qgstransaction.h"
77#include "qgsauxiliarystorage.h"
78#include "qgsgeometryoptions.h"
80#include "qgsruntimeprofiler.h"
82#include "qgsvectorlayerutils.h"
84#include "qgsprofilerequest.h"
85#include "qgssymbollayerutils.h"
86
87#include <QDir>
88#include <QFile>
89#include <QImage>
90#include <QPainter>
91#include <QPainterPath>
92#include <QPolygonF>
93#include <QProgressDialog>
94#include <QString>
95#include <QDomNode>
96#include <QVector>
97#include <QStringBuilder>
98#include <QUrl>
99#include <QUndoCommand>
100#include <QUrlQuery>
101#include <QUuid>
102#include <QRegularExpression>
103#include <QTimer>
104
105#include <limits>
106#include <optional>
107
108#ifdef TESTPROVIDERLIB
109#include <dlfcn.h>
110#endif
111
112typedef bool saveStyle_t(
113 const QString &uri,
114 const QString &qmlStyle,
115 const QString &sldStyle,
116 const QString &styleName,
117 const QString &styleDescription,
118 const QString &uiFileContent,
119 bool useAsDefault,
120 QString &errCause
121);
122
123typedef QString loadStyle_t(
124 const QString &uri,
125 QString &errCause
126);
127
128typedef int listStyles_t(
129 const QString &uri,
130 QStringList &ids,
131 QStringList &names,
132 QStringList &descriptions,
133 QString &errCause
134);
135
136typedef QString getStyleById_t(
137 const QString &uri,
138 QString styleID,
139 QString &errCause
140);
141
142typedef bool deleteStyleById_t(
143 const QString &uri,
144 QString styleID,
145 QString &errCause
146);
147
148
149QgsVectorLayer::QgsVectorLayer( const QString &vectorLayerPath,
150 const QString &baseName,
151 const QString &providerKey,
152 const QgsVectorLayer::LayerOptions &options )
153 : QgsMapLayer( QgsMapLayerType::VectorLayer, baseName, vectorLayerPath )
154 , mTemporalProperties( new QgsVectorLayerTemporalProperties( this ) )
155 , mElevationProperties( new QgsVectorLayerElevationProperties( this ) )
156 , mAuxiliaryLayer( nullptr )
157 , mAuxiliaryLayerKey( QString() )
158 , mReadExtentFromXml( options.readExtentFromXml )
159 , mRefreshRendererTimer( new QTimer( this ) )
160{
162
163 if ( options.fallbackCrs.isValid() )
164 setCrs( options.fallbackCrs, false );
165 mWkbType = options.fallbackWkbType;
166
167 setProviderType( providerKey );
168
169 mGeometryOptions = std::make_unique<QgsGeometryOptions>();
170 mActions = new QgsActionManager( this );
171 mConditionalStyles = new QgsConditionalLayerStyles( this );
172 mStoredExpressionManager = new QgsStoredExpressionManager();
173 mStoredExpressionManager->setParent( this );
174
175 mJoinBuffer = new QgsVectorLayerJoinBuffer( this );
176 mJoinBuffer->setParent( this );
177 connect( mJoinBuffer, &QgsVectorLayerJoinBuffer::joinedFieldsChanged, this, &QgsVectorLayer::onJoinedFieldsChanged );
178
179 mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
180 // if we're given a provider type, try to create and bind one to this layer
181 if ( !vectorLayerPath.isEmpty() && !mProviderKey.isEmpty() )
182 {
183 QgsDataProvider::ProviderOptions providerOptions { options.transformContext };
184 QgsDataProvider::ReadFlags providerFlags = QgsDataProvider::ReadFlags();
185 if ( options.loadDefaultStyle )
186 {
188 }
189 if ( options.forceReadOnly )
190 {
191 providerFlags |= QgsDataProvider::ForceReadOnly;
192 mDataSourceReadOnly = true;
193 }
194 setDataSource( vectorLayerPath, baseName, providerKey, providerOptions, providerFlags );
195 }
196
197 for ( const QgsField &field : std::as_const( mFields ) )
198 {
199 if ( !mAttributeAliasMap.contains( field.name() ) )
200 mAttributeAliasMap.insert( field.name(), QString() );
201 }
202
203 if ( isValid() )
204 {
205 mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( mDataProvider->temporalCapabilities() );
206 if ( !mTemporalProperties->isActive() )
207 {
208 // didn't populate temporal properties from provider metadata, so at least try to setup some initially nice
209 // selections
210 mTemporalProperties->guessDefaultsFromFields( mFields );
211 }
212
213 mElevationProperties->setDefaultsFromLayer( this );
214 }
215
216 connect( this, &QgsVectorLayer::selectionChanged, this, [ = ] { triggerRepaint(); } );
217 connect( QgsProject::instance()->relationManager(), &QgsRelationManager::relationsLoaded, this, &QgsVectorLayer::onRelationsLoaded );
218
222
223 // Default simplify drawing settings
224 QgsSettings settings;
225 mSimplifyMethod.setSimplifyHints( settings.flagValue( QStringLiteral( "qgis/simplifyDrawingHints" ), mSimplifyMethod.simplifyHints(), QgsSettings::NoSection ) );
226 mSimplifyMethod.setSimplifyAlgorithm( settings.enumValue( QStringLiteral( "qgis/simplifyAlgorithm" ), mSimplifyMethod.simplifyAlgorithm() ) );
227 mSimplifyMethod.setThreshold( settings.value( QStringLiteral( "qgis/simplifyDrawingTol" ), mSimplifyMethod.threshold() ).toFloat() );
228 mSimplifyMethod.setForceLocalOptimization( settings.value( QStringLiteral( "qgis/simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ).toBool() );
229 mSimplifyMethod.setMaximumScale( settings.value( QStringLiteral( "qgis/simplifyMaxScale" ), mSimplifyMethod.maximumScale() ).toFloat() );
230
231 connect( mRefreshRendererTimer, &QTimer::timeout, this, [ = ] { triggerRepaint( true ); } );
232}
233
235{
236 emit willBeDeleted();
237
238 setValid( false );
239
240 delete mDataProvider;
241 delete mEditBuffer;
242 delete mJoinBuffer;
243 delete mExpressionFieldBuffer;
244 delete mLabeling;
245 delete mDiagramLayerSettings;
246 delete mDiagramRenderer;
247
248 delete mActions;
249
250 delete mRenderer;
251 delete mConditionalStyles;
252 delete mStoredExpressionManager;
253
254 if ( mFeatureCounter )
255 mFeatureCounter->cancel();
256
257 qDeleteAll( mRendererGenerators );
258}
259
261{
263 // We get the data source string from the provider when
264 // possible because some providers may have changed it
265 // directly (memory provider does that).
266 QString dataSource;
267 if ( mDataProvider )
268 {
269 dataSource = mDataProvider->dataSourceUri();
270 options.transformContext = mDataProvider->transformContext();
271 }
272 else
273 {
274 dataSource = source();
275 }
276 options.forceReadOnly = mDataSourceReadOnly;
277 QgsVectorLayer *layer = new QgsVectorLayer( dataSource, name(), mProviderKey, options );
278 if ( mDataProvider && layer->dataProvider() )
279 {
280 layer->dataProvider()->handlePostCloneOperations( mDataProvider );
281 }
282 QgsMapLayer::clone( layer );
283
284 QList<QgsVectorLayerJoinInfo> joins = vectorJoins();
285 const auto constJoins = joins;
286 for ( const QgsVectorLayerJoinInfo &join : constJoins )
287 {
288 // do not copy join information for auxiliary layer
289 if ( !auxiliaryLayer()
290 || ( auxiliaryLayer() && auxiliaryLayer()->id() != join.joinLayerId() ) )
291 layer->addJoin( join );
292 }
293
294 if ( mDataProvider )
295 layer->setProviderEncoding( mDataProvider->encoding() );
298 layer->setReadOnly( isReadOnly() );
303
304 const auto constActions = actions()->actions();
305 for ( const QgsAction &action : constActions )
306 {
307 layer->actions()->addAction( action );
308 }
309
310 if ( auto *lRenderer = renderer() )
311 {
312 layer->setRenderer( lRenderer->clone() );
313 }
314
315 if ( auto *lLabeling = labeling() )
316 {
317 layer->setLabeling( lLabeling->clone() );
318 }
320
322
323 if ( auto *lDiagramRenderer = diagramRenderer() )
324 {
325 layer->setDiagramRenderer( lDiagramRenderer->clone() );
326 }
327
328 if ( auto *lDiagramLayerSettings = diagramLayerSettings() )
329 {
330 layer->setDiagramLayerSettings( *lDiagramLayerSettings );
331 }
332
333 for ( int i = 0; i < fields().count(); i++ )
334 {
335 layer->setFieldAlias( i, attributeAlias( i ) );
337 layer->setEditorWidgetSetup( i, editorWidgetSetup( i ) );
340
341 QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength> constraints = fieldConstraintsAndStrength( i );
342 auto constraintIt = constraints.constBegin();
343 for ( ; constraintIt != constraints.constEnd(); ++ constraintIt )
344 {
345 layer->setFieldConstraint( i, constraintIt.key(), constraintIt.value() );
346 }
347
348 if ( fields().fieldOrigin( i ) == QgsFields::OriginExpression )
349 {
350 layer->addExpressionField( expressionField( i ), fields().at( i ) );
351 }
352 }
353
355
356 if ( auto *lAuxiliaryLayer = auxiliaryLayer() )
357 layer->setAuxiliaryLayer( lAuxiliaryLayer->clone( layer ) );
358
359 layer->mElevationProperties = mElevationProperties->clone();
360 layer->mElevationProperties->setParent( layer );
361
362 return layer;
363}
364
366{
367 if ( mDataProvider )
368 {
369 return mDataProvider->storageType();
370 }
371 return QString();
372}
373
374
376{
377 if ( mDataProvider )
378 {
379 return mDataProvider->capabilitiesString();
380 }
381 return QString();
382}
383
385{
386 return mDataProvider && mDataProvider->isSqlQuery();
387}
388
389Qgis::VectorLayerTypeFlags QgsVectorLayer::vectorLayerTypeFlags() const
390{
391 return mDataProvider ? mDataProvider->vectorLayerTypeFlags() : Qgis::VectorLayerTypeFlags();
392}
393
395{
396 if ( mDataProvider )
397 {
398 return mDataProvider->dataComment();
399 }
400 return QString();
401}
402
404{
405 return crs();
406}
407
409{
410 return name();
411}
412
414{
415 if ( mDataProvider )
416 {
417 mDataProvider->reloadData();
418 updateFields();
419 }
420}
421
423{
424 return new QgsVectorLayerRenderer( this, rendererContext );
425}
426
427
428void QgsVectorLayer::drawVertexMarker( double x, double y, QPainter &p, Qgis::VertexMarkerType type, int m )
429{
430 switch ( type )
431 {
433 p.setPen( QColor( 50, 100, 120, 200 ) );
434 p.setBrush( QColor( 200, 200, 210, 120 ) );
435 p.drawEllipse( x - m, y - m, m * 2 + 1, m * 2 + 1 );
436 break;
437
439 p.setPen( QColor( 255, 0, 0 ) );
440 p.drawLine( x - m, y + m, x + m, y - m );
441 p.drawLine( x - m, y - m, x + m, y + m );
442 break;
443
445 break;
446 }
447}
448
450{
451 mSelectedFeatureIds.insert( fid );
452 mPreviousSelectedFeatureIds.clear();
453
454 emit selectionChanged( QgsFeatureIds() << fid, QgsFeatureIds(), false );
455}
456
457void QgsVectorLayer::select( const QgsFeatureIds &featureIds )
458{
459 mSelectedFeatureIds.unite( featureIds );
460 mPreviousSelectedFeatureIds.clear();
461
462 emit selectionChanged( featureIds, QgsFeatureIds(), false );
463}
464
466{
467 mSelectedFeatureIds.remove( fid );
468 mPreviousSelectedFeatureIds.clear();
469
470 emit selectionChanged( QgsFeatureIds(), QgsFeatureIds() << fid, false );
471}
472
474{
475 mSelectedFeatureIds.subtract( featureIds );
476 mPreviousSelectedFeatureIds.clear();
477
478 emit selectionChanged( QgsFeatureIds(), featureIds, false );
479}
480
482{
483 // normalize the rectangle
484 rect.normalize();
485
486 QgsFeatureIds newSelection;
487
489 .setFilterRect( rect )
491 .setNoAttributes() );
492
493 QgsFeature feat;
494 while ( features.nextFeature( feat ) )
495 {
496 newSelection << feat.id();
497 }
498 features.close();
499
500 selectByIds( newSelection, behavior );
501}
502
503void QgsVectorLayer::selectByExpression( const QString &expression, Qgis::SelectBehavior behavior, QgsExpressionContext *context )
504{
505 QgsFeatureIds newSelection;
506
507 std::optional< QgsExpressionContext > defaultContext;
508 if ( !context )
509 {
510 defaultContext.emplace( QgsExpressionContextUtils::globalProjectLayerScopes( this ) );
511 context = &defaultContext.value();
512 }
513
515 {
517 .setExpressionContext( *context )
520
521 QgsFeatureIterator features = getFeatures( request );
522
523 if ( behavior == Qgis::SelectBehavior::AddToSelection )
524 {
525 newSelection = selectedFeatureIds();
526 }
527 QgsFeature feat;
528 while ( features.nextFeature( feat ) )
529 {
530 newSelection << feat.id();
531 }
532 features.close();
533 }
535 {
536 QgsExpression exp( expression );
537 exp.prepare( context );
538
539 QgsFeatureIds oldSelection = selectedFeatureIds();
540 QgsFeatureRequest request = QgsFeatureRequest().setFilterFids( oldSelection );
541
542 //refine request
543 if ( !exp.needsGeometry() )
546
547 QgsFeatureIterator features = getFeatures( request );
548 QgsFeature feat;
549 while ( features.nextFeature( feat ) )
550 {
551 context->setFeature( feat );
552 bool matches = exp.evaluate( context ).toBool();
553
554 if ( matches && behavior == Qgis::SelectBehavior::IntersectSelection )
555 {
556 newSelection << feat.id();
557 }
558 else if ( !matches && behavior == Qgis::SelectBehavior::RemoveFromSelection )
559 {
560 newSelection << feat.id();
561 }
562 }
563 }
564
565 selectByIds( newSelection );
566}
567
569{
570 QgsFeatureIds newSelection;
571
572 switch ( behavior )
573 {
575 newSelection = ids;
576 break;
577
579 newSelection = mSelectedFeatureIds + ids;
580 break;
581
583 newSelection = mSelectedFeatureIds - ids;
584 break;
585
587 newSelection = mSelectedFeatureIds.intersect( ids );
588 break;
589 }
590
591 QgsFeatureIds deselectedFeatures = mSelectedFeatureIds - newSelection;
592 mSelectedFeatureIds = newSelection;
593 mPreviousSelectedFeatureIds.clear();
594
595 emit selectionChanged( newSelection, deselectedFeatures, true );
596}
597
598void QgsVectorLayer::modifySelection( const QgsFeatureIds &selectIds, const QgsFeatureIds &deselectIds )
599{
600 QgsFeatureIds intersectingIds = selectIds & deselectIds;
601 if ( !intersectingIds.isEmpty() )
602 {
603 QgsDebugMsgLevel( QStringLiteral( "Trying to select and deselect the same item at the same time. Unsure what to do. Selecting dubious items." ), 3 );
604 }
605
606 mSelectedFeatureIds -= deselectIds;
607 mSelectedFeatureIds += selectIds;
608 mPreviousSelectedFeatureIds.clear();
609
610 emit selectionChanged( selectIds, deselectIds - intersectingIds, false );
611}
612
614{
616 ids.subtract( mSelectedFeatureIds );
617 selectByIds( ids );
618}
619
621{
623}
624
626{
627 // normalize the rectangle
628 rect.normalize();
629
631 .setFilterRect( rect )
633 .setNoAttributes() );
634
635 QgsFeatureIds selectIds;
636 QgsFeatureIds deselectIds;
637
638 QgsFeature fet;
639 while ( fit.nextFeature( fet ) )
640 {
641 if ( mSelectedFeatureIds.contains( fet.id() ) )
642 {
643 deselectIds << fet.id();
644 }
645 else
646 {
647 selectIds << fet.id();
648 }
649 }
650
651 modifySelection( selectIds, deselectIds );
652}
653
655{
656 if ( mSelectedFeatureIds.isEmpty() )
657 return;
658
659 const QgsFeatureIds previous = mSelectedFeatureIds;
661 mPreviousSelectedFeatureIds = previous;
662}
663
665{
666 if ( mPreviousSelectedFeatureIds.isEmpty() || !mSelectedFeatureIds.empty() )
667 return;
668
669 selectByIds( mPreviousSelectedFeatureIds );
670}
671
673{
674 return mDataProvider;
675}
676
678{
679 return mDataProvider;
680}
681
683{
684 return mTemporalProperties;
685}
686
688{
689 return mElevationProperties;
690}
691
693{
694 QgsProfileRequest modifiedRequest( request );
696 return new QgsVectorLayerProfileGenerator( this, modifiedRequest );
697}
698
699void QgsVectorLayer::setProviderEncoding( const QString &encoding )
700{
701 if ( isValid() && mDataProvider && mDataProvider->encoding() != encoding )
702 {
703 mDataProvider->setEncoding( encoding );
704 updateFields();
705 }
706}
707
709{
710 delete mDiagramRenderer;
711 mDiagramRenderer = r;
712 emit rendererChanged();
713 emit styleChanged();
714}
715
717{
718 return QgsWkbTypes::geometryType( mWkbType );
719}
720
722{
723 return mWkbType;
724}
725
727{
728 if ( !isValid() || !isSpatial() || mSelectedFeatureIds.isEmpty() || !mDataProvider ) //no selected features
729 {
730 return QgsRectangle( 0, 0, 0, 0 );
731 }
732
733 QgsRectangle r, retval;
734 retval.setMinimal();
735
736 QgsFeature fet;
737 if ( mDataProvider->capabilities() & QgsVectorDataProvider::SelectAtId )
738 {
740 .setFilterFids( mSelectedFeatureIds )
741 .setNoAttributes() );
742
743 while ( fit.nextFeature( fet ) )
744 {
745 if ( !fet.hasGeometry() )
746 continue;
747 r = fet.geometry().boundingBox();
748 retval.combineExtentWith( r );
749 }
750 }
751 else
752 {
754 .setNoAttributes() );
755
756 while ( fit.nextFeature( fet ) )
757 {
758 if ( mSelectedFeatureIds.contains( fet.id() ) )
759 {
760 if ( fet.hasGeometry() )
761 {
762 r = fet.geometry().boundingBox();
763 retval.combineExtentWith( r );
764 }
765 }
766 }
767 }
768
769 if ( retval.width() == 0.0 || retval.height() == 0.0 )
770 {
771 // If all of the features are at the one point, buffer the
772 // rectangle a bit. If they are all at zero, do something a bit
773 // more crude.
774
775 if ( retval.xMinimum() == 0.0 && retval.xMaximum() == 0.0 &&
776 retval.yMinimum() == 0.0 && retval.yMaximum() == 0.0 )
777 {
778 retval.set( -1.0, -1.0, 1.0, 1.0 );
779 }
780 }
781
782 return retval;
783}
784
786{
787 return mLabelsEnabled && static_cast< bool >( mLabeling );
788}
789
791{
792 mLabelsEnabled = enabled;
793}
794
796{
797 if ( !mDiagramRenderer || !mDiagramLayerSettings )
798 return false;
799
800 QList<QgsDiagramSettings> settingList = mDiagramRenderer->diagramSettings();
801 if ( !settingList.isEmpty() )
802 {
803 return settingList.at( 0 ).enabled;
804 }
805 return false;
806}
807
808long long QgsVectorLayer::featureCount( const QString &legendKey ) const
809{
810 if ( !mSymbolFeatureCounted )
811 return -1;
812
813 return mSymbolFeatureCountMap.value( legendKey, -1 );
814}
815
816QgsFeatureIds QgsVectorLayer::symbolFeatureIds( const QString &legendKey ) const
817{
818 if ( !mSymbolFeatureCounted )
819 return QgsFeatureIds();
820
821 return mSymbolFeatureIdMap.value( legendKey, QgsFeatureIds() );
822}
824{
825 if ( ( mSymbolFeatureCounted || mFeatureCounter ) && !( storeSymbolFids && mSymbolFeatureIdMap.isEmpty() ) )
826 return mFeatureCounter;
827
828 mSymbolFeatureCountMap.clear();
829 mSymbolFeatureIdMap.clear();
830
831 if ( !isValid() )
832 {
833 QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer" ), 3 );
834 return mFeatureCounter;
835 }
836 if ( !mDataProvider )
837 {
838 QgsDebugMsgLevel( QStringLiteral( "invoked with null mDataProvider" ), 3 );
839 return mFeatureCounter;
840 }
841 if ( !mRenderer )
842 {
843 QgsDebugMsgLevel( QStringLiteral( "invoked with null mRenderer" ), 3 );
844 return mFeatureCounter;
845 }
846
847 if ( !mFeatureCounter || ( storeSymbolFids && mSymbolFeatureIdMap.isEmpty() ) )
848 {
849 mFeatureCounter = new QgsVectorLayerFeatureCounter( this, QgsExpressionContext(), storeSymbolFids );
850 connect( mFeatureCounter, &QgsTask::taskCompleted, this, &QgsVectorLayer::onFeatureCounterCompleted, Qt::UniqueConnection );
851 connect( mFeatureCounter, &QgsTask::taskTerminated, this, &QgsVectorLayer::onFeatureCounterTerminated, Qt::UniqueConnection );
852 QgsApplication::taskManager()->addTask( mFeatureCounter );
853 }
854
855 return mFeatureCounter;
856}
857
859{
860 // do not update extent by default when trust project option is activated
861 if ( force || !mReadExtentFromXml || ( mReadExtentFromXml && mXmlExtent.isNull() ) )
862 mValidExtent = false;
863}
864
866{
868 mValidExtent = true;
869}
870
871void QgsVectorLayer::updateDefaultValues( QgsFeatureId fid, QgsFeature feature )
872{
873 if ( !mDefaultValueOnUpdateFields.isEmpty() )
874 {
875 if ( !feature.isValid() )
876 feature = getFeature( fid );
877
878 int size = mFields.size();
879 for ( int idx : std::as_const( mDefaultValueOnUpdateFields ) )
880 {
881 if ( idx < 0 || idx >= size )
882 continue;
883
884 feature.setAttribute( idx, defaultValue( idx, feature ) );
885 updateFeature( feature, true );
886 }
887 }
888}
889
891{
892 QgsRectangle rect;
893 rect.setMinimal();
894
895 if ( !isSpatial() )
896 return rect;
897
898 if ( !mValidExtent && mLazyExtent && mReadExtentFromXml && !mXmlExtent.isNull() )
899 {
900 updateExtent( mXmlExtent );
901 mValidExtent = true;
902 mLazyExtent = false;
903 }
904
905 if ( !mValidExtent && mLazyExtent && mDataProvider && mDataProvider->isValid() )
906 {
907 // store the extent
908 updateExtent( mDataProvider->extent() );
909 mValidExtent = true;
910 mLazyExtent = false;
911
912 // show the extent
913 QgsDebugMsgLevel( QStringLiteral( "Extent of layer: %1" ).arg( mExtent.toString() ), 3 );
914 }
915
916 if ( mValidExtent )
917 return QgsMapLayer::extent();
918
919 if ( !isValid() || !mDataProvider )
920 {
921 QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider" ), 3 );
922 return rect;
923 }
924
925 if ( !mEditBuffer ||
926 ( !mDataProvider->transaction() && ( mEditBuffer->deletedFeatureIds().isEmpty() && mEditBuffer->changedGeometries().isEmpty() ) ) ||
928 {
929 mDataProvider->updateExtents();
930
931 // get the extent of the layer from the provider
932 // but only when there are some features already
933 if ( mDataProvider->featureCount() != 0 )
934 {
935 const QgsRectangle r = mDataProvider->extent();
936 rect.combineExtentWith( r );
937 }
938
939 if ( mEditBuffer && !mDataProvider->transaction() )
940 {
941 const auto addedFeatures = mEditBuffer->addedFeatures();
942 for ( QgsFeatureMap::const_iterator it = addedFeatures.constBegin(); it != addedFeatures.constEnd(); ++it )
943 {
944 if ( it->hasGeometry() )
945 {
946 const QgsRectangle r = it->geometry().boundingBox();
947 rect.combineExtentWith( r );
948 }
949 }
950 }
951 }
952 else
953 {
955 .setNoAttributes() );
956
957 QgsFeature fet;
958 while ( fit.nextFeature( fet ) )
959 {
960 if ( fet.hasGeometry() && fet.geometry().type() != QgsWkbTypes::UnknownGeometry )
961 {
962 const QgsRectangle bb = fet.geometry().boundingBox();
963 rect.combineExtentWith( bb );
964 }
965 }
966 }
967
968 if ( rect.xMinimum() > rect.xMaximum() && rect.yMinimum() > rect.yMaximum() )
969 {
970 // special case when there are no features in provider nor any added
971 rect = QgsRectangle(); // use rectangle with zero coordinates
972 }
973
974 updateExtent( rect );
975 mValidExtent = true;
976
977 // Send this (hopefully) up the chain to the map canvas
978 emit recalculateExtents();
979
980 return rect;
981}
982
984{
985 return extent();
986}
987
989{
990 if ( !isValid() || !mDataProvider )
991 {
992 QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider" ), 3 );
993 return customProperty( QStringLiteral( "storedSubsetString" ) ).toString();
994 }
995 return mDataProvider->subsetString();
996}
997
998bool QgsVectorLayer::setSubsetString( const QString &subset )
999{
1000 if ( !isValid() || !mDataProvider )
1001 {
1002 QgsDebugMsgLevel( QStringLiteral( "invoked with invalid layer or null mDataProvider or while editing" ), 3 );
1003 setCustomProperty( QStringLiteral( "storedSubsetString" ), subset );
1004 return false;
1005 }
1006 else if ( mEditBuffer )
1007 {
1008 QgsDebugMsgLevel( QStringLiteral( "invoked while editing" ), 3 );
1009 return false;
1010 }
1011
1012 if ( subset == mDataProvider->subsetString() )
1013 return true;
1014
1015 bool res = mDataProvider->setSubsetString( subset );
1016
1017 // get the updated data source string from the provider
1018 mDataSource = mDataProvider->dataSourceUri();
1019 updateExtents();
1020 updateFields();
1021
1022 if ( res )
1023 {
1024 emit subsetStringChanged();
1026 }
1027
1028 return res;
1029}
1030
1032{
1033 if ( isValid() && mDataProvider && !mEditBuffer && ( isSpatial() && geometryType() != QgsWkbTypes::PointGeometry ) && ( mSimplifyMethod.simplifyHints() & simplifyHint ) && renderContext.useRenderingOptimization() )
1034 {
1035 double maximumSimplificationScale = mSimplifyMethod.maximumScale();
1036
1037 // check maximum scale at which generalisation should be carried out
1038 return !( maximumSimplificationScale > 1 && renderContext.rendererScale() <= maximumSimplificationScale );
1039 }
1040 return false;
1041}
1042
1044{
1045 return mConditionalStyles;
1046}
1047
1049{
1050 if ( !isValid() || !mDataProvider )
1051 return QgsFeatureIterator();
1052
1053 return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( new QgsVectorLayerFeatureSource( this ), true, request ) );
1054}
1055
1057{
1058 QgsFeature feature;
1060 if ( feature.isValid() )
1061 return feature.geometry();
1062 else
1063 return QgsGeometry();
1064}
1065
1067{
1068 if ( !isValid() || !mEditBuffer || !mDataProvider )
1069 return false;
1070
1071
1072 if ( mGeometryOptions->isActive() )
1073 {
1074 QgsGeometry geom = feature.geometry();
1075 mGeometryOptions->apply( geom );
1076 feature.setGeometry( geom );
1077 }
1078
1079 bool success = mEditBuffer->addFeature( feature );
1080
1081 if ( success )
1082 {
1083 updateExtents();
1084
1085 if ( mJoinBuffer->containsJoins() )
1086 success = mJoinBuffer->addFeature( feature );
1087 }
1088
1089 return success;
1090}
1091
1092bool QgsVectorLayer::updateFeature( QgsFeature &updatedFeature, bool skipDefaultValues )
1093{
1094 if ( !mEditBuffer || !mDataProvider )
1095 {
1096 return false;
1097 }
1098
1099 QgsFeature currentFeature = getFeature( updatedFeature.id() );
1100 if ( currentFeature.isValid() )
1101 {
1102 bool hasChanged = false;
1103 bool hasError = false;
1104
1105 if ( ( updatedFeature.hasGeometry() || currentFeature.hasGeometry() ) && !updatedFeature.geometry().equals( currentFeature.geometry() ) )
1106 {
1107 QgsGeometry geometry = updatedFeature.geometry();
1108 if ( changeGeometry( updatedFeature.id(), geometry, true ) )
1109 {
1110 hasChanged = true;
1111 updatedFeature.setGeometry( geometry );
1112 }
1113 else
1114 {
1115 QgsDebugMsgLevel( QStringLiteral( "geometry of feature %1 could not be changed." ).arg( updatedFeature.id() ), 3 );
1116 }
1117 }
1118
1119 QgsAttributes fa = updatedFeature.attributes();
1120 QgsAttributes ca = currentFeature.attributes();
1121
1122 for ( int attr = 0; attr < fa.count(); ++attr )
1123 {
1124 if ( !qgsVariantEqual( fa.at( attr ), ca.at( attr ) ) )
1125 {
1126 if ( changeAttributeValue( updatedFeature.id(), attr, fa.at( attr ), ca.at( attr ), true ) )
1127 {
1128 hasChanged = true;
1129 }
1130 else
1131 {
1132 QgsDebugMsgLevel( QStringLiteral( "attribute %1 of feature %2 could not be changed." ).arg( attr ).arg( updatedFeature.id() ), 3 );
1133 hasError = true;
1134 }
1135 }
1136 }
1137 if ( hasChanged && !mDefaultValueOnUpdateFields.isEmpty() && !skipDefaultValues )
1138 updateDefaultValues( updatedFeature.id(), updatedFeature );
1139
1140 return !hasError;
1141 }
1142 else
1143 {
1144 QgsDebugMsgLevel( QStringLiteral( "feature %1 could not be retrieved" ).arg( updatedFeature.id() ), 3 );
1145 return false;
1146 }
1147}
1148
1149
1150bool QgsVectorLayer::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
1151{
1152 if ( !isValid() || !mEditBuffer || !mDataProvider )
1153 return false;
1154
1155 QgsVectorLayerEditUtils utils( this );
1156 bool result = utils.insertVertex( x, y, atFeatureId, beforeVertex );
1157 if ( result )
1158 updateExtents();
1159 return result;
1160}
1161
1162
1163bool QgsVectorLayer::insertVertex( const QgsPoint &point, QgsFeatureId atFeatureId, int beforeVertex )
1164{
1165 if ( !isValid() || !mEditBuffer || !mDataProvider )
1166 return false;
1167
1168 QgsVectorLayerEditUtils utils( this );
1169 bool result = utils.insertVertex( point, atFeatureId, beforeVertex );
1170 if ( result )
1171 updateExtents();
1172 return result;
1173}
1174
1175
1176bool QgsVectorLayer::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
1177{
1178 if ( !isValid() || !mEditBuffer || !mDataProvider )
1179 return false;
1180
1181 QgsVectorLayerEditUtils utils( this );
1182 bool result = utils.moveVertex( x, y, atFeatureId, atVertex );
1183
1184 if ( result )
1185 updateExtents();
1186 return result;
1187}
1188
1189bool QgsVectorLayer::moveVertex( const QgsPoint &p, QgsFeatureId atFeatureId, int atVertex )
1190{
1191 if ( !isValid() || !mEditBuffer || !mDataProvider )
1192 return false;
1193
1194 QgsVectorLayerEditUtils utils( this );
1195 bool result = utils.moveVertex( p, atFeatureId, atVertex );
1196
1197 if ( result )
1198 updateExtents();
1199 return result;
1200}
1201
1203{
1204 if ( !isValid() || !mEditBuffer || !mDataProvider )
1206
1207 QgsVectorLayerEditUtils utils( this );
1208 Qgis::VectorEditResult result = utils.deleteVertex( featureId, vertex );
1209
1210 if ( result == Qgis::VectorEditResult::Success )
1211 updateExtents();
1212 return result;
1213}
1214
1215
1217{
1218 if ( !isValid() || !mDataProvider || !( mDataProvider->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
1219 {
1220 return false;
1221 }
1222
1223 if ( !isEditable() )
1224 {
1225 return false;
1226 }
1227
1228 int deleted = 0;
1229 int count = mSelectedFeatureIds.size();
1230 // Make a copy since deleteFeature modifies mSelectedFeatureIds
1231 QgsFeatureIds selectedFeatures( mSelectedFeatureIds );
1232 for ( QgsFeatureId fid : std::as_const( selectedFeatures ) )
1233 {
1234 deleted += deleteFeature( fid, context ); // removes from selection
1235 }
1236
1238 updateExtents();
1239
1240 if ( deletedCount )
1241 {
1242 *deletedCount = deleted;
1243 }
1244
1245 return deleted == count;
1246}
1247
1248static const QgsPointSequence vectorPointXY2pointSequence( const QVector<QgsPointXY> &points )
1249{
1250 QgsPointSequence pts;
1251 pts.reserve( points.size() );
1252 QVector<QgsPointXY>::const_iterator it = points.constBegin();
1253 while ( it != points.constEnd() )
1254 {
1255 pts.append( QgsPoint( *it ) );
1256 ++it;
1257 }
1258 return pts;
1259}
1260Qgis::GeometryOperationResult QgsVectorLayer::addRing( const QVector<QgsPointXY> &ring, QgsFeatureId *featureId )
1261{
1262 return addRing( vectorPointXY2pointSequence( ring ), featureId );
1263}
1264
1266{
1267 if ( !isValid() || !mEditBuffer || !mDataProvider )
1269
1270 QgsVectorLayerEditUtils utils( this );
1272
1273 //first try with selected features
1274 if ( !mSelectedFeatureIds.isEmpty() )
1275 {
1276 result = utils.addRing( ring, mSelectedFeatureIds, featureId );
1277 }
1278
1280 {
1281 //try with all intersecting features
1282 result = utils.addRing( ring, QgsFeatureIds(), featureId );
1283 }
1284
1285 return result;
1286}
1287
1289{
1290 if ( !isValid() || !mEditBuffer || !mDataProvider )
1291 {
1292 delete ring;
1294 }
1295
1296 if ( !ring )
1297 {
1299 }
1300
1301 if ( !ring->isClosed() )
1302 {
1303 delete ring;
1305 }
1306
1307 QgsVectorLayerEditUtils utils( this );
1309
1310 //first try with selected features
1311 if ( !mSelectedFeatureIds.isEmpty() )
1312 {
1313 result = utils.addRing( static_cast< QgsCurve * >( ring->clone() ), mSelectedFeatureIds, featureId );
1314 }
1315
1317 {
1318 //try with all intersecting features
1319 result = utils.addRing( static_cast< QgsCurve * >( ring->clone() ), QgsFeatureIds(), featureId );
1320 }
1321
1322 delete ring;
1323 return result;
1324}
1325
1327{
1328 QgsPointSequence pts;
1329 pts.reserve( points.size() );
1330 for ( QList<QgsPointXY>::const_iterator it = points.constBegin(); it != points.constEnd() ; ++it )
1331 {
1332 pts.append( QgsPoint( *it ) );
1333 }
1334 return addPart( pts );
1335}
1336
1337#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1338Qgis::GeometryOperationResult QgsVectorLayer::addPart( const QVector<QgsPointXY> &points )
1339{
1340 return addPart( vectorPointXY2pointSequence( points ) );
1341}
1342#endif
1343
1345{
1346 if ( !isValid() || !mEditBuffer || !mDataProvider )
1348
1349 //number of selected features must be 1
1350
1351 if ( mSelectedFeatureIds.empty() )
1352 {
1353 QgsDebugMsgLevel( QStringLiteral( "Number of selected features <1" ), 3 );
1355 }
1356 else if ( mSelectedFeatureIds.size() > 1 )
1357 {
1358 QgsDebugMsgLevel( QStringLiteral( "Number of selected features >1" ), 3 );
1360 }
1361
1362 QgsVectorLayerEditUtils utils( this );
1363 Qgis::GeometryOperationResult result = utils.addPart( points, *mSelectedFeatureIds.constBegin() );
1364
1366 updateExtents();
1367 return result;
1368}
1369
1371{
1372 if ( !isValid() || !mEditBuffer || !mDataProvider )
1374
1375 //number of selected features must be 1
1376
1377 if ( mSelectedFeatureIds.empty() )
1378 {
1379 QgsDebugMsgLevel( QStringLiteral( "Number of selected features <1" ), 3 );
1381 }
1382 else if ( mSelectedFeatureIds.size() > 1 )
1383 {
1384 QgsDebugMsgLevel( QStringLiteral( "Number of selected features >1" ), 3 );
1386 }
1387
1388 QgsVectorLayerEditUtils utils( this );
1389 Qgis::GeometryOperationResult result = utils.addPart( ring, *mSelectedFeatureIds.constBegin() );
1390
1392 updateExtents();
1393 return result;
1394}
1395
1396// TODO QGIS 4.0 -- this should return Qgis::GeometryOperationResult, not int
1397int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double dy )
1398{
1399 if ( !isValid() || !mEditBuffer || !mDataProvider )
1400 return static_cast< int >( Qgis::GeometryOperationResult::LayerNotEditable );
1401
1402 QgsVectorLayerEditUtils utils( this );
1403 int result = utils.translateFeature( featureId, dx, dy );
1404
1405 if ( result == static_cast< int >( Qgis::GeometryOperationResult::Success ) )
1406 updateExtents();
1407 return result;
1408}
1409
1410Qgis::GeometryOperationResult QgsVectorLayer::splitParts( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
1411{
1412 return splitParts( vectorPointXY2pointSequence( splitLine ), topologicalEditing );
1413}
1414
1416{
1417 if ( !isValid() || !mEditBuffer || !mDataProvider )
1419
1420 QgsVectorLayerEditUtils utils( this );
1421 return utils.splitParts( splitLine, topologicalEditing );
1422}
1423
1424Qgis::GeometryOperationResult QgsVectorLayer::splitFeatures( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
1425{
1426 return splitFeatures( vectorPointXY2pointSequence( splitLine ), topologicalEditing );
1427}
1428
1430{
1431 QgsLineString splitLineString( splitLine );
1432 QgsPointSequence topologyTestPoints;
1433 bool preserveCircular = false;
1434 return splitFeatures( &splitLineString, topologyTestPoints, preserveCircular, topologicalEditing );
1435}
1436
1437Qgis::GeometryOperationResult QgsVectorLayer::splitFeatures( const QgsCurve *curve, QgsPointSequence &topologyTestPoints, bool preserveCircular, bool topologicalEditing )
1438{
1439 if ( !isValid() || !mEditBuffer || !mDataProvider )
1441
1442 QgsVectorLayerEditUtils utils( this );
1443 return utils.splitFeatures( curve, topologyTestPoints, preserveCircular, topologicalEditing );
1444}
1445
1447{
1448 if ( !isValid() || !mEditBuffer || !mDataProvider )
1449 return -1;
1450
1451 QgsVectorLayerEditUtils utils( this );
1452 return utils.addTopologicalPoints( geom );
1453}
1454
1456{
1457 return addTopologicalPoints( QgsPoint( p ) );
1458}
1459
1461{
1462 if ( !isValid() || !mEditBuffer || !mDataProvider )
1463 return -1;
1464
1465 QgsVectorLayerEditUtils utils( this );
1466 return utils.addTopologicalPoints( p );
1467}
1468
1470{
1471 if ( !mValid || !mEditBuffer || !mDataProvider )
1472 return -1;
1473
1474 QgsVectorLayerEditUtils utils( this );
1475 return utils.addTopologicalPoints( ps );
1476}
1477
1479{
1480 if ( mLabeling == labeling )
1481 return;
1482
1483 delete mLabeling;
1484 mLabeling = labeling;
1485}
1486
1488{
1489 if ( project() && project()->transactionMode() == Qgis::TransactionMode::BufferedGroups )
1490 return project()->startEditing( this );
1491
1492 if ( !isValid() || !mDataProvider )
1493 {
1494 return false;
1495 }
1496
1497 // allow editing if provider supports any of the capabilities
1498 if ( !supportsEditing() )
1499 {
1500 return false;
1501 }
1502
1503 if ( mEditBuffer )
1504 {
1505 // editing already underway
1506 return false;
1507 }
1508
1509 mDataProvider->enterUpdateMode();
1510
1511 emit beforeEditingStarted();
1512
1513 createEditBuffer();
1514
1515 updateFields();
1516
1517 emit editingStarted();
1518
1519 return true;
1520}
1521
1523{
1524 if ( mDataProvider )
1525 mDataProvider->setTransformContext( transformContext );
1526}
1527
1529{
1530 return mDataProvider ? mDataProvider->hasSpatialIndex() : QgsFeatureSource::SpatialIndexUnknown;
1531}
1532
1534{
1535 if ( mRenderer )
1536 if ( !mRenderer->accept( visitor ) )
1537 return false;
1538
1539 if ( mLabeling )
1540 if ( !mLabeling->accept( visitor ) )
1541 return false;
1542
1543 return true;
1544}
1545
1546bool QgsVectorLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
1547{
1548 QgsDebugMsgLevel( QStringLiteral( "Datasource in QgsVectorLayer::readXml: %1" ).arg( mDataSource.toLocal8Bit().data() ), 3 );
1549
1550 //process provider key
1551 QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1552
1553 if ( pkeyNode.isNull() )
1554 {
1555 mProviderKey.clear();
1556 }
1557 else
1558 {
1559 QDomElement pkeyElt = pkeyNode.toElement();
1560 mProviderKey = pkeyElt.text();
1561 }
1562
1563 // determine type of vector layer
1564 if ( !mProviderKey.isNull() )
1565 {
1566 // if the provider string isn't empty, then we successfully
1567 // got the stored provider
1568 }
1569 else if ( mDataSource.contains( QLatin1String( "dbname=" ) ) )
1570 {
1571 mProviderKey = QStringLiteral( "postgres" );
1572 }
1573 else
1574 {
1575 mProviderKey = QStringLiteral( "ogr" );
1576 }
1577
1578 const QDomElement elem = layer_node.toElement();
1580 QgsDataProvider::ReadFlags flags;
1582 {
1584 }
1585 if ( ( mReadFlags & QgsMapLayer::FlagDontResolveLayers ) || !setDataProvider( mProviderKey, options, flags ) )
1586 {
1588 {
1589 QgsDebugMsg( QStringLiteral( "Could not set data provider for layer %1" ).arg( publicSource() ) );
1590 }
1591
1592 // for invalid layer sources, we fallback to stored wkbType if available
1593 if ( elem.hasAttribute( QStringLiteral( "wkbType" ) ) )
1594 mWkbType = qgsEnumKeyToValue( elem.attribute( QStringLiteral( "wkbType" ) ), mWkbType );
1595 }
1597 {
1599 mDataSourceReadOnly = true;
1600 }
1601
1602 QDomElement pkeyElem = pkeyNode.toElement();
1603 if ( !pkeyElem.isNull() )
1604 {
1605 QString encodingString = pkeyElem.attribute( QStringLiteral( "encoding" ) );
1606 if ( mDataProvider && !encodingString.isEmpty() )
1607 {
1608 mDataProvider->setEncoding( encodingString );
1609 }
1610 }
1611
1612 // load vector joins - does not resolve references to layers yet
1613 mJoinBuffer->readXml( layer_node );
1614
1615 updateFields();
1616
1617 // If style doesn't include a legend, we'll need to make a default one later...
1618 mSetLegendFromStyle = false;
1619
1620 QString errorMsg;
1621 if ( !readSymbology( layer_node, errorMsg, context ) )
1622 {
1623 return false;
1624 }
1625
1626 readStyleManager( layer_node );
1627
1628 QDomNode depsNode = layer_node.namedItem( QStringLiteral( "dataDependencies" ) );
1629 QDomNodeList depsNodes = depsNode.childNodes();
1630 QSet<QgsMapLayerDependency> sources;
1631 for ( int i = 0; i < depsNodes.count(); i++ )
1632 {
1633 QString source = depsNodes.at( i ).toElement().attribute( QStringLiteral( "id" ) );
1634 sources << QgsMapLayerDependency( source );
1635 }
1636 setDependencies( sources );
1637
1638 if ( !mSetLegendFromStyle )
1640
1641 // read extent
1643 {
1644 mReadExtentFromXml = true;
1645 }
1646 if ( mReadExtentFromXml )
1647 {
1648 const QDomNode extentNode = layer_node.namedItem( QStringLiteral( "extent" ) );
1649 if ( !extentNode.isNull() )
1650 {
1651 mXmlExtent = QgsXmlUtils::readRectangle( extentNode.toElement() );
1652 }
1653 }
1654
1655 // auxiliary layer
1656 const QDomNode asNode = layer_node.namedItem( QStringLiteral( "auxiliaryLayer" ) );
1657 const QDomElement asElem = asNode.toElement();
1658 if ( !asElem.isNull() )
1659 {
1660 mAuxiliaryLayerKey = asElem.attribute( QStringLiteral( "key" ) );
1661 }
1662
1663 // QGIS Server WMS Dimensions
1664 mServerProperties->readXml( layer_node );
1665
1666 return isValid(); // should be true if read successfully
1667
1668} // void QgsVectorLayer::readXml
1669
1670
1671void QgsVectorLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider,
1672 const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1673{
1675
1676 mDataSource = dataSource;
1677 setName( baseName );
1678 setDataProvider( provider, options, flags );
1679
1680 if ( !isValid() )
1681 {
1682 return;
1683 }
1684
1685 // Always set crs
1687
1688 bool loadDefaultStyleFlag = false;
1690 {
1691 loadDefaultStyleFlag = true;
1692 }
1693
1694 // reset style if loading default style, style is missing, or geometry type is has changed (and layer is valid)
1695 if ( !renderer() || !legend() || ( isValid() && geomType != geometryType() ) || loadDefaultStyleFlag )
1696 {
1697 std::unique_ptr< QgsScopedRuntimeProfile > profile;
1698 if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) )
1699 profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Load layer style" ), QStringLiteral( "projectload" ) );
1700
1701 bool defaultLoadedFlag = false;
1702
1703 // defer style changed signal until we've set the renderer, labeling, everything.
1704 // we don't want multiple signals!
1705 ScopedIntIncrementor styleChangedSignalBlocker( &mBlockStyleChangedSignal );
1706
1707 // need to check whether the default style included a legend, and if not, we need to make a default legend
1708 // later...
1709 mSetLegendFromStyle = false;
1710
1711 // first check if there is a default style / propertysheet defined
1712 // for this layer and if so apply it
1713 // this should take precedence over all
1714 if ( !defaultLoadedFlag && loadDefaultStyleFlag )
1715 {
1716 loadDefaultStyle( defaultLoadedFlag );
1717 }
1718
1719 if ( loadDefaultStyleFlag && !defaultLoadedFlag && isSpatial() && mDataProvider->capabilities() & QgsVectorDataProvider::CreateRenderer )
1720 {
1721 // if we didn't load a default style for this layer, try to create a renderer directly from the data provider
1722 std::unique_ptr< QgsFeatureRenderer > defaultRenderer( mDataProvider->createRenderer() );
1723 if ( defaultRenderer )
1724 {
1725 defaultLoadedFlag = true;
1726 setRenderer( defaultRenderer.release() );
1727 }
1728 }
1729
1730 // if the default style failed to load or was disabled use some very basic defaults
1731 if ( !defaultLoadedFlag && isSpatial() )
1732 {
1733 // add single symbol renderer
1735 }
1736
1737 if ( !mSetLegendFromStyle )
1739
1740 if ( mDataProvider->capabilities() & QgsVectorDataProvider::CreateLabeling )
1741 {
1742 std::unique_ptr< QgsAbstractVectorLayerLabeling > defaultLabeling( mDataProvider->createLabeling() );
1743 if ( defaultLabeling )
1744 {
1745 setLabeling( defaultLabeling.release() );
1746 setLabelsEnabled( true );
1747 }
1748 }
1749
1750 styleChangedSignalBlocker.release();
1752 }
1753}
1754
1755QString QgsVectorLayer::loadDefaultStyle( bool &resultFlag )
1756{
1757 // first try to load a user-defined default style - this should always take precedence
1758 QString res = QgsMapLayer::loadDefaultStyle( resultFlag );
1759 if ( resultFlag )
1760 return res;
1761
1762 if ( isSpatial() && mDataProvider->capabilities() & QgsVectorDataProvider::CreateRenderer )
1763 {
1764 // otherwise try to create a renderer directly from the data provider
1765 std::unique_ptr< QgsFeatureRenderer > defaultRenderer( mDataProvider->createRenderer() );
1766 if ( defaultRenderer )
1767 {
1768 resultFlag = true;
1769 setRenderer( defaultRenderer.release() );
1770 return QString();
1771 }
1772 }
1773
1774 return QString();
1775}
1776
1777bool QgsVectorLayer::setDataProvider( QString const &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1778{
1779 mProviderKey = provider;
1780 delete mDataProvider;
1781
1782 // For Postgres provider primary key unicity is tested at construction time,
1783 // so it has to be set before initializing the provider,
1784 // this manipulation is necessary to preserve default behavior when
1785 // "trust layer metadata" project level option is set and checkPrimaryKeyUnicity
1786 // was not explicitly passed in the uri
1787 if ( provider.compare( QLatin1String( "postgres" ) ) == 0 )
1788 {
1789 const QString checkUnicityKey { QStringLiteral( "checkPrimaryKeyUnicity" ) };
1791 if ( ! uri.hasParam( checkUnicityKey ) )
1792 {
1793 uri.setParam( checkUnicityKey, mReadExtentFromXml ? "0" : "1" );
1794 mDataSource = uri.uri( false );
1795 }
1796 }
1797
1798 std::unique_ptr< QgsScopedRuntimeProfile > profile;
1799 if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) )
1800 profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Create %1 provider" ).arg( provider ), QStringLiteral( "projectload" ) );
1801
1802 mDataProvider = qobject_cast<QgsVectorDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, mDataSource, options, flags ) );
1803 if ( !mDataProvider )
1804 {
1805 setValid( false );
1806 QgsDebugMsgLevel( QStringLiteral( "Unable to get data provider" ), 2 );
1807 return false;
1808 }
1809
1810 mDataProvider->setParent( this );
1811 connect( mDataProvider, &QgsVectorDataProvider::raiseError, this, &QgsVectorLayer::raiseError );
1812
1813 QgsDebugMsgLevel( QStringLiteral( "Instantiated the data provider plugin" ), 2 );
1814
1815 setValid( mDataProvider->isValid() );
1816 if ( !isValid() )
1817 {
1818 QgsDebugMsgLevel( QStringLiteral( "Invalid provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 );
1819 return false;
1820 }
1821
1822 if ( profile )
1823 profile->switchTask( tr( "Read layer metadata" ) );
1825 {
1826 // we combine the provider metadata with the layer's existing metadata, so as not to reset any user customizations to the metadata
1827 // back to the default if a layer's data source is changed
1828 QgsLayerMetadata newMetadata = mDataProvider->layerMetadata();
1829 // this overwrites the provider metadata with any properties which are non-empty from the existing layer metadata
1830 newMetadata.combine( &mMetadata );
1831
1832 setMetadata( newMetadata );
1833 QgsDebugMsgLevel( QStringLiteral( "Set Data provider QgsLayerMetadata identifier[%1]" ).arg( metadata().identifier() ), 4 );
1834 }
1835
1836 // TODO: Check if the provider has the capability to send fullExtentCalculated
1837 connect( mDataProvider, &QgsVectorDataProvider::fullExtentCalculated, this, [ = ] { updateExtents(); } );
1838
1839 // get and store the feature type
1840 mWkbType = mDataProvider->wkbType();
1841
1842 // before we update the layer fields from the provider, we first copy any default set alias and
1843 // editor widget config from the data provider fields, if present
1844 const QgsFields providerFields = mDataProvider->fields();
1845 for ( const QgsField &field : providerFields )
1846 {
1847 // we only copy defaults from the provider if we aren't overriding any configuration made in the layer
1848 if ( !field.editorWidgetSetup().isNull() && mFieldWidgetSetups.value( field.name() ).isNull() )
1849 {
1850 mFieldWidgetSetups[ field.name() ] = field.editorWidgetSetup();
1851 }
1852 if ( !field.alias().isEmpty() && mAttributeAliasMap.value( field.name() ).isEmpty() )
1853 {
1854 mAttributeAliasMap[ field.name() ] = field.alias();
1855 }
1856 }
1857
1858 if ( profile )
1859 profile->switchTask( tr( "Read layer fields" ) );
1860 updateFields();
1861
1862 if ( mProviderKey == QLatin1String( "postgres" ) )
1863 {
1864 // update datasource from data provider computed one
1865 mDataSource = mDataProvider->dataSourceUri( false );
1866
1867 QgsDebugMsgLevel( QStringLiteral( "Beautifying layer name %1" ).arg( name() ), 3 );
1868
1869 // adjust the display name for postgres layers
1870 const QRegularExpression reg( R"lit("[^"]+"\."([^"] + )"( \‍([^)]+\))?)lit" );
1871 const QRegularExpressionMatch match = reg.match( name() );
1872 if ( match.hasMatch() )
1873 {
1874 QStringList stuff = match.capturedTexts();
1875 QString lName = stuff[1];
1876
1877 const QMap<QString, QgsMapLayer *> &layers = QgsProject::instance()->mapLayers();
1878
1879 QMap<QString, QgsMapLayer *>::const_iterator it;
1880 for ( it = layers.constBegin(); it != layers.constEnd() && ( *it )->name() != lName; ++it )
1881 ;
1882
1883 if ( it != layers.constEnd() && stuff.size() > 2 )
1884 {
1885 lName += '.' + stuff[2].mid( 2, stuff[2].length() - 3 );
1886 }
1887
1888 if ( !lName.isEmpty() )
1889 setName( lName );
1890 }
1891 QgsDebugMsgLevel( QStringLiteral( "Beautified layer name %1" ).arg( name() ), 3 );
1892 }
1893 else if ( mProviderKey == QLatin1String( "osm" ) )
1894 {
1895 // make sure that the "observer" has been removed from URI to avoid crashes
1896 mDataSource = mDataProvider->dataSourceUri();
1897 }
1898 else if ( provider == QLatin1String( "ogr" ) )
1899 {
1900 // make sure that the /vsigzip or /vsizip is added to uri, if applicable
1901 mDataSource = mDataProvider->dataSourceUri();
1902 if ( mDataSource.right( 10 ) == QLatin1String( "|layerid=0" ) )
1903 mDataSource.chop( 10 );
1904 }
1905 else if ( provider == QLatin1String( "memory" ) )
1906 {
1907 // required so that source differs between memory layers
1908 mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
1909 }
1910 else if ( provider == QLatin1String( "hana" ) )
1911 {
1912 // update datasource from data provider computed one
1913 mDataSource = mDataProvider->dataSourceUri( false );
1914 }
1915
1916 connect( mDataProvider, &QgsVectorDataProvider::dataChanged, this, &QgsVectorLayer::emitDataChanged );
1918
1919 return true;
1920} // QgsVectorLayer:: setDataProvider
1921
1922
1923
1924
1925/* virtual */
1926bool QgsVectorLayer::writeXml( QDomNode &layer_node,
1927 QDomDocument &document,
1928 const QgsReadWriteContext &context ) const
1929{
1930 // first get the layer element so that we can append the type attribute
1931
1932 QDomElement mapLayerNode = layer_node.toElement();
1933
1934 if ( mapLayerNode.isNull() || ( "maplayer" != mapLayerNode.nodeName() ) )
1935 {
1936 QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
1937 return false;
1938 }
1939
1940 mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( QgsMapLayerType::VectorLayer ) );
1941
1942 // set the geometry type
1943 mapLayerNode.setAttribute( QStringLiteral( "geometry" ), QgsWkbTypes::geometryDisplayString( geometryType() ) );
1944 mapLayerNode.setAttribute( QStringLiteral( "wkbType" ), qgsEnumValueToKey( wkbType() ) );
1945
1946 // add provider node
1947 if ( mDataProvider )
1948 {
1949 QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1950 provider.setAttribute( QStringLiteral( "encoding" ), mDataProvider->encoding() );
1951 QDomText providerText = document.createTextNode( providerType() );
1952 provider.appendChild( providerText );
1953 layer_node.appendChild( provider );
1954 }
1955
1956 //save joins
1957 mJoinBuffer->writeXml( layer_node, document );
1958
1959 // dependencies
1960 QDomElement dependenciesElement = document.createElement( QStringLiteral( "layerDependencies" ) );
1961 const auto constDependencies = dependencies();
1962 for ( const QgsMapLayerDependency &dep : constDependencies )
1963 {
1965 continue;
1966 QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
1967 depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
1968 dependenciesElement.appendChild( depElem );
1969 }
1970 layer_node.appendChild( dependenciesElement );
1971
1972 // change dependencies
1973 QDomElement dataDependenciesElement = document.createElement( QStringLiteral( "dataDependencies" ) );
1974 for ( const QgsMapLayerDependency &dep : constDependencies )
1975 {
1976 if ( dep.type() != QgsMapLayerDependency::DataDependency )
1977 continue;
1978 QDomElement depElem = document.createElement( QStringLiteral( "layer" ) );
1979 depElem.setAttribute( QStringLiteral( "id" ), dep.layerId() );
1980 dataDependenciesElement.appendChild( depElem );
1981 }
1982 layer_node.appendChild( dataDependenciesElement );
1983
1984 // save expression fields
1985 mExpressionFieldBuffer->writeXml( layer_node, document );
1986
1987 writeStyleManager( layer_node, document );
1988
1989 // auxiliary layer
1990 QDomElement asElem = document.createElement( QStringLiteral( "auxiliaryLayer" ) );
1991 if ( mAuxiliaryLayer )
1992 {
1993 const QString pkField = mAuxiliaryLayer->joinInfo().targetFieldName();
1994 asElem.setAttribute( QStringLiteral( "key" ), pkField );
1995 }
1996 layer_node.appendChild( asElem );
1997
1998 // save QGIS Server properties (WMS Dimension, metadata URLS...)
1999 mServerProperties->writeXml( layer_node, document );
2000
2001 // renderer specific settings
2002 QString errorMsg;
2003 return writeSymbology( layer_node, document, errorMsg, context );
2004}
2005
2006QString QgsVectorLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
2007{
2008 QString src( source );
2009
2010 // TODO: what about postgres, mysql and others, they should not go through writePath()
2011 if ( providerType() == QLatin1String( "spatialite" ) )
2012 {
2013 QgsDataSourceUri uri( src );
2014 QString database = context.pathResolver().writePath( uri.database() );
2015 uri.setConnection( uri.host(), uri.port(), database, uri.username(), uri.password() );
2016 src = uri.uri();
2017 }
2018 else if ( providerType() == QLatin1String( "ogr" ) )
2019 {
2020 QStringList theURIParts = src.split( '|' );
2021 theURIParts[0] = context.pathResolver().writePath( theURIParts[0] );
2022 src = theURIParts.join( QLatin1Char( '|' ) );
2023 }
2024 else if ( providerType() == QLatin1String( "gpx" ) )
2025 {
2026 QStringList theURIParts = src.split( '?' );
2027 theURIParts[0] = context.pathResolver().writePath( theURIParts[0] );
2028 src = theURIParts.join( QLatin1Char( '?' ) );
2029 }
2030 else if ( providerType() == QLatin1String( "delimitedtext" ) )
2031 {
2032 QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
2033 QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().writePath( urlSource.toLocalFile() ) );
2034 urlDest.setQuery( urlSource.query() );
2035 src = QString::fromLatin1( urlDest.toEncoded() );
2036 }
2037 else if ( providerType() == QLatin1String( "memory" ) )
2038 {
2039 // Refetch the source from the provider, because adding fields actually changes the source for this provider.
2040 src = dataProvider()->dataSourceUri();
2041 }
2042 else if ( providerType() == QLatin1String( "virtual" ) )
2043 {
2044 QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
2045 QStringList theURIParts;
2046
2047 QUrlQuery query = QUrlQuery( urlSource.query() );
2048 QList<QPair<QString, QString> > queryItems = query.queryItems();
2049
2050 for ( int i = 0; i < queryItems.size(); i++ )
2051 {
2052 QString key = queryItems.at( i ).first;
2053 QString value = queryItems.at( i ).second;
2054 if ( key == QLatin1String( "layer" ) )
2055 {
2056 // syntax: provider:url_encoded_source_URI(:name(:encoding)?)?
2057 theURIParts = value.split( ':' );
2058 theURIParts[1] = QUrl::fromPercentEncoding( theURIParts[1].toUtf8() );
2059
2060 if ( theURIParts[0] == QLatin1String( "delimitedtext" ) )
2061 {
2062 QUrl urlSource = QUrl( theURIParts[1] );
2063 QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().writePath( urlSource.toLocalFile() ) );
2064 urlDest.setQuery( urlSource.query() );
2065 theURIParts[1] = QUrl::toPercentEncoding( urlDest.toString(), QByteArray( "" ), QByteArray( ":" ) );
2066 }
2067 else
2068 {
2069 theURIParts[1] = context.pathResolver().writePath( theURIParts[1] );
2070 theURIParts[1] = QUrl::toPercentEncoding( theURIParts[1] );
2071 }
2072
2073 queryItems[i].second = theURIParts.join( QLatin1Char( ':' ) ) ;
2074 }
2075 }
2076
2077 query.setQueryItems( queryItems );
2078
2079 QUrl urlDest = QUrl( urlSource );
2080 urlDest.setQuery( query.query() );
2081 src = QString::fromLatin1( urlDest.toEncoded() );
2082 }
2083 else
2084 {
2085 src = context.pathResolver().writePath( src );
2086 }
2087
2088 return src;
2089}
2090
2091QString QgsVectorLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
2092{
2093 QString src( source );
2094
2095 if ( provider == QLatin1String( "spatialite" ) )
2096 {
2097 QgsDataSourceUri uri( src );
2098 uri.setDatabase( context.pathResolver().readPath( uri.database() ) );
2099 src = uri.uri();
2100 }
2101 else if ( provider == QLatin1String( "ogr" ) )
2102 {
2103 QStringList theURIParts = src.split( '|' );
2104 theURIParts[0] = context.pathResolver().readPath( theURIParts[0] );
2105 src = theURIParts.join( QLatin1Char( '|' ) );
2106 }
2107 else if ( provider == QLatin1String( "gpx" ) )
2108 {
2109 QStringList theURIParts = src.split( '?' );
2110 theURIParts[0] = context.pathResolver().readPath( theURIParts[0] );
2111 src = theURIParts.join( QLatin1Char( '?' ) );
2112 }
2113 else if ( provider == QLatin1String( "delimitedtext" ) )
2114 {
2115 QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
2116
2117 if ( !src.startsWith( QLatin1String( "file:" ) ) )
2118 {
2119 QUrl file = QUrl::fromLocalFile( src.left( src.indexOf( '?' ) ) );
2120 urlSource.setScheme( QStringLiteral( "file" ) );
2121 urlSource.setPath( file.path() );
2122 }
2123
2124 QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().readPath( urlSource.toLocalFile() ) );
2125 urlDest.setQuery( urlSource.query() );
2126 src = QString::fromLatin1( urlDest.toEncoded() );
2127 }
2128 else if ( provider == QLatin1String( "virtual" ) )
2129 {
2130 QUrl urlSource = QUrl::fromEncoded( src.toLatin1() );
2131 QStringList theURIParts;
2132
2133 QUrlQuery query = QUrlQuery( urlSource.query() );
2134 QList<QPair<QString, QString> > queryItems = query.queryItems();
2135
2136 for ( int i = 0; i < queryItems.size(); i++ )
2137 {
2138 QString key = queryItems.at( i ).first;
2139 QString value = queryItems.at( i ).second;
2140 if ( key == QLatin1String( "layer" ) )
2141 {
2142 // syntax: provider:url_encoded_source_URI(:name(:encoding)?)?
2143 theURIParts = value.split( ':' );
2144 theURIParts[1] = QUrl::fromPercentEncoding( theURIParts[1].toUtf8() );
2145
2146 if ( theURIParts[0] == QLatin1String( "delimitedtext" ) )
2147 {
2148 QUrl urlSource = QUrl( theURIParts[1] );
2149
2150 if ( !theURIParts[1].startsWith( QLatin1String( "file:" ) ) )
2151 {
2152 QUrl file = QUrl::fromLocalFile( theURIParts[1].left( theURIParts[1].indexOf( '?' ) ) );
2153 urlSource.setScheme( QStringLiteral( "file" ) );
2154 urlSource.setPath( file.path() );
2155 }
2156
2157 QUrl urlDest = QUrl::fromLocalFile( context.pathResolver().readPath( urlSource.toLocalFile() ) );
2158 urlDest.setQuery( urlSource.query() );
2159
2160 theURIParts[1] = urlDest.toString();
2161 }
2162 else
2163 {
2164 theURIParts[1] = context.pathResolver().readPath( theURIParts[1] );
2165 }
2166
2167 theURIParts[1] = QUrl::toPercentEncoding( theURIParts[1] );
2168 queryItems[i].second = theURIParts.join( QLatin1Char( ':' ) ) ;
2169 }
2170 }
2171
2172 query.setQueryItems( queryItems );
2173
2174 QUrl urlDest = QUrl( urlSource );
2175 urlDest.setQuery( query.query() );
2176 src = QString::fromLatin1( urlDest.toEncoded() );
2177 }
2178 else
2179 {
2180 src = context.pathResolver().readPath( src );
2181 }
2182
2183 return src;
2184}
2185
2186
2187
2189{
2191 mJoinBuffer->resolveReferences( project );
2192}
2193
2194
2195bool QgsVectorLayer::readSymbology( const QDomNode &layerNode, QString &errorMessage,
2196 QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2197{
2198 if ( categories.testFlag( Fields ) )
2199 {
2200 if ( !mExpressionFieldBuffer )
2201 mExpressionFieldBuffer = new QgsExpressionFieldBuffer();
2202 mExpressionFieldBuffer->readXml( layerNode );
2203
2204 updateFields();
2205 }
2206
2207 if ( categories.testFlag( Relations ) )
2208 {
2209 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Relations" ) );
2210
2211 const QgsPathResolver resolver { QgsProject::instance()->pathResolver() };
2212
2213 // Restore referenced layers: relations where "this" is the child layer (the referencing part, that holds the FK)
2214 QDomNodeList referencedLayersNodeList = layerNode.toElement().elementsByTagName( QStringLiteral( "referencedLayers" ) );
2215 if ( referencedLayersNodeList.size() > 0 )
2216 {
2217 const QDomNodeList relationNodes { referencedLayersNodeList.at( 0 ).childNodes() };
2218 for ( int i = 0; i < relationNodes.length(); ++i )
2219 {
2220 const QDomElement relationElement = relationNodes.at( i ).toElement();
2221
2222 mWeakRelations.push_back( QgsWeakRelation::readXml( this, QgsWeakRelation::Referencing, relationElement, resolver ) );
2223 }
2224 }
2225
2226 // Restore referencing layers: relations where "this" is the parent layer (the referenced part where the FK points to)
2227 QDomNodeList referencingLayersNodeList = layerNode.toElement().elementsByTagName( QStringLiteral( "referencingLayers" ) );
2228 if ( referencingLayersNodeList.size() > 0 )
2229 {
2230 const QDomNodeList relationNodes { referencingLayersNodeList.at( 0 ).childNodes() };
2231 for ( int i = 0; i < relationNodes.length(); ++i )
2232 {
2233 const QDomElement relationElement = relationNodes.at( i ).toElement();
2234 mWeakRelations.push_back( QgsWeakRelation::readXml( this, QgsWeakRelation::Referenced, relationElement, resolver ) );
2235 }
2236 }
2237 }
2238
2239 QDomElement layerElement = layerNode.toElement();
2240
2241 readCommonStyle( layerElement, context, categories );
2242
2243 readStyle( layerNode, errorMessage, context, categories );
2244
2245 if ( categories.testFlag( MapTips ) )
2246 mMapTipTemplate = layerNode.namedItem( QStringLiteral( "mapTip" ) ).toElement().text();
2247
2248 if ( categories.testFlag( LayerConfiguration ) )
2249 mDisplayExpression = layerNode.namedItem( QStringLiteral( "previewExpression" ) ).toElement().text();
2250
2251 // Try to migrate pre QGIS 3.0 display field property
2252 QString displayField = layerNode.namedItem( QStringLiteral( "displayfield" ) ).toElement().text();
2253 if ( mFields.lookupField( displayField ) < 0 )
2254 {
2255 // if it's not a field, it's a maptip
2256 if ( mMapTipTemplate.isEmpty() && categories.testFlag( MapTips ) )
2257 mMapTipTemplate = displayField;
2258 }
2259 else
2260 {
2261 if ( mDisplayExpression.isEmpty() && categories.testFlag( LayerConfiguration ) )
2262 mDisplayExpression = QgsExpression::quotedColumnRef( displayField );
2263 }
2264
2265 // process the attribute actions
2266 if ( categories.testFlag( Actions ) )
2267 mActions->readXml( layerNode );
2268
2269 if ( categories.testFlag( Fields ) )
2270 {
2271 // IMPORTANT - we don't clear mAttributeAliasMap here, as it may contain aliases which are coming direct
2272 // from the data provider. Instead we leave any existing aliases and only overwrite them if the style
2273 // has a specific value for that field's alias
2274 QDomNode aliasesNode = layerNode.namedItem( QStringLiteral( "aliases" ) );
2275 if ( !aliasesNode.isNull() )
2276 {
2277 QDomElement aliasElem;
2278
2279 QDomNodeList aliasNodeList = aliasesNode.toElement().elementsByTagName( QStringLiteral( "alias" ) );
2280 for ( int i = 0; i < aliasNodeList.size(); ++i )
2281 {
2282 aliasElem = aliasNodeList.at( i ).toElement();
2283
2284 QString field;
2285 if ( aliasElem.hasAttribute( QStringLiteral( "field" ) ) )
2286 {
2287 field = aliasElem.attribute( QStringLiteral( "field" ) );
2288 }
2289 else
2290 {
2291 int index = aliasElem.attribute( QStringLiteral( "index" ) ).toInt();
2292
2293 if ( index >= 0 && index < fields().count() )
2294 field = fields().at( index ).name();
2295 }
2296
2297 QString alias;
2298
2299 if ( !aliasElem.attribute( QStringLiteral( "name" ) ).isEmpty() )
2300 {
2301 //if it has alias
2302 alias = context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ), aliasElem.attribute( QStringLiteral( "name" ) ) );
2303 QgsDebugMsgLevel( "context" + QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ) + " source " + aliasElem.attribute( QStringLiteral( "name" ) ), 3 );
2304 }
2305 else
2306 {
2307 //if it has no alias, it should be the fields translation
2308 alias = context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ), field );
2309 QgsDebugMsgLevel( "context" + QStringLiteral( "project:layers:%1:fieldaliases" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text() ) + " source " + field, 3 );
2310 //if it gets the exact field value, there has been no translation (or not even translation loaded) - so no alias should be generated;
2311 if ( alias == aliasElem.attribute( QStringLiteral( "field" ) ) )
2312 alias.clear();
2313 }
2314
2315 QgsDebugMsgLevel( "field " + field + " origalias " + aliasElem.attribute( QStringLiteral( "name" ) ) + " trans " + alias, 3 );
2316 mAttributeAliasMap.insert( field, alias );
2317 }
2318 }
2319
2320 // default expressions
2321 mDefaultExpressionMap.clear();
2322 QDomNode defaultsNode = layerNode.namedItem( QStringLiteral( "defaults" ) );
2323 if ( !defaultsNode.isNull() )
2324 {
2325 QDomNodeList defaultNodeList = defaultsNode.toElement().elementsByTagName( QStringLiteral( "default" ) );
2326 for ( int i = 0; i < defaultNodeList.size(); ++i )
2327 {
2328 QDomElement defaultElem = defaultNodeList.at( i ).toElement();
2329
2330 QString field = defaultElem.attribute( QStringLiteral( "field" ), QString() );
2331 QString expression = defaultElem.attribute( QStringLiteral( "expression" ), QString() );
2332 bool applyOnUpdate = defaultElem.attribute( QStringLiteral( "applyOnUpdate" ), QStringLiteral( "0" ) ) == QLatin1String( "1" );
2333 if ( field.isEmpty() || expression.isEmpty() )
2334 continue;
2335
2336 mDefaultExpressionMap.insert( field, QgsDefaultValue( expression, applyOnUpdate ) );
2337 }
2338 }
2339
2340 // constraints
2341 mFieldConstraints.clear();
2342 mFieldConstraintStrength.clear();
2343 QDomNode constraintsNode = layerNode.namedItem( QStringLiteral( "constraints" ) );
2344 if ( !constraintsNode.isNull() )
2345 {
2346 QDomNodeList constraintNodeList = constraintsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
2347 for ( int i = 0; i < constraintNodeList.size(); ++i )
2348 {
2349 QDomElement constraintElem = constraintNodeList.at( i ).toElement();
2350
2351 QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
2352 int constraints = constraintElem.attribute( QStringLiteral( "constraints" ), QStringLiteral( "0" ) ).toInt();
2353 if ( field.isEmpty() || constraints == 0 )
2354 continue;
2355
2356 mFieldConstraints.insert( field, static_cast< QgsFieldConstraints::Constraints >( constraints ) );
2357
2358 int uniqueStrength = constraintElem.attribute( QStringLiteral( "unique_strength" ), QStringLiteral( "1" ) ).toInt();
2359 int notNullStrength = constraintElem.attribute( QStringLiteral( "notnull_strength" ), QStringLiteral( "1" ) ).toInt();
2360 int expStrength = constraintElem.attribute( QStringLiteral( "exp_strength" ), QStringLiteral( "1" ) ).toInt();
2361
2362 mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintUnique ), static_cast< QgsFieldConstraints::ConstraintStrength >( uniqueStrength ) );
2363 mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintNotNull ), static_cast< QgsFieldConstraints::ConstraintStrength >( notNullStrength ) );
2364 mFieldConstraintStrength.insert( qMakePair( field, QgsFieldConstraints::ConstraintExpression ), static_cast< QgsFieldConstraints::ConstraintStrength >( expStrength ) );
2365 }
2366 }
2367 mFieldConstraintExpressions.clear();
2368 QDomNode constraintExpressionsNode = layerNode.namedItem( QStringLiteral( "constraintExpressions" ) );
2369 if ( !constraintExpressionsNode.isNull() )
2370 {
2371 QDomNodeList constraintNodeList = constraintExpressionsNode.toElement().elementsByTagName( QStringLiteral( "constraint" ) );
2372 for ( int i = 0; i < constraintNodeList.size(); ++i )
2373 {
2374 QDomElement constraintElem = constraintNodeList.at( i ).toElement();
2375
2376 QString field = constraintElem.attribute( QStringLiteral( "field" ), QString() );
2377 QString exp = constraintElem.attribute( QStringLiteral( "exp" ), QString() );
2378 QString desc = constraintElem.attribute( QStringLiteral( "desc" ), QString() );
2379 if ( field.isEmpty() || exp.isEmpty() )
2380 continue;
2381
2382 mFieldConstraintExpressions.insert( field, qMakePair( exp, desc ) );
2383 }
2384 }
2385
2386 updateFields();
2387 }
2388
2389 // load field configuration
2390 if ( categories.testFlag( Fields ) || categories.testFlag( Forms ) )
2391 {
2392 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Forms" ) );
2393
2394 QDomElement widgetsElem = layerNode.namedItem( QStringLiteral( "fieldConfiguration" ) ).toElement();
2395 QDomNodeList fieldConfigurationElementList = widgetsElem.elementsByTagName( QStringLiteral( "field" ) );
2396 for ( int i = 0; i < fieldConfigurationElementList.size(); ++i )
2397 {
2398 const QDomElement fieldConfigElement = fieldConfigurationElementList.at( i ).toElement();
2399 const QDomElement fieldWidgetElement = fieldConfigElement.elementsByTagName( QStringLiteral( "editWidget" ) ).at( 0 ).toElement();
2400
2401 QString fieldName = fieldConfigElement.attribute( QStringLiteral( "name" ) );
2402
2403 if ( categories.testFlag( Fields ) )
2404 mFieldConfigurationFlags[fieldName] = qgsFlagKeysToValue( fieldConfigElement.attribute( QStringLiteral( "configurationFlags" ) ), QgsField::ConfigurationFlag::None );
2405
2406 // Load editor widget configuration
2407 if ( categories.testFlag( Forms ) )
2408 {
2409 const QString widgetType = fieldWidgetElement.attribute( QStringLiteral( "type" ) );
2410 const QDomElement cfgElem = fieldConfigElement.elementsByTagName( QStringLiteral( "config" ) ).at( 0 ).toElement();
2411 const QDomElement optionsElem = cfgElem.childNodes().at( 0 ).toElement();
2412 QVariantMap optionsMap = QgsXmlUtils::readVariant( optionsElem ).toMap();
2413 if ( widgetType == QLatin1String( "ValueRelation" ) )
2414 {
2415 optionsMap[ QStringLiteral( "Value" ) ] = context.projectTranslator()->translate( QStringLiteral( "project:layers:%1:fields:%2:valuerelationvalue" ).arg( layerNode.namedItem( QStringLiteral( "id" ) ).toElement().text(), fieldName ), optionsMap[ QStringLiteral( "Value" ) ].toString() );
2416 }
2417 QgsEditorWidgetSetup setup = QgsEditorWidgetSetup( widgetType, optionsMap );
2418 mFieldWidgetSetups[fieldName] = setup;
2419 }
2420 }
2421 }
2422
2423 // Legacy reading for QGIS 3.14 and older projects
2424 // Attributes excluded from WMS and WFS
2425 if ( categories.testFlag( Fields ) )
2426 {
2427 const QList<QPair<QString, QgsField::ConfigurationFlag>> legacyConfig
2428 {
2429 qMakePair( QStringLiteral( "excludeAttributesWMS" ), QgsField::ConfigurationFlag::HideFromWms ),
2430 qMakePair( QStringLiteral( "excludeAttributesWFS" ), QgsField::ConfigurationFlag::HideFromWfs )
2431 };
2432 for ( const auto &config : legacyConfig )
2433 {
2434 QDomNode excludeNode = layerNode.namedItem( config.first );
2435 if ( !excludeNode.isNull() )
2436 {
2437 QDomNodeList attributeNodeList = excludeNode.toElement().elementsByTagName( QStringLiteral( "attribute" ) );
2438 for ( int i = 0; i < attributeNodeList.size(); ++i )
2439 {
2440 QString fieldName = attributeNodeList.at( i ).toElement().text();
2441 if ( !mFieldConfigurationFlags.contains( fieldName ) )
2442 mFieldConfigurationFlags[fieldName] = config.second;
2443 else
2444 mFieldConfigurationFlags[fieldName].setFlag( config.second, true );
2445 }
2446 }
2447 }
2448 }
2449
2450 if ( categories.testFlag( GeometryOptions ) )
2451 mGeometryOptions->readXml( layerNode.namedItem( QStringLiteral( "geometryOptions" ) ) );
2452
2453 if ( categories.testFlag( Forms ) )
2454 mEditFormConfig.readXml( layerNode, context );
2455
2456 if ( categories.testFlag( AttributeTable ) )
2457 {
2458 mAttributeTableConfig.readXml( layerNode );
2459 mConditionalStyles->readXml( layerNode, context );
2460 mStoredExpressionManager->readXml( layerNode );
2461 }
2462
2463 if ( categories.testFlag( CustomProperties ) )
2464 readCustomProperties( layerNode, QStringLiteral( "variable" ) );
2465
2466 QDomElement mapLayerNode = layerNode.toElement();
2467 if ( categories.testFlag( LayerConfiguration )
2468 && mapLayerNode.attribute( QStringLiteral( "readOnly" ), QStringLiteral( "0" ) ).toInt() == 1 )
2469 mReadOnly = true;
2470
2471 updateFields();
2472
2473 if ( categories.testFlag( Legend ) )
2474 {
2475 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Legend" ) );
2476
2477 const QDomElement legendElem = layerNode.firstChildElement( QStringLiteral( "legend" ) );
2478 if ( !legendElem.isNull() )
2479 {
2480 std::unique_ptr< QgsMapLayerLegend > legend( QgsMapLayerLegend::defaultVectorLegend( this ) );
2481 legend->readXml( legendElem, context );
2482 setLegend( legend.release() );
2483 mSetLegendFromStyle = true;
2484 }
2485 }
2486
2487 return true;
2488}
2489
2490bool QgsVectorLayer::readStyle( const QDomNode &node, QString &errorMessage,
2491 QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
2492{
2493 bool result = true;
2494 emit readCustomSymbology( node.toElement(), errorMessage );
2495
2496 // we must try to restore a renderer if our geometry type is unknown
2497 // as this allows the renderer to be correctly restored even for layers
2498 // with broken sources
2499 if ( isSpatial() || mWkbType == QgsWkbTypes::Unknown )
2500 {
2501 // defer style changed signal until we've set the renderer, labeling, everything.
2502 // we don't want multiple signals!
2503 ScopedIntIncrementor styleChangedSignalBlocker( &mBlockStyleChangedSignal );
2504
2505 // try renderer v2 first
2506 if ( categories.testFlag( Symbology ) )
2507 {
2508 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Symbology" ) );
2509
2510 QDomElement rendererElement = node.firstChildElement( RENDERER_TAG_NAME );
2511 if ( !rendererElement.isNull() )
2512 {
2513 QgsFeatureRenderer *r = QgsFeatureRenderer::load( rendererElement, context );
2514 if ( r )
2515 {
2516 setRenderer( r );
2517 }
2518 else
2519 {
2520 result = false;
2521 }
2522 }
2523 // make sure layer has a renderer - if none exists, fallback to a default renderer
2524 if ( isSpatial() && !renderer() )
2525 {
2527 }
2528 }
2529
2530 // read labeling definition
2531 if ( categories.testFlag( Labeling ) )
2532 {
2533 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Labeling" ) );
2534
2535 QDomElement labelingElement = node.firstChildElement( QStringLiteral( "labeling" ) );
2537 if ( labelingElement.isNull() ||
2538 ( labelingElement.attribute( QStringLiteral( "type" ) ) == QLatin1String( "simple" ) && labelingElement.firstChildElement( QStringLiteral( "settings" ) ).isNull() ) )
2539 {
2540 // make sure we have custom properties for labeling for 2.x projects
2541 // (custom properties should be already loaded when reading the whole layer from XML,
2542 // but when reading style, custom properties are not read)
2543 readCustomProperties( node, QStringLiteral( "labeling" ) );
2544
2545 // support for pre-QGIS 3 labeling configurations written in custom properties
2546 labeling = readLabelingFromCustomProperties();
2547 }
2548 else
2549 {
2550 labeling = QgsAbstractVectorLayerLabeling::create( labelingElement, context );
2551 }
2553
2554 if ( node.toElement().hasAttribute( QStringLiteral( "labelsEnabled" ) ) )
2555 mLabelsEnabled = node.toElement().attribute( QStringLiteral( "labelsEnabled" ) ).toInt();
2556 else
2557 mLabelsEnabled = true;
2558 }
2559
2560 if ( categories.testFlag( Symbology ) )
2561 {
2562 // get and set the blend mode if it exists
2563 QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
2564 if ( !blendModeNode.isNull() )
2565 {
2566 QDomElement e = blendModeNode.toElement();
2567 setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
2568 }
2569
2570 // get and set the feature blend mode if it exists
2571 QDomNode featureBlendModeNode = node.namedItem( QStringLiteral( "featureBlendMode" ) );
2572 if ( !featureBlendModeNode.isNull() )
2573 {
2574 QDomElement e = featureBlendModeNode.toElement();
2575 setFeatureBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
2576 }
2577 }
2578
2579 // get and set the layer transparency and scale visibility if they exists
2580 if ( categories.testFlag( Rendering ) )
2581 {
2582 QDomNode layerTransparencyNode = node.namedItem( QStringLiteral( "layerTransparency" ) );
2583 if ( !layerTransparencyNode.isNull() )
2584 {
2585 QDomElement e = layerTransparencyNode.toElement();
2586 setOpacity( 1.0 - e.text().toInt() / 100.0 );
2587 }
2588 QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
2589 if ( !layerOpacityNode.isNull() )
2590 {
2591 QDomElement e = layerOpacityNode.toElement();
2592 setOpacity( e.text().toDouble() );
2593 }
2594
2595 const bool hasScaleBasedVisibiliy { node.attributes().namedItem( QStringLiteral( "hasScaleBasedVisibilityFlag" ) ).nodeValue() == '1' };
2596 setScaleBasedVisibility( hasScaleBasedVisibiliy );
2597 bool ok;
2598 const double maxScale { node.attributes().namedItem( QStringLiteral( "maxScale" ) ).nodeValue().toDouble( &ok ) };
2599 if ( ok )
2600 {
2601 setMaximumScale( maxScale );
2602 }
2603 const double minScale { node.attributes().namedItem( QStringLiteral( "minScale" ) ).nodeValue().toDouble( &ok ) };
2604 if ( ok )
2605 {
2606 setMinimumScale( minScale );
2607 }
2608
2609 QDomElement e = node.toElement();
2610
2611 // get the simplification drawing settings
2612 mSimplifyMethod.setSimplifyHints( static_cast< QgsVectorSimplifyMethod::SimplifyHints >( e.attribute( QStringLiteral( "simplifyDrawingHints" ), QStringLiteral( "1" ) ).toInt() ) );
2613 mSimplifyMethod.setSimplifyAlgorithm( static_cast< QgsVectorSimplifyMethod::SimplifyAlgorithm >( e.attribute( QStringLiteral( "simplifyAlgorithm" ), QStringLiteral( "0" ) ).toInt() ) );
2614 mSimplifyMethod.setThreshold( e.attribute( QStringLiteral( "simplifyDrawingTol" ), QStringLiteral( "1" ) ).toFloat() );
2615 mSimplifyMethod.setForceLocalOptimization( e.attribute( QStringLiteral( "simplifyLocal" ), QStringLiteral( "1" ) ).toInt() );
2616 mSimplifyMethod.setMaximumScale( e.attribute( QStringLiteral( "simplifyMaxScale" ), QStringLiteral( "1" ) ).toFloat() );
2617
2618 if ( mRenderer )
2619 mRenderer->setReferenceScale( e.attribute( QStringLiteral( "symbologyReferenceScale" ), QStringLiteral( "-1" ) ).toDouble() );
2620 }
2621
2622 //diagram renderer and diagram layer settings
2623 if ( categories.testFlag( Diagrams ) )
2624 {
2625 QgsReadWriteContextCategoryPopper p = context.enterCategory( tr( "Diagrams" ) );
2626
2627 delete mDiagramRenderer;
2628 mDiagramRenderer = nullptr;
2629 QDomElement singleCatDiagramElem = node.firstChildElement( QStringLiteral( "SingleCategoryDiagramRenderer" ) );
2630 if ( !singleCatDiagramElem.isNull() )
2631 {
2632 mDiagramRenderer = new QgsSingleCategoryDiagramRenderer();
2633 mDiagramRenderer->readXml( singleCatDiagramElem, context );
2634 }
2635 QDomElement linearDiagramElem = node.firstChildElement( QStringLiteral( "LinearlyInterpolatedDiagramRenderer" ) );
2636 if ( !linearDiagramElem.isNull() )
2637 {
2638 if ( linearDiagramElem.hasAttribute( QStringLiteral( "classificationAttribute" ) ) )
2639 {
2640 // fix project from before QGIS 3.0
2641 int idx = linearDiagramElem.attribute( QStringLiteral( "classificationAttribute" ) ).toInt();
2642 if ( idx >= 0 && idx < mFields.count() )
2643 linearDiagramElem.setAttribute( QStringLiteral( "classificationField" ), mFields.at( idx ).name() );
2644 }
2645
2646 mDiagramRenderer = new QgsLinearlyInterpolatedDiagramRenderer();
2647 mDiagramRenderer->readXml( linearDiagramElem, context );
2648 }
2649
2650 if ( mDiagramRenderer )
2651 {
2652 QDomElement diagramSettingsElem = node.firstChildElement( QStringLiteral( "DiagramLayerSettings" ) );
2653 if ( !diagramSettingsElem.isNull() )
2654 {
2655 bool oldXPos = diagramSettingsElem.hasAttribute( QStringLiteral( "xPosColumn" ) );
2656 bool oldYPos = diagramSettingsElem.hasAttribute( QStringLiteral( "yPosColumn" ) );
2657 bool oldShow = diagramSettingsElem.hasAttribute( QStringLiteral( "showColumn" ) );
2658 if ( oldXPos || oldYPos || oldShow )
2659 {
2660 // fix project from before QGIS 3.0
2662 if ( oldXPos )
2663 {
2664 int xPosColumn = diagramSettingsElem.attribute( QStringLiteral( "xPosColumn" ) ).toInt();
2665 if ( xPosColumn >= 0 && xPosColumn < mFields.count() )
2666 ddp.setProperty( QgsDiagramLayerSettings::PositionX, QgsProperty::fromField( mFields.at( xPosColumn ).name(), true ) );
2667 }
2668 if ( oldYPos )
2669 {
2670 int yPosColumn = diagramSettingsElem.attribute( QStringLiteral( "yPosColumn" ) ).toInt();
2671 if ( yPosColumn >= 0 && yPosColumn < mFields.count() )
2672 ddp.setProperty( QgsDiagramLayerSettings::PositionY, QgsProperty::fromField( mFields.at( yPosColumn ).name(), true ) );
2673 }
2674 if ( oldShow )
2675 {
2676 int showColumn = diagramSettingsElem.attribute( QStringLiteral( "showColumn" ) ).toInt();
2677 if ( showColumn >= 0 && showColumn < mFields.count() )
2678 ddp.setProperty( QgsDiagramLayerSettings::Show, QgsProperty::fromField( mFields.at( showColumn ).name(), true ) );
2679 }
2680 QDomElement propertiesElem = diagramSettingsElem.ownerDocument().createElement( QStringLiteral( "properties" ) );
2682 {
2683 { QgsDiagramLayerSettings::PositionX, QgsPropertyDefinition( "positionX", QObject::tr( "Position (X)" ), QgsPropertyDefinition::Double ) },
2684 { QgsDiagramLayerSettings::PositionY, QgsPropertyDefinition( "positionY", QObject::tr( "Position (Y)" ), QgsPropertyDefinition::Double ) },
2685 { QgsDiagramLayerSettings::Show, QgsPropertyDefinition( "show", QObject::tr( "Show diagram" ), QgsPropertyDefinition::Boolean ) },
2686 };
2687 ddp.writeXml( propertiesElem, defs );
2688 diagramSettingsElem.appendChild( propertiesElem );
2689 }
2690
2691 delete mDiagramLayerSettings;
2692 mDiagramLayerSettings = new QgsDiagramLayerSettings();
2693 mDiagramLayerSettings->readXml( diagramSettingsElem );
2694 }
2695 }
2696 }
2697 // end diagram
2698
2699 styleChangedSignalBlocker.release();
2701 }
2702 return result;
2703}
2704
2705
2706bool QgsVectorLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage,
2707 const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2708{
2709 QDomElement layerElement = node.toElement();
2710 writeCommonStyle( layerElement, doc, context, categories );
2711
2712 ( void )writeStyle( node, doc, errorMessage, context, categories );
2713
2714 if ( categories.testFlag( GeometryOptions ) )
2715 mGeometryOptions->writeXml( node );
2716
2717 if ( categories.testFlag( Legend ) && legend() )
2718 {
2719 QDomElement legendElement = legend()->writeXml( doc, context );
2720 if ( !legendElement.isNull() )
2721 node.appendChild( legendElement );
2722 }
2723
2724 // Relation information for both referenced and referencing sides
2725 if ( categories.testFlag( Relations ) )
2726 {
2727 // Store referenced layers: relations where "this" is the child layer (the referencing part, that holds the FK)
2728 QDomElement referencedLayersElement = doc.createElement( QStringLiteral( "referencedLayers" ) );
2729 node.appendChild( referencedLayersElement );
2730
2731 const QList<QgsRelation> referencingRelations { QgsProject::instance()->relationManager()->referencingRelations( this ) };
2732 for ( const QgsRelation &rel : referencingRelations )
2733 {
2734 switch ( rel.type() )
2735 {
2737 QgsWeakRelation::writeXml( this, QgsWeakRelation::Referencing, rel, referencedLayersElement, doc );
2738 break;
2740 break;
2741 }
2742 }
2743
2744 // Store referencing layers: relations where "this" is the parent layer (the referenced part, that holds the FK)
2745 QDomElement referencingLayersElement = doc.createElement( QStringLiteral( "referencingLayers" ) );
2746 node.appendChild( referencedLayersElement );
2747
2748 const QList<QgsRelation> referencedRelations { QgsProject::instance()->relationManager()->referencedRelations( this ) };
2749 for ( const QgsRelation &rel : referencedRelations )
2750 {
2751 switch ( rel.type() )
2752 {
2754 QgsWeakRelation::writeXml( this, QgsWeakRelation::Referenced, rel, referencingLayersElement, doc );
2755 break;
2757 break;
2758 }
2759 }
2760 }
2761
2762 // write field configurations
2763 if ( categories.testFlag( Fields ) || categories.testFlag( Forms ) )
2764 {
2765 QDomElement fieldConfigurationElement;
2766 // field configuration flag
2767 fieldConfigurationElement = doc.createElement( QStringLiteral( "fieldConfiguration" ) );
2768 node.appendChild( fieldConfigurationElement );
2769
2770 for ( const QgsField &field : std::as_const( mFields ) )
2771 {
2772 QDomElement fieldElement = doc.createElement( QStringLiteral( "field" ) );
2773 fieldElement.setAttribute( QStringLiteral( "name" ), field.name() );
2774 fieldConfigurationElement.appendChild( fieldElement );
2775
2776 if ( categories.testFlag( Fields ) )
2777 {
2778 fieldElement.setAttribute( QStringLiteral( "configurationFlags" ), qgsFlagValueToKeys( field.configurationFlags() ) );
2779 }
2780
2781 if ( categories.testFlag( Forms ) )
2782 {
2784
2785 // TODO : wrap this part in an if to only save if it was user-modified
2786 QDomElement editWidgetElement = doc.createElement( QStringLiteral( "editWidget" ) );
2787 fieldElement.appendChild( editWidgetElement );
2788 editWidgetElement.setAttribute( QStringLiteral( "type" ), field.editorWidgetSetup().type() );
2789 QDomElement editWidgetConfigElement = doc.createElement( QStringLiteral( "config" ) );
2790
2791 editWidgetConfigElement.appendChild( QgsXmlUtils::writeVariant( widgetSetup.config(), doc ) );
2792 editWidgetElement.appendChild( editWidgetConfigElement );
2793 // END TODO : wrap this part in an if to only save if it was user-modified
2794 }
2795 }
2796 }
2797
2798 if ( categories.testFlag( Fields ) )
2799 {
2800 //attribute aliases
2801 QDomElement aliasElem = doc.createElement( QStringLiteral( "aliases" ) );
2802 for ( const QgsField &field : std::as_const( mFields ) )
2803 {
2804 QDomElement aliasEntryElem = doc.createElement( QStringLiteral( "alias" ) );
2805 aliasEntryElem.setAttribute( QStringLiteral( "field" ), field.name() );
2806 aliasEntryElem.setAttribute( QStringLiteral( "index" ), mFields.indexFromName( field.name() ) );
2807 aliasEntryElem.setAttribute( QStringLiteral( "name" ), field.alias() );
2808 aliasElem.appendChild( aliasEntryElem );
2809 }
2810 node.appendChild( aliasElem );
2811
2812 //default expressions
2813 QDomElement defaultsElem = doc.createElement( QStringLiteral( "defaults" ) );
2814 for ( const QgsField &field : std::as_const( mFields ) )
2815 {
2816 QDomElement defaultElem = doc.createElement( QStringLiteral( "default" ) );
2817 defaultElem.setAttribute( QStringLiteral( "field" ), field.name() );
2818 defaultElem.setAttribute( QStringLiteral( "expression" ), field.defaultValueDefinition().expression() );
2819 defaultElem.setAttribute( QStringLiteral( "applyOnUpdate" ), field.defaultValueDefinition().applyOnUpdate() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
2820 defaultsElem.appendChild( defaultElem );
2821 }
2822 node.appendChild( defaultsElem );
2823
2824 // constraints
2825 QDomElement constraintsElem = doc.createElement( QStringLiteral( "constraints" ) );
2826 for ( const QgsField &field : std::as_const( mFields ) )
2827 {
2828 QDomElement constraintElem = doc.createElement( QStringLiteral( "constraint" ) );
2829 constraintElem.setAttribute( QStringLiteral( "field" ), field.name() );
2830 constraintElem.setAttribute( QStringLiteral( "constraints" ), field.constraints().constraints() );
2831 constraintElem.setAttribute( QStringLiteral( "unique_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) );
2832 constraintElem.setAttribute( QStringLiteral( "notnull_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) );
2833 constraintElem.setAttribute( QStringLiteral( "exp_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );
2834 constraintsElem.appendChild( constraintElem );
2835 }
2836 node.appendChild( constraintsElem );
2837
2838 // constraint expressions
2839 QDomElement constraintExpressionsElem = doc.createElement( QStringLiteral( "constraintExpressions" ) );
2840 for ( const QgsField &field : std::as_const( mFields ) )
2841 {
2842 QDomElement constraintExpressionElem = doc.createElement( QStringLiteral( "constraint" ) );
2843 constraintExpressionElem.setAttribute( QStringLiteral( "field" ), field.name() );
2844 constraintExpressionElem.setAttribute( QStringLiteral( "exp" ), field.constraints().constraintExpression() );
2845 constraintExpressionElem.setAttribute( QStringLiteral( "desc" ), field.constraints().constraintDescription() );
2846 constraintExpressionsElem.appendChild( constraintExpressionElem );
2847 }
2848 node.appendChild( constraintExpressionsElem );
2849
2850 // save expression fields
2851 if ( !mExpressionFieldBuffer )
2852 {
2853 // can happen when saving style on a invalid layer
2855 dummy.writeXml( node, doc );
2856 }
2857 else
2858 {
2859 mExpressionFieldBuffer->writeXml( node, doc );
2860 }
2861 }
2862
2863 // add attribute actions
2864 if ( categories.testFlag( Actions ) )
2865 mActions->writeXml( node );
2866
2867 if ( categories.testFlag( AttributeTable ) )
2868 {
2869 mAttributeTableConfig.writeXml( node );
2870 mConditionalStyles->writeXml( node, doc, context );
2871 mStoredExpressionManager->writeXml( node );
2872 }
2873
2874 if ( categories.testFlag( Forms ) )
2875 mEditFormConfig.writeXml( node, context );
2876
2877 // save readonly state
2878 if ( categories.testFlag( LayerConfiguration ) )
2879 node.toElement().setAttribute( QStringLiteral( "readOnly" ), mReadOnly );
2880
2881 // save preview expression
2882 if ( categories.testFlag( LayerConfiguration ) )
2883 {
2884 QDomElement prevExpElem = doc.createElement( QStringLiteral( "previewExpression" ) );
2885 QDomText prevExpText = doc.createTextNode( mDisplayExpression );
2886 prevExpElem.appendChild( prevExpText );
2887 node.appendChild( prevExpElem );
2888 }
2889
2890 // save map tip
2891 if ( categories.testFlag( MapTips ) )
2892 {
2893 QDomElement mapTipElem = doc.createElement( QStringLiteral( "mapTip" ) );
2894 QDomText mapTipText = doc.createTextNode( mMapTipTemplate );
2895 mapTipElem.appendChild( mapTipText );
2896 node.toElement().appendChild( mapTipElem );
2897 }
2898
2899 return true;
2900}
2901
2902bool QgsVectorLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage,
2903 const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
2904{
2905 QDomElement mapLayerNode = node.toElement();
2906
2907 emit writeCustomSymbology( mapLayerNode, doc, errorMessage );
2908
2909 // we must try to write the renderer if our geometry type is unknown
2910 // as this allows the renderer to be correctly restored even for layers
2911 // with broken sources
2912 if ( isSpatial() || mWkbType == QgsWkbTypes::Unknown )
2913 {
2914 if ( categories.testFlag( Symbology ) )
2915 {
2916 if ( mRenderer )
2917 {
2918 QDomElement rendererElement = mRenderer->save( doc, context );
2919 node.appendChild( rendererElement );
2920 }
2921 }
2922
2923 if ( categories.testFlag( Labeling ) )
2924 {
2925 if ( mLabeling )
2926 {
2927 QDomElement labelingElement = mLabeling->save( doc, context );
2928 node.appendChild( labelingElement );
2929 }
2930 mapLayerNode.setAttribute( QStringLiteral( "labelsEnabled" ), mLabelsEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
2931 }
2932
2933 // save the simplification drawing settings
2934 if ( categories.testFlag( Rendering ) )
2935 {
2936 mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingHints" ), QString::number( mSimplifyMethod.simplifyHints() ) );
2937 mapLayerNode.setAttribute( QStringLiteral( "simplifyAlgorithm" ), QString::number( mSimplifyMethod.simplifyAlgorithm() ) );
2938 mapLayerNode.setAttribute( QStringLiteral( "simplifyDrawingTol" ), QString::number( mSimplifyMethod.threshold() ) );
2939 mapLayerNode.setAttribute( QStringLiteral( "simplifyLocal" ), mSimplifyMethod.forceLocalOptimization() ? 1 : 0 );
2940 mapLayerNode.setAttribute( QStringLiteral( "simplifyMaxScale" ), QString::number( mSimplifyMethod.maximumScale() ) );
2941 }
2942
2943 //save customproperties
2944 if ( categories.testFlag( CustomProperties ) )
2945 {
2946 writeCustomProperties( node, doc );
2947 }
2948
2949 if ( categories.testFlag( Symbology ) )
2950 {
2951 // add the blend mode field
2952 QDomElement blendModeElem = doc.createElement( QStringLiteral( "blendMode" ) );
2953 QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
2954 blendModeElem.appendChild( blendModeText );
2955 node.appendChild( blendModeElem );
2956
2957 // add the feature blend mode field
2958 QDomElement featureBlendModeElem = doc.createElement( QStringLiteral( "featureBlendMode" ) );
2959 QDomText featureBlendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( featureBlendMode() ) ) );
2960 featureBlendModeElem.appendChild( featureBlendModeText );
2961 node.appendChild( featureBlendModeElem );
2962 }
2963
2964 // add the layer opacity and scale visibility
2965 if ( categories.testFlag( Rendering ) )
2966 {
2967 QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
2968 QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
2969 layerOpacityElem.appendChild( layerOpacityText );
2970 node.appendChild( layerOpacityElem );
2971 mapLayerNode.setAttribute( QStringLiteral( "hasScaleBasedVisibilityFlag" ), hasScaleBasedVisibility() ? 1 : 0 );
2972 mapLayerNode.setAttribute( QStringLiteral( "maxScale" ), maximumScale() );
2973 mapLayerNode.setAttribute( QStringLiteral( "minScale" ), minimumScale() );
2974
2975 mapLayerNode.setAttribute( QStringLiteral( "symbologyReferenceScale" ), mRenderer ? mRenderer->referenceScale() : -1 );
2976 }
2977
2978 if ( categories.testFlag( Diagrams ) && mDiagramRenderer )
2979 {
2980 mDiagramRenderer->writeXml( mapLayerNode, doc, context );
2981 if ( mDiagramLayerSettings )
2982 mDiagramLayerSettings->writeXml( mapLayerNode, doc );
2983 }
2984 }
2985 return true;
2986}
2987
2988bool QgsVectorLayer::readSld( const QDomNode &node, QString &errorMessage )
2989{
2990 // get the Name element
2991 QDomElement nameElem = node.firstChildElement( QStringLiteral( "Name" ) );
2992 if ( nameElem.isNull() )
2993 {
2994 errorMessage = QStringLiteral( "Warning: Name element not found within NamedLayer while it's required." );
2995 }
2996
2997 if ( isSpatial() )
2998 {
2999 QgsFeatureRenderer *r = QgsFeatureRenderer::loadSld( node, geometryType(), errorMessage );
3000 if ( !r )
3001 return false;
3002
3003 // defer style changed signal until we've set the renderer, labeling, everything.
3004 // we don't want multiple signals!
3005 ScopedIntIncrementor styleChangedSignalBlocker( &mBlockStyleChangedSignal );
3006
3007 setRenderer( r );
3008
3009 // labeling
3010 readSldLabeling( node );
3011
3012 styleChangedSignalBlocker.release();
3014 }
3015 return true;
3016}
3017
3018bool QgsVectorLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QVariantMap &props ) const
3019{
3020 Q_UNUSED( errorMessage )
3021
3022 QVariantMap localProps = QVariantMap( props );
3024 {
3026 }
3027
3028 if ( isSpatial() )
3029 {
3030 // store the Name element
3031 QDomElement nameNode = doc.createElement( QStringLiteral( "se:Name" ) );
3032 nameNode.appendChild( doc.createTextNode( name() ) );
3033 node.appendChild( nameNode );
3034
3035 QDomElement userStyleElem = doc.createElement( QStringLiteral( "UserStyle" ) );
3036 node.appendChild( userStyleElem );
3037
3038 QDomElement nameElem = doc.createElement( QStringLiteral( "se:Name" ) );
3039 nameElem.appendChild( doc.createTextNode( name() ) );
3040
3041 userStyleElem.appendChild( nameElem );
3042
3043 QDomElement featureTypeStyleElem = doc.createElement( QStringLiteral( "se:FeatureTypeStyle" ) );
3044 userStyleElem.appendChild( featureTypeStyleElem );
3045
3046 mRenderer->toSld( doc, featureTypeStyleElem, localProps );
3047 if ( labelsEnabled() )
3048 {
3049 mLabeling->toSld( featureTypeStyleElem, localProps );
3050 }
3051 }
3052 return true;
3053}
3054
3055
3056bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, QgsGeometry &geom, bool skipDefaultValue )
3057{
3058 if ( !mEditBuffer || !mDataProvider )
3059 {
3060 return false;
3061 }
3062
3063 if ( mGeometryOptions->isActive() )
3064 mGeometryOptions->apply( geom );
3065
3066 updateExtents();
3067
3068 bool result = mEditBuffer->changeGeometry( fid, geom );
3069
3070 if ( result )
3071 {
3072 updateExtents();
3073 if ( !skipDefaultValue && !mDefaultValueOnUpdateFields.isEmpty() )
3074 updateDefaultValues( fid );
3075 }
3076 return result;
3077}
3078
3079
3080bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue, bool skipDefaultValues )
3081{
3082 bool result = false;
3083
3084 switch ( fields().fieldOrigin( field ) )
3085 {
3087 result = mJoinBuffer->changeAttributeValue( fid, field, newValue, oldValue );
3088 if ( result )
3089 emit attributeValueChanged( fid, field, newValue );
3090 break;
3091
3095 {
3096 if ( mEditBuffer && mDataProvider )
3097 result = mEditBuffer->changeAttributeValue( fid, field, newValue, oldValue );
3098 break;
3099 }
3100
3102 break;
3103 }
3104
3105 if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
3106 updateDefaultValues( fid );
3107
3108 return result;
3109}
3110
3111bool QgsVectorLayer::changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues, bool skipDefaultValues )
3112{
3113 bool result = true;
3114
3115 QgsAttributeMap newValuesJoin;
3116 QgsAttributeMap oldValuesJoin;
3117
3118 QgsAttributeMap newValuesNotJoin;
3119 QgsAttributeMap oldValuesNotJoin;
3120
3121 for ( auto it = newValues.constBegin(); it != newValues.constEnd(); ++it )
3122 {
3123 const int field = it.key();
3124 const QVariant newValue = it.value();
3125 QVariant oldValue;
3126
3127 if ( oldValues.contains( field ) )
3128 oldValue = oldValues[field];
3129
3130 switch ( fields().fieldOrigin( field ) )
3131 {
3133 newValuesJoin[field] = newValue;
3134 oldValuesJoin[field] = oldValue;
3135 break;
3136
3140 {
3141 newValuesNotJoin[field] = newValue;
3142 oldValuesNotJoin[field] = oldValue;
3143 break;
3144 }
3145
3147 break;
3148 }
3149 }
3150
3151 if ( ! newValuesJoin.isEmpty() && mJoinBuffer )
3152 {
3153 result = mJoinBuffer->changeAttributeValues( fid, newValuesJoin, oldValuesJoin );
3154 }
3155
3156 if ( ! newValuesNotJoin.isEmpty() && mEditBuffer && mDataProvider )
3157 {
3158 result &= mEditBuffer->changeAttributeValues( fid, newValuesNotJoin, oldValues );
3159 }
3160
3161 if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
3162 {
3163 updateDefaultValues( fid );
3164 }
3165
3166 return result;
3167}
3168
3170{
3171 if ( !mEditBuffer || !mDataProvider )
3172 return false;
3173
3174 return mEditBuffer->addAttribute( field );
3175}
3176
3178{
3179 if ( attIndex < 0 || attIndex >= fields().count() )
3180 return;
3181
3182 QString name = fields().at( attIndex ).name();
3183 mFields[ attIndex ].setAlias( QString() );
3184 if ( mAttributeAliasMap.contains( name ) )
3185 {
3186 mAttributeAliasMap.remove( name );
3187 updateFields();
3188 mEditFormConfig.setFields( mFields );
3189 emit layerModified();
3190 }
3191}
3192
3193bool QgsVectorLayer::renameAttribute( int index, const QString &newName )
3194{
3195 if ( index < 0 || index >= fields().count() )
3196 return false;
3197
3198 switch ( mFields.fieldOrigin( index ) )
3199 {
3201 {
3202 if ( mExpressionFieldBuffer )
3203 {
3204 int oi = mFields.fieldOriginIndex( index );
3205 mExpressionFieldBuffer->renameExpression( oi, newName );
3206 updateFields();
3207 return true;
3208 }
3209 else
3210 {
3211 return false;
3212 }
3213 }
3214
3217
3218 if ( !mEditBuffer || !mDataProvider )
3219 return false;
3220
3221 return mEditBuffer->renameAttribute( index, newName );
3222
3225 return false;
3226
3227 }
3228
3229 return false; // avoid warning
3230}
3231
3232void QgsVectorLayer::setFieldAlias( int attIndex, const QString &aliasString )
3233{
3234 if ( attIndex < 0 || attIndex >= fields().count() )
3235 return;
3236
3237 QString name = fields().at( attIndex ).name();
3238
3239 mAttributeAliasMap.insert( name, aliasString );
3240 mFields[ attIndex ].setAlias( aliasString );
3241 mEditFormConfig.setFields( mFields );
3242 emit layerModified(); // TODO[MD]: should have a different signal?
3243}
3244
3245QString QgsVectorLayer::attributeAlias( int index ) const
3246{
3247 if ( index < 0 || index >= fields().count() )
3248 return QString();
3249
3250 return fields().at( index ).alias();
3251}
3252
3254{
3255 if ( index >= 0 && index < mFields.count() )
3256 return mFields.at( index ).displayName();
3257 else
3258 return QString();
3259}
3260
3262{
3263 return mAttributeAliasMap;
3264}
3265
3267{
3268 QSet<QString> excludeList;
3269 QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
3270 for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
3271 {
3272 if ( flagsIt->testFlag( QgsField::ConfigurationFlag::HideFromWms ) )
3273 {
3274 excludeList << flagsIt.key();
3275 }
3276 }
3277 return excludeList;
3278}
3279
3280void QgsVectorLayer::setExcludeAttributesWms( const QSet<QString> &att )
3281{
3282 QMap< QString, QgsField::ConfigurationFlags >::iterator flagsIt = mFieldConfigurationFlags.begin();
3283 for ( ; flagsIt != mFieldConfigurationFlags.end(); ++flagsIt )
3284 {
3285 flagsIt->setFlag( QgsField::ConfigurationFlag::HideFromWms, att.contains( flagsIt.key() ) );
3286 }
3287 updateFields();
3288}
3289
3291{
3292 QSet<QString> excludeList;
3293 QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
3294 for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
3295 {
3296 if ( flagsIt->testFlag( QgsField::ConfigurationFlag::HideFromWfs ) )
3297 {
3298 excludeList << flagsIt.key();
3299 }
3300 }
3301 return excludeList;
3302}
3303
3304void QgsVectorLayer::setExcludeAttributesWfs( const QSet<QString> &att )
3305{
3306 QMap< QString, QgsField::ConfigurationFlags >::iterator flagsIt = mFieldConfigurationFlags.begin();
3307 for ( ; flagsIt != mFieldConfigurationFlags.end(); ++flagsIt )
3308 {
3309 flagsIt->setFlag( QgsField::ConfigurationFlag::HideFromWfs, att.contains( flagsIt.key() ) );
3310 }
3311 updateFields();
3312}
3313
3315{
3316 if ( index < 0 || index >= fields().count() )
3317 return false;
3318
3319 if ( mFields.fieldOrigin( index ) == QgsFields::OriginExpression )
3320 {
3321 removeExpressionField( index );
3322 return true;
3323 }
3324
3325 if ( !mEditBuffer || !mDataProvider )
3326 return false;
3327
3328 return mEditBuffer->deleteAttribute( index );
3329}
3330
3331bool QgsVectorLayer::deleteAttributes( const QList<int> &attrs )
3332{
3333 bool deleted = false;
3334
3335 // Remove multiple occurrences of same attribute
3336 QList<int> attrList = qgis::setToList( qgis::listToSet( attrs ) );
3337
3338 std::sort( attrList.begin(), attrList.end(), std::greater<int>() );
3339
3340 for ( int attr : std::as_const( attrList ) )
3341 {
3342 if ( deleteAttribute( attr ) )
3343 {
3344 deleted = true;
3345 }
3346 }
3347
3348 return deleted;
3349}
3350
3351bool QgsVectorLayer::deleteFeatureCascade( QgsFeatureId fid, QgsVectorLayer::DeleteContext *context )
3352{
3353 if ( !mEditBuffer )
3354 return false;
3355
3356 if ( context && context->cascade )
3357 {
3358 const QList<QgsRelation> relations = context->project->relationManager()->referencedRelations( this );
3359 const bool hasRelationsOrJoins = !relations.empty() || mJoinBuffer->containsJoins();
3360 if ( hasRelationsOrJoins )
3361 {
3362 if ( context->mHandledFeatures.contains( this ) )
3363 {
3364 QgsFeatureIds &handledFeatureIds = context->mHandledFeatures[ this ];
3365 if ( handledFeatureIds.contains( fid ) )
3366 {
3367 // avoid endless recursion
3368 return false;
3369 }
3370 else
3371 {
3372 // add feature id
3373 handledFeatureIds << fid;
3374 }
3375 }
3376 else
3377 {
3378 // add layer and feature id
3379 context->mHandledFeatures.insert( this, QgsFeatureIds() << fid );
3380 }
3381
3382 for ( const QgsRelation &relation : relations )
3383 {
3384 //check if composition (and not association)
3385 switch ( relation.strength() )
3386 {
3388 {
3389 //get features connected over this relation
3390 QgsFeatureIterator relatedFeaturesIt = relation.getRelatedFeatures( getFeature( fid ) );
3391 QgsFeatureIds childFeatureIds;
3392 QgsFeature childFeature;
3393 while ( relatedFeaturesIt.nextFeature( childFeature ) )
3394 {
3395 childFeatureIds.insert( childFeature.id() );
3396 }
3397 if ( childFeatureIds.count() > 0 )
3398 {
3399 relation.referencingLayer()->startEditing();
3400 relation.referencingLayer()->deleteFeatures( childFeatureIds, context );
3401 }
3402 break;
3403 }
3404
3406 break;
3407 }
3408 }
3409 }
3410 }
3411
3412 if ( mJoinBuffer->containsJoins() )
3413 mJoinBuffer->deleteFeature( fid, context );
3414
3415 bool res = mEditBuffer->deleteFeature( fid );
3416
3417 return res;
3418}
3419
3421{
3422 if ( !mEditBuffer )
3423 return false;
3424
3425 bool res = deleteFeatureCascade( fid, context );
3426
3427 if ( res )
3428 {
3429 updateExtents();
3430 }
3431
3432 return res;
3433}
3434
3436{
3437 bool res = true;
3438 const auto constFids = fids;
3439 for ( QgsFeatureId fid : constFids )
3440 res = deleteFeatureCascade( fid, context ) && res;
3441
3442 if ( res )
3443 {
3444 mSelectedFeatureIds.subtract( fids ); // remove it from selection
3445 updateExtents();
3446 }
3447
3448 return res;
3449}
3450
3452{
3453 return mFields;
3454}
3455
3457{
3458 QgsAttributeList pkAttributesList;
3459 if ( !mDataProvider )
3460 return pkAttributesList;
3461
3462 QgsAttributeList providerIndexes = mDataProvider->pkAttributeIndexes();
3463 for ( int i = 0; i < mFields.count(); ++i )
3464 {
3465 if ( mFields.fieldOrigin( i ) == QgsFields::OriginProvider &&
3466 providerIndexes.contains( mFields.fieldOriginIndex( i ) ) )
3467 pkAttributesList << i;
3468 }
3469
3470 return pkAttributesList;
3471}
3472
3474{
3475 if ( !mDataProvider )
3476 return static_cast< long long >( Qgis::FeatureCountState::UnknownCount );
3477 return mDataProvider->featureCount() +
3478 ( mEditBuffer && ! mDataProvider->transaction() ? mEditBuffer->addedFeatures().size() - mEditBuffer->deletedFeatureIds().size() : 0 );
3479}
3480
3482{
3483 const QgsFeatureIds deletedFeatures( mEditBuffer && ! mDataProvider->transaction() ? mEditBuffer->deletedFeatureIds() : QgsFeatureIds() );
3484 const QgsFeatureMap addedFeatures( mEditBuffer && ! mDataProvider->transaction() ? mEditBuffer->addedFeatures() : QgsFeatureMap() );
3485
3486 if ( mEditBuffer && !deletedFeatures.empty() )
3487 {
3488 if ( addedFeatures.size() > deletedFeatures.size() )
3489 return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
3490 else
3491 return QgsFeatureSource::FeatureAvailability::FeaturesMaybeAvailable;
3492 }
3493
3494 if ( ( !mEditBuffer || addedFeatures.empty() ) && mDataProvider && mDataProvider->empty() )
3495 return QgsFeatureSource::FeatureAvailability::NoFeaturesAvailable;
3496 else
3497 return QgsFeatureSource::FeatureAvailability::FeaturesAvailable;
3498}
3499
3500bool QgsVectorLayer::commitChanges( bool stopEditing )
3501{
3502 if ( project() && project()->transactionMode() == Qgis::TransactionMode::BufferedGroups )
3503 return project()->commitChanges( mCommitErrors, stopEditing, this );
3504
3505 mCommitErrors.clear();
3506
3507 if ( !mDataProvider )
3508 {
3509 mCommitErrors << tr( "ERROR: no provider" );
3510 return false;
3511 }
3512
3513 if ( !mEditBuffer )
3514 {
3515 mCommitErrors << tr( "ERROR: layer not editable" );
3516 return false;
3517 }
3518
3519 emit beforeCommitChanges( stopEditing );
3520
3521 if ( !mAllowCommit )
3522 return false;
3523
3524 mCommitChangesActive = true;
3525
3526 bool success = false;
3527 if ( mEditBuffer->editBufferGroup() )
3528 success = mEditBuffer->editBufferGroup()->commitChanges( mCommitErrors, stopEditing );
3529 else
3530 success = mEditBuffer->commitChanges( mCommitErrors );
3531
3532 mCommitChangesActive = false;
3533
3534 if ( !mDeletedFids.empty() )
3535 {
3536 emit featuresDeleted( mDeletedFids );
3537 mDeletedFids.clear();
3538 }
3539
3540 if ( success )
3541 {
3542 if ( stopEditing )
3543 {
3544 clearEditBuffer();
3545 }
3546 undoStack()->clear();
3547 emit afterCommitChanges();
3548 if ( stopEditing )
3549 emit editingStopped();
3550 }
3551 else
3552 {
3553 QgsMessageLog::logMessage( tr( "Commit errors:\n %1" ).arg( mCommitErrors.join( QLatin1String( "\n " ) ) ) );
3554 }
3555
3556 updateFields();
3557
3558 mDataProvider->updateExtents();
3559 mDataProvider->leaveUpdateMode();
3560
3561 // This second call is required because OGR provider with JSON
3562 // driver might have changed fields order after the call to
3563 // leaveUpdateMode
3564 if ( mFields.names() != mDataProvider->fields().names() )
3565 {
3566 updateFields();
3567 }
3568
3570
3571 return success;
3572}
3573
3575{
3576 return mCommitErrors;
3577}
3578
3579bool QgsVectorLayer::rollBack( bool deleteBuffer )
3580{
3581 if ( project() && project()->transactionMode() == Qgis::TransactionMode::BufferedGroups )
3582 return project()->rollBack( mCommitErrors, deleteBuffer, this );
3583
3584 if ( !mEditBuffer )
3585 {
3586 return false;
3587 }
3588
3589 if ( !mDataProvider )
3590 {
3591 mCommitErrors << tr( "ERROR: no provider" );
3592 return false;
3593 }
3594
3595 bool rollbackExtent = !mDataProvider->transaction() && ( !mEditBuffer->deletedFeatureIds().isEmpty() ||
3596 !mEditBuffer->addedFeatures().isEmpty() ||
3597 !mEditBuffer->changedGeometries().isEmpty() );
3598
3599 emit beforeRollBack();
3600
3601 mEditBuffer->rollBack();
3602
3603 emit afterRollBack();
3604
3605 if ( isModified() )
3606 {
3607 // new undo stack roll back method
3608 // old method of calling every undo could cause many canvas refreshes
3609 undoStack()->setIndex( 0 );
3610 }
3611
3612 updateFields();
3613
3614 if ( deleteBuffer )
3615 {
3616 delete mEditBuffer;
3617 mEditBuffer = nullptr;
3618 undoStack()->clear();
3619 }
3620 emit editingStopped();
3621
3622 if ( rollbackExtent )
3623 updateExtents();
3624
3625 mDataProvider->leaveUpdateMode();
3626
3628 return true;
3629}
3630
3632{
3633 return mSelectedFeatureIds.size();
3634}
3635
3637{
3638 return mSelectedFeatureIds;
3639}
3640
3642{
3643 QgsFeatureList features;
3644 features.reserve( mSelectedFeatureIds.count() );
3645 QgsFeature f;
3646
3648
3649 while ( it.nextFeature( f ) )
3650 {
3651 features.push_back( f );
3652 }
3653
3654 return features;
3655}
3656
3658{
3659 if ( mSelectedFeatureIds.isEmpty() )
3660 return QgsFeatureIterator();
3661
3664
3665 if ( mSelectedFeatureIds.count() == 1 )
3666 request.setFilterFid( *mSelectedFeatureIds.constBegin() );
3667 else
3668 request.setFilterFids( mSelectedFeatureIds );
3669
3670 return getFeatures( request );
3671}
3672
3674{
3675 if ( !mEditBuffer || !mDataProvider )
3676 return false;
3677
3678 if ( mGeometryOptions->isActive() )
3679 {
3680 for ( auto feature = features.begin(); feature != features.end(); ++feature )
3681 {
3682 QgsGeometry geom = feature->geometry();
3683 mGeometryOptions->apply( geom );
3684 feature->setGeometry( geom );
3685 }
3686 }
3687
3688 bool res = mEditBuffer->addFeatures( features );
3689 updateExtents();
3690
3691 if ( res && mJoinBuffer->containsJoins() )
3692 res = mJoinBuffer->addFeatures( features );
3693
3694 return res;
3695}
3696
3698{
3699 // if layer is not spatial, it has not CRS!
3700 setCrs( ( isSpatial() && mDataProvider ) ? mDataProvider->crs() : QgsCoordinateReferenceSystem() );
3701}
3702
3704{
3706 if ( exp.isField() )
3707 {
3708 return static_cast<const QgsExpressionNodeColumnRef *>( exp.rootNode() )->name();
3709 }
3710
3711 return QString();
3712}
3713
3714void QgsVectorLayer::setDisplayExpression( const QString &displayExpression )
3715{
3716 if ( mDisplayExpression == displayExpression )
3717 return;
3718
3719 mDisplayExpression = displayExpression;
3721}
3722
3724{
3725 if ( !mDisplayExpression.isEmpty() || mFields.isEmpty() )
3726 {
3727 return mDisplayExpression;
3728 }
3729 else
3730 {
3731 const QString candidateName = QgsVectorLayerUtils::guessFriendlyIdentifierField( mFields );
3732 if ( !candidateName.isEmpty() )
3733 {
3734 return QgsExpression::quotedColumnRef( candidateName );
3735 }
3736 else
3737 {
3738 return QString();
3739 }
3740 }
3741}
3742
3744{
3745 return ( mEditBuffer && mDataProvider );
3746}
3747
3749{
3752}
3753
3754bool QgsVectorLayer::isReadOnly() const
3755{
3756 return mDataSourceReadOnly || mReadOnly;
3757}
3758
3759bool QgsVectorLayer::setReadOnly( bool readonly )
3760{
3761 // exit if the layer is in editing mode
3762 if ( readonly && mEditBuffer )
3763 return false;
3764
3765 // exit if the data source is in read-only mode
3766 if ( !readonly && mDataSourceReadOnly )
3767 return false;
3768
3769 mReadOnly = readonly;
3770 emit readOnlyChanged();
3771 return true;
3772}
3773
3775{
3776 if ( ! mDataProvider )
3777 return false;
3778
3779 if ( mDataSourceReadOnly )
3780 return false;
3781
3782 return mDataProvider->capabilities() & QgsVectorDataProvider::EditingCapabilities && ! mReadOnly;
3783}
3784
3786{
3787 emit beforeModifiedCheck();
3788 return mEditBuffer && mEditBuffer->isModified();
3789}
3790
3791bool QgsVectorLayer::isAuxiliaryField( int index, int &srcIndex ) const
3792{
3793 bool auxiliaryField = false;
3794 srcIndex = -1;
3795
3796 if ( !auxiliaryLayer() )
3797 return auxiliaryField;
3798
3799 if ( index >= 0 && fields().fieldOrigin( index ) == QgsFields::OriginJoin )
3800 {
3801 const QgsVectorLayerJoinInfo *info = mJoinBuffer->joinForFieldIndex( index, fields(), srcIndex );
3802
3803 if ( info && info->joinLayerId() == auxiliaryLayer()->id() )
3804 auxiliaryField = true;
3805 }
3806
3807 return auxiliaryField;
3808}
3809
3811{
3812 // we must allow setting a renderer if our geometry type is unknown
3813 // as this allows the renderer to be correctly set even for layers
3814 // with broken sources
3815 if ( !isSpatial() && mWkbType != QgsWkbTypes::Unknown )
3816 return;
3817
3818 if ( r != mRenderer )
3819 {
3820 delete mRenderer;
3821 mRenderer = r;
3822 mSymbolFeatureCounted = false;
3823 mSymbolFeatureCountMap.clear();
3824 mSymbolFeatureIdMap.clear();
3825
3826 if ( mRenderer )
3827 {
3828 const double refreshRate = QgsSymbolLayerUtils::rendererFrameRate( mRenderer );
3829 if ( refreshRate <= 0 )
3830 {
3831 mRefreshRendererTimer->stop();
3832 mRefreshRendererTimer->setInterval( 0 );
3833 }
3834 else
3835 {
3836 mRefreshRendererTimer->setInterval( 1000 / refreshRate );
3837 mRefreshRendererTimer->start();
3838 }
3839 }
3840
3841 emit rendererChanged();
3843 }
3844}
3845
3847{
3848 if ( generator )
3849 {
3850 mRendererGenerators << generator;
3851 }
3852}
3853
3855{
3856 for ( int i = mRendererGenerators.count() - 1; i >= 0; --i )
3857 {
3858 if ( mRendererGenerators.at( i )->id() == id )
3859 {
3860 delete mRendererGenerators.at( i );
3861 mRendererGenerators.removeAt( i );
3862 }
3863 }
3864}
3865
3866QList<const QgsFeatureRendererGenerator *> QgsVectorLayer::featureRendererGenerators() const
3867{
3868 QList< const QgsFeatureRendererGenerator * > res;
3869 for ( const QgsFeatureRendererGenerator *generator : mRendererGenerators )
3870 res << generator;
3871 return res;
3872}
3873
3874void QgsVectorLayer::beginEditCommand( const QString &text )
3875{
3876 if ( !mDataProvider )
3877 {
3878 return;
3879 }
3880 if ( mDataProvider->transaction() )
3881 {
3882 QString ignoredError;
3883 mDataProvider->transaction()->createSavepoint( ignoredError );
3884 }
3885 undoStack()->beginMacro( text );
3886 mEditCommandActive = true;
3887 emit editCommandStarted( text );
3888}
3889
3891{
3892 if ( !mDataProvider )
3893 {
3894 return;
3895 }
3896 undoStack()->endMacro();
3897 mEditCommandActive = false;
3898 if ( !mDeletedFids.isEmpty() )
3899 {
3900 if ( selectedFeatureCount() > 0 )
3901 {
3902 mSelectedFeatureIds.subtract( mDeletedFids );
3903 }
3904 emit featuresDeleted( mDeletedFids );
3905 mDeletedFids.clear();
3906 }
3907 emit editCommandEnded();
3908}
3909
3911{
3912 if ( !mDataProvider )
3913 {
3914 return;
3915 }
3916 undoStack()->endMacro();
3917 undoStack()->undo();
3918
3919 // it's not directly possible to pop the last command off the stack (the destroyed one)
3920 // and delete, so we add a dummy obsolete command to force this to occur.
3921 // Pushing the new command deletes the destroyed one, and since the new
3922 // command is obsolete it's automatically deleted by the undo stack.
3923 std::unique_ptr< QUndoCommand > command = std::make_unique< QUndoCommand >();
3924 command->setObsolete( true );
3925 undoStack()->push( command.release() );
3926
3927 mEditCommandActive = false;
3928 mDeletedFids.clear();
3929 emit editCommandDestroyed();
3930}
3931
3933{
3934 return mJoinBuffer->addJoin( joinInfo );
3935}
3936
3937
3938bool QgsVectorLayer::removeJoin( const QString &joinLayerId )
3939{
3940 return mJoinBuffer->removeJoin( joinLayerId );
3941}
3942
3943const QList< QgsVectorLayerJoinInfo > QgsVectorLayer::vectorJoins() const
3944{
3945 return mJoinBuffer->vectorJoins();
3946}
3947
3948int QgsVectorLayer::addExpressionField( const QString &exp, const QgsField &fld )
3949{
3950 emit beforeAddingExpressionField( fld.name() );
3951 mExpressionFieldBuffer->addExpression( exp, fld );
3952 updateFields();
3953 int idx = mFields.indexFromName( fld.name() );
3954 emit attributeAdded( idx );
3955 return idx;
3956}
3957
3959{
3960 emit beforeRemovingExpressionField( index );
3961 int oi = mFields.fieldOriginIndex( index );
3962 mExpressionFieldBuffer->removeExpression( oi );
3963 updateFields();
3964 emit attributeDeleted( index );
3965}
3966
3967QString QgsVectorLayer::expressionField( int index ) const
3968{
3969 if ( mFields.fieldOrigin( index ) != QgsFields::OriginExpression )
3970 return QString();
3971
3972 int oi = mFields.fieldOriginIndex( index );
3973 if ( oi < 0 || oi >= mExpressionFieldBuffer->expressions().size() )
3974 return QString();
3975
3976 return mExpressionFieldBuffer->expressions().at( oi ).cachedExpression.expression();
3977}
3978
3979void QgsVectorLayer::updateExpressionField( int index, const QString &exp )
3980{
3981 int oi = mFields.fieldOriginIndex( index );
3982 mExpressionFieldBuffer->updateExpression( oi, exp );
3983}
3984
3986{
3987 if ( !mDataProvider )
3988 return;
3989
3990 QgsFields oldFields = mFields;
3991
3992 mFields = mDataProvider->fields();
3993
3994 // added / removed fields
3995 if ( mEditBuffer )
3996 mEditBuffer->updateFields( mFields );
3997
3998 // joined fields
3999 if ( mJoinBuffer->containsJoins() )
4000 mJoinBuffer->updateFields( mFields );
4001
4002 if ( mExpressionFieldBuffer )
4003 mExpressionFieldBuffer->updateFields( mFields );
4004
4005 // set aliases and default values
4006 QMap< QString, QString >::const_iterator aliasIt = mAttributeAliasMap.constBegin();
4007 for ( ; aliasIt != mAttributeAliasMap.constEnd(); ++aliasIt )
4008 {
4009 int index = mFields.lookupField( aliasIt.key() );
4010 if ( index < 0 )
4011 continue;
4012
4013 mFields[ index ].setAlias( aliasIt.value() );
4014 }
4015
4016 // Update configuration flags
4017 QMap< QString, QgsField::ConfigurationFlags >::const_iterator flagsIt = mFieldConfigurationFlags.constBegin();
4018 for ( ; flagsIt != mFieldConfigurationFlags.constEnd(); ++flagsIt )
4019 {
4020 int index = mFields.lookupField( flagsIt.key() );
4021 if ( index < 0 )
4022 continue;
4023
4024 mFields[index].setConfigurationFlags( flagsIt.value() );
4025 }
4026
4027 // Update default values
4028 mDefaultValueOnUpdateFields.clear();
4029 QMap< QString, QgsDefaultValue >::const_iterator defaultIt = mDefaultExpressionMap.constBegin();
4030 for ( ; defaultIt != mDefaultExpressionMap.constEnd(); ++defaultIt )
4031 {
4032 int index = mFields.lookupField( defaultIt.key() );
4033 if ( index < 0 )
4034 continue;
4035
4036 mFields[ index ].setDefaultValueDefinition( defaultIt.value() );
4037 if ( defaultIt.value().applyOnUpdate() )
4038 mDefaultValueOnUpdateFields.insert( index );
4039 }
4040
4041 QMap< QString, QgsFieldConstraints::Constraints >::const_iterator constraintIt = mFieldConstraints.constBegin();
4042 for ( ; constraintIt != mFieldConstraints.constEnd(); ++constraintIt )
4043 {
4044 int index = mFields.lookupField( constraintIt.key() );
4045 if ( index < 0 )
4046 continue;
4047
4048 QgsFieldConstraints constraints = mFields.at( index ).constraints();
4049
4050 // always keep provider constraints intact
4051 if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintNotNull ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintNotNull ) )
4053 if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintUnique ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintUnique ) )
4055 if ( !( constraints.constraints() & QgsFieldConstraints::ConstraintExpression ) && ( constraintIt.value() & QgsFieldConstraints::ConstraintExpression ) )
4057 mFields[ index ].setConstraints( constraints );
4058 }
4059
4060 QMap< QString, QPair< QString, QString > >::const_iterator constraintExpIt = mFieldConstraintExpressions.constBegin();
4061 for ( ; constraintExpIt != mFieldConstraintExpressions.constEnd(); ++constraintExpIt )
4062 {
4063 int index = mFields.lookupField( constraintExpIt.key() );
4064 if ( index < 0 )
4065 continue;
4066
4067 QgsFieldConstraints constraints = mFields.at( index ).constraints();
4068
4069 // always keep provider constraints intact
4071 continue;
4072
4073 constraints.setConstraintExpression( constraintExpIt.value().first, constraintExpIt.value().second );
4074 mFields[ index ].setConstraints( constraints );
4075 }
4076
4077 QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator constraintStrengthIt = mFieldConstraintStrength.constBegin();
4078 for ( ; constraintStrengthIt != mFieldConstraintStrength.constEnd(); ++constraintStrengthIt )
4079 {
4080 int index = mFields.lookupField( constraintStrengthIt.key().first );
4081 if ( index < 0 )
4082 continue;
4083
4084 QgsFieldConstraints constraints = mFields.at( index ).constraints();
4085
4086 // always keep provider constraints intact
4088 continue;
4089
4090 constraints.setConstraintStrength( constraintStrengthIt.key().second, constraintStrengthIt.value() );
4091 mFields[ index ].setConstraints( constraints );
4092 }
4093
4094 auto fieldWidgetIterator = mFieldWidgetSetups.constBegin();
4095 for ( ; fieldWidgetIterator != mFieldWidgetSetups.constEnd(); ++ fieldWidgetIterator )
4096 {
4097 int index = mFields.indexOf( fieldWidgetIterator.key() );
4098 if ( index < 0 )
4099 continue;
4100
4101 mFields[index].setEditorWidgetSetup( fieldWidgetIterator.value() );
4102 }
4103
4104 if ( oldFields != mFields )
4105 {
4106 emit updatedFields();
4107 mEditFormConfig.setFields( mFields );
4108 }
4109
4110}
4111
4112
4113QVariant QgsVectorLayer::defaultValue( int index, const QgsFeature &feature, QgsExpressionContext *context ) const
4114{
4115 if ( index < 0 || index >= mFields.count() || !mDataProvider )
4116 return QVariant();
4117
4118 QString expression = mFields.at( index ).defaultValueDefinition().expression();
4119 if ( expression.isEmpty() )
4120 return mDataProvider->defaultValue( index );
4121
4122 QgsExpressionContext *evalContext = context;
4123 std::unique_ptr< QgsExpressionContext > tempContext;
4124 if ( !evalContext )
4125 {
4126 // no context passed, so we create a default one
4128 evalContext = tempContext.get();
4129 }
4130
4131 if ( feature.isValid() )
4132 {
4134 featScope->setFeature( feature );
4135 featScope->setFields( feature.fields() );
4136 evalContext->appendScope( featScope );
4137 }
4138
4139 QVariant val;
4140 QgsExpression exp( expression );
4141 exp.prepare( evalContext );
4142 if ( exp.hasEvalError() )
4143 {
4144 QgsLogger::warning( "Error evaluating default value: " + exp.evalErrorString() );
4145 }
4146 else
4147 {
4148 val = exp.evaluate( evalContext );
4149 }
4150
4151 if ( feature.isValid() )
4152 {
4153 delete evalContext->popScope();
4154 }
4155
4156 return val;
4157}
4158
4160{
4161 if ( index < 0 || index >= mFields.count() )
4162 return;
4163
4164 if ( definition.isValid() )
4165 {
4166 mDefaultExpressionMap.insert( mFields.at( index ).name(), definition );
4167 }
4168 else
4169 {
4170 mDefaultExpressionMap.remove( mFields.at( index ).name() );
4171 }
4172 updateFields();
4173}
4174
4176{
4177 if ( index < 0 || index >= mFields.count() )
4178 return QgsDefaultValue();
4179 else
4180 return mFields.at( index ).defaultValueDefinition();
4181}
4182
4183QSet<QVariant> QgsVectorLayer::uniqueValues( int index, int limit ) const
4184{
4185 QSet<QVariant> uniqueValues;
4186 if ( !mDataProvider )
4187 {
4188 return uniqueValues;
4189 }
4190
4191 QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
4192 switch ( origin )
4193 {
4195 return uniqueValues;
4196
4197 case QgsFields::OriginProvider: //a provider field
4198 {
4199 uniqueValues = mDataProvider->uniqueValues( index, limit );
4200
4201 if ( mEditBuffer && ! mDataProvider->transaction() )
4202 {
4203 QSet<QString> vals;
4204 const auto constUniqueValues = uniqueValues;
4205 for ( const QVariant &v : constUniqueValues )
4206 {
4207 vals << v.toString();
4208 }
4209
4210 QgsFeatureMap added = mEditBuffer->addedFeatures();
4211 QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
4212 while ( addedIt.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
4213 {
4214 addedIt.next();
4215 QVariant v = addedIt.value().attribute( index );
4216 if ( v.isValid() )
4217 {
4218 QString vs = v.toString();
4219 if ( !vals.contains( vs ) )
4220 {
4221 vals << vs;
4222 uniqueValues << v;
4223 }
4224 }
4225 }
4226
4227 QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
4228 while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
4229 {
4230 it.next();
4231 QVariant v = it.value().value( index );
4232 if ( v.isValid() )
4233 {
4234 QString vs = v.toString();
4235 if ( !vals.contains( vs ) )
4236 {
4237 vals << vs;
4238 uniqueValues << v;
4239 }
4240 }
4241 }
4242 }
4243
4244 return uniqueValues;
4245 }
4246
4248 // the layer is editable, but in certain cases it can still be avoided going through all features
4249 if ( mDataProvider->transaction() || (
4250 mEditBuffer->deletedFeatureIds().isEmpty() &&
4251 mEditBuffer->addedFeatures().isEmpty() &&
4252 !mEditBuffer->deletedAttributeIds().contains( index ) &&
4253 mEditBuffer->changedAttributeValues().isEmpty() ) )
4254 {
4255 uniqueValues = mDataProvider->uniqueValues( index, limit );
4256 return uniqueValues;
4257 }
4259 //we need to go through each feature
4262 {
4263 QgsAttributeList attList;
4264 attList << index;
4265
4268 .setSubsetOfAttributes( attList ) );
4269
4270 QgsFeature f;
4271 QVariant currentValue;
4272 QHash<QString, QVariant> val;
4273 while ( fit.nextFeature( f ) )
4274 {
4275 currentValue = f.attribute( index );
4276 val.insert( currentValue.toString(), currentValue );
4277 if ( limit >= 0 && val.size() >= limit )
4278 {
4279 break;
4280 }
4281 }
4282
4283 return qgis::listToSet( val.values() );
4284 }
4285 }
4286
4287 Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
4288 return uniqueValues;
4289}
4290
4291QStringList QgsVectorLayer::uniqueStringsMatching( int index, const QString &substring, int limit, QgsFeedback *feedback ) const
4292{
4293 QStringList results;
4294 if ( !mDataProvider )
4295 {
4296 return results;
4297 }
4298
4299 QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
4300 switch ( origin )
4301 {
4303 return results;
4304
4305 case QgsFields::OriginProvider: //a provider field
4306 {
4307 results = mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
4308
4309 if ( mEditBuffer && ! mDataProvider->transaction() )
4310 {
4311 QgsFeatureMap added = mEditBuffer->addedFeatures();
4312 QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
4313 while ( addedIt.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
4314 {
4315 addedIt.next();
4316 QVariant v = addedIt.value().attribute( index );
4317 if ( v.isValid() )
4318 {
4319 QString vs = v.toString();
4320 if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
4321 {
4322 results << vs;
4323 }
4324 }
4325 }
4326
4327 QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
4328 while ( it.hasNext() && ( limit < 0 || results.count() < limit ) && ( !feedback || !feedback->isCanceled() ) )
4329 {
4330 it.next();
4331 QVariant v = it.value().value( index );
4332 if ( v.isValid() )
4333 {
4334 QString vs = v.toString();
4335 if ( vs.contains( substring, Qt::CaseInsensitive ) && !results.contains( vs ) )
4336 {
4337 results << vs;
4338 }
4339 }
4340 }
4341 }
4342
4343 return results;
4344 }
4345
4347 // the layer is editable, but in certain cases it can still be avoided going through all features
4348 if ( mDataProvider->transaction() || ( mEditBuffer->deletedFeatureIds().isEmpty() &&
4349 mEditBuffer->addedFeatures().isEmpty() &&
4350 !mEditBuffer->deletedAttributeIds().contains( index ) &&
4351 mEditBuffer->changedAttributeValues().isEmpty() ) )
4352 {
4353 return mDataProvider->uniqueStringsMatching( index, substring, limit, feedback );
4354 }
4356 //we need to go through each feature
4359 {
4360 QgsAttributeList attList;
4361 attList << index;
4362
4363 QgsFeatureRequest request;
4364 request.setSubsetOfAttributes( attList );
4366 QString fieldName = mFields.at( index ).name();
4367 request.setFilterExpression( QStringLiteral( "\"%1\" ILIKE '%%2%'" ).arg( fieldName, substring ) );
4368 QgsFeatureIterator fit = getFeatures( request );
4369
4370 QgsFeature f;
4371 QString currentValue;
4372 while ( fit.nextFeature( f ) )
4373 {
4374 currentValue = f.attribute( index ).toString();
4375 if ( !results.contains( currentValue ) )
4376 results << currentValue;
4377
4378 if ( ( limit >= 0 && results.size() >= limit ) || ( feedback && feedback->isCanceled() ) )
4379 {
4380 break;
4381 }
4382 }
4383
4384 return results;
4385 }
4386 }
4387
4388 Q_ASSERT_X( false, "QgsVectorLayer::uniqueStringsMatching()", "Unknown source of the field!" );
4389 return results;
4390}
4391
4392QVariant QgsVectorLayer::minimumValue( int index ) const
4393{
4394 QVariant minimum;
4395 minimumOrMaximumValue( index, &minimum, nullptr );
4396 return minimum;
4397}
4398
4399QVariant QgsVectorLayer::maximumValue( int index ) const
4400{
4401 QVariant maximum;
4402 minimumOrMaximumValue( index, nullptr, &maximum );
4403 return maximum;
4404}
4405
4406void QgsVectorLayer::minimumAndMaximumValue( int index, QVariant &minimum, QVariant &maximum ) const
4407{
4408 minimumOrMaximumValue( index, &minimum, &maximum );
4409}
4410
4411void QgsVectorLayer::minimumOrMaximumValue( int index, QVariant *minimum, QVariant *maximum ) const
4412{
4413 if ( minimum )
4414 *minimum = QVariant();
4415 if ( maximum )
4416 *maximum = QVariant();
4417
4418 if ( !mDataProvider )
4419 {
4420 return;
4421 }
4422
4423 QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
4424
4425 switch ( origin )
4426 {
4428 {
4429 return;
4430 }
4431
4432 case QgsFields::OriginProvider: //a provider field
4433 {
4434 if ( minimum )
4435 *minimum = mDataProvider->minimumValue( index );
4436 if ( maximum )
4437 *maximum = mDataProvider->maximumValue( index );
4438 if ( mEditBuffer && ! mDataProvider->transaction() )
4439 {
4440 const QgsFeatureMap added = mEditBuffer->addedFeatures();
4441 QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
4442 while ( addedIt.hasNext() )
4443 {
4444 addedIt.next();
4445 const QVariant v = addedIt.value().attribute( index );
4446 if ( minimum && v.isValid() && qgsVariantLessThan( v, *minimum ) )
4447 *minimum = v;
4448 if ( maximum && v.isValid() && qgsVariantGreaterThan( v, *maximum ) )
4449 *maximum = v;
4450 }
4451
4452 QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
4453 while ( it.hasNext() )
4454 {
4455 it.next();
4456 const QVariant v = it.value().value( index );
4457 if ( minimum && v.isValid() && qgsVariantLessThan( v, *minimum ) )
4458 *minimum = v;
4459 if ( maximum && v.isValid() && qgsVariantGreaterThan( v, *maximum ) )
4460 *maximum = v;
4461 }
4462 }
4463 return;
4464 }
4465
4467 {
4468 // the layer is editable, but in certain cases it can still be avoided going through all features
4469 if ( mDataProvider->transaction() || ( mEditBuffer->deletedFeatureIds().isEmpty() &&
4470 mEditBuffer->addedFeatures().isEmpty() &&
4471 !mEditBuffer->deletedAttributeIds().contains( index ) &&
4472 mEditBuffer->changedAttributeValues().isEmpty() ) )
4473 {
4474 if ( minimum )
4475 *minimum = mDataProvider->minimumValue( index );
4476 if ( maximum )
4477 *maximum = mDataProvider->maximumValue( index );
4478 return;
4479 }
4480 }
4482 // no choice but to go through all features
4485 {
4486 // we need to go through each feature
4487 QgsAttributeList attList;
4488 attList << index;
4489
4492 .setSubsetOfAttributes( attList ) );
4493
4494 QgsFeature f;
4495 bool firstValue = true;
4496 while ( fit.nextFeature( f ) )
4497 {
4498 const QVariant currentValue = f.attribute( index );
4499 if ( QgsVariantUtils::isNull( currentValue ) )
4500 continue;
4501
4502 if ( firstValue )
4503 {
4504 if ( minimum )
4505 *minimum = currentValue;
4506 if ( maximum )
4507 *maximum = currentValue;
4508 firstValue = false;
4509 }
4510 else
4511 {
4512 if ( minimum && currentValue.isValid() && qgsVariantLessThan( currentValue, *minimum ) )
4513 *minimum = currentValue;
4514 if ( maximum && currentValue.isValid() && qgsVariantGreaterThan( currentValue, *maximum ) )
4515 *maximum = currentValue;
4516 }
4517 }
4518 return;
4519 }
4520 }
4521
4522 Q_ASSERT_X( false, "QgsVectorLayer::minimumOrMaximumValue()", "Unknown source of the field!" );
4523}
4524
4525void QgsVectorLayer::createEditBuffer()
4526{
4527 if ( mEditBuffer )
4528 clearEditBuffer();
4529
4530 if ( mDataProvider->transaction() )
4531 {
4532 mEditBuffer = new QgsVectorLayerEditPassthrough( this );
4533
4534 connect( mDataProvider->transaction(), &QgsTransaction::dirtied, this, &QgsVectorLayer::onDirtyTransaction, Qt::UniqueConnection );
4535 }
4536 else
4537 {
4538 mEditBuffer = new QgsVectorLayerEditBuffer( this );
4539 }
4540 // forward signals
4541 connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::invalidateSymbolCountedFlag );
4542 connect( mEditBuffer, &QgsVectorLayerEditBuffer::layerModified, this, &QgsVectorLayer::layerModified ); // TODO[MD]: necessary?
4543 //connect( mEditBuffer, SIGNAL( layerModified() ), this, SLOT( triggerRepaint() ) ); // TODO[MD]: works well?
4545 connect( mEditBuffer, &QgsVectorLayerEditBuffer::featureDeleted, this, &QgsVectorLayer::onFeatureDeleted );
4556
4557}
4558
4559void QgsVectorLayer::clearEditBuffer()
4560{
4561 delete mEditBuffer;
4562 mEditBuffer = nullptr;
4563}
4564
4565QVariant QgsVectorLayer::aggregate( QgsAggregateCalculator::Aggregate aggregate, const QString &fieldOrExpression,
4567 bool *ok, QgsFeatureIds *fids, QgsFeedback *feedback, QString *error ) const
4568{
4569 if ( ok )
4570 *ok = false;
4571 if ( error )
4572 error->clear();
4573
4574 if ( !mDataProvider )
4575 {
4576 if ( error )
4577 *error = tr( "Layer is invalid" );
4578 return QVariant();
4579 }
4580
4581 // test if we are calculating based on a field
4582 const int attrIndex = QgsExpression::expressionToLayerFieldIndex( fieldOrExpression, this );
4583 if ( attrIndex >= 0 )
4584 {
4585 // aggregate is based on a field - if it's a provider field, we could possibly hand over the calculation
4586 // to the provider itself
4587 QgsFields::FieldOrigin origin = mFields.fieldOrigin( attrIndex );
4588 if ( origin == QgsFields::OriginProvider )
4589 {
4590 bool providerOk = false;
4591 QVariant val = mDataProvider->aggregate( aggregate, attrIndex, parameters, context, providerOk, fids );
4592 if ( providerOk )
4593 {
4594 // provider handled calculation
4595 if ( ok )
4596 *ok = true;
4597 return val;
4598 }
4599 }
4600 }
4601
4602 // fallback to using aggregate calculator to determine aggregate
4603 QgsAggregateCalculator c( this );
4604 if ( fids )
4605 c.setFidsFilter( *fids );
4606 c.setParameters( parameters );
4607 bool aggregateOk = false;
4608 const QVariant result = c.calculate( aggregate, fieldOrExpression, context, &aggregateOk, feedback );
4609 if ( ok )
4610 *ok = aggregateOk;
4611 if ( !aggregateOk && error )
4612 *error = c.lastError();
4613
4614 return result;
4615}
4616
4617void QgsVectorLayer::setFeatureBlendMode( QPainter::CompositionMode featureBlendMode )
4618{
4619 if ( mFeatureBlendMode == featureBlendMode )
4620 return;
4621
4622 mFeatureBlendMode = featureBlendMode;
4625}
4626
4627QPainter::CompositionMode QgsVectorLayer::featureBlendMode() const
4628{
4629 return mFeatureBlendMode;
4630}
4631
4632void QgsVectorLayer::readSldLabeling( const QDomNode &node )
4633{
4634 setLabeling( nullptr ); // start with no labeling
4635 setLabelsEnabled( false );
4636
4637 QDomElement element = node.toElement();
4638 if ( element.isNull() )
4639 return;
4640
4641 QDomElement userStyleElem = element.firstChildElement( QStringLiteral( "UserStyle" ) );
4642 if ( userStyleElem.isNull() )
4643 {
4644 QgsDebugMsgLevel( QStringLiteral( "Info: UserStyle element not found." ), 4 );
4645 return;
4646 }
4647
4648 QDomElement featTypeStyleElem = userStyleElem.firstChildElement( QStringLiteral( "FeatureTypeStyle" ) );
4649 if ( featTypeStyleElem.isNull() )
4650 {
4651 QgsDebugMsgLevel( QStringLiteral( "Info: FeatureTypeStyle element not found." ), 4 );
4652 return;
4653 }
4654
4655 // create empty FeatureTypeStyle element to merge TextSymbolizer's Rule's from all FeatureTypeStyle's
4656 QDomElement mergedFeatTypeStyle = featTypeStyleElem.cloneNode( false ).toElement();
4657
4658 // use the RuleRenderer when more rules are present or the rule
4659 // has filters or min/max scale denominators set,
4660 // otherwise use the Simple labeling
4661 bool needRuleBasedLabeling = false;
4662 int ruleCount = 0;
4663
4664 while ( !featTypeStyleElem.isNull() )
4665 {
4666 QDomElement ruleElem = featTypeStyleElem.firstChildElement( QStringLiteral( "Rule" ) );
4667 while ( !ruleElem.isNull() )
4668 {
4669 // test rule children element to check if we need to create RuleRenderer
4670 // and if the rule has a symbolizer
4671 bool hasTextSymbolizer = false;
4672 bool hasRuleBased = false;
4673 QDomElement ruleChildElem = ruleElem.firstChildElement();
4674 while ( !ruleChildElem.isNull() )
4675 {
4676 // rule has filter or min/max scale denominator, use the RuleRenderer
4677 if ( ruleChildElem.localName() == QLatin1String( "Filter" ) ||
4678 ruleChildElem.localName() == QLatin1String( "MinScaleDenominator" ) ||
4679 ruleChildElem.localName() == QLatin1String( "MaxScaleDenominator" ) )
4680 {
4681 hasRuleBased = true;
4682 }
4683 // rule has a renderer symbolizer, not a text symbolizer
4684 else if ( ruleChildElem.localName() == QLatin1String( "TextSymbolizer" ) )
4685 {
4686 QgsDebugMsgLevel( QStringLiteral( "Info: TextSymbolizer element found" ), 4 );
4687 hasTextSymbolizer = true;
4688 }
4689
4690 ruleChildElem = ruleChildElem.nextSiblingElement();
4691 }
4692
4693 if ( hasTextSymbolizer )
4694 {
4695 ruleCount++;
4696
4697 // append a clone of all Rules to the merged FeatureTypeStyle element
4698 mergedFeatTypeStyle.appendChild( ruleElem.cloneNode().toElement() );
4699
4700 if ( hasRuleBased )
4701 {
4702 QgsDebugMsgLevel( QStringLiteral( "Info: Filter or Min/MaxScaleDenominator element found: need a RuleBasedLabeling" ), 4 );
4703 needRuleBasedLabeling = true;
4704 }
4705 }
4706
4707 // more rules present, use the RuleRenderer
4708 if ( ruleCount > 1 )
4709 {
4710 QgsDebugMsgLevel( QStringLiteral( "Info: More Rule elements found: need a RuleBasedLabeling" ), 4 );
4711 needRuleBasedLabeling = true;
4712 }
4713
4714 // not use the rule based labeling if no rules with textSymbolizer
4715 if ( ruleCount == 0 )
4716 {
4717 needRuleBasedLabeling = false;
4718 }
4719
4720 ruleElem = ruleElem.nextSiblingElement( QStringLiteral( "Rule" ) );
4721 }
4722 featTypeStyleElem = featTypeStyleElem.nextSiblingElement( QStringLiteral( "FeatureTypeStyle" ) );
4723 }
4724
4725 if ( ruleCount == 0 )
4726 {
4727 QgsDebugMsgLevel( QStringLiteral( "Info: No TextSymbolizer element." ), 4 );
4728 return;
4729 }
4730
4731 QDomElement ruleElem = mergedFeatTypeStyle.firstChildElement( QStringLiteral( "Rule" ) );
4732
4733 if ( needRuleBasedLabeling )
4734 {
4735 QgsDebugMsgLevel( QStringLiteral( "Info: rule based labeling" ), 4 );
4736 QgsRuleBasedLabeling::Rule *rootRule = new QgsRuleBasedLabeling::Rule( nullptr );
4737 while ( !ruleElem.isNull() )
4738 {
4739
4740 QString label, description, filterExp;
4741 int scaleMinDenom = 0, scaleMaxDenom = 0;
4742 QgsPalLayerSettings settings;
4743
4744 // retrieve the Rule element child nodes
4745 QDomElement childElem = ruleElem.firstChildElement();
4746 while ( !childElem.isNull() )
4747 {
4748 if ( childElem.localName() == QLatin1String( "Name" ) )
4749 {
4750 // <se:Name> tag contains the rule identifier,
4751 // so prefer title tag for the label property value
4752 if ( label.isEmpty() )
4753 label = childElem.firstChild().nodeValue();
4754 }
4755 else if ( childElem.localName() == QLatin1String( "Description" ) )
4756 {
4757 // <se:Description> can contains a title and an abstract
4758 QDomElement titleElem = childElem.firstChildElement( QStringLiteral( "Title" ) );
4759 if ( !titleElem.isNull() )
4760 {
4761 label = titleElem.firstChild().nodeValue();
4762 }
4763
4764 QDomElement abstractElem = childElem.firstChildElement( QStringLiteral( "Abstract" ) );
4765 if ( !abstractElem.isNull() )
4766 {
4767 description = abstractElem.firstChild().nodeValue();
4768 }
4769 }
4770 else if ( childElem.localName() == QLatin1String( "Abstract" ) )
4771 {
4772 // <sld:Abstract> (v1.0)
4773 description = childElem.firstChild().nodeValue();
4774 }
4775 else if ( childElem.localName() == QLatin1String( "Title" ) )
4776 {
4777 // <sld:Title> (v1.0)
4778 label = childElem.firstChild().nodeValue();
4779 }
4780 else if ( childElem.localName() == QLatin1String( "Filter" ) )
4781 {
4783 if ( filter )
4784 {
4785 if ( filter->hasParserError() )
4786 {
4787 QgsDebugMsgLevel( QStringLiteral( "SLD Filter parsing error: %1" ).arg( filter->parserErrorString() ), 3 );
4788 }
4789 else
4790 {
4791 filterExp = filter->expression();
4792 }
4793 delete filter;
4794 }
4795 }
4796 else if ( childElem.localName() == QLatin1String( "MinScaleDenominator" ) )
4797 {
4798 bool ok;
4799 int v = childElem.firstChild().nodeValue().toInt( &ok );
4800 if ( ok )
4801 scaleMinDenom = v;
4802 }
4803 else if ( childElem.localName() == QLatin1String( "MaxScaleDenominator" ) )
4804 {
4805 bool ok;
4806 int v = childElem.firstChild().nodeValue().toInt( &ok );
4807 if ( ok )
4808 scaleMaxDenom = v;
4809 }
4810 else if ( childElem.localName() == QLatin1String( "TextSymbolizer" ) )
4811 {
4812 readSldTextSymbolizer( childElem, settings );
4813 }
4814
4815 childElem = childElem.nextSiblingElement();
4816 }
4817
4818 QgsRuleBasedLabeling::Rule *ruleLabeling = new QgsRuleBasedLabeling::Rule( new QgsPalLayerSettings( settings ), scaleMinDenom, scaleMaxDenom, filterExp, label );
4819 rootRule->appendChild( ruleLabeling );
4820
4821 ruleElem = ruleElem.nextSiblingElement();
4822 }
4823
4824 setLabeling( new QgsRuleBasedLabeling( rootRule ) );
4825 setLabelsEnabled( true );
4826 }
4827 else
4828 {
4829 QgsDebugMsgLevel( QStringLiteral( "Info: simple labeling" ), 4 );
4830 // retrieve the TextSymbolizer element child node
4831 QDomElement textSymbolizerElem = ruleElem.firstChildElement( QStringLiteral( "TextSymbolizer" ) );
4833 if ( readSldTextSymbolizer( textSymbolizerElem, s ) )
4834 {
4836 setLabelsEnabled( true );
4837 }
4838 }
4839}
4840
4841bool QgsVectorLayer::readSldTextSymbolizer( const QDomNode &node, QgsPalLayerSettings &settings ) const
4842{
4843 if ( node.localName() != QLatin1String( "TextSymbolizer" ) )
4844 {
4845 QgsDebugMsgLevel( QStringLiteral( "Not a TextSymbolizer element: %1" ).arg( node.localName() ), 3 );
4846 return false;
4847 }
4848 QDomElement textSymbolizerElem = node.toElement();
4849 // Label
4850 QDomElement labelElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Label" ) );
4851 if ( !labelElem.isNull() )
4852 {
4853 QDomElement propertyNameElem = labelElem.firstChildElement( QStringLiteral( "PropertyName" ) );
4854 if ( !propertyNameElem.isNull() )
4855 {
4856 // set labeling defaults
4857
4858 // label attribute
4859 QString labelAttribute = propertyNameElem.text();
4860 settings.fieldName = labelAttribute;
4861 settings.isExpression = false;
4862
4863 int fieldIndex = mFields.lookupField( labelAttribute );
4864 if ( fieldIndex == -1 )
4865 {
4866 // label attribute is not in columns, check if it is an expression
4867 QgsExpression exp( labelAttribute );
4868 if ( !exp.hasEvalError() )
4869 {
4870 settings.isExpression = true;
4871 }
4872 else
4873 {
4874 QgsDebugMsgLevel( QStringLiteral( "SLD label attribute error: %1" ).arg( exp.evalErrorString() ), 3 );
4875 }
4876 }
4877 }
4878 else
4879 {
4880 QgsDebugMsgLevel( QStringLiteral( "Info: PropertyName element not found." ), 4 );
4881 return false;
4882 }
4883 }
4884 else
4885 {
4886 QgsDebugMsgLevel( QStringLiteral( "Info: Label element not found." ), 4 );
4887 return false;
4888 }
4889
4891 if ( textSymbolizerElem.hasAttribute( QStringLiteral( "uom" ) ) )
4892 {
4893 sldUnitSize = QgsSymbolLayerUtils::decodeSldUom( textSymbolizerElem.attribute( QStringLiteral( "uom" ) ) );
4894 }
4895
4896 QString fontFamily = QStringLiteral( "Sans-Serif" );
4897 int fontPointSize = 10;
4899 int fontWeight = -1;
4900 bool fontItalic = false;
4901 bool fontUnderline = false;
4902
4903 // Font
4904 QDomElement fontElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Font" ) );
4905 if ( !fontElem.isNull() )
4906 {
4907 QgsStringMap fontSvgParams = QgsSymbolLayerUtils::getSvgParameterList( fontElem );
4908 for ( QgsStringMap::iterator it = fontSvgParams.begin(); it != fontSvgParams.end(); ++it )
4909 {
4910 QgsDebugMsgLevel( QStringLiteral( "found fontSvgParams %1: %2" ).arg( it.key(), it.value() ), 4 );
4911
4912 if ( it.key() == QLatin1String( "font-family" ) )
4913 {
4914 fontFamily = it.value();
4915 }
4916 else if ( it.key() == QLatin1String( "font-style" ) )
4917 {
4918 fontItalic = ( it.value() == QLatin1String( "italic" ) ) || ( it.value() == QLatin1String( "Italic" ) );
4919 }
4920 else if ( it.key() == QLatin1String( "font-size" ) )
4921 {
4922 bool ok;
4923 int fontSize = it.value().toInt( &ok );
4924 if ( ok )
4925 {
4926 fontPointSize = fontSize;
4927 fontUnitSize = sldUnitSize;
4928 }
4929 }
4930 else if ( it.key() == QLatin1String( "font-weight" ) )
4931 {
4932 if ( ( it.value() == QLatin1String( "bold" ) ) || ( it.value() == QLatin1String( "Bold" ) ) )
4933 fontWeight = QFont::Bold;
4934 }
4935 else if ( it.key() == QLatin1String( "font-underline" ) )
4936 {
4937 fontUnderline = ( it.value() == QLatin1String( "underline" ) ) || ( it.value() == QLatin1String( "Underline" ) );
4938 }
4939 }
4940 }
4941
4942 QgsTextFormat format;
4943 QFont font( fontFamily, fontPointSize, fontWeight, fontItalic );
4944 font.setUnderline( fontUnderline );
4945 format.setFont( font );
4946 format.setSize( fontPointSize );
4947 format.setSizeUnit( fontUnitSize );
4948
4949 // Fill
4950 QDomElement fillElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Fill" ) );
4951 QColor textColor;
4952 Qt::BrushStyle textBrush = Qt::SolidPattern;
4953 QgsSymbolLayerUtils::fillFromSld( fillElem, textBrush, textColor );
4954 if ( textColor.isValid() )
4955 {
4956 QgsDebugMsgLevel( QStringLiteral( "Info: textColor %1." ).arg( QVariant( textColor ).toString() ), 4 );
4957 format.setColor( textColor );
4958 }
4959
4960 QgsTextBufferSettings bufferSettings;
4961
4962 // Halo
4963 QDomElement haloElem = textSymbolizerElem.firstChildElement( QStringLiteral( "Halo" ) );
4964 if ( !haloElem.isNull() )
4965 {
4966 bufferSettings.setEnabled( true );
4967 bufferSettings.setSize( 1 );
4968
4969 QDomElement radiusElem = haloElem.firstChildElement( QStringLiteral( "Radius" ) );
4970 if ( !radiusElem.isNull() )
4971 {
4972 bool ok;
4973 double bufferSize = radiusElem.text().toDouble( &ok );
4974 if ( ok )
4975 {
4976 bufferSettings.setSize( bufferSize );
4977 bufferSettings.setSizeUnit( sldUnitSize );
4978 }
4979 }
4980
4981 QDomElement haloFillElem = haloElem.firstChildElement( QStringLiteral( "Fill" ) );
4982 QColor bufferColor;
4983 Qt::BrushStyle bufferBrush = Qt::SolidPattern;
4984 QgsSymbolLayerUtils::fillFromSld( haloFillElem, bufferBrush, bufferColor );
4985 if ( bufferColor.isValid() )
4986 {
4987 QgsDebugMsgLevel( QStringLiteral( "Info: bufferColor %1." ).arg( QVariant( bufferColor ).toString() ), 4 );
4988 bufferSettings.setColor( bufferColor );
4989 }
4990 }
4991
4992 // LabelPlacement
4993 QDomElement labelPlacementElem = textSymbolizerElem.firstChildElement( QStringLiteral( "LabelPlacement" ) );
4994 if ( !labelPlacementElem.isNull() )
4995 {
4996 // PointPlacement
4997 QDomElement pointPlacementElem = labelPlacementElem.firstChildElement( QStringLiteral( "PointPlacement" ) );
4998 if ( !pointPlacementElem.isNull() )
4999 {
5002 {
5004 }
5005
5006 QDomElement displacementElem = pointPlacementElem.firstChildElement( QStringLiteral( "Displacement" ) );
5007 if ( !displacementElem.isNull() )
5008 {
5009 QDomElement displacementXElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementX" ) );
5010 if ( !displacementXElem.isNull() )
5011 {
5012 bool ok;
5013 double xOffset = displacementXElem.text().toDouble( &ok );
5014 if ( ok )
5015 {
5016 settings.xOffset = xOffset;
5017 settings.offsetUnits = sldUnitSize;
5018 }
5019 }
5020 QDomElement displacementYElem = displacementElem.firstChildElement( QStringLiteral( "DisplacementY" ) );
5021 if ( !displacementYElem.isNull() )
5022 {
5023 bool ok;
5024 double yOffset = displacementYElem.text().toDouble( &ok );
5025 if ( ok )
5026 {
5027 settings.yOffset = yOffset;
5028 settings.offsetUnits = sldUnitSize;
5029 }
5030 }
5031 }
5032 QDomElement anchorPointElem = pointPlacementElem.firstChildElement( QStringLiteral( "AnchorPoint" ) );
5033 if ( !anchorPointElem.isNull() )
5034 {
5035 QDomElement anchorPointXElem = anchorPointElem.firstChildElement( QStringLiteral( "AnchorPointX" ) );
5036 if ( !anchorPointXElem.isNull() )
5037 {
5038 bool ok;
5039 double xOffset = anchorPointXElem.text().toDouble( &ok );
5040 if ( ok )
5041 {
5042 settings.xOffset = xOffset;
5043 settings.offsetUnits = sldUnitSize;
5044 }
5045 }
5046 QDomElement anchorPointYElem = anchorPointElem.firstChildElement( QStringLiteral( "AnchorPointY" ) );
5047 if ( !anchorPointYElem.isNull() )
5048 {
5049 bool ok;
5050 double yOffset = anchorPointYElem.text().toDouble( &ok );
5051 if ( ok )
5052 {
5053 settings.yOffset = yOffset;
5054 settings.offsetUnits = sldUnitSize;
5055 }
5056 }
5057 }
5058
5059 QDomElement rotationElem = pointPlacementElem.firstChildElement( QStringLiteral( "Rotation" ) );
5060 if ( !rotationElem.isNull() )
5061 {
5062 bool ok;
5063 double rotation = rotationElem.text().toDouble( &ok );
5064 if ( ok )
5065 {
5066 settings.angleOffset = 360 - rotation;
5067 }
5068 }
5069 }
5070 else
5071 {
5072 // PointPlacement
5073 QDomElement linePlacementElem = labelPlacementElem.firstChildElement( QStringLiteral( "LinePlacement" ) );
5074 if ( !linePlacementElem.isNull() )
5075 {
5077 }
5078 }
5079 }
5080
5081 // read vendor options
5082 QgsStringMap vendorOptions;
5083 QDomElement vendorOptionElem = textSymbolizerElem.firstChildElement( QStringLiteral( "VendorOption" ) );
5084 while ( !vendorOptionElem.isNull() && vendorOptionElem.localName() == QLatin1String( "VendorOption" ) )
5085 {
5086 QString optionName = vendorOptionElem.attribute( QStringLiteral( "name" ) );
5087 QString optionValue;
5088 if ( vendorOptionElem.firstChild().nodeType() == QDomNode::TextNode )
5089 {
5090 optionValue = vendorOptionElem.firstChild().nodeValue();
5091 }
5092 else
5093 {
5094 if ( vendorOptionElem.firstChild().nodeType() == QDomNode::ElementNode &&
5095 vendorOptionElem.firstChild().localName() == QLatin1String( "Literal" ) )
5096 {
5097 QgsDebugMsg( vendorOptionElem.firstChild().localName() );
5098 optionValue = vendorOptionElem.firstChild().firstChild().nodeValue();
5099 }
5100 else
5101 {
5102 QgsDebugMsg( QStringLiteral( "unexpected child of %1 named %2" ).arg( vendorOptionElem.localName(), optionName ) );
5103 }
5104 }
5105
5106 if ( !optionName.isEmpty() && !optionValue.isEmpty() )
5107 {
5108 vendorOptions[ optionName ] = optionValue;
5109 }
5110
5111 vendorOptionElem = vendorOptionElem.nextSiblingElement();
5112 }
5113 if ( !vendorOptions.isEmpty() )
5114 {
5115 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
5116 {
5117 if ( it.key() == QLatin1String( "underlineText" ) && it.value() == QLatin1String( "true" ) )
5118 {
5119 font.setUnderline( true );
5120 format.setFont( font );
5121 }
5122 else if ( it.key() == QLatin1String( "strikethroughText" ) && it.value() == QLatin1String( "true" ) )
5123 {
5124 font.setStrikeOut( true );
5125 format.setFont( font );
5126 }
5127 else if ( it.key() == QLatin1String( "maxDisplacement" ) )
5128 {
5130 }
5131 else if ( it.key() == QLatin1String( "followLine" ) && it.value() == QLatin1String( "true" ) )
5132 {
5134 {
5136 }
5137 else
5138 {
5140 }
5141 }
5142 else if ( it.key() == QLatin1String( "maxAngleDelta" ) )
5143 {
5144 bool ok;
5145 double angle = it.value().toDouble( &ok );
5146 if ( ok )
5147 {
5148 settings.maxCurvedCharAngleIn = angle;
5149 settings.maxCurvedCharAngleOut = angle;
5150 }
5151 }
5152 // miscellaneous options
5153 else if ( it.key() == QLatin1String( "conflictResolution" ) && it.value() == QLatin1String( "false" ) )
5154 {
5156 }
5157 else if ( it.key() == QLatin1String( "forceLeftToRight" ) && it.value() == QLatin1String( "false" ) )
5158 {
5159 settings.upsidedownLabels = Qgis::UpsideDownLabelHandling::AlwaysAllowUpsideDown;
5160 }
5161 else if ( it.key() == QLatin1String( "group" ) && it.value() == QLatin1String( "yes" ) )
5162 {
5163 settings.lineSettings().setMergeLines( true );
5164 }
5165 else if ( it.key() == QLatin1String( "labelAllGroup" ) && it.value() == QLatin1String( "true" ) )
5166 {
5167 settings.lineSettings().setMergeLines( true );
5168 }
5169 }
5170 }
5171
5172 format.setBuffer( bufferSettings );
5173 settings.setFormat( format );
5174 return true;
5175}
5176
5178{
5179 return mEditFormConfig;
5180}
5181
5183{
5184 if ( mEditFormConfig == editFormConfig )
5185 return;
5186
5187 mEditFormConfig = editFormConfig;
5188 mEditFormConfig.onRelationsLoaded();
5189 emit editFormConfigChanged();
5190}
5191
5193{
5194 return mMapTipTemplate;
5195}
5196
5197void QgsVectorLayer::setMapTipTemplate( const QString &mapTip )
5198{
5199 if ( mMapTipTemplate == mapTip )
5200 return;
5201
5202 mMapTipTemplate = mapTip;
5203 emit mapTipTemplateChanged();
5204}
5205
5207{
5208 QgsAttributeTableConfig config = mAttributeTableConfig;
5209
5210 if ( config.isEmpty() )
5211 config.update( fields() );
5212
5213 return config;
5214}
5215
5217{
5218 if ( mAttributeTableConfig != attributeTableConfig )
5219 {
5220 mAttributeTableConfig = attributeTableConfig;
5221 emit configChanged();
5222 }
5223}
5224
5226{
5228}
5229
5231{
5233}
5234
5236{
5237 if ( !mDiagramLayerSettings )
5238 mDiagramLayerSettings = new QgsDiagramLayerSettings();
5239 *mDiagramLayerSettings = s;
5240}
5241
5243{
5244 QgsLayerMetadataFormatter htmlFormatter( metadata() );
5245 QString myMetadata = QStringLiteral( "<html><head></head>\n<body>\n" );
5246
5247 myMetadata += generalHtmlMetadata();
5248
5249 // Begin Provider section
5250 myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
5251 myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
5252
5253 // storage type
5254 if ( !storageType().isEmpty() )
5255 {
5256 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Storage" ) + QStringLiteral( "</td><td>" ) + storageType() + QStringLiteral( "</td></tr>\n" );
5257 }
5258
5259 // comment
5260 if ( !dataComment().isEmpty() )
5261 {
5262 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Comment" ) + QStringLiteral( "</td><td>" ) + dataComment() + QStringLiteral( "</td></tr>\n" );
5263 }
5264
5265 // encoding
5266 const QgsVectorDataProvider *provider = dataProvider();
5267 if ( provider )
5268 {
5269 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Encoding" ) + QStringLiteral( "</td><td>" ) + provider->encoding() + QStringLiteral( "</td></tr>\n" );
5270 }
5271
5272 if ( isSpatial() )
5273 {
5274 // geom type
5276 if ( type < 0 || type > QgsWkbTypes::NullGeometry )
5277 {
5278 QgsDebugMsgLevel( QStringLiteral( "Invalid vector type" ), 2 );
5279 }
5280 else
5281 {
5282 QString typeString( QStringLiteral( "%1 (%2)" ).arg( QgsWkbTypes::geometryDisplayString( geometryType() ),
5284 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Geometry" ) + QStringLiteral( "</td><td>" ) + typeString + QStringLiteral( "</td></tr>\n" );
5285 }
5286
5287 // Extent
5288 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
5289 }
5290
5291 // feature count
5292 QLocale locale = QLocale();
5293 locale.setNumberOptions( locale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
5294 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
5295 + tr( "Feature count" ) + QStringLiteral( "</td><td>" )
5296 + ( featureCount() == -1 ? tr( "unknown" ) : locale.toString( static_cast<qlonglong>( featureCount() ) ) )
5297 + QStringLiteral( "</td></tr>\n" );
5298
5299 // End Provider section
5300 myMetadata += QLatin1String( "</table>\n<br><br>" );
5301
5302 if ( isSpatial() )
5303 {
5304 // CRS
5305 myMetadata += crsHtmlMetadata();
5306 }
5307
5308 // identification section
5309 myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
5310 myMetadata += htmlFormatter.identificationSectionHtml( );
5311 myMetadata += QLatin1String( "<br><br>\n" );
5312
5313 // extent section
5314 myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
5315 myMetadata += htmlFormatter.extentSectionHtml( isSpatial() );
5316 myMetadata += QLatin1String( "<br><br>\n" );
5317
5318 // Start the Access section
5319 myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
5320 myMetadata += htmlFormatter.accessSectionHtml( );
5321 myMetadata += QLatin1String( "<br><br>\n" );
5322
5323 // Fields section
5324 myMetadata += QStringLiteral( "<h1>" ) + tr( "Fields" ) + QStringLiteral( "</h1>\n<hr>\n<table class=\"list-view\">\n" );
5325
5326 // primary key
5328 if ( !pkAttrList.isEmpty() )
5329 {
5330 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Primary key attributes" ) + QStringLiteral( "</td><td>" );
5331 const auto constPkAttrList = pkAttrList;
5332 for ( int idx : constPkAttrList )
5333 {
5334 myMetadata += fields().at( idx ).name() + ' ';
5335 }
5336 myMetadata += QLatin1String( "</td></tr>\n" );
5337 }
5338
5339 const QgsFields myFields = fields();
5340
5341 // count fields
5342 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Count" ) + QStringLiteral( "</td><td>" ) + QString::number( myFields.size() ) + QStringLiteral( "</td></tr>\n" );
5343
5344 myMetadata += QLatin1String( "</table>\n<br><table width=\"100%\" class=\"tabular-view\">\n" );
5345 myMetadata += QLatin1String( "<tr><th>" ) + tr( "Field" ) + QLatin1String( "</th><th>" ) + tr( "Type" ) + QLatin1String( "</th><th>" ) + tr( "Length" ) + QLatin1String( "</th><th>" ) + tr( "Precision" ) + QLatin1String( "</th><th>" ) + tr( "Comment" ) + QLatin1String( "</th></tr>\n" );
5346
5347 for ( int i = 0; i < myFields.size(); ++i )
5348 {
5349 QgsField myField = myFields.at( i );
5350 QString rowClass;
5351 if ( i % 2 )
5352 rowClass = QStringLiteral( "class=\"odd-row\"" );
5353 myMetadata += QLatin1String( "<tr " ) + rowClass + QLatin1String( "><td>" ) + myField.name() + QLatin1String( "</td><td>" ) + myField.typeName() + QLatin1String( "</td><td>" ) + QString::number( myField.length() ) + QLatin1String( "</td><td>" ) + QString::number( myField.precision() ) + QLatin1String( "</td><td>" ) + myField.comment() + QLatin1String( "</td></tr>\n" );
5354 }
5355
5356 //close field list
5357 myMetadata += QLatin1String( "</table>\n<br><br>" );
5358
5359 // Start the contacts section
5360 myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
5361 myMetadata += htmlFormatter.contactsSectionHtml( );
5362 myMetadata += QLatin1String( "<br><br>\n" );
5363
5364 // Start the links section
5365 myMetadata += QStringLiteral( "<h1>" ) + tr( "Links" ) + QStringLiteral( "</h1>\n<hr>\n" );
5366 myMetadata += htmlFormatter.linksSectionHtml( );
5367 myMetadata += QLatin1String( "<br><br>\n" );
5368
5369 // Start the history section
5370 myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
5371 myMetadata += htmlFormatter.historySectionHtml( );
5372 myMetadata += QLatin1String( "<br><br>\n" );
5373
5374 myMetadata += QLatin1String( "\n</body>\n</html>\n" );
5375 return myMetadata;
5376}
5377
5378void QgsVectorLayer::invalidateSymbolCountedFlag()
5379{
5380 mSymbolFeatureCounted = false;
5381}
5382
5383void QgsVectorLayer::onFeatureCounterCompleted()
5384{
5385 onSymbolsCounted();
5386 mFeatureCounter = nullptr;
5387}
5388
5389void QgsVectorLayer::onFeatureCounterTerminated()
5390{
5391 mFeatureCounter = nullptr;
5392}
5393
5394void QgsVectorLayer::onJoinedFieldsChanged()
5395{
5396 // some of the fields of joined layers have changed -> we need to update this layer's fields too
5397 updateFields();
5398}
5399
5400void QgsVectorLayer::onFeatureDeleted( QgsFeatureId fid )
5401{
5402 if ( mEditCommandActive || mCommitChangesActive )
5403 {
5404 mDeletedFids << fid;
5405 }
5406 else
5407 {
5408 mSelectedFeatureIds.remove( fid );
5409 emit featuresDeleted( QgsFeatureIds() << fid );
5410 }
5411
5412 emit featureDeleted( fid );
5413}
5414
5415void QgsVectorLayer::onRelationsLoaded()
5416{
5417 mEditFormConfig.onRelationsLoaded();
5418}
5419
5420void QgsVectorLayer::onSymbolsCounted()
5421{
5422 if ( mFeatureCounter )
5423 {
5424 mSymbolFeatureCounted = true;
5425 mSymbolFeatureCountMap = mFeatureCounter->symbolFeatureCountMap();
5426 mSymbolFeatureIdMap = mFeatureCounter->symbolFeatureIdMap();
5428 }
5429}
5430
5431QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx ) const
5432{
5434}
5435
5436QList<QgsWeakRelation> QgsVectorLayer::weakRelations() const
5437{
5438 return mWeakRelations;
5439}
5440
5441void QgsVectorLayer::setWeakRelations( const QList<QgsWeakRelation> &relations )
5442{
5443 mWeakRelations = relations;
5444}
5445
5446int QgsVectorLayer::listStylesInDatabase( QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError )
5447{
5448 return QgsProviderRegistry::instance()->listStyles( mProviderKey, mDataSource, ids, names, descriptions, msgError );
5449}
5450
5451QString QgsVectorLayer::getStyleFromDatabase( const QString &styleId, QString &msgError )
5452{
5453 return QgsProviderRegistry::instance()->getStyleById( mProviderKey, mDataSource, styleId, msgError );
5454}
5455
5456bool QgsVectorLayer::deleteStyleFromDatabase( const QString &styleId, QString &msgError )
5457{
5459}
5460
5461
5462void QgsVectorLayer::saveStyleToDatabase( const QString &name, const QString &description,
5463 bool useAsDefault, const QString &uiFileContent, QString &msgError, QgsMapLayer::StyleCategories categories )
5464{
5465
5466 QString sldStyle, qmlStyle;
5467 QDomDocument qmlDocument, sldDocument;
5468 QgsReadWriteContext context;
5469 exportNamedStyle( qmlDocument, msgError, context, categories );
5470 if ( !msgError.isNull() )
5471 {
5472 return;
5473 }
5474 qmlStyle = qmlDocument.toString();
5475
5476 this->exportSldStyle( sldDocument, msgError );
5477 if ( !msgError.isNull() )
5478 {
5479 return;
5480 }
5481 sldStyle = sldDocument.toString();
5482
5484 mDataSource, qmlStyle, sldStyle, name,
5485 description, uiFileContent, useAsDefault, msgError );
5486}
5487
5488
5489
5490QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, QgsMapLayer::StyleCategories categories )
5491{
5492 return loadNamedStyle( theURI, resultFlag, false, categories );
5493}
5494
5495bool QgsVectorLayer::loadAuxiliaryLayer( const QgsAuxiliaryStorage &storage, const QString &key )
5496{
5497 bool rc = false;
5498
5499 QString joinKey = mAuxiliaryLayerKey;
5500 if ( !key.isEmpty() )
5501 joinKey = key;
5502
5503 if ( storage.isValid() && !joinKey.isEmpty() )
5504 {
5505 QgsAuxiliaryLayer *alayer = nullptr;
5506
5507 int idx = fields().lookupField( joinKey );
5508
5509 if ( idx >= 0 )
5510 {
5511 alayer = storage.createAuxiliaryLayer( fields().field( idx ), this );
5512
5513 if ( alayer )
5514 {
5515 setAuxiliaryLayer( alayer );
5516 rc = true;
5517 }
5518 }
5519 }
5520
5521 return rc;
5522}
5523
5525{
5526 mAuxiliaryLayerKey.clear();
5527
5528 if ( mAuxiliaryLayer )
5529 removeJoin( mAuxiliaryLayer->id() );
5530
5531 if ( alayer )
5532 {
5533 addJoin( alayer->joinInfo() );
5534
5535 if ( !alayer->isEditable() )
5536 alayer->startEditing();
5537
5538 mAuxiliaryLayerKey = alayer->joinInfo().targetFieldName();
5539 }
5540
5541 mAuxiliaryLayer.reset( alayer );
5542 if ( mAuxiliaryLayer )
5543 mAuxiliaryLayer->setParent( this );
5544 updateFields();
5545}
5546
5548{
5549 return mAuxiliaryLayer.get();
5550}
5551
5553{
5554 return mAuxiliaryLayer.get();
5555}
5556
5557QString QgsVectorLayer::loadNamedStyle( const QString &theURI, bool &resultFlag, bool loadFromLocalDB, QgsMapLayer::StyleCategories categories )
5558{
5559 QgsDataSourceUri dsUri( theURI );
5560 QString returnMessage;
5561 QString qml, errorMsg;
5562 if ( !loadFromLocalDB && mDataProvider && mDataProvider->isSaveAndLoadStyleToDatabaseSupported() )
5563 {
5565 }
5566 if ( !qml.isEmpty() )
5567 {
5568 QDomDocument myDocument( QStringLiteral( "qgis" ) );
5569 myDocument.setContent( qml );
5570 resultFlag = importNamedStyle( myDocument, errorMsg );
5571 returnMessage = QObject::tr( "Loaded from Provider" );
5572 }
5573 else
5574 {
5575 returnMessage = QgsMapLayer::loadNamedStyle( theURI, resultFlag, categories );
5576 }
5577
5578 if ( resultFlag )
5579 emit styleLoaded( categories );
5580
5581 return returnMessage;
5582}
5583
5584QSet<QgsMapLayerDependency> QgsVectorLayer::dependencies() const
5585{
5586 if ( mDataProvider )
5587 return mDataProvider->dependencies() + mDependencies;
5588 return mDependencies;
5589}
5590
5591void QgsVectorLayer::emitDataChanged()
5592{
5593 if ( mDataChangedFired )
5594 return;
5595
5596 updateExtents(); // reset cached extent to reflect data changes
5597
5598 mDataChangedFired = true;
5599 emit dataChanged();
5600 mDataChangedFired = false;
5601}
5602
5603void QgsVectorLayer::onAfterCommitChangesDependency()
5604{
5605 mDataChangedFired = true;
5606 reload();
5607 mDataChangedFired = false;
5608}
5609
5610bool QgsVectorLayer::setDependencies( const QSet<QgsMapLayerDependency> &oDeps )
5611{
5612 QSet<QgsMapLayerDependency> deps;
5613 const auto constODeps = oDeps;
5614 for ( const QgsMapLayerDependency &dep : constODeps )
5615 {
5616 if ( dep.origin() == QgsMapLayerDependency::FromUser )
5617 deps << dep;
5618 }
5619
5620 QSet<QgsMapLayerDependency> toAdd = deps - dependencies();
5621
5622 // disconnect layers that are not present in the list of dependencies anymore
5623 for ( const QgsMapLayerDependency &dep : std::as_const( mDependencies ) )
5624 {
5625 QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
5626 if ( !lyr )
5627 continue;
5628 disconnect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::emitDataChanged );
5629 disconnect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::emitDataChanged );
5630 disconnect( lyr, &QgsVectorLayer::geometryChanged, this, &QgsVectorLayer::emitDataChanged );
5631 disconnect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::emitDataChanged );
5633 disconnect( lyr, &QgsVectorLayer::afterCommitChanges, this, &QgsVectorLayer::onAfterCommitChangesDependency );
5634 }
5635
5636 // assign new dependencies
5637 if ( mDataProvider )
5638 mDependencies = mDataProvider->dependencies() + deps;
5639 else
5640 mDependencies = deps;
5641 emit dependenciesChanged();
5642
5643 // connect to new layers
5644 for ( const QgsMapLayerDependency &dep : std::as_const( mDependencies ) )
5645 {
5646 QgsVectorLayer *lyr = static_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( dep.layerId() ) );
5647 if ( !lyr )
5648 continue;
5649 connect( lyr, &QgsVectorLayer::featureAdded, this, &QgsVectorLayer::emitDataChanged );
5650 connect( lyr, &QgsVectorLayer::featureDeleted, this, &QgsVectorLayer::emitDataChanged );
5651 connect( lyr, &QgsVectorLayer::geometryChanged, this, &QgsVectorLayer::emitDataChanged );
5652 connect( lyr, &QgsVectorLayer::dataChanged, this, &QgsVectorLayer::emitDataChanged );
5654 connect( lyr, &QgsVectorLayer::afterCommitChanges, this, &QgsVectorLayer::onAfterCommitChangesDependency );
5655 }
5656
5657 // if new layers are present, emit a data change
5658 if ( ! toAdd.isEmpty() )
5659 emitDataChanged();
5660
5661 return true;
5662}
5663
5664QgsFieldConstraints::Constraints QgsVectorLayer::fieldConstraints( int fieldIndex ) const
5665{
5666 if ( fieldIndex < 0 || fieldIndex >= mFields.count() || !mDataProvider )
5667 return QgsFieldConstraints::Constraints();
5668
5669 QgsFieldConstraints::Constraints constraints = mFields.at( fieldIndex ).constraints().constraints();
5670
5671 // make sure provider constraints are always present!
5672 if ( mFields.fieldOrigin( fieldIndex ) == QgsFields::OriginProvider )
5673 {
5674 constraints |= mDataProvider->fieldConstraints( mFields.fieldOriginIndex( fieldIndex ) );
5675 }
5676
5677 return constraints;
5678}
5679
5680QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength> QgsVectorLayer::fieldConstraintsAndStrength( int fieldIndex ) const
5681{
5682 QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength > m;
5683
5684 if ( fieldIndex < 0 || fieldIndex >= mFields.count() )
5685 return m;
5686
5687 QString name = mFields.at( fieldIndex ).name();
5688
5689 QMap< QPair< QString, QgsFieldConstraints::Constraint >, QgsFieldConstraints::ConstraintStrength >::const_iterator conIt = mFieldConstraintStrength.constBegin();
5690 for ( ; conIt != mFieldConstraintStrength.constEnd(); ++conIt )
5691 {
5692 if ( conIt.key().first == name )
5693 {
5694 m[ conIt.key().second ] = mFieldConstraintStrength.value( conIt.key() );
5695 }
5696 }
5697
5698 return m;
5699}
5700
5702{
5703 if ( index < 0 || index >= mFields.count() )
5704 return;
5705
5706 QString name = mFields.at( index ).name();
5707
5708 // add constraint to existing constraints
5709 QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, QgsFieldConstraints::Constraints() );
5710 constraints |= constraint;
5711 mFieldConstraints.insert( name, constraints );
5712
5713 mFieldConstraintStrength.insert( qMakePair( name, constraint ), strength );
5714
5715 updateFields();
5716}
5717
5719{
5720 if ( index < 0 || index >= mFields.count() )
5721 return;
5722
5723 QString name = mFields.at( index ).name();
5724
5725 // remove constraint from existing constraints
5726 QgsFieldConstraints::Constraints constraints = mFieldConstraints.value( name, QgsFieldConstraints::Constraints() );
5727 constraints &= ~constraint;
5728 mFieldConstraints.insert( name, constraints );
5729
5730 mFieldConstraintStrength.remove( qMakePair( name, constraint ) );
5731
5732 updateFields();
5733}
5734
5736{
5737 if ( index < 0 || index >= mFields.count() )
5738 return QString();
5739
5740 return mFields.at( index ).constraints().constraintExpression();
5741}
5742
5744{
5745 if ( index < 0 || index >= mFields.count() )
5746 return QString();
5747
5748 return mFields.at( index ).constraints().constraintDescription();
5749}
5750
5751void QgsVectorLayer::setConstraintExpression( int index, const QString &expression, const QString &description )
5752{
5753 if ( index < 0 || index >= mFields.count() )
5754 return;
5755
5756 if ( expression.isEmpty() )
5757 {
5758 mFieldConstraintExpressions.remove( mFields.at( index ).name() );
5759 }
5760 else
5761 {
5762 mFieldConstraintExpressions.insert( mFields.at( index ).name(), qMakePair( expression, description ) );
5763 }
5764 updateFields();
5765}
5766
5767void QgsVectorLayer::setFieldConfigurationFlags( int index, QgsField::ConfigurationFlags flags )
5768{
5769 if ( index < 0 || index >= mFields.count() )
5770 return;
5771
5772 mFieldConfigurationFlags.insert( mFields.at( index ).name(), flags );
5773 updateFields();
5774}
5775
5777{
5778 if ( index < 0 || index >= mFields.count() )
5779 return;
5780 QgsField::ConfigurationFlags flags = mFields.at( index ).configurationFlags();
5781 flags.setFlag( flag, active );
5783}
5784
5785QgsField::ConfigurationFlags QgsVectorLayer::fieldConfigurationFlags( int index ) const
5786{
5787
5788 if ( index < 0 || index >= mFields.count() )
5790
5791 return mFields.at( index ).configurationFlags();
5792}
5793
5795{
5796 if ( index < 0 || index >= mFields.count() )
5797 return;
5798
5799 if ( setup.isNull() )
5800 mFieldWidgetSetups.remove( mFields.at( index ).name() );
5801 else
5802 mFieldWidgetSetups.insert( mFields.at( index ).name(), setup );
5803 updateFields();
5804}
5805
5807{
5808
5809 if ( index < 0 || index >= mFields.count() )
5810 return QgsEditorWidgetSetup();
5811
5812 return mFields.at( index ).editorWidgetSetup();
5813}
5814
5815QgsAbstractVectorLayerLabeling *QgsVectorLayer::readLabelingFromCustomProperties()
5816{
5818 if ( customProperty( QStringLiteral( "labeling" ) ).toString() == QLatin1String( "pal" ) )
5819 {
5820 if ( customProperty( QStringLiteral( "labeling/enabled" ), QVariant( false ) ).toBool() )
5821 {
5822 // try to load from custom properties
5823 QgsPalLayerSettings settings;
5824 settings.readFromLayerCustomProperties( this );
5825 labeling = new QgsVectorLayerSimpleLabeling( settings );
5826 }
5827
5828 // also clear old-style labeling config
5829 removeCustomProperty( QStringLiteral( "labeling" ) );
5830 const auto constCustomPropertyKeys = customPropertyKeys();
5831 for ( const QString &key : constCustomPropertyKeys )
5832 {
5833 if ( key.startsWith( QLatin1String( "labeling/" ) ) )
5834 removeCustomProperty( key );
5835 }
5836 }
5837
5838 return labeling;
5839}
5840
5842{
5843 return mAllowCommit;
5844}
5845
5846void QgsVectorLayer::setAllowCommit( bool allowCommit )
5847{
5848 if ( mAllowCommit == allowCommit )
5849 return;
5850
5851 mAllowCommit = allowCommit;
5852 emit allowCommitChanged();
5853}
5854
5856{
5857 return mGeometryOptions.get();
5858}
5859
5860void QgsVectorLayer::setReadExtentFromXml( bool readExtentFromXml )
5861{
5862 mReadExtentFromXml = readExtentFromXml;
5863}
5864
5866{
5867 return mReadExtentFromXml;
5868}
5869
5870void QgsVectorLayer::onDirtyTransaction( const QString &sql, const QString &name )
5871{
5873 if ( tr && mEditBuffer )
5874 {
5875 qobject_cast<QgsVectorLayerEditPassthrough *>( mEditBuffer )->update( tr, sql, name );
5876 }
5877}
5878
5879QList<QgsVectorLayer *> QgsVectorLayer::DeleteContext::handledLayers( bool includeAuxiliaryLayers ) const
5880{
5881 QList<QgsVectorLayer *> layers;
5882 QMap<QgsVectorLayer *, QgsFeatureIds>::const_iterator i;
5883 for ( i = mHandledFeatures.begin(); i != mHandledFeatures.end(); ++i )
5884 {
5885 if ( includeAuxiliaryLayers || !qobject_cast< QgsAuxiliaryLayer * >( i.key() ) )
5886 layers.append( i.key() );
5887 }
5888 return layers;
5889}
5890
5892{
5893 return mHandledFeatures[layer];
5894}
@ 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...
GeometryOperationResult
Success or failure of a geometry operation.
Definition: qgis.h:955
@ InvalidInputGeometryType
The input geometry (ring, part, split line, etc.) has not the correct geometry type.
@ Success
Operation succeeded.
@ SelectionIsEmpty
No features were selected.
@ AddRingNotInExistingFeature
The input ring doesn't have any existing ring to fit into.
@ AddRingNotClosed
The input ring is not closed.
@ SelectionIsGreaterThanOne
More than one features were selected.
@ LayerNotEditable
Cannot edit layer.
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
@ Curved
Arranges candidates following the curvature of a line feature. Applies to line layers only.
@ AroundPoint
Arranges candidates in a circle around a point (or centroid of a polygon). Applies to point or polygo...
@ Line
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon'...
@ Horizontal
Arranges horizontal candidates scattered throughout a polygon feature. Applies to polygon layers only...
@ PerimeterCurved
Arranges candidates following the curvature of a polygon's boundary. Applies to polygon layers only.
@ BufferedGroups
Buffered transactional editing means that all editable layers in the buffered transaction group are t...
@ Generated
A generated relation is a child of a polymorphic relation.
@ Normal
A normal relation.
VertexMarkerType
Editing vertex markers, used for showing vertices during a edit operation.
Definition: qgis.h:860
@ SemiTransparentCircle
Semi-transparent circle marker.
@ Cross
Cross marker.
VectorEditResult
Flags which control feature selection behavior.
Definition: qgis.h:845
@ Success
Edit operation was successful.
@ InvalidLayer
Edit failed due to invalid layer.
@ AllowOverlapIfRequired
Avoids overlapping labels when possible, but permit overlaps if labels for features cannot otherwise ...
SelectBehavior
Specifies how a selection should be applied.
Definition: qgis.h:798
@ SetSelection
Set selection, removing any existing selection.
@ AddToSelection
Add selection to current selection.
@ IntersectSelection
Modify current selection to include only select features which match.
@ RemoveFromSelection
Remove from current selection.
Abstract base class for objects which generate elevation profiles.
virtual bool writeXml(QDomElement &collectionElem, const QgsPropertiesDefinition &definitions) const
Writes the current state of the property collection into an XML element.
Abstract base class - its implementations define different approaches to the labeling of a vector lay...
virtual bool accept(QgsStyleEntityVisitorInterface *visitor) const
Accepts the specified symbology visitor, causing it to visit all symbols associated with the labeling...
virtual void toSld(QDomNode &parent, const QVariantMap &props) const
Writes the SE 1.1 TextSymbolizer element based on the current layer labeling settings.
static QgsAbstractVectorLayerLabeling * create(const QDomElement &element, const QgsReadWriteContext &context)
Try to create instance of an implementation based on the XML data.
virtual QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) const =0
Returns labeling configuration as XML element.
Storage and management of actions associated with a layer.
bool writeXml(QDomNode &layer_node) const
Writes the actions out in XML format.
QList< QgsAction > actions(const QString &actionScope=QString()) const
Returns a list of actions that are available in the given action scope.
QUuid addAction(QgsAction::ActionType type, const QString &name, const QString &command, bool capture=false)
Add an action with the given name and action details.
bool readXml(const QDomNode &layer_node)
Reads the actions in in XML format.
Utility class that encapsulates an action based on vector attributes.
Definition: qgsaction.h:35
Utility class for calculating aggregates for a field (or expression) over the features from a vector ...
Aggregate
Available aggregates to calculate.
static QgsRuntimeProfiler * profiler()
Returns the application runtime profiler.
static QgsTaskManager * taskManager()
Returns the application's task manager, used for managing application wide background task handling.
This is a container for configuration of the attribute table.
bool isEmpty() const
Returns true if the configuration is empty, ie it contains no columns.
void readXml(const QDomNode &node)
Deserialize to XML on layer load.
void update(const QgsFields &fields)
Update the configuration with the given fields.
void writeXml(QDomNode &node) const
Serialize to XML on layer save.
A vector of attributes.
Definition: qgsattributes.h:59
Class allowing to manage the auxiliary storage for a vector layer.
QgsVectorLayerJoinInfo joinInfo() const
Returns information to use for joining with primary key and so on.
Class providing some utility methods to manage auxiliary storage.
QgsAuxiliaryLayer * createAuxiliaryLayer(const QgsField &field, QgsVectorLayer *layer) const
Creates an auxiliary layer for a vector layer.
bool isValid() const
Returns the status of the auxiliary storage currently defined.
The QgsConditionalLayerStyles class holds conditional style information for a layer.
bool readXml(const QDomNode &node, const QgsReadWriteContext &context)
Reads the condition styles state from a DOM node.
bool writeXml(QDomNode &node, QDomDocument &doc, const QgsReadWriteContext &context) const
Writes the condition styles state to a DOM node.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Contains information about the context in which a coordinate transform is executed.
Abstract base class for curved geometry type.
Definition: qgscurve.h:36
virtual bool isClosed() const SIP_HOLDGIL
Returns true if the curve is closed.
Definition: qgscurve.cpp:53
QgsCurve * clone() const override=0
Clones the geometry by performing a deep copy.
virtual bool leaveUpdateMode()
Leave update mode.
@ FlagLoadDefaultStyle
Reset the layer's style to the default for the datasource.
@ FlagTrustDataSource
Trust datasource config (primary key unicity, geometry type and srid, etc). Improves provider load ti...
@ ForceReadOnly
Open layer in a read-only mode (since QGIS 3.28)
QgsCoordinateTransformContext transformContext() const
Returns data provider coordinate transform context.
virtual QgsCoordinateReferenceSystem crs() const =0
Returns the coordinate system for the data source.
void dataChanged()
Emitted whenever a change is made to the data provider which may have caused changes in the provider'...
void fullExtentCalculated()
Emitted whenever a deferred extent calculation is completed by the provider.
virtual QString subsetString() const
Returns the subset definition string (typically sql) currently in use by the layer and used by the pr...
virtual QgsLayerMetadata layerMetadata() const
Returns layer metadata collected from the provider's source.
virtual bool isValid() const =0
Returns true if this is a valid layer.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
virtual void updateExtents()
Update the extents of the layer.
virtual bool setSubsetString(const QString &subset, bool updateFeatureCount=true)
Set the subset string used to create a subset of features in the layer.
virtual void reloadData()
Reloads the data from the source for providers with data caches to synchronize, changes in the data s...
virtual bool enterUpdateMode()
Enter update mode.
virtual QgsRectangle extent() const =0
Returns the extent of the layer.
virtual void setTransformContext(const QgsCoordinateTransformContext &transformContext)
Sets data coordinate transform context to transformContext.
Class for storing the component parts of a RDBMS data source URI (e.g.
void setConnection(const QString &aHost, const QString &aPort, const QString &aDatabase, const QString &aUsername, const QString &aPassword, SslMode sslmode=SslPrefer, const QString &authConfigId=QString())
Sets all connection related members at once.
QString uri(bool expandAuthConfig=true) const
Returns the complete URI as a string.
QString username() const
Returns the username stored in the URI.
QString host() const
Returns the host name stored in the URI.
bool useEstimatedMetadata() const
Returns true if estimated metadata should be used for the connection.
QString password() const
Returns the password stored in the URI.
QString port() const
Returns the port stored in the URI.
QString database() const
Returns the database name stored in the URI.
void setDatabase(const QString &database)
Sets the URI database name.
The QgsDefaultValue class provides a container for managing client side default values for fields.
Q_GADGET QString expression
bool isValid() const
Returns if this default value should be applied.
Stores the settings for rendering of all diagrams for a layer.
@ PositionX
X-coordinate data defined diagram position.
@ Show
Whether to show the diagram.
@ PositionY
Y-coordinate data defined diagram position.
void readXml(const QDomElement &elem)
Reads the diagram settings from a DOM element.
void writeXml(QDomElement &layerElem, QDomDocument &doc) const
Writes the diagram settings to a DOM element.
Evaluates and returns the diagram settings relating to a diagram for a specific feature.
virtual void writeXml(QDomElement &layerElem, QDomDocument &doc, const QgsReadWriteContext &context) const =0
Writes diagram state to a DOM element.
virtual QList< QgsDiagramSettings > diagramSettings() const =0
Returns list with all diagram settings in the renderer.
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)=0
Reads diagram state from a DOM element.
Contains configuration settings for an editor form.
void readXml(const QDomNode &node, QgsReadWriteContext &context)
Read XML information Deserialize on project load.
void writeXml(QDomNode &node, const QgsReadWriteContext &context) const
Write XML information Serialize on project save.
Holder for the widget type and its configuration for a field.
QVariantMap config() const
void clear()
Clear error messages.
Definition: qgserror.h:127
Single scope for storing variables and functions for use within a QgsExpressionContext.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the scope.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the scope.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Buffers information about expression fields for a vector layer.
void removeExpression(int index)
Remove an expression from the buffer.
void writeXml(QDomNode &layer_node, QDomDocument &document) const
Saves expressions to xml under the layer node.
void readXml(const QDomNode &layer_node)
Reads expressions from project file.
void updateFields(QgsFields &flds) const
Adds fields with the expressions buffered in this object to a QgsFields object.
void addExpression(const QString &exp, const QgsField &fld)
Add an expression to the buffer.
QList< QgsExpressionFieldBuffer::ExpressionField > expressions() const
void updateExpression(int index, const QString &exp)
Changes the expression at a given index.
void renameExpression(int index, const QString &name)
Renames an expression field at a given index.
An expression node which takes it value from a feature's field.
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.
QString expression() const
Returns the original, unmodified expression string.
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.
bool isField() const
Checks whether an expression consists only of a single field reference.
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
static int expressionToLayerFieldIndex(const QString &expression, const QgsVectorLayer *layer)
Attempts to resolve an expression to a field index from the given layer.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
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)
An interface for objects which generate feature renderers for vector layers.
static QgsFeatureRenderer * defaultRenderer(QgsWkbTypes::GeometryType geomType)
Returns a new renderer - used by default in vector layers.
Definition: qgsrenderer.cpp:79
virtual void toSld(QDomDocument &doc, QDomElement &element, const QVariantMap &props=QVariantMap()) const
used from subclasses to create SLD Rule elements following SLD v1.1 specs
Definition: qgsrenderer.h:326
virtual QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context)
Stores renderer properties to an XML element.
double referenceScale() const
Returns the symbology reference scale.
Definition: qgsrenderer.h:466
static QgsFeatureRenderer * loadSld(const QDomNode &node, QgsWkbTypes::GeometryType geomType, QString &errorMessage)
Create a new renderer according to the information contained in the UserStyle element of a SLD style ...
void setReferenceScale(double scale)
Sets the symbology reference scale.
Definition: qgsrenderer.h:482
static QgsFeatureRenderer * load(QDomElement &symbologyElem, const QgsReadWriteContext &context)
create a renderer from XML element
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 & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
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.
@ SubsetOfAttributes
Fetch only a subset of attributes (setSubsetOfAttributes sets this flag)
@ ExactIntersect
Use exact geometry intersection (slower) instead of bounding boxes.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets the feature ID that should be fetched.
virtual bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags())
Adds a single feature to the sink.
virtual QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const
Returns the set of unique values contained within the specified fieldIndex from this source.
SpatialIndexPresence
Enumeration of spatial index presence states.
@ SpatialIndexUnknown
Spatial index presence cannot be determined, index may or may not exist.
FeatureAvailability
Possible return value for hasFeatures() to determine if a source is empty.
virtual QgsFeatureIds allFeatureIds() const
Returns a list of all feature IDs for features present in the source.
virtual SpatialIndexPresence hasSpatialIndex() const
Returns an enum value representing the presence of a valid spatial index on the source,...
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
QgsGeometry geometry
Definition: qgsfeature.h:67
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:233
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.
void setConstraintStrength(Constraint constraint, ConstraintStrength strength)
Sets the strength of a constraint.
void setConstraintExpression(const QString &expression, const QString &description=QString())
Set the constraint expression for the field.
@ ConstraintOriginProvider
Constraint was set at data provider.
@ ConstraintOriginLayer
Constraint was set by layer.
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.
Constraint
Constraints which may be present on a field.
@ 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
void setConstraint(Constraint constraint, ConstraintOrigin origin=ConstraintOriginLayer)
Sets a constraint on the field.
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
QString typeName() const
Gets the field type.
Definition: qgsfield.cpp:140
QString name
Definition: qgsfield.h:60
int precision
Definition: qgsfield.h:57
int length
Definition: qgsfield.h:56
QString displayName() const
Returns the name to use when displaying this field.
Definition: qgsfield.cpp:90
ConfigurationFlags configurationFlags
Definition: qgsfield.h:64
QString alias
Definition: qgsfield.h:61
QgsDefaultValue defaultValueDefinition
Definition: qgsfield.h:62
QString comment
Definition: qgsfield.h:59
QgsFieldConstraints constraints
Definition: qgsfield.h:63
ConfigurationFlag
Configuration flags for fields These flags are meant to be user-configurable and are not describing a...
Definition: qgsfield.h:80
@ HideFromWfs
Field is not available if layer is served as WFS from QGIS server.
@ None
No flag is defined.
@ HideFromWms
Field is not available if layer is served as WMS from QGIS server.
QgsEditorWidgetSetup editorWidgetSetup() const
Gets the editor widget setup for the field.
Definition: qgsfield.cpp:631
Container of fields for a vector layer.
Definition: qgsfields.h:45
int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:202
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
Definition: qgsfields.cpp:207
@ OriginExpression
Field is calculated from an expression.
Definition: qgsfields.h:54
@ OriginEdit
Field has been temporarily added in editing mode (originIndex = index in the list of added attributes...
Definition: qgsfields.h:53
@ OriginUnknown
It has not been specified where the field comes from.
Definition: qgsfields.h:50
@ 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
QStringList names() const
Returns a list with field names.
Definition: qgsfields.cpp:143
The QgsGeometryOptions class contains options to automatically adjust geometries to constraints on a ...
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:164
bool equals(const QgsGeometry &geometry) const
Test if this geometry is exactly equal to another geometry.
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:167
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
void setMergeLines(bool merge)
Sets whether connected line features with identical label text should be merged prior to generating l...
void setOverlapHandling(Qgis::LabelOverlapHandling handling)
Sets the technique used to handle overlapping labels.
Class for metadata formatter.
QString linksSectionHtml() const
Formats the "Links" section according to a metadata object.
QString extentSectionHtml(const bool showSpatialExtent=true) const
Formats the "Extents" section according to a metadata object (extent and temporal).
QString contactsSectionHtml() const
Formats the "Contacts" section according to a metadata object.
QString identificationSectionHtml() const
Formats the "Identification" section according to a metadata object.
QString historySectionHtml() const
Formats the "History" section according to a metadata object.
QString accessSectionHtml() const
Formats the "Access" section according to a metadata object.
A structured metadata store for a map layer.
void combine(const QgsAbstractMetadataBase *other) override
Combines the metadata from this object with the metadata from an other object.
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:45
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:122
This class models dependencies with or between map layers.
Base class for storage of map layer elevation properties.
static QString typeToString(QgsMapLayerType type)
Converts a map layer type to a string value.
virtual void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads configuration from a DOM element previously written by writeXml()
virtual QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Writes configuration to a DOM element, to be used later with readXml()
static QgsMapLayerLegend * defaultVectorLegend(QgsVectorLayer *vl)
Create new legend implementation for vector layer.
Base class for utility classes that encapsulate information necessary for rendering of map layers.
Base class for storage of map layer temporal properties.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QString name
Definition: qgsmaplayer.h:76
void readStyleManager(const QDomNode &layerNode)
Read style manager's configuration (if any). To be called by subclasses.
virtual void exportNamedStyle(QDomDocument &doc, QString &errorMsg, const QgsReadWriteContext &context=QgsReadWriteContext(), QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const
Export the properties of this layer as named style in a QDomDocument.
void dependenciesChanged()
Emitted when dependencies are changed.
void writeStyleManager(QDomNode &layerNode, QDomDocument &doc) const
Write style manager's configuration (if exists). To be called by subclasses.
QgsMapLayerLegend * legend() const
Can be nullptr.
virtual bool importNamedStyle(QDomDocument &doc, QString &errorMsg, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Import the properties of this layer from a QDomDocument.
void editingStopped()
Emitted when edited changes have been successfully written to the data provider.
void recalculateExtents() const
This is used to send a request that any mapcanvas using this layer update its extents.
virtual QgsRectangle extent() const
Returns the extent of the layer.
QString source() const
Returns the source for the layer.
Q_INVOKABLE QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
int mBlockStyleChangedSignal
If non-zero, the styleChanged signal should not be emitted.
Definition: qgsmaplayer.h:2009
QString providerType() const
Returns the provider type (provider key) for this layer.
void removeCustomProperty(const QString &key)
Remove a custom property from layer.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
QgsMapLayerType type
Definition: qgsmaplayer.h:80
void configChanged()
Emitted whenever the configuration is changed.
void setMinimumScale(double scale)
Sets the minimum map scale (i.e.
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
QgsMapLayer::LayerFlags flags() const
Returns the flags for this layer.
void editingStarted()
Emitted when editing on this layer has started.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
friend class QgsVectorLayer
Definition: qgsmaplayer.h:2130
void writeCustomProperties(QDomNode &layerNode, QDomDocument &doc) const
Write custom properties to project file.
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
QString crsHtmlMetadata() const
Returns a HTML fragment containing the layer's CRS metadata, for use in the htmlMetadata() method.
void setMaximumScale(double scale)
Sets the maximum map scale (i.e.
QgsLayerMetadata metadata
Definition: qgsmaplayer.h:78
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
virtual void setOpacity(double opacity)
Sets the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
void setFlags(QgsMapLayer::LayerFlags flags)
Returns the flags for this layer.
QSet< QgsMapLayerDependency > mDependencies
List of layers that may modify this layer on modification.
Definition: qgsmaplayer.h:1970
void readCustomProperties(const QDomNode &layerNode, const QString &keyStartsWith=QString())
Read custom properties from project file.
virtual void setMetadata(const QgsLayerMetadata &metadata)
Sets the layer's metadata store.
Q_INVOKABLE void setCustomProperty(const QString &key, const QVariant &value)
Set a custom property for layer.
QString mProviderKey
Data provider key (name of the data provider)
Definition: qgsmaplayer.h:1983
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
void styleChanged()
Signal emitted whenever a change affects the layer's style.
QUndoStack * undoStack()
Returns pointer to layer's undo stack.
void rendererChanged()
Signal emitted when renderer is changed.
virtual QgsError error() const
Gets current status error.
void setScaleBasedVisibility(bool enabled)
Sets whether scale based visibility is enabled for the layer.
void dataSourceChanged()
Emitted whenever the layer's data source has been changed.
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
virtual QString loadNamedStyle(const QString &uri, bool &resultFlag, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Retrieve a named style for this layer if one exists (either as a .qml file on disk or as a record in ...
void styleLoaded(QgsMapLayer::StyleCategories categories)
Emitted when a style has been loaded.
void emitStyleChanged()
Triggers an emission of the styleChanged() signal.
void dataChanged()
Data of layer changed.
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
void setName(const QString &name)
Set the display name of the layer.
virtual void setExtent(const QgsRectangle &rect)
Sets the extent.
virtual void resolveReferences(QgsProject *project)
Resolve references to other layers (kept as layer IDs after reading XML) into layer objects.
bool isValid
Definition: qgsmaplayer.h:81
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:1942
@ FlagReadExtentFromXml
Read extent from xml and skip get extent from provider.
Definition: qgsmaplayer.h:642
@ FlagTrustLayerMetadata
Trust layer metadata. Improves layer load time by skipping expensive checks like primary key unicity,...
Definition: qgsmaplayer.h:641
@ FlagForceReadOnly
Force open as read only.
Definition: qgsmaplayer.h:643
@ FlagDontResolveLayers
Don't resolve layer paths or create data providers for layers.
Definition: qgsmaplayer.h:640
void setValid(bool valid)
Sets whether layer is valid or not.
void readCommonStyle(const QDomElement &layerElement, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)
Read style data common to all layer types.
QgsMapLayer::ReadFlags mReadFlags
Read flags. It's up to the subclass to respect these when restoring state from XML.
Definition: qgsmaplayer.h:1988
void setDataSource(const QString &dataSource, const QString &baseName, const QString &provider, bool loadDefaultStyleFlag=false)
Updates the data source of the layer.
double minimumScale() const
Returns the minimum map scale (i.e.
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
virtual void exportSldStyle(QDomDocument &doc, QString &errorMsg) const
Export the properties of this layer as SLD style in a QDomDocument.
Q_INVOKABLE QStringList customPropertyKeys() const
Returns list of all keys within custom properties.
QgsProject * project() const
Returns the parent project if this map layer is added to a project.
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
double opacity
Definition: qgsmaplayer.h:82
bool mValid
Indicates if the layer is valid and can be drawn.
Definition: qgsmaplayer.h:1939
@ GeometryOptions
Geometry validation configuration.
Definition: qgsmaplayer.h:172
@ AttributeTable
Attribute table settings: choice and order of columns, conditional styling.
Definition: qgsmaplayer.h:169
@ LayerConfiguration
General configuration: identifiable, removable, searchable, display expression, read-only.
Definition: qgsmaplayer.h:160
@ Symbology
Symbology.
Definition: qgsmaplayer.h:161
@ MapTips
Map tips.
Definition: qgsmaplayer.h:167
@ Rendering
Rendering: scale visibility, simplify method, opacity.
Definition: qgsmaplayer.h:170
@ Relations
Relations.
Definition: qgsmaplayer.h:173
@ CustomProperties
Custom properties (by plugins for instance)
Definition: qgsmaplayer.h:171
@ Actions
Actions.
Definition: qgsmaplayer.h:166
@ Forms
Feature form.
Definition: qgsmaplayer.h:165
@ Fields
Aliases, widgets, WMS/WFS, expressions, constraints, virtual fields.
Definition: qgsmaplayer.h:164
@ Legend
Legend settings (since QGIS 3.16)
Definition: qgsmaplayer.h:175
@ Diagrams
Diagrams.
Definition: qgsmaplayer.h:168
@ Labeling
Labeling.
Definition: qgsmaplayer.h:163
void layerModified()
Emitted when modifications has been done on layer.
void setProviderType(const QString &providerType)
Sets the providerType (provider key)
QString generalHtmlMetadata() const
Returns an HTML fragment containing general metadata information, for use in the htmlMetadata() metho...
void writeCommonStyle(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const
Write style data common to all layer types.
double maximumScale() const
Returns the maximum map scale (i.e.
bool mShouldValidateCrs
true if the layer's CRS should be validated and invalid CRSes are not permitted.
Definition: qgsmaplayer.h:1995
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
static QgsPainting::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
static QPainter::CompositionMode getCompositionMode(QgsPainting::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:20
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer.
Definition: qgspainting.h:37
Contains settings for how a map layer will be labeled.
double yOffset
Vertical offset of label.
const QgsLabelPlacementSettings & placementSettings() const
Returns the label placement settings.
double maxCurvedCharAngleIn
Maximum angle between inside curved label characters (valid range 20.0 to 60.0).
void setFormat(const QgsTextFormat &format)
Sets the label text formatting settings, e.g., font settings, buffer settings, etc.
double xOffset
Horizontal offset of label.
Qgis::LabelPlacement placement
Label placement mode.
QgsUnitTypes::RenderUnit offsetUnits
Units for offsets of label.
double angleOffset
Label rotation, in degrees clockwise.
double maxCurvedCharAngleOut
Maximum angle between outside curved label characters (valid range -20.0 to -95.0)
bool isExpression
true if this label is made from a expression string, e.g., FieldName || 'mm'
const QgsLabelLineSettings & lineSettings() const
Returns the label line settings, which contain settings related to how the label engine places and fo...
Qgis::UpsideDownLabelHandling upsidedownLabels
Controls whether upside down labels are displayed and how they are handled.
QString fieldName
Name of field (or an expression) to use for label text.
Resolves relative paths into absolute paths and vice versa.
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
A class to represent a 2D point.
Definition: qgspointxy.h:59
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
Encapsulates properties and constraints relating to fetching elevation profiles from different source...
QgsExpressionContext & expressionContext()
Returns the expression context used to evaluate expressions.
virtual QString translate(const QString &context, const QString &sourceText, const char *disambiguation=nullptr, int n=-1) const =0
The derived translate() translates with QTranslator and qm file the sourceText.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:104
QgsRelationManager * relationManager
Definition: qgsproject.h:114
bool commitChanges(QStringList &commitErrors, bool stopEditing=true, QgsVectorLayer *vectorLayer=nullptr)
Attempts to commit to the underlying data provider any buffered changes made since the last to call t...
Definition: qgsproject.cpp:702
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:477
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
bool rollBack(QStringList &rollbackErrors, bool stopEditing=true, QgsVectorLayer *vectorLayer=nullptr)
Stops a current editing operation on vectorLayer and discards any uncommitted edits.
Definition: qgsproject.cpp:726
QgsPathResolver pathResolver() const
Returns path resolver object with considering whether the project uses absolute or relative paths and...
bool startEditing(QgsVectorLayer *vectorLayer=nullptr)
Makes the layer editable.
Definition: qgsproject.cpp:683
QMap< QString, QgsMapLayer * > mapLayers(const bool validOnly=false) const
Returns a map of all registered layers by layer ID.
A grouped map of multiple QgsProperty objects, each referenced by a integer key value.
void setProperty(int key, const QgsProperty &property)
Adds a property to the collection and takes ownership of it.
Definition for a property.
Definition: qgsproperty.h:46
@ Double
Double value (including negative values)
Definition: qgsproperty.h:56
@ Boolean
Boolean value.
Definition: qgsproperty.h:52
static QgsProperty fromField(const QString &fieldName, bool isActive=true)
Returns a new FieldBasedProperty created from the specified field name.
QString loadStyle(const QString &providerKey, const QString &uri, QString &errCause)
Loads a layer style defined by uri.
QString getStyleById(const QString &providerKey, const QString &uri, const QString &styleId, QString &errCause)
Gets a layer style defined by styleId.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
bool deleteStyleById(const QString &providerKey, const QString &uri, const QString &styleId, QString &errCause)
Deletes a layer style defined by styleId.
int listStyles(const QString &providerKey, const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)
Lists stored layer styles in the provider defined by providerKey and uri.
bool saveStyle(const QString &providerKey, const QString &uri, const QString &qmlStyle, const QString &sldStyle, const QString &styleName, const QString &styleDescription, const QString &uiFileContent, bool useAsDefault, QString &errCause)
Saves a layer style to provider.
Allows entering a context category and takes care of leaving this category on deletion of the class.
The class is used as a container of context for various read/write operations on other objects.
MAYBE_UNUSED NODISCARD QgsReadWriteContextCategoryPopper enterCategory(const QString &category, const QString &details=QString()) const
Push a category to the stack.
const QgsProjectTranslator * projectTranslator() const
Returns the project translator.
QgsCoordinateTransformContext transformContext() const
Returns data provider coordinate transform context.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
void set(const QgsPointXY &p1, const QgsPointXY &p2, bool normalize=true)
Sets the rectangle from two QgsPoints.
Definition: qgsrectangle.h:122
void setMinimal() SIP_HOLDGIL
Set a rectangle so that min corner is at max and max corner is at min.
Definition: qgsrectangle.h:172
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
Definition: qgsrectangle.h:391
void normalize()
Normalize the rectangle so it has non-negative width/height.
Definition: qgsrectangle.h:203
QList< QgsRelation > referencedRelations(const QgsVectorLayer *layer=nullptr) const
Gets all relations where this layer is the referenced part (i.e.
QList< QgsRelation > referencingRelations(const QgsVectorLayer *layer=nullptr, int fieldIdx=-2) const
Gets all relations where the specified layer (and field) is the referencing part (i....
void relationsLoaded()
Emitted when the relations were loaded after reading a project.
Contains information about the context of a rendering operation.
double rendererScale() const
Returns the renderer map scale.
bool useRenderingOptimization() const
Returns true if the rendering optimization (geometry simplification) can be executed.
A child rule for QgsRuleBasedLabeling.
void appendChild(QgsRuleBasedLabeling::Rule *rule)
add child rule, take ownership, sets this as parent
Rule based labeling for a vector layer.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
T flagValue(const QString &key, const T &defaultValue, const Section section=NoSection)
Returns the setting value for a setting based on a flag.
Definition: qgssettings.h:362
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
T enumValue(const QString &key, const T &defaultValue, const Section section=NoSection)
Returns the setting value for a setting based on an enum.
Definition: qgssettings.h:284
Renders the diagrams for all features with the same settings.
Manages stored expressions regarding creation, modification and storing in the project.
bool writeXml(QDomNode &layerNode) const
Writes the stored expressions out in XML format.
bool readXml(const QDomNode &layerNode)
Reads the stored expressions in in XML format.
An interface for classes which can visit style entity (e.g.
static QgsUnitTypes::RenderUnit decodeSldUom(const QString &str, double *scaleFactor=nullptr)
Decodes a SLD unit of measure string to a render unit.
static double rendererFrameRate(const QgsFeatureRenderer *renderer)
Calculates the frame rate (in frames per second) at which the given renderer must be redrawn.
static QgsStringMap getSvgParameterList(QDomElement &element)
static void mergeScaleDependencies(double mScaleMinDenom, double mScaleMaxDenom, QVariantMap &props)
Merges the local scale limits, if any, with the ones already in the map, if any.
static bool fillFromSld(QDomElement &element, Qt::BrushStyle &brushStyle, QColor &color)
long addTask(QgsTask *task, int priority=0)
Adds a task to the manager.
void taskCompleted()
Will be emitted by task to indicate its successful completion.
void taskTerminated()
Will be emitted by task if it has terminated for any reason other then completion (e....
bool isActive() const
Returns true if the temporal property is active.
Container for settings relating to a text buffer.
void setColor(const QColor &color)
Sets the color for the buffer.
void setEnabled(bool enabled)
Sets whether the text buffer will be drawn.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units used for the buffer size.
void setSize(double size)
Sets the size of the buffer.
Container for all settings relating to text rendering.
Definition: qgstextformat.h:41
void setColor(const QColor &color)
Sets the color that text will be rendered in.
void setSize(double size)
Sets the size for rendered text.
void setFont(const QFont &font)
Sets the font used for rendering text.
void setBuffer(const QgsTextBufferSettings &bufferSettings)
Sets the text's buffer settings.
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the size of rendered text.
This class allows including a set of layers in a database-side transaction, provided the layer data p...
QString createSavepoint(QString &error)
creates a save point returns empty string on error returns the last created savepoint if it's not dir...
void dirtied(const QString &sql, const QString &name)
Emitted if a sql query is executed and the underlying data is modified.
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:168
@ RenderPoints
Points (e.g., for font sizes)
Definition: qgsunittypes.h:173
@ RenderPixels
Pixels.
Definition: qgsunittypes.h:171
static bool isNull(const QVariant &variant)
Returns true if the specified variant should be considered a NULL value.
This is the base class for vector data providers.
virtual QString dataComment() const override
Returns a short comment for the data that this provider is providing access to (e....
@ ReadLayerMetadata
Provider can read layer metadata from data store. Since QGIS 3.0. See QgsDataProvider::layerMetadata(...
@ SelectAtId
Fast access to features using their ID.
@ DeleteFeatures
Allows deletion of features.
@ CreateLabeling
Provider can set labeling settings using backend-specific formatting information. Since QGIS 3....
@ CreateRenderer
Provider can create feature renderers using backend-specific formatting information....
QgsWkbTypes::Type wkbType() const override=0
Returns the geometry type which is returned by this layer.
virtual bool isSaveAndLoadStyleToDatabaseSupported() const
It returns false by default.
static const int EditingCapabilities
Bitmask of all provider's editing capabilities.
long long featureCount() const override=0
Number of features in the layer.
virtual QgsFeatureRenderer * createRenderer(const QVariantMap &configuration=QVariantMap()) const
Creates a new vector layer feature renderer, using provider backend specific information.
virtual QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
virtual 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.
void raiseError(const QString &msg) const
Signals an error in this provider.
virtual bool isSqlQuery() const
Returns true if the layer is a query (SQL) layer.
virtual bool empty() const
Returns true if the layer does not contain any feature.
virtual QgsAttributeList pkAttributeIndexes() const
Returns list of indexes of fields that make up the primary key.
virtual void handlePostCloneOperations(QgsVectorDataProvider *source)
Handles any post-clone operations required after this vector data provider was cloned from the source...
virtual QSet< QgsMapLayerDependency > dependencies() const
Gets the list of layer ids on which this layer depends.
virtual void setEncoding(const QString &e)
Set encoding used for accessing data from layer.
virtual Qgis::VectorLayerTypeFlags vectorLayerTypeFlags() const
Returns the vector layer type flags.
QVariant maximumValue(int index) const override
Returns the maximum value of an attribute.
QgsFields fields() const override=0
Returns the fields associated with this data provider.
QVariant minimumValue(int index) const override
Returns the minimum value of an attribute.
virtual QVariant aggregate(QgsAggregateCalculator::Aggregate aggregate, int index, const QgsAggregateCalculator::AggregateParameters &parameters, QgsExpressionContext *context, bool &ok, QgsFeatureIds *fids=nullptr) const
Calculates an aggregated value from the layer's features.
QString encoding() const
Returns the encoding which is used for accessing data.
virtual QVariant defaultValue(int fieldIndex) const
Returns any literal default values which are present at the provider for a specified field index.
QgsFieldConstraints::Constraints fieldConstraints(int fieldIndex) const
Returns any constraints which are present at the provider for a specified field index.
virtual QgsTransaction * transaction() const
Returns the transaction this data provider is included in, if any.
virtual QgsAbstractVectorLayerLabeling * createLabeling(const QVariantMap &configuration=QVariantMap()) const
Creates labeling settings, using provider backend specific information.
virtual Q_INVOKABLE QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
QgsVectorDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
QString capabilitiesString() const
Returns the above in friendly format.
bool commitChanges(QStringList &commitErrors, bool stopEditing=true)
Attempts to commit any changes to disk.
void committedAttributesDeleted(const QString &layerId, const QgsAttributeList &deletedAttributes)
Signals emitted after committing changes.
virtual bool deleteFeature(QgsFeatureId fid)
Delete a feature from the layer (but does not commit it)
QgsFeatureIds deletedFeatureIds() const
Returns a list of deleted feature IDs which are not committed.
QgsChangedAttributesMap changedAttributeValues() const
Returns a map of features with changed attributes values which are not committed.
void committedAttributeValuesChanges(const QString &layerId, const QgsChangedAttributesMap &changedAttributesValues)
virtual bool renameAttribute(int attr, const QString &newName)
Renames an attribute field (but does not commit it)
void geometryChanged(QgsFeatureId fid, const QgsGeometry &geom)
Emitted when a feature's geometry is changed.
virtual bool addAttribute(const QgsField &field)
Adds an attribute field (but does not commit it) returns true if the field was added.
void committedAttributesAdded(const QString &layerId, const QList< QgsField > &addedAttributes)
virtual bool addFeatures(QgsFeatureList &features)
Insert a copy of the given features into the layer (but does not commit it)
virtual bool changeAttributeValues(QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues)
Changes values of attributes (but does not commit it).
QgsFeatureMap addedFeatures() const
Returns a map of new features which are not committed.
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
void updateFields(QgsFields &fields)
Updates fields.
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
void featureDeleted(QgsFeatureId fid)
QgsGeometryMap changedGeometries() const
Returns a map of features with changed geometries which are not committed.
QgsVectorLayerEditBufferGroup * editBufferGroup() const
Returns the parent edit buffer group for this edit buffer, or nullptr if not part of a group.
QgsAttributeList deletedAttributeIds() const
Returns a list of deleted attributes fields which are not committed.
void attributeAdded(int idx)
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
virtual bool addFeature(QgsFeature &f)
Adds a feature.
virtual void rollBack()
Stop editing and discard the edits.
void attributeDeleted(int idx)
void featureAdded(QgsFeatureId fid)
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &)
virtual bool commitChanges(QStringList &commitErrors)
Attempts to commit any changes to disk.
virtual bool deleteAttribute(int attr)
Deletes an attribute field (but does not commit it)
virtual bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant())
Changed an attribute value (but does not commit it)
virtual bool changeGeometry(QgsFeatureId fid, const QgsGeometry &geom)
Change feature's geometry.
void layerModified()
Emitted when modifications has been done on layer.
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
bool insertVertex(double x, double y, QgsFeatureId atFeatureId, int beforeVertex)
Insert a new vertex before the given vertex number, in the given ring, item (first number is index 0)...
Q_DECL_DEPRECATED Qgis::GeometryOperationResult addPart(const QVector< QgsPointXY > &ring, QgsFeatureId featureId)
Adds a new part polygon to a multipart feature.
Qgis::VectorEditResult deleteVertex(QgsFeatureId featureId, int vertex)
Deletes a vertex from a feature.
int addTopologicalPoints(const QgsGeometry &geom)
Adds topological points for every vertex of the geometry.
Q_DECL_DEPRECATED Qgis::GeometryOperationResult splitParts(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
Q_DECL_DEPRECATED Qgis::GeometryOperationResult splitFeatures(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
bool moveVertex(double x, double y, QgsFeatureId atFeatureId, int atVertex)
Moves the vertex at the given position number, ring and item (first number is index 0),...
Q_DECL_DEPRECATED Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring, const QgsFeatureIds &targetFeatureIds=QgsFeatureIds(), QgsFeatureId *modifiedFeatureId=nullptr)
Adds a ring to polygon/multipolygon features.
Vector layer specific subclass of QgsMapLayerElevationProperties.
void setDefaultsFromLayer(QgsMapLayer *layer) override
Sets default properties based on sensible choices for the given map layer.
QgsVectorLayerElevationProperties * clone() const override
Creates a clone of the properties.
Counts the features in a QgsVectorLayer in task.
QHash< QString, long long > symbolFeatureCountMap() const
Returns the count for each symbol.
void cancel() override
Notifies the task that it should terminate.
QHash< QString, QgsFeatureIds > symbolFeatureIdMap() const
Returns the QgsFeatureIds for each symbol.
Manages joined fields for a vector layer.
void resolveReferences(QgsProject *project)
Resolves layer IDs of joined layers using given project's available layers.
bool addJoin(const QgsVectorLayerJoinInfo &joinInfo)
Joins another vector layer to this layer.
void readXml(const QDomNode &layer_node)
Reads joins from project file.
void writeXml(QDomNode &layer_node, QDomDocument &document) const
Saves mVectorJoins to xml under the layer node.
const QgsVectorLayerJoinInfo * joinForFieldIndex(int index, const QgsFields &fields, int &sourceFieldIndex) const
Finds the vector join for a layer field index.
bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant())
Changes attribute value in joined layers.
bool removeJoin(const QString &joinLayerId)
Removes a vector layer join.
bool containsJoins() const
Quick way to test if there is any join at all.
bool changeAttributeValues(QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues=QgsAttributeMap())
Changes attributes' values in joined layers.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features in joined layers.
void joinedFieldsChanged()
Emitted whenever the list of joined fields changes (e.g.
void updateFields(QgsFields &fields)
Updates field map with joined attributes.
bool deleteFeature(QgsFeatureId fid, QgsVectorLayer::DeleteContext *context=nullptr) const
Deletes a feature from joined layers.
const QgsVectorJoinList & vectorJoins() const
Defines left outer join from our vector layer to some other vector layer.
QString targetFieldName() const
Returns name of the field of our layer that will be used for join.
QString joinLayerId() const
ID of the joined layer - may be used to resolve reference to the joined layer.
Implementation of QgsAbstractProfileGenerator for vector layers.
Implementation of threaded rendering for vector layers.
Basic implementation of the labeling interface.
Implementation of map layer temporal properties for vector layers.
void guessDefaultsFromFields(const QgsFields &fields)
Attempts to setup the temporal properties by scanning a set of fields and looking for standard naming...
void setDefaultsFromDataProviderTemporalCapabilities(const QgsDataProviderTemporalCapabilities *capabilities) override
Sets the layers temporal settings to appropriate defaults based on a provider's temporal capabilities...
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...
Represents a vector layer which manages a vector based data sets.
void setLabeling(QgsAbstractVectorLayerLabeling *labeling)
Sets labeling configuration.
QString attributeDisplayName(int index) const
Convenience function that returns the attribute alias if defined or the field name else.
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.
int addExpressionField(const QString &exp, const QgsField &fld)
Add a new field which is calculated by the expression specified.
void committedFeaturesAdded(const QString &layerId, const QgsFeatureList &addedFeatures)
Emitted when features are added to the provider if not in transaction mode.
void setExtent(const QgsRectangle &rect) FINAL
Sets the extent.
Q_DECL_DEPRECATED Qgis::GeometryOperationResult addPart(const QList< QgsPointXY > &ring)
Adds a new part polygon to a multipart feature.
QgsRectangle sourceExtent() const FINAL
Returns the extent of all geometries from the source.
void featureBlendModeChanged(QPainter::CompositionMode blendMode)
Signal emitted when setFeatureBlendMode() is called.
bool labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const FINAL
bool isModified() const override
Returns true if the provider has been modified since the last commit.
bool writeStyle(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const FINAL
void addFeatureRendererGenerator(QgsFeatureRendererGenerator *generator)
Adds a new feature renderer generator to the layer.
Q_DECL_DEPRECATED void setExcludeAttributesWfs(const QSet< QString > &att)
A set of attributes that are not advertised in WFS requests with QGIS server.
Q_INVOKABLE bool deleteSelectedFeatures(int *deletedCount=nullptr, QgsVectorLayer::DeleteContext *context=nullptr)
Deletes the selected features.
Q_INVOKABLE void selectByRect(QgsRectangle &rect, Qgis::SelectBehavior behavior=Qgis::SelectBehavior::SetSelection)
Selects features found within the search rectangle (in layer's coordinates)
void removeFieldAlias(int index)
Removes an alias (a display name) for attributes to display in dialogs.
void setAuxiliaryLayer(QgsAuxiliaryLayer *layer=nullptr)
Sets the current auxiliary layer.
void beforeRemovingExpressionField(int idx)
Will be emitted, when an expression field is going to be deleted from this vector layer.
virtual void saveStyleToDatabase(const QString &name, const QString &description, bool useAsDefault, const QString &uiFileContent, QString &msgError, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Saves named and sld style of the layer to the style table in the db.
QString loadDefaultStyle(bool &resultFlag) FINAL
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
void committedGeometriesChanges(const QString &layerId, const QgsGeometryMap &changedGeometries)
Emitted when geometry changes are saved to the provider if not in transaction mode.
void beforeCommitChanges(bool stopEditing)
Emitted before changes are committed to the data provider.
Q_INVOKABLE bool startEditing()
Makes the layer editable.
QMap< QgsFieldConstraints::Constraint, QgsFieldConstraints::ConstraintStrength > fieldConstraintsAndStrength(int fieldIndex) const
Returns a map of constraint with their strength for a specific field of the layer.
bool addJoin(const QgsVectorLayerJoinInfo &joinInfo)
Joins another vector layer to this layer.
QSet< QgsMapLayerDependency > dependencies() const FINAL
Gets the list of dependencies.
QgsMapLayerTemporalProperties * temporalProperties() override
Returns the layer's temporal properties.
void mapTipTemplateChanged()
Emitted when the map tip changes.
Q_DECL_DEPRECATED Qgis::GeometryOperationResult splitFeatures(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
QgsDefaultValue defaultValueDefinition(int index) const
Returns the definition of the expression used when calculating the default value for a field.
QgsExpressionContextScope * createExpressionContextScope() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) FINAL
Returns new instance of QgsMapLayerRenderer that will be used for rendering of given context.
QgsVectorLayerFeatureCounter * countSymbolFeatures(bool storeSymbolFids=false)
Count features for symbols.
QPainter::CompositionMode featureBlendMode() const
Returns the current blending mode for features.
QString constraintExpression(int index) const
Returns the constraint expression for for a specified field index, if set.
bool addAttribute(const QgsField &field)
Add an attribute field (but does not commit it) returns true if the field was added.
void attributeAdded(int idx)
Will be emitted, when a new attribute has been added to this vector layer.
QString capabilitiesString() const
Capabilities for this layer, comma separated and translated.
void deselect(QgsFeatureId featureId)
Deselects feature by its ID.
virtual int listStylesInDatabase(QStringList &ids, QStringList &names, QStringList &descriptions, QString &msgError)
Lists all the style in db split into related to the layer and not related to.
void allowCommitChanged()
Emitted whenever the allowCommitChanged() property of this layer changes.
friend class QgsVectorLayerEditBuffer
void editCommandStarted(const QString &text)
Signal emitted when a new edit command has been started.
void updateFields()
Will regenerate the fields property of this layer by obtaining all fields from the dataProvider,...
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
virtual QString loadNamedStyle(const QString &theURI, bool &resultFlag, bool loadFromLocalDb, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories)
Loads a named style from file/local db/datasource db.
const QgsDiagramLayerSettings * diagramLayerSettings() const
void setFieldConstraint(int index, QgsFieldConstraints::Constraint constraint, QgsFieldConstraints::ConstraintStrength strength=QgsFieldConstraints::ConstraintStrengthHard)
Sets a constraint for a specified field index.
bool loadAuxiliaryLayer(const QgsAuxiliaryStorage &storage, const QString &key=QString())
Loads the auxiliary layer for this vector layer.
bool deleteFeature(QgsFeatureId fid, DeleteContext *context=nullptr)
Deletes a feature from the layer (but does not commit it).
bool insertVertex(double x, double y, QgsFeatureId atFeatureId, int beforeVertex)
Inserts a new vertex before the given vertex number, in the given ring, item (first number is index 0...
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsAbstractProfileGenerator * createProfileGenerator(const QgsProfileRequest &request) override
Given a profile request, returns a new profile generator ready for generating elevation profiles.
QString mapTipTemplate
QString htmlMetadata() const FINAL
Obtain a formatted HTML string containing assorted metadata for this layer.
Q_INVOKABLE QgsRectangle boundingBoxOfSelected() const
Returns the bounding box of the selected features. If there is no selection, QgsRectangle(0,...
QgsFields fields() const FINAL
Returns the list of fields of this layer.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a list of features to the sink.
Q_INVOKABLE QgsFeatureList selectedFeatures() const
Returns a copy of the user-selected features.
QString expressionField(int index) const
Returns the expression used for a given expression field.
bool readSymbology(const QDomNode &layerNode, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) FINAL
void removeFeatureRendererGenerator(const QString &id)
Removes the feature renderer with matching id from the layer.
friend class QgsVectorLayerEditPassthrough
void setSimplifyMethod(const QgsVectorSimplifyMethod &simplifyMethod)
Sets the simplification settings for fast rendering of features.
void editCommandDestroyed()
Signal emitted, when an edit command is destroyed.
QgsFieldConstraints::Constraints fieldConstraints(int fieldIndex) const
Returns any constraints which are present for a specified field index.
bool deleteFeatures(const QgsFeatureIds &fids, DeleteContext *context=nullptr)
Deletes a set of features from the layer (but does not commit it)
void setMapTipTemplate(const QString &mapTipTemplate)
The mapTip is a pretty, html representation for feature information.
Q_DECL_DEPRECATED QSet< QString > excludeAttributesWms() const
A set of attributes that are not advertised in WMS requests with QGIS server.
QgsFeatureIds symbolFeatureIds(const QString &legendKey) const
Ids of features rendered with specified legend key.
void removeFieldConstraint(int index, QgsFieldConstraints::Constraint constraint)
Removes a constraint for a specified field index.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
virtual QString getStyleFromDatabase(const QString &styleId, QString &msgError)
Returns the named style corresponding to style id provided.
void featuresDeleted(const QgsFeatureIds &fids)
Emitted when features have been deleted.
Qgis::VectorLayerTypeFlags vectorLayerTypeFlags() const
Returns the vector layer type flags.
void setLabelsEnabled(bool enabled)
Sets whether labels should be enabled for the layer.
void subsetStringChanged()
Emitted when the layer's subset string has changed.
void setFieldConfigurationFlags(int index, QgsField::ConfigurationFlags flags)
Sets the configuration flags of the field at given index.
QgsAuxiliaryLayer * auxiliaryLayer()
Returns the current auxiliary layer.
void setCoordinateSystem()
Setup the coordinate system transformation for the layer.
void committedFeaturesRemoved(const QString &layerId, const QgsFeatureIds &deletedFeatureIds)
Emitted when features are deleted from the provider if not in transaction mode.
void updateExpressionField(int index, const QString &exp)
Changes the expression used to define an expression based (virtual) field.
Q_INVOKABLE void selectByExpression(const QString &expression, Qgis::SelectBehavior behavior=Qgis::SelectBehavior::SetSelection, QgsExpressionContext *context=nullptr)
Selects matching features using an expression.
~QgsVectorLayer() override
QgsCoordinateReferenceSystem sourceCrs() const FINAL
Returns the coordinate reference system for features in the source.
void endEditCommand()
Finish edit command and add it to undo/redo stack.
void destroyEditCommand()
Destroy active command and reverts all changes in it.
bool isAuxiliaryField(int index, int &srcIndex) const
Returns true if the field comes from the auxiliary layer, false otherwise.
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
QList< QgsRelation > referencingRelations(int idx) const
Returns the layer's relations, where the foreign key is on this layer.
Q_DECL_DEPRECATED QSet< QString > excludeAttributesWfs() const
A set of attributes that are not advertised in WFS requests with QGIS server.
Q_DECL_DEPRECATED Qgis::GeometryOperationResult splitParts(const QVector< QgsPointXY > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
void setDefaultValueDefinition(int index, const QgsDefaultValue &definition)
Sets the definition of the expression to use when calculating the default value for a field.
bool diagramsEnabled() const
Returns whether the layer contains diagrams which are enabled and should be drawn.
void setAllowCommit(bool allowCommit)
Controls, if the layer is allowed to commit changes.
bool setDependencies(const QSet< QgsMapLayerDependency > &layers) FINAL
Sets the list of dependencies.
void symbolFeatureCountMapChanged()
Emitted when the feature count for symbols on this layer has been recalculated.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
Qgis::VectorEditResult deleteVertex(QgsFeatureId featureId, int vertex)
Deletes a vertex from a feature.
void setFeatureBlendMode(QPainter::CompositionMode blendMode)
Sets the blending mode used for rendering each feature.
QString constraintDescription(int index) const
Returns the descriptive name for the constraint expression for a specified field index.
void writeCustomSymbology(QDomElement &element, QDomDocument &doc, QString &errorMessage) const
Signal emitted whenever the symbology (QML-file) for this layer is being written.
const QgsAbstractVectorLayerLabeling * labeling() const
Access to const labeling configuration.
void setProviderEncoding(const QString &encoding)
Sets the text encoding of the data provider.
bool writeSld(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QVariantMap &props=QVariantMap()) const
Writes the symbology of the layer into the document provided in SLD 1.1 format.
void setDisplayExpression(const QString &displayExpression)
Set the preview expression, used to create a human readable preview string.
virtual bool deleteAttribute(int attr)
Deletes an attribute field (but does not commit it).
void resolveReferences(QgsProject *project) FINAL
Resolves references to other layers (kept as layer IDs after reading XML) into layer objects.
bool changeAttributeValues(QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues=QgsAttributeMap(), bool skipDefaultValues=false)
Changes attributes' values for a feature (but does not immediately commit the changes).
QgsMapLayerElevationProperties * elevationProperties() override
Returns the layer's elevation properties.
bool removeJoin(const QString &joinLayerId)
Removes a vector layer join.
Q_INVOKABLE void invertSelectionInRectangle(QgsRectangle &rect)
Inverts selection of features found within the search rectangle (in layer's coordinates)
void setRenderer(QgsFeatureRenderer *r)
Sets the feature renderer which will be invoked to represent this layer in 2D map views.
Q_INVOKABLE void selectAll()
Select all the features.
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
QStringList commitErrors() const
Returns a list containing any error messages generated when attempting to commit changes to the layer...
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
bool readExtentFromXml() const
Returns true if the extent is read from the XML document when data source has no metadata,...
QString dataComment() const
Returns a description for this layer as defined in the data provider.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
QgsGeometryOptions * geometryOptions() const
Configuration and logic to apply automatically on any edit happening on this layer.
QgsStringMap attributeAliases() const
Returns a map of field name to attribute alias.
Q_INVOKABLE int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
virtual void updateExtents(bool force=false)
Update the extents for the layer.
void attributeDeleted(int idx)
Will be emitted, when an attribute has been deleted from this vector layer.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
void beforeEditingStarted()
Emitted before editing on this layer is started.
void committedAttributeValuesChanges(const QString &layerId, const QgsChangedAttributesMap &changedAttributesValues)
Emitted when attribute value changes are saved to the provider if not in transaction mode.
QString subsetString
void committedAttributesAdded(const QString &layerId, const QList< QgsField > &addedAttributes)
Emitted when attributes are added to the provider if not in transaction mode.
void setEditFormConfig(const QgsEditFormConfig &editFormConfig)
Sets the editFormConfig (configuration) of the form used to represent this vector layer.
void committedAttributesDeleted(const QString &layerId, const QgsAttributeList &deletedAttributes)
Emitted when attributes are deleted from the provider if not in transaction mode.
QString displayExpression
void displayExpressionChanged()
Emitted when the display expression changes.
QVariant minimumValue(int index) const FINAL
Returns the minimum value for an attribute column or an invalid variant in case of error.
QgsFeatureIterator getSelectedFeatures(QgsFeatureRequest request=QgsFeatureRequest()) const
Returns an iterator of the selected features.
void setEditorWidgetSetup(int index, const QgsEditorWidgetSetup &setup)
The editor widget setup defines which QgsFieldFormatter and editor widget will be used for the field ...
void setConstraintExpression(int index, const QString &expression, const QString &description=QString())
Sets the constraint expression for the specified field index.
Q_INVOKABLE bool rollBack(bool deleteBuffer=true)
Stops a current editing operation and discards any uncommitted edits.
bool readStyle(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) FINAL
bool updateFeature(QgsFeature &feature, bool skipDefaultValues=false)
Updates an existing feature in the layer, replacing the attributes and geometry for the feature with ...
Q_INVOKABLE bool commitChanges(bool stopEditing=true)
Attempts to commit to the underlying data provider any buffered changes made since the last to call t...
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
bool setReadOnly(bool readonly=true)
Makes layer read-only (editing disabled) or not.
QgsField::ConfigurationFlags fieldConfigurationFlags(int index) const
Returns the configuration flags of the field at given index.
void editFormConfigChanged()
Will be emitted whenever the edit form configuration of this layer changes.
Q_INVOKABLE void modifySelection(const QgsFeatureIds &selectIds, const QgsFeatureIds &deselectIds)
Modifies the current selection on this layer.
void setWeakRelations(const QList< QgsWeakRelation > &relations)
Sets the layer's weak relations.
void reselect()
Reselects the previous set of selected features.
void select(QgsFeatureId featureId)
Selects feature by its ID.
QgsEditorWidgetSetup editorWidgetSetup(int index) const
The editor widget setup defines which QgsFieldFormatter and editor widget will be used for the field ...
long long featureCount() const FINAL
Returns feature count including changes which have not yet been committed If you need only the count ...
virtual bool deleteStyleFromDatabase(const QString &styleId, QString &msgError)
Deletes a style from the database.
void setReadExtentFromXml(bool readExtentFromXml)
Flag allowing to indicate if the extent has to be read from the XML document when data source has no ...
void afterCommitChanges()
Emitted after changes are committed to the data provider.
QgsVectorLayer * clone() const override
Returns a new instance equivalent to this one.
QgsAttributeTableConfig attributeTableConfig() const
Returns the attribute table configuration object.
QgsActionManager * actions()
Returns all layer actions defined on this layer.
bool readSld(const QDomNode &node, QString &errorMessage) FINAL
QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.
Q_INVOKABLE void selectByIds(const QgsFeatureIds &ids, Qgis::SelectBehavior behavior=Qgis::SelectBehavior::SetSelection)
Selects matching features using a list of feature IDs.
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.
void raiseError(const QString &msg)
Signals an error related to this vector layer.
void editCommandEnded()
Signal emitted, when an edit command successfully ended.
void supportsEditingChanged()
Emitted when the read only state or the data provider of this layer is changed.
QgsFeatureSource::SpatialIndexPresence hasSpatialIndex() const override
void readOnlyChanged()
Emitted when the read only state of this layer is changed.
void removeExpressionField(int index)
Removes an expression field.
virtual void setTransformContext(const QgsCoordinateTransformContext &transformContext) override
Sets the coordinate transform context to transformContext.
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &value)
Emitted whenever an attribute value change is done in the edit buffer.
static Q_DECL_DEPRECATED void drawVertexMarker(double x, double y, QPainter &p, Qgis::VertexMarkerType type, int vertexSize)
Draws a vertex symbol at (screen) coordinates x, y.
bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false)
Changes an attribute value for a feature (but does not immediately commit the changes).
void setFieldConfigurationFlag(int index, QgsField::ConfigurationFlag flag, bool active)
Sets the given configuration flag for the field at given index to be active or not.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a single feature to the sink.
void setFieldAlias(int index, const QString &aliasString)
Sets an alias (a display name) for attributes to display in dialogs.
friend class QgsVectorLayerFeatureSource
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
QgsRectangle extent() const FINAL
Returns the extent of the layer.
Q_DECL_DEPRECATED void setExcludeAttributesWms(const QSet< QString > &att)
A set of attributes that are not advertised in WMS requests with QGIS server.
void setAttributeTableConfig(const QgsAttributeTableConfig &attributeTableConfig)
Sets the attribute table configuration object.
virtual bool setSubsetString(const QString &subset)
Sets the string (typically sql) used to define a subset of the layer.
bool readXml(const QDomNode &layer_node, QgsReadWriteContext &context) FINAL
Reads vector layer specific state from project file Dom node.
FeatureAvailability hasFeatures() const FINAL
Determines if this vector layer has features.
void afterRollBack()
Emitted after changes are rolled back.
QString decodedSource(const QString &source, const QString &provider, const QgsReadWriteContext &context) const FINAL
Called by readLayerXML(), used by derived classes to decode provider's specific data source from proj...
void setDiagramLayerSettings(const QgsDiagramLayerSettings &s)
QList< QgsWeakRelation > weakRelations() const
Returns the layer's weak relations as specified in the layer's style.
const QgsVectorSimplifyMethod & simplifyMethod() const
Returns the simplification settings for fast rendering of features.
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
void beforeAddingExpressionField(const QString &fieldName)
Will be emitted, when an expression field is going to be added to this vector layer.
bool deleteAttributes(const QList< int > &attrs)
Deletes a list of attribute fields (but does not commit it)
void updatedFields()
Emitted whenever the fields available from this layer have been changed.
QVariant defaultValue(int index, const QgsFeature &feature=QgsFeature(), QgsExpressionContext *context=nullptr) const
Returns the calculated default value for the specified field index.
void featureAdded(QgsFeatureId fid)
Emitted when a new feature has been added to the layer.
QString sourceName() const FINAL
Returns a friendly display name for the source.
QString attributeAlias(int index) const
Returns the alias of an attribute name or a null string if there is no alias.
void featureDeleted(QgsFeatureId fid)
Emitted when a feature has been deleted.
Q_INVOKABLE void removeSelection()
Clear selection.
bool allowCommit() const
Controls, if the layer is allowed to commit changes.
QgsConditionalLayerStyles * conditionalStyles() const
Returns the conditional styles that are set for this layer.
void readCustomSymbology(const QDomElement &element, QString &errorMessage)
Signal emitted whenever the symbology (QML-file) for this layer is being read.
void reload() FINAL
Synchronises with changes in the datasource.
const QList< QgsVectorLayerJoinInfo > vectorJoins() const
bool renameAttribute(int index, const QString &newName)
Renames an attribute field (but does not commit it).
bool isSqlQuery() const
Returns true if the layer is a query (SQL) layer.
bool simplifyDrawingCanbeApplied(const QgsRenderContext &renderContext, QgsVectorSimplifyMethod::SimplifyHint simplifyHint) const
Returns whether the VectorLayer can apply the specified simplification hint.
void beforeRollBack()
Emitted before changes are rolled back.
QgsAttributeList primaryKeyAttributes() const
Returns the list of attributes which make up the layer's primary keys.
bool writeXml(QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context) const FINAL
Writes vector layer specific state to project file Dom node.
QString encodedSource(const QString &source, const QgsReadWriteContext &context) const FINAL
Called by writeLayerXML(), used by derived classes to encode provider's specific data source to proje...
void beginEditCommand(const QString &text)
Create edit command for undo/redo operations.
QString displayField() const
This is a shorthand for accessing the displayExpression if it is a simple field.
Q_DECL_DEPRECATED Qgis::GeometryOperationResult addRing(const QVector< QgsPointXY > &ring, QgsFeatureId *featureId=nullptr)
Adds a ring to polygon/multipolygon features.
void setDiagramRenderer(QgsDiagramRenderer *r)
Sets diagram rendering object (takes ownership)
void geometryChanged(QgsFeatureId fid, const QgsGeometry &geometry)
Emitted whenever a geometry change is done in the edit buffer.
QgsEditFormConfig editFormConfig
QList< const QgsFeatureRendererGenerator * > featureRendererGenerators() const
Returns a list of the feature renderer generators owned by the layer.
bool moveVertex(double x, double y, QgsFeatureId atFeatureId, int atVertex)
Moves the vertex at the given position number, ring and item (first number is index 0),...
QgsGeometry getGeometry(QgsFeatureId fid) const
Queries the layer for the geometry at the given id.
int addTopologicalPoints(const QgsGeometry &geom)
Adds topological points for every vertex of the geometry.
void beforeModifiedCheck() const
Emitted when the layer is checked for modifications. Use for last-minute additions.
Q_INVOKABLE void invertSelection()
Selects not selected features and deselects selected ones.
const QgsDiagramRenderer * diagramRenderer() const
QVariant aggregate(QgsAggregateCalculator::Aggregate aggregate, const QString &fieldOrExpression, const QgsAggregateCalculator::AggregateParameters &parameters=QgsAggregateCalculator::AggregateParameters(), QgsExpressionContext *context=nullptr, bool *ok=nullptr, QgsFeatureIds *fids=nullptr, QgsFeedback *feedback=nullptr, QString *error=nullptr) const
Calculates an aggregated value from the layer's features.
bool changeGeometry(QgsFeatureId fid, QgsGeometry &geometry, bool skipDefaultValue=false)
Changes a feature's geometry within the layer's edit buffer (but does not immediately commit the chan...
QSet< QVariant > uniqueValues(int fieldIndex, int limit=-1) const FINAL
Calculates a list of unique values contained within an attribute in the layer.
bool forceLocalOptimization() const
Gets where the simplification executes, after fetch the geometries from provider, or when supported,...
void setSimplifyHints(SimplifyHints simplifyHints)
Sets the simplification hints of the vector layer managed.
float maximumScale() const
Gets the maximum scale at which the layer should be simplified.
void setThreshold(float threshold)
Sets the simplification threshold of the vector layer managed.
void setSimplifyAlgorithm(SimplifyAlgorithm simplifyAlgorithm)
Sets the local simplification algorithm of the vector layer managed.
void setForceLocalOptimization(bool localOptimization)
Sets where the simplification executes, after fetch the geometries from provider, or when supported,...
SimplifyHints simplifyHints() const
Gets the simplification hints of the vector layer managed.
SimplifyAlgorithm simplifyAlgorithm() const
Gets the local simplification algorithm of the vector layer managed.
float threshold() const
Gets the simplification threshold of the vector layer managed.
SimplifyHint
Simplification flags for fast rendering of features.
SimplifyAlgorithm
Types of local simplification algorithms that can be used.
void setMaximumScale(float maximumScale)
Sets the maximum scale at which the layer should be simplified.
@ Referencing
The layer is referencing (or the "child" / "right" layer in the relationship)
@ Referenced
The layer is referenced (or the "parent" / "left" left in the relationship)
static void writeXml(const QgsVectorLayer *layer, WeakRelationType type, const QgsRelation &relation, QDomNode &node, QDomDocument &doc)
Writes a weak relation infoto an XML structure.
static QgsWeakRelation readXml(const QgsVectorLayer *layer, WeakRelationType type, const QDomNode &node, const QgsPathResolver resolver)
Returns a weak relation for the given 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
static QString geometryDisplayString(GeometryType type) SIP_HOLDGIL
Returns a display string for a geometry type.
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
static QString displayString(Type type) SIP_HOLDGIL
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
static QgsRectangle readRectangle(const QDomElement &element)
Definition: qgsxmlutils.cpp:39
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgis.h:47
@ UnknownCount
Provider returned an unknown feature count.
@ VectorLayer
Vector layer.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsVariantEqual(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether they are equal, two NULL values are always treated a...
Definition: qgis.cpp:266
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
Definition: qgis.cpp:119
bool qgsVariantGreaterThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is greater than the second.
Definition: qgis.cpp:187
#define FALLTHROUGH
Definition: qgis.h:3088
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
Definition: qgis.h:2700
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition: qgis.h:2681
QString qgsFlagValueToKeys(const T &value, bool *returnOk=nullptr)
Returns the value for the given keys of a flag.
Definition: qgis.h:2739
T qgsFlagKeysToValue(const QString &keys, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given keys of a flag.
Definition: qgis.h:2761
QMap< QString, QString > QgsStringMap
Definition: qgis.h:3022
QVector< QgsPoint > QgsPointSequence
QMap< int, QVariant > QgsAttributeMap
Definition: qgsattributes.h:42
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:922
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
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
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QMap< int, QgsPropertyDefinition > QgsPropertiesDefinition
Definition of available properties.
#define RENDERER_TAG_NAME
Definition: qgsrenderer.h:50
bool saveStyle_t(const QString &uri, const QString &qmlStyle, const QString &sldStyle, const QString &styleName, const QString &styleDescription, const QString &uiFileContent, bool useAsDefault, QString &errCause)
int listStyles_t(const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)
QString getStyleById_t(const QString &uri, QString styleID, QString &errCause)
bool deleteStyleById_t(const QString &uri, QString styleID, QString &errCause)
QString loadStyle_t(const QString &uri, QString &errCause)
QMap< QgsFeatureId, QgsFeature > QgsFeatureMap
A bundle of parameters controlling aggregate calculation.
Setting options for creating vector data providers.
Context for cascade delete features.
QList< QgsVectorLayer * > handledLayers(bool includeAuxiliaryLayers=true) const
Returns a list of all layers affected by the delete operation.
QMap< QgsVectorLayer *, QgsFeatureIds > mHandledFeatures
QgsFeatureIds handledFeatures(QgsVectorLayer *layer) const
Returns a list of feature IDs from the specified layer affected by the delete operation.
Setting options for loading vector layers.
QgsWkbTypes::Type fallbackWkbType
Fallback geometry type.
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
bool forceReadOnly
Controls whether the layer is forced to be load as Read Only.
bool loadDefaultStyle
Set to true if the default layer style should be loaded.
QgsCoordinateTransformContext transformContext
Coordinate transform context.
QgsCoordinateReferenceSystem fallbackCrs
Fallback layer coordinate reference system.